STM32启动文件执行步骤分析

发布者:Qingliu2022最新更新时间:2021-12-14 来源: eefocus关键字:STM32  启动文件  执行步骤 手机看文章 扫描二维码
随时随地手机看文章

一、启动文件简介

启动文件由汇编编写,是系统上电复位后第一个执行的程序。主要做了以下工作:

1、初始化堆栈指针 SP=_initial_sp

2、初始化 PC 指针=Reset_Handler

3、初始化中断向量表

4、配置系统时钟

5、调用 C 库函数_main 初始化用户堆栈,从而最终调用 main 函数去到 C 的世界


二、启动文件代码讲解

1.Stack—栈

1 Stack_Size EQU 0x00000400

2

3 AREA STACK, NOINIT, READWRITE, ALIGN=3

4 Stack_Mem SPACE Stack_Size

5 __initial_sp


开辟栈的大小为 0X00000400(1KB),名字为 STACK,NOINIT 即不初始化,可读可写,8(2^3)字节对齐。


栈的作用是用于局部变量,函数调用,函数形参等的开销,栈的大小不能超过内部SRAM 的大小。


EQU:宏定义的伪指令,相当于等于,类似与 C 中的 define。

AREA:告诉汇编器汇编一个新的代码段或者数据段。STACK 表示段名,这个可以任

意命名;NOINIT表示不初始化;READWRITE表示可读可写,ALIGN=3,表示按照 2^3对齐,即 8 字节对齐。


SPACE:用于分配一定大小的内存空间,单位为字节。这里指定大小等于 Stack_Size。

标号__initial_sp紧挨着 SPACE语句放置,表示栈的结束地址,即栈顶地址,栈是由高

向低生长的。


2. Heap 堆

1 Heap_Size EQU 0x00000200

2

3 AREA HEAP, NOINIT, READWRITE, ALIGN=3

4 __heap_base

5 Heap_Mem SPACE Heap_Size

6 __heap_limit

PRESERVE8

THUMB


开辟堆的大小为 0X00000200(512 字节),名字为 HEAP,NOINIT 即不初始化,可读可写,8(2^3)字节对齐。


堆主要用来动态内存的分配,像 malloc()函数申请的内存就在堆上面。这个在 STM32里面用的比较少。


PRESERVE8:指定当前文件的堆栈按照 8 字节对齐。

THUMB:表示后面指令兼容 THUMB 指令。


3. 向量表

1 AREA RESET, DATA, READONLY

2 EXPORT __Vectors

3 EXPORT __Vectors_End

4 EXPORT __Vectors_Size


定义一个数据段,名字为 RESET,可读。


当内核响应了一个发生的异常后,对应的异常服务例程(ESR)就会执行。为了决定 ESR的入口地址, 内核使用了“向量表查表机制”。


EXPORT:声明一个标号可被外部的文件使用,使标号具有全局属性。如果是 IAR 编译器,则使用的是 GLOBAL 这个指令。


4. 复位程序

1 AREA |.text|, CODE, READONLY


定义一个名称为.text 的代码段,可读。


1 Reset_Handler PROC

2 EXPORT Reset_Handler [WEAK]

3 IMPORT SystemInit

4 IMPORT __main

5

6 LDR R0, =SystemInit

7 BLX R0

8 LDR R0, =__main

9 BX R0

10 ENDP


复位子程序是系统上电后第一个执行的程序,调用 SystemInit 函数初始化系统时钟,然后调用 C 库函数_mian,最终调用 main 函数去到 C 的世界。


WEAK:表示弱定义,如果外部文件优先定义了该标号则首先引用该标号,如果外部文件没有声明也不会出错。


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


SystemInit()是一个标准的库函数,在 system_stm32f10x.c这个库文件总定义。主要作用是配置系统时钟,这里调用这个函数之后,单片机的系统时钟配被配置为 72M。


