Skip to content

Commit 785aa2e

Browse files
committed
Pull CMSIS headers from github
1 parent 2a61ea2 commit 785aa2e

14 files changed

+66
-22190
lines changed

README.md

+24-57
Original file line numberDiff line numberDiff line change
@@ -1315,26 +1315,23 @@ CMSIS is an ARM standard, and since CMSIS headers are supplied by the MCU
13151315
vendor, they are the source of authority. Therefore, using vendor
13161316
headers is a preferred way, rather than writing definitions manually.
13171317
1318-
In this section, we will replace our API functions in the `mcu.h` by the
1319-
CMSIS vendor header, and leave the rest of the firmware intact.
1320-
1321-
STM32 CMSIS headers for F4 family can be found at
1322-
https://github.com/STMicroelectronics/cmsis_device_f4 repo. From there,
1323-
copy the following files into our firmware directory,
1324-
[step-5-cmsis](step-5-cmsis):
1325-
- [stm32f429xx.h](https://raw.githubusercontent.com/STMicroelectronics/cmsis_device_f4/master/Include/stm32f429xx.h)
1326-
- [system_stm32f4xx.h](https://raw.githubusercontent.com/STMicroelectronics/cmsis_device_f4/master/Include/system_stm32f4xx.h)
1327-
1328-
Those two files depend on a standard ARM CMSIS includes, download them too:
1329-
- [core_cm4.h](https://raw.githubusercontent.com/STMicroelectronics/STM32CubeF4/master/Drivers/CMSIS/Core/Include/core_cm4.h)
1330-
- [cmsis_gcc.h](https://raw.githubusercontent.com/STMicroelectronics/STM32CubeF4/master/Drivers/CMSIS/Core/Include/cmsis_gcc.h)
1331-
- [cmsis_version.h](https://raw.githubusercontent.com/STMicroelectronics/STM32CubeF4/master/Drivers/CMSIS/Core/Include/cmsis_version.h)
1332-
- [cmsis_compiler.h](https://raw.githubusercontent.com/STMicroelectronics/STM32CubeF4/master/Drivers/CMSIS/Core/Include/cmsis_compiler.h)
1333-
- [mpu_armv7.h](https://raw.githubusercontent.com/STMicroelectronics/STM32CubeF4/master/Drivers/CMSIS/Core/Include/mpu_armv7.h)
1334-
1335-
From the `mcu.h`, remove all peripheral API and definitions, and leave only
1336-
standard C inludes, vendor CMSIS include, defines to PIN, BIT, FREQ, and
1337-
`timer_expired()` helper function:
1318+
There are two sets of CMSIS headers:
1319+
- First, there are ARM Core CMSIS headers. They describe ARM core,
1320+
and published by ARM on github: https://github.com/ARM-software/CMSIS_5
1321+
- Second, there are MCU vendor CMSIS headers. They describe MCU peripherals,
1322+
and published by the MCU vendor. In our case, ST publishes them at
1323+
https://github.com/STMicroelectronics/cmsis_device_f4
1324+
1325+
We can pull those headers by a simple Makefile snippet:
1326+
1327+
The ST CMSIS package also provides startup files for all their MCUs. We
1328+
can use those instead of hand-writing the startup.c. The ST-provided startup
1329+
file calls `SystemInit()` function, so we define it in the `main.c`.
1330+
1331+
Now, let's replace our API functions in the `mcu.h` using CMSIS definitions,
1332+
and leave the rest of the firmware intact. From the `mcu.h`, remove all
1333+
peripheral API and definitions, and leave only standard C inludes, vendor CMSIS
1334+
include, defines to PIN, BIT, FREQ, and `timer_expired()` helper function:
13381335
13391336
```c
13401337
#pragma once
@@ -1366,38 +1363,12 @@ If we try to rebuild the firmware - `make clean build`, then GCC will fail
13661363
complaining about missing `systick_init()`, `GPIO_MODE_OUTPUT`, `uart_init()`,
13671364
and `UART3`. Let's add those using STM32 CMSIS files.
13681365
1369-
Let's start from `systick_init()`. The `core_cm4.h` header defines
1370-
`SysTick_Type` structure which is identical to our `struct systick`, and has
1371-
an appropriate #define for `SysTick` peripheral. Also, `stm32f429xx.h` has
1372-
a `RCC_TypeDef` structure and appropriate #define for the `RCC`. Therefore
1373-
our `systick_init()` function remains almost unchanged: we only have to replace
1374-
`SYSTICK` with `SysTick`:
1375-
1376-
```c
1377-
static inline void systick_init(uint32_t ticks) {
1378-
if ((ticks - 1) > 0xffffff) return; // Systick timer is 24 bit
1379-
SysTick->LOAD = ticks - 1;
1380-
SysTick->VAL = 0;
1381-
SysTick->CTRL = BIT(0) | BIT(1) | BIT(2); // Enable systick
1382-
RCC->APB2ENR |= BIT(14); // Enable SYSCFG
1383-
}
1384-
```
1366+
Let's start from `systick_init()`. ARM core CMSIS headers provide a
1367+
`SysTick_Config()` function that does the same - so we'll use it.
13851368
13861369
Next goes `gpio_set_mode()` function. The `stm32f429xx.h` header has
13871370
`GPIO_TypeDef` structure, identical to our `struct gpio`. Let's use it:
1388-
1389-
```c
1390-
#define GPIO(bank) ((GPIO_TypeDef *) (GPIOA_BASE + 0x400 * (bank)))
1391-
enum { GPIO_MODE_INPUT, GPIO_MODE_OUTPUT, GPIO_MODE_AF, GPIO_MODE_ANALOG };
1392-
1393-
static inline void gpio_set_mode(uint16_t pin, uint8_t mode) {
1394-
GPIO_TypeDef *gpio = GPIO(PINBANK(pin)); // GPIO bank
1395-
int n = PINNO(pin); // Pin number
1396-
RCC->AHB1ENR |= BIT(PINBANK(pin)); // Enable GPIO clock
1397-
gpio->MODER &= ~(3U << (n * 2)); // Clear existing setting
1398-
gpio->MODER |= (mode & 3) << (n * 2); // Set new mode
1399-
}
1400-
```
1371+
https://github.com/cpq/bare-metal-programming-guide/blob/2a61ea23e44c4531b66f6508238cfc43ca7c2634/step-5-cmsis/mcu.h#L32-L41
14011372
14021373
The `gpio_set_af()` and `gpio_write()` functions is also trivial -
14031374
simply replace `struct gpio` with `GPIO_TypeDef`, and that's all.
@@ -1419,15 +1390,11 @@ shows the output. Congratulations, we have adopted our firmware code to
14191390
use vendor CMSIS header files. Now let's reorganise the repository a bit
14201391
by moving all standard files into `include` directory and updating Makefile
14211392
to let GCC know about it:
1393+
https://github.com/cpq/bare-metal-programming-guide/blob/2a61ea23e44c4531b66f6508238cfc43ca7c2634/step-5-cmsis/Makefile#L3
14221394
1423-
```make
1424-
...
1425-
-g3 -Os -ffunction-sections -fdata-sections -I. -Iinclude \
1426-
```
1427-
1428-
We have left with
1429-
a project template that can be reused for the future projects.
1430-
A complete project source code you can find in [step-5-cmsis](step-5-cmsis)
1395+
We have left with a project template that can be reused for the future
1396+
projects. A complete project source code you can find in
1397+
[step-5-cmsis](step-5-cmsis)
14311398
14321399
14331400
## Setting up clocks

step-5-cmsis/Makefile

+14-6
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,34 @@
11
CFLAGS ?= -W -Wall -Wextra -Werror -Wundef -Wshadow -Wdouble-promotion \
22
-Wformat-truncation -fno-common -Wconversion \
3-
-g3 -Os -ffunction-sections -fdata-sections -I. -Iinclude \
3+
-g3 -Os -ffunction-sections -fdata-sections \
4+
-I. -Iinclude -Icmsis_core/CMSIS/Core/Include -Icmsis_f4/Include \
45
-mcpu=cortex-m4 -mthumb -mfloat-abi=hard -mfpu=fpv4-sp-d16 $(EXTRA_CFLAGS)
56
LDFLAGS ?= -Tlink.ld -nostartfiles -nostdlib --specs nano.specs -lc -lgcc -Wl,--gc-sections -Wl,-Map=$@.map
6-
SOURCES = main.c startup.c syscalls.c
7+
SOURCES = main.c syscalls.c
8+
SOURCES += cmsis_f4/Source/Templates/gcc/startup_stm32f429xx.s # ST startup file. Compiler-dependent!
79

810
ifeq ($(OS),Windows_NT)
911
RM = cmd /C del /Q /F
1012
else
11-
RM = rm -f
13+
RM = rm -rf
1214
endif
1315

1416
build: firmware.bin
1517

16-
firmware.elf: $(SOURCES)
17-
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(LDFLAGS) -o $@
18+
firmware.elf: cmsis_core cmsis_f4 mcu.h link.ld Makefile $(SOURCES)
19+
arm-none-eabi-gcc $(SOURCES) $(CFLAGS) $(CFLAGS_EXTRA) $(LDFLAGS) -o $@
1820

1921
firmware.bin: firmware.elf
2022
arm-none-eabi-objcopy -O binary $< $@
2123

2224
flash: firmware.bin
2325
st-flash --reset write $< 0x8000000
2426

27+
cmsis_core:
28+
git clone --depth 1 -b 5.9.0 https://github.com/ARM-software/CMSIS_5 $@
29+
30+
cmsis_f4:
31+
git clone --depth 1 -b v2.6.8 https://github.com/STMicroelectronics/cmsis_device_f4 $@
32+
2533
clean:
26-
$(RM) firmware.*
34+
$(RM) firmware.* cmsis_*

0 commit comments

Comments
 (0)