痞子衡嵌入式:MCUXpresso IDE下工程链接文件配置管理与自动生成机制
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家介绍的是MCUXpresso IDE下工程链接文件配置管理与自动生成机制。
痞子衡在 2018 年初写过一个专题 《嵌入式开发文件系列》,用 8 篇文章系统地介绍了 ARM Cortex-M 内核微控制器开发过程中所要了解的主要文件类型:源文件、链接文件、工程文件、可重定向文件、映射文件、可执行文件、反汇编文件、镜像文件。
上述 8 种文件中,大家对源文件、工程文件以及镜像文件这三种应该是最熟悉的,而其余文件类型,很多人应该都没有深入研究过,但痞子衡一直认为只有深入了解了链接文件才算是真正步入嵌入式开发老手行列。
我们知道不同 IDE 下链接文件语法是不一样的,而恩智浦 MCUXpresso IDE 底层编译器是 Arm GCC,因此其链接文件就是标准 GCC 下 .ld 文件。如果你对 .ld 文件语法非常精通,当然可以自己从头开始写链接文件,如果不太熟的话,也不要紧张,MCUXpresso IDE 早就为你扫清了障碍,在这个 IDE 下能够支持图形界面里做链接配置,然后自动生成相应链接文件的。今天痞子衡就和大家聊聊这个特性:
- Note: 在开始今天的主题之前,可以先看一下痞子衡的旧文 《MCUXpresso IDE下SDK工程在Build配置上与IAR,MDK差异》,本篇实际上就是这篇文章的后续。
一、准备开发环境
首先需要准备好环境,包含必要的软件,痞子衡的环境如下:
二、MCUXpresso IDE下链接文件配置
现在进入正题,我们先按照 《MCUXpresso IDE下SDK工程导入与workspace管理机制》 一文步骤从 SDK 包里导入生成一个工程(就选最简单的 hello_world 吧)。工程导入成功后,会在 \MCUXpressoIDE_11.4.0_6224\workspace\evkmimxrt1170_hello_world_demo_cm7 下看到 .project 工程文件,在 MCUXpresso IDE 下打开这个工程。
2.1 Memory 空间定义
在工程名上右击选择 Properties 进入选项配置界面,其中 MCU settings 一栏里定义的就是 MCU 实际存储空间,这是链接文件的空间分配基础,我们后面会将程序里全部的段都链接在这些区域里。
存储空间属性(Type)分为两类:一类是 Flash(存放 RO 段),一类是 RAM(存放 RW 段)。每个属性的空间都可以被定义很多个,但其中仅 Alias 名为 Flash 和 RAM 的空间才是默认被选中用于链接程序段的(可通过上下移动按钮将指定空间调整到前排 Flash 和 RAM 的位置)。
2.2 默认程序段分配
还是在上一节打开的 Properties 选项配置界面,其中 Settings / Managed Linker Script 页面就是链接文件里具体程序段链接设置,这个页面的最上面 Manage linker script 要保持勾选,勾选上则代表使用 IDE 的链接文件自动生成功能。
在一个具体应用程序项目工程里,如果源文件仅包含标准 C 和汇编代码,那么程序段会被默认归纳为三大类:RO 段(函数代码,常量,全局变量初值等),RW 段(全局变量,重定向到 RAM 中函数代码等),Heap/Stack。IDE 里分别提供了这三类程序段的空间指定:
1. Link application to RAM 勾选框:
- 不勾选,则 RO 段放在 2.1 节图中 Alias 名为 Flash 的空间里
- 勾选上,则 RO 段放在 2.1 节图中 Alias 名为 RAM 的空间里
2. Heap and Stack placement 配置框:
- 可以按需调整 Heap/Stack 里的 Region,Location,Size,其中 Region 可以是 2.1 节图中属性为 RAM 的任意空间
- Heap/Stack 默认大小均为 4KB,放在 2.1 节图中 Alias 名为 RAM 的空间里
3. Global data placement 下拉框:
- 可以按需链接 RW 段到 2.1 节图中属性为 RAM 的任意空间
- RW 段默认放在 2.1 节图中 Alias 名为 RAM 的空间里
2.3 自定义程序段分配
除了上一节链接器默认的程序段名外,我们也可以自定义一些用户段名,方便一些特殊代码处理。这里需要使用 __attribute__((section("UserSectionName"))) 链接器语法来修饰指定函数/变量,这样该函数/变量就会被放在 UserSectionName 段里,然后我们在上一节图中链接设置框的最后 Extra linker script input sections 框里单独为自定义 UserSectionName 段指定链接空间。
比如工程 clock_config.c 文件里如下函数 UpdateSemcClock(),这个函数在默认的 RO .text 段里,RO 段都是链接在 Flash 里的,但是我们希望将这个函数重定向到 ITCM 里执行,所以我们可以使用 __attribute__((section("CodeQuickAccess"))) 链接器语法来修饰这个函数,然后在 Extra linker script input sections 框里将 CodeQuickAccess 段放到 SRAM_ITC_cm7 空间里即可。
#define AT_QUICKACCESS_SECTION_CODE(func) __attribute__((section("CodeQuickAccess"), __noinline__)) func
#define AT_QUICKACCESS_SECTION_DATA(func) __attribute__((section("DataQuickAccess"))) func
AT_QUICKACCESS_SECTION_CODE(void UpdateSemcClock(void));
void UpdateSemcClock(void)
{
SEMC->IPCMD = 0xA55A000D;
while ((SEMC->INTR & 0x3) == 0);
SEMC->INTR = 0x3;
SEMC->DCCR = 0x0B;
CCM->CLOCK_ROOT[kCLOCK_Root_Semc].CONTROL = 0x602;
}
2.4 自动生成的链接文件
链接设置完成后,会在工程目录 \MCUXpressoIDE_11.4.0_6224\workspace\evkmimxrt1170_hello_world_demo_cm7\Debug 下自动生成最终链接文件(假定用得 debug build),文件一共有三个,其中 evkmimxrt1170_hello_world_demo_cm7_Debug.ld 是主链接文件,感兴趣的可以打开这个链接文件学习一下(如果看不懂语法可以结合这篇文章 https://www.embedded.com/building-bare-metal-arm-systems-with-gnu-part-3/ )。
2.5 查看Map文件确认
按照 2.1 节和 2.2 节 图中的链接设置,我们编译链接 evkmimxrt1170_hello_world_demo_cm7 工程可以得到如下链接结果,从空间占用上来看是符合预期的。
现在我们可以打开生成的 evkmimxrt1170_hello_world_demo_cm7.map 文件具体分析一下最终链接情况,痞子衡摘录了最核心部分如下:
Memory Configuration
Name Origin Length Attributes
/------------------------------------------------------------/
// RO .text 段在 BOARD_FLASH:0x30000000 - 0x30006eaf,共 28336 个字节
// RO CodeQuickAccess 段在 BOARD_FLASH:0x30006eb0 - 0x30006ee7,共 56 个字节
// RO .data_init 段在 BOARD_FLASH:0x30006ee8 - 0x30006eeb,共 4 个字节
.boot_hdr 0x30000000 0x2000
.text 0x30002000 0x4eb0
// RW CodeQuickAccess 段在 SRAM_ITC_cm7:0x00000000 - 0x00000037,共 56 个字节
.data_RAM4 0x00000000 0x38 load address 0x30006eb0
CodeQuickAccess
0x00000000 0x38 ./board/clock_config.o
0x00000000 UpdateSemcClock
// RW .data 段在 BOARD_SDRAM:0x80000000 - 0x80000003,共 4 个字节
.data 0x80000000 0x4 load address 0x30006ee8
.data.SystemCoreClock
0x80000000 0x4 ./device/system_MIMXRT1176_cm7.o
// RW .bss 段在 BOARD_SDRAM:0x80000004 - 0x80000107,共 260 个字节
.bss 0x80000004 0x104
// Heap 在 BOARD_SDRAM:0x80000108 - 0x80001107,共 4KB
.heap 0x80000108 0x1000
// Stack 在 BOARD_SDRAM:0x82fff000 - 0x82ffffff,共 4KB
.stack 0x82fff000 0x0
0x82fff000 _vStackBase = .
0x82fff000 . = ALIGN (0x4)
0x83000000 _vStackTop = (. + _StackSize)
简单总结下,RO 段一般从 Flash 的最前面开始链接的,.text 段在最前面,然后是 ramfunc 函数实体,最后是 .data_init 段(全局变量初值)。RW 段也是从 RAM 的最前面开始链接,.data 段在前,.bss 在后,然后是 Heap 和 Stack(Heap/Stack的具体位置是可以设置的,有 Start、End、Post Data 三种选择)。
三、MCUXpresso IDE下链接小实验
根据上面的知识,我们现在来做些链接设置小实验,在做实验前,我们调整下 Memory 定义,把 SDRAM 相关空间移到后面去,默认 RAM 用 SRAM_DTC_cm7 空间,这样看起来习惯一点。
3.1 默认 XiP 链接
调整过 Memory 空间顺序后的链接结果如下:
3.2 Non-XiP 链接
现在我们尝试使能 Link application to RAM 选项,其余不变,此时可以看到 28396 Bytes 的 RO 段也到了 SRAM_DTC_cm7 空间里,BOARD_FLASH 空间完全没有任何占用:
3.3 XiP 链接,调整 Stack 大小并放置到 OCRAM1
我们尝试调整 Stack 大小到 1KB 并放置到 SRAM_OC1,其余不变,此时可以看到 SRAM_DTC_cm7 空间消耗相比 3.1 节里少了 4KB,但 SRAM_OC1 空间消耗多了 1KB:
3.4 XiP 链接,调整 RW 段到 OCRAM2
我们尝试调整 RW 段到 SRAM_OC2,其余不变,此时可以看到 SRAM_DTC_cm7 空间消耗相比 3.1 节里少了 264 Bytes,但 SRAM_OC2 空间消耗多了 264 Bytes:
至此,MCUXpresso IDE下工程链接文件配置管理与自动生成机制痞子衡便介绍完毕了,掌声在哪里~~~
欢迎订阅
文章会同时发布到我的 博客园主页、CSDN主页、知乎主页、微信公众号 平台上。
微信搜索"痞子衡嵌入式"或者扫描下面二维码,就可以在手机上第一时间看了哦。

痞子衡嵌入式:MCUXpresso IDE下工程链接文件配置管理与自动生成机制的更多相关文章
- 痞子衡嵌入式:MCUXpresso IDE下将应用程序RW段分散链接的几种方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下将应用程序RW段分散链接的几种方法. 早期的 MCU 芯片,一般都会嵌入内部 Flash 和 RAM,并且 ...
- 痞子衡嵌入式:把玩i.MXRT1062 TencentOS Tiny EVB_AIoT开发板(1) - 开发环境搭建与点灯
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是i.MXRT1062 TencentOS Tiny EVB_AIoT开发板环境搭建与点灯. 腾讯 TencentOS 团队于2021年1 ...
- 痞子衡嵌入式:MCUXpresso IDE下添加C++源文件进SDK工程编译的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下添加C++源文件进SDK工程编译的方法. 最近有客户反映在MCUXpresso IDE下的SDK工程里添加 ...
- 痞子衡嵌入式:MCUXpresso IDE下SDK工程在Build配置上与IAR,MDK差异
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下SDK工程在Build配置上与IAR,MDK差异. 恩智浦 SW 团队每个季度都会公布 SDK.Tool ...
- 痞子衡嵌入式:MCUXpresso IDE下SDK工程导入与workspace管理机制
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下SDK工程导入与workspace管理机制. MCUXpresso IDE是恩智浦软件团队倾注很大心血研发 ...
- 痞子衡嵌入式:MCUXpresso IDE下添加新路径下源文件进工程编译的方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下添加新路径下源文件进工程编译的方法. 接着上篇文章 <MCUXpresso IDE下SDK工程导入与 ...
- 痞子衡嵌入式:MCUXpresso IDE下将关键函数重定向到RAM中执行的几种方法
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是MCUXpresso IDE下将关键函数重定向到RAM中执行的几种方法. 前段时间痞子衡写了一篇 <在IAR开发环境下将关键函数重 ...
- 痞子衡嵌入式:MCUXpresso IDE下将源码制作成Lib库方法及其与IAR,MDK差异
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家分享的是MCUXpresso IDE下将源码制作成Lib库方法及其与IAR,MDK差异. 程序函数库是一个包含已经编译好代码和数据的函数集合,这 ...
- 痞子衡嵌入式:MCUXpresso IDE下使用J-Link下载算法在Flash调试注意事项(i.MXRT500为例)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是MCUXpresso IDE下使用J-Link下载算法在Flash调试注意事项. 痞子衡前段时间写过一篇小文<为i.MXRT设计更 ...
随机推荐
- 什么是CIDR?
英文缩写: CIDR (Classless InterDomain Routing) 中文译名: 无类别域间路由选择 IP地址有"类"的概念,/8掩码是A类,/16掩码是B类,/2 ...
- Ming Yin(@kalasoo)在知乎的几个回答 : 观点犀利
这篇文章汇总了掘金前站长Ming Yin(阴明)在知乎的几个犀利的观点,原文可访问zhihu.com/kalasoo 由@flightmakers转载(收藏)在此 你是否有个人网站.可否和大家分享一下 ...
- .NET 6 预览版 7 发布——最后一个预览版
原文:bit.ly/2VJxjxQ 作者:Richard 翻译:精致码农-王亮 说明:文中有大量的超链接,这些链接在公众号文章中被自动剔除,一部分包含超链接列表的小段落被我删减了,如果你对此感兴趣,请 ...
- 守护线程_daemon
守护线程_daemon 线程分为用户线程和守护线程 虚拟机必须确保用户线程(main)执行完毕 虚拟机不用等待守护线程(gc)执行完毕 如:后台记录操作日志,监控内存,垃圾回收等等 测试案例: pac ...
- 算法竞赛中的常用JAVA API :HashSet 和 TreeSet(转载)
算法竞赛中的常用JAVA API :HashSet 和 TreeSet set set容器的特点是不包含重复元素,也就是说自动去重. HashSet HashSet基于哈希表实现,无序. add(E ...
- Redisson实战-BloomFilter
1. 简介 布隆过滤器是防止缓存穿透的方案之一.布隆过滤器主要是解决大规模数据下不需要精确过滤的业务场景,如检查垃圾邮件地址,爬虫URL地址去重, 解决缓存穿透问题等. 布隆过滤器:在一个存在一定数量 ...
- Linux线程同步之读写锁(rwlock)
读写锁和互斥量(互斥锁)很类似,是另一种线程同步机制,但不属于POSIX标准,可以用来同步同一进程中的各个线程.当然如果一个读写锁存放在多个进程共享的某个内存区中,那么还可以用来进行进程间的同步, 和 ...
- SpringBoot开发七-开发注册功能
需求介绍-开发注册功能 首先访问注册页面-点击顶部的链接,打开注册页面 提交注册数据 通过表单提交数据 服务端验证账号是否存在,邮箱是否已经注册 服务端发送激活邮件 激活注册账号 点击邮件中的链接,访 ...
- 【vulapps】Sturcts2 S2-037RCE漏洞复现
一.漏洞基本信息 S2-037官方公告 CVE编号:CVE-2016-4438漏洞名称:Struts(S2-037)远程代码执行漏洞发布日期:2016.615受影响的软件及系统:Apache stru ...
- [数据库系列之MySQL] Mysql整体架构浅析一
一.引言 平时我们在做Java系统时,一般情况下都会连接到一个MySQL数据库上去,执行各种增删改查的语句.大部分的Java工程师对MySQL的了解和掌握程度,大致就停留在这么一个阶段:对MySQL可 ...