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

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

[复制链接]
STMCU小助手 发布时间:2021-12-27 18:00
一,STM32H7 RAM介绍" r. R2 z+ S9 S1 W8 C# f' a
使用过STM32H7的朋友应该知道H7的RAM是有很多的区域的,不同的区域,使用了不同的总线,所能支持的外设也就不一样了,具体的总线结构如下图所示
4 Z% q  `4 L/ G7 d
2020021922201274.jpg

0 |" M9 t  v' T5 L8 B3 V
/ x, v5 C/ ~3 M+ I7 |( g
20200219221709559.jpg
% x5 W! j9 B7 j1 O

. F: @# T. r9 x3 @通过上图和上表就能发现如果要使用DMA就必须对多RAM进行管理,要么自己去实现内存管理,要么通过__attribute__ 关键字去定义,这样或多或少会有些麻烦,后来看到安福莱STM32H743动态内存管理,同时分区管理AXI RAM,DTCM,SRAM1等五块空间 这篇文章,想到RT-Thread 肯定也应该是支持多内存管理的,看到查看官方的文档中心发现 可以使用 memheap 管理算法。) W: H5 W# J+ p- G( ^
0 {$ ^: u9 w, ~6 N/ Z, @# z
20200219224822144.jpg

3 h: e- w; [8 d/ p: q7 U! O5 u- e* E) t1 O- O2 a  ~
既然RT-Thread 已经支持了多内存的管理算法,那么接下来就要考虑一个问题,RT-Thread是默认使能HEAP,且RT-Thread很多优秀的组件都使用了动态内存,所以要解决究竟是哪一块内存分给rt_malloc 使用。
! t2 W0 g5 `8 z8 Z. u
. W0 B' C& y; `二 多RAM管理办法
: y0 ?, _7 e/ L& J/ O2 d! NSTM32H7的内存可用内存有很多,DTCM和AXI SRAM使用哪一个作为主heap呢?本文分别对DTCM和AXI SRAM做主heap来进行介绍。7 o/ Y5 t9 Z, d2 y5 N$ t1 v, t
首先找到RT-Thread bsp/stm32/目录下的stm32h7的支持包,通过ENV工具打开 memheap
8 S2 S' |6 B! W  e, P$ S% q1 `' o: s
20200219230749268.jpg

% {- L, t' E7 Y# y" n# X3 o: s: r% D! ^. D1 M
之后重新生成工程。, l9 F4 n/ ?# P/ u4 I! v
' F! o% X$ E* ^) p/ Y0 b2 R
1,TCM区域做为主heap% l6 q4 H' J" [
TCM区域的优势是速度快,仅仅只支持MDMA的访问,但是内存小只有128K,不支持其他DMA的访问, s8 f# n9 q! M! E+ T2 }

# c3 W. G7 u) U- q9 C8 i9 ]
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.       ; *************************************************************1 ]- Y- @, ~2 q4 b5 P4 Z7 E
  2. ; *** Scatter-Loading Description File generated by uVision ***
    # y' ~! |2 E* s$ Z; |
  3. ; *************************************************************  G0 C9 f" F' b8 @
  4. ( f1 h, }! n  l# n
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    # z: {5 R$ `1 m7 E1 k/ N
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
    & q4 M# p! f& Z* Z5 Q- E) L. [. h
  7.    *.o (RESET, +First)
    6 H4 b: P8 P2 H: T( m
  8.    *(InRoot$Sections)% o. h5 B/ X; [$ ^$ y8 a9 _
  9.    .ANY (+RO)7 V) I  K# A" W0 h
  10.   }
    & N9 G) h* Y0 H9 m- p
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data' e! X8 D7 K0 p" T
  12.    .ANY (+RW +ZI)
    $ E; |& I) j7 O  N$ Y- g
  13.   }8 _" q$ N. L8 v. L
  14. }
复制代码
  1. 第三步 写一个axi_sram.c
