使用RTT Studio指定特殊函数加载到RAM的方法

一, RTT Studio 指定特殊函数到RAM的作用

用ITCM给ART-Pi(STM32H7)代码加速 , 这篇文章就提到了,将特殊的函数(如,算法相关)加载到速度更快的 ITCM,但是这篇文章中使用 GCC 编译器的时候,无法保证在断电复位后 RAM 段的代码不消失,所以本文来研究这个问题。
众所周知,RAM 是掉电丢失数据的,为了做到产品中也能使用这种操作,就需要将代码编译到 ROM 中,然后启动的时候,从 ROM 拷贝到 RAM 当中,知道了原理,具体如何操作呢?

二, RTT Studio 指定特殊函数到RAM的办法

为了实现这种操作,需要知道可执行程序的生成过程,预处理- >编译 ->汇编-> 链接,可以从这几个地方去着手解决这个问题。RTT Studio 使用的是 GCC 的编译器,所以修改相应的 GCC 文件就可以了。

1. 修改链接文件

为了实现这个目的,所以需要在链接文件中增加对应的 .section.

描述 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 =0x00000000,LENGTH =64k
}

ITCM (rx) :名字是 ITCM,r: Read-only sections. , x : Sections containing executable code.
ORIGIN =0x00000000 : 起始地址
LENGTH =64k : 总长度

构造 section

SECTIONS
{   
    .text :
    {
        . = ALIGN(4);
        _stext = .;
        KEEP(*(.isr_vector))            /* Startup code */
        . = ALIGN(4);
        *(.text.*)
        *(.rodata)                      /* read-only data (constants) */
        *(.rodata*)
        *(.glue_7)
        *(.glue_7t)
        *(.gnu.linkonce.t*)

        /* section information for finsh shell */
        . = ALIGN(4);
        __fsymtab_start = .;
        KEEP(*(FSymTab))
        __fsymtab_end = .;

        . = ALIGN(4);
        __vsymtab_start = .;
        KEEP(*(VSymTab))
        __vsymtab_end = .;

        /* section information for utest */
        . = ALIGN(4);
        __rt_utest_tc_tab_start = .;
        KEEP(*(UtestTcTab))
        __rt_utest_tc_tab_end = .;

        /* section information for at server */
        . = ALIGN(4);
        __rtatcmdtab_start = .;
        KEEP(*(RtAtCmdTab))
        __rtatcmdtab_end = .;
        . = ALIGN(4);

        /* section information for modules */
        . = ALIGN(4);
        __rtmsymtab_start = .;
        KEEP(*(RTMSymTab))
        __rtmsymtab_end = .;

        /* section information for initial. */
        . = ALIGN(4);
        __rt_init_start = .;
        KEEP(*(SORT(.rti_fn*)))
        __rt_init_end = .;

        . = ALIGN(4);

        PROVIDE(__ctors_start__ = .);
        KEEP (*(SORT(.init_array.*)))
        KEEP (*(.init_array))
        PROVIDE(__ctors_end__ = .);

        . = ALIGN(4);

        _etext = .;
    } > ROM
    
    .ITCM :
    {
        . = ALIGN(4);
        __itcm_start = .;
        *(.ITCM)
        . = ALIGN(4);
        __itcm_end = .;
    } > ITCM AT>ROM
    __itcm_rom_start = LOADADDR(.ITCM);
    __itcm_size = SIZEOF(.ITCM);

这里链接文件的修改的作用是,将 __attribute__((section(".ITCM"))) int main(void) 这种指定函数到特殊区域的 ITCM 段的函数,编译后放到 ROM 里面,程序运行的时候从 RAM 取这个函数,这样可以在系统上电之后可以从 ROM 中把数据复制到 RAM 当中,这样就解决了上一篇文章的问题。这里定义了 2 个全局变量方便后续在汇编当中把函数从 ROM 拷贝到 RAM。

2. 修改启动汇编

startup_stm32h750xx.s 这里只做了,已初始化值的数据,从 ROM 拷贝到 RAM 的操作,所以需要增加一些代码来实现把函数从 ROM 拷贝到 RAM
修改部分:

Reset_Handler:   /* 程序复位后的启动地址 */
  ldr   sp, =_estack      /* 设置 SP */

  ldr r0 ,=__itcm_rom_start  /* 加载 放在了 ROM 当中,需要加载到 ITCM 中数据的起始地址到 R0 */
  ldr r1 ,=__itcm_start /* 加载 ITCM 第一个函数的起始放置位置到 R1 */
  ldr r2 ,=__itcm_size /* 加载 ITCM 的大小到 R2 */
  add r2 , r1, r2  /* R1 加 R2 的值 放到 R2 */

1:
  cmp r2, r1  /* 比较 R1 与 R2 */
  beq 2f /* 如果上面的比较之后是相等的 则跳转到标签 2  */
  ldr r3 ,[r0],#4 /*  将 R0 寄存器里面存放的地址处的代码,写入到 R3 寄存器里面。然后 R0 + 4 */
  str r3 ,[r1],#4 /* 将R3中的数据写入以R1为地址的存储器中,然后 R1 + 4*/
  b 1b /* 调回到标签 1,循环拷贝 */
2: /* 以下是未修改之前的 GCC 启动汇编代码 */

/* Copy the data segment initializers from flash to SRAM */  
  movs  r1, #0
  b  LoopCopyDataInit

这里使用了数字标签,所以跳转时候标签后缀为b或f,b==back ,f == forward。
这里的拷贝方法就是,知道程序下载之后放在了 ROM 的位置,然后从这个位置拷贝到 RAM 中去。

3. 将函数指定链接位置

__attribute__((section(".ITCM")))
int main(void)
{
    rt_uint32_t count = 0;
    
    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
}

三, 总结

  1. 用ITCM给ART-Pi(STM32H7)代码加速 提到的方法,MDK 可以实现启动的时候将 ROM 中的函数搬运到 RAM 当中的操作,使用 RTT Studio 也可以实现
  2. 在 GCC 的链接文件可以描述一个文件的 section 的中数据的存放地址和加载地址不一致。
  3. 在 RTT Studio 中实现这个操作,确实比 MDK 会复杂很多,对于研究底层的人而言,在 MDK 中很难看到这些细节,喜欢自定义操作的人而言,GCC 就更加的灵活了。
  • 3
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值