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

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

[复制链接]
STMCU小助手 发布时间:2021-12-27 18:00
一,STM32H7 RAM介绍  X& c! _' \* Q! X& j
使用过STM32H7的朋友应该知道H7的RAM是有很多的区域的,不同的区域,使用了不同的总线,所能支持的外设也就不一样了,具体的总线结构如下图所示- q! ]! {6 Y- E: u
2020021922201274.jpg
0 s# F# M% Q3 q9 f4 E
0 D, z# B% [3 x* F3 A
20200219221709559.jpg

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

5 _  H! R. t3 ?% K. C
20200219224822144.jpg
5 Z& G9 }% [. J4 d5 |3 w

" n* z3 P2 y8 H: U5 h, N既然RT-Thread 已经支持了多内存的管理算法,那么接下来就要考虑一个问题,RT-Thread是默认使能HEAP,且RT-Thread很多优秀的组件都使用了动态内存,所以要解决究竟是哪一块内存分给rt_malloc 使用。
: x3 S. G. V( d! C2 ?# T5 ?* V
+ x+ e7 i% |: H) y+ l二 多RAM管理办法
0 L, {+ _" r- A, X% cSTM32H7的内存可用内存有很多,DTCM和AXI SRAM使用哪一个作为主heap呢?本文分别对DTCM和AXI SRAM做主heap来进行介绍。8 K) Y: d7 \  ]
首先找到RT-Thread bsp/stm32/目录下的stm32h7的支持包,通过ENV工具打开 memheap7 G  ^! N# C8 o. }7 ?  [

# f+ V; M1 ^4 c' C- v
20200219230749268.jpg
; ]) P% W9 w: C$ C9 ?8 b

' q, }' J! D9 ]3 M/ {, y之后重新生成工程。6 Y! z& z5 Y4 ~* U) d6 h

5 h' W6 N  ^8 |; I$ N7 e6 g; M$ R1,TCM区域做为主heap
! L* c5 i: ~  Q3 Z% ?TCM区域的优势是速度快,仅仅只支持MDMA的访问,但是内存小只有128K,不支持其他DMA的访问
# y/ u/ \; p2 l7 R
' l; T8 ~9 B5 P$ i# l6 ]
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.       ; *************************************************************' Z  B4 N# @% R1 V  c2 x" O2 k# H
  2. ; *** Scatter-Loading Description File generated by uVision ***/ z$ J: n7 S% `8 S/ k% J- ?
  3. ; *************************************************************
    % E+ L$ Q# D8 T: I$ s

  4. 3 G% d; U; _2 D" Y& R
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    0 ^( g) V' a4 i
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    1 `6 h$ [; p# @5 P3 {  D
  7.    *.o (RESET, +First)
    8 f. B1 u. W/ Z) S9 }2 k6 M
  8.    *(InRoot$Sections)$ B# H% U5 _- T. {- `
  9.    .ANY (+RO)
    ; S0 ]) Z3 V7 [! W7 _2 R. _9 Y
  10.   }/ ?, o3 q* D4 t6 l
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data1 k3 K9 i& J: Y0 Y% p+ W
  12.    .ANY (+RW +ZI)  z+ t8 K; Y9 f8 N- R" K
  13.   }
    9 H  x4 k$ h4 ?; ~- h: W! ~' E- p& u
  14. }
复制代码
  1. 第三步 写一个axi_sram.c
