【STM32】单片机启动文件分析

2023-11-12

启动文件

启动文件由汇编语言写成,时单片机上电之后执行的第一个文件。也就是从上电到mian函数中间的一段过程。

bootloader

bootloader也可以叫启动文件,每种MCU都有对应的启动文件。但开发环境往往自动完整地提供了这个启动文件,不需要开发人员再行干预启动过程,只需要从main函数开始进行应用程序的设计即可。

启动文件是使用汇编指令写的,所以在看启动文件之前大家需要先了解一下汇编指令,常用的汇编指令如下:

常见指令

指令 含义
EQU 给数字常量取一个符号名,类似于define
AREA 汇编一个新的代码或者数据段
SPACE 分配内存空间
PRESERVE8 当前文件堆栈需要按8字节对齐
EXPORT 声明一个符号具有全局属性,可以被外部文件调用
DCD 以word为单位分配内存,要求4byte对齐,并且要求初始化这些内存
PROC 定义子程序,与ENDP一同使用表示程序结束
WEAK 弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件也没有定义,也不会出错。这个是编译器指令,不属于arm的指令。
IMPORT 声明标号来自外部文件,类似于extern
B 跳转到一个标号
ALIGN 编译器对数据或者内存进行对齐,一般跟一个立即数。缺省表示4字节对齐,这个是编译器指令,不属于arm的指令。
END 到达文件末尾文件结束
IF,ELSE,ENDIF 条件语句类似于if else
LDR(load) LDR R0,[R1] 假设R1的值是x,读取地址x上的数据(4个字节)。保存到R0中。
STR(store) STR R0,[R1] 假设R1的值是x,把R0的值写到地址x(4个字节)。
MOV:移动 MOV R0, R1:把R1的值赋给R0. MOV R0, #0x100 R0=0x100

启动文件做了什么

1.设置堆栈指针 SP = _initial_sp
2.设置PC指针 = Reset_Handler
3.配置系统时钟
4.配置外部 SRAM 用于程序变量等数据存储(可选)
5.调用C库的 _main 函数,最终调用main函数

这边我们举个例子来具体说明启动文件具体的执行

开辟栈

Stack_Size      EQU     0x00001800	

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

在这里插入图片描述

EQU 是伪指令。伪指令的意思是指这个 “指令” 并不会生产二进制程序代码,也不会引起变量空间分配。
ARER :汇编一个新的代码或者数据段
STACK : 表示这个段的名字,可以任意命名。
NOINIT: 表示此数据段不需要填入初始数据。
READWRITE:表示此段可读可写。
ALIGN=3: 表示首地址按照2的3次方对齐,所以栈空间是8字节对齐的
SPACE 给 STACK 段分配 Stack_Size 的空间。

__initial_sp只是一个标号,标号主要用于表示一片内存空间的某个位置,等价于C语言中的“地址”概念。地址仅仅表示存储空间的位置。此处的 __initial_sp 紧接着 SPACE 语句放置,表示了栈顶地址。

开辟堆空间

堆和栈的属性都是 READWRITE 可读写,可读写段保存于 SRAM区,即地址0x2000 0000 地址后

; <h> Heap Configuration
;   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>

Heap_Size       EQU     0x00000000

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

在这里插入图片描述

中断向量表部分

PRESERVE8:指定当前文件的堆栈按照8 字节对齐。
THUMB :表示后面指令兼容THUMB 指令。

                PRESERVE8
                THUMB


; Vector Table Mapped to Address 0 at Reset

                AREA    DEFVECT, DATA, READONLY
                EXPORT  __Vectors

__Vectors       DCD     __initial_sp              ; Top of Stack
                DCD     Reset_Handler             ; Reset Handler

