STM32 HAL库开发学习3.STM32启动浅析

STM32 HAL库开发学习3.STM32启动浅析

  • 一、STM32启动模式(也称自举模式)
    • [1. MSP与PC指针赋值](#1. MSP与PC指针赋值)
    • [2. F1系列的启动模式:](#2. F1系列的启动模式:)
    • [3. F4系列启动模式](#3. F4系列启动模式)
    • [4. F7系列启动模式](#4. F7系列启动模式)
    • [5. H7系列启动模式](#5. H7系列启动模式)
  • 二、STM32启动过程
    • [1. MSP 栈顶地址](#1. MSP 栈顶地址)
    • [2. PC值](#2. PC值)
    • [3. Reset_Handler](#3. Reset_Handler)
    • [4. 启动文件内容](#4. 启动文件内容)
    • [5. 堆栈](#5. 堆栈)
    • [6. 中断向量表](#6. 中断向量表)
  • 三、STM32启动过程图解

一、STM32启动模式(也称自举模式)

1. MSP与PC指针赋值

STM32 系列微控制器中的 M3、M4、M7 内核在经历复位操作之后,会率先从特定的内存地址 0x0000 0000 处尝试获取堆栈指针 MSP 的初始值。此初始值具有极为关键的意义,它明确界定了栈顶在内存中的具体位置,为后续程序运行时的函数调用、局部变量存储以及中断处理等操作建立起至关重要的栈空间基础架构。

然后,内核从0x0000 0004处取出程序计数器PC的初始值,该初始值指向的是复位向量所对应的复位处理程序的入口地址(名称为Reset_Handler),这一步明确了程序即将开始执行的具体起始点,使得处理器能够准确地跳转到复位处理程序中,进而开启一系列诸如初始化系统时钟、配置外设、设置中断相关参数等系统初始化操作。

2. F1系列的启动模式:

  1. 系统复位后,SYSCLK的第4个上升沿,BOOT引脚的值锁存;
  2. 启动模式选择引脚。
BOOT1 BOOT0 启动模式 0x00000000映射地址 0x00000004映射地址
x 0 主闪存存储器 0x08000000 0x08000004
0 1 系统存储器, ST Boot Loader 0x1FFFF000 0x1FFFF004
1 1 内置 SRAM 0x20000000 0x20000000

系统存储器启动时,内嵌的自举程序存放在系统存储区,由ST在生产线上写入,用于通过可用的串行接口对闪存储器进行重新编程。

  • 对于小容量、中容量和大容量的产品而言,可以通过UART1接口启用自举程序。
  • 对于互联型产品而言,可以通过以下某个接口启用自举程序:USART1、USART2(重映像的)、CAN2(重映像的)或USB OTG全速接口的设备模式(通过固件更新DFU协同)。
  • USART接口依靠内部8MHz振荡器(HSI)运行。CAN和USB接口只能当外部8MHz、14.7456MHz或25MHz时钟(HSE)时运行。

3. F4系列启动模式

与F1系列基本一致,注意的是:

如果使用内置 SRAM, 可以使用FSMC重映射到外部的SRAM,可以通过SYSCFG_MEMRMP 寄存器配置。

4. F7系列启动模式

BOOT 启动地址选项字节 启动模式
0 BOOT_ADD0[15:0] 由用户选项字节 BOOT_ADD0[15:0] 决定启动地址,ST出厂默认的启动地址为:位于0x0200 0000的ITCM上的FLASH
1 BOOT_ADD1[15:0] 由用户选项字节 BOOT_ADD1[15:0] 决定启动地址,ST出厂默认的启动地址为:位于0x0010 0000的系统自举程序
Flash选项控制寄存器(FLASH_OPTCR1)----BOOT_ADDx[15:0] 对应地址位 [29:14]
  • BOOT_ADDx = 0x0000: 从 ITCM RAM (0x0000 0000)启动
  • BOOT_ADDx = 0x0040: 从系统存储器 (0x0010 0000) 启动
  • BOOT_ADDx = 0x0080: 从ITCM 接口上的FLASH(0x0020 0000)启动
  • BOOT_ADDx = 0x2000: 从 AXIM 接口上的 FLASH(0x0800 0000)启动
  • BOOT_ADDx = 0x8000: 从 DTCM RAM(0x2000 0000)启动
  • BOOT_ADDx = 0x8004: 从 SRAM1(0x2001 0000)启动
  • BOOT_ADDx = 0x8013: 从 SRAM2(0x2004 C000)启动

x=0/1, 出厂时,BOOT_ADD0=0x0080, BOOT_ADD1 = 0x0040

5. H7系列启动模式

BOOT 启动地址选项字节 启动模式
0 BOOT_ADD0[15:0] 由用户选项字节BOOT_ADD0[15:0]决定启动地址,ST出厂默认的启动地址为:0x0800 0000的Flash地址
1 BOOT_ADD1[15:0] 由用户选项字节 BOOT_ADD1[15:0]决定启动地址,ST出厂默认的启动地址为: 0x1FF0 0000的系统存储器地址

二、STM32启动过程

以内部Flash启动为例。

1. MSP 栈顶地址

当芯片配置为从主闪存启动(例如 BOOT0 = 0,BOOT1 = x)时,存储控制器会自动将起始地址 0x00000000 映射到主闪存的起始物理地址(通常是 0x08000000)。这是通过芯片内部的硬连线和一些基本的逻辑电路来实现的,这些电路会根据启动模式引脚(BOOT0 和 BOOT1)的状态来确定初始的地址映射关系。

这是MSP值就是 0x0800 0000。

2. PC值

内核第二步获取PC的初始值。 这个PC的初始值指向的就是 Reset_Handler。

Reset_Handler定义在启动文件: startup_stm32xxx.S 里。

3. Reset_Handler

Reset_Handler执行一些初始化,再去调用 main函数。

asm 复制代码
Reset_Handler PROC
    EXPORT Reset_Handler [WEAK]		; WEAK 意思允许其它地方重新定义
    IMPORT __main                                 ;  声明来自外部的函数
    IMPORT SystemInit
    LDR R0, =SystemInit                          ; 调用函数 SystemInit
    BLX R0
    LDR R0, =__main                                 ; 调用 __main
    BX R0
    ENDP

4. 启动文件内容

  1. 初始化MSP 指针 从 0x0800 0000 获取
  2. 初始化PC 从0x0800 0004 获取
  3. 设置堆栈大小 Heap_Size(堆), Stack_Size(栈)
  4. 初始化中断向量表 __Vectors 定义
  5. 调用初始化函数,可选的,如调用 SystemInit 函数
  6. 调用 __main
  7. 调用 main

5. 堆栈

  1. 栈(Stack):由编译器自动分配和释放,存放函数参数、局部变量等
  2. 堆(Heap):由malloc,calloc,realloc等 程序分配和释放
asm 复制代码
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

6. 中断向量表

从__Vectors 里开始。

中断向量表里面的很多个DCD结构。

asm 复制代码
__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

由于 __initial sp是指向 0x0800 0000,后面每一项偏移4个字节。

每一项是一个函数名,(函数名就是函数的地址)。

三、STM32启动过程图解

从图上可以看出,启动时从0x0800 0000获取 MSP地址,就是栈顶地址,即: 0x2000 0788。

然后 0x0800 0004放的是PC指针,程序到 0x0800 01CD执行引导代码,即Reset_Hander函数。

对于这些地址值,在 .map 文件里也可以找到其地址。

本文学习资源来自 正点原子HAL开发 官方教程。

相关推荐
Chrikk1 小时前
NCCL学习笔记-概念全解
笔记·学习
GHL2842710901 小时前
redis学习-value数据结构
数据库·redis·学习
vortex51 小时前
正则表达式进阶学习(一):环视、捕获分组与后向引用
学习·正则表达式
武昌库里写JAVA1 小时前
Redis奇幻之旅(四)4. Redis Cluster
java·开发语言·spring boot·学习·课程设计
酒与花生米1 小时前
【Vue学习】Vue 组件实例的生命周期(四个阶段,八个钩子)
javascript·vue.js·学习
开心邮递员1 小时前
关于元学习的相关论文
学习
KBDYD10101 小时前
单片机控制
stm32·单片机·嵌入式硬件
私人珍藏库1 小时前
《空舞的巨兽》官方学习版
学习
黄金右肾2 小时前
STM32之CAN通讯(十一)
stm32·单片机·can·嵌入式软件
番茄老夫子2 小时前
STM32H7的SPI总线基础知识备忘
stm32·单片机·嵌入式硬件