第48章 MDK的编译过程及文件类型全解—零死角玩转STM32-F429

2019-09-19来源: eefocus关键字:MDK  编译过程  文件类型  STM32-F429系列

本章参考资料:MDK的帮助手册《ARM Development Tools》,点击MDK界面的"help->uVision Help"菜单可打开该文件。关于ELF文件格式,参考配套资料里的《ELF文件格式》文件。


在本章中讲解了非常多的文件类型,学习时请跟着教程的节奏,打开实际工程中的文件来了解。


相信您已经非常熟练地使用MDK创建应用程序了,平时使用MDK编写源代码,然后编译生成机器码,再把机器码下载到STM32芯片上运行,但是这个编译、下载的过程MDK究竟做了什么工作?它编译后生成的各种文件又有什么作用?本章节将对这些过程进行讲解,了解编译及下载过程有助于理解芯片的工作原理,这些知识对制作IAP(bootloader)以及读写控制器内部FLASH的应用时非常重要。


48.1 编译过程

48.1.1 编译过程简介

首先我们简单了解下MDK的编译过程,它与其它编译器的工作过程是类似的,该过程见图 481。

图 481 MDK编译过程    


编译过程生成的不同文件将在后面的小节详细说明,此处先抓住主要流程来理解。


(1)    编译,MDK软件使用的编译器是armcc和armasm,它们根据每个c/c++和汇编源文件编译成对应的以".o"为后缀名的对象文件(Object Code,也称目标文件),其内容主要是从源文件编译得到的机器码,包含了代码、数据以及调试使用的信息;


(2)    链接,链接器armlink把各个.o文件及库文件链接成一个映像文件".axf"或".elf";


(3)    格式转换,一般来说Windows或Linux系统使用链接器直接生成可执行映像文件elf后,内核根据该文件的信息加载后,就可以运行程序了,但在单片机平台上,需要把该文件的内容加载到芯片上,所以还需要对链接器生成的elf映像文件利用格式转换器fromelf转换成".bin"或".hex"文件,交给下载器下载到芯片的FLASH或ROM中。


48.1.2 具体工程中的编译过程

下面我们打开"多彩流水灯"的工程,以它为例进行讲解,其它工程的编译过程也是一样的,只是文件有差异。打开工程后,点击MDK的"rebuild"按钮,它会重新构建整个工程,构建的过程会在MDK下方的"Build Output"窗口输出提示信息,见图 482。


图 482 编译工程时的编译提示


构建工程的提示输出主要分6个部分,说明如下:


(1)    提示信息的第一部分说明构建过程调用的编译器。图中的编译器名字是"V5.06(build 20)",后面附带了该编译器所在的文件夹。在电脑上打开该路径,可看到该编译器包含图 483中的各个编译工具,如armar、armasm、armcc、armlink及fromelf,后面四个工具已在图 481中已讲解,而armar是用于把.o文件打包成lib文件的。

图 483 编译工具


(2)    使用armasm编译汇编文件。图中列出了编译startup启动文件时的提示,编译后每个汇编源文件都对应有一个独立的.o文件。


(3)    使用armcc编译c/c++文件。图中列出了工程中所有的c/c++文件的提示,同样地,编译后每个c/c++源文件都对应有一个独立的.o文件。


(4)    使用armlink链接对象文件,根据程序的调用把各个.o文件的内容链接起来,最后生成程序的axf映像文件,并附带程序各个域大小的说明,包括Code、RO-data、RW-data及ZI-data的大小。


(5)    使用fromelf生成下载格式文件,它根据axf映像文件转化成hex文件,并列出编译过程出现的错误(Error)和警告(Warning)数量。


(6)    最后一段提示给出了整个构建过程消耗的时间。


构建完成后,可在工程的"Output"及"Listing"目录下找到由以上过程生成的各种文件,见图 484。

图 484 编译后Output及Listing文件夹中的内容


可以看到,每个C源文件都对应生成了.o、.d及.crf后缀的文件,还有一些额外的.dep、.hex、.axf、.htm、.lnp、.sct、.lst及.map文件。


48.2 程序的组成、存储与运行

48.2.1 CODE、RO、RW、ZI Data域及堆栈空间

