STM32入门系列-启动文件介绍
在启动文件内部使用的都是汇编语言,这个文件的作用是负责执行微控制器从“复位”到“开始执行 main 函数”中间这段启动时间所必须进行的工作。它完成的具体工作有:
初始化堆栈指针SP=_initial_sp
初始化PC指针=Reset_Handler
初始化中断向量表
配置系统时钟
调用C库函数_main初始化用户堆栈,从而转向我们用户应用程序的main。
汇编指令
打开STM32的启动文件会发现,里面全部都是汇编语句,对于汇编指令不了解的朋友来说可能一头雾水。下面我们按照启动文件内指令出现的顺序来介绍,相信可以了解到大概情况。
EQU:给数字常量取一个符号名, 相当于C语言中的预处理命令define。其常用格式如下:
Stack_Size EQU 0x00000400
表示将0x00000400这个数值,用Stack_Size名代替。
AREA:汇编一个新的代码段或者数据段。常用格式如下:
AREA STACK, NOINIT, READWRITE, ALIGN=3
表示汇编一个数据段,名字是STACK,NOINIT表示不初始化,READWRITE表示可读可写,ALIGN表示字节对齐,通常后面会赋一个立即数,比如ALIGN=3表示的就是2^3字节对齐,即8字节对齐。
SPACE:分配一定大小的内存空间,单位为字节。常用格式如下:
Stack_Mem SPACE Stack_Size
表示给Stack_Mem分配一个Stack_Size大小的内存空间。通常它后面还会跟随一个__initial_sp语句,表示栈的结束地址,即栈顶地址,因为栈是由高向低生长的。
PRESERVE8:当前文件堆栈需按照8字节对齐。格式:直接写此指令即可。
THUMB:表示后面指令兼容THUMB指令。在ARM以前的指令集中有16位的THUMBM指令,现在Cortex-M系列使用的都是THUMB-2指令集,THUMB-2是32位的,兼容16位和32位的指令,是THUMB的超级版。格式:直接写此指令即可。
EXPORT:声明一个具有全局属性的标号,可被外部文件使用。常用格式如下:
EXPORT __Vectors
表示__Vectors标号具有全局属性,外部文件可以调用它。
DCD:以字为单位分配内存, 要求4字节对齐, 并要求初始化这些内存。常用格式如下:
DCD Reset_Handler ; Reset Handler
表示给Reset_Handler名称的地址分配内存并初始化, 这个名称地址可以在“STM32F4xx中文参考手册”-“中断和事件”-“中断和异常向量”章节中找到。在那个函数名后面还有一个“;”, 在汇编程序中“;”即注释,和C语言中的//类似效果。在后面的学习中会接触很多的中断函数,这些中断函数名都可在DCD这部分找到。
PROC:定义子程序。常用格式:
; Reset handler
Reset_Handler PROC
EXPORT Reset_Handler [WEAK]
IMPORT SystemInit
IMPORT __main
LDR R0, =SystemInit
BLX R0
LDR R0, =__main
BX R0
ENDP
表示定义一个全局的子程序Reset_Handler,需与ENDP成对使用,表示子程序结束。在
EXPORT Reset_Handler [WEAK]
后面有一个[WEAK],这个是弱定义,如果外部文件声明了一个标号,则优先使用外部文件定义的标号,如果外部文件没有定义也不出错。要注意的是:这个并不是ARM的指令,是编译器的。
LDR:从存储器中加载字到一个寄存器中。常用格式:
LDR R0, =SystemInit
BLX:跳转到由寄存器给出的地址,并根据寄存器的LSE确定处理器的状态,还要把跳转前的下条指令地址保存到LR。常用格式:
BLX R0
BX:跳转到由寄存器/标号给出的地址,不用返回。常用格式:
BX R0
IMPORT:声明标号来自外部文件,和C语言中的extern关键字类似。
IMPORT SystemInit
IMPORT __main
上述代码中表示声明SystemInit和main为外部文件,所以 在创建寄存器模板的时候写一个SystemInit()空函数。如果想修改main.c文件中的main函数名,在这个地方就可以改动,然后后面
LDR R0, =__main
中的main也需要改动,对汇编不了解的不建议改动。
B:跳转到一个标号。常用格式如下:
B .
在B后面有一个“.”,在汇编语言中表示循环。这句话的意思就是说跳进了循环。
IF,ELSE,ENDIF:汇编条件分支语句,与C语言的if else类似。其常用格式:
IF :DEF:__MICROLIB
EXPORT __initial_sp
EXPORT __heap_base
EXPORT __heap_limit
ELSE
IMPORT __use_two_region_memory
EXPORT __user_initial_stackheap
ENDIF
END:到达文件的末尾,文件结束。
到这里启动文件指令就介绍完了, 有的朋友在学习过程中还会遇到其他的汇编指令,那么怎么查找它们的功能和用法呢?其实很简单,KEIL5软件内已经给我们提供了帮组文档,打开Help选项就会弹出帮助文档,如下图所示。
帮助文档的界面如下图所示,如果要查找AREA指令,只需要选择搜索,输入要搜索的指令,选择列出主题即可。选择对应的指令,右侧就会显示指令的具体介绍和格式说明。
堆栈
学习过C语言的朋友对堆栈这一词很熟悉。在启动文件开始处就定义了一堆栈的大小,代码如下:
;栈空间的开辟
Stack_Size EQU 0x00000400
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp ;栈的结束地址
;堆空间的开辟
Heap_Size EQU 0x00000200
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base
Heap_Mem SPACE Heap_Size
__heap_limit ;堆的结束地址
在程序开头开辟了一个0x00000400即1KB的Stack_Size栈空间。 栈主要用于存放函数的参数值、局部变量的值等,其操作方式类似于数据结构中的栈。栈的大小不能超过内部RAM的大小。假如开发的程序占用的RAM比较大,局部变量使用的比较多,那么可以在启动文件内修改这个Stack_Size值。
如果程序出现了莫名其妙的错误,并进入了硬fault的时候,你就要考虑下是不是栈不够大,溢出了的问题。通常我们修改最多的还是栈值。
程序紧接着又开辟了一个0x00000200即512字节的Heap_Size堆空间。堆中的内存一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收。分配方式类似于数据结构中的链表。堆和栈生长方式是相反的,堆是由低向高生长的,而栈是由高向低生长的。
STM32入门系列-启动文件介绍的更多相关文章
- STM32入门系列-GPIO概念介绍
GPIO(general purpose intput output)是通用输入输出端口的简称,可以通过软件来控制其输入和输出.STM32 芯片的 GPIO 引脚与外部设备连接起来,从而实现与外部通讯 ...
- STM32入门系列-库目录及文件介绍
已经介绍了过了CMSIS标准,ST公司按照这个标准设计了一套基于STM32F10x的固件库,我们可以直接在ST公司的官网进行下载,现在给大家STM32最新固件库v3.5,在网盘上给大家提供了下载包,链 ...
- STM32入门系列-创建寄存器模板
介绍如何使用 KEIL5 软件创建寄存器模板, 方便之后使用寄存器方式来操作STM32开发板上的LED,让大家创建属于自己的寄存器工程模板. 获取工程模板的基础文件 首先我们在电脑任意位置创建一个文件 ...
- STM32入门系列-STM32最小系统介绍
STM32最小系统组成 单片机最小系统,也就是能够使得单片机正常运行程序,最少需要连接哪些器件.一般来说,STM32最小系统由四部分组成: 电源电路 复位电路 晶振电路 下载电路 STM32单片机由A ...
- STM32入门系列-存储器与寄存器介绍
介绍两部分内容: 什么是存储器映射 什么是寄存器及寄存器映射 为了让大家对存储器与寄存器有一个更清楚的认识,并且为之后使用 C 语言来访问 STM32 寄存器内容打下基础.等明白了如何使用 C 语言封 ...
- STM32入门系列-介绍STM32型号与功用
作为STM32初学者,一般会选择购置一块开发板,因为在开发板上有很多已经集成好的模块,如红外模块.按键模块.LED模块.DAC模块.ADC模块.can模块.485模块.以太网模块.WiFi模块.蜂鸣器 ...
- STM32入门系列-学习STM32要掌握的内容
STM32芯片架构 STM32F103系列芯片的系统架构如下: STM32芯片基于ARM公司的Cortex-M3内核,由ST公司设计生产,内核与总线矩阵之间有I(指令).S(系统).D(数据)三条信号 ...
- STM32入门系列-STM32时钟系统,时钟使能配置函数
之前的推文中说到,当使用一个外设时,必须先使能它的时钟.怎么通过库函数使能时钟呢?如需了解寄存器配置时钟,可以参考<STM32F10x中文参考手册>"复位和时钟控制(RCC)&q ...
- STM32入门系列-STM32时钟系统,时钟初始化配置函数
在前面推文的介绍中,我们知道STM32系统复位后首先进入SystemInit函数进行时钟的设置,然后进入主函数main.那么我们就来看下SystemInit()函数到底做了哪些操作,首先打开我们前面使 ...
随机推荐
- React手稿之State Hooks of Hooks
React Hooks React在16.7.0-alpha.0版本中提到了Hooks的概念,目前还是Proposal阶段. 官方也陈述,接下来的90%的工作会投入到React Hooks中. 从目前 ...
- 【小白学PyTorch】16 TF2读取图片的方法
[新闻]:机器学习炼丹术的粉丝的人工智能交流群已经建立,目前有目标检测.医学图像.NLP等多个学术交流分群和水群唠嗑的总群,欢迎大家加炼丹兄为好友,加入炼丹协会.微信:cyx645016617. 参考 ...
- 拉格朗日乘子法 Lagrange multipliers
- This is Riv3r1and.
总是要弄个博客来搞的嘛.
- Open CV leaning
刚接触Open CV 几个比较好的介绍: OpenCV学习笔记:https://blog.csdn.net/yang_xian521/column/info/opencv-manual/3 OpenC ...
- matlab中imread 从图形文件读取图像
来源:https://ww2.mathworks.cn/help/matlab/ref/imread.html?searchHighlight=imread&s_tid=doc_srchtit ...
- 每日一题 LeetCode 486. 预测赢家 【递推】【前缀和】【动态规划】
题目链接 https://leetcode-cn.com/problems/predict-the-winner/ 题目说明 题解 主要方法:递推:动态规划:前缀和 解释说明: 求前缀和 pre_nu ...
- Redis 的完整安装过程
Windos 版本安装 Redis 官方并不支持 Window 版本,但是微软公司在 Github 上维护了一个 Windows 版本的 Redis 项目,供 Windows 用户下载使用. 下载地址 ...
- 题解:洛谷P1357 花园
题解:洛谷P1357 花园 Description 小 L 有一座环形花园,沿花园的顺时针方向,他把各个花圃编号为 \(1∼n\).花园 \(1\) 和 \(n\) 是相邻的. 他的环形花园每天都会换 ...
- WebFlux快速上手
一.新建项目 示例使用IDEA快速创建基于SpringBoot的工程. springboot 2.3.1 java 8 WebFlux 必须选用Reactive的库 POM 依赖 <depend ...