复制代码
  1. struct rt_memheap axi_sram_heap;7 P8 o5 D2 n$ P' T. R; t  s  ?
  2. void *axi_sram_malloc(unsigned long size)
    + p3 G: c5 s# c5 f( _+ Z3 V3 h' a6 @
  3. {! o* A' G* o. R8 S$ \% Y# x
  4.     return rt_memheap_alloc(&axi_sram_heap,size);/ {! }& ~5 l" @! \6 g
  5. }
    5 Y& Z: }' I+ L+ M" W/ b: g# ~; ^

  6. ' m+ m! o  E. I; S  p6 w
  7. void axi_sram_free(void *ptr)9 z$ K, X/ k& ^0 t
  8. {
    8 @$ ^* l7 D3 b- _# s+ p1 l
  9.     rt_memheap_free(ptr);
    2 `+ a/ f& J3 r- a
  10. }/ p* }/ r+ W3 g3 G/ o) J  o) Z
  11. , b+ A! z, n! u# O6 S/ |
  12. void *axi_sram_calloc(unsigned int n,unsigned int size)
    6 X" `# N/ ~2 @1 r( g
  13. {
    % g& ]* a6 g& K: c: W
  14.     void* ptr = NULL;
    + f7 v: a+ \7 e) {. N, i5 e

  15. 1 G7 g8 \& P' p8 C; H1 ?. }9 g, y
  16.     ptr = axi_sram_malloc(n * size);5 i1 e$ B/ q! }. g  L' _3 m3 ~2 J
  17.     if(ptr)
    8 H& _0 T. Z& B* {
  18.     {, ~, \: o: m0 _$ J- ?
  19.         memset(ptr, 0, n*size);
    ( |8 l% Q. }4 U! C  ]
  20.     }
    * E# i! q: N5 u' ~2 k

  21. . d# c5 X& ]) W9 m0 B: [
  22.     return ptr;
    / {, \4 v) i  x3 l( H$ Z; ^
  23. }
复制代码
  1. 第四步 修改drv_common.c,增加一行axi_sram初始化的代码
复制代码
  1.   #if defined(RT_USING_HEAP)- b# ?- c6 d# I; h8 L, I- A, Q5 \
  2.     rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
    1 ^: V2 Q  T8 ]. y, c8 w3 Q
  3. #endif8 z* ], i$ X3 y, V  t' x2 o  H
  4. 2 l8 a( K. e/ u! x: T4 d
  5.     rt_memheap_init(&axi_sram_heap,"AXISRAM",(void *)RT_AXI_SRAM_BEGIN,RT_AXI_SRAM_SIZE);   
复制代码
编写一个测试代码
: l, M& r' i4 [! g# u
- n/ Q' y# b  Q- n% P1 k
  1. int main(void)
    / g  G- F+ t! @3 ~
  2. {1 V4 d7 M7 M, Y6 e1 A( Y
  3.     int count = 1;
    & g' k5 n7 a  a8 f* i2 V. t
  4.     /* set LED0 pin mode to output */
    + Q3 j! T3 K9 v# G( Z  D, q
  5.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);3 [& \! z  n+ ~: g7 z) n5 W' }

  6. ( a6 X. ?5 `3 C  V
  7.     char *test_ptr;
    # l: I4 t" P2 Q0 G$ }! r

  8. 9 G; T: m4 r: F* q. P- f9 D
  9.     while (count++)9 |. b4 ^0 X; |  R! M) x& u' q3 Q
  10.     {. b6 x7 r% h* X, X
  11.         test_ptr = axi_sram_malloc(100);
    7 i8 L" L0 h/ W* }
  12.         rt_pin_write(LED0_PIN, PIN_HIGH);8 K. s0 l- P6 i& l
  13.         rt_thread_mdelay(500);
    # b- V7 Y; o6 u, F1 r5 H, ~
  14.         rt_pin_write(LED0_PIN, PIN_LOW);
    * {* g9 W& s: N- g6 G* o% W
  15.         rt_thread_mdelay(500);# v1 E/ F0 J9 z: j  {8 h
  16.         axi_sram_free(test_ptr);( j* H2 p. T% @5 ]: h6 r4 Z
  17.     }7 m9 D; i/ y9 A7 m
  18.     return RT_EOK;* U/ p$ a/ g- I6 Q. M' P
  19. }
复制代码
$ T$ O. p* K  u% Y2 d) l* h6 Z
编译一下  ~$ ?. F& {  J
  1. Program Size: Code=55136 RO-data=7508 RW-data=548 ZI-data=4060  
    * Y. t% I: M$ R( v5 i
  2. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    ! D& v& j% F$ u  L6 Z
  3. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 0 Warning(s).
    + i6 S. R. U; t4 o7 K3 ^
  4. Build Time Elapsed:  00:00:08
复制代码
4 s, u& M' v: y
没有错误,没有警告,下载正常运行。
; I" z' n" i7 V# i# j7 l) ?: N, W& R
2,AXI SRAM区域作为主heap
% M6 z7 X; |. f3 l9 sAXI区域 的主要优势是内存大 512K ,支持DMA1 DMA2 IDMA的访问,劣势不如TCM速度快
: w# s# W) a1 p0 i& H! h8 N( L" u/ O- `+ w3 D, o
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.   ; *************************************************************
    4 f: n# P; Q% B( X, y
  2. ; *** Scatter-Loading Description File generated by uVision ***9 z* ]; ?; V7 O6 L+ F, E. E0 D
  3. ; *************************************************************
    8 V- ~" y* I$ e" U/ j: d
  4. + Z. a4 `; w9 w' z) j1 G7 @
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    8 {' q4 e4 ~) |  z5 A) _9 B* [& u
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    ! f+ E) h( F0 j( G& a
  7.    *.o (RESET, +First)# e9 ^* {8 `, s' {' X1 U6 m
  8.    *(InRoot$Sections)
    ; o2 i9 B# o: c6 r0 a; f
  9.    .ANY (+RO)' A& u+ b7 g  p! s
  10.   }
    ( o6 w) W: F) u( k+ f
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data: m, X* l6 w3 Q' K* g" D
  12.    .ANY (+RW +ZI)
    0 w* |, y" m; E0 D) p
  13.   }
    * w9 G8 N- X7 s" F2 K) @8 u5 _" C
  14.   RW_IRAM_HEAP 0x24000000 0x00080000  {  ; RW data0 N1 [5 B4 Q; O2 F* _( }5 p) X
  15.    *(.RAM_HEAP)1 c& e) Y* V; ]  v
  16.   }7 t2 K( Z0 y1 ~2 }
  17. }
