基于STM32芯片的工程代码里有个很重要的文件,即启动文件。该文件主要由汇编语言写成,文件名冠以.s结尾,它是芯片程序运行首先要执行的一个文件。其功能及作用简单点说就是做执行用户程序前的基本准备,比方执行复位程序初始化栈、堆,做时钟系统的默认配置、中断矢量表的定义与分配等。
网络上有些文章对该文件做了不错的整体性介绍,这里仅就该文件中的几个小问题一起交流分享下。【注:下面用到的工程是基于STM32F429的,使用IDE为ARM MDK】
怎么在编译后的MAP文件里看不到变量__heap_base?
有人发现在启动文件里明明有定义__initial_sp和__heap_base,可在MAP文件里只看到__initial_sp的地址安排,却死活找不到__heap_base的影子。为什么呢?
这是因为我们目前的工程代码里没有涉及到堆操作。虽然启动文件里有针对HEAP的配置,但由于代码里实际上没用到堆,编译时候就没分配堆的地址相关信息,自然在MAP文件里找不到__heap_base。
以上图为例,其实此时Heap_Size写多大是没啥实际意义的,写0x200和写0没差别。这就像我们在代码定义一些完全不会被用到的变量一样,编译时是不会被安排内存空间的。
然而,如果我们在代码里有涉及HEAP操作,若启动文件里的HEAP配置依然如上图所示,那情况就不一样了。比方我们在用户代码做动态内存分配,这里使用malloc函数进行动态内存分配示例下。
这时我们再去查看MAP文件,就可看到堆的地址信息了,跟启动文件里分配的一致。顺便提醒下,我们在用户代码里做内存动态分配时注意分配的空间大小要遵循启动文件里预设的HEAP大小限制,必要时需做适当调整。
启动文件里怎么用掉了1KB的RAM?
有人在查看STM32程序代码编译后的MAP文件时,发现启动文件就用掉了1024B的RAM,如下图所示。觉得有点奇怪,想知道这1KB用到哪里去了?是不是固定的?
我们知道启动文件主要基于汇编写成,实现些最基本的软硬件初始化工作,似乎用不到这么多RAM。
其实,这里1KB初始值为0的RAM,是安排给栈用的,而这个栈大小的配置就是在启动文件里实现,但并非仅限于用在启动文件里。MAP文件里显示的启动文件所用ZI数据大小,跟下面栈配置是关联的。
显然,这个RAM开销并非固定的。
尽管我们建立工程时可能有些默认配置或经验配置,但我们完全可以结合自身工程代码的需要灵活调整。如果说,代码里函数调用涉及到的局部变量较少、中断嵌套情形也不多,你完全可以将栈数据设计得小些,或许很多时候512B【0x200】都绰绰有余了。总之,这个数据不是固定不变的,具体开发时按需调整。
比方,我将上面的栈空间大小改为512B,再看看编译后的结果。那个ZI Data大小也随之而变了。
上面是基于栈空间大小的调整来解释启动文件里ZI数据的大小变化。如果说我们的代码里还用到堆,这时启动文件里的ZI数据就不仅仅是栈空间大小的数据了,还会包括堆空间的大小。比方,我们在代码里启用动态内存分配使用到堆。在启动文件里对堆、栈的配置如下:
按照上面配置并启用动态内存分配,再去查看编译结果,基于启动文件所用到的ZI数据大小变成了栈与堆空间二者之和。如下图所示【1024+512=1536】:
启动文件里的RO Data是怎么产生的?
有人在查看MAP文件时,发现启动文件里产生了一批RO只读数据,如下图所示:
上图是基于STM32F429的工程编译后产生的,那个428 Bytes只读数据怎么来的?
其实,这个数据就是存放中断向量地址表所用到的,不同的系列这个数据会有差异。该向量表除了第一个字单元存放MSP栈顶地址外,其它均为系统异常或中断入口地址,作为常量数据存放在FLASH里。我们具体看看这里的428B怎么来的。打开启动文件,我们可以看到一串连续的DCD操作,如下图所示:
以STM32F429为例,在启动文件里稍微数数可得知这里共有107个地址入口项,每项用到一个4字节字,刚好对应上面的428 Bytes.
启动文件里的__main函数跟用户的main()有关系吗?
我们知道,启动文件的主要功能就是为用户程序的正常运行做最基本的初始化准备工作,__main()函数就是完成该使命的重要一环。它是一个C库初始化函数入口,主要负责执行一些必要的代码及数据从装载区到执行区的拷贝,将ZI内存区的数据初始化为0。对C库函数进行初始化,初始化堆、栈等,有时还可能包括一些代码解压操作,最后跳转至用户man()函数运行用户程序。
一般来讲,关于这个__main()函数的功能及作用大致了解就好,通常将其视为黑盒子。
启动文件里对中断矢量表起始地址进行初始化是在哪里实现的?
在STM32 MCU家族里,除了基于Cortex M0内核的STM32F0系列外,都有个中断矢量寄存器【SCB-》VTOR】用来初始化中断矢量表的起始地址。它的初始化一般在启动文件的复位程序里的SystemInit()函数完成。
最后基于该话题顺便给些提醒作为本篇结尾。我们在基于STM32芯片做IAP应用时,对于APP代码记得做好VTOR的重定位【注:F0系列操作例外】;在从BOOT区跳转到APP区之前先将刚才开启过的所有中断使能都禁用掉;如果开启了Cache的话,也将Cache禁用掉;保证跳转时清清爽爽,不捎一滴水,不带一片云。
上一篇:多功能STM32开发工具STM32CubeIDE使用指南
下一篇:详解STM32低功耗模式
推荐阅读最新更新时间:2024-11-12 10:13
设计资源 培训 开发板 精华推荐
- 具有反向电池和太阳能电池板保护的 LTC4367HMS8-1 系列迟滞太阳能充电器的典型应用
- HV7802 高压侧电流监视器 8V 至 450V、可配置输出的典型应用
- Sg3525A稳压脉宽调制器典型应用电路
- 使用 TC7662B 电荷泵作为外部时钟的典型应用电路
- 【常熟理工】A题放大器线性研究
- LTC4162EUFD-FST 9V 至 35V 2 节 3.2A 充电器的典型应用,具有 PowerPath 和 2A 输入限制
- 用于维恩桥振荡器的 LMV821SQ3T2G 单路低电压运算放大器的典型应用电路
- EVAL-CN-304-SDZ,用于评估 AD9834 20 mW 功率、2.3V 至 5.5V、75 MHz 完整 DDS 的评估板
- 采用单端 15V 输入电源的 LTC3265HFE 低功率 ±20V 电源的典型应用电路
- MB39C022J降压DC/DC转换器+低噪声LDO的典型应用
- 齐分享,月月有奖第25期活动华丽升级来袭
- ADI有奖下载活动之12 ADI基于视觉的占用检测解决方案
- 我们猜啦!MDO3000之竞猜有奖:免费的部分会值多少?
- 100%获奖,EE新年福利!
- 下载有礼:2017年泰克亚太专家大讲堂第一期:大数据与云存储环境下的高速总线技术演进
- 【MPS有奖评论】一起聊聊选型的那些过往
- 创新驱动变革,R&S示波器助力功率电子测试
- 邀您共赴一场技术盛宴! 2022英特尔® FPGA中国技术周 ——加速,让创新有迹可循
- 免费领取|价值400元的乐鑫无线屏幕交互开发板ESP32-S3-LCD-EV-BOARD
- MSP430经典资料大搜集!赢给力TI 无线运动手表开发工具!!!