欢迎您访问 最编程 本站为您分享编程语言代码,编程技术文章!
您现在的位置是: 首页

如何在RT-Thread Studio中将特定函数装载到RAM的步骤指南

最编程 2024-02-12 08:28:46
...


用ITCM给ART-Pi(STM32H7)代码加速 , 这篇文章就提到了,将特殊的函数(如,算法相关)加载到速度更快的 ITCM,但是这篇文章中使用 GCC 编译器的时候,无法保证在断电复位后 RAM 段的代码不消失,所以本文来研究这个问题。

众所周知,RAM 是掉电丢失数据的,为了做到产品中也能使用这种操作,就需要将代码编译到 ROM 中,然后启动的时候,从 ROM 拷贝到 RAM 当中,知道了原理,具体如何操作呢?

二、RT-Thread Studio 指定特殊函数到RAM的办法

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

1. 修改链接文件

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

描述 ITCM 的属性

1MEMORY
2{
3ROM (rx) : ORIGIN =0x90000000,LENGTH =8192k
4RAM (rw) : ORIGIN =0x24000000,LENGTH =512k
5RxDecripSection (rw) : ORIGIN =0x30040000,LENGTH =32k
6TxDecripSection (rw) : ORIGIN =0x30040060,LENGTH =32k
7RxArraySection (rw) : ORIGIN =0x30040200,LENGTH =32k
8ITCM (rx) : ORIGIN =0x00000000,LENGTH =64k
9}


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

构造 section

 1SECTIONS
2{   
3    .text :
4    {
5        . = ALIGN(4);
6        _stext = .;
7        KEEP(*(.isr_vector))            /* Startup code */
8        . = ALIGN(4);
9        *(.text.*)
10        *(.rodata)                      /* read-only data (constants) */
11        *(.rodata*)
12        *(.glue_7)
13        *(.glue_7t)
14        *(.gnu.linkonce.t*)
15
16        /* section information for finsh shell */
17        . = ALIGN(4);
18        __fsymtab_start = .;
19        KEEP(*(FSymTab))
20        __fsymtab_end = .;
21
22        . = ALIGN(4);
23        __vsymtab_start = .;
24        KEEP(*(VSymTab))
25        __vsymtab_end = .;
26
27        /* section information for utest */
28        . = ALIGN(4);
29        __rt_utest_tc_tab_start = .;
30        KEEP(*(UtestTcTab))
31        __rt_utest_tc_tab_end = .;
32
33        /* section information for at server */
34        . = ALIGN(4);
35        __rtatcmdtab_start = .;
36        KEEP(*(RtAtCmdTab))
37        __rtatcmdtab_end = .;
38        . = ALIGN(4);
39
40        /* section information for modules */
41        . = ALIGN(4);
42        __rtmsymtab_start = .;
43        KEEP(*(RTMSymTab))
44        __rtmsymtab_end = .;
45
46        /* section information for initial. */
47        . = ALIGN(4);
48        __rt_init_start = .;
49        KEEP(*(SORT(.rti_fn*)))
50        __rt_init_end = .;
51
52        . = ALIGN(4);
53
54        PROVIDE(__ctors_start__ = .);
55        KEEP (*(SORT(.init_array.*)))
56        KEEP (*(.init_array))
57        PROVIDE(__ctors_end__ = .);
58
59        . = ALIGN(4);
60
61        _etext = .;
62    } > ROM
63
64    .ITCM :
65    {
66        . = ALIGN(4);
67        __itcm_start = .;
68        *(.ITCM)
69        . = ALIGN(4);
70        __itcm_end = .;
71    } > ITCM AT>ROM
72    __itcm_rom_start = LOADADDR(.ITCM);
73    __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
修改部分:

 1Reset_Handler:   /* 程序复位后的启动地址 */
2  ldr   sp, =_estack      /* 设置 SP */
3
4  ldr r0 ,=__itcm_rom_start  /* 加载 放在了 ROM 当中,需要加载到 ITCM 中数据的起始地址到 R0 */
5  ldr r1 ,=__itcm_start /* 加载 ITCM 第一个函数的起始放置位置到 R1 */
6  ldr r2 ,=__itcm_size /* 加载 ITCM 的大小到 R2 */
7  add r2 , r1, r2  /* R1 加 R2 的值 放到 R2 */
8
91:
10  cmp r2, r1  /* 比较 R1 与 R2 */
11  beq 2f /* 如果上面的比较之后是相等的 则跳转到标签 2  */
12  ldr r3 ,[r0],#4 /*  将 R0 寄存器里面存放的地址处的代码,写入到 R3 寄存器里面。然后 R0 + 4 */
13  str r3 ,[r1],#4 /* 将R3中的数据写入以R1为地址的存储器中,然后 R1 + 4*/
14  b 1b /* 调回到标签 1,循环拷贝 */
152/* 以下是未修改之前的 GCC 启动汇编代码 */
16
17/* Copy the data segment initializers from flash to SRAM */  
18  movs  r1, #0
19  b  LoopCopyDataInit


这里使用了数字标签,所以跳转时候标签后缀为b或f,b==back ,f == forward。

这里的拷贝方法就是,知道程序下载之后放在了 ROM 的位置,然后从这个位置拷贝到 RAM 中去。

3. 将函数指定链接位置

1__attribute__((section(".ITCM")))
2int main(void)
3
{
4    rt_uint32_t count = 0;
5
6    rt_pin_mode(LED_PIN, PIN_MODE_OUTPUT);
7}


三, 总结

1、用ITCM给ART-Pi(STM32H7)代码加速 提到的方法,MDK 可以实现启动的时候将 ROM 中的函数搬运到 RAM 当中的操作,使用 RTT Studio 也可以实现

2、在 GCC 的链接文件可以描述一个文件的 section 的中数据的存放地址和加载地址不一致。

3、在 RT-Thread Studio 中实现这个操作,确实比 MDK 会复杂很多,对于研究底层的人而言,在 MDK 中很难看到这些细节,喜欢自定义操作的人而言,GCC 就更加的灵活了。

 


  


邀请你参加 2021 RT-Thread 开发者大会的七大理由

1、刷新RT-Thread最新技术动态和产业服务能力

2、聆听行业大咖分享,洞察产业趋势

4、丰富的技术和产品展示,前沿技术发展和应用

5、绝佳的实践机会:从MCU、AIOT、MPU、RISC-V、安全总有一个应用场景满足你

6、现场揭晓开发者专属纪念胸牌升级和新玩法

7、互动区体验掌握技术带来的魅力



立即长按识别下方二维码报名


   

你可以添加微信17775982065为好友,注明:公司+姓名,拉进RT-Thread官方微信交流群!



???? 阅读原文