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

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

[复制链接]
STMCU小助手 发布时间:2021-12-27 18:00
一,STM32H7 RAM介绍
5 O" \# A7 B! y6 Q! e' [' A使用过STM32H7的朋友应该知道H7的RAM是有很多的区域的,不同的区域,使用了不同的总线,所能支持的外设也就不一样了,具体的总线结构如下图所示
8 ^& g1 Z" N0 N0 s
2020021922201274.jpg

  E7 a; I; w, k% s
, V3 T4 X2 S# A) [8 d* Y! B8 n; t
20200219221709559.jpg

1 x, G" I/ C0 k' m1 Y; {- k, o1 a7 j1 g9 ~  j
通过上图和上表就能发现如果要使用DMA就必须对多RAM进行管理,要么自己去实现内存管理,要么通过__attribute__ 关键字去定义,这样或多或少会有些麻烦,后来看到安福莱STM32H743动态内存管理,同时分区管理AXI RAM,DTCM,SRAM1等五块空间 这篇文章,想到RT-Thread 肯定也应该是支持多内存管理的,看到查看官方的文档中心发现 可以使用 memheap 管理算法。
, Q) v5 m; k& Q. Q% n* a, I# O0 |8 ]3 M( z$ o" N0 Y% m% C
20200219224822144.jpg

4 @' O/ f; {8 w7 Q. r( P& v8 T+ |( o3 k( Y8 z' u. E7 e
既然RT-Thread 已经支持了多内存的管理算法,那么接下来就要考虑一个问题,RT-Thread是默认使能HEAP,且RT-Thread很多优秀的组件都使用了动态内存,所以要解决究竟是哪一块内存分给rt_malloc 使用。
) C$ X2 @& I& {0 |) P% D
- X3 f# M4 {+ @- H二 多RAM管理办法2 _3 ]  Q' n# \) B8 j. w
STM32H7的内存可用内存有很多,DTCM和AXI SRAM使用哪一个作为主heap呢?本文分别对DTCM和AXI SRAM做主heap来进行介绍。9 E1 K# D; p2 ]3 j1 u) Q& z
首先找到RT-Thread bsp/stm32/目录下的stm32h7的支持包,通过ENV工具打开 memheap# E* ~9 k/ y) Y! ?% Z; W. d
+ n1 q8 d! D. q& T
20200219230749268.jpg

; r* b3 J7 F1 T% r) E/ E& g2 K" e' `
之后重新生成工程。- {3 R. h" B: E7 C

! S7 ~6 C% k2 `, l0 ^; }1,TCM区域做为主heap! ~" }6 w: m2 K0 M
TCM区域的优势是速度快,仅仅只支持MDMA的访问,但是内存小只有128K,不支持其他DMA的访问
$ ~5 ~4 i& f6 d# T
3 I  I* D  x, v* _
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.       ; *************************************************************
    # L. a; s0 g, ?: h. ~9 c
  2. ; *** Scatter-Loading Description File generated by uVision ***
      M1 |3 k! H2 w2 j3 i2 P: ?" q
  3. ; *************************************************************
    + y; k( H% h& F: w1 k: l" ~
  4. + C  [8 J* j2 i! T5 V( Z
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    2 w3 n4 C* \; h
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address5 H1 F) G2 f7 |3 J8 ^9 V
  7.    *.o (RESET, +First)
    6 q5 l) l% u9 n+ O3 Q7 X- d0 z
  8.    *(InRoot$Sections)- F( {1 w# B* x2 Q3 d7 ?  }" ^
  9.    .ANY (+RO)- S1 a! a( C* ]4 L  U. P' `
  10.   }7 B& U1 T6 g- }  v% {8 u
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data  s- {& H. k& f1 E3 Y* T' w  c
  12.    .ANY (+RW +ZI)8 K/ b. e! N1 r# _& g2 v3 K7 b# l8 @
  13.   }
    + U, H" Q  }/ _; w
  14. }
复制代码
  1. 第三步 写一个axi_sram.c
