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

STM32启动过程分析 1. 程序和数据在Flash和SRAM上的存储结构 在讲解 STM32 启动过程之前,我们先来了解一下 STM32 的程序和数据在 Flash 和 SRAM 上到底是如何存储的,因为有了这方面的知识之后,非常有助于我们理解 STM32 启动过程中还做了哪些隐藏的工作。关于详细的程序和数据存储分布信息,我们可以从Keil生成的 .map 文件中得到,要生成 .map 文件操作如下: 1.1 STM32的程序在flash上的存储结构 STM32 的程序在 Flash 上的存储结构如下图所示: 栈顶指针 M 阅读详情
AI摘要

启动文件是单片机上电后执行的第一段代码,通常由汇编语言编写,包括设置堆栈指针、初始化PC指针、配置系统时钟、调用C库的_main函数。中断向量表是处理中断的关键,而Reset_Handler是系统复位后的第一个中断服务函数,负责调用系统初始化和进入main函数。文章还介绍了汇编指令的基本用法以及堆和栈的分配。

启动文件

启动文件由汇编语言写成,时单片机上电之后执行的第一个文件。也就是从上电到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的代码段

初始化堆栈

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

stm32学习笔记-启动文件 1、配置栈 Stack_Size EQU 0x00000400 AREA STACK, NOINIT, READWRITE, ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp EQU:相当于C中的define,定义Stack_Size = 0x00000400。 AREA: 指... 阅读详情

相关推荐

ARM命令

Stack_Size EQU 0x00000400 AREA Mystack,NOINIT,READWRITE,ALIGN=3 Stack_Mem SPACE Stack_Size __initial_sp __Ventors DCD __initial_sp DCD Reset_Handle...

汉诺塔少年的博客 930

STM32第二章-启动过程详解

复位序列 硬件复位之后,CPU 内的时序逻辑电路首先完成如下两个工作(程序代码下载到内部flash为例,flash首地址 0x0800 0000) 将 0x08000000 位置存放的堆栈栈顶地址存放到 SP 中(MSP)。 将 0x08000004 位置存放的向量地址装入 PC 程序计数器。 CPU 从 PC 寄存器指向的物理地址取出第 1 条指令开始执行程序,也就是开始执行复位中断服务程序 ......

果果小师弟的博客 5739

[东拼西凑]STM32单片机启动流程及RAM和Flash的配置关系和堆栈溢出现象

开头的话: 之前一直用现成的LED工程demo,改改就上,也没细究。直到做MQTT移植的时候,发现malloc始终出错,开始找问题,于是写下本文。(前前后后摘抄、参考、改进本文,侵删) 一、STM32上电启动 BOOT1 BOOT0 启动方式 X 0 从STM32内置flash启动,JTAG或者SWD固化程序位置 1 1 从STM32内置SRAM启动,由于SRAM没有程序存储能...

江东风又起 1万+

STM32基础--启动文件详解

ALIGNALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示 4 字节对齐。ELSEBX LRALIGNENDIF首先判断是否定义了 __MICROLIB ,如果定义了这个宏则赋予标号 __initial_sp(栈顶地址)、__heap_base(堆起始地址)、__heap_limit(堆结束地址)全局属性,可供外部文件调用。有关这个宏我们在 KEIL 里面配置,具体见图使用微库。然后堆栈的初始化就由 C 库函数 _main 来完成。

weixin_48713132的博客 2368

STM32程序下载3:通过STM32CubePro-UART下载

文章目录摘要STM32启动模式三、下载步骤1. 准备HEX文件2. 连接单片机与串口模块2-1. 注意:3. 单片机进入bootloader模式4.下载工具连接单片机5. 装载hex文件 摘要 这一章主要介绍如何使用串口模块对STM32进行程序下载,使用ST-Link下载程序需要购买ST-Link,同样的使用UART下载程序也需要买一个USB转串口模块,而且串口模块相对来说比较便宜。但使用UART方式下载的缺点是下载速度缓慢。 这里我们依然使用STM32CubeProgrammer这个工具进行下载。 使用这

小白的学习笔记 9346

K_A23_001 基于STM32等单片机AT指令驱动ESP-01/ESP-01S实现手机遥控点灯

K_A23_001 基于STM32等单片机AT指令驱动ESP-01/ESP-01S实现手机遥控点灯

lfmnlxx79691557的博客 2928

01-STM32基础

ST” 是指制造商 STMicroelectronics 的缩写。“M” 表示其是基于 ARM 的 Cortex-M 系列核心。“32” 则代表其为32 位微控制器(使用32个比特位来表示一个地址)。STM32 的常见系列1)内核(core):32位,高性能ARM Cortex-M3处理器,时钟72M,实际可超频一点2)IO口: STM32F103ZET6,144引脚,112个IO,大部分IO口都耐5V(模拟通道除外),支持调试:SWD 和 JTAG,SWD只要2根数据线3)存储器容量。

小玖工作坊-博客 6993

基于stm32单片机智能手环心率血压血氧体温佩戴检测APP设计

基于stm32单片机智能手环心率血压血氧体温佩戴检测APP设计1、项目简介1.1 系统功能1.2 演示视频2、部分电路设计2.1 STM32单片机核心板电路设计2.2 血压、心率、血氧检测电路设计2.3 ESP8266 WIFI无线通信电路设计2.4 OLED显示电路设计3、单片机代码展示3.1 系统初始化3.2 手环佩戴...

qq_35485206的博客 2026

STM32-01-认识单片机

本文包含单片机简介、Cortex-M系列介绍、初识STM32、STM32原理图设计、搭建开发环境、STM32初体验、MDK5使用技巧。

