Low Level API - for STM32F1 chips

Table of Contents


The STM32 Low Level API is an API provided as a part of the STM32 Cube HAL. It's inconvenient to get from the STM32 website, so I'm providing an easy to access copy here that is built without the HAL using CMake. Below I describe how I created this.

Removing the HAL

Note: The STM32 Cube HAL is under a BSD license (per the documentation)

To start I took the HAL as provided by STM on their website. Then I copied all the stm32f1xx_ll_*.c files from STM32Cube_FW_F1_V1.6.0/Drivers/STM32F1xx_HAL_Driver/Src over to the src folder and added them to library

cmake_minimum_required(VERSION 3.0)


Next I copied over their equivalent headers from STM32Cube_FW_F1_V1.6.0/Drivers/STM32F1xx_HAL_Driver/Inc over to the inc folder. B/c of how the Low Level API is configured I needed to also copy 3 extra files:

  • stm32f1xx_hal.h
  • stm32f1xx_hal_def.h
  • stm32f1xx_hal_conf_template.h which was copied over as stm32f1xx_hal_conf.h

In this new stm32f1xx_hal_conf.h I then went to the Module Selection section at the top and comment out all the HAL modules starting from #define HAL_MODULE_ENABLED to completely disable the HAL. Next, per these instruction I add a #include "stm32f1xx_hal_def.h somewhere a the top in this same file

Once that's all done I could add these LL-API headers

target_include_directories(ll PUBLIC inc)

Adding the CMSIS

The CMSIS (Cortex Microcontroller Software Interface Standard) is the standard interface API for all ARM chips. It's common across all ARM vendors and STM's LL is build on top of this common layer. The CMSIS is also provided to us with the STM Cube HAL we downloaded - under STM32Cube_FW_F1_V1.6.0/Drivers/CMSIS. I copied this one over in its entirety.

Note: The CMSIS is under the Apache 2.0 license

Naturally ARM boards are all quite different internally, including all the boards in the STM32 family. They will have different amount of space, different peripherals available and different memory layouts. So to have a common API and to enable the programmer to program once and run on all ARM chips you also need certain parts tailored to the particular chip. These configurations for the F1 family of chips are all located in CMSIS/Device/ST/STM32F1xx/Include/ and as you can see - even withing one chip-type each chip has it's own configration file. These files will assign generic ARM variables like GPIOABASE to actual memory location for this particular chip. So once we use the CMSIS we can program directly with these labels, like GPIOBASE, and under the hood - as long as you point at the right configuration file - everything works identically on different hardware.

Now the STM guys lein on this CMSIS mechanism to write their whole LL-API. You maybe noticed that we didn't do any chip configuration/selection in the previous section - it was all just one library for the whole F1 group of chips. If you open up the LL headers you will see that they all include a certain file stm32f1xx.h - and this is in a sense the entry point to the CMSIS for the LL-API. This include acts as a sort of "switch" which engages the correct configuration file for our particular chip for the CMSIS. The actual file is at CMSIS/Device/ST/STM32F1xx/Include/stm32f1xx.h. It's really short - so just open it up and at the top you will see a big ugly table where you can find the preprocessor switch values that you will use. Once we set this value the correct configuration file gets included and everything simply works across the whole LL

B/c the bluepill uses a STM32F103C8T6, this maps to a proprocessor value of STM32F103xB (you can find the actual config file as well if you want to take a look at it). I will provide this value by default in CMake, but any user of this library can provide another value; either on the command line when running cmake with cmake -DSTM32_DEVICE_GROUP=XXX or more properly when included from a parent CMakeLists.txt with set(STM32_DEVICE_GROUP XXX CACHE STRING "Selected device group")

 "Chip configuration as defined in stm32f1xx.h (default value for the bluepill)")

target_compile_definitions(ll PUBLIC ${STM32_DEVICE_GROUP})
target_compile_definitions(ll PUBLIC "USE_FULL_LL_DRIVER")
target_include_directories(ll PUBLIC CMSIS/Device/ST/STM32F1xx/Include)

The very last step is to include the actual CMSIS itself which is simply in CMSIS/Include and to tell the compiler the target ARM architecture.

target_include_directories(ll PUBLIC CMSIS/Include)
target_compile_options(ll PUBLIC

Note: The CMSIS folder is pretty huge.. It's over 60MB. Even stripped of most things it is over 10MB in size. However, git seems to compress it pretty easily

Note: This repository was made on 2018-08-18. I make no promises about keeping it up to date with newer updates of the LL-API and CMSIS

Author: George Kontsevich

Created: 2019-07-25 Thu 11:08