【STM32】MDK的编译过程及文件类型全解

1.编译过程简介

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中。

MDK常见的文件类型

2.编译工具链

2.1环境变量

我们下载arm编译工具后,需要将目录添加到环境变了中。

在这里插入图片描述

  • armcc用于把c/c++文件编译成ARM指令代码,编译后会输出ELF格式的O文件(对象、目标文件)。
  • armasm是汇编器,它把汇编文件编译成O文件。
  • armlink是链接器,它把各个O文件链接组合在一起生成ELF格式的AXF文件,AXF文件是可执行的,下载器把该文件中的指令代码下载到芯片后, 该芯片就能运行程序了;利用armlink还可以控制程序存储到指定的ROM或RAM地址。
  • armar工具用于把工程打包成库文件。
  • fromelf可根据axf文件生成hex、bin文件,hex和bin文件是大多数下载器支持的下载文件格式。
2.2使用fromelf工具生成bin文件
  • HEX文件:这是一种ASCII编码的文件格式,它包含了以特定ASCII字符表示的十六进制数据。HEX文件通常较大,因为它们使用两个ASCII字符来表示一个字节的数据,并且包含了文件头、记录类型、地址字段等额外信息。
  • BIN文件:这是一种二进制文件格式,只包含实际的二进制数据,没有额外的文本信息。BIN文件通常比HEX文件小,因为它们不包含任何ASCII编码的开销。
fromelf --bin --output ..\Output\F407_Demo.bin ..\Output\F407_Demo.axf

在这里插入图片描述

Build started: Project: F407_Demo
*** Using Compiler 'V5.06 update 7 (build 960)', folder: 'D:\Keil_v5\ARM\ARM_Compiler_5.06u7\Bin'
Build target 'F407_Demo'
After Build - User command #1: fromelf --bin --output ..\Output\F407_Demo.bin ..\Output\F407_Demo.axf
"..\Output\F407_Demo.axf" - 0 Error(s), 0 Warning(s).
Build Time Elapsed:  00:00:01

在这里插入图片描述

3.程序的组成、存储与运行

3.1CODE、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动态申请堆空间, 编译器会优化,不把堆空间计算在内)。
3.2程序的存储与运行

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

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

图中的左侧是应用程序的存储状态,右侧是运行状态,而上方是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读取指令运行。

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

程序状态区域的组成

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

3.3配置RAM和ROM大小

STM32F407ZGT6微控制器的SRAM和Flash大小如下:

  • Flash:STM32F407ZGT6拥有最大1MB(1024KB)的Flash存储空间,用于存储程序代码和只读数据。Flash的地址范围从0x8000000开始。
  • SRAM:该微控制器具备总共192KB的SRAM,其中包括:
    • 112KB的主SRAM(SRAM1),地址从0x20000000开始,大小为0x20000即128KB。
    • 64KB的CCM(核心耦合存储器)数据RAM,地址从0x10000000开始,这部分内存仅CPU可以访问,不适用于DMA操作。
    • 备份SRAM,大小为4KB。

此外,STM32F407系列的芯片可以通过FSMC(灵活的静态存储控制器)扩展外部SRAM,例如使用型号为IS62WV51216的SRAM芯片,其容量为1MB(1024KB)。这为需要更多运行时数据存储空间的应用程序提供了扩展选项。

在这里插入图片描述

所以,

  • 程序存储状态时占用的ROM区=Code+RO_data+RW_data不能够超过1024KB。
  • 程序执行时占用RAM区=RW_data+ZI_data不能够超过128KB。

其中ZI_data包括初始值为0的全局变量、局部变量和动态分配的空间,局部变量属于栈空间,动态分配的空间属于堆空间。这两块空间也是可以单独配置的,在启动文件startup_stm32f40xx.s中。

在这里插入图片描述

4.map文件说明

在Listing目录下包含了*.map及*.lst文件,它们都是文本格式的。map文件是由链接器生成的,它主要包含交叉链接信息,查看该文件可以了解工程中各种符号之间的引用以及整个工程的Code、RO-data、 RW-data以及ZI-data的详细及汇总信息。它的内容中主要包含了“节区的跨文件引用”、“删除无用节区”、“符号映像表”、 “存储器映像索引”以及“映像组件大小”。

map文件的最后一部分是包含映像组件大小的信息(Image component sizes),这也是最常查询的内容。

