Low Level API - for STM32F1 chips
Table of Contents
Intro
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) add_library(ll src/stm32f1xx_ll_utils.c src/stm32f1xx_ll_usb.c src/stm32f1xx_ll_usart.c src/stm32f1xx_ll_tim.c src/stm32f1xx_ll_spi.c src/stm32f1xx_ll_sdmmc.c src/stm32f1xx_ll_rtc.c src/stm32f1xx_ll_rcc.c src/stm32f1xx_ll_pwr.c src/stm32f1xx_ll_i2c.c src/stm32f1xx_ll_gpio.c src/stm32f1xx_ll_fsmc.c src/stm32f1xx_ll_exti.c src/stm32f1xx_ll_dma.c src/stm32f1xx_ll_dac.c src/stm32f1xx_ll_crc.c src/stm32f1xx_ll_adc.c)
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 asstm32f1xx_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")
set(STM32_DEVICE_GROUP "STM32F103xB" CACHE STRING "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 -mthumb -mcpu=cortex-m3 -mfloat-abi=soft -mlittle-endian)
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