复制代码
  1. struct rt_memheap axi_sram_heap;6 H6 x6 G6 T1 L5 c
  2. void *axi_sram_malloc(unsigned long size); i& v0 H9 Y% h4 q0 c$ R
  3. {$ a& A9 Z! a; V- \8 b( }
  4.     return rt_memheap_alloc(&axi_sram_heap,size);
    8 Q$ K' N& k8 ?
  5. }
    - p/ }# D" t6 Y7 `9 u# X( l
  6. ! U# I+ \8 V+ P. h
  7. void axi_sram_free(void *ptr)( C4 d) A! y6 A, X" o8 ~
  8. {' X; P9 F% X( N1 n; U
  9.     rt_memheap_free(ptr);
      }$ C2 ?: ^8 Y; t: k8 v: d
  10. }
    ! k8 x+ E) ]2 c; g8 P2 ~" ]& J

  11. 1 `" s7 _5 R6 U, F3 [
  12. void *axi_sram_calloc(unsigned int n,unsigned int size)
    ! D2 N$ g. e; P( Z
  13. {# _8 p4 y1 h" H* L; ?5 ~1 x
  14.     void* ptr = NULL;4 y" z; q* [- X2 ?

  15. , _: ]: E+ }) X* x# V# `6 D
  16.     ptr = axi_sram_malloc(n * size);
    4 C, i2 [( q/ W" o2 A
  17.     if(ptr)- w5 F! s7 T9 w6 D- M
  18.     {2 ?5 |5 y; [# r, y
  19.         memset(ptr, 0, n*size);1 H' ^  |, A& Z: C) o, D$ j5 o
  20.     }/ ~) A2 D0 c$ ~
  21. 7 P0 C* `- b- I" R$ ?) R
  22.     return ptr;
    : M# {3 m3 e% x' L
  23. }
复制代码
  1. 第四步 修改drv_common.c,增加一行axi_sram初始化的代码
复制代码
  1.   #if defined(RT_USING_HEAP)
    * b: n: Q$ s8 Z1 o/ m+ J. h  ?+ m
  2.     rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);1 B" Z' K: o' h. n8 @
  3. #endif1 @- Q5 I* i+ N- B9 U

  4. 0 m! X/ ?! `1 s$ Y
  5.     rt_memheap_init(&axi_sram_heap,"AXISRAM",(void *)RT_AXI_SRAM_BEGIN,RT_AXI_SRAM_SIZE);   
复制代码
编写一个测试代码
" K- e) c- h( b8 `) E  W3 f5 F) f& A6 ^0 c( x9 l! G/ Y
  1. int main(void)* s; {2 N2 {8 Z& E* X
  2. {7 ]. S3 q2 g. \8 q) g# h8 g. l
  3.     int count = 1;7 x: t0 @' ~# v1 t; m  _( S$ M7 M
  4.     /* set LED0 pin mode to output */
    " t; ?% @( }- K& x0 U( v
  5.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);4 C) O  w' [' G& o1 D" q
  6. 3 n/ |4 Z$ }  u: s( v
  7.     char *test_ptr;# I: H! B9 M4 F

  8. 0 p& P- J2 P) L% f. V( ?# I
  9.     while (count++)8 d4 a% j% k( M( `1 {1 M# r
  10.     {
    - ~) X: K3 j+ }. e1 T3 f
  11.         test_ptr = axi_sram_malloc(100);
    ; L) }; I' K# o9 F
  12.         rt_pin_write(LED0_PIN, PIN_HIGH);) k$ Z( C  l1 \  J6 v) V1 a' ^
  13.         rt_thread_mdelay(500);
    2 |& `: z& i* F. ]
  14.         rt_pin_write(LED0_PIN, PIN_LOW);/ G3 V5 h4 L* x+ y! Q  n' }8 G
  15.         rt_thread_mdelay(500);
    9 V* h+ S% l# B9 s( ^
  16.         axi_sram_free(test_ptr);
    / }  U& y. r% o$ u' x
  17.     }% T7 V. e9 C% }4 E+ F
  18.     return RT_EOK;# C- M0 o- U9 J: ]
  19. }
