在MDK开发环境下将关键函数重定向到RAM中执行的几种方法

一、准备工作

为了便于描述后面的函数重定向方法实现,我们先做一些准备工作,选定的硬件平台是恩智浦 MIMXRT1170-EVK,主芯片内部有2MB RAM,外挂了 16MB Flash 和 2 片 32MB SDRAM。这些存储设备在芯片系统中映射地址空间如下:

NOR Flash: 0x30000000 - 0x30FFFFFF16MB)
ITCM RAM:  0x00000000 - 0x0003FFFF256KB)
DTCM RAM:  0x20000000 - 0x2003FFFF256KB)
OCRAM:     0x20200000 - 0x2037FFFF1.5MB)
SDRAM:     0x80000000 - 0x83FFFFFF64MB)

我们随便选择一个测试例程:
\SDK_2.10.0_EVK-MIMXRT1170\boards\evkmimxrt1170\demo_apps\hello_world\cm7\mdk,其中 flexspi_nor 工程是最典型的代码链接场景(见 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 文件),全部的 readonly 段分配在 0x30000000 - 0x30FFFFFF 空间(在 Flash 中),全部的 readwrite 段分配在 0x20000000 - 0x2003FFFF 空间(在 DTCM 中)。链接文件精简如下:

LR_m_text 0x30002000 0x00FFE000 {
  VECTOR_ROM 0x30002000 FIXED 0x00000400 {
    * (.isr_vector,+FIRST)
  }
  ER_m_text 0x30002400 FIXED 0x00FFDC00 {
    * (InRoot$$Sections)
    .ANY (+RO)
  }
  RW_m_data 0x20000000 0x0003F800 {
    .ANY (+RW +ZI)
  }
  ARM_LIB_HEAP +0 EMPTY 0x00000400 {
  }
  ARM_LIB_STACK 0x20040000 EMPTY -0x00000400 {
  }
}

现在我们再创建一个新源文件 critical_code.c 用于示例关键函数,将这个源文件添加进 hello_world_demo_cm7.uvprojx 工程里,critical_code.c 文件中只有如下三个测试函数(它们在 main 函数里会被调用):

void critical_func1(uint32_t n)
{
    PRINTF("Arg = %d .\r\n", n);
}
void critical_func2(uint32_t n)
{
    PRINTF("Arg * 2 = %d .\r\n", 2 * n);
}
void critical_func3(uint32_t n)
{
    PRINTF("Arg * 3 = %d .\r\n", 3 * n);
}

编译链接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相关的内容如下,显然 critical_code.c 中的三个函数都会被链在 Flash 空间里(均在 .text 段里)。

===============================================================================
Image Symbol Table
    Global Symbols
    Symbol Name                              Value     Ov Type        Size  Object(Section)
    critical_func1                           0x30005429   Thumb Code    28  critical_code.o(.text.critical_func1)
    critical_func2                           0x30005449   Thumb Code    32  critical_code.o(.text.critical_func2)
    critical_func3                           0x30005469   Thumb Code    36  critical_code.o(.text.critical_func3)
===============================================================================
Memory Map of the image
    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b68, Max: 0x00fbdc00, ABSOLUTE, FIXED)
 
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x30005428   0x30005428   0x0000001c   Code   RO           17    .text.critical_func1  critical_code.o
    0x30005444   0x30005444   0x00000004   PAD
    0x30005448   0x30005448   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o
    0x30005468   0x30005468   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o
    0x3000548c   0x3000548c   0x00000004   PAD
===============================================================================
Image component sizes
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
        96         56          0          0          0        903   critical_code.o

二、重定向到RAM中方法

我们现在要做的事就是将 critical_code.c 文件中的函数重定向到 RAM 里执行,原链接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 中指定的是 DTCM 来存放 readwrite 段,那我们就尝试将关键函数放到 DTCM 里(如需改到 ITCM、OCRAM、SDRAM,方法类似)。

2.1 自定义p指定函数 - 针对单个函数

第一种方法是用 attribute((p(“UserSectionName”))) 语法来修饰函数定义,将其放到自定义程序段里。这种方法主要适用重定向单个关键函数,比如我们将 critical_func1() 函数放到名为 .criticalFunc 的自定义段里:

__attribute__((p(".criticalFunc"))) void critical_func1(uint32_t n)
{
    PRINTF("Arg = %d .\r\n", n);
}
void critical_func2(uint32_t n)
{
    PRINTF("Arg * 2 = %d .\r\n", 2 * n);
}
void critical_func3(uint32_t n)
{
    PRINTF("Arg * 3 = %d .\r\n", 3 * n);
}

然后在工程链接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 里将这个自定义的 p .criticalFunc 也放进 RW_m_data 执行域中:

LR_m_text 0x30002000 0x00FFE000 {
  ; ...
  RW_m_data 0x20000000 0x0003F800 {
    .ANY (+RW +ZI)
    * (.criticalFunc)  ;添加 .criticalFunc 段
      ; 第二种写法:*.o (.criticalFunc)
  }
  ; ...
}

编译链接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相关的内容如下,此时 critical_func1() 已经被放到自定义段 .criticalFunc 里,并且这个段被 MDK 底层链接器链接到了 RAM 里(RW_m_data 执行域空间)。

===============================================================================
Image Symbol Table
    Global Symbols
    Symbol Name                              Value     Ov Type        Size  Object(Section)
    critical_func1                           0x20000001   Thumb Code    28  critical_code.o(.criticalFunc)
    critical_func2                           0x30005429   Thumb Code    32  critical_code.o(.text.critical_func2)
    critical_func3                           0x30005449   Thumb Code    36  critical_code.o(.text.critical_func3)
