使用ITCM给ART-Pi(STM32H7)代码加速

一 ITCM 简介

ART-Pi 使用 STM32H750 做为主控。 STM32H7 使用的是 Cortex_M7 架构,中自带了ITCM(Instruction tightly coupled RAM)。下图可以看到 ITCM 与 Cortex_M7 内核直连,可实现 0 等待状态。
在这里插入图片描述

TCM RAM 与 CPU 是同频,其他 AHB 总线无法做到和 CPU 同频,所以使用 TCM 可以获得更好的性能。
虽然 TCM 的速度很快,但是他也有缺点,例如 DTCM 不能使用 DMA1 DMA2,ITCM 只能作为指令 RAM。
要使用 ITCM 得先知道他的地址:
在这里插入图片描述
通过上图可以看到 ITCM 的区域是 0x00000000 - 0x0000FFFF 的 64K。ITCM 从 0 地址就很尴尬了,一般在程序判断 NULL 就是用的 0 地址,所以最好的办法就是避开起始地址,为了某些情况下对齐操作,建议从 0x00000008 地址开始使用。

二 ITCM 在不同编译器下的使用

一个可执行程序是由 编译 --> 链接 这个过程的产生的。如何将函数指定到 ITCM ,其实就是将函数链接的地址设置在 ITCM 区域就可以了。
本文以 ART-Pi-LED 的示例代码来展示这一过程。

在 RTT Studio 中如何使用 ITCM

RTT Studio 中使用的编译器为 :GCC ,所以直接按照 GCC 链接脚本的方式去定义就好了。

在 RTT Studio 中如何指定某个函数到指定地址,需要三个步骤:

第一步:在链接文件中增加一个 ITCM 的描述信息

MEMORY
{
ROM (rx) : ORIGIN =0x90000000,LENGTH =8192k
RAM (rw) : ORIGIN =0x24000000,LENGTH =512k
RxDecripSection (rw) : ORIGIN =0x30040000,LENGTH =32k
TxDecripSection (rw) : ORIGIN =0x30040060,LENGTH =32k
RxArraySection (rw) : ORIGIN =0x30040200,LENGTH =32k
ITCM (rx) : ORIGIN =0x00000008,LENGTH =64k
}

最后一行增加了 ITCM 的描述信息

第二步:在链接文件中 SECTIONS 中增加 ITCM 的信息

SECTIONS
{   
    .ITCM :
    {
    . = ALIGN(4);
    *(.ITCM)
    *(.ITCM.*)
    . = ALIGN(4);
    } > ITCM = 0
    
    .text :
    {
        . = ALIGN(4);
        _stext = .;
        KEEP(*(.isr_vector))            /* Startup code */
     .
     .
     .
     }
 }

这里需要注意的是新增加的 .ITCM 一定要放到 .text 的前面

第三步,指定函数到 ITCM

__attribute__((section(".ITCM")))int main(void)
{
    rt_uint32_t count = 0;

    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
    
    rt_kprintf("main adderss is 0x%08x\r\n",main);
    rt_thread_mdelay(500);

    led_light();
}

在修改之后重新 build 工程,查看 map 文件

 *(.ITCM)
 .ITCM          0x00000008       0x3c ./applications/main.o
                0x00000008                main

可以看到 main 函数的地址已经被指定到 ITCM 的区域。

在 RTT Studio 中如何某个文件夹的所有函数到指定地址,需要两个步骤:

第一步:在链接文件中增加一个 ITCM 的描述信息

MEMORY
{
ROM (rx) : ORIGIN =0x90000000,LENGTH =8192k
RAM (rw) : ORIGIN =0x24000000,LENGTH =512k
RxDecripSection (rw) : ORIGIN =0x30040000,LENGTH =32k
TxDecripSection (rw) : ORIGIN =0x30040060,LENGTH =32k
RxArraySection (rw) : ORIGIN =0x30040200,LENGTH =32k
ITCM (rx) : ORIGIN =0x00000008,LENGTH =64k
}

