stm32启动文件详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
STM32启动文件详解
一、启动文件的作用
1.初始化堆栈指针SP;
2.初始化程序计数器指针PC;
3.设置堆、栈的大小;
4.设置异常向量表的入口地址;
5.配置外部SRAM作为数据存储器(这个由用户配置,一般的开发板可没有外部SRAM);
6.设置C库的分支入口__main(最终用来调用main函数);
7.在版的启动文件还调用了在文件中的SystemIni()函数配置系统时钟。
二、汇编指令
三、启动代码
----- 栈
Stack_Size EQU 0x00000400 ; 栈的大小
AREA STACK, NOINIT, READWRITE,ALIGN=3
Stack_Mem SPACE Stack_Size ; 分配栈空间
__initial_sp ; 栈的结束地址(栈顶地址)
分配名为STACK,不初始化,可读可写,8(2^3)字节对齐的1KB空间。
栈:局部变量,函数形参等。栈的大小不能超过内部SRAM大小。
AREA:汇编一个新的代码段或者数据段。STACK段名,任意命名;NOINIT表示不初始化;READWRITE可读可写;ALIGN=3(2^3= 8字节对齐)。
__initial_sp紧挨了SPACE放置,表示栈的结束地址,栈是从高往低生长,结束地址就是栈顶地址。
----- 堆
Heap_Size EQU 0x00000200 ; 堆的大小(512Bytes)
AREA HEAP, NOINIT, READWRITE,ALIGN=3
__heap_base ; 堆的起始地址
Heap_Mem SPACE Heap_Size ; 分配堆空间
__heap_limit ; 堆的结束地址
分配名为HEAP,不初始化,可读可写,8(2^3)字节对齐的512字节空间。__heap_base堆的起始地址,__heap_limit堆的结束地址。堆由低向高生长。动态分配内存用到堆。
PRESERVE8 -- 指定当前文件的堆/栈按照8 字节对齐。
THUMB-- 表示后面指令兼容THUMB 指令。THUBM 是ARM 以前的指令集,16bit;现在Cortex-M 系列的都使用THUMB-2 指令集,THUMB-2 是32 位的,兼容16 位和32 位的指令,是THUMB 的超级。
3.向量表
AREA RESET, DATA, READONLY
EXPORT __Vectors
E XPORT __Vectors_End
E XPORT __Vectors_Size
定义一个名为RESET,可读的数据段。并声明__Vectors、__Vectors_End 和__Vectors_Size 这三个标号可被外部的文件使用。
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
DCD NMI_Handler ; NMI Handler
DCD HardFault_Handler ; Hard Fault Handler
DCD MemManage_Handler ; MPU Fault Handler
DCD BusFault_Handler ; Bus Fault Handler
DCD UsageFault_Handler ; Usage Fault Handler
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD 0 ; Reserved
DCD SVC_Handler ; SVCall Handler
DCD DebugMon_Handler ; Debug Monitor Handler
DCD 0 ; Reserved
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
.
.
.
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors ;向量表大小
__Vectors 为向量表起始地址,__Vectors_End 为向量表结束地址,两个相减即可算出向量表大小。
向量表从Flash 的0x0 地址开始放置,以 4 个字节为一个单位,地址0 存放的是栈顶地址,0x04 存放的是复位程序的地址,以此类推。从代码上看,向
量表中存放的都是中断服务函数的函数名,可我们知道 C 语言中的函数名就是一个地址。
4.复位程序
AREA |.text|, CODE, READONLY
定义一个名为.text,可读的代码段
Reset_Handler PROC ;复位子程序开始
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP ;子程序结束
复位子程序是系统上电后第一个执行的程序,调用SystemInit ()函数初始化系统时钟,然后调用 C 库函数_main。
备注:
__main() 和main()
当所有的系统初始化工作完成之后,就需要把程序流程转入主应用程序,即呼叫主应用程序。最简单的一种情况是:
IMPORT main
B main
直接从启动代码跳转到应用程序的主函数入口,当然主函数名字可以由用户随便定义。
在ARM ADS环境中,还另外提供了一套系统级的呼叫机制。
IMPORT __main
B __main
__main()是编译系统提供的一个函数,负责完成库函数的初始化和初始化应用程序执行环境,最后自动跳转到main()。所以说,前者是库函数,后者就是我们自己编写的main()主函数;
因此我们用的B __main其实是执行库函数,然后该库函数再调用我们的main() 函数,因此在单步调试时会看到先要跑一段程序(其实是库函数),然后再单步到我们自己的main函数(这个同时也说明如果有B __main 则就对应必须有main函数,否则编译出错),如果我们用 B main来进入我们的主函数的话,那在单步调试时就