===============================================================================
Memory Map of the image
    Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30005f60, Size: 0x00000078, Max: 0x0003f800, ABSOLUTE)
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x20000000   0x30005f60   0x0000001c   Code   RO           17    .criticalFunc       critical_code.o
 
    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b60, Max: 0x00fbdc00, ABSOLUTE, FIXED)
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x30005428   0x30005428   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o
    0x30005448   0x30005448   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o
    0x3000546c   0x3000546c   0x00000004   PAD
===============================================================================
Image component sizes
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
        96         56          0          0          0        903   critical_code.o

2.2 自定义p指定函数 - 针对同一文件里的多个函数

第二种方法是利用 #pragma 语法来修饰函数定义(注意 AC5 编译器 Armcc 和 AC6 编译器 Armclang 语法不太一样),将同一源文件里紧挨在一起的多个关键函数放到自定义段里。比如我们将 critical_func1() 和 critical_func2() 函数放到名为 .criticalFunc 的自定义段里:

#pragma clang p text = ".criticalFunc"  // 适用 AC6 编译器(范围开始)
//#pragma arm p code = ".criticalFunc"  // 适用 AC5 编译器(范围开始)
void critical_func1(uint32_t n)
{
    PRINTF("Arg = %d .\r\n", n);
}
void critical_func2(uint32_t n)
{
    PRINTF("Arg * 2 = %d .\r\n", 2 * n);
}
#pragma clang p text = ""   // 适用 AC6 编译器(范围结束)
//#pragma arm p code        // 适用 AC5 编译器(范围结束)
void critical_func3(uint32_t n)
{
    PRINTF("Arg * 3 = %d .\r\n", 3 * n);
}

然后也是同样在工程链接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 里将这个自定义的 p .criticalFunc 也放进 RW_m_data 执行域中:

LR_m_text 0x30002000 0x00FFE000 {
  ; ...
  RW_m_data 0x20000000 0x0003F800 {
    .ANY (+RW +ZI)
    * (.criticalFunc)  ;添加 .criticalFunc 段
  }
  ; ...
}

编译链接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相关的内容如下,此时 critical_func1/2() 均已经被放到自定义段 .criticalFunc 里,并且这个段被 MDK 底层链接器链接到了 RAM 里(RW_m_data 执行域空间)。

===============================================================================
Image Symbol Table
    Global Symbols
    Symbol Name                              Value     Ov Type        Size  Object(Section)
    critical_func1                           0x20000001   Thumb Code    28  critical_code.o(.criticalFunc)
    critical_func2                           0x20000021   Thumb Code    32  critical_code.o(.criticalFunc)
    critical_func3                           0x30005429   Thumb Code    36  critical_code.o(.text.critical_func3)
===============================================================================
Memory Map of the image
    Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30005f50, Size: 0x0000009c, Max: 0x0003f800, ABSOLUTE)
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x20000000   0x30005f50   0x00000040   Code   RO           17    .criticalFunc       critical_code.o
 
    Execution Region ER_m_text (Exec base: 0x30002400, Load base: 0x30002400, Size: 0x00003b4c, Max: 0x00fbdc00, ABSOLUTE, FIXED)
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x30005428   0x30005428   0x00000024   Code   RO           19    .text.critical_func3  critical_code.o
    0x3000544c   0x3000544c   0x00000004   PAD
===============================================================================
Image component sizes
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
       100         60          0          0          0        887   critical_code.o

2.3 针对源文件中全部函数

前两种重定向方法都是针对具体函数的(如果是多个关键函数分散在多个文件里,按方法逐一添加修饰当然也行),但如果某个库源文件特别多,并且我们希望将这些源文件里函数全部重定向到 RAM 里,有没有更便捷的方法呢?当然有!

我们现在将 critical_code.c 文件里全部函数都重定向,只需要在工程链接文件 MIMXRT1176xxxxx_cm7_flexspi_nor.scf 里做如下修改:

LR_m_text 0x30002000 0x00FFE000 {
  ; ...
  RW_m_data 0x20000000 0x0003F800 {
    .ANY (+RW +ZI)
    critical_code.o (+RO +RW +ZI)  ;添加 critical_code.o 全部目标
  }
  ; ...
}

编译链接修改后的工程,然后查看其映射文件(hello_world_demo_cm7.map)找到跟 critical_code.c 文件相关的内容如下,此时 critical_func1/2/3() 都链接在 RAM 里了。

===============================================================================
Image Symbol Table
    Global Symbols
    Symbol Name                              Value     Ov Type        Size  Object(Section)
    critical_func1                           0x20000001   Thumb Code    28  critical_code.o(.text.critical_func1)
    critical_func2                           0x20000021   Thumb Code    32  critical_code.o(.text.critical_func2)
    critical_func3                           0x20000041   Thumb Code    36  critical_code.o(.text.critical_func3)
===============================================================================
Memory Map of the image
    Execution Region RW_m_data (Exec base: 0x20000000, Load base: 0x30005f30, Size: 0x000000c0, Max: 0x0003f800, ABSOLUTE)
    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object
    0x20000000   0x30005f30   0x0000001c   Code   RO           17    .text.critical_func1  critical_code.o
    0x2000001c   0x30005f4c   0x00000004   PAD
    0x20000020   0x30005f50   0x00000020   Code   RO           19    .text.critical_func2  critical_code.o
    0x20000040   0x30005f70   0x00000024   Code   RO           21    .text.critical_func3  critical_code.o
===============================================================================
Image component sizes
      Code (inc. data)   RO Data    RW Data    ZI Data      Debug   Object Name
        96         56          0          0          0        903   critical_code.o
  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值