• MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制


    一、准备工作

      首先需要准备好环境,包含必要的软件,痞子衡的环境如下:

    • 集成开发环境: MCUXpresso IDE_11.6.0_8187,点此下载
    • 软件开发包: SDK_2.12.1_EVK-MIMXRT1170(Toolchain需包含MCUXpresso IDE),点此下载

      然后按照 《MCUXpresso IDE下将关键函数重定向到RAM中执行的几种方法》 文章 一、准备工作 小节里改造下 evkmimxrt1170_hello_world_demo_cm7 示例工程选项,并添加 critical_code.c 源文件。在这篇文章的 2.3 针对源文件中全部函数 小节里,痞子衡为了将 critical_code.c 里代码全部链接到 DTCM,使用了回退到 IAR/Keil 那种传统改写链接文件的方式。今天我们就尝试用 FreeMarker 链接文件模板机制这个特性来实现。

    二、FreeMarker机制

      FreeMarker 是一个模板引擎(更通俗的说法其实就是链接文本的生成器),它集成在 MCUXpresso IDE 内部,由 MCUXpresso IDE 自动调用。MCUXpresso IDE 下最终的链接文件其实是由这个 FreeMarker 处理生成的。在 MCUXpresso IDE 软件内部有一组默认的系统模板(也叫根模板),它还支持用户提供的模板(这些模板均是用一种专用的语法 FTL 来描述的),所有适用工程的模板最终统一经过 FreeMarker 来处理。

      模板的设计是组件化的,这意味着用户不需要编写整个工程的模板,只需要加入指定的用户模板实现个性化链接需求即可,其它部分仍由 MCUXpresso IDE 图形配置界面完成。默认情况下,用户模板需要被放在指定的 user_project_root/linkscripts 目录下(这个路径不用额外添加进工程选项 C/C++ General \ Paths and Symbols \ Source Location 中)。

    • Note:更多 FreeMarker 细节,可以参见 \MCUXpressoIDE_11.6.0_8187\MCUXpresso_IDE_User_Guide.pdf 文档里的 17.14 FreeMarker Linker Script Templates 小节。

    三、新方法解决问题

      现在我们尝试用 FreeMarker 特性来解决 critical_code.o 的链接需求。首先是在 \MCUXpressoIDE_11.6.0_81874\workspace\evkmimxrt1170_hello_world_demo_cm7 下创建一个名为 linkscripts 的文件夹(前面说了,这个新文件夹路径不需要在工程选项里登记),然后在 linkscripts 里面新建如下三个 .ldt 文件(固定文件名,由 FreeMarker 定死的):

    1. bss.ldt
    2. data.ldt -- 作用是将 critical_code.o 放到指定 RAMx 区域
    3. -- 备注:如果 MCU 仅一块 RAM 空间,则此处应为 main_data.ldt
    4. main_text.ldt -- 作用是将 critical_code.o 从 .text 段(默认链接在 Flash 区域)移出来

      main_text.ldt 内容比较简单,仅仅是用于告诉 FreeMarker 不要将 critical_code.o 里的 text 段放进主 .text 段里一起处理:

    1. // 单目标文件写法
    2. *(EXCLUDE_FILE(*critical_code.o) .text*)
    3. // 如果是多目标文件,写法可以这样
    4. *(EXCLUDE_FILE(*critical_code1.o *critical_code2.o) .text*)

      data.ldt 中内容比较关键,用于重置 critical_code.o 里的 text 段。这里需要注意的是如果是将该 text 放置进主 RAM 区域(即工程选项 MCU settings 里 Alias 名为 RAM 的空间),其写法跟不放进主 RAM 不一样:

    1. // 如果目标文件放进主 RAM - 正确写法,等效于放进 memory.alias=="RAM" 或者 memory.name=="SRAM_DTC_cm7" 区域
    2. *critical_code.o(.text*)
    3. // 如果目标文件放进主 RAM - 错误写法,实际不生效,等于没有重置,代码依旧放进 Flash 区域
    4. <#if memory.alias=="RAM">
    5. *critical_code.o(.text*)
    6. </#if>
    7. // 如果目标文件不是放进主 RAM - 正确写法1
    8. <#if memory.name=="SRAM_ITC_cm7">
    9. *critical_code.o(.text*)
    10. </#if>
    11. // 如果目标文件不是放进主 RAM - 正确写法2
    12. <#if memory.alias=="RAM2">
    13. *critical_code.o(.text*)
    14. </#if>
    15. // 如果是多目标文件,写法可以这样
    16. <#if memory.name=="SRAM_ITC_cm7">
    17. *critical_code1.o(.text*)
    18. *critical_code2.o(.text*)
    19. </#if>

      现在编译工程查看映射文件,我们会发现 critical_code.c 里全部函数都已经链接在指定的 RAMx 区域了。如果你想更进一步,把 critical_code.c 里全部 RO data 段都放进指定 RAMx 区域,则需要再在 linkscripts 文件夹里增加一个名为 main_rodata.ldt 文件。其内容如下,这里是告诉 FreeMarker 不要将 critical_code.o 里的 RO data 段放进主 RO data 段里一起处理。

    1. *(EXCLUDE_FILE(*critical_code.o) .rodata)
    2. *(EXCLUDE_FILE(*critical_code.o) .rodata.*)
    3. *(EXCLUDE_FILE(*critical_code.o) .constdata)
    4. *(EXCLUDE_FILE(*critical_code.o) .constdata.*)
    5. . = ALIGN(${text_align});

      然后 data.ldt 里改成如下这样就可以了:

    1. <#if memory.alias=="RAM2">
    2. *critical_code.o(.text*)
    3. *critical_code.o(.rodata .rodata.* .constdata .constdata.*)
    4. </#if>

      至此,MCUXpresso IDE下高度灵活的FreeMarker链接文件模板机制痞子衡便介绍完毕了,掌声在哪里~~~

  • 相关阅读:
    使用树莓派学习PostgreSQL
    京东面试官:讲讲Redis各个数据类型的底层数据结构
    Nacos源码系列—服务端那些事儿
    记录一下工作中completableFutures异步多线程的使用
    MySQL流程控制函数
    SpringBoot教程(十六) SpringBoot集成swagger(全网最全)
    一起来学习flutter 的布局组件
    1 opencv-python图像读写模块
    数理统计笔记6:假设检验
    vue: 使用下拉树组件@riophae/vue-treeselect
  • 原文地址:https://blog.csdn.net/sinat_40572875/article/details/128110322