一.什么是CMSIS
CMSIS ( Cortex Microcontroller Software Interface Standard ),翻译过来是ARM Cortex™ 微控制器软件接口标准 。这个标准是谁提的呢?提的这个标准是用来干什么的呢?这里不得不说说ARM和STM32、TI这些公司的关系了,ARM 是一个做芯片标准的公司,它负责的是芯片内核的架构设计,而TI、ST这样的公司,他们并不做标准,他们是芯片公司,他们是根据 ARM 公司提供的芯片内核标准设计自己的芯片。所以,任何一个做 Cortex M3 芯 片 ,他们的内核结构都是一样的,不同的是他们的存储器容量, 片上外设 IO 以及其他模块的区别。
1. 标准是谁提的呢?
ARM跟芯片厂商共同提出的,目的就是为了不同芯片厂商生产的Cortex-M3芯片能在软件上基本兼容,各芯片厂商就得按照这个标准去编写自己芯片内核的驱动程序,比如系统函数的命名、芯片初始化启动流程等;STM32的官方库(标准库、HAL库、LL库)就是按照这个标准写的。
2. 这个标准是用来干什么的呢?
如下图它向下负责与内核和各个外设直接打交道,向上提供实时操作系统用户程序调用的函数接口。分为 3 个基本功能层:
核内外设访问层:ARM 公司提供的访问,定义处理器内部寄存器地址以及功能函数。
中间件访问层:定义访问中间件的通用 API, 也是 ARM 公司提供。
外设访问层:定义硬件寄存器的地址以及外设的访问函数。
1、Include文件
在该文件中主要使用了stm32f4xx.h 和 stm32f429xx.h(不同的芯片这个文件不同),如下图
(1)在stm32f429xx.h 头文件包含了该芯片所有外设的寄存器定义和封装内存操作,直接操作这些寄存器就可以控制外设了,使用STM32任何型号的芯片都需要包含这个头文件。
(2)在stm32f4xx.h中会根据芯片型号宏标识符(我这里是STM32F429xx )选择对应的头文件(stm32f429xx.h),如果定义了USE_HAL_DRIVER宏标识符,还会将HAL库外设驱动包含进来,具体包含关系为:
2、Source文件
在该文件中主要用到了 system_stm32f4xx.c、startup_stm32f429xx.s、stm32f429xx_flash.icf。如下图:
startup_stm32f429xx.s | 启动文件的作用主要是进行堆栈的初始化,中断向量表以及中断函数定义等。会设置系统复位后,直接调用 SystemInit函数进行系统初始化。还有一个很重要的作用就是系统复位后引导进入 main函数。 |
system_stm32f4xx.c | 主要是声明和定义了系统初始化函数 SystemInit 以及系统时钟更新函数 SystemCoreClockUpdate。SystemInit函数的作用是进行时钟系统的一些初始化操作以及中断向量表偏移地址设置,但它并没有设置具体的时钟值 |
stm32f429xx_flash.icf | 定义了芯片的FLASH和RAM的起始和结束地址、以及大小 |
3.介绍两个宏定义的作用
USE_HAL_DRIVER
STM32F103xB
如果定义这个USE_HAL_DRIVER宏,它就可以把HAL库包含进来
如果定义STM32F103xB这个宏就会包含下面这个头文件
4.开始介绍工程文件
4.1启动文件
作用:这个是汇编文件,用来启动文件。用于初始化硬件、设置堆栈和中断,然后跳槽转到C\C++的程序入口。(main)
4.2中断文件
作用:中断服务历程文件,它包含了处理各种中断的C语言函数,例如定时器中断、外部中断等。
4.3 系统初始化函数和时钟更新函数
作用:定义了系统初始化函数、SysTEMinit和系统时钟更新函数。
4.4 SYSTEM
作用:delay是延时函数、sys是时钟函数、uart是串口配置。
4.5 STM32Fxx_HAL_Driver
作用:HAL库初始化、系统滴答、HAL库延时等相关函数。
作用:内核通用函数定义和声明,如:NVIC、MPU、系统软件复位、Systick等,其实主要是对core_cm3.h文件的相关函数再次封装。
作用:这些都是外设的函数定义,其中ex的作用,主要是存放外设的扩展功能的驱动源码。
4.6常用.h文件
作用:是所有F1系列的顶层头文件,通过条件编译来包含某个芯片的头文件,定义通用的枚举类型、定义通用的宏定义。
作用:终端编号定义、外设寄存器结构体类型定义、寄存器映射、寄存器位定义、外设判定。
作用:HAL库的用户配置文件、用于裁剪HAL库、配置晶振参数等。
作用: 包含HAL库通用的枚举类型数据和宏定义
5. STM32单片机的启动流程
总结
CMSIS就是定义了一套芯片外设控制及编写规范的标准。我们在移植一个新的工程时,只需要修改添加:
1、添加system_stm32f4xx.c、startup_stm32f429xx.s、stm32f429xx_flash.icf
2、添加stm32f4xx.h
3、修改全局宏标识 STM32F429xx
5.1复位/上电
上电与复位。当STM32微控制器上电或发生复位时,CPU从固定的复位向量地址开始执行代码。对于大多数STM32型号,复位向量地址通常是0x08000000。
5.2根据BOOT0/BOOT1 确定程序从哪个存储位置执行。
可以去看我之前博客写的那个关于STM32,其中有一个存储器映射图。
1.常规模式(主闪存存储器):
这是最常见的启动模式。
在此模式下,处理器会执行复位向量表中的复位地址,从而启动芯片。
芯片会执行各种初始化操作,包括时钟初始化、外设初始化等,然后跳转到用户定义的启动代码。
基地址:0x0800000
2.Bootloader模式(系统存储器):
这是一种特殊的启动模式,通常用于更新固件或通过外部接口(如UART或USB)加载新的程序。
在此模式下,处理器会将启动地址设置为Bootloader的起始地址,而不是复位向量表中的复位地址。
Bootloader负责检查外部接口是否有新的程序,如果有,则加载并启动新程序;否则,它会跳转到复位向量表中的复位地址。
基地址:0x1FFFF000
3.系统内存模式(内置SRAM):
这种模式通常用于恢复或修复芯片中的固件。
在此模式下,处理器会将启动地址设置为系统内存中的特定地址,而不是复位向量表中的复位地址。
系统内存包含一个特殊的Bootloader,它可以用于加载新的固件或执行其他恢复操作。
基地址:0x20000000
5.3 初始化SP及PC指针
复位向量地址处的代码通常是由STM32官方提供的或用户自定义的启动代码,这段代码主要负责初始化堆栈指针(SP)和程序计数器(PC),并跳转至C语言环境下的初始化函数。
将0X8000 0000 位置的栈顶地址存放在SP指针中。
将0X8000 0000 位置存放的项链地址装入PC程序计数器
5.4 初始化系统时钟
启动代码继续执行必要的最低层硬件初始化,包括设置中断向量表、配置内部高速时钟、低速时钟以及系统时钟、初始化NVIC(Nested Vectored Interrupt Controller)、初始化堆栈、初始化静态存储区的内容,将flash中已经初始化的数据拷贝到相应的SRAM区域,清零未初始化的数据段。
5.5 初始化用户堆栈
- 如果使用了标准库函数
__MICROLIB
,则导出了栈和堆的初始化函数__user_initial_stackheap
。 - 如果未使用标准库函数,则需要手动定义栈和堆的初始化函数,并在其中设置栈的起始地址、堆的起始地址和结束地址。
5.6 进去main函数
6. Map文件
6.1 MDK生成的map文件大致可以分为五大部分,以及作用
MDK(Microcontroller Development Kit)生成的map文件通常可以分为以下五个主要部分,其作用与一般Map文件相似:
1.模块、段(入口)交叉引用(Selection Cross Reference):描述了各文件之间函数调用的关系,有助于理解各个源文件如何相互关联。
2.移除未使用的模块(Removing Unused input sections from the image.)描述了工程中为用到而被删除的冗余程序段,有助于优化代码、降低内存负担。
3.映射符号表(Image Symbol Table):描述了各个符号(程序段、数据)在存储器中的地址、类型、大小等信息,对于理解程序的内存布局以及定位代码或数据段非常有用。
4.内存(映射)分布(Memroy Map of the image):描述了各程序段(函数)在存储器中的地址占用大小、有助于分析程序的内存占用情况。
5.映射组件大小(Image component sizes):给出整个映像代码(.o)占用了空间的汇总信息,包括代码、只读数据、已初始化读写数据、未初始化读写数据等的大小,有助于了解程序的总体内存使用情况。
MAP文件的这五部分提供了对程序内存布局,函数调用关系,以及各模块占用情况的全面分析,是STM32开发中重要的优化和调试工具。
map文件的相关的概念:
段section:描述映像文件的代码和数据块
RO:Read-Only的缩写,包括RO-data只读数据和RO-code(代码)
RW:Read-Write的缩写,主要是RW-data, RW-data由程序初始化初始值
ZI:Zero-initialiized的缩写,主要是ZI-data,由编译器初始化为0
.text:与RO-code 同义
.bss:与ZI-data 同义
.data:与RW-data同义
最后的数据是相对应的
6.2 map 文件如何生成