复制代码
7 ]" P' [5 @- O/ J( W- s- I3 _# l# t
编译一下
% G, b. w2 y% {' B) {
  1. Program Size: Code=55136 RO-data=7508 RW-data=548 ZI-data=4060  
    * C1 Y; _0 P& k$ e4 V7 P
  2. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    $ j# M4 {, v: U" W7 s
  3. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 0 Warning(s).0 b0 |% N: S" k$ H/ I
  4. Build Time Elapsed:  00:00:08
复制代码

: U' R2 o9 d) |! V) m没有错误,没有警告,下载正常运行。
; P) z8 t, y4 b" }
9 `5 D. g9 S" X# M( \! r  i2,AXI SRAM区域作为主heap9 d8 q% X# v5 @
AXI区域 的主要优势是内存大 512K ,支持DMA1 DMA2 IDMA的访问,劣势不如TCM速度快) |  f. T; y. X8 Q0 {

$ K1 C8 _+ D, d- a% C
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.   ; *************************************************************
    : `( t4 W( k  P3 L
  2. ; *** Scatter-Loading Description File generated by uVision ***
    / ?$ q/ g6 A; n6 t
  3. ; *************************************************************
    ! a4 a- l+ ^  U3 Z

  4. ; U2 Q/ {0 L+ d6 @# _4 O
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    1 w1 `" Q8 T( H& m( D& h9 J" b
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    & Z1 ^7 d& j1 u8 l8 l' o- r  @: M
  7.    *.o (RESET, +First)* m, u. l5 ]  a7 R
  8.    *(InRoot$Sections)
    " S. R1 t7 z/ }' @' n3 z  o
  9.    .ANY (+RO)" h8 Q! T8 W- r
  10.   }( N, t6 m2 L. o* v( J  l
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data4 k" D+ L- F4 l5 n5 Z0 d$ S7 k
  12.    .ANY (+RW +ZI)) V- q) U6 u4 Y$ M8 ?
  13.   }3 k; G+ M7 m; X! ^- f* Q
  14.   RW_IRAM_HEAP 0x24000000 0x00080000  {  ; RW data5 B% K! f5 W! M6 F8 O) ^. r" Z) y: `
  15.    *(.RAM_HEAP)
    9 m- B) g& w' B7 z
  16.   }/ H4 h2 J! o: e- X
  17. }
复制代码
  1. 第二步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (128)
    , I4 N+ s& u  h  d& U- T
  2. #define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)# e- G1 m7 q" z. \1 d6 b; u- g7 D

  3. 5 `8 r+ t' ^+ B! T
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)
    9 b6 z. ^4 s" _; K: F# r3 e& O
  5. extern int Image$RW_IRAM1$ZI$Limit;# b+ I! d2 ?1 L0 M% ?
  6. #define HEAP_BEGIN      (&Image$RW_IRAM1$ZI$Limit)
    4 A2 i7 F4 O* q5 e, l
  7. #elif __ICCARM__
    4 z2 `" N2 v3 [( e5 t( {% W7 W
  8. #pragma section="CSTACK"7 o. X$ K* Z/ t6 H4 K; \! s- r
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    - c: B- j: b9 ~/ m9 |- q. s, l
  10. #else
    / q1 R+ n( B+ i8 L! {( M2 }5 w
  11. extern int __bss_end;
    8 L3 P& }8 L+ q4 R
  12. #define HEAP_BEGIN      (&__bss_end)
    $ ~* S, @4 Z7 v
  13. #
复制代码
  1. 第三步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (512)
    ! |4 W# V, \  E' W& j, C- h
  2. #define STM32_SRAM_END            (0x24000000 + STM32_SRAM_SIZE * 1024)" i0 Q$ `4 k+ H. x; p0 b7 H

  3. ' M. [2 ^' w' }  N3 m/ k
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)" G% T3 `/ u) \" y4 c
  5. //extern int Image$RW_IRAM2$ZI$Limit;
    * P5 ?; x" s2 t8 [8 l0 i- C3 Q
  6. #define HEAP_BEGIN      0x24000000//(&Image$RW_IRAM1$ZI$Limit)
    0 e* `2 |( A% j
  7. #elif __ICCARM__
    3 a! C3 K) Y+ ~2 s) h/ f- K
  8. #pragma section="CSTACK"' k, |* U8 ?$ i& O
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))) ]( B- U5 u1 n" e5 Q) p2 s
  10. #else. Z# s" O9 R  b8 A
  11. extern int __bss_end;
    - @' m7 s/ V" I' M# p& `
  12. #define HEAP_BEGIN      (&__bss_end)0 J( J9 T) F- S* x/ x; A- ]
  13. #endif