最后一行增加了 ITCM 的描述信息

第二步:在链接文件中 SECTIONS 中增加 ITCM 的信息

SECTIONS
{   
    .ITCM :
    {
    . = ALIGN(4);
    ./applications/main.o (.text*)
    *(.ITCM)
    *(.ITCM.*)
    . = ALIGN(4);
    } > ITCM = 0
    
    .text :
    {
        . = ALIGN(4);
        _stext = .;
        KEEP(*(.isr_vector))            /* Startup code */
     .
     .
     .
     }
 }

这里将 ./applications/main.o 中的 .text 段都放入到了 ITCM

查看 map 文件

 .text.led_light
                0x00000024       0x38 ./applications/main.o
                0x00000024                led_light
 .text.main     0x0000005c       0x3c ./applications/main.o
                0x0000005c                main
 .text.vtor_config
                0x00000098       0x1c ./applications/main.o

可以看到 main.c 中的文件都被定义到了 ITCM 段

在 MDK 中如何使用 ITCM

在 MDK 中也需要修改对用的链接文件

在 MDK 中如何指定某个函数到指定地址,需要二个步骤:

第一步,修改链接文件

LR_IROM1 0x90000000 0x00800000  {    ; load region size_region
  ER_IROM1 0x90000000 0x00800000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM0 0x00000008 0x0000FFF8  {  ; ITCM 64K
   *(.ITCM)
  }
  RW_IRAM1 0x24000000 0x00080000  {  ; AXI SRAM 512K
   .ANY (+RW +ZI)
  }
}

增加 ITCM 的描述

第二步,指定函数到 ITCM

__attribute__((section(".ITCM")))  void led_light(void)
{
    rt_kprintf("main adderss is 0x%08x\r\n",led_light);
    while(1)
    {
        rt_thread_mdelay(500);
        rt_pin_write(LED_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED_PIN, PIN_LOW);
    }
}

查看 map 文件

led_light                                0x00000009   Thumb Code    46  main.o

可以看到 led_light 函数已经被放到 ITCM 区域

在 MDK 中如何某个C文件的某些函数到指定地址,需要二个步骤:

第一步,修改链接文件

LR_IROM1 0x90000000 0x00800000  {    ; load region size_region
  ER_IROM1 0x90000000 0x00800000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM0 0x00000008 0x0000FFF8  {  ; ITCM 64K
   *(.ITCM)
  }
  RW_IRAM1 0x24000000 0x00080000  {  ; AXI SRAM 512K
   .ANY (+RW +ZI)
  }
}

增加 ITCM 的描述

第二步,指定某些函数到 ITCM

可以在这些函数的前面和结束之后地方加上关键字,如下所示:

#pragma arm section code = ".ITCM"
void led_light(void)
{
    rt_kprintf("main adderss is 0x%08x\r\n",led_light);
    while(1)
    {
        rt_thread_mdelay(500);
        rt_pin_write(LED_PIN, PIN_HIGH);
        rt_thread_mdelay(500);
        rt_pin_write(LED_PIN, PIN_LOW);
    }
}


int main(void)
{
    rt_uint32_t count = 0;

    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
    
    rt_kprintf("main adderss is 0x%08x\r\n",main);
    rt_thread_mdelay(500);

    led_light();

    return RT_EOK;
}
#pragma arm section

查看 map 文件

    led_light                                0x00000009   Thumb Code    
    $Super$$main                             0x00000037   Thumb Code 

三 注意事项

大家都知道 RAM 是掉电易失的,这种加速的方法如何在量产产品中使用呢?实际上使用以上的方法,MDK 会将特定的函数编译到 ROM 当中,在每次启动的时候都会将 ROM 中指定的函数拷贝到 RAM 放中。
但是上面的方法在 RTT Studio 中只会将函数写到指定的 RAM,这样掉电就丢失了,后续我会继续研究 RTT Studio 实现这个操作。

  • 10
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值