RTOS和GUI_基于英飞凌tc2x及stm32开发板

iar设置函数跑在ram中加速运行--Apple的学习笔记

2023-07-05  本文已影响0人  applecai

一,前言

让代码跑在ram中的情况主要为了执行速度快。在c代码中添加段有3种方法。而我主要学习链接脚本的修改方法。因为这类操作我曾经没用过。就拿之前stm32做的iar timer中断工程来实验。

二,实验

实验概览:主要目的是完成5个自定义小需求,以此来提升应用技巧。


image.png
  1. 实验对象是main.c中的testfun函数,正常情况函数放代码段就是0x8xx的。
main                     0x800'071d  0x2c  Code  Gb  main.o [1]
testcnt                 0x2000'00ce   0x1  Data  Gb  main.o [1]
testfun                  0x800'070d   0xa  Code  Gb  main.o [1]
  1. 添加关键字__ramfunc改成__ramfunc void testfun(void)后编译,看到testfun的函数地址变为0x2xx的sram了。但是位置是自动分配的。
main                     0x800'0741  0x2c  Code  Gb  main.o [1]
testcnt                 0x2000'00de   0x1  Data  Gb  main.o [1]
testfun                 0x2000'0001  0x10  Code  Gb  main.o [1]

在ram中运行的代码,应该是先保存在flash中,然后flash中copy到ram中,能看到如下说明testfun函数保存的flash地址是0x8000980,运行的ram地址是0x20000000

Copy (__iar_copy_init3)
    1 source range, total size 0x10:
           0x800'0980  0x10
    1 destination range, total size 0x10:
          0x2000'0000  0x10
  1. 我们常见的应用中不可能只有一个函数,另外就是一般都会设计sector段来规范模块区域,而非让它自动分配地址。所以我要加一个rw sector段把函数放入固定ram位置。
    修改icf链接文件
a.  把段名.APsramfun添加从rom自动copy到ram
initialize by copy { readwrite,section .APsarmfun };
b.  定义一个block作为这个段名的专属block
define block APramfun  with alignment = 32, size = 1K     {section .APsarmfun};
c.  将block放入自定义的sram区域
place in SRAM_region_my {block APramfun};
define region SRAM_region_my  =   mem:[from __ICFEDIT_region_SRAM2_start__  to __ICFEDIT_region_SRAM2_end__ ];

代码中函数首尾添加段区域名

#pragma default_function_attributes = @".APsarmfun"
/*#pragma location = ".APsarmfun"*/
/*__ramfunc void testfun(void)*/
void testfun(void)
{
  testcnt++;
}
#pragma default_function_attributes =

检查编译的map文件,地址正确是sram2的首地址0x2001C000,怎么从1开始的?原来首尾是自动创建的,用于copy用途时候获取首尾地址。那么是正确的。

APramfun$$Base          0x2001'c000         --   Gb  - Linker created -
APramfun$$Limit         0x2001'c400         --   Gb  - Linker created –

main                     0x800'0741  0x2c  Code  Gb  main.o [1]
testcnt                 0x2000'00ce   0x1  Data  Gb  main.o [1]
testfun                 0x2001'c001  0x10  Code  Gb  main.o [1]

ram的位置固定到我预期的sram2区域了,不是自动分配了。

Copy (__iar_copy_init3)
    1 source range, total size 0x10:
           0x800'0834  0x10
    1 destination range, total size 0x10:
          0x2001'c000  0x10
  1. 把函数放入ram的期望的地址段问题已解决,但是函数在rom中的位置不是固定的,若要把rom位置也固定到自定义区域如何设置呢?
    看了example及help文档,想想确实函数和data一样的操作方法,data不是bss,所以需要从rom复制初始化值到ram。按help一般都添加后缀_init,同一个.data拆分2个其中带后缀_init的放入ROM即可。


    image.png

    实战了,先添加一个rom的内存区域,在添加一个rom的block。最重要的就是sector要加后缀_init

define block APromfun  with alignment = 32,size = 1K {section .APsarmfun_init};

生成的map文件中能看到rom也变成了预期的位置了,从0x80f0000开始

Copy (__iar_copy_init3)
    1 source range, total size 0x10:
           0x80f'0000  0x10
    1 destination range, total size 0x10:
          0x2001'c000  0x10
  1. 那么以前使用的链接文件,直接在代码中不加段名,也可以把代码放在固定段,直接把o文件或lib文件放入block即可,iar的链接文件应该也是支持的,但是要做成在ram中运行o文件中所有函数,那个_init和o文件应该怎么挂钩呢!
    在帮助中找到了。sql数据库筛选都玩过吧,多条件的组合。如下筛选就是与的条件关系,正好满足我的需求某个o文件的只读属性,然后再与上sector,逐步缩小范围。


    image.png

    来实战了,按如下添加文件中的筛选组合段到block中,完美解决问题。main中的2个函数都放入ram运行,且存储在rom中都是从0x80f0000地址开始的。
    在ram的block中添加readonly code object main.o筛选组合段
    在对应rom的block中添加readonly code section *_init object main.o筛选组合段
    在自动copy中添加readonly code object main.o筛选组合段

Copy (__iar_copy_init3)
    1 source range, total size 0x64:
           0x80f'0000  0x64
    1 destination range, total size 0x64:
          0x2000'0000  0x64

main                    0x2000'0039  0x2c  Code  Gb  main.o [1]
testcnt                 0x2000'0132   0x1  Data  Gb  main.o [1]
testfun                 0x2000'0029   0xa  Code  Gb  main.o [1]
  1. 我要把main.o的一个文件改成多个文件,进行批处理,那么就是用模糊文件名即可,如下main.o改成了stm32f4xx为前缀的所有这些文件中的所有函数都copy到ram中运行。
define block APramfun  with alignment = 32,size = 1K {section .APsarmfun,readonly code object stm32f4xx*.o};
define block APromfun  with alignment = 32,size = 1K {section .APsarmfun_init,readonly code section *_init object stm32f4xx*.o};
initialize by copy { readwrite,section .APsarmfun,readonly code object stm32f4xx*.o };

生成的map文件中stm32f4xx*.c文件中所有函数的地址都是0x2001c开头符合预期

TIM_ClearITPendingBit   0x2001'c0cd   0x6  Code  Gb  stm32f4xx_tim.o [1]
TIM_Cmd                 0x2001'c069  0x1a  Code  Gb  stm32f4xx_tim.o [1]
TIM_GetITStatus         0x2001'c0b5  0x18  Code  Gb  stm32f4xx_tim.o [1]
TIM_ITConfig            0x2001'c0a1  0x14  Code  Gb  stm32f4xx_tim.o [1]
TIM_TimeBaseInit        0x2001'c001  0x68  Code  Gb  stm32f4xx_tim.o [1]
USART1_IRQHandler        0x800'04b9  0x68  Code  Gb  usart.o [1]
USART_GetITStatus       0x2001'c0ed  0x46  Code  Gb  stm32f4xx_usart.o [1]
USART_RX_BUF            0x2000'00ac  0xc8  Data  Gb  usart.o [1]
USART_RX_STA            0x2000'0174   0x2  Data  Gb  usart.o [1]
USART_ReceiveData       0x2001'c0e5   0x8  Code  Gb  stm32f4xx_usart.o [1]
UsageFault_Handler      0x2001'c0db   0x2  Code  Gb  stm32f4xx_it.o [1]

三,小结

完美解决所有自己提出的需求,我把需求的难度一步步提高,然后跟着help文档去找解决方案,通过做实验来闭环验证理解。every thing under the control,这种感觉真好~

上一篇 下一篇

猜你喜欢

热点阅读