Image component sizesCode (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name140         56        128          0        128       1362   bsp_dma.o60         26          0          0          0        531   bsp_exti.o88         16          0          0          0       1389   bsp_led.o12          4          0          0          0        465   bsp_pwm2.o276         70          0         16          0        962   bsp_timer.o350         32          0         10          0       4498   bsp_usart.o16          0          0          0          0        506   bsp_wwdg.o64         28          0          0          0        531   main.o124         16          0          0          0       1887   misc.o36          8        392          0       1024        952   startup_stm32f40xx.o142         28          0          0          0       3647   stm32f4xx_dma.o32         10          0          0          0       1260   stm32f4xx_exti.o168          0          0          0          0       3286   stm32f4xx_gpio.o20          0          0          0          0       4082   stm32f4xx_it.o216         24          0         16          0       4626   stm32f4xx_rcc.o38          0          0          0          0       3354   stm32f4xx_tim.o308          8          0          0          0       5440   stm32f4xx_usart.o28         10          0          0          0       1107   stm32f4xx_wwdg.o276         34          0          0          0     306193   system_stm32f4xx.o----------------------------------------------------------------------2410        370        552         44       1152     346078   Object Totals0          0         32          0          0          0   (incl. Generated)16          0          0          2          0          0   (incl. Padding)----------------------------------------------------------------------Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Member Name0          0          0          0          0          0   entry.o0          0          0          0          0          0   entry10a.o0          0          0          0          0          0   entry11a.o4          0          0          0          0          0   entry12b.o8          4          0          0          0          0   entry2.o4          0          0          0          0          0   entry5.o0          0          0          0          0          0   entry7b.o0          0          0          0          0          0   entry8b.o8          4          0          0          0          0   entry9a.o30          0          0          0          0          0   handlers.o36          8          0          0          0         68   init.o0          0          0          0          0          0   iusefp.o30          0          0          0          0         68   llshl.o36          0          0          0          0         68   llsshr.o32          0          0          0          0         68   llushr.o26          0          0          0          0         80   memcmp.o2218         90          0          0          0        464   printfa.o0          0          0          4          0          0   stdout.o44          0          0          0          0         80   uidiv.o98          0          0          0          0         92   uldiv.o48          0          0          0          0         68   cdrcmple.o56          0          0          0          0         88   d2f.o334          0          0          0          0        148   dadd.o222          0          0          0          0        100   ddiv.o186          0          0          0          0        176   depilogue.o48          0          0          0          0         68   dfixul.o26          0          0          0          0         76   dfltui.o228          0          0          0          0         96   dmul.o38          0          0          0          0         68   f2d.o110          0          0          0          0        168   fepilogue.o----------------------------------------------------------------------3874        106          0          4          0       2044   Library Totals4          0          0          0          0          0   (incl. Padding)----------------------------------------------------------------------Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Library Name2574        106          0          4          0        988   mc_w.l1296          0          0          0          0       1056   mf_w.l----------------------------------------------------------------------3874        106          0          4          0       2044   Library Totals----------------------------------------------------------------------==============================================================================Code (inc. data)   RO Data    RW Data    ZI Data      Debug   6284        476        552         48       1152     342938   Grand Totals6284        476        552         48       1152     342938   ELF Image Totals6284        476        552         48          0          0   ROM Totals==============================================================================Total RO  Size (Code + RO Data)                 6836 (   6.68kB)Total RW  Size (RW Data + ZI Data)              1200 (   1.17kB)Total ROM Size (Code + RO Data + RW Data)       6884 (   6.72kB)==============================================================================

5.sct分散加载文件

当工程按默认配置构建时,MDK会根据我们选择的芯片型号,获知芯片的内部FLASH及内部SRAM存储器概况, 生成一个以工程名命名的后缀为*.sct的分散加载文件(Linker Control File,scatter loading), 链接器根据该文件的配置分配各个节区地址, 生成分散加载代码,因此我们通过修改该文件可以定制具体节区的存储位置。

在这里插入图片描述

文件内容如下:

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00100000  {    ; load region size_regionER_IROM1 0x08000000 0x00100000  {  ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20000000 0x00020000  {  ; RW data.ANY (+RW +ZI)}RW_IRAM2 0x10000000 0x00010000  {.ANY (+RW +ZI)}
}

我们的sct示例文件配置如下:程序的加载域为内部FLASH的0x08000000,最大空间为0x00100000;程序的执行基地址与加载基地址相同, 其中RESET节区定义的向量表要存储在内部FLASH的首地址,且所有o文件及lib文件的RO属性内容都存储在内部FLASH中; 程序执行时RW及ZI区域都存储在以0x20000000为基地址,大小为0x00020000的空间(128KB),这部分正好是STM32内部主SRAM的大小。

链接器根据sct文件链接,链接后各个节区、符号的具体地址信息可以在map文件中查看。

了解sct文件的格式后,可以手动编辑该文件控制整个工程的分散加载配置,但sct文件格式比较复杂,所以MDK提供了相应的配置选项可以方便地修改该文件, 这些选项配置能满足基本的使用需求,其实就是我们在上文中配置的RAM和ROM大小。

5.1控制文件分配到指定的存储空间

在这里插入图片描述

在弹出的对话框中有一个“Memory Assignment”区域(存储器分配),在该区域中可以针对文件的各种属性内容进行分配, 如Code/Const内容(RO)、Zero Initialized Data内容(ZI-data)以及Other Data内容(RW-data), 点击下拉菜单可以找到在前面Target页面配置的IROM1、IRAM1、IRAM2等存储器。 例如图中我们把这个bsp_led.c文件的OtherData属性的内容分配到了IRAM2存储器(在Target标签页中我们勾选了IRAM1及IRAM2), 当在bsp_led.c文件定义了一些RW-data内容时(如初值非0的全局变量),该变量将会被分配到IRAM2空间,配置完成后点击OK,然后编译工程, 查看到的sct文件。

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************LR_IROM1 0x08000000 0x00100000  {    ; load region size_regionER_IROM1 0x08000000 0x00100000  {  ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO).ANY (+XO)}RW_IRAM1 0x20000000 0x00020000  {  ; RW data.ANY (+RW +ZI)}RW_IRAM2 0x10000000 0x00010000  {bsp_led.o (+RW).ANY (+RW +ZI)}
}

虽然MDK的这些存储器配置选项很方便,但有很多高级的配置还是需要手动编写sct文件实现的, 例如MDK选项中的内部ROM选项最多只可以填充两个选项位置,若想把内部ROM分成多片地址管理就无法实现了; 另外MDK配置可控的最小粒度为文件,若想控制特定的节区也需要直接编辑sct文件。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/43632.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

无线网卡怎么连接台式电脑?让上网更便捷!

随着无线网络的普及,越来越多的台式电脑用户希望通过无线网卡连接到互联网。无线网卡为台式电脑提供了无线连接的便利性,避免了有线网络的束缚。本文将详细介绍无线网卡怎么连接台式电脑的四种方法,包括使用USB无线网卡、内置无线网卡以及使用…

火柴棒图python绘画

使用Python绘制二项分布的概率质量函数(PMF) 在这篇博客中,我们将探讨如何使用Python中的scipy库和matplotlib库来绘制二项分布的概率质量函数(PMF)。二项分布是统计学中常见的离散概率分布,描述了在固定次…

Flask 邮件发送实例(代码直接可用)

关于Flask 邮件发送功能的代码实现,很多文章讲得并不清楚,往往学习视频才能讲清楚,我在这里出一个简单实例,直接告诉你各个配置具体对应的是什么意思以及如何获取。 1、实例 from flask import Flask from flask_mail import Ma…

快速掌握 ==== js 正则表达式

git 地址 https://gitee.com/childe-jia/reg-test.git 背景 在日常开发中,我们经常会遇到使用正则表达式的场景,比如一些常见的表单校验,会让你匹配用户输入的手机号或者身份信息是否规范,这就可以用正则表达式去匹配。相信大多数…

ISO 20000认证:驱动企业IT服务管理变革的利器

在信息技术驱动商业发展的今天,企业对高效、可靠和安全的IT服务需求日益增长。ISO 20000作为国际公认的IT服务管理标准,能够帮助企业在竞争激烈的市场环境中脱颖而出,实现IT服务管理的全面提升。本文将深入探讨ISO 20000认证如何帮助企业优化…

C++第三弹 -- 类与对象(上)

目录 前言一. 面向过程和面向对象的初步认识二. 类的引入三. 类的定义1.定义2. 命名规则建议 四. 类的访问限定符以及封装1. 访问限定符2.面试题3. 封装 五. 类的作用域六. 类的实例化七. 类的对象大小的计算八. 类成员函数this指针1. this指针的引出2. this指针的特性3. C语言…

最新版本的办公工具,你不来尝试一下吗?

前言 大家好,我是小雨,看到最近ONLYOFFICE更新了最新的版本,更新了一下当前版本来具体的测评一下,先来看看官网提供的各类更新信息,下面是我找到的三个主页,包括功能演示链接,官网连接以及专门…

能源电子领域2区SCI,版面稀缺,即将截稿,无版面费!

【SciencePub学术】今天小编给大家推荐1本能源电子领域的SCI!影响因子1.0-2.0之间,最重要的是审稿周期较短,对急投的学者较为友好! 能源电子类SCI 01 / 期刊概况 【期刊简介】IF:1.0-2.0,JCR2区&#xf…

羊大师:探索羊奶奥秘,解锁免疫力提升新篇章

在浩瀚的自然界中,羊奶以其独特的营养价值和健康益处,悄然成为提升免疫力的新宠。自古以来,羊奶就被视为珍贵的滋补佳品,而今,随着科学的深入探索,其提升免疫力的奥秘正逐渐揭开面纱。 羊奶中富含的免疫球蛋…

Avalonia开发实践(二)——开发带边框的Grid

一、开发背景 在实际开发工作中,常常会用到Grid进行布局。为了美观考虑,会给每个格子加上边框,如下图: 原生的Grid虽然有ShowGridLines属性可以控制显示格子之间的线,但线的样式不能定义,可以说此功能非常…

java中 使用数组实现需求小案例(二)

Date: 2024.07.09 16:43:47 author: lijianzhan 需求实现: 设计一个java类,java方法,使用Random函数,根据实现用户输入随机数生成一个打乱的数组。 package com.lin.java.test;import java.util.Arrays; import java.util.Rando…

TAGE predictor

参考文档:分支预测算法(一):TAGE|SunnyChen的小窝 TAGE的基础概念 TAGE是现今最经典的分支预测算法,TAGE及其后续的变体都是当今高性能微处理器的分支预测算法基础。因此,要聊分支预测算法的话题必定绕不开…

uniapp内置组件uni.navigateTo跳转后页面空白问题解决

文章目录 导文空白问题 导文 在h5上跳转正常 但是在小程序里面跳转有问题 无任何报错 页面跳转地址显示正确,但页面内容为空 空白问题 控制台: 问题解决: 方法1: 可能是没有注册的问题,把没注册的页面 注册一下。 方…

数据库基础练习4

准备 create table dept (dept1 int ,dept_name varchar(11)) charsetutf8; create table emp (sid int ,name varchar(11),age int,worktime_start date,incoming int,dept2 int) charsetutf8;insert into dept values(101,财务),(102,销售),(103,IT技术),(104,行政);INSERT …

WANGLS

DHCP 动态主机配置协议 原理 网络 网络是双向的,网络是有方向的 广播;广播是由种类的,广播是有范围的的 租约的建立——租约的相应、租约的选择——租约的完成 租约的建立:租约的请求 有客户端发出 DHCP discover 广播、寻找服务器 租约的响应 收到响应,不是服务器,…

模块一SpringBoot(一)

maven记得配置本地路径和镜像 IJ搭建 SpringIntiallizer--》将https://start.spring.io改成https://start.aliyun.com/ 项目结构 Spring有默认配置, application.properties会覆盖默认信息: 如覆盖端口号server.port8888

提升校园管理效率!智慧校园人事管理的职工培训功能解析

在智慧校园的构建框架下,人事管理系统中关于职工培训的部分,扮演了一个促进师资力量成长与个人职业规划深度融合的角色。这一模块细腻地融合了现代教育的需求与教职工个人发展的期望,为提升教学团队的整体实力铺设了一条高效路径。 首先&…

为什么3d模型在透视里面闪烁?---模大狮模型网

在展览3D模型设计中,透视效果是展示空间深度和立体感的重要手段。然而,有时候我们会面对3D模型在特定透视角度下出现闪烁或者失真的问题。本文将深入探讨这一现象的原因及解决方法,帮助设计师们更好地理解和处理这类挑战。 一、为什么3D模型在…

哪个充电宝口碑比较好?怎么选充电宝?2024年口碑优秀充电宝推荐

在如今快节奏的生活中,充电宝已然成为我们日常生活中的必备品。然而,市场上充电宝品牌众多,质量参差不齐,如何选择一款安全、可靠且口碑优秀的充电宝成为了消费者关注的焦点。安全性能不仅关系到充电宝的使用寿命,更关…

记一次mysql迁移Kingbase8

目录 一、下载Kingbase工具二、客户端安装三、数据库开发管理工具 KStudio3.1 主界面3.2 导出数据库建表语句DDL3.3 导出数据 四、数据迁移工具 KDTS4.1 启动KDTS4.2 新建源数据库4.3 新建目标数据库4.4 迁移任务管理 一、下载Kingbase工具 kingbase数据库服务(内置…