stm32启动文件分析

一个人想着一个人 提交于 2019-12-24 02:02:39

这篇文章主要是分析stm32启动文件,启动文件是由汇编编写的,文件名为startup_stm32f40_41xxx.s。

启动文件做的工作:

启动文件最主要的功能就是初始化堆栈指针sp,执行复位程序进入C语言main函数
1.初始化堆栈空间大小,定义栈顶位置、堆起始位置等等
2.定义中断向量表,初始化sp指针
3.Reset_Handler复位函数定义
4.配置系统时钟,进入main函数

具体代码分析

Stack_Size      EQU     0x00000400
                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp

在MDK帮助文档中可以查到EQU是宏定义的伪指令,它的作用就相当于C语言中的define,首先定义栈大小为1KB(0x00000400)。
栈的作用主要保存函数中的局部变量,函数调用过程中的形参,返回地址,因此在函数中如果有较多的局部变量,大型数组最好不要放在函数中定义,在这种情况下就要考虑栈大小是否充足,如果栈溢出了,那程序会出现跑飞,找不到返回地址。
AREA是告诉编译器汇编一个代码段或者数据段,STACK 表示段名,这个可以任意命名; NOINIT 表示不初始化; READWRITE 表示可读可写, ALIGN=3,表示按照 2^3对齐,即 8 字节对齐。
SPACE是分配一定大小的内存空间,单位为字节。
最后一句_initial_sp是栈顶指针,这里栈的生长方向是从高地址到低地址,所以栈初始地址就是在高地址位置。

Heap_Size       EQU     0x00000200
                AREA    HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit

这里是声明堆的大小,方法和栈类似,不同点在于_heap_base堆初始位置在内存分配之前,也就是低地址,_heap_limit是堆结束位置,堆的生长方向是从低地址向高地址。堆主要用于动态内存的分配。

__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
                ...

这里就是中断向量表的定义,中断向量表是储存在flash的0地址位置。向量表第一个位置保存的是栈顶地址,即 __initial_sp,这个值在stm32开始运行后会赋给栈指针sp。向量表第二个位置保存的是复位中断的地址,其函数名Reset_Handler就是地址,在后面有定义,这个地址值会赋给程序运行地址指针pc,然后就运行复位程序。

Reset_Handler    PROC
                 EXPORT  Reset_Handler             [WEAK]
        IMPORT  SystemInit
        IMPORT  __main

                 LDR     R0, =SystemInit
                 BLX     R0
                 LDR     R0, =__main
                 BX      R0
                 ENDP

复位程序会导入Systeminit和_main函数的地址,并由下面的汇编代码,运行Systeminit函数,这个函数是对系统时钟进行设置,然后运行_main函数,这个函数是对堆栈进行一些初始化工作,然后跳转到main函数,并且不在返回该位置。
整个过程就是先设置堆和栈的大小,并且设置相应的地址,然后定义中断向量表,最后定义复位函数,跳转到main函数。

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!