在这里插入图片描述
上图中的 AREA 定义了一段名为 RESET 的 READONLY 只读数据段,只读属性保存在 Flash 区(如果STM32从Flash启动,则此中断向量表的地址为0x0800 0000)
EXPORT 指令,使得标号可以被外部文件调用,对应的有个 IMPORT 指令,指示后续符号是在外部文件定义的,外部文件的函数供汇编文件调用
标号__Vectors,表示中断向量表入口地址
标号 __Vectors_End,表示中断向量表的结束地址
标号__Vectors_Size,表示中断向量表的大号

开始建立中断向量表:

在这里插入图片描述
中间中断向量省略。。。。。。。
在这里插入图片描述
DCD指令作用是开辟一段空间,其意义等价于 C 语言中的地址符 “&” 。
中断向量表的建立类似于使用C语言定义了一个指针数组,其每一个成员都是一个函数指针,分别指向各个中断服务函数。

; Vector Table Mapped to Address 0 at Reset

                AREA    DEFVECT, DATA, READONLY
                EXPORT  __Vectors				

__Vectors       DCD     __initial_sp              ; Top of Stack	//分配4字节的空间
                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     DMACERR0_IRQHandler       ; 0,   DMAC Error Count Interrupt
                DCD     DMACTC0_IRQHandler        ; 1,   DMAC Terminal Count Interrupt
                DCD     DMACERR1_IRQHandler       ; 2,   DMAC Error Count Interrupt
                DCD     DMACTC1_IRQHandler        ; 3,   DMAC Terminal Count Interrupt
                DCD     DMACERR2_IRQHandler       ; 4,   DMAC Error Count Interrupt
                DCD  

Reset_Handler 系统启动

系统上电或者复位后首先执行的代码就是复位中断服务函数 Reset_Handler:也是中断向量表的第一个函数。
在这里插入图片描述
图中的 Reset_Handler 中断服务函数使用了WEAK申明,说明我们在外部可以自定义 Reset_Handler 函数
PROC、ENDP这一对伪指令把程序分为若干个过程,是程序结构更加清晰
LDR R0,[R1]:假设R1的值是x,读取地址x上的数据(4个字节)。保存到R0中。这里是读取SystemInit函数地址,存入R0.

调用SystemInit函数。这个函数里面开启了外部晶振设置了PLL除能了所有中断设置了时钟

_main 标号表示 C/C++标准实时库函数里的一个初始化子程序 _main的入口地址。该程序的一个主要作用是初始化堆栈(跳转_user_initial_stackheap标号进行初始化堆栈),并初始化映像文件,最后跳转到C程序中的main函数。这也正解释了为什么所有的C程序必须有一个main函数作为程序的起点,因为这是由C/C++标准实时库所规定的。

; Reset Handler

Reset_Handler   PROC
                EXPORT  Reset_Handler             [WEAK]
                IMPORT  boot_init
                IMPORT  boot_entry
                LDR     R0, =boot_init
                BLX     R0
				LDR     R0, =0x1008DFFC		;ブートプログラム破損検知状態格納アドレスに"0"を設定
				LDR     R1, =0x00000000
				STR     R1, [R0]
                LDR     R0, =boot_entry
                BX      R0
                ENDP

LDR R0, =0x1008DFFC:仍然是LDR,但是里面有个等号,这是一条伪指令,伪指令就是并不存在这么一条指令,它最终会被拆分成几条真正的RAM指令。执行结果是R0=0x1008DFFC

STR R1, [R0]:假设R1的值是x,把R0的值写到地址x(4个字节)。这里是把R0, =0x1008DFFC的地址写到R1 (R1, =0x00000000)

中断服务程序

在这里插入图片描述

; Dummy Exception Handlers (infinite loops which can be modified)

NMI_Handler     PROC
                EXPORT  NMI_Handler               [WEAK]
                B       .
                ENDP

中间中断服务程序省略。。。。。。。
在这里插入图片描述
中间中断服务程序省略。。。。。。。
在这里插入图片描述
当CPU检查到某个中断产生时,硬件会根据我们提供的中断号自动跳转到向量表中与这个中断号对应的这个中断服务函数的入口地址。

