zoukankan      html  css  js  c++  java
  • 【转载】CodeWarrior IDE使用tips之prm链接文件详解(自定义存储器分区以及自定义RAM数据初始化与在RAM中运行函数)

    CodeWarrior IDE使用tips之prm链接文件详解(自定义存储器分区以及自定义RAM数据初始化与在RAM中运行函数)

    2017-08-19 胡恩伟 汽车电子expert成长之路

    内容提要

    引言

    1. 链接文件的作用和特点

    2. CodeWarrior 5.x IDE工程的prm链接文件详解

    3. CodeWarrior 5.x IDE工程的prm链接文件高级应用

            3.1 自定义全局变量、常数和函数代码指定到指定的存储器空间

            3.2 自定义全局变量、常数和函数代码指定到指定的存储器空间的注意事项

    总结

    引言

            在嵌入式MCU应用程序的开发过程中,工程师将源代码(汇编或者C/C++语言)编辑好,到最终生成可以下载到MCU被CPU执行的二进制可执行文件,需要经过预编译、编译、汇编和链接四个过程,其分别有集成开发环境IDE中的预编译器(pre-compiler)、C/C++编译器(compiler)、汇编器(assemler)和链接器(linker)完成。

    1. 链接文件的作用和特点

            在CodeWarrior 5.x IDE中,处理头文件中各种宏定义以及inline函数的预编译器集成在C/C++编译器中,其完成对C/C++源文件(.c/.cpp和.h)的编译输出相应的.obj目标文件,而汇编器完成对汇编源代码输入文件(.s和.inc)的编译并生成相应的.obj目标文件。接下来由链接器根据链接文件对obj目标文件进行链接,生成最终的abs/elf二进制可执行文件以及Flash下载编程S19文件(其与HEX和BIN文件作用相同,都包含编译结果中需要下载的代码/数据以及存储地址信息,可以相互转换(convert))。

            链接文件(Linker File)作为链接器的输入,其作用是告诉链接器如何将obj文件中所包含的函数/程序代码和用户数据链接到目标MCU的存储器资源中----具体的各种存储器的大小、起始地址和结束地址、属性(只读(RO)还是可读可写(R/W))、系统分区和用户分区信息、堆栈大小设置等。

    链接文件具有如下特点:

            a. 不同的链接器(或者IDE)链接文件的格式不同。比如CodeWarrior 6.x(S08系列MCU工程)、CodeWarrior 4.x/5.x(S12(X)系列MCU工程)和CodeWarrior10.x(S08系列和MagniV S12Z系列MCU工程)的链接文件为prm文件;而CodeWarrior10.x(Kinetis/KEA 系列和Qorivva MPC56xx系列MCU工程)、CodeWarrior 2.x(Qorivva MPC56xx系列MCU工程)、S32DS for ARM/Power 使用的GNU工具链的工程链接文件则为ld文件; Keil/MDK工程的链接文件为sct分散加载文件; IAR工程的链接文件为icf文件。

            b.链接文件中存储器资源的种类和大小以及地址范围必须严格与目标MCU硬件存储器资源一致,才能保证工程链接结果在目标MCU上可以正常下载和运行(PS: 存储器的大小可以小于目标MCU真实的大小,但决不能大于MCU实际的大小,否则如果是Flash/EEPROM下载时(擦除和编程)会报地址溢出错误,若果是RAM,下载不会报错,但运行时会导致非法地址访问引起内核CPU异常或者直接非法地址复位,程序跑飞等);

            c.一个工程可以有多个链接文件对于不同的链接目标(target),但每一次链接(make)仅使用一个链接目标(不同的目标可以编译不同的文件和库)、通过工程属性-->l链接器配置进行设置选择。

    2. CodeWarrior 5.x IDE工程的prm链接文件详解

            这里以一个S12G128MCU的CodeWarrior 5.x IDE工程为例,来介绍CodeWarrior IDE的prm链接文件。

    在CodeWarrior 5.1 IDE中工程的链接文件就是新建工程时默认根据所选part number添加的prm文件,其位于CodeWarrior工程的工程视窗-->Files-->Project Settings-->Linker Files目录下,prm文件可以使用任意文本编辑器打开并修改:

            首先我们来看看一个S12G128默认工程的prm文件:

            其中蓝色高亮的部分为prm文件保留关键词和默认系统段名:

     

            在SEGMENTS...END中对MCU存储器资源进行分区时,一般格式如下:

            分区名    = 存储属性   访问属性  开始地址  TO 结束地址;

            其中“= ”和“TO ”为关键词,每一个分区以分号“;”结束。其余部分解释如下:

    分区名:需要给每一个分区取一个名字,可以用户自定义,只要方便理解即可;

    存储属性:用于指示存储器的存储属性

    访问属性:包括使用near指针(16-bit地址)访问:DATA_NEAR, IBCC_NEAR(代码访问,只适用于只读存储器,如EEPROM和Flash)和使用far指针(24-bit地址)访问:DATA_FAR, IBCC_FAR(代码访问,只适用于只读存储器,如EEPROM和Flash);

    开始地址和结束地址:该存储器分区的起始地址和结束地址,这里只能使用存储器的本地地址和逻辑地址/分页地址,不能直接使用全局地址/物理地址;

            在PLACEMENT...END中,将系统和用户数据/代码段放入具体分区的格式为:

            段名1,段名2...    INTO   分区名;

            其中“INTO”为关键词,表述放入,可以将一个或多个段(以不同的段名表示)放置在一个分区(以分区名区别)中,关于段名和分区名解释如下:

    段名:可以是系统保留段和用户自定义段,用于表示不同的数据或代码段,可以将多个不同的段放在同一分区内:

    分区名: 在SEGMENTS...END中定义好的分区;

    注意:系统保留段必须放置在未分页区(non-paged)中。

    3. CodeWarrior 5.x IDE工程的prm链接文件高级应用

            基于以上介绍,我们通过编辑prm链接文件可以完成以下高级应用:

    3.1 自定义全局变量、常数和函数代码指定到指定的存储器空间

            具体步骤如下:

            第一步,在prm文件SEGMENTS..END中对片上RAM和Flash进行分区如下:

            并在PLACEMENT..END中给要需要自定义存储的全局变量(USR_DATA_SECTION)、常数(USR_CONST_SECTION)和函数代码(USR_CODE_SECTION)定义一个段,并分配带特定的分区中,完整的工程prm文件如下:

            第二步、在C语言中,使用"#pragma CODE_SEG/DATA_SEG/CONST_SEG/STRINGS_SEG 段名",将具体的用户数据和代码指定到相应的段(segment);

    具体语法为:

    #pragma XX_SEG (<Modif>  <Name>|DEFAULT)

    "#pragma"为关键词;

    XX_SEG(必选)以是以下四种之一:

     

    <Modif>(可选)为该段的访问属性,可以是以下几种之一:

            __DIRECT_SEG (compatibility alias: DIRECT)

            __NEAR_SEG   (compatibility alias: NEAR)

            __CODE_SEG   (compatibility alias: CODE)

            __FAR_SEG    (compatibility alias: FAR)

    <Name>|DEFAULT:用户自定义段名,或者DEFAULT(恢复默认段,将数据和代码放到DEFAULT_RAM或者DEFAULT_ROM默认段中)或者其他系统保留段,比如NON_BANK;

    具体如下:

    3.2 自定义全局变量、常数和函数代码指定到指定的存储器空间的注意事项

    a. 用户新建工程后,在C文件中数据定义都默认放到DEFAULT_RAM区,函数代码都放到DEFAULT_ROM区;当时用“#pragma XX_SEG (<Modif>  <Name>”自定义一个数据、代码段之后需要使用“#pragma XX_SEG  DEFAULT”将其恢复默认段;

    头文件声明和C文件定义时也需要使用“#pragma XX_SEG(<Modif>  <Name>|DEFAULT)”保持其一致性;

    b. 用户自定义的全局变量数据段分区属性若为READ_WRITE,则MCUstartup过程中会对该段进行初始化,比如prm分区如下:

    则相应链接生成的map文件如下:

    如果用户不想让其在startup过程中被coypdown RAM初始化时置零或者赋初始化值,则需要在定义分区时将其属性该位NO_INIT,比如:

    这样链接后map文件中_Startup启动结构体中ZeroOut区数量变为了1,不会对0x3000开始的My_Data_RAM进行初始化:

    c. 用户定义代码段如果使用关键词RELOCATE_TO使重定向到RAM中,则可以实现将用户函数运行时地址重定向到RAM中的作用:

    相应的工程链接结果map文件如下:

    从工程链接的结果可以看到, 用户自定义函数My_Function的存储地址为0xF000而运行时地址为重定向之后的RAM地址0x3800;

    注意:运行这类重定向到RAM中的函数之前,必须手动将其拷贝搬移到重定向的RAM地址才能正常运行,MCU startup启动过程中并不会帮用户做这个代码拷贝的工作:

    总结

    本文介绍的prm文件规则和使用技巧,同样适用于S08系列和MagniV S12Z系列MCU的CodeWarrior IDE工程。掌握prm文件的规则之后,我们能够实现对MCU存储器资源的使用做个性化的定制,以满足特定需求,比如对存储器进行分区、某些变量的保护和将函数代码链接到RAM中执行,这些知识对开发BootLoader十分有用,因为BootLoader中需要对Flash进行编程,运行Flash擦除和编程驱动函数时,必须将其拷贝到RAM执行,以避免Read-while-write带来的总线冲突和程序崩溃。

    另外,我将本文中介绍prm文件所使用的完整CodeWarrior 5.x工程(Project_S12G128_UserCustomize_Prm_DemoPrj.mcp),分享到百度云盘,供大家参考学习:

    链接:http://pan.baidu.com/s/1dESeY0D

    密码:jvkj

    以上就是今天跟大家分享的内容。希望对大家有用。

            

            本微信公众号已经发布的个人原创精品----嵌套嵌入式系统技术文章链接如下,欢迎大家参考学习,并转发分享:

             如果你喜欢本公众号的文章,请点击文章最开始的公众号关注或微信直接长按扫描识别下方二维码关注,你也可以在微信添加朋友-->公众号-->输入"汽车电子expert成长之路"搜索-->点击关注。若对本文观点有任何意见和建议也欢迎留言指出。您的关注、点赞、转发分享是对我辛勤写作的最大肯定。

     胡恩伟

                          NXP汽车电子FAE

                       2017年8月19日于山城·重庆

     
     

    微信扫一扫
    关注该公众号

  • 相关阅读:
    hdu 5366 简单递推
    hdu 5365 判断正方形
    hdu 3635 并查集
    hdu 4497 数论
    hdu5419 Victor and Toys
    hdu5426 Rikka with Game
    poj2074 Line of Sight
    hdu5425 Rikka with Tree II
    hdu5424 Rikka with Graph II
    poj1009 Edge Detection
  • 原文地址:https://www.cnblogs.com/HuangNanShan/p/8253633.html
Copyright © 2011-2022 走看看