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

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

[复制链接]
STMCU小助手 发布时间:2021-12-27 18:00
一,STM32H7 RAM介绍
8 F5 `( ?) r# Y5 P( v使用过STM32H7的朋友应该知道H7的RAM是有很多的区域的,不同的区域,使用了不同的总线,所能支持的外设也就不一样了,具体的总线结构如下图所示
; @/ e8 ]" U* k* x6 Q1 G) V  j
2020021922201274.jpg

- w, l2 ?- w- |/ p  N- R' |" Z* }( ~& w, e- {' b
20200219221709559.jpg
7 f- O3 }  g5 j

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

5 B) J3 L3 u6 R2 [  y
20200219224822144.jpg
0 k  n/ i8 q( {, z$ M
/ B7 v( W0 h7 R& l" t+ ~
既然RT-Thread 已经支持了多内存的管理算法,那么接下来就要考虑一个问题,RT-Thread是默认使能HEAP,且RT-Thread很多优秀的组件都使用了动态内存,所以要解决究竟是哪一块内存分给rt_malloc 使用。
! @" M) P3 C& |7 d
) K2 T# h) V- l二 多RAM管理办法: l$ p7 J" q. ?9 v7 A) S. m
STM32H7的内存可用内存有很多,DTCM和AXI SRAM使用哪一个作为主heap呢?本文分别对DTCM和AXI SRAM做主heap来进行介绍。
% b/ D. S/ Q+ j6 M! ?首先找到RT-Thread bsp/stm32/目录下的stm32h7的支持包,通过ENV工具打开 memheap
) t6 R5 s6 E3 I% [( J0 T* Q1 q. c: o1 F: l3 I3 t
20200219230749268.jpg

$ M7 k! L1 x2 W2 T- v0 p5 G# m, B& ?: s7 N- C. i7 S! D
之后重新生成工程。
2 ^5 p8 V7 C: g1 o/ R- t# e0 N- H; y
1,TCM区域做为主heap& b! f7 {% d( r: W
TCM区域的优势是速度快,仅仅只支持MDMA的访问,但是内存小只有128K,不支持其他DMA的访问
: J, [  b- x2 _: L% k
! H) g( H* R& X+ q
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.       ; *************************************************************# d, N% ?; w- h) N
  2. ; *** Scatter-Loading Description File generated by uVision ***- O  G2 P( Q/ c" h8 `
  3. ; *************************************************************
    8 }; @+ D% e% u0 g. N" W6 P( ?' }9 Z
  4. + E& l9 i: X1 Q4 d2 U$ ]8 x
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region- X( ?) C& H$ K" h! P0 {
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address% k+ I8 P4 E9 ]) Y7 I/ U
  7.    *.o (RESET, +First)
    4 R/ y/ `2 `) B1 n7 \; K5 Y! |, {9 [
  8.    *(InRoot$Sections)
    . F1 h& s6 |# X' W, R( L8 `" [
  9.    .ANY (+RO)
    1 T4 k0 h5 x* M8 _0 x
  10.   }2 m- H( m9 Y3 `" d! ^* P: g
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data9 U9 T1 v  W$ j# J* p
  12.    .ANY (+RW +ZI)- q: X4 c6 G: @8 Z
  13.   }7 W5 B8 _. a. p6 `: H1 u  \% a
  14. }
复制代码
  1. 第三步 写一个axi_sram.c
复制代码
  1. struct rt_memheap axi_sram_heap;
    7 c2 A; ~1 S1 ~; M8 e( f
  2. void *axi_sram_malloc(unsigned long size)
    9 W) G, [1 F; o2 K9 _$ w
  3. {
    # \' e6 k+ v8 U8 A: n
  4.     return rt_memheap_alloc(&axi_sram_heap,size);# T: q) }1 E% z) [. {2 S8 k
  5. }
    5 ?1 k2 i) a( Z/ \

  6. + m! @- x; Q; {! `& {
  7. void axi_sram_free(void *ptr)& h' b/ j' G, f" y
  8. {4 {8 m! R6 y0 y% w3 R
  9.     rt_memheap_free(ptr);9 J0 a" m" Y; c1 q' K3 Y7 l; n6 S
  10. }
    ( q# S3 }/ }& s. K7 [$ F

  11. + F9 X! X  |+ d" B. s, r
  12. void *axi_sram_calloc(unsigned int n,unsigned int size)
    : G. ~8 U* K4 V" d
  13. {# |! w. k3 j# X5 h* |
  14.     void* ptr = NULL;/ E, a* V, Y: L" X3 Q1 P, I2 r

  15. 8 A: z* [7 n, c
  16.     ptr = axi_sram_malloc(n * size);9 _% p7 }( p# o1 K8 d6 c8 K
  17.     if(ptr)
    5 |# E8 J6 [) z% s% ~" f# U
  18.     {- ]7 V4 n3 o3 E
  19.         memset(ptr, 0, n*size);
    " \9 ^1 U! Y! x# c/ B4 |
  20.     }
    ( H! S1 H& i- |" |8 I

  21. + F+ e; _, u9 n
  22.     return ptr;
    . p: y' i. d) U2 F
  23. }
复制代码
  1. 第四步 修改drv_common.c,增加一行axi_sram初始化的代码
复制代码
  1.   #if defined(RT_USING_HEAP)
    5 {  T5 ?$ N" F9 Z# p% B
  2.     rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
    / p. y$ G, {. b, F
  3. #endif
    / ]6 ]2 V5 [  n+ \! E
  4. % E, i/ o8 c6 [0 ]! J4 |1 w
  5.     rt_memheap_init(&axi_sram_heap,"AXISRAM",(void *)RT_AXI_SRAM_BEGIN,RT_AXI_SRAM_SIZE);   
复制代码
编写一个测试代码8 F& k! L* X* v7 M' \0 H
3 n8 B6 y7 ?- S' b
  1. int main(void)
      f2 k3 K2 v* _7 G, ^1 G; h
  2. {
    / ^( v8 ~7 [6 |% G! d
  3.     int count = 1;% p/ h/ N9 B8 |' S0 A( s2 g
  4.     /* set LED0 pin mode to output */
    2 M$ h1 z$ N* s! S8 Z' u5 c
  5.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);* ~" |" O4 i& P4 P' a+ F
  6. - D# c& ~! s4 k0 X2 M% d
  7.     char *test_ptr;
    1 S) T4 q1 X! g: |1 c% Z

  8. ( k1 H* i, L6 d  g% a* f
  9.     while (count++)) V, ~, I3 k+ C3 J+ @8 {$ d: P( ^  ]
  10.     {
    ' `; g5 J6 V, q2 r+ y
  11.         test_ptr = axi_sram_malloc(100);
    1 J( U: E2 m/ @( W9 H2 l4 c
  12.         rt_pin_write(LED0_PIN, PIN_HIGH);* `+ i! T3 S7 P. _# P: a: b
  13.         rt_thread_mdelay(500);
    + |2 C# F- P0 D9 u* x
  14.         rt_pin_write(LED0_PIN, PIN_LOW);
    6 ]) w4 V$ j7 l# e( D
  15.         rt_thread_mdelay(500);
    " n1 g+ y9 `. s; ^
  16.         axi_sram_free(test_ptr);7 f$ N$ c. F7 Y- [8 d) s9 C' ?" l4 S
  17.     }* r; C# Y+ w* T( `' e; b" {) ~1 D, g$ H
  18.     return RT_EOK;# h6 J8 n* z- D# N
  19. }
复制代码

0 M% p& d- M3 C- ?# }& q编译一下
2 S, j5 O/ c: o
  1. Program Size: Code=55136 RO-data=7508 RW-data=548 ZI-data=4060  
    " ]4 M5 z5 |, f
  2. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin! B$ E. M+ R/ Y/ b
  3. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 0 Warning(s).
    & L: v& y7 U0 T" _. F# @/ A5 \
  4. Build Time Elapsed:  00:00:08
复制代码
* M% l% e) P$ Z
没有错误,没有警告,下载正常运行。3 d1 y2 d4 ^! i. s1 b
' `% i; Y4 `) _4 ~6 X. N3 C
2,AXI SRAM区域作为主heap
6 G! J9 A. v$ ~  Z+ U5 {& _AXI区域 的主要优势是内存大 512K ,支持DMA1 DMA2 IDMA的访问,劣势不如TCM速度快. S2 \  L3 G6 ~( K1 M$ @/ B

0 U5 k1 u; P5 q" f: c
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.   ; *************************************************************+ _/ i/ w' h' I2 }6 I
  2. ; *** Scatter-Loading Description File generated by uVision ***+ X4 @, ?+ @" \# q" l2 B( g
  3. ; *************************************************************+ Y2 V( R4 a" k$ s8 G) u7 G
  4. 0 L' Q5 V- u- d) w6 G! C5 }
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    ( h5 ]7 v# M' _& [
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    ) h- p# t; h' _. }: H: b
  7.    *.o (RESET, +First)& H: b# z* {/ t5 g2 `4 s9 N
  8.    *(InRoot$Sections)
    3 `+ ?+ n. m: n* K+ I) L' j
  9.    .ANY (+RO)# O' K: h. r& t' L" f# @
  10.   }
    * f6 i; o! J3 @6 n4 G
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data
    . F/ K; f# h0 E  P6 y9 \+ ?4 U
  12.    .ANY (+RW +ZI)
    4 k# H4 L8 q+ Y% r% `. s$ S1 |
  13.   }
    9 n' Y/ S/ a, @4 s  X. K4 ]& \# {
  14.   RW_IRAM_HEAP 0x24000000 0x00080000  {  ; RW data# s+ v1 A, r9 N" U0 h" c
  15.    *(.RAM_HEAP)! D/ L% \. K- r, [5 O* w9 U
  16.   }
    / P3 _/ h+ }; K7 |
  17. }
复制代码
  1. 第二步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (128)# y9 o' [2 m- l7 W& k4 ]0 H
  2. #define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)3 h6 f( S7 D5 C; H4 `
  3. + ]. h! x( c! ~) g+ Q% N
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)
    * c; _; X3 i, I: r
  5. extern int Image$RW_IRAM1$ZI$Limit;! f, p! [: H3 r  T
  6. #define HEAP_BEGIN      (&Image$RW_IRAM1$ZI$Limit)* D' M$ F( ~/ M; v- L' b% c# s
  7. #elif __ICCARM__9 L, L2 N* _$ @' m- S  ]+ _" u7 D
  8. #pragma section="CSTACK"' A! B6 g6 K$ y0 s0 M9 ]! I; p
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    " @1 ?1 |: ]" H& n# h  _: d: |
  10. #else+ T, b8 l3 j: D3 L+ r9 b
  11. extern int __bss_end;) ]/ X0 @/ n6 M0 ?9 z
  12. #define HEAP_BEGIN      (&__bss_end)7 i2 k3 Z5 B7 H2 w! u  v1 l
  13. #
复制代码
  1. 第三步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (512)
    & _$ i- g! r" |3 A- e
  2. #define STM32_SRAM_END            (0x24000000 + STM32_SRAM_SIZE * 1024)
    ) f+ u" ]2 V7 V8 |

  3. 6 ?( e) I; h' ?) x
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)
    5 v1 I/ I1 a" e  D
  5. //extern int Image$RW_IRAM2$ZI$Limit;
    4 f  H4 }! U/ `( ~  H2 S
  6. #define HEAP_BEGIN      0x24000000//(&Image$RW_IRAM1$ZI$Limit)
    : U- H' l: P) d1 ]: g; J
  7. #elif __ICCARM__
    ) }5 |& w; L. X5 R! S( T
  8. #pragma section="CSTACK"
    6 D+ J, l& p! Y5 F9 F: l
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    . R& i' n( |  y$ w) x1 M* g
  10. #else
    . p2 T# `" I. {! o
  11. extern int __bss_end;2 F/ q% ^' M) [- c
  12. #define HEAP_BEGIN      (&__bss_end)
    ! C* P* l; G* v; X: H
  13. #endif
复制代码
设置heap的起始区域是0x24000000区域的512k大小。
$ B/ t" _+ {3 E5 U6 k$ S修改完毕看一下,来测试一下
: k6 p: M# q. f4 u7 ?3 r
# ]" Z& K* k1 x# {3 W6 W
  1. #define LED0_PIN    GET_PIN(B, 10)
    / Z5 W4 s% Y' v% [9 J  k7 t$ P  A6 [
  2.     uint8_t test_buff[1000]= {0};1 a! U+ }0 @; n+ |* F
  3. int main(void)4 r2 f2 {6 z& P
  4. {   
    / q- O. c  s. l! j
  5.     int count = 1;
    9 t4 f  q8 O8 ?8 R# G7 B
  6.     /* set LED0 pin mode to output */
    - |. Z5 v8 W9 M+ j8 S, \
  7.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);! J5 e3 [8 c) W! A
  8. 0 P: p7 J' S1 d
  9.     char *test_ptr;2 j' Q" _8 }% V7 {9 q; f- Y; e1 y( J
  10.     test_buff[10] = 1; $ |% N6 X* I/ x, v
  11.     while (count++)
    4 G0 @; |- b; D' h+ u1 p
  12.     {( P' f! ^. r' k6 f3 `  q' X
  13.         test_ptr = rt_malloc(100);) q. v/ a" E2 w. A6 r
  14.         rt_pin_write(LED0_PIN, PIN_HIGH);
    6 n) Q9 R  m4 }$ B/ r
  15.         rt_thread_mdelay(500);4 P3 p: w! m8 M3 |% a6 X; ]
  16.         rt_pin_write(LED0_PIN, PIN_LOW);* {% x: W2 v3 @* m8 c( x( @, E# l
  17.         rt_thread_mdelay(500);* W! ?$ b/ q3 K1 K0 ~( i! ^! a  \
  18.         rt_free(test_ptr);
    6 h4 n* g: t1 |0 x6 Z7 f& O
  19.     }" l, @8 H: e. j; ]7 q% L
  20.     return RT_EOK;
    ( c+ a9 C. ^  o2 {) o' o
  21. }
复制代码

/ v! A2 T: ~- r0 Y编译一下/ B3 l# w, w, f) n6 R/ M0 z
  1. Build started: Project: project
    + U9 a( F- n/ @" z* a
  2. *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin': s8 P; w: {$ d* i0 @0 V3 z
  3. Build target 'rtthread'3 R- l7 S1 z/ _& n2 e2 b  M
  4. compiling main.c...
    , [: D: S9 J( L5 K0 K; g4 [
  5. linking...
    - {4 Z3 F- Y$ E. w
  6. .\board\linker_scripts\link.sct(15): warning: L6314W: No section matches pattern *(.RAM_HEAP).
    # t5 a1 A7 U4 J( _" g4 ]
  7. Program Size: Code=55084 RO-data=7508 RW-data=548 ZI-data=4964  
    ! T* n( R- n& s$ w
  8. Finished: 0 information, 1 warning and 0 error messages.  c# O7 y* B* l. m: W; z
  9. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin" T% T2 ^3 H, U+ ?
  10. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 1 Warning(s).
    - m" z# v" c- v$ C$ Q1 \4 B0 q
  11. Build Time Elapsed:  00:00:02
复制代码
* g' o+ m! S; N( _3 T$ m6 e" t9 K! D
有一处警告 不要紧,查看一下map文件
9 n! o; T+ E/ H; u; t6 \
) @1 h1 E5 i. A1 _' s! |
20200219233304754.jpg
; U, y! l& E* ]; g- R: w

9 r, Q; n- T) l% @可以看到定义的test_buff是在地址0x20000898的位置。
- S) g8 M0 W) Y  ^
1 S: E7 @* C* S2 g4 C) T6 t  @三 总结分析
2 n6 |1 `5 F% j3 ]3 ]) H. F实验成功
. D; P3 p7 U/ b; u0 X; r3 i. O0 H+ U( R
TCM作为了主heap既使用rt_malloc来分配tcm区域的内存,axi_sram_malloc 来分配 axi区域的内存,但是这种方法存在一个问题,如果在使用DMA的时候,会出现问题,RT-Thread的组件默认使用了rt_malloc去申请内存,如果想正常的使用这种方法,需要更具实际情况去把组件里面的rt_malloc去替换成axi_sram_mallo。
- y% Z3 `+ P( I8 c: q$ }1 n6 t) G$ A: e3 l  B; m
AXI_SRAM做为主heap既使用rt_malloc去分配axi_sram区域的内存。如果要使用tcm区域,那么就直接定义全局变量就可以了。使用这样方法存在的问题就是无法把高速的tcm利用率最大化,优势就是就是不需要重定向RT-Thread组件里面的rt_malloc。
* Z  m, e+ N. w/ C6 d* X8 B' a( G3 I
; n7 r! c+ Q/ O  A

. b2 i  Q3 \9 G  n1 x
收藏 评论0 发布时间:2021-12-27 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版