文件关系:链接文件(.icf) + 工程文件(.ewp) + 可重定向文件(.o/.a) -> 映射文件(.map)
痞子衡在第四节课可重定向文件(.o/.a)里分析object文件里的symbol list时讲到由于object文件并没有经过链接,所以所有symbol地址信息是无效的(待分配的),而map文件就是所有relocatable文件经过链接器统一链接后生成的记录链接信息的文件,map文件里可以查到所有symbol在存储器中具体分配地址。话不多说,让我们直接开启map文件分析之旅,以第三节课工程文件(.ewp)里demo工程为例。
一、解析map文件

在IAR软件选项设置options->Linker->List里选中Generate linker map file,编译链接demo工程可在D:\myProject\bsp\builds\demo\Release\List路径下得到demo.map文件。让我们从头到尾逐一分析里面内容:
1.1 工程文件信息
map文件里第一部分信息记录的是工程文件相关信息,包括工程使用的软件版本,工程编译时间,工程文件目录,工程文件生成文件信息。
################################################################################# IAR ELF Linker V8.11.2.13589/W32 for ARM 12/Jan/2018 17:37:39# Copyright 2007-2017 IAR Systems AB.## Output file = D:\myProject\bsp\builds\demo\Release\Exe\demo.elf# Map file = D:\myProject\bsp\builds\demo\Release\List\demo.map# Command line =# -f C:\Users\Baoge\AppData\Local\Temp\EW5D86.tmp# (D:\myProject\bsp\builds\demo\Release\Obj\main.o# D:\myProject\bsp\builds\demo\Release\Obj\reset.o# D:\myProject\bsp\builds\demo\Release\Obj\startup.o# D:\myProject\bsp\builds\demo\Release\Obj\startup_MKL25Z4.o# D:\myProject\bsp\builds\demo\Release\Obj\system_MKL25Z4.o# D:\myProject\bsp\builds\demo\Release\Obj\task.o -o# D:\myProject\bsp\builds\demo\Release\Exe\demo.elf --map# D:\myProject\bsp\builds\demo\Release\List\demo.map --config# D:\myProject\bsp\builds\demo/../../linker/iar/KL25Z128xxx4_flash.icf# --entry Reset_Handler --inline --vfe --text_out locale)################################################################################
1.2 系统库使用信息
map文件里第二部分信息记录的是工程系统库使用情况,由于task.c里调用了malloc()、free()等HEAP相关操作的API,所以自然我们在编译链接工程时会使用到HEAP相关系统库,这里告诉我们用的是DLib里的DLMalloc,而DLMalloc有很多种不同的HEAP实现策略,我们可在options->General Options->Library Option 2->Heap selection指定具体策略,由于demo工程选的是Automatic,也就是让IDE自动选择,这里告诉我们最终用的策略是advanced heap。
RUNTIME MODEL ATTRIBUTESCppFlavor = __Heap_Handler = DLMalloc__SystemLibrary = DLib__dlib_version = 6 HEAP SELECTIONThe advanced heap was selected because the application calls memoryallocation functions outside of system library functions, and thereare calls to deallocation functions in the application.
1.3 各object中Section放置信息
从map文件第三部分开始,就进入非常有用的信息环节了。第一个重要信息就是section放置信息。我们在第四节课可重定向文件(.o/.a)里分析过单个relocatable文件task.o,task.o里各个基本section都有,但是都并没有分配有效地址,而这里列出了所有relocatable文件统一存储和地址分配信息,从这里我们可以看到,链接器在整合各section的时候,都是以object文件为单位的,这意味着同一个object文件里的同一个section里的对象(变量/函数)在存储空间里的位置也是靠在一起的。
另外一个有意思的信息是在第二节课链接文件(.icf)里,我们一共有四句block放置语句,在这里section也被分成了四个block:A0,P1,P2,P3。IDE给每个block重命名了,这些重命名的信息将会在第六节课可执行文件(.out/.elf)里被提到……
查看原文:https://www.dianyuan.com/eestar/article-7993.html
真实S7-1200与RobotStudio 6.0 的仿真通讯
其实本人比较不太会记笔记(Actually, I'm lazy),都是靠着映像和记忆的,怎奈何随着年纪的突飞猛进,脑子的各项功能开始下降,所以好记性真的不如烂笔头啊,同时也借助这个公众号平台和大家进行工业机器人相关的技术交流,共同学习共同进步。
好的,闲话不多说,进入正题:
一、使用硬件和软件
1-硬件:西门子PLC S7-1200 CPU1214 DCDCDC;
2-软件:TIA Portal V16 和 ABB RobotStudio 6.08
3-RobotStudio 6.08的插件:
RSConnectDIOToSnap7.rslib和RSConnectGIOToSnap7,其实这是两个库文件,分别是PLC和RobotStudio进行单个输入输出信号以及组信号的通讯。那么如何获取这两个库文件呢?直接看下图:
3.1-在RobotStudio中的RobotApps中搜索sanp7;
3.2-下载;
3.3-下载的这两个库文件存放在哪里?
其实存放在哪里都可以,只要你能找到的地方,这里我是放在“用户库”,路径可以打开上图的“位置”,就可以看到具体的路径了,请看下图。
二、具体通讯连接操作
1、使用RobotStudio 6.08创建一个系统工作站,无需任何附加选项。
2、重点来了,导入RSConnectDIOToSnap7.rslib库文件……
查看原文:https://www.dianyuan.com/eestar/article-7962.html
RT-Thread下IAR工程函数重定向为何失效?
痞子衡旧文 《在IAR下将关键函数重定向到RAM中执行的方法》 里介绍了三种关键函数重定向方法,不过这三种方法只是写法形式不同,本质上没啥区别,都是利用 IAR 链接器特性将函数重定向到工程数据段(RW)所在 RAM 里。
对于 i.MXRT 这种拥有多块地址非连续的 RAM 的芯片,其实我们也可以单独将这些重定向函数放到一个指定的 RAM 里,不一定非得跟数据段放在同一个 RAM 里。具体实现也很简单,只需要在链接文件里额外加一句 place in 语句处理即可,恩智浦官方 SDK 包里就是这么做的。
然而痞子衡最近在移植一个 i.MXRT1170 RT-Thread 工程时发现,在 IAR 链接文件里用自定义段来单独指定重定向函数到 ITCM 竟然失效了,这是怎么回事?今天我们一起来看一下:
Note 1:阅读本文前需要对 《IAR链接文件(.icf)》、《IAR映射文件(.map)》 这两种文件有所了解。
Note 2:本文使用的 IAR EWARM 软件版本是 v9.10.2。
一、回顾SDK里函数重定向做法
我们以最经典的 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\demo_apps\hello_world\cm7\iar 例程来看,工程 Build 选择 flexspi_nor_sdram_debug(仅该 build 预编译宏里有 XIP_BOOT_HEADER_DCD_ENABLE=1),即代码段放在 Flash 里(0x30000000 - ),数据段放在 SDRAM 里(0x80000000 - )。
在时钟初始化函数 BOARD_BootClockRUN() 里会调用如下 UpdateSemcClock() 函数,这个函数需要重定向到 RAM 里执行,在代码里先将它放到自定义 CodeQuickAccess 段里。
#define AT_QUICKACCESS_SECTION_CODE(func) func @"CodeQuickAccess"#if defined(XIP_BOOT_HEADER_ENABLE) && (XIP_BOOT_HEADER_ENABLE == 1)#if defined(XIP_BOOT_HEADER_DCD_ENABLE) && (XIP_BOOT_HEADER_DCD_ENABLE == 1)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;}#endif#endif
然后在工程链接文件 MIMXRT1176xxxxx_cm7_flexspi_nor_sdram.icf 里(仅摘录部分),再将 CodeQuickAccess 段单独放在 ITCM 里(0x00000000 - ),这就是官方 SDK 里的做法。
define symbol m_data3_start = 0x80000000;define symbol m_data3_end = 0x82FFFFFF;define symbol m_qacode_start = 0x00000000;define symbol m_qacode_end = 0x0003FFFF;define region DATA3_region = mem:[from m_data3_start to m_data3_end-__size_cstack__];define region QACODE_region = mem:[from m_qacode_start to m_qacode_end];define block RW { first readwrite, section m_usb_dma_init_data };define block QACCESS_CODE { section CodeQuickAccess };initialize by copy { readwrite, section .textrw, section CodeQuickAccess };place in DATA3_region { block RW };place in QACODE_region { block QACCESS_CODE };
编译链接 hello_world_demo_cm7.ewp 工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 UpdateSemcClock() 函数相关的内容如下,显然这是符合预期的。这里特别注意一下,CodeQuickAccess 的类别显示的是 inited,表明其不是常见的 ro code,而是经过重定向的,而且 UpdateSemcClock() 函数所在 clock_config.o 里包含了 60个字节的 rw code……
查看原文:https://www.dianyuan.com/eestar/article-7992.html
深扒IAR启动函数流程及其底层初始化设计
大家好,我是痞子衡,是正经搞技术的痞子。今天痞子衡给大家分享的是IAR启动函数流程及其__low_level_init设计对函数重定向的影响。
上一篇文章 《IAR下RT-Thread工程自定义函数段重定向失效分析》 里我们找出了影响 IAR 链接器处理自定义程序段重定向的原因,主要跟 __low_level_init() 函数有关,这个函数属于 IAR 底层设计,它在 IAR 启动函数 __iar_program_start() 中会被自动调用。
__iar_program_start() 是 IAR 标准启动函数,也属于 IDE 底层设计。在任何一个 Cortex-M 厂商芯片的启动文件里(startup_xxDevice.s)都能看到它的身影,它是复位函数 Reset_Handler() 和 主函数 main() 之间的桥梁,今天我们就仔细说说这个启动函数以及其中 __low_level_init 设计:
Note 1:阅读本文前需要对《IAR链接文件(.icf)》、《IAR映射文件(.map)》这两种文件有所了解。
Note 2:本文使用的 IAR EWARM 软件版本是 v9.10.2。
一、通用芯片上电启动流程
在深入挖掘 IAR 启动函数源代码之前,有必要先整体了解一下通用的芯片上电启动流程,即进入用户 main 函数之前内核必须要做的事情,注意这里并不包含芯片底层外设的初始化(这是因芯片而异的)。
通用启动流程简单来说分为如下四步:第一步是从 ROM 区域中断向量表里获取入口函数开始执行,设置好初始栈指针,有了正确的栈,内核就具备函数跳转执行的能力了。第二步和第三步是全局变量的初始化(将全局变量初值从 ROM 区域拷贝到变量所链接的 RAM 区域),全局变量初始化完成,应用程序就有了正确的初始态,最后一步就是跳转到 main 函数。
二、从源代码角度看启动流程
在上一节通用启动流程的指导下,我们还需要增加一些 MCU 外设相关的初始化便形成了完整的芯片启动流程,现在我们从源代码角度再来看一下具体实现。
2.1 典型的 Cortex-M 复位函数
我们知道复位函数 Reset_Handler() 是芯片上电启动执行的第一个函数(有时又叫入口函数),它完成了进入用户 main() 函数之前的全部动作。随便下载一家 Cortex-M 厂商芯片 SDK 包,找到 IAR 版启动文件,其复位函数流程都差不多,这是 Cortex-M 内核架构决定的。
如下是典型的复位函数代码。复位函数里的操作包括关全局中断、设置中断向量表首地址、设置栈顶、系统初始化、开全局中断、进启动函数。其中系统初始化 SystemInit() 函数是因芯片而异的,各厂商 SDK 里会有具体源代码实现(一般在 system_xxDevice.c 文件里),这里面主要做芯片硬件层面的初始化,比如关看门狗、Cache 初步设置等,保证内核不受硬件模块状态影响,能正常执行指令。
THUMB PUBWEAK Reset_Handler SECTION .text:CODE:REORDER:NOROOT(2)Reset_Handler CPSID I ; Mask interrupts LDR R0, =0xE000ED08 LDR R1, =__vector_table STR R1, [R0] LDR R2, [R1] MSR MSP, R2 LDR R0, =SystemInit BLX R0 CPSIE I ; Unmask interrupts LDR R0, =__iar_program_start BX R0
2.2 __iar_program_start() 到底干了啥?
上一小节里我们知道复位函数里的最后一个动作就是跳转到启动函数,将内核执行权交给 __iar_program_start(),这个启动函数源代码并不在厂商 SDK 包里,而在 IAR 安装目录下,因为它是 IAR 的通用底层设计。
为了找到 __iar_program_start() 的源代码,我们可以随便编译一个 SDK 例程(痞子衡选择的是 \SDK_2.11.0_MIMXRT1170-EVK\boards\evkmimxrt1170\demo_apps\hello_world\cm7\iar),查看其对应映射文件(.map),发现启动函数来自于 cstartup_M.o,然后我们在 IAR 安装目录下搜索 cstartup_M.c/.s 文件,最终我们在如下路径找到了启动函数相关的全部源文件。
\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\thumb\cstartup_M.s\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\thumb\cmain.s\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\runtime\low_level_init.c\IAR Systems\Embedded Workbench 9.10.2\arm\src\lib\init\data_init.c
结合启动函数相关源文件里的代码,我们终于搞清了启动函数全部流程,也找到了我们最关心的 __low_level_init() 函数调用位置,它在 .data/.bss/.textrw 段初始化之前被执行,所以它的功能应该跟 SystemInit() 差不多。默认 __low_level_init() 函数是空的,返回值是 1(返回值 0/1 决定后面的 __iar_data_init3() 要不要执行,1 是要执行),如果你想激活这个函数,需要在自己的源文件里重新定义实现,IAR 编译时会优先引用重新定义的版本……
查看原文:https://www.dianyuan.com/eestar/article-7991.html
更多精彩内容,尽在电子星球 APP(https://www.eestar.com/)
六篇技术文章,让你秒懂电容的脾气秉性
七篇DIY技术文章献给你,让你脑洞全开
五篇文章帮你开启DSP的学习思路
汇总篇:关于PID知识,重点在此