复制代码
  1. struct rt_memheap axi_sram_heap;. x- i  T1 P4 d6 b
  2. void *axi_sram_malloc(unsigned long size)* k. x% v- r! n# y4 ~
  3. {3 I0 a9 Q  y" ^7 k$ x. u- x
  4.     return rt_memheap_alloc(&axi_sram_heap,size);
    5 Y: V; p  A" c3 m! d3 E
  5. }
    " W6 q5 w1 b* M$ Y( u

  6. # j! U, _, y; w7 s, J
  7. void axi_sram_free(void *ptr)
    / n, N% U' j6 o8 K
  8. {
    : a- Z. j" c7 O4 E( s) Z$ g3 [6 H+ R
  9.     rt_memheap_free(ptr);
    , R2 O3 [. P) V' X; E5 Z
  10. }
    ' I) c: h: i; Z% z: U& {& v
  11. # E4 C6 }$ a8 q# W, O8 C/ s
  12. void *axi_sram_calloc(unsigned int n,unsigned int size)
    + `; f% Z" E2 O7 d, B' ?6 T9 o8 f
  13. {
      y5 q) p9 l6 u! W1 b1 \5 A& ?6 c% ?
  14.     void* ptr = NULL;4 C# U, }. y8 c

  15. : d( I. }  {+ [' ~& I9 R
  16.     ptr = axi_sram_malloc(n * size);
    1 k" M7 y0 B, V, {; Q
  17.     if(ptr)5 u0 e" d/ w7 W/ Z4 U5 X5 g
  18.     {
    + `1 U, \3 c$ h! j4 p( U
  19.         memset(ptr, 0, n*size);; s3 y' L( j2 J
  20.     }
    # `# X: g- c  c

  21. 9 w) e  D' \- R. @& ?! F
  22.     return ptr;
    0 H8 @+ G- j! Z5 j0 Y9 S  W2 P7 F
  23. }
复制代码
  1. 第四步 修改drv_common.c,增加一行axi_sram初始化的代码
复制代码
  1.   #if defined(RT_USING_HEAP)
    . Q9 D. E4 a! n% K4 K" F, s
  2.     rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END);
    + i5 R0 d8 R! m) {4 a9 l' K
  3. #endif; `, E; U" j- ]: D
  4. / ~, r6 X3 U5 |
  5.     rt_memheap_init(&axi_sram_heap,"AXISRAM",(void *)RT_AXI_SRAM_BEGIN,RT_AXI_SRAM_SIZE);   
复制代码
编写一个测试代码1 H' q' ~* P* z6 H
4 X, F6 S; E/ {) h  v6 T
  1. int main(void)' o+ O# b( `1 v9 T
  2. {
    - @0 l+ s9 T- _) s: K" U, K, m5 L
  3.     int count = 1;
    5 o( ~: U' z# j& d
  4.     /* set LED0 pin mode to output */1 e6 C0 S- @! y1 U: V! M
  5.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    " ?8 h) H7 M% A, w
  6. ( h# J3 i) v. h  g8 E/ E
  7.     char *test_ptr;. X$ Y6 r6 _* y

  8. 0 p" S8 l) o$ R4 y: A+ _* ~% d
  9.     while (count++)
    7 m4 ?7 y' b0 D+ |) ?0 E
  10.     {
      _6 {; A! ]6 I4 j
  11.         test_ptr = axi_sram_malloc(100);
    7 N+ z6 }1 y9 `! C# l( b/ n
  12.         rt_pin_write(LED0_PIN, PIN_HIGH);
    . J( p6 u1 J9 Z0 v
  13.         rt_thread_mdelay(500);! d9 e9 @3 \+ T" n4 E
  14.         rt_pin_write(LED0_PIN, PIN_LOW);
    ( Y9 o( G6 M) ]9 H6 g( n
  15.         rt_thread_mdelay(500);# P4 k6 D0 ]+ D! C2 [1 M
  16.         axi_sram_free(test_ptr);  e1 F$ E# a1 t# {
  17.     }
    , c$ F$ A  k1 Z3 t
  18.     return RT_EOK;# c2 J2 u3 M+ w; S3 s0 W
  19. }
复制代码

& R9 I# Q* c3 ?1 J, [编译一下2 B" q% ?' x7 m" ^0 @4 M
  1. Program Size: Code=55136 RO-data=7508 RW-data=548 ZI-data=4060  
    $ W6 v' a3 \9 O! k8 [6 h
  2. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin# [3 b2 u9 P  R0 A8 G
  3. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 0 Warning(s).0 u. U  ~- w) A9 Z) h) L7 r
  4. Build Time Elapsed:  00:00:08
复制代码

9 m  n0 f! ~* T, {6 u* E没有错误,没有警告,下载正常运行。$ ]' ?  \4 y. M$ B7 h# e
4 ~# R  n$ {$ F$ p
2,AXI SRAM区域作为主heap. p' N" C, u0 E) e! z% k9 W8 Z8 W
AXI区域 的主要优势是内存大 512K ,支持DMA1 DMA2 IDMA的访问,劣势不如TCM速度快
+ {- `/ T9 W5 ]2 Z' S# a" D- y. T9 @6 W9 }
  1.   第一步 修改keil连接文件link.sct  
复制代码
  1.   ; *************************************************************
    / {+ [0 P& y4 W# N) `
  2. ; *** Scatter-Loading Description File generated by uVision ***, t# d! z4 D" r* ?- J) |, w
  3. ; *************************************************************# P+ t" x6 e* x7 L

  4. - ]0 a) Z) v, ~( `
  5. LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
    # _* ?1 D$ H8 g: k% w/ S% ], x
  6.   ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address0 f) H0 r! j/ d% H$ E5 X" A" l
  7.    *.o (RESET, +First)
    8 o, w2 V, h* e
  8.    *(InRoot$Sections)) s! s9 i# D4 l, M$ D, t! r
  9.    .ANY (+RO)' _! w+ Q+ R$ w$ R% Q8 r* G
  10.   }$ O7 T" l3 \$ s9 ~$ ?
  11.   RW_IRAM1 0x20000000 0x00020000  {  ; RW data. e& D  Y2 K3 z0 q3 }& L& b) T
  12.    .ANY (+RW +ZI)
    2 _6 U/ C# w4 i9 c- o" Y  ]
  13.   }4 a, I+ B; q9 p3 }0 }9 O7 Y
  14.   RW_IRAM_HEAP 0x24000000 0x00080000  {  ; RW data
    ; \7 A+ A1 Q. ?3 g% o5 t/ H! _
  15.    *(.RAM_HEAP)
    ( h5 h7 i, P1 {2 V
  16.   }
    $ T. ]& m- C* e3 X
  17. }
复制代码
  1. 第二步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (128)
    ) b! o, \# J* U6 G& Q" z
  2. #define STM32_SRAM_END            (0x20000000 + STM32_SRAM_SIZE * 1024)
    / n0 }- i6 Y2 L5 m' N3 G% @' W
  3. 0 T5 Y: e6 a. o: k8 Y. t7 `
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)+ g0 X$ }  F4 d/ W' p: B8 i8 ^
  5. extern int Image$RW_IRAM1$ZI$Limit;! Z  F5 S( _6 C4 A! U; R% L
  6. #define HEAP_BEGIN      (&Image$RW_IRAM1$ZI$Limit)
    . c1 s! i% I. E1 C" p- H
  7. #elif __ICCARM__
    7 }0 W# u( r1 o7 P" g* z
  8. #pragma section="CSTACK"
    & c' M, N1 [6 l+ \
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    ' i5 h" J: M% X+ Y3 a3 K* t* {
  10. #else
    8 I1 T% U+ n$ p$ P: ?: q2 e9 s
  11. extern int __bss_end;* ~; M( O; h- A- V! ]0 U
  12. #define HEAP_BEGIN      (&__bss_end)6 X* e0 R) R* D% m  l/ ~
  13. #
