首页 理论教育 STM32复位与启动过程

STM32复位与启动过程

时间:2023-11-23 理论教育 版权反馈
【摘要】:STM32单片机启动后的程序入口受芯片引脚BOOT0和BOOT1控制,具体见表4.5。表4.5STM32启动模式控制如图4.22所示,在退出复位后,处理器会从存储器中读取两个字,然后再去执行程序:图4.22STM32复位序列初始主堆栈指针值:从存储器地址0x00000000取堆栈指针初始值,也是内核寄存器R13的初始值。当STM32遇到复位信号后,则从0x8000004处取出复位中断服务入口地址,继而执行复位中断服务程序,然后跳转_main函数,最后进入main函数,来到C的世界。

STM32复位与启动过程

STM32单片机启动后的程序入口受芯片引脚BOOT0和BOOT1控制,具体见表4.5。在烧写的时候除了BOOT[1∶0]=11方式之外都可以烧写,但是烧写完如要启动,则选择第一种“主闪存存储器”方式启动。BOOT1可选择为0,这样两种启动方式都可通过BOOT0选择。BOOT0=0为正常启动烧写的程序;BOOT0=1为启动片内的引导程序,这时可以通过串口来烧写程序。

表4.5 STM32启动模式控制

如图4.22所示,在退出复位后,处理器会从存储器中读取两个字,然后再去执行程序:

图4.22 STM32复位序列

初始主堆栈指针值(MSP):从存储器地址0x00000000取堆栈指针初始值,也是内核寄存器R13的初始值。

复位向量值:从存储器地址0x00000004取复位向量(程序执行的起始地址,LSB的值应该置为1,以表明是Thumb状态)。

对于Cortex-M3和Cortex-M4,MSP的初始值位于存储器映射的开始处,后面紧跟着就是向量表(在程序的执行过程中,向量表可以被重新分配到另外一个地址处)。值得注意的是,向量表的内容为地址,而非跳转指令。(www.xing528.com)

由于Cortex-M3和Cortex-M4内核的栈操作为满递减(堆栈指针指向栈顶元素,并且堆栈由高地址向低地址生长),所以,SP的初始值应该指向栈顶元素上面的存储单元。注意:堆栈指针始终都是指向入栈的最后一个字节的存储单元,而不是提前指向下一个即将入栈的数据单元处。

在进行项目开发时,需要在工程中配置启动文件,比如STM32F10X.S,现启动文件的复位代码分析:

[WEAK]选项表示当所有的源文件都没有定义这样一个标号时,编译器也不给出错误信息,在多数情况下将该标号置为0,若该标号为B或BL指令引用,则将B或BL指令置为NOP操作。EXPORT提示编译器该标号可以为外部文件引用。

启动文件中的_main标号并不表示C程序中的main函数入口地址,因此LDR R0,=_main与BX R0也并不是跳转至main函数开始执行C程序。_main标号表示C/C++标准实时库函数里的一个初始化子程序_main的入口地址。该程序的一个主要作用是初始化堆栈,并初始化映像文件,最后跳转C程序中的main函数。这就解释了为何所有的C程序必须有一个main函数作为程序的起点——因为这是由C/C++标准实时库所规定的——并且不能更改,因为C/C++标准实时库并不对外界开发源代码。因此,实际上在用户可见的前提下,程序在执行LDR R0,=_main与BX R0后就跳转至.c文件中的main函数,开始执行C程序。

至此可以总结STM32的启动文件和启动过程:首先对栈和堆的大小进行定义(向下生成满堆栈),并在代码区的起始处建立中断向量表,其第一个表项是栈顶地址,第二个表项是复位中断服务入口地址。然后在复位中断服务程序中执行LDR R0,=_main与BX R0跳转C/C++标准实时库的_main函数,完成用户堆栈等的初始化后,跳转.c文件中的main函数开始执行C程序。

假设STM32被设置为从内部FLASH启动(这也是最常见的一种情况),中断向量表起始地位为0x8000000,则栈顶地址存放于0x8000000处,而复位中断服务入口地址存放于0x8000004处。当STM32遇到复位信号后,则从0x8000004处取出复位中断服务入口地址,继而执行复位中断服务程序,然后跳转_main函数,最后进入main函数,来到C的世界

免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

我要反馈