Showing results for 
Search instead for 
Did you mean: 

What is the recommended alternative to using HAL? The ST docs all refer me back to using HAL with CubeMX however I see many suggesting staying away from it. I could not find where to download and use libraries such as CMSIS for my STM32F407G Disco board

Senior II

Are the libraries I need already in my CubeIDE project somewhere? I rather not use only bare metal, so CMSIS would be the way to go right?


CMSIS Libraries, and Include files are provided with the HAL / CubeF4 repository.

How much you use is up to you.

The HAL is illustrative of how to use the registers.

There's the LL (Low Level) library

Or the old SPL (Standard Peripheral Library)

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Ok great, I found the CMSIS libraries. Not sure if I should focus on CMSIS (V1/V2?), HAL(recommended by ST), or SPL/LL. Does LL replace SPL? Is SPL deprecated? It sounds like the best one in the list ( Standard ) but you mention it's 'Old' which hints at deprecation. Is LL maybe more like SPLV2? Which libraries do you use for all your new projects Tesla?

 Also, I think LL is no longer supported.


SPL is deprecated for many years, LL is lower level than SPL and there was at time a script to convert existing SPL based code to LL. LL and HAL are maintained by ST. Some people hybridly mix HAL and LL when using different IPs (peripeherals). You can also create your own style for simple IPs.

One example if Datasheet Pinout C encoded within the code for easier GPIO handling (including dynamically) on STM32C0 here. It needs to invest a bit to create manually the base, yet there is an accelerated payback over time in code intuitivity yet optimized code size in the end.

Lead II

You must use the CMSIS files that describe the MCU.

Then concerning the HAL you have to know several things:

It's a very generic library, which tries to cover several MCU families, so it's massive (not always easy to read the code) and very poorly optimized, and that's assumed.

When using the HAL, you must first study the MCU's reference manual to know how the peripherals work, and what they can do. Then we have to study how ST implements them in the HAL. Double job.

Then the way the HAL implements peripherals may not be what you need (usually there is a lot more...).

Those who want to use ready-made "libraries" without reading the manuals too much can try...

I don't use the HAL...

The LL is much more basic: it's basically a collection of inline functions that set bits in registers. The LL has the advantage of defining names for a whole bunch of things that are missing in CMSIS files, for example multi-bit fields. And the function names are self-explanatory and make the code more readable.

For me an advantage of LL is the device initialization functions: they take into account all the peculiarities. For example, on some MCUs, some UARTs may have several clock sources, and not the same depending on the MCU model in the family. To configure the baud rate of the UART, the LL manages to find the clock source and its frequency then calculates the divisor to use (the function is big and is 600 bytes for a G0!). This can of course be done by writing pre-calculated values directly into some registers. But then you have to study everything, and if you change the UART or the baud rate, everything has to be redone...

But for "large peripherals" like USB or LAN there is only HAL... We can mix LL and HAL.

In summary for me the HAL and the LL require an investment to master them. But the investment in LL is more profitable in the long term because the product code is smaller, more efficient, and better adapted to the need. And depends less on third-party software that you don't control.

Ok great, thank you for passing on this info., it makes sense.

Do you recommend enabling LL in STM32CubeIDE or just reference LL libraries where I use them? I plan on starting with HAL and then migrating parts of code to LL or CMSIS where HAL gives me problems. ( eg. SPI with DMA is currently giving me problems and that is why I started looking at CMSIS and now LL )

Lead II

You want to accumulate problems by using everything at the same time or successively!

It will no doubt be instructive.

What I can say is that I develop with the LL and the reference manual, and I write my own code. In the end, it doesn't take longer than trying to understand what the HAL is doing...

Regarding the SPI with DMA it is necessary to study the example provided by HAL / CubeF4 repository.

You will get contradictory information here, based on personal preferences of users.

I for example recommend against using LL, as it's IMO in most cases just an unnecessary rename of registers.

I personally recommend to go the painful way of using registers directly through symbols in the CMSIS-mandated device headers.

Note, that ST pushes Cube, mostly in its HAL form, and refuses to work on register based examples.


Senior II

Great info. from everyone, thank you! I can see how there could be many different approaches.

I have always found the reference manual easy to understand as it details each register and has the charts/maps to reference individual bits to assist as I code. Understanding each register is critical and cannot be abstracted away.

Since each register has a specific function, I like the idea of having 1 line of code to set each one so that I can add matching comments reasoning out why the value is chosen. Since HAL and LL hide multiple register settings behind function calls, it's not as simple to document.

Also, since everything is low lever coding anyways, just setting registers, I'm starting to see less and less value in having an abstraction layer for my own coding flow. I can see higher level peripherals like USB and ETH using abstraction layer like HAL though but not most of my own uC code.

Lastly, I'll end up spending most of my efforts optimizing my code for speed and memory so it makes sense to eliminate any layers which won't bring value at that point.

I'll stick to a bit of HAL and mostly CMSIS for now and see how that goes.

 UPDATE: I have already been able to easily convert code from HAL to CMSIS so I'm all set for now and the long-run!