当前位置:首页 > 公众号精选 > strongerHuang
[导读]关注星标公众号,不错过精彩内容转自|茶话MCU基于STM32芯片的工程代码里有个很重要的文件,即启动文件。该文件主要由汇编语言写成,文件名冠以.s结尾,它是芯片程序运行首先要执行的一个文件。其功能及作用简单点说就是做执行用户程序前的基本准备,比方执行复位程序初始化栈、堆,做时钟系...


转自 | 茶话MCU



基于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文件时,发现启动文件就用掉了1024BRAM,如下图所示。觉得有点奇怪,想知道这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禁用掉;保证跳转时清清爽爽,不捎一滴水,不带一片云。
------------ END ------------





本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

串口作为单片机开发的一个常用的外设,应用范围非常广。大部分时候,串口需要接收处理的数据长度是不定的。那么怎么才能判断一帧数据是否结束呢,今天就以STM32单片机为例,介绍几种接收不定长数据的方法。

关键字: 单片机 串口 STM32

脉冲宽度调制(PWM) 是一种数字信号,最常用于控制电路。该信号在预定义的时间和速度中设置为高(5v或3.3v)和低(0v)。通常,我们将PWM的高电平称为1,低电平为0。

关键字: STM32 PWM 控制

摘要:随着计算机技术与电子科技的快速发展,人工智能、云计算等技术的不断进步,智能家居新型产业模式也得到了巨大的发展,至今国内智能家居市场投资达到了2396亿元,市场规模占比不断增大,未来十年内家居智能化将实现大规模应用。...

关键字: STM32 嵌入式 人工智能

​GD32作为国产MCU里的佼佼者,产品线也比较丰富,是替代STM32的一个很好的选择。前段时间有个项目用到GD32的单片机,今天来说说使用的一些体会。

关键字: 国产MCU STM32 单片机

STM32 用户界面设计环境新增屏幕旋转和纹理映射功能,支持性能强大的Neochrom图形加速器

关键字: 意法半导体 STM32 MCU

意法半导体(ST)发布了STM32Cube.AIversion7.2.0,这是微控制器厂商推出的首款支持超高效深度量化神经网络的人工智能(AI)开发工具。

关键字: 意法半导体 STM32

2022年是意法半导体STM32家族问世15周年。在全球疫情阻止人们面对面沟通交流的当下,7月18-22日,意法半导体举办首届暨2022年STM32中国线上技术周,庆祝与生态合作伙伴共同创新的十五载。 在这个为期五天的线...

关键字: 意法半导体 STM32

展示与STM32生态伙伴的十五年创新成就

关键字: 意法半导体 STM32

摘要:根据四旋翼飞行器工作原理,以STM32控制器为基础,对四旋翼飞行器飞行控制系统的软硬件设计进行了分析,可有效调整四旋翼飞行器飞行姿态与飞行位置,实现了控制模块与地面站的有效联系。

关键字: STM32 控制系统 软件设计

摘要:研究一类基于STM32的数据采集系统,采集并储存有轨电车车载超级电容的电压/电流数值。首先介绍该数据采集系统中硬件部分的各个功能区域,随后设计了数据采集系统的软件部分,编写了ADC采集的程序并通过GPRS4G无线通...

关键字: STM32 数据采集系统 寿命预测

strongerHuang

689 篇文章

关注

发布文章

编辑精选

技术子站

关闭