在工程的编译提示输出信息中有一个语句"Program Size:Code=xx RO-data=xx RW-data=xx ZI-data=xx",它说明了程序各个域的大小,编译后,应用程序中所有具有同一性质的数据(包括代码)被归到一个域,程序在存储或运行的时候,不同的域会呈现不同的状态,这些域的意义如下:


    Code:即代码域,它指的是编译器生成的机器指令,这些内容被存储到ROM区。


    RO-data:Read Only data,即只读数据域,它指程序中用到的只读数据,这些数据被存储在ROM区,因而程序不能修改其内容。例如C语言中const关键字定义的变量就是典型的RO-data。


    RW-data:Read Write data,即可读写数据域,它指初始化为"非0值"的可读写数据,程序刚运行时,这些数据具有非0的初始值,且运行的时候它们会常驻在RAM区,因而应用程序可以修改其内容。例如C语言中使用定义的全局变量,且定义时赋予"非0值"给该变量进行初始化。


    ZI-data:Zero Initialie data,即0初始化数据,它指初始化为"0值"的可读写数据域,它与RW-data的区别是程序刚运行时这些数据初始值全都为0,而后续运行过程与RW-data的性质一样,它们也常驻在RAM区,因而应用程序可以更改其内容。例如C语言中使用定义的全局变量,且定义时赋予"0值"给该变量进行初始化(若定义该变量时没有赋予初始值,编译器会把它当ZI-data来对待,初始化为0);


    ZI-data的栈空间(Stack)及堆空间(Heap):在C语言中,函数内部定义的局部变量属于栈空间,进入函数的时候从向栈空间申请内存给局部变量,退出时释放局部变量,归还内存空间。而使用malloc动态分配的变量属于堆空间。在程序中的栈空间和堆空间都是属于ZI-data区域的,这些空间都会被初始值化为0值。编译器给出的ZI-data占用的空间值中包含了堆栈的大小(经实际测试,若程序中完全没有使用malloc动态申请堆空间,编译器会优化,不把堆空间计算在内)。


综上所述,以程序的组成构件为例,它们所属的区域类别见表 481。


表 481 程序组件所属的区域

image.png

48.2.2 程序的存储与运行

RW-data和ZI-data它们仅仅是初始值不一样而已,为什么编译器非要把它们区分开?这就涉及到程序的存储状态了,应用程序具有静止状态和运行状态。静止态的程序被存储在非易失存储器中,如STM32的内部FLASH,因而系统掉电后也能正常保存。但是当程序在运行状态的时候,程序常常需要修改一些暂存数据,由于运行速度的要求,这些数据往往存放在内存中(RAM),掉电后这些数据会丢失。因此,程序在静止与运行的时候它在存储器中的表现是不一样的,见图 485。

图 485 应用程序的加载视图与执行视图


图中的左侧是应用程序的存储状态,右侧是运行状态,而上方是RAM存储器区域,下方是ROM存储器区域。


程序在存储状态时,RO节(RO section)及RW节都被保存在ROM区。当程序开始运行时,内核直接从ROM中读取代码,并且在执行主体代码前,会先执行一段加载代码,它把RW节数据从ROM复制到RAM,并且在RAM加入ZI节,ZI节的数据都被初始化为0。加载完后RAM区准备完毕,正式开始执行主体程序。


编译生成的RW-data的数据属于图中的RW节,ZI-data的数据属于图中的ZI节。是否需要掉电保存,这就是把RW-data与ZI-data区别开来的原因,因为在RAM创建数据的时候,默认值为0,但如果有的数据要求初值非0,那就需要使用ROM记录该初始值,运行时再复制到RAM。


STM32的RO区域不需要加载到SRAM,内核直接从FLASH读取指令运行。计算机系统的应用程序运行过程很类似,不过计算机系统的程序在存储状态时位于硬盘,执行的时候甚至会把上述的RO区域(代码、只读数据)加载到内存,加快运行速度,还有虚拟内存管理单元(MMU)辅助加载数据,使得可以运行比物理内存还大的应用程序。而STM32没有MMU,所以无法支持Linux和Windows系统。


当程序存储到STM32芯片的内部FLASH时(即ROM区),它占用的空间是Code、RO-data及RW-data的总和,所以如果这些内容比STM32芯片的FLASH空间大,程序就无法被正常保存了。当程序在执行的时候,需要占用内部SRAM空间(即RAM区),占用的空间包括RW-data和ZI-data。应用程序在各个状态时各区域的组成见表 482。


表 482 程序状态区域的组成

image.png

在MDK中,我们建立的工程一般会选择芯片型号,选择后就有确定的FLASH及SRAM大小,若代码超出了芯片的存储器的极限,编译器会提示错误,这时就需要裁剪程序了,裁剪时可针对超出的区域来优化。


48.3 编译工具链

在前面编译过程中,MDK调用了各种编译工具,平时我们直接配置MDK,不需要学习如何使用它们,但了解它们是非常有好处的。例如,若希望使用MDK编译生成bin文件的,需要在MDK中输入指令控制fromelf工具;在本章后面讲解AXF及O文件的时候,需要利用fromelf工具查看其文件信息,这都是无法直接通过MDK做到的。关于这些工具链的说明,在MDK的帮助手册《ARM Development Tools》都有详细讲解,点击MDK界面的"help->uVision Help"菜单可打开该文件。


48.3.1 设置环境变量

调用这些

[1] [2] [3] [4] [5] [6] [7] [8] [9] [10] ..[12]
关键字:MDK  编译过程  文件类型  STM32-F429系列 编辑:什么鱼 引用地址:http://news.eeworld.com.cn/mcu/ic475055.html 本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。