__main 是一个标准的 C 库函数,主要作用是初始化用户堆栈,并在函数的最后调用main 函数去到 C 的世界。这就是为什么我们写的程序都有一个 main 函数的原因。


5. 中断服务程序

在启动文件里面已经帮我们写好所有中断的中断服务函数,跟我们平时写的中断服务函数不一样的就是这些函数都是空的,真正的中断复服务程序需要我们在外部的 C 文件里面重新实现,这里只是提前占了一个位置而已。


1 NMI_Handler PROC ;系统异常

2 EXPORT NMI_Handler [WEAK]

3 B .

4 ENDP

5

18 LTDC_IRQHandler

19 LTDC_ER_IRQHandler

20 DMA2D_IRQHandler

21 B .


B:跳转到一个标号。这里跳转到一个‘.’,即表示无线循环。


6. 用户堆栈初始化

1 ALIGN


ALIGN:对指令或者数据存放的地址进行对齐,后面会跟一个立即数。缺省表示 4 字节对齐。


1 ;用户栈和堆初始化,由 C 库函数_main 来完成

2 IF :DEF:__MICROLIB ;这个宏在 KEIL 里面开启

3

4 EXPORT __initial_sp

5 EXPORT __heap_base

6 EXPORT __heap_limit

7


首先判断是否定义了__MICROLIB ,如果定义了这个宏则赋予标号__initial_sp(栈顶地址)、__heap_base(堆起始地址)、__heap_limit(堆结束地址)全局属性,可供外部文件调用。然后堆栈的初始化就由 C 库函数_main 来完成。


一、收获

1.栈溢出

如果编写的程序比较大,定义的局部变量很多,那么就需要修改栈的大小。如果某一天,你写的程序出现了莫名奇怪的错误,并进入了硬 fault 的时候,这时你就要考虑下是不是栈不够大,溢出了。

关键字:STM32  启动文件  执行步骤 引用地址:STM32启动文件执行步骤分析

上一篇:STM32系统时钟RCC工作流程详解+配置函数中文注释+使用HSE代码
下一篇:STM32位带操作实现GPIO输入输出

推荐阅读最新更新时间:2024-11-19 21:48

