你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

【经验分享】STM32H7在RT-Thread上的多内存使用方法

[复制链接]
STMCU小助手 发布时间:2021-12-27 18:00
一,STM32H7 RAM介绍
使用过STM32H7的朋友应该知道H7的RAM是有很多的区域的,不同的区域,使用了不同的总线,所能支持的外设也就不一样了,具体的总线结构如下图所示
2020021922201274.jpg


20200219221709559.jpg


通过上图和上表就能发现如果要使用DMA就必须对多RAM进行管理,要么自己去实现内存管理,要么通过__attribute__ 关键字去定义,这样或多或少会有些麻烦,后来看到安福莱STM32H743动态内存管理,同时分区管理AXI RAM,DTCM,SRAM1等五块空间 这篇文章,想到RT-Thread 肯定也应该是支持多内存管理的,看到查看官方的文档中心发现 可以使用 memheap 管理算法。

20200219224822144.jpg


既然RT-Thread 已经支持了多内存的管理算法,那么接下来就要考虑一个问题,RT-Thread是默认使能HEAP,且RT-Thread很多优秀的组件都使用了动态内存,所以要解决究竟是哪一块内存分给rt_malloc 使用。

二 多RAM管理办法
STM32H7的内存可用内存有很多,DTCM和AXI SRAM使用哪一个作为主heap呢?本文分别对DTCM和AXI SRAM做主heap来进行介绍。
首先找到RT-Thread bsp/stm32/目录下的stm32h7的支持包,通过ENV工具打开 memheap

20200219230749268.jpg


之后重新生成工程。

1,TCM区域做为主heap
TCM区域的优势是速度快,仅仅只支持MDMA的访问,但是内存小只有128K,不支持其他DMA的访问

  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.       ; *************************************************************
  2. ; *** Scatter-Loading Description File generated by uVision ***
  3. ; *************************************************************

  4. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
  5.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
  6.    *.o (RESET, +First)
  7.    *(InRoot$Sections)
  8.    .ANY (+RO)
  9.   }
  10.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data
  11.    .ANY (+RW +ZI)
  12.   }
  13. }
复制代码
  1. 第三步 写一个axi_sram.c
复制代码
  1. struct rt_memheap axi_sram_heap;
  2. void *axi_sram_malloc(unsigned long size)
  3. {
  4.     return rt_memheap_alloc(&axi_sram_heap,size);
  5. }

  6. void axi_sram_free(void *ptr)
  7. {
  8.     rt_memheap_free(ptr);
  9. }

  10. void *axi_sram_calloc(unsigned int n,unsigned int size)
  11. {
  12.     void* ptr = NULL;

  13.     ptr = axi_sram_malloc(n * size);
  14.     if(ptr)
  15.     {
  16.         memset(ptr, 0, n*size);
  17.     }

  18.     return ptr;
  19. }
复制代码
  1. 第四步 修改drv_common.c,增加一行axi_sram初始化的代码
复制代码
  1.   #if defined(RT_USING_HEAP)
  2.     rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
  3. #endif

  4.     rt_memheap_init(&axi_sram_heap,"AXISRAM",(void *)RT_AXI_SRAM_BEGIN,RT_AXI_SRAM_SIZE);   
复制代码
编写一个测试代码

  1. int main(void)
  2. {
  3.     int count = 1;
  4.     /* set LED0 pin mode to output */
  5.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);

  6.     char *test_ptr;

  7.     while (count++)
  8.     {
  9.         test_ptr = axi_sram_malloc(100);
  10.         rt_pin_write(LED0_PIN, PIN_HIGH);
  11.         rt_thread_mdelay(500);
  12.         rt_pin_write(LED0_PIN, PIN_LOW);
  13.         rt_thread_mdelay(500);
  14.         axi_sram_free(test_ptr);
  15.     }
  16.     return RT_EOK;
  17. }
复制代码

编译一下
  1. Program Size: Code=55136 RO-data=7508 RW-data=548 ZI-data=4060  
  2. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
  3. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 0 Warning(s).
  4. Build Time Elapsed:  00:00:08
复制代码

没有错误,没有警告,下载正常运行。