复制代码
  1. 第三步 修改board.h
复制代码
  1. #define STM32_SRAM_SIZE           (512)
    # R# l% B" F* W; L7 ?! e
  2. #define STM32_SRAM_END            (0x24000000 + STM32_SRAM_SIZE * 1024)/ R- ^; t( n( A& T

  3. 0 }( j* @; P0 E% m+ ^' M
  4. #if defined(__CC_ARM) || defined(__CLANG_ARM)5 m! Z: z- x1 C# B+ v. X
  5. //extern int Image$RW_IRAM2$ZI$Limit;
    - w6 s. x$ g  |
  6. #define HEAP_BEGIN      0x24000000//(&Image$RW_IRAM1$ZI$Limit)0 `4 n0 ^* B5 }$ M8 ?) q
  7. #elif __ICCARM__
    5 n0 v; }& d3 q7 k
  8. #pragma section="CSTACK"
    & j1 ^% ^' D9 f
  9. #define HEAP_BEGIN      (__segment_end("CSTACK"))
    9 A$ z. n4 V( c8 T0 H$ f
  10. #else; d( x1 P1 R8 l8 j" U+ a+ l* E% V
  11. extern int __bss_end;
    / W3 n* K5 ~; O3 _( U; q
  12. #define HEAP_BEGIN      (&__bss_end)
    / I& L3 ]3 g' F9 G7 j3 S: m7 x' ~
  13. #endif
复制代码
设置heap的起始区域是0x24000000区域的512k大小。
1 r) |, B1 Y7 C" R$ l修改完毕看一下,来测试一下! u" L  r- R% |/ M5 z! C- Q- y