复制代码
  1. 第二步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (128)
    * M( o: A5 W7 T# L
  2. #define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)
    # M, y; G4 g1 v/ L. L

  3. # f$ Z! C/ n, O4 Z: i
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)
    9 \1 b3 w3 C' I( v6 a* o  L: E
  5. extern int Image$RW_IRAM1$ZI$Limit;: o# ?4 ~- i8 N* a" n
  6. #define HEAP_BEGIN      (&Image$RW_IRAM1$ZI$Limit)
    # ], T: Y+ _$ m9 R( A& n
  7. #elif __ICCARM__
    & ^; ]" ~$ b9 H
  8. #pragma section="CSTACK"$ u9 \' h2 O$ `& K& h
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))( X' U. K, x6 L) o0 t  J; }
  10. #else. y0 l- w/ M1 W+ Q+ o0 x
  11. extern int __bss_end;6 W: V7 m7 h! U8 t/ c, V' h
  12. #define HEAP_BEGIN      (&__bss_end)3 U2 V) ?: w8 a( E1 B  G+ K
  13. #
复制代码
  1. 第三步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (512)( ]9 D4 N' z# ]& x- b- h
  2. #define STM32_SRAM_END            (0x24000000 + STM32_SRAM_SIZE * 1024)7 S/ N) Q5 y. H) A0 p% c
  3. $ k' K" p0 t- _# J9 @1 M2 W+ o% l0 }
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)- @# O# T& o2 l" N" J( E: V* E) a
  5. //extern int Image$RW_IRAM2$ZI$Limit;3 _4 p: _+ S, d, g/ Q
  6. #define HEAP_BEGIN      0x24000000//(&Image$RW_IRAM1$ZI$Limit)) F3 K  Z8 g6 L% c: a8 V6 j
  7. #elif __ICCARM__
    3 s5 m7 P/ [, J/ Y0 w8 ^  Y) q
  8. #pragma section="CSTACK"
    8 q- l- K* R+ v) s! T4 o" N3 E
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    / b" r) h0 ?6 @
  10. #else; s/ [( G6 @4 O
  11. extern int __bss_end;
    2 T% Z5 c+ p. M3 ^
  12. #define HEAP_BEGIN      (&__bss_end)6 `! L2 F# ?- H1 o1 Z- S
  13. #endif
