ST-ARM理论(4):STM32F1启动
前提摘要
-
个人说明:
限于时间紧迫以及作者水平有限,本文错误、疏漏之处恐不在少数,恳请读者批评指正。意见请留言或者发送邮件至:“noahpanzzz@gmail.com”
-
参考
正文
启动模式(STM32F1)
在系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值将被锁存。用户可以通过设置BOOT1和BOOT0引脚的状态,来选择在复位后的启动模式。
在STM32F10xxx里,可以通过BOOT[1:0]引脚选择三种不同启动模式。
- 主闪存存储器 , 芯片内置的FLASH。
- 系统存储器,芯片内部一块特定的区域,芯片出厂时在这个区域预置了一段Bootloader,就是通常说的ISP程序。这个区域的内容在芯片出厂后没有人能够修改或擦除,即它是一个ROM区。这个系统存储器只是帮你通过ISP程序下载hex进去的。
- 内置SRAM,芯片内置的内存。
在启动延迟之后,CPU从地址0x0000 0000获取堆栈顶的地址 ,即获取堆栈指针MSP的初始值;并从启动存储器的0x0000 0004指示的地址开始执行代码,即取出程序计数器指针PC的初始值,该值为复位向量。
下图摘自STM32F10xxx参考手册_V10(中文版)
从上图红框中文字可以得到以下信息
- 主闪存存储器被映射到启动空间,可以通过0x0000 0000或0x0800 0000进行访问。
- 系统存储器被映射到启动空间,可以通过0x0000 0000或0x1FFF F000进行访问。
- 内置RAM被映射到启动空间,只能通过0x2000 0000进行访问。
对比存储器映射(Memory Map),就可以得到这些地址得来的原因。
主闪存存储器启动
地址范围0x0800 0000~0x0807 FFFF,大小为512KB。一般使用JTAG或者SWD模式下载程序。
系统存储器启动
地址范围0x1FFF F000~0x1FFF F7FF,大小为2KB。一般使用USART1启动自举程序。
内置SRAM启动
地址范围0x2000 0000~0x2000 FFFF,大小为64KB。由于SRAM掉电数据丢失,所以这种启动方式多用于调试。
注:由于笔者之前的本职是FPGA方向,对这方面的了解不多,水平有限,欢迎指正。
Bootloader
暂时没有写,等后面补充。
启动文件
汇编指令
指令名称 | 作用 |
---|---|
EQU | 给数字常量取一个符号名,相当于C语言中的 define |
AREA | 汇编一个新的代码段或者数据段 |
ALIGN | 编译器对指令或者数据的存放地址进行对齐,一般需要跟一个立即数,缺省表示 4字节对齐。要注意的是,这个不是 ARM的指令,是编译器的,这里放到一起为了方便。 |
SPACE | 分配内存空间 |
PRESERVE8 | 当前文件堆栈需要按照8字节对齐 |
THUMB | 表示后面指令兼容 THUMB指令。在 ARM以前的指令集中有 16位的THUMBM指令,现在 Cortex M系列使用的都是 THUMB 2指令集,THUMB 2是 32位的,兼容 16位和 32位的指令,是 THUMB的超级版。 |
EXPORT | 声明一个标号具有全局属性,可被外部的文件使用 |
DCD | 以字节为单位分配内存,要求4字节对齐,并要求初始化这些内存 |
PROC | 定义子程序,与ENDP成对使用,表示子程序结束 |
WEAK | 弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不会出错。要注意的是,这个不是 ARM的指令,是编译器的,这里放到一起为了方便。 |
IMPORT | 声明标号来自外部文件,跟C语言中的 extern关键字类似 |
LDR | 从存储器中加载字到一个存储器中 |
BLX | 跳转到由寄存器给出的地址,并根据寄存器的 LSE 确定处理器的状态,还要把跳转前的下条指令地址保存到 LR |
BX | 跳转到由寄存器 /标号给出的地址,不用返回 |
B | 跳转到一个标号 |
IF,ELSE,ENDIF | 汇编条件分支语句,跟C语言的类似 |
END | 到达文件的末尾,与PROC成对使用,文件结束 |
STM32启动文件
STM32启动文件主要实现了下面五种功能
- Set the initial SP.
- Set the initial PC == Reset_Handler.
- Set the vector table entries with the exceptions ISR address.
- Configure the clock system and also configure the external SRAM mounted on STM3210E-EVAL board to be used as data memory (optional, to be enabled by user).
- Branches to __main in the C library (which eventually calls main()).
- 初始化堆栈指针MSP = __initial_sp。
- 初始化程序计数器指针PC = Reset_Handler。
- 设置堆和栈的大小。
- 设置中断向量表,中断服务函数地址。
- 配置时钟系统,通过调用 SystemInit函数和配置外部SRAM作为数据存储器。
- 调用 C库 中的 _main 函数 初始化用户堆栈,最终调用 main 函数。
堆和栈
Stack_Size EQU 0x400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
; <h> Heap Configuration
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit
PRESERVE8
作用 | |
---|---|
栈(Stack) | 编译器自动分配和释放,存放函数参数、局部变量等。 |
堆(Heap) | 程序员分配和释放,如malloc、calloc、realloc等。 |
Stack-栈
在启动文件中,默认栈的大小为0X00000400(1KB)。
栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部 RAM 的大小(STM32F103VET6内部RAM大小为64KB)。
示例:函数内部定义局部数组变量
uint8_t receive_data[4096];
如果Stack的大小是1KB,程序就会进入HardFault_Handler()硬件错误中断。
解决办法:
- 将启动文件下的栈空间改大,需要注意不能超过内部RAM的大小。
- 用静态数组代替普通局部数组。
- 使用全局变量代替局部数组,如果使用OS,则使用内存管理。
Heap-堆
在启动文件中,默认堆的大小为 0X00000200(512B)。
堆主要用来动态内存的分配,像 malloc() 函数申请的内存就在堆上面。这个在 STM32 裸机里面用的比较少,但是在RTOS中使用较多。
为了节约空间,堆的生长方向:向上生长,栈的生长方向:向下生长。文章来源:https://www.toymoban.com/news/detail-792385.html
初始化MSP和PC
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
初始化中断向量表
; Vector Table Mapped to Address 0 at Reset
AREA RESET, DATA, READONLY
EXPORT __Vectors
EXPORT __Vectors_End
EXPORT __Vectors_Size
__Vectors DCD __initial_sp ; Top of Stack
DCD Reset_Handler ; Reset Handler
...
...
DCD PendSV_Handler ; PendSV Handler
DCD SysTick_Handler ; SysTick Handler
; External Interrupts
DCD WWDG_IRQHandler ; Window Watchdog
DCD PVD_IRQHandler ; PVD through EXTI Line detect
...
...
DCD DMA2_Channel3_IRQHandler ; DMA2 Channel3
DCD DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End
__Vectors_Size EQU __Vectors_End - __Vectors
AREA |.text|, CODE, READONLY
Reset_Handler
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT __main
IMPORT SystemInit
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
总结
本文均为原创,欢迎转载,请注明文章出处:。百度和各类采集站皆不可信,搜索请谨慎鉴别。技术类文章一般都有时效性,本人习惯不定期对自己的博文进行修正和更新,因此请访问出处以查看本文的最新版本。文章来源地址https://www.toymoban.com/news/detail-792385.html
到了这里,关于ST-ARM理论(4):STM32F1启动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!