上面的这些不管是系统的中断服务程序还是外设的中断服务程序,都是_WEAK申明,其实我们写中断服务函数的时候,都会自己实现,比如F1中,我们在stm32f1xx_it.c文件中实现使用到的中断服务函数:
在这里插入图片描述

在工作中遇到一个第二次Reset_Handler2的例子

                ALIGN

                AREA    boot_program_2, CODE, READONLY

; Reset Handler2

Reset_Handler2  PROC
                EXPORT  Reset_Handler2             [WEAK]
                IMPORT  boot_init
                IMPORT  boot_entry
                LDR     R0, =boot_init
                BLX     R0				
				LDR     R0, =0x1008DFFC		;ブートプログラム破損検知状態格納アドレスに"1"を設定
				LDR     R1, =0x00000001
				STR     R1, [R0]
                LDR     R0, =boot_entry
                BX      R0
                ENDP

AREA boot_program_2, CODE, READONLY开辟一段数据空间名叫boot_program_2的readonly的代码段

初始化堆栈

文件最后就是堆栈的初始化工作:
在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【STM32】单片机启动文件分析 的相关文章

  • opencv-python中的腐蚀与膨胀函数

    1 图像的腐蚀 就像土壤侵蚀一样 这个操作会把前景物体的边界腐蚀掉 但是前景仍然是白色 这是怎么做到的呢 卷积核沿着图像滑动 如果与卷积核对应的原图像的所有像素值都是1 那么中心元素就保持原来的像素值 否则就变为零 这回产生什么影响呢 根据
  • Vision-Centric BEV Perception: A Survey (以视觉为中心的BEV感知综述)论文笔记

    原文链接 https arxiv org abs 2208 02797 1 引言 BEV表达包含了丰富的语义信息 精确定位和绝对尺度 可直接应用于下游任务如行为预测和运动规划 此外 BEV表达为融合不同视角 模态 时间和智能体的信息提供了物

