IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> STM32启动过程笔记 -> 正文阅读

[嵌入式]STM32启动过程笔记

STM32启动过程

STM32的启动过程中包括

  1. 堆栈指针SP的初始化
  2. PC指针的初始化(指向复位程序)
  3. 初始化中断向量表
  4. 配置系统时钟
  5. 调用C库函数_main,开始执行main函数

启动文件

STM32从地址0x00000000开始启动,它是怎么到main函数的呢?

这里以F103为例,查看启动文件

Stack_Size      EQU     0x00000400

                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     0x00000200

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

                PRESERVE8
                THUMB


; 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     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
                ...(省略)
                DCD     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors

                AREA    |.text|, CODE, READONLY
                
; Reset handler
Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  __main
                IMPORT  SystemInit
                LDR     R0, =SystemInit
                BLX     R0               
                LDR     R0, =__main
                BX      R0
                ENDP
                
; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
...(省略)
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP

Default_Handler PROC

                EXPORT  WWDG_IRQHandler            [WEAK]
                ...
                EXPORT  DMA2_Channel3_IRQHandler   [WEAK]
                EXPORT  DMA2_Channel4_5_IRQHandler [WEAK]

WWDG_IRQHandler
...(省略)
DMA2_Channel4_5_IRQHandler
                B       .

                ENDP

                ALIGN

;*******************************************************************************
; User Stack and Heap initialization
;*******************************************************************************
                 IF      :DEF:__MICROLIB
                
                 EXPORT  __initial_sp
                 EXPORT  __heap_base
                 EXPORT  __heap_limit
                
                 ELSE
                
                 IMPORT  __use_two_region_memory
                 EXPORT  __user_initial_stackheap
                 
__user_initial_stackheap

                 LDR     R0, =  Heap_Mem
                 LDR     R1, =(Stack_Mem + Stack_Size)
                 LDR     R2, = (Heap_Mem +  Heap_Size)
                 LDR     R3, = Stack_Mem
                 BX      LR

                 ALIGN

                 ENDIF

                 END

;******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE*****

栈空间配置

  • 主要用于局部变量函数调用函数形参的开销
Stack_Size      EQU     0x00000400

                AREA    STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem       SPACE   Stack_Size
__initial_sp
  1. EQU宏定义的伪指令,相当于#define Stack_Size 0x00000400
  2. AREA告诉汇编编译器一个新的代码段或者数据段
    • STACK表示定义的是一个栈区
    • NOINIT表示不将初始值写入内存区域,也就是初始化为03
    • READWRITE标志区域可读可写
    • ALIGN=3,表示2^3=8字节对齐(相当于ALIGN 8)
  3. SPACE用于分配一定大小的内存空间,单位为字节,相当于分配了一个Stack_Size大小的内存空间,这段内存空间的起始地址是Stack_Mem
  4. __initial_sp紧挨着SAPCE语句放置,表示栈的结束地址,也即栈顶地址(栈是由高向低生长的)

堆空间配置

  • 用于动态内存的分配,malloc函数分配内存用的就是这里的内存

    Heap_Size       EQU     0x00000200
    
                    AREA    HEAP, NOINIT, READWRITE, ALIGN=3
    __heap_base
    Heap_Mem        SPACE   Heap_Size
    __heap_limit
    
  • 同上,这段代码的函数是:分配一个大小为Heap_Size的堆区,可读写,8字节对齐,堆区的起始地址是Heap_Mem

  • __heap_limit是汇编代码的地址标号,这里用来表示堆区的结束地址

ARM指令集

PRESERVE8
THUMB
  • PRESERVE8表示指定当前文件的堆栈按照8字节对齐
  • THUMB表示后面的指令为THUMB指令。THUMB是ARM以前的指令集,16bit,现在的Cortex-M系列用的是THUMB-2指令集,32bit的,也兼容16bit的,绝大多数 16 位 Thumb 指令只能访问 R0‐R7,而 32 位 Thumb‐2 指令可以访问所有寄存器。

向量表

AREA    RESET, DATA, READONLY
EXPORT  __Vectors
EXPORT  __Vectors_End
EXPORT  __Vectors_Size
  1. 定义一个新的数据段RESET,只读
  2. 声明三个全局标号
__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     DMA2_Channel4_5_IRQHandler ; DMA2 Channel4 & Channel5
__Vectors_End

__Vectors_Size  EQU  __Vectors_End - __Vectors
  1. 通过DCD分配一片连续的字单元的存储空间,__Vectors标号的存储的值是__initial_sp所表示的地址值,也就是栈顶地址
  2. 向量表的第二个表项Reset_Handler是中断复位函数Reset_Handler的入口地址,以此类推
  3. __Vectors_End表示中断向量表结束
  4. __Vectors_Size的大小就是__Vectors_End - __Vectors
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
  1. PROC定义一个子程序Reset_Handler
  2. Reset_Handler作为一个全局标号
  3. __mainSystemInit来自外部文件,C库的main函数和库函数的系统时钟的配置函数
  4. LDR R0, =SystemInitSystemInit函数的指针的值传入R0寄存器中,然后跳转到SystemInit执行,跳转之前把下条指令保存到LR连接寄存器中,当SystemInit执行完成之后,再继续执行下条指令,也就是LDR R0, =__main
  5. LDR R0, =__main将C库的main函数的地址值传入R0寄存器中,然后跳转到main函数中执行,BX不用返回,然后就开始执行用户的APP程序了
  6. ENDP表示子程序结束
; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler                [WEAK]
                B       .
                ENDP
HardFault_Handler\
                PROC
                EXPORT  HardFault_Handler          [WEAK]
                B       .
                ENDP
...(省略)
SysTick_Handler PROC
                EXPORT  SysTick_Handler            [WEAK]
                B       .
                ENDP
Default_Handler PROC

                EXPORT  WWDG_IRQHandler            [WEAK]
                EXPORT  PVD_IRQHandler             [WEAK]
                EXPORT  TAMPER_IRQHandler          [WEAK]
                ...省略
                EXPORT  DMA2_Channel3_IRQHandler   [WEAK]
                EXPORT  DMA2_Channel4_5_IRQHandler [WEAK]

WWDG_IRQHandler
PVD_IRQHandler
TAMPER_IRQHandler
...(省略)
DMA2_Channel3_IRQHandler
DMA2_Channel4_5_IRQHandler
                B       .

                ENDP

                ALIGN
  • 定义各个中断服务程序,启动文件为我们写好了全部的中断服务程序,函数的名称必须与向量表里面初始化的名称一样。
  • 这些程序都是空的,需要我们在C文件里面重新实现。如果我们写的中断服务程序的函数名写错了,程序也不报错,而是会进入一个死循环
  • [WEAK]选项声明其他的同名标号优先于该标号被引用
  • Default_Handler前面的和后面的分别属于系统异常中断服务程序和外部中断服务程序

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dHwA269I-1650807753243)(C:\Users\Lux\AppData\Roaming\Typora\typora-user-images\image-20220424211807457.png)]

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-316O54Yt-1650807753243)(C:\Users\Lux\AppData\Roaming\Typora\typora-user-images\image-20220424211840573.png)]

IF      :DEF:__MICROLIB

    EXPORT  __initial_sp
    EXPORT  __heap_base
    EXPORT  __heap_limit

ELSE

    IMPORT  __use_two_region_memory
    EXPORT  __user_initial_stackheap
    __user_initial_stackheap

    LDR     R0, =  Heap_Mem
    LDR     R1, =(Stack_Mem + Stack_Size)
    LDR     R2, = (Heap_Mem +  Heap_Size)
    LDR     R3, = Stack_Mem
    BX      LR

    ALIGN

ENDIF

END
  1. 判断是否使能了MicroLib

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xG1TPN8V-1650807753244)(C:\Users\Lux\AppData\Roaming\Typora\typora-user-images\image-20220424212306886.png)]

  2. 使能,则将__initial_sp __heap_base __heap_limit赋予全局属性

  3. 未使能

    • 将堆区首地址保存到R0
    • 将栈区大小保存到R1
    • 将堆区大小保存到R2
    • 将栈区首地址保存到R3
      • 跳转到LR寄存器保存的地址中执行,相当于MOV PC, LR
  4. R14 是连接寄存器( LR)。在一个汇编程序中,你可以把它写作 both LR 和 R14。 LR 用于在调用子程序时存储返回地址。例如,当你在使用 BL(分支并连接, Branch and Link)指令时,就自动填充 LR 的值

  5. 在ARM体系结构中LR的特殊用途有两种:一是用来保存子程序返回地址;二是当异常发生时,LR中保存的值等于异常发生时PC的值减4(或者减2),因此在各种异常模式下可以根据LR的值返回到异常发生前的相应位置继续执行。在这里是第一种功能,那么结合BX的用法,就是回到之前保存的返回地址处。

汇编指令

  • EXPORT声明一个标号具有全局属性,可被外部的文件使用。

  • DCD分配一个或者多个以字为单位的内存,以四字节对齐,并要求初始化这些内存。在向量表中, DCD 分配了一堆内存,并且以 ESR 的入口地址初始化它们

  • WEAK表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。这里表示复位子程序可以由用户在其他文件重新实现,这里并不是唯一的。

  • IMPORT表示该标号来自外部文件,跟 C 语言中的EXTERN 关键字类似。

  • LDR从存储器中加载字到一个寄存器中

  • BL跳转到有寄存器或者标号给出的地址,并把跳转前的下条指令地址保存到LR(ARM内核的连接寄存器)

  • BLX跳转到寄存器给出的地址,并根据寄存器的LSE确定处理器的状态,还要把跳转前的下条指令保存到LR

  • BX跳转到寄存器或者标号给出的地址,不用返回

  • B跳转到下一个标号

  • IF,ELSE,ELDIF汇编的条件分支语句

  • END文件结束

  • ALIGN对指令或者数据存放的地址进行对齐,默认是4字节对齐

  • PROC定义子程序,与ENDP成对使用,表示子程序结束

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2022-04-26 11:55:20  更:2022-04-26 11:58:04 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:36:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码