L的博客 1681

STM32系列单片机的启动流程

M3系列内核与早期的ARM9/ARM11的启动动作不同,启动地址本身不再偏移,而是映射不同空间到0地址实现不同方式启动。

1839

嵌入式入门实践——编写简单STM32程序

嵌入式入门——编写简单STM32程序

qq_66144143的博客 5770

STM32上电引导过程 | 启动模式、启动文件、启动流程

01 STM32的三种启动模式 STM32有三种启动模式:FLASH启动、SRAM启动和系统存储器启动,通常三种启动方式由外部引脚boot0和boot1的电平决定。每个系列boot0和boot1电平对应的意义可能不同,下表是STM32F4xx系列的启动方式选择 当STM32上电时,无论哪种启动模式,程序都将会从地址0x0000 0000开始执行,三种启动模式只是将各自存储空间映射到地址0x0000 0000。事实上,原存储空间的内容仍然被保留,也就是说从地址0x0000 0000和原存储地址都可以

iFTrue电力电子专栏 5643

基于AT32(STM32)单片机的模块化代码之——ADC代码模块化

基于AT32(STM32)单片机的模块化代码之——ADC代码模块化 1.环境介绍 平台:AT32F415单片机,雅特力公司的AT32系列单片机其实跟STM32系列单片机大同小异,包括库函数等基本都是一样的,所以这款代码无论是AT32还是STM32都是适用的。 开发环境:MDK V5 for arm 简介:在实际的项目开发中,经常会用到多路ADC检测,所以特意在32的库函数之上做了2次封装,形成一个模块化的代码,以便于下次项目便捷开发 2.代码模块化思路 2.1在adc.h文件中枚举用到的adc通道 type

qq_39932620的博客 4083

【STM32】简介

引脚定义是非常重要的,以后再学习STM32的时候我们会经常和这些引脚定义打交道。​说明⇢在上述图中有一个小黑点代表着一号引脚,然后逆时针依次排列直到48号引脚为止。拓展⇢SWDIO和SWCLK是用于调试和编程嵌入式系统的串行线接口。SWDIO是串行线数据输入/输出线,而SWCLK是串行线时钟线。它们通常与SWD(Serial Wire Debug)协议一起使用,用于与微控制器或其他嵌入式设备进行通信和调试。引脚颜色标记橙色代表的是电源相关的引脚。蓝色代表的是最小系统相关的引脚。

"謓泽"正在路上朝着"攻城狮"方向"前进四"! 2960

手把手教你完成STM32连接阿里云平台,代码开源!!!

使用STM32轻松连接阿里云平台,完成数据上传等功能

秦朝有趣的培根 4807

STM407ZET6+OV5640调试心得

最近一个项目用了STMF407ZET6 +OV5640,调试了好几天做些总结; STMF407ZET6 开发板用的是正点原子的开发板,OV5640摄像头用的是秉火摄像头; 这其中有一个大坑,开发板的DCMI接口跟摄像头的接口不一样,要重新用杜邦线进行连接; 本人是在正点原子的“”15,ATK-OV5640摄像头模块“”源码上进行修改的。

kingseacjh的专栏 8325

STM32串口下载程序

STM32 串口下载程序 引言: 如果我们用下载器下载程序很快,很方便,但是需要购买下载器,很破费。为此我们用串口 下载程序,省去了购买下载器的麻烦。 下面介绍用串口下载程序的方法: 所需工具: 串口转 TTL 模块一个,STM32 单片机一个,杜邦线 4 根,mcuisp 软件。 单片机最小系统如图所示: 自制串口下载电路:(自制开发板的时候使用,本...

lengyuefeng212的博客 2万+

FAST-LIO 实战:从 LI-Init 标定到 YAML 配置全解析

本文详细解析了FAST-LIO算法中LI-Init标定的关键步骤与YAML配置优化技巧。从激光雷达与IMU的时空标定原理到实战参数调优,提供了一套完整的解决方案,帮助开发者解决点云畸变、建图漂移等常见问题,提升SLAM系统在动态环境中的稳定性和精度。

weixin_42651281的博客 325

基于STM32单片机的健康监护语音播报APP设计

系统构成:本设计由STM32单片机电路+心率血氧采集电路+DS18B20温度采集电路+蜂鸣器报警电路+ 按键检测电路+wifi电路+美锐-MR628 TTS语音播报电路+LED指示灯电路+OLED显示电路+电源电路组成。

嵌入式基地 3513

测试人必看!正交表与Allpairs工具对比:如何选择最适合你的组合测试方案?

本文深入对比了正交表、PICT与Allpairs三种主流组合测试方案,帮助测试人员根据项目场景做出最佳选择。文章分析了各自的核心原理、优劣势及适用场景,特别强调了在涉及复杂约束时PICT工具的强大功能,并提供了从原理学习到CI/CD集成的实战选型指南。

weixin_29224309的博客 267

ArcGIS+PLUS+InVEST三件套实战:从零搞定土地利用变化与碳储量预测(附完整数据包)

本文详细介绍了如何整合ArcGIS、PLUS模型和InVEST模型,构建土地利用变化与碳储量预测的完整研究流水线。通过多情景模拟和生态系统服务评估,提供从数据准备到结果验证的实战指南,助力研究者高效完成生态评估项目。

weixin_30399821的博客 543
上一篇: 【os模块】os.walk 获取指定路径下文件名
下一篇: 【STM32】启动流程分析补充
熟练的魔法师
博客等级 码龄8年 2714粉丝 77原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值