演示STM32中PWM的配置与应用
打开CubeMX软件,新建工程。 输入芯片型号。 根据封装选择列表中的芯片,我的是LQFP144封装,双击此项。 在Project Manager选项卡中,配置工程名、编译工具,如下图所示。 在Pinout&Configuration选项卡中,配置System的Debug为Serial Wire,否则可能无法下载程序。 RCC选择高速外部时钟。 根据电路原理图,可知LED7对应PC6管脚。 本实验要让PC6管脚输出PWM波形,实现LED7呼吸灯效果。 找到PC6,选中TIM3_CH1。 找到TIM3,通道1配置PWM输出。 查找STM32参考手册时钟图,找到TIM3时钟的位置在APB1上。
[单片机]
演示<font color='red'>STM32</font>中PWM的配置与应用
深度解析链表在STM32中的应用
1、为何引入链表 在程序中经常面临一个问题,我们需要保存一定数量的对象,但是对象数目是不确定的,或者说是随时增加或减少的。这时候最简单的方法是创建一个足够大的数组,用来存储这些对象。我最近开发一个项目就遇到类似的问题,下面我把问题简化一下。 需求:通过PC下发一些矩形的坐标和宽高信息,每个区域有个ID编号,并在这些矩形内填充一定的数据。 通常情况下,最简单易懂的做法是,限制最多5个区域,每个区域存储1K数据。因此设置了这样的一个结构体(类似于面向对象语言里说的成员属性)。 typedef struct Area_Inf{ uint8_t ID; uint8_t X; uint8_t Y; uint8_t Width; uint
[单片机]
深度解析链表在<font color='red'>STM32</font>中的应用
stm32专题十八:stm32读写SPI FLASH
直接上代码: bsp_spi_flash.c /** ****************************************************************************** * @file bsp_spi_flash.c * @author STMicroelectronics * @version V1.0 * @date 2019 * @brief SPI FLASH(W25Q64)应用函数bsp ****************************************************************************** */
[单片机]
STM32程序编写基本流程(LED流水灯)
LED流水灯程序初始化流程 //1.定义结构体变量 GPIO_InitTypeDef GPIO_InitStructure; //2.开启GPIOC的外部时钟,不同的外设开启不同的时钟,IO口复用时两个时钟都要开启。stmf10x_rcc.h RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE); //3.设置要控制的GPIO管脚 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; //4.设置管脚模式,推挽输出 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_
[单片机]
STM32 输入捕获功能
01、STM32捕获功能 从STM32的定时器框图中看 ①部分基础定时器模块,已经在《 STM32基础定时器详解 》讲解过了。 ②部分捕获/对比通道模块,已经在《 定时器的PWM功能 》讲解过了。 ③部分是本文的重点,输入捕获模块。 从上图可以看出定时器1共有4个输入捕获通道。 下文以定时器1的捕获通道2为例讲解。 首先确定下对应的GPIO,从STM32F207数据手册的Alternatefunction mapping看出,定时器1通道2对应的GPIO有PA9和PE11,下文将使用PE11。 02、输入捕获过程 输入阶段采样对应的对输入TIx,去产生滤波后的信号TIxF。然后极性选择边沿检测器产生一个信号(TIx
[单片机]
<font color='red'>STM32</font> 输入捕获功能
STM32 CAN 通讯 标示符过滤器设置
简介:最近看了下STM32 CAN 通讯其中标示符过滤器设置大有讲究。特别是你要使用ST库函数时,当过滤器工作在屏蔽模式下,并且你把屏蔽位设了1也就是标示符对应位必须全部匹配才能通过,这是由其要小心。 举个例子吧,过滤器长度为32位,模式为屏蔽模式,假如我要发送的标示符为0x1314;那过滤器设置如下 一、过滤器完全无效 接收到的标示符全部通过 0x1314 二进制码: 0000 0000 0000 0000 0001 0011 0001 0100 CAN_Filter xxxx xxxx xxxxxxxx xxxx xxxx xxxx xxxx CAN_FilterMask 0000 0000 0000 00
[单片机]
stm32之ADC应用实例(单通道、多通道、基于DMA)
硬件:STM32F103VCT6 开发工具:Keil uVision4 下载调试工具:ARM仿真器 网上资料很多,这里做一个详细的整合。(也不是很详细,但很通俗)。 所用的芯片内嵌3个12位的模拟/数字转换器(ADC),每个ADC共用多达16个外部通道,2个内部通道。 3个:代表ADC1、ADC2、ADC3(下图是芯片固件库的截图) 12位:也叫ADC分辨率、采样精度。先来看看二进制的12位可表示0-4095个数,也就是说转换器通过采集转换所得到的最大值是4095,如:“111111111111”=4095,那么我们怎么通过转换器转换出来的值得到实际的电压值呢?如果我们要转换的电压范围是0v-3.3v的话,转换器就会把0v
[单片机]
<font color='red'>stm32</font>之ADC应用实例(单通道、多通道、基于DMA)
ARM学习《六》——从头文件开始自己动手设置STM32串口通讯
运用STM32的库函数时,有时候为了看懂一句语句需要翻遍整个头文件,找到头文件中预定义的名字到底代表的是什么意思,具体寄存器设置的数值是多少,相当麻烦。我花了一天的时间才明白串口设置的具体过程,只是库函数想的比较周全。下面是我调试好的串口设置程序,头文件是我自己定义的,舍去了库文件中繁琐的结构体定义 首先定义头文件: / RCC_CFGR &= (uint32_t)0xF8FF0000; RCC_CR &= (uint32_t)0xFEF6FFFF; // RCC_CR &= (uint32_t)0xFFFBFFFF; // RCC_CFGR &= (uint32_t)0
[单片机]
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
更多每日新闻

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved