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

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

[复制链接]
STMCU小助手 发布时间:2021-12-27 18:00
一,STM32H7 RAM介绍
2 I( P& `; G' J使用过STM32H7的朋友应该知道H7的RAM是有很多的区域的,不同的区域,使用了不同的总线,所能支持的外设也就不一样了,具体的总线结构如下图所示
6 ^# D0 Q6 B# w$ d& W
2020021922201274.jpg

9 k7 C: r6 B: [" {; c; l4 u% |/ ~7 d4 t6 I
20200219221709559.jpg

4 f. m: L* u; U5 Z% ?$ l) J+ M
: ]$ K: k) t) @* O# ?通过上图和上表就能发现如果要使用DMA就必须对多RAM进行管理,要么自己去实现内存管理,要么通过__attribute__ 关键字去定义,这样或多或少会有些麻烦,后来看到安福莱STM32H743动态内存管理,同时分区管理AXI RAM,DTCM,SRAM1等五块空间 这篇文章,想到RT-Thread 肯定也应该是支持多内存管理的,看到查看官方的文档中心发现 可以使用 memheap 管理算法。
. A: U* b6 o0 s; W9 |- _6 I& A* Y# a8 u8 o  i% U! {
20200219224822144.jpg

& h5 C+ d7 }+ c9 y: ]3 H
/ m2 O/ r5 U; {既然RT-Thread 已经支持了多内存的管理算法,那么接下来就要考虑一个问题,RT-Thread是默认使能HEAP,且RT-Thread很多优秀的组件都使用了动态内存,所以要解决究竟是哪一块内存分给rt_malloc 使用。
6 L) u+ s/ ^. m5 F) n
* s- A! S% g" K  D6 x+ I& s9 u二 多RAM管理办法
' z# M: e* f& H4 A3 ZSTM32H7的内存可用内存有很多,DTCM和AXI SRAM使用哪一个作为主heap呢?本文分别对DTCM和AXI SRAM做主heap来进行介绍。
5 F% K" e' {% X. t首先找到RT-Thread bsp/stm32/目录下的stm32h7的支持包,通过ENV工具打开 memheap* ~$ T9 O1 Z# |8 {/ T, T* H
! @6 R* L. d" f# [
20200219230749268.jpg

& K1 B' S, I5 l3 T* O* t
* N6 f; G4 b6 x1 K" I: K: `: U之后重新生成工程。
& l, N" {- [; h& A' d- e8 R
. ~( t  a0 H& d! Z$ M: n1,TCM区域做为主heap
6 k5 i1 m: T. e. b# lTCM区域的优势是速度快,仅仅只支持MDMA的访问,但是内存小只有128K,不支持其他DMA的访问9 R3 _7 P; w! R% D; s
: d0 T- r, A. L# r# d  h
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.       ; *************************************************************
    ) o% k6 @0 K) x1 `/ V
  2. ; *** Scatter-Loading Description File generated by uVision ***( |0 l4 c+ v2 ^' h2 O" m% u
  3. ; *************************************************************7 X) a, V: q( t9 P. p

  4. ( z6 w! a6 X  I" a
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region  Z; Q/ y) T) \3 q
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    + U( _" r' V) `6 X: C
  7.    *.o (RESET, +First)
    ( B. P9 i8 I+ b* P" V/ e# S. y
  8.    *(InRoot$Sections)
    5 ~. F1 @$ c! C# H' \
  9.    .ANY (+RO)
    ; Y' g5 g* Y5 t) A
  10.   }
    ; h1 w7 w- U4 s& H# i! p7 b% `
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data
    . I7 n- i1 b- K- Q+ m4 l
  12.    .ANY (+RW +ZI)- D" ^, h: A% r$ z# I
  13.   }+ z# e: P, S7 H  \' p1 m, {6 L9 H
  14. }
复制代码
  1. 第三步 写一个axi_sram.c
复制代码
  1. struct rt_memheap axi_sram_heap;
    + A, U% H+ Z/ i' ^1 u5 E
  2. void *axi_sram_malloc(unsigned long size)
    3 s5 s. J8 j6 [7 U$ z. [# r
  3. {6 H) N8 L6 E1 @" Z
  4.     return rt_memheap_alloc(&axi_sram_heap,size);
    / E! D& [% ?" x  I: u
  5. }& j$ L" \8 v7 [
  6. ; g2 }) y) t1 ^* F
  7. void axi_sram_free(void *ptr)6 U# `2 y& v5 Y8 U
  8. {" U; J7 v  l7 Y+ d/ l
  9.     rt_memheap_free(ptr);
    ) o$ |; [( ~( H0 y1 Z7 A( v5 t
  10. }) [9 w/ |, _5 J5 F! i7 f" {
  11. ( V# x2 @9 ~8 s2 M7 f- g
  12. void *axi_sram_calloc(unsigned int n,unsigned int size)
    4 }( P# K! Y) S- N- ?
  13. {: e) v6 C7 ?* d7 u4 f, [
  14.     void* ptr = NULL;
    7 c7 A5 o' O: l4 I8 Y& g  w

  15. * e' E8 m% r* C
  16.     ptr = axi_sram_malloc(n * size);  O: _  ~$ H# u# S% z& t) ^! m+ D! r
  17.     if(ptr)1 V& H" ]( j5 X% q" O! R
  18.     {! @! O8 y5 e' x2 t! d5 U. k
  19.         memset(ptr, 0, n*size);6 ]* D- [: W1 @$ q+ ]. b
  20.     }
    $ m7 J; X9 t. A, z+ s

  21. & _3 A- L9 w7 j# d' [
  22.     return ptr;4 n+ z6 U# A, ~1 O! |2 G/ n
  23. }
复制代码
  1. 第四步 修改drv_common.c,增加一行axi_sram初始化的代码
复制代码
  1.   #if defined(RT_USING_HEAP)( c; [" j* ?! W; b: L4 D" d0 p( y
  2.     rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);  Q% _8 S, g1 A" {
  3. #endif& O5 I* k0 T& n) B. R

  4. - s8 C! U: A- `9 s
  5.     rt_memheap_init(&axi_sram_heap,"AXISRAM",(void *)RT_AXI_SRAM_BEGIN,RT_AXI_SRAM_SIZE);   
复制代码
编写一个测试代码$ A9 t+ U# J8 S  J+ E

% g/ d; L0 Y2 Z$ C
  1. int main(void)2 x; i% d; C. L) Y  R& l
  2. {$ g6 ], z' P0 ?2 H
  3.     int count = 1;
    5 ^9 n  t$ b# L. ?# R
  4.     /* set LED0 pin mode to output */
    : T1 T9 b1 h  [- p. G5 K4 u; L% s8 @0 x
  5.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);$ a5 O" N/ n/ c1 d2 m7 Q) D1 @

  6. ( V( Z# a# ~& K* ?3 S
  7.     char *test_ptr;) M: t; [, _" j3 ^' D) t

  8. : R, t# g7 l# f! v% g
  9.     while (count++): ?; b% {* `- S  c
  10.     {
    : k  o% O* h4 I) \0 Z
  11.         test_ptr = axi_sram_malloc(100);* {. M8 v/ u: ?$ n& o
  12.         rt_pin_write(LED0_PIN, PIN_HIGH);
    # }# B/ t4 L! y, J
  13.         rt_thread_mdelay(500);
    5 q, m4 H& e* o% _1 \! Q4 ]
  14.         rt_pin_write(LED0_PIN, PIN_LOW);8 o# C3 B( S7 z7 a) J# ]! b
  15.         rt_thread_mdelay(500);* G6 d1 d7 g1 ~- _# e% a
  16.         axi_sram_free(test_ptr);0 M9 }! Z7 A1 e/ G9 Y! S2 m7 J$ ]
  17.     }, T5 w* l+ ?# Q8 b- m) y
  18.     return RT_EOK;
    $ W% w3 o7 k# n- Y( @5 `: C& t
  19. }
复制代码
5 m+ K8 g- O9 j, ^
编译一下) h1 k, B, Q, n7 F2 D0 J) p
  1. Program Size: Code=55136 RO-data=7508 RW-data=548 ZI-data=4060  + e4 K2 w. x5 i0 E; f4 K# Z
  2. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    " `1 F4 I3 Y  J) F; O
  3. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 0 Warning(s).
    6 i  ~! W# h" Q+ O) ]
  4. Build Time Elapsed:  00:00:08
复制代码

7 k) `: U  T* b' Q4 R/ n没有错误,没有警告,下载正常运行。+ F2 J* S. n* H2 [+ x

4 v* r: [- F9 v% h6 ]' s! f# L2,AXI SRAM区域作为主heap$ ]2 g9 C: D2 K
AXI区域 的主要优势是内存大 512K ,支持DMA1 DMA2 IDMA的访问,劣势不如TCM速度快
: F+ I. I/ P! ?4 S6 Z. \5 \1 I, Z9 f" f
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.   ; *************************************************************6 M) K5 f: W7 |$ L! @# m/ s
  2. ; *** Scatter-Loading Description File generated by uVision ***7 p+ T$ u! w: h1 J; ~" f6 [" Q
  3. ; *************************************************************, w/ ^1 \# ^% k1 k$ Z5 \
  4. 6 G8 P2 w  {% B  ?( x) o1 O
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
      J/ p. ]9 P' Z3 \
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    # ?$ T2 Q2 t& H* D" |
  7.    *.o (RESET, +First)
    4 B/ [9 [/ S; V3 ~/ u- G1 q, H
  8.    *(InRoot$Sections), y! C5 ], l) L5 @% s6 z3 O4 P0 L+ b- v
  9.    .ANY (+RO): s$ n* S6 r3 D8 @
  10.   }' [5 ^. q3 g' p6 r& |
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data; Y/ d0 j" ]- F6 {9 ]0 U/ }
  12.    .ANY (+RW +ZI)5 ?5 G# w% b& ]
  13.   }
    1 P7 r8 f: p' @0 S: L; N& \+ R
  14.   RW_IRAM_HEAP 0x24000000 0x00080000  {  ; RW data9 N$ ^+ I  w6 @0 s. R# m
  15.    *(.RAM_HEAP)* h. n4 S3 T, O% k; k9 ]+ J5 J
  16.   }1 `0 M; h( y' H. }
  17. }
复制代码
  1. 第二步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (128)/ C3 g* @$ b6 d8 h
  2. #define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)' q4 K  `% G3 {- i! ]0 J3 K/ ^( V

  3. 1 F4 ^/ o8 A, L7 T* A3 ~, L
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)
    * O7 A6 \" w  W0 j* N  K7 E
  5. extern int Image$RW_IRAM1$ZI$Limit;$ j# K- @8 D* M+ o1 q
  6. #define HEAP_BEGIN      (&Image$RW_IRAM1$ZI$Limit)
    & W5 {; C6 P. ^* [' J
  7. #elif __ICCARM__
    1 @4 K" I: }! W9 x! M
  8. #pragma section="CSTACK"
    # }0 q) d) }" t$ l" \
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    $ h; z! j0 p. j/ u: [2 N
  10. #else
    ' @# [, P, E  h2 U$ K+ v3 H
  11. extern int __bss_end;
    % g5 a. l! y4 k/ v) C: |
  12. #define HEAP_BEGIN      (&__bss_end). d$ S8 ]. f6 _7 T
  13. #
复制代码
  1. 第三步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (512)
    9 U) n( g7 H+ r. x6 Q: }! ?( P, V0 @4 [
  2. #define STM32_SRAM_END            (0x24000000 + STM32_SRAM_SIZE * 1024)" f' [$ N5 v& ^. q; z
  3. 8 `$ `5 _: ]6 K
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM), r: V$ [  S" S: Z' `2 x. @$ o- Q- B
  5. //extern int Image$RW_IRAM2$ZI$Limit;
    ! {% j/ C, m" Z+ \3 c& P
  6. #define HEAP_BEGIN      0x24000000//(&Image$RW_IRAM1$ZI$Limit)  @8 i; k4 n% ~. v
  7. #elif __ICCARM__; f. k% s$ w# Y. Q! Y
  8. #pragma section="CSTACK"3 u3 A* {9 T9 U0 @1 _7 y# E
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))2 W7 h2 n- c9 @+ G. J4 P: F& L
  10. #else, d5 i/ y( u" G) Y* d6 {- S
  11. extern int __bss_end;
    $ R) a! S/ e7 A
  12. #define HEAP_BEGIN      (&__bss_end)
    4 Y8 c2 y  X8 D8 Q
  13. #endif