上一篇:第47章 QR-Decoder-OV5640二维码识别—零死角玩转STM32-F429系列
下一篇:第49章 在SRAM中调试代码—零死角玩转STM32-F429系列

关注eeworld公众号 快捷获取更多信息
关注eeworld公众号
快捷获取更多信息
关注eeworld服务号 享受更多官方福利
关注eeworld服务号
享受更多官方福利

推荐阅读

STM32 KEIL MDK 本地时间和Unix timestamp相互转换
p  gm_date->tm_year=118;//2018年,+1900就是现在的年 gm_date->tm_mon=3;//4月 gm_date->tm_mday=11; gm_date->tm_hour=10; gm_date->tm_min=8; gm_date->tm_sec=30; seconds=mktime(gm_date); printf("unix timestamp:%08x rn",seconds); //unix timestamp:5acdde9e  //北京时间: 2018/4/11 18:8:30 }
发表于 2019-10-09
MDK V5.12 + ST-Link V2 + Win10 STM32开发环境搭建1
养成每天写笔记的习惯,很多知识,时间一长就忘记了。以前都是用Jlink来仿真调试STM32,现在找不到Jlink去哪里了,可能留在了前公司。然后了解到ST-Link很便宜,就果断在淘宝上了化了不到20买了一个回来。环境:操作系统:Win10 64位IDE:keil MDK uVision V5.12仿真下载器:ST-Link V2  注:开始的时候使用keil MDK V4.0 的版本,好像对ST-Link V2的支持不好,然后就用了MDK V5.12 。 自己有个Jlink-V7是盗版的,MDK5.12 会识别到JLink-V7,直接闪退,MDK V4.0 倒是没有问题。 1:ST-Link V2
发表于 2019-10-08
MDK V5.12 + ST-Link V2 + Win10 STM32开发环境搭建1
课程设计题八:篮球比赛计分器
;      http://www.51hei.com/bbs/mcu-2-1.html---------------------------------------------------------------------------------【dev.env.】MDK4.02及以上版本【Target  】STC89C51第一次修订:2019/05/09第二次修订:2019/05/21第三次修订:2019/06/10【problem 】    (1)库内补充的不全面;    (2)库内解释部分不全面;    (3)库内还存在一定的bug
发表于 2019-09-29
课程设计题八:篮球比赛计分器
STM32在MDK下的一种通用建立库函数工程的方法(标准库)
物料准备MDK4或者(MDK5+Legacy支持包)ST官方下载的库文件(STM32F10x_StdPeriph_Lib_V3.5.0)下载地址 http://pan.baidu.com/s/1cyxwXS库函数主要文件夹简介需要的用的库文件都在STM32F10x_StdPeriph_Lib_V3.5.0Libraries文件夹下,它又包含了以下两个文件夹 CMSIS(一些核心和库文件代码,CMSIS主要代码) CM3DeviceSupportSTSTM32F10x文件夹 system_stm32f10x.c(STM32F10x CMSIS Cortex-M3设备访问层的系统源
发表于 2019-09-28
STM32在MDK下的一种通用建立库函数工程的方法(标准库)
STM32开发环境(MDK)搭建及第一个项目工程
一、开发环境搭建1.1 下载IDE目前STM32开发常用的IDE有IAR、MDK等,这里我挑选MDK。如果你是IAR的爱好者,那么这篇文章可能不适合你。MDK官方下载地址,目前最新版本是5.26。 官网下载页面入口:下载需要填写个人信息:点击下载即可:从官网下载会比较慢,为了方便大家下载,有需要的同学可以到我的网盘上获取。1.2 IDE安装可以配置安装路径。默认安装在C盘根目录下。填写用户信息。随便写,不影响使用。一路Next,最后点击Finish。弹出一个包安装的界面。如果你要开发的芯片MDK不支持,需要通过这个Pack Installer去安装相应的包,这里先关闭忽略掉。到此,MDK已经安装完成,在桌面上出现了快捷键。点击运行
发表于 2019-09-28
STM32开发环境(MDK)搭建及第一个项目工程
STM32工程模板简单套用教程(Keil MDK)
在Mdk配置stm32工程是一件很麻烦的事情,故直接套用工程模板,减少时间花费。(此处用野火的m3工程模板)模板的配置是根据相对路径的,所以模板可以随意复制到任意一个地方。1.文件夹改名,这里我改为shuoGG_project,打开工程(在USER里),改改output名和文件名什么的,当然不改也没什么影响;2.选型换一换,这个模板默认是stm32f103ve的;3.个人习惯:把stm32f10x_conf.h和stm32f10x_it.h加到USER文件夹方便修改;4.用串口烧写的记得勾上create hex;5.在stm32f10x_conf.h注释掉用不到的外设,可以减少一点编译时间,但是外设c文件依旧会编译,所以只是省了
发表于 2019-09-27
STM32工程模板简单套用教程(Keil MDK)
小广播
何立民专栏 单片机及嵌入式宝典

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

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