复制代码
设置heap的起始区域是0x24000000区域的512k大小。
+ {% S1 v, Z; J8 k修改完毕看一下,来测试一下
. z9 V2 L4 N) N$ b: g: m  r$ ]2 I: c9 P9 A
  1. #define LED0_PIN    GET_PIN(B, 10)
    ( [( B( A, H) Q4 ?: D7 ?
  2.     uint8_t test_buff[1000]= {0};
    + o( f* e, t( g5 W+ U
  3. int main(void)& \' a* e# j, V; g3 H3 y8 v% b
  4. {   0 p  u1 W1 Z/ T; |6 t1 s8 t1 d
  5.     int count = 1;1 v% ^+ u8 q( [
  6.     /* set LED0 pin mode to output */
    : N3 r$ y4 b9 H- B% ~7 Z
  7.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    2 C& A5 x$ y) q' y/ w: B: Z2 e- ?: K
  8. ; ]! R5 y) B' `& ~6 v- E
  9.     char *test_ptr;
    2 |2 X% k" q8 s, n" v
  10.     test_buff[10] = 1;
    % U7 B( c0 {  o* @2 [8 g
  11.     while (count++)+ @8 \2 v* w$ W
  12.     {
    / {% W$ ]3 T& S* G/ V
  13.         test_ptr = rt_malloc(100);" x0 Y! R/ B) d6 x
  14.         rt_pin_write(LED0_PIN, PIN_HIGH);) K8 y/ U9 I& N7 Z0 v
  15.         rt_thread_mdelay(500);$ f1 S1 S. ^/ W
  16.         rt_pin_write(LED0_PIN, PIN_LOW);) e# j0 l% \7 c. {; r; W3 G# o  r
  17.         rt_thread_mdelay(500);
      h7 Z* B1 q8 o* B5 y
  18.         rt_free(test_ptr);- J0 w5 s9 a4 L
  19.     }5 d: l- {, o: x( ~
  20.     return RT_EOK;
    9 G* d9 |" T& S2 Q& z& Y% V. Q
  21. }
复制代码
" |: P1 @( t" ^
编译一下
% r8 m& T# o9 k& p5 u0 q
  1. Build started: Project: project
    . U4 i1 X( @! m+ s  r& s
  2. *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
      f1 p& f" f. M" Y7 u  Z
  3. Build target 'rtthread': Q% S2 t( U/ g- O
  4. compiling main.c...
    ' @9 ]4 B/ Z6 P& |
  5. linking...0 u  @8 X1 {9 S8 K* u( q- s& u* W
  6. .\board\linker_scripts\link.sct(15): warning: L6314W: No section matches pattern *(.RAM_HEAP).* z# c6 U7 q* \) v, m1 H
  7. Program Size: Code=55084 RO-data=7508 RW-data=548 ZI-data=4964  9 i* q% _) e1 @  f5 e/ w- B! `- f
  8. Finished: 0 information, 1 warning and 0 error messages.* [! l5 `, h+ q2 L% f6 E
  9. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    : U! W2 n5 E+ A" \2 A* E+ L
  10. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 1 Warning(s).: A5 v3 d% g, S& P# t0 k# Z* _, _
  11. Build Time Elapsed:  00:00:02
复制代码

* v- Z% x* _! m3 O* |有一处警告 不要紧,查看一下map文件$ T6 u0 c& P6 Z) {* i) [! B
9 g2 K- Z: B  T/ N' f- v4 z- ^" H* W
20200219233304754.jpg

, r  {9 f& V6 V( ^
, M4 k% i: _* R  ]" B可以看到定义的test_buff是在地址0x20000898的位置。! D( U7 M2 b: v/ B4 L, x7 H

) z1 m9 L: y& K5 Z三 总结分析
" d: @" q5 C! ^& Y, c7 z, a& c实验成功
% U# Z) _: j1 N2 _, ]3 U* J
0 z$ a5 C$ K" }! BTCM作为了主heap既使用rt_malloc来分配tcm区域的内存,axi_sram_malloc 来分配 axi区域的内存,但是这种方法存在一个问题,如果在使用DMA的时候,会出现问题,RT-Thread的组件默认使用了rt_malloc去申请内存,如果想正常的使用这种方法,需要更具实际情况去把组件里面的rt_malloc去替换成axi_sram_mallo。
' Z1 h* e! w+ M" D3 M; C; Y; h: `+ |1 ^: e0 u9 s
AXI_SRAM做为主heap既使用rt_malloc去分配axi_sram区域的内存。如果要使用tcm区域,那么就直接定义全局变量就可以了。使用这样方法存在的问题就是无法把高速的tcm利用率最大化,优势就是就是不需要重定向RT-Thread组件里面的rt_malloc。0 _; J* b) n0 J. w" @7 h! @  y8 k  [
3 {) |# ]& H* W
, Q  }# |6 f) S6 _! i' }
4 o3 C, N$ r, U3 V' [" h  p' S
收藏 评论0 发布时间:2021-12-27 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版