复制代码
设置heap的起始区域是0x24000000区域的512k大小。9 P9 o0 @- v1 ?
修改完毕看一下,来测试一下
& S& M# x2 f& D2 y
+ n0 k% l4 g- q; @
  1. #define LED0_PIN    GET_PIN(B, 10)4 P) V' y4 _, R) O- ~: d
  2.     uint8_t test_buff[1000]= {0};
    1 G) t% q, u& V2 }1 a$ ^
  3. int main(void)" V1 g3 a4 x; w) x8 S
  4. {   
    ( C+ ?3 t! \7 ?) U) m* {8 y, c
  5.     int count = 1;
    % n' n5 ]$ J, d) O- `6 l
  6.     /* set LED0 pin mode to output */' g3 B" T7 n' @5 N9 @% s
  7.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    ; H. z  p1 q  k6 z6 @5 U+ f6 g

  8. ! U0 P7 C- q$ K% T
  9.     char *test_ptr;. y9 h( F+ B( t- h& _6 B7 {. o
  10.     test_buff[10] = 1;
    4 R: C3 i+ s$ P5 O) b
  11.     while (count++)
    ( T) W) X: d: E9 F, |( K! ^
  12.     {' k% Z2 I; u3 Z1 F, j$ `3 |
  13.         test_ptr = rt_malloc(100);
    6 n. V& J8 f2 n$ R" m8 @$ ^& w
  14.         rt_pin_write(LED0_PIN, PIN_HIGH);* a7 p  w/ g/ n! @# B/ S" j( W
  15.         rt_thread_mdelay(500);2 D4 H+ u9 `- a5 y% D/ r& a" _
  16.         rt_pin_write(LED0_PIN, PIN_LOW);! N3 g2 C) q" ~: S
  17.         rt_thread_mdelay(500);
    5 {0 |6 @4 L5 d2 Z
  18.         rt_free(test_ptr);! X/ [$ ?7 L' X; u7 k
  19.     }
    7 o! g. s5 b6 T- N5 ?( y
  20.     return RT_EOK;
    3 f7 U# ?; v5 U) ?2 p1 B
  21. }
复制代码
$ d/ b; a8 @( L
编译一下: o2 O* U8 |: ^$ Z& {9 q% I
  1. Build started: Project: project( {0 J3 r* c/ g# p7 K
  2. *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'4 |% @% p. Y* n7 {/ q  t/ [
  3. Build target 'rtthread'' m3 _: n4 z. ^1 J6 G! f
  4. compiling main.c...1 G. c" y# G; i6 U; Z* M
  5. linking...
    7 o. h( U; X  n' T
  6. .\board\linker_scripts\link.sct(15): warning: L6314W: No section matches pattern *(.RAM_HEAP).+ J3 n& @5 B. d
  7. Program Size: Code=55084 RO-data=7508 RW-data=548 ZI-data=4964  - x) h$ _* f- ], `
  8. Finished: 0 information, 1 warning and 0 error messages.; V6 Q3 }6 W8 h- }: y' c
  9. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    ( p( m5 ^5 d: x1 b: }8 Z8 V# e8 J
  10. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 1 Warning(s).
    ( \2 I5 O2 B1 X& T" V0 ~+ c
  11. Build Time Elapsed:  00:00:02
复制代码
) l8 j: c; d$ O8 M1 `
有一处警告 不要紧,查看一下map文件
' f, w0 i/ c. o3 p! r7 y; y) m# P: \5 ~4 }/ o
20200219233304754.jpg

. Z+ J+ W6 b0 N
2 @, ^! S, S& _! R% ?5 V9 ~可以看到定义的test_buff是在地址0x20000898的位置。
9 ^5 ?9 k! s3 N; g( i4 `! ]4 \, D1 A8 Y- ^& s2 f
三 总结分析
, T( c7 C5 Z; n+ C& U实验成功/ P. U. n# ^6 r. B/ }; i8 \. c1 U3 N

) u  s6 y* D; j4 BTCM作为了主heap既使用rt_malloc来分配tcm区域的内存,axi_sram_malloc 来分配 axi区域的内存,但是这种方法存在一个问题,如果在使用DMA的时候,会出现问题,RT-Thread的组件默认使用了rt_malloc去申请内存,如果想正常的使用这种方法,需要更具实际情况去把组件里面的rt_malloc去替换成axi_sram_mallo。, y2 H1 r9 X, D" A5 D9 f5 Z
# m3 N5 ]+ M, N, Y
AXI_SRAM做为主heap既使用rt_malloc去分配axi_sram区域的内存。如果要使用tcm区域,那么就直接定义全局变量就可以了。使用这样方法存在的问题就是无法把高速的tcm利用率最大化,优势就是就是不需要重定向RT-Thread组件里面的rt_malloc。
+ O/ S) Z6 O! B4 r! G" r: c( D+ P* b
+ }; U# T" _" e" @
7 y: j$ ]7 a! L0 k1 A! [" u; K7 [) E& `$ p$ @4 R
收藏 评论0 发布时间:2021-12-27 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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