Standard Peripherals Library vs CMSIS vs HAL vs Low Level Library

Tags: ARM, C, Electronics, Embedded, Programming

The STM32 line of microcontrollers offer a bunch of features in a nice package at reasonable cost, something I like. What I don't like as much are the development libraries around it provided by ST. For this reason, most of the time I stick to writing code using the 'Cortex Microcontroller Software Interface Standard' (CMSIS) and the datasheet, and this works nicely but can be slow to develop. While it's still my personal favorite, I recently checked out the other options to see where things are going to do the prep work for some ports of older projects built using the 'Standard Peripherals Library' to newer processors such as the STM32L4.




So, why not stick to the Standard Peripherals Library? Simply because ST decided to discontinue this library for future processors like the STM32L4. Instead, ST is pushing their HAL to provide a standardized API across the devices in combination with the STM32CubeMX tool for code generation for clock settings, pin muxing, peripheral settings, etc. While this sounds nice in theory, it expects a certain IDE for the generated project files, but also hides a lot of the complexities and details behind abstraction layers. The latter means that a) your code gets bigger (substantially so) and b) hand editing and verification becomes a lot harder. The documentation is also not the best to say the least, and seems I'm not the only one noticing these issues.

It's the verification part in particular that keeps me from using it. The HAL can be buggy (and has been in the past). This means spending a lot more time verifying all the layers for correctness in critical applications. The project generation sounds nice, and probably is when you use the supported IDE. I tend to use the GCC compiler and Makefiles, because it integrates nicely with the way we do our production. It also means we can easily run a build process on a remote machine without a GUI getting in the way, again, to integrate with the rest. While I'm sure you can convert some of those project files to a Makefile, it would still need manual tweaking to the particular project at hand every time a change is made using CubeMX. The way I see it, CubeMX is nice for those new to STM microcontrollers, people doing hobby projects, makers, etc., but I don't see this work in professional environments where you usually want full control over what goes on under the hood and resource use is optimized. Then again, maybe I'm in the minority here?

At one point, ST planned on ditching the Standard Peripherals Library altogether and going with HAL all the way. Luckily they came back from that, and created the 'Low Level Library​'. This thing is much better (although it could definitely use improvements). It's pretty close to the way the Standard Peripherals Library worked, but it's in my opinion cleaner, and definitely results in smaller, more optimized, code. One of the reasons is that you can disable the 'full' version of this library that does away with the more complex functions (think about the way GPIO is set up with a struct) and can just use what are basically simple CMSIS wrappers in the form of inlined functions to perform these tasks. This makes it a lot easier to verify the correctness of it all.

In short the Low Level Library is small, clean and and it's also easily built using a Makefile, in that you can just build a library with all the *_ll_*.c named files and link it in your project just like the Standard Peripherals Library used to work. This also means that any custom linker files migrate along nicely. I've ported a reasonable sized project that used to use the Standard Peripherals Library to the new Low Level Library over a weekend. Let's hope improvements will continue to be made, and that this (or the direct CMSIS way) will become the standard way STM microcontrollers are programmed in more serious environments.