how to construct a stm32 stdlib project without ide

in other words, how to create a stm32 stdlib project with gcc/makefile
actally, what you need do is to consider it as a c projectt then create a proper project structure and create a makefile to build it, what make it special is the regular c file become the peripheral file and you need to provide a startfile and a link script explicitly.

Peripheral Library

library structure:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
STM32F4xx_DSP_StdPeriph_Lib_V1.9.0  $ tree -L 2 .             
.
├── _htmresc
│   ├── CMSIS_Logo_Final.jpg
│   ├── favicon.png
│   ├── logo.bmp
│   ├── mini-st_2020.css
│   ├── st_logo_2020.png
│   └── st_logo.png
├── Libraries
│   ├── CMSIS
│   └── STM32F4xx_StdPeriph_Driver
├── Package_license.html
├── Package_license.md
├── Project
│   ├── STM32F4xx_StdPeriph_Examples
│   └── STM32F4xx_StdPeriph_Templates
├── Release_Notes.html
├── stm32f4xx_dsp_stdperiph_lib_um.chm
└── Utilities
├── Media
├── ST
├── STM32_EVAL
└── Third_Party

13 directories, 10 files

Library

包含两个文件夹CMSIS 和 STM32F4xx_StdPeriph_Driver, CMSIS(Cortex Microcontroller Software Interface Standard) 包含对Cortex的调用接口支持,而STM32F4xx_StdPeriph_Driver 包含了实际上的外设库文件,包括gpio/spi/i2c等等。

CMSMS

CMSIS是arm提供的

  • 启动文件

位于Libraries/CMSIS/Device/ST/STM32F4xx/Source/Templates,包含不同开发工具链的启动文件

1
2
3
4
5
6
7
8
9
10
11
Templates  $ tree -L 1 .                                          
.
├── arm // 给keil的
├── gcc_ride7 // 给gcc的
├── iar // 给 IAR Embedded Workbench
├── SW4STM32 // 给System Workbench for STM32, 基于 Eclipse 的免费 IDE,使用 GCC 工具链
├── system_stm32f4xx.c
├── TASKING // TASKING VX-Toolset(第三方编译器,汽车/工业领域常用)
└── TrueSTUDIO // TrueSTUDIO(ST 官方收购的基于 Eclipse 的免费 IDE,后改为 SW4STM32

7 directories, 1 file

其中,arm和gcc的启动文件我都尝试过,剩余几个由ai给出解释,未做验证。

  • 其他头文件
    • stm32f4xx.h
      位于Libraries/CMSIS/Device/ST/STM32F4xx/Include 包含与外设相关的定义,比如寄存器映射,外设结构体,比如GPIO_TypeDef就在这个文件中
    • system_stm32f4xx.h
      位于Libraries/CMSIS/Device/ST/STM32F4xx/Include包含系统级别初始化相关的定义,实际上在stm32f4中,只包含了两个函数的定义
    1
    2
    extern void SystemInit(void);
    extern void SystemCoreClockUpdate(void);
    • core_cm4.h
      位于Libraries/CMSIS/Include包含ARM Cortex CPU 本身包含的一些功能,比如中断,系统定时器,fpu支持,与芯片厂商(比如ST)无关

Driver

很多,包含必要的就行

其他文件

  1. stm32f40x_conf.h
    • 这个文件做了两件事,包含所有外设头文件和定义了assert_param这个宏。
    • 这个文件在stm32f4xx.h中被包含
    1
    2
    3
    #ifdef USE_STDPERIPH_DRIVER
    #include "stm32f4xx_conf.h"
    #endif /* USE_STDPERIPH_DRIVER */
    • 而且这个文件并未在Libraries中,但是可以在Project/STM32F4xx_StdPeriph_Templates下找到,所以这个文件不是必须的。
    • 如果不想使用这个文件,就需要手动做上面的两件事,原本只需要包含stm32f4xx.h就会包含stm32f4xx_conf.h然后包含外设头文件,现在需要在必要的时候显式包含外设头文件,当然,这个一个好的习惯,所以不是问题。接下来,需要显式定义assert_param,问题在与各个外设.c文件都在使用这个宏,如果在某个.h中手动定义的话,还需要修改外设.h文件以包含进去,不可行;有一个方法是通过gcc传递定义,即在makefile中通过-D'assert_param(expr)=((void)0)'的方式定义。
    • 总结,还是直接使用这个文件。使用条件是需要定义USE_STDPERIPH_DRIVERUSE_FULL_ASSERT宏,同时对于不同芯片,还需要定义一些特定的宏详细看stm32f4xx_conf.h文件
  2. stm32f10x_it.h
    这个文件和stm32f4xx_conf.h一样,没有在Libraries而在Project
  3. 链接脚本
    这个也有意思,没有提供,目前我知道的能提供链接脚本的只有STM32CubeMX,而且虽然目前cubemx只支持hal库,但是生成的链接脚本也能用于标准库

项目结构

项目结构不是固定统一的,只要能够写出对应的Makefile就行。
我的项目结构如下

1
2
3
4
5
6
7
8
9
10
11
12
example  $ tree -L 2 .                                                                                                           [0/0]
.
├── Core
│   ├── Inc // 用户头文件 和没有在Libraries中的头文件
│   └── Src // 用户.c 和没有在Libraries中的.c文件
├── Libraries // 全部复制过来,至于用那些,在makefie中定义
│   ├── CMSIS
│   └── STM32F10x_StdPeriph_Driver
├── Makefile
└── STM32F103XX_FLASH.ld

7 directories, 2 files

Core 目录如下

1
2
3
4
5
6
7
8
9
10
11
12
Core  $ tree                                                                                                                     [0/0]
.
├── Inc
│   ├── led.h
│   ├── stm32f10x_conf.h
│   └── stm32f10x_it.h
└── Src
├── led.c
├── main.c
└── stm32f10x_it.c

3 directories, 6 files

Makefile

和项目结构对应
也是改自cubemx生成