复制代码
设置heap的起始区域是0x24000000区域的512k大小。
7 H, ^6 Q% }( @0 v1 Z7 Z修改完毕看一下,来测试一下0 v' L# G7 E0 d4 h/ u
. a7 D) p" h  P( }
  1. #define LED0_PIN    GET_PIN(B, 10)
    / i7 h+ Z, D2 T! y2 F& b+ i
  2.     uint8_t test_buff[1000]= {0};. |" Y! R9 v5 [7 C) E
  3. int main(void)
    + z8 V$ u% N+ m# q( _; t
  4. {   
    : V' ^! r) H+ ^. S$ d5 N
  5.     int count = 1;
    / d2 r! p! \) p' h/ I
  6.     /* set LED0 pin mode to output */$ {! }6 m8 ^, s- v7 @/ C
  7.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    ( ]" P/ o. T1 k/ B. k

  8. ' A& o- u7 i! b+ Q
  9.     char *test_ptr;
    + {6 }3 }7 {) h& r) i3 {
  10.     test_buff[10] = 1;
    ( C1 `! I! Z* Z/ r
  11.     while (count++)' e2 z* h- k; V7 Q& [0 v4 p& q
  12.     {
    ' ^& O( J' g2 P' g; \
  13.         test_ptr = rt_malloc(100);
    * t+ v! D/ I: J' f. }
  14.         rt_pin_write(LED0_PIN, PIN_HIGH);
    ' z  H/ D6 P5 n  }; I$ C  E
  15.         rt_thread_mdelay(500);
    : n% E) W, b' S3 Q
  16.         rt_pin_write(LED0_PIN, PIN_LOW);
    ( c+ @$ x) |1 E: s/ z
  17.         rt_thread_mdelay(500);- ]7 H4 {, v7 N/ v7 i  y4 _
  18.         rt_free(test_ptr);1 ]' S6 r, v2 r7 g) K9 j
  19.     }0 |1 t; c* H& W9 h% C& M
  20.     return RT_EOK;5 @. f+ r7 Q0 i, e
  21. }
复制代码
3 M4 D& g- ^" t% b# U
编译一下2 ^/ R, d* e7 a# D
  1. Build started: Project: project' b! \+ {7 Z" F/ ]0 {8 C8 A
  2. *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
    . q9 q. V+ O0 N) @# n) f0 P
  3. Build target 'rtthread'
    , W" }1 s' E* b' i' B% W
  4. compiling main.c...
    # \6 K- B/ x: D) m$ v3 b
  5. linking...! b; R4 A2 k  n- k- n/ ~' G, |
  6. .\board\linker_scripts\link.sct(15): warning: L6314W: No section matches pattern *(.RAM_HEAP).
    : A- ?& D0 E, \
  7. Program Size: Code=55084 RO-data=7508 RW-data=548 ZI-data=4964  ) f) T& x+ R/ y3 A
  8. Finished: 0 information, 1 warning and 0 error messages.) z3 o4 f7 e/ S( ^' r3 r0 B9 }
  9. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    0 Z3 k8 I- h* D% Q% k/ k- j8 @! h
  10. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 1 Warning(s).
    " m( M. A) M3 v2 _7 `2 x
  11. Build Time Elapsed:  00:00:02
复制代码

5 _7 O" ^, {8 y3 C  B& D: g0 s+ x有一处警告 不要紧,查看一下map文件: ~4 `# E; w- V0 d, B) ^% u/ @$ d
7 a! Q" B) K- v7 V
20200219233304754.jpg
- c& [0 w) H: U, U

$ K  e# F4 m7 D可以看到定义的test_buff是在地址0x20000898的位置。
/ O* d) m8 m; R: L( k- T5 d7 J4 Y* b5 P" U, u; S+ C# R
三 总结分析/ O# ~: t% @+ E; O3 X
实验成功; n! o4 U$ ?; C
/ k3 g3 j7 r+ Q3 Z' h" H
TCM作为了主heap既使用rt_malloc来分配tcm区域的内存,axi_sram_malloc 来分配 axi区域的内存,但是这种方法存在一个问题,如果在使用DMA的时候,会出现问题,RT-Thread的组件默认使用了rt_malloc去申请内存,如果想正常的使用这种方法,需要更具实际情况去把组件里面的rt_malloc去替换成axi_sram_mallo。
: l* I7 ^6 ?& ^/ O! i- n4 Q; ]& U1 p. V
AXI_SRAM做为主heap既使用rt_malloc去分配axi_sram区域的内存。如果要使用tcm区域,那么就直接定义全局变量就可以了。使用这样方法存在的问题就是无法把高速的tcm利用率最大化,优势就是就是不需要重定向RT-Thread组件里面的rt_malloc。- R/ |& I9 X( W+ J

" X$ O) L9 H' d# X& n1 A0 y4 [
7 c7 a( a' y# H) v0 F" X+ B) A6 w+ w1 ^3 f
收藏 评论0 发布时间:2021-12-27 18:00

举报

0个回答

所属标签

相似分享

官网相关资源

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