! }- A! b; X# k3 @4 w2 T6 v7 e
  1. #define LED0_PIN    GET_PIN(B, 10)
    . k) P' N! |& `# h: Z) w
  2.     uint8_t test_buff[1000]= {0};4 `" [7 {' G, |% p
  3. int main(void)
    1 G$ A5 S) ?  A# t' v
  4. {   
    ( x% _, _! t1 l% M, w- s9 T
  5.     int count = 1;& J/ m' j! S4 W' m
  6.     /* set LED0 pin mode to output */
    ( s( E( x$ K; Y6 C3 a& P6 F) e
  7.     rt_pin_mode(LED0_PIN, PIN_MODE_OUTPUT);
    , h, G) |' F# K( a  z3 ~) \

  8. 6 w7 |- |5 s2 b7 X4 s
  9.     char *test_ptr;
    ; j+ F$ d& Z$ _1 b$ n, B! P/ [
  10.     test_buff[10] = 1;
    : n+ s/ t* F& F9 c) D: X0 s1 P
  11.     while (count++)
    $ g/ I& k) j, [' h# [
  12.     {5 S, J- |  U/ f9 k
  13.         test_ptr = rt_malloc(100);
    / b$ J2 ?% }$ z* ]! m) ~
  14.         rt_pin_write(LED0_PIN, PIN_HIGH);
    & ?. N1 u8 J3 }3 w: O
  15.         rt_thread_mdelay(500);
    1 D6 n9 ]7 b0 G  u0 {7 h3 ]
  16.         rt_pin_write(LED0_PIN, PIN_LOW);
    9 c7 v( Z- E* R6 j& |6 W" S
  17.         rt_thread_mdelay(500);: f' h7 K+ m4 M- i+ g
  18.         rt_free(test_ptr);) N) P+ g( t4 |3 v2 o/ W) }) g" T4 W1 h
  19.     }
    - J/ Y( l' ~, o" X" o
  20.     return RT_EOK;+ i; `% W! q- b9 U9 f# F
  21. }
复制代码
6 O( O9 ~# u* l  E9 Q( F7 g
编译一下' I. ]$ [! v" U1 i- m
  1. Build started: Project: project! }" X/ K4 Y! e! ]3 K. |( [
  2. *** Using Compiler 'V5.06 update 6 (build 750)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'. u0 ^' g# g% E6 w7 ~& W6 O
  3. Build target 'rtthread'
    ! c9 _" I+ t  \7 \3 T  }' c3 F/ H
  4. compiling main.c...0 @7 V6 @) ?9 F* {6 X1 W: i
  5. linking...7 A, [+ l, d, u; k! x
  6. .\board\linker_scripts\link.sct(15): warning: L6314W: No section matches pattern *(.RAM_HEAP).% [. T4 X' T& ~# |8 c' q
  7. Program Size: Code=55084 RO-data=7508 RW-data=548 ZI-data=4964  . N0 l+ n, ]1 w/ E1 _
  8. Finished: 0 information, 1 warning and 0 error messages.
    : _% f( U) D0 h& ~* l6 l7 C5 |
  9. After Build - User command #1: fromelf --bin .\build\keil\Obj\rt-thread.axf --output rtthread.bin
    ' y8 {8 L# u4 {- K
  10. ".\build\keil\Obj\rt-thread.axf" - 0 Error(s), 1 Warning(s).
    , v! g' B& C8 b' `* @9 n
  11. Build Time Elapsed:  00:00:02
复制代码
4 d$ H3 y4 m5 \( X' |
有一处警告 不要紧,查看一下map文件
3 n; X3 e% Z1 P, G- `, ^  ^2 G4 n$ P6 d0 e  G0 u, W+ [
20200219233304754.jpg

* ^- O& _, k% z: p' {% S5 \
' h7 Z8 M# B4 c2 B可以看到定义的test_buff是在地址0x20000898的位置。+ n8 g7 Z# E; J* n& Y) p* w

# m4 [) {- W4 M4 ?三 总结分析
( [' Y9 j5 V9 v* A# a! l实验成功
$ \: t& l  M6 ]+ G. P, `6 q
* x2 h. c, V5 FTCM作为了主heap既使用rt_malloc来分配tcm区域的内存,axi_sram_malloc 来分配 axi区域的内存,但是这种方法存在一个问题,如果在使用DMA的时候,会出现问题,RT-Thread的组件默认使用了rt_malloc去申请内存,如果想正常的使用这种方法,需要更具实际情况去把组件里面的rt_malloc去替换成axi_sram_mallo。9 A7 u# c: d- c1 V0 G$ O" T
5 b* O  x; L2 k6 X) r9 H3 y7 \
AXI_SRAM做为主heap既使用rt_malloc去分配axi_sram区域的内存。如果要使用tcm区域,那么就直接定义全局变量就可以了。使用这样方法存在的问题就是无法把高速的tcm利用率最大化,优势就是就是不需要重定向RT-Thread组件里面的rt_malloc。, h4 h; e# ^  l

! d$ V9 A- T1 Q
5 }  E1 z& F9 p
0 N  r8 \% f" n" s1 Q6 ~
收藏 评论0 发布时间:2021-12-27 18:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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