随机推荐

  • nginx配置文件root和alias区别

    总结 alias指定的目录是准确的 root是指定目录的上级目录 并且该上级目录要含有location指定名称的同名目录 root的处理结果是 root路径 location路径 http后面的地址 alias的处理结果是 使用alias路
  • R语言的包bnlearn生成的概率图模型如何进行后续的检验和验证是否合理?有相关示例和论文吗?...

    bnlearn 包生成的概率图模型可以通过多种方法进行后续检验和验证 具体来说 可以考虑以下几种方法 对模型进行统计检验 以评估模型是否符合数据的分布 例如 可以使用Kolmogorov Smirnov检验 Lilliefors检验等 对模
  • condition update在分布式系统中设计

    condition update在分布式系统中设计 1 定义 condition update称为条件更新 用于分布式系统中数据一致性 能够保证在并发操作数据时的正确性 2 方式 1 可以通过version来保证condition upda
  • 解决pgAdmin4启动失败方法

    1 问题现象 有时pgadmin 4启动仅显示启动界面 或者 点击图标一直都没反应 启动界面用鼠标点击下就消失了 然后过很长时间就保错 the application server could not be contect 错误 比如一直出
  • python安装anaconda_安装Anaconda后,python出现import Error

    背景 Win10 VSCode下安装了Python3 6 4和一些package 有的package在site package路径下 在已经安装了Python3 6 4之后 又安装了Anaconda 安装设置都是默认的 Error出现 这时
  • qt控件学习笔记

    QToolBox控件 QToolBox控件 类似于下拉列表控件 头文件 include
  • Jenkins持续集成demo

    1 下载Jenkins的war包 官网地址 https jenkins io 点击下载 将jenkins war 部署到Tomcat中 本文使用的是Tomcat8 5 35 注意Tomcat需要配置账号密码 Tomcat7 是 manage
  • MySQL、Oracle中去重并保留最新的一条数据

    MySQL select from my table where id in select id from select id name group code max create time mt from my table group b
  • IDEA的设置

    terminal wsl2 setting gt tools gt Termianl gt shell path 填写wsl exe的绝对路 绝对路径的查找 wsl2 安装 https docs microsoft com en us wi
  • LA@向量组线性相关性

    文章目录 向量组线性相关性 线性相关 线性无关 多向量向量组线性相关 单向量向量组的线性相关性 单位向量向量组线性相关性 双向量向量组的线性相关性 双向量线性相关的几何意义 三向量线性相关的几何意义 包含零向量的向量组线性相关 概念迁移 线
  • STC89C51——中断系统

    前言 本文介绍基于常见的51单片机 即如下图的芯片 STC89C51具备5个中断源 中断源 优先级 中断请求标志位 中断允许控制位 外部中断0 0 IE0 EX0 定时器中断0 1 TF0 ET0 外部中断1 2 IE1 EX1 定时器中断
  • 2021 Web 前端热点笔试面试题总结【更新版】

    提醒 我只是答案的搬运工 如果在浏览中发现有错误 欢迎评论中提出来 我好修改 谢谢 简述异步和同步的区别 同步 浏览器访问服务器请求 用户看得到页面刷新 重新发请求 等请求完 页面刷新 新内容出现 用户看到新内容 进行下一步操作 异步 浏览
  • 指定岗位

    一 背景介绍 这里我们选择的是目前求职和招聘最常用的网站Bxxx 在采用其它方法的试验中 我们可能会遇到如下问题 不知道该怎么解析网址 自定义城市和岗位的搜索词 不知道怎么样批量爬取 这里指的是自动切页 不知道该怎么破解动态cookie的问
  • K8S 安装 Ingress Controller

    版本介绍 版本1 NGINX Ingress Controller nginx公司的nginx ingress NGINX Ingress Controller 由 F5 NGINX 开发和维护 docs nginx com 可在 GitH
  • Ubuntu命令介绍——echo

    echo是一个非常简单 直接的linux命令 将argument送出至标准输出 STDOUT 通常就是在显示器 monitor 上输出 为了更好的理解 不如先让我们跑一下 echo 命令好了 echo 你会发现只有一个空白行 然后又回到 s
  • k8s--基础--6.1--环境搭建--多master高可用集群

    k8s 基础 6 1 环境搭建 多master高可用集群 前提 使用root用户 1 机器 主机名 IP 说明 master1 192 168 187 154 2核4G 硬盘20G 核数最小要求是2 master2 192 168 187
  • SQLite向arm板子的移植

    SQLite向arm linux的移植 SQLite是一个开源的嵌入式关系数据库 我们用它来管理从M0端接收的数据 将检测到的仓库信息存储起来 SQLite环境的建立 首先从下载最新版本的sqlite源码包 我下载的是sqlite amal
  • mac idea 使用技巧-长期更新

    公司配发了新款Mac book pro M1 以前都是使用window 版本 切换成了mac 操作idea 很多技巧需要重新掌握 现在总结文档 idea 版本 试用版 建议大家自行购买账户 idea 在Mac 环境下游多中快捷键组合 注意事
  • 最通俗易懂的nginx

    nginx 文章目录 nginx 什么是nginx nginx配置文件 正向代理 反向代理 负载均衡 动静分离 高可用 什么是nginx Nginx是一款自由的 开源的 高性能的HTTP服务器和反向代理服务器 同时也是一个IMAP POP3
  • 【STM32】单片机启动文件分析

    启动文件 启动文件由汇编语言写成 时单片机上电之后执行的第一个文件 也就是从上电到mian函数中间的一段过程 bootloader bootloader也可以叫启动文件 每种MCU都有对应的启动文件 但开发环境往往自动完整地提供了这个启动文