There is an unending dispute about which library should you use when writing an application for STM32 microcontroller. Actually, there are at least three choices which you should consider. In this post I will highlight the advantages and disadvantages of each approach which can be considered when writing software for ST microcontrollers.
CMSIS
CMSIS stands for Cortex Microcontroller Software Interface Standard. CMSIS is a hardware abstraction layer for Cortex-M devices. It is common interface across different vendors which is good because it is a standard when Cortex-M devices are being considered. It means that you don’t have to worry about the compatibility issues. However, talking to the peripherals like SPI is completely different case because CMSIS handles only the basics, excluding mentioned peripherals. Communication with MCU peripherals requires a direct registry manipulation. This solution is error prone if you don’t know what you are doing. For example you can misunderstand the documentation in some cases and wonder why something is not working, it happens very rarely but still. If you get it right you will probably get the best code and the most efficient piece of software. This is not recommended for beginners who just started their adventure with microcontrollers programming.
The compatibility across different microcontrollers is, however, different issue. The code which you have written will only work on a specific target device. Sometimes it can be ported to a different device but from the same family line. Using this approach you won’t avoid adjustments.
SPL
SPL stands for Standard Peripheral Library. It is a set of libraries created by ST company which in theory should make programmers life easier. In practice you end up with two things. First of all, you have to learn how to use the library. Fortunately, the company published a lot of examples on which you can learn but close to zero useful documentation. The other thing, however, is that you also need to learn a bit about the ST microcontrollers; there is no shortcut. In the end you don’t only have to teach yourself how to use the library itself but also you have to know the architecture of the MCU which you are going to use. In conclusion, you have to do the same work twice which is terribly inefficient.
Where is the advantage of this approach? It’s quite obvious. Using SPL makes life easier. Your code is, more or less, portable and you don’t have to know the nuances. In either case, it is better to know them. The biggest disadvantages is the library itself because of two reasons. You don’t know if it is buggy. There is plenty of talk about this and it is not in favour of the SPL. Also let’s say that you want to make something more complex, like two or three peripherals depending on each other, if the SPL wasn’t prepared for this you end up exactly where you were before. You have to write your own code which operates on MCU registers. Going this way, it gets the job done but if you were dreaming about any kind of portability of your code, now you can forget about it completely.
Also, it is very recent situation which has cover in real life, the ST company decided to discontinue the development of this piece of software. This is the case, ST decided to make a new library called HAL. It is described below.
HAL
HAL is an abbreviation for Hardware Abstraction Layer. In comparison to the SPL it has a lot of new features. Not only it was rebuild from the ground up but also there is a new tool which should make your life easier – STM32CubeMX.
Let’s focus on the library itself. When analysing the library and its code you can be under impression that the names of functions, variables etc. were changed and everything else stayed the same. Actually, a lot has been changed and improved. One big advantage is that you can reuse your code between different chip families based on Cortex-M core from this vendor. ST delivers a set of libraries which have identical API (in majority of cases), and the only thing that you have to do, to run the code on a different MCU, is to switch a set of libraries which shouldn’t be painful; and recompile your code. Sounds fantastic but, like with everything else, only to a certain point.
At the beginning, I mentioned the STM32CubeMx. It is an outstanding piece of software, only it has been introduced to the market a few years too late. If you are familiar with Code Expert from Motorola, now Freescale, the STM32CubeMx is more or less the same. The STM32CubeMx is a tool which allows you to:
- Select a chip in which you are interested in by many different criteria,
- Select peripherals which you would like to use and configure them,
- Configure clocks by filling up gaps/changing values in diagram,
- Configure internal peripherals,
- Do some profiling for power consumption based on designed chip activity,
- And the last but not the lest, to automatically generate C code for your project.
Still this tool requires a lot of work and there is still room for some improvement.
So why not to use HAL along with STM32CubeMx if it is so versatile. There is still a risk when ST becomes bored with the HAL, however unlikely it may seem, it can happen and then they simply discontinue this project. The HAL library can meet the same fate as SPL did.
The HAL library is not only library for the internal peripherals. It also allows you to configure FreeRTOS, FatFS and along with it SD card support. Let’s look more closely on the FreeRTOS support. ST created a set of wrappers and called it a new OS which actually runs FreeRTOS under the hood. But still you can use native FreeRTOS 🙂
Different solutions
Also there are some other libraries dedicated to the specific core or even a family of devices. One of them is a set of libraries created by Tilen Majerle. It was build upon the HAL library. Furthermore, it is not only a set of libraries with wrappers but also a set of drivers for external devices like LCD, DS18B20, and a few others. It is definitely worth to have a look on this one.
Also there are proprietary libraries which come with a whole IDE like CrossWorks for ARM from Rowley.
To sum, there is a whole variety of IDEs and libraries. Some have more pros then others. What is the most important factor which you have to keep in mind, however, is if the library you are going to use suddenly could be discontinued. But still, it is not a very big problem if you separate hardware layer from your logic layer. Then you can relatively easily switch from one to another.
Update
There was published a second part about SPL, HAL, and LL frameworks.
SPL vs HAL: which one should you use (and Low Layer Library) — part 2
It was very useful to me, thank u
It’s a very enlightening post. Thank you Domski. I’m migrating from 8bit microcontrollers to the STM32 line. I will go with CMSIS library. Do you have tips and/or examples that may help me with the learning process? Best Regards.
I am very happy to hear that.
As for starting with CMSIS it might not be a very good idea. CMSIS are general libraries for the CPU core. If you want to use other peripherals like GPIO or timers you will be forced to go with direct register access. It can be very educative but it won’t do for bigger project. Instead of focusing on developing your project you, at the beginning, you will spend a lot of time to just make things work. But after some time you should be very proficient at it. I can advise to start with HAL and then maybe switch to LL. Best of luck!
Hi..
How can I use LL to transmit and receive data using STM32F4 SPI.
Hi. Have you tried official examples for the SPI?
The advantage of LL is that it is almost as setting appropriate bits in registers. For example (just a snippet):
LL_SPI_SetBaudRatePrescaler(SPI1, LL_SPI_BAUDRATEPRESCALER_DIV256);
LL_SPI_SetTransferDirection(SPI1,LL_SPI_FULL_DUPLEX);
LL_SPI_SetClockPhase(SPI1, LL_SPI_PHASE_2EDGE);
LL_SPI_SetClockPolarity(SPI1, LL_SPI_POLARITY_HIGH);
LL_SPI_SetDataWidth(SPI1, LL_SPI_DATAWIDTH_8BIT);
LL_SPI_SetNSSMode(SPI1, LL_SPI_NSS_SOFT);
LL_SPI_SetRxFIFOThreshold(SPI1, LL_SPI_RX_FIFO_TH_QUARTER);
LL_SPI_SetMode(SPI1, LL_SPI_MODE_MASTER);
Sets SPI1 in Full-Duplex in master mode.
Good reference point is the LL documentation (it is the same document which describes the HAL API).
Hi,
Thank you for reply….Yes I have try with LL and can successfully transmit receive using HAL..But in both cases I am getting more delay in transmit and receive clock…I want to reduce that delay to improve performance.
That clock delay is more in LL than HAL library commands…
How can I reduce it???
Thank You.
What do you mean that the clock is delayed? Do you mean that it works at lower frequency or the moment of transmission start itself is delayed? Or do you mean something entirely different?
Also how do you check this delay? If you use an oscilloscope or a logic analyser could you maybe share the graphs?
I would also suggest to check the configuration while it is done with HAL and then with LL. By checking the configuration I mean reading the SPI configuration registers to actually see that there is no difference between them or if there is one then where exactly it is.
The best HAL right now is Arduino HAL because it works on AVR8, ESP32, STM32 and in future will be works on the RISC-V too 😉
Thanks for the information. However, the Arduino HAL, to the best of my knowledge, is somehow limited. Yes, you can quickly prototype a solution or even prepare a working device but if you want to do something non-standard which requires a specific configuration of peripherals then you have to do some stuff by hand. On the other hand, if you want to port your application to a different platform including STM32 you can do this with almost no hassle.
Hi,
I did something similar to CubeMX but for SPL library (for Nucleo-L152RE board), named VPC – Visual Pin Configurator. It generates the C source code, Makefile and some config files for the Visual Studio Code IDE and Cortex Debugger. But is only for Linux and FreeBSD. The project is written in Pascal and is open source (it can be modified by anyone that still works with SPL to support his microcontroller of choice):
https://gitlab.com/funlw65/vscode_nucleo_l152re
and the blog is here: https://vpc.home.blog/