2,AXI SRAM区域作为主heap
AXI区域 的主要优势是内存大 512K ,支持DMA1 DMA2 IDMA的访问,劣势不如TCM速度快

  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.   ; *************************************************************
  2. ; *** Scatter-Loading Description File generated by uVision ***
  3. ; *************************************************************

  4. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
  5.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
  6.    *.o (RESET, +First)
  7.    *(InRoot$Sections)
  8.    .ANY (+RO)
  9.   }
  10.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data
  11.    .ANY (+RW +ZI)
  12.   }
  13.   RW_IRAM_HEAP 0x24000000 0x00080000  {  ; RW data
  14.    *(.RAM_HEAP)
  15.   }
  16. }
复制代码
  1. 第二步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (128)
  2. #define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)

  3. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  4. extern int Image$RW_IRAM1$ZI$Limit;
  5. #define HEAP_BEGIN      (&Image$RW_IRAM1$ZI$Limit)
  6. #elif __ICCARM__
  7. #pragma section="CSTACK"
  8. #define HEAP_BEGIN      (__segment_end("CSTACK"))
  9. #else
  10. extern int __bss_end;
  11. #define HEAP_BEGIN      (&__bss_end)
  12. #
复制代码
  1. 第三步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (512)
  2. #define STM32_SRAM_END            (0x24000000 + STM32_SRAM_SIZE * 1024)

  3. #if defined(__CC_ARM) || defined(__CLANG_ARM)
  4. //extern int Image$RW_IRAM2$ZI$Limit;
  5. #define HEAP_BEGIN      0x24000000//(&Image$RW_IRAM1$ZI$Limit)
  6. #elif __ICCARM__
  7. #pragma section="CSTACK"
  8. #define HEAP_BEGIN      (__segment_end("CSTACK"))
  9. #else
  10. extern int __bss_end;
  11. #define HEAP_BEGIN      (&__bss_end)
  12. #endif
复制代码
设置heap的起始区域是0x24000000区域的512k大小。
修改完毕看一下,来测试一下

  1. #define LED0_PIN    GET_PIN(B, 10)
  2.     uint8_t test_buff[1000]= {0};
  3. int main(void)
  4. {   
  5.     int count = 1;
  6.     /* set LED0 pin mode to output */
  7.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);

  8.     char *test_ptr;
  9.     test_buff[10] = 1;
  10.     while (count++)
  11.     {
  12.         test_ptr = rt_malloc(100);
  13.         rt_pin_write(LED0_PIN, PIN_HIGH);
  14.         rt_thread_mdelay(500);
  15.         rt_pin_write(LED0_PIN, PIN_LOW);
  16.         rt_thread_mdelay(500);
  17.         rt_free(test_ptr);
  18.     }
  19.     return RT_EOK;
  20. }
复制代码

编译一下
  1. Build started: Project: project
  2. *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
  3. Build target 'rtthread'
  4. compiling main.c...
  5. linking...
  6. .\board\linker_scripts\link.sct(15): warning: L6314W: No section matches pattern *(.RAM_HEAP).
  7. Program Size: Code=55084 RO-data=7508 RW-data=548 ZI-data=4964  
  8. Finished: 0 information, 1 warning and 0 error messages.
  9. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
  10. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 1 Warning(s).
  11. Build Time Elapsed:  00:00:02
复制代码

有一处警告 不要紧,查看一下map文件

20200219233304754.jpg


可以看到定义的test_buff是在地址0x20000898的位置。

三 总结分析
实验成功

TCM作为了主heap既使用rt_malloc来分配tcm区域的内存,axi_sram_malloc 来分配 axi区域的内存,但是这种方法存在一个问题,如果在使用DMA的时候,会出现问题,RT-Thread的组件默认使用了rt_malloc去申请内存,如果想正常的使用这种方法,需要更具实际情况去把组件里面的rt_malloc去替换成axi_sram_mallo。

AXI_SRAM做为主heap既使用rt_malloc去分配axi_sram区域的内存。如果要使用tcm区域,那么就直接定义全局变量就可以了。使用这样方法存在的问题就是无法把高速的tcm利用率最大化,优势就是就是不需要重定向RT-Thread组件里面的rt_malloc。



收藏 评论0 发布时间:2021-12-27 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版