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

【经验分享】STM32F7xx —— 内存管理

[复制链接]
STMCU小助手 发布时间:2021-12-11 12:00
目的:高效、快速的分配,并在适当的时候回收内存资源。最终就是实现malloc和free函数。(实现方法参考原子哥)# t: d: e7 [3 e6 K6 S

% A+ E8 |, @6 R, g( B/ [
  1. #define CONFIG_SRAM_OUT_ENABLE     0
    " n, b& z3 p7 ?+ {7 a
  2. # @) v4 f6 w- P% ]
  3. typedef enum
    0 }0 w- r$ `+ q+ @& n$ L
  4. {' o8 u# `" S1 A+ }, i( |. @. k$ u
  5.   SRAM_TYPE_IN,   // 内部内存池" i3 f5 \% y& T: b" O0 h9 S- o" ^
  6. #if(CONFIG_SRAM_OUT_ENABLE == 1)
    ' I- }* ^: S/ m
  7.   SRAM_YPE_OUT,   // 外部内存池(SDRAM)
    3 g+ a2 s+ Y" }1 ^* W
  8. #endif
    # v5 o4 L; b/ B
  9.   SRAM_TYPE_DTCM, // DTCM内存池(此部分SRAM仅仅CPU可以访问!!!)! j' }+ D9 v( {+ J( U+ `
  10.   SRAM_TYPE_MAX,  // 最多支持的SRAM块数.
    & ~5 t$ o; \0 p9 h
  11. } sram_type_t;% ^+ W. [5 H8 M* I1 O8 k/ Q# J

  12. 6 i" j7 R# r2 V6 Q
  13. // 内部SRAM0 @4 r0 m3 U) {; [, n7 M9 J
  14. #define SRAM_IN_BLOCK_SIZE        64            // 内存块大小为64字节
    ! ?/ s" T' b1 M3 h; ?5 `8 Z8 u) t# z
  15. #define SRAM_IN_MAX_SIZE          (160 * 1024)  // 最大管理内存160K, D' ]: k& ]) \
  16. #define SRAM_IN_ALLOC_TABLE_SIZE  (SRAM_IN_MAX_SIZE / SRAM_IN_BLOCK_SIZE)' T" A/ n  J' d3 `$ \, o/ z
  17. 0 t, @/ D) A0 D  c! P. x
  18. #if(CONFIG_SRAM_OUT_ENABLE == 1)
    5 Q1 U- v& _2 C# d
  19. // 外部SDRAM里面
    ) l% v! v; ?% z, f1 C) w
  20. #define SRAM_OUT_BLOCK_SIZE       64            // 内存块大小为64字节& J: f% v5 y, ~3 \) d9 [
  21. #define SRAM_OUT_MAX_SIZE         (100 *1024)   // 最大管理内存100K
    9 d& ~( z0 D3 P1 g
  22. #define SRAM_OUT_ALLOC_TABLE_SIZE (SRAM_OUT_MAX_SIZE / SRAM_OUT_BLOCK_SIZE)) V5 z3 h$ j% c0 ~) K2 [( ]
  23. #endif
    ) A% \$ Y3 \1 G6 P* b6 s% d

  24. 0 N- M% c: w5 t7 F3 }0 R
  25. // CCM,用于管理DTCM(特别注意,这部分SRAM,仅CPU可以访问!!)
    , x# A  `# y3 Y- h
  26. #define SRAM_DTCM_BLOCK_SIZE      64                  //内存块大小为64字节
    ( z8 k1 U' e3 H, J7 ~
  27. #define SRAM_DTCM_MAX_SIZE        (100 *1024)             //最大管理内存60K
    ! }  t# d5 c3 Q: J0 @1 G: j; g
  28. #define SRAM_DTCM_ALLOC_TABLE_SIZE  (SRAM_DTCM_MAX_SIZE/SRAM_DTCM_BLOCK_SIZE)3 G4 N. X7 b; Z3 y8 h
  29. //内存池(32字节对齐): \# F* t+ B) X+ e& A: p. {
  30. __align(32) uint8_t sram_in_base[SRAM_IN_MAX_SIZE];                                      // 内部SRAM内存池3 @& Z! b1 q5 @9 B: U2 j
  31. uint32_t sram_in_map_base[SRAM_IN_ALLOC_TABLE_SIZE];
    1 |# f/ }$ H- v8 o! @4 \9 L

  32. 5 w* Q/ z4 _9 T9 Q( o7 }7 _; }. r# t
  33. #if(CONFIG_SRAM_OUT_ENABLE == 1)2 y) w2 J0 f6 {, R3 d7 i7 d
  34. __align(32) uint8_t sram_out_base[SRAM_OUT_MAX_SIZE] __attribute__((at(0xC01F4000)));   // 外部SDRAM内存池/ r$ P4 y4 |* f
  35. uint32_t sram_out_map_base[SRAM_OUT_ALLOC_TABLE_SIZE] __attribute__((at(0xC01F4000 + SRAM_OUT_MAX_SIZE))); // 外部SRAM内存池MAP7 \0 H- q0 F5 z2 p: k
  36. #endif. R4 G: |+ u$ ~
  37. 3 P" P- k9 y7 Z8 c  s
  38. __align(32) uint8_t sram_dtcm_base[SRAM_DTCM_MAX_SIZE] __attribute__((at(0x20000000))); // 内部DTCM内存池- ?2 |9 H1 Q" a/ l& i
  39. uint32_t sram_dtcm_map_base[SRAM_DTCM_ALLOC_TABLE_SIZE] __attribute__((at(0x20000000 + SRAM_DTCM_MAX_SIZE))); //内部DTCM内存池MAP3 ~& p+ I: g$ C2 o

  40. # w6 y; H9 u6 \
  41. static const uint32_t memtblsize[SRAM_TYPE_MAX] = {SRAM_IN_ALLOC_TABLE_SIZE,
    / G/ {% x; m. F; G1 x, Z' z
  42. #if(CONFIG_SRAM_OUT_ENABLE == 1)/ u1 W4 d7 Y8 s4 M$ t3 x3 C
  43.                                             SRAM_OUT_ALLOC_TABLE_SIZE,
    " _* m( J7 W. P: P
  44. #endif
    " c& F: z6 Q$ w
  45.                                             SRAM_DTCM_ALLOC_TABLE_SIZE& s& L0 P% B& u9 b% L6 c
  46.                                            }; //内存表大小7 I2 _! _9 r. l

  47. 3 ^4 b, d4 ?. ^2 y0 b1 p
  48. static const uint32_t memblksize[SRAM_TYPE_MAX] = {SRAM_IN_BLOCK_SIZE,
    ) X  R( q5 _2 b9 B3 p9 o
  49. #if(CONFIG_SRAM_OUT_ENABLE == 1)
      y8 n6 U0 k1 Z( w* X
  50.                                             SRAM_OUT_BLOCK_SIZE,& i/ o. j% F9 k
  51. #endif
    1 s" N' m; H0 F8 r
  52.                                             SRAM_DTCM_BLOCK_SIZE
    1 U! J: z( s- d& a) X2 e8 S3 i
  53.                                            };     //内存分块大小+ {7 S( n& j, C* w2 t2 D

  54. 1 n. M. H& z  y
  55. static const uint32_t memsize[SRAM_TYPE_MAX] = {SRAM_IN_MAX_SIZE,+ {$ P/ _2 r8 c3 G
  56. #if(CONFIG_SRAM_OUT_ENABLE == 1), @( W0 `, W; ^$ p' H% G
  57.                                          SRAM_OUT_MAX_SIZE,
    , T# P" h& X/ q' Q# P
  58. #endif
    6 W! y( B& e" R+ g9 l
  59.                                          SRAM_DTCM_MAX_SIZE
    ; |5 S9 U: B! k6 `! e5 l' e" \+ `
  60.                                         };          //内存总大小
    , z8 \. h* V3 ~- e" z8 I

  61. ! |. G9 m: h. W; T: B& Q
  62. void mymem_init(uint8_t type);4 W' F9 p: c3 g, D) @
  63. uint16_t mymem_perused(uint8_t type);
    8 C! ~9 C! N$ f, M

  64. . W  P% W7 v6 y/ [& W( L" `. {
  65. typedef struct( t6 N+ g' W1 A5 N$ `" ?" h9 l, S
  66. {
    3 @  n" D5 i4 U/ C$ ^$ N
  67.         void (* init)(uint8_t );
    1 t0 u1 {# I( N9 |# S
  68.         uint16_t (* perused)(uint8_t);                 // 内存使用率0 S2 q6 z1 @2 T4 X" d
  69.         uint8_t         *membase[SRAM_TYPE_MAX]; // 内存池 管理SRAMBANK个区域的内存
    ; M# N8 D  W3 T6 R
  70.         uint32_t *memmap[SRAM_TYPE_MAX];          // 内存管理状态表' v* m: u2 ~% y) Z& ^" ?
  71.         uint8_t  memrdy[SRAM_TYPE_MAX];    // 内存管理是否就绪) A& C3 }8 v0 I) L" y  b! E
  72. } sram_dev_t;
    ! X7 E2 p# |  l- `, [6 [
  73. / k' L, {  Q, N
  74. //内存管理控制器7 i) h6 G9 F6 w$ X. C! i7 k
  75. static sram_dev_t sram_dev =
    6 Y7 H; d6 ?- u
  76. {
    - C% n/ y* }) i  l. b. ~3 |
  77.   mymem_init,        // 内存初始化
    8 G( R! O6 h! ]# z- {( L
  78.   mymem_perused,     // 内存使用率: E# B+ u! g$ J5 o: x
  79.   sram_in_base,: X' Z! M; ~* {$ R; v8 g

  80. 5 h' ?5 Q9 W# p* x+ H8 b- m
  81. #if(CONFIG_SRAM_OUT_ENABLE == 1)7 x+ \/ o6 O. r
  82.   sram_out_base,( ?9 G! a* U0 y9 ]. v
  83. #endif% L7 \0 ~8 q2 g6 T) t  z
  84.   sram_dtcm_base,  // 内存池# X: _8 c1 m! _- b9 [$ P
  85.   sram_in_map_base,
    $ C' g) h; G$ T5 J
  86. #if(CONFIG_SRAM_OUT_ENABLE == 1)
    3 V& M7 |) H4 g
  87.   sram_out_map_base,
    8 |4 e" z1 n' h5 B
  88. #endif
    ( ~  ^0 X0 k! B7 `
  89.   sram_dtcm_map_base,
    2 V# |+ D* J$ P0 V9 @9 g3 S
  90.   0,
      s* _  a* L( H4 ?
  91. #if(CONFIG_SRAM_OUT_ENABLE == 1)
    ( N. Y% D8 H# l2 q/ c
  92.   0,
    ( Q: r: P- t0 D2 |: B" l0 h: w
  93. #endif' w' q  E1 A- p+ {- c
  94.   0,3 A" z) }/ n5 n
  95. };* ?: s. G9 T% }  {0 G  R# X

  96. 1 K! S: H# Z4 f, ^  }
  97. // 内存管理初始化/ `, s" F& a5 G" s
  98. static void mymem_init(uint8_t memx)
    # u/ |( l+ T: g7 J! t; G
  99. {
    # K$ N" Q! Y, X
  100.   memset(sram_dev.memmap[memx], 0, memtblsize[memx] * 4); // 内存状态表数据清零' z0 q" o! x: [& L/ T# T4 T( k# S
  101.   sram_dev.memrdy[memx] = 1;                              // 内存管理初始化OK# a( W0 h3 `) }; H2 |
  102. }" L6 E4 |+ _+ c& d( X9 K2 a
  103. . Q9 K' v" _& V! c; ?& {
  104. // 获取内存使用率. \0 }# M7 h0 K) U
  105. // type:所属内存块
    : h0 p% B! T7 N8 i/ B
  106. // 返回值:使用率(扩大了10倍,0~1000,代表0.0%~100.0%)5 c  Q/ v+ w1 ^
  107. static uint16_t mymem_perused(uint8_t type)1 r- f. z9 i" C4 f4 }
  108. {
    $ W3 K1 U5 N. A. E3 i
  109.   uint32_t used = 0;5 S: V5 E2 a4 ^/ V3 X" T% f) L
  110.   uint32_t i;) |$ w6 _9 U( t/ }" B
  111.   for(i = 0; i < memtblsize[type]; ++i)" C/ M9 f4 D+ Y& f3 G6 R$ k
  112.   {# \2 G5 f4 e0 N+ B3 [2 t% p
  113.     if(sram_dev.memmap[type]<i>)</i>+ a, _* U$ t: j$ ], Q4 p
  114.     {, S# b  x/ G& ]8 l0 S- g4 w
  115.       used++;) B. S1 F! v5 M0 @& Q+ k% g! E4 a  m
  116.     }
    ' }8 a+ {0 w9 d/ u1 Q# K
  117.   }
    , q$ ^2 u+ Q3 ?) |
  118.         
    1 P' w; C6 b* Q
  119.   return (used * 1000) / (memtblsize[type]);
    . f' O+ `; R7 s2 C9 K- S% U- Z( d8 _/ L
  120. }6 ]: I4 v6 m# N
  121. + N4 k0 s; r' p+ Z, e
  122. // 内存分配(内部调用)
    % J2 M' U6 m/ c1 s9 o" N( R
  123. // type:所属内存块5 M/ P! ~% ^* O% M2 `2 c4 _
  124. // size:要分配的内存大小(字节)0 Y# M2 p% R% P1 y3 M8 U
  125. // 返回值:0XFFFFFFFF,代表错误;其他,内存偏移地址; s1 ^; s) j% |' x
  126. static uint32_t mymem_malloc(uint8_t type, uint32_t size)
    ' f% r$ ]" g$ Q; o" _9 L
  127. {
    7 b% y' ~  f+ {1 G, T. J
  128.   signed long offset = 0;) [+ q/ m- V( e: U
  129.   uint32_t nmemb;     // 需要的内存块数
    $ K  k4 C% U4 {
  130.   uint32_t cmemb = 0; // 连续空内存块数" s2 v8 v# u, E; O( e
  131.   uint32_t i;3 t9 g) x  q! g. {3 g+ L: t
  132. 2 }$ |4 u% P4 t  D+ ~
  133.   if(!sram_dev.memrdy[type])4 c$ f. d5 v% V! u
  134.   {8 s; v" [6 n- l  [+ R( T
  135.     sram_dev.init(type);  // 未初始化,先执行初始化$ M% W9 [2 G* G/ D9 D
  136.   }5 ]# G. o  E3 R* D/ L
  137.   if(size == 0)
    ) n* a( |$ R+ O  y; @) A
  138.   {
    - b8 q4 B0 s; ?! G: }' t
  139.     return 0xFFFFFFFF;  // 不需要分配% u3 w# x6 s0 f' `) m7 P
  140.   }
    6 R2 Q/ i+ u$ I8 o8 C$ a
  141.   nmemb = size / memblksize[type]; // 获取需要分配的连续内存块数
    4 X$ R2 z# {  D; q1 {( ?
  142.   if(size % memblksize[type])
    : T4 b" e4 @$ w! n
  143.   {
    # D! J$ l% {, F& I  Z. c1 y
  144.     nmemb++;
    & v$ z& t# `% Z' `5 N
  145.   }
    : q- ]# L1 R% h
  146.   for(offset = memtblsize[type] - 1; offset >= 0; offset--) // 搜索整个内存控制区
    1 ^9 N, o! Y6 g% J7 V
  147.   {
    ! E6 q! Y3 Y0 I
  148.     if(!sram_dev.memmap[type][offset])7 ^  x! d  o# d
  149.     {- |8 t0 N/ }$ F% Q' B
  150.       cmemb++;    // 连续空内存块数增加) m" z  i  }" q3 h1 q* V
  151.     }
    5 a) Y5 W/ d0 @4 R5 \4 r
  152.     else/ h! [* Z8 s2 Y* e
  153.     {
    * l, u( `5 }7 R' w5 ]
  154.       cmemb = 0;  // 连续内存块清零9 l& G; w0 d. j, b) r
  155.     }6 g$ u% A% j3 ?6 S* W( |
  156.     if(cmemb == nmemb)                // 找到了连续nmemb个空内存块
    1 j* P( _5 t/ n! G
  157.     {
    3 T# T  A1 v6 h( ~. `
  158.       for(i = 0; i < nmemb; i++)      // 标注内存块非空
    - y2 I* ?! i, ]
  159.       {6 w  R7 _/ _% ?5 U7 j
  160.         sram_dev.memmap[type][offset + i] = nmemb;) c8 J/ z. s" G$ c1 `4 |( m: t% U
  161.       }
    ; P) ?: o  u" E4 b& K
  162.       return (offset * memblksize[type]); // 返回偏移地址3 v1 ]7 H* B9 L$ \8 y/ b" y
  163.     }' k2 a* d; h  B6 t3 z: ~' w* M* q
  164.   }
    5 a( R# }( Z  [& P
  165.   return 0xFFFFFFFF; // 未找到符合分配条件的内存块
    # _" K' W( I% T1 W" a
  166. }2 S  b3 h; L# @0 `/ I3 h

  167.   U0 A8 D9 W) G' l0 E" ^2 ~
  168. // 释放内存(内部调用)
    + ~3 k4 G4 x2 N5 h2 H
  169. // type:所属内存块5 X% p( y  \9 C
  170. // offset:内存地址偏移$ V7 N: }3 x" o5 B- L9 p
  171. // 返回值:0,释放成功;1,释放失败;
    * @; _4 p! ?" x; T# ]
  172. static uint8_t mymem_free(uint8_t type, uint32_t offset)
    , t, s, i7 D: J5 ]  l' V
  173. {! {2 B& B1 v. l8 T1 U
  174.   int i;7 x# c& C7 D9 X3 R: ^  C8 ?
  175.   if(!sram_dev.memrdy[type])// 未初始化,先执行初始化* S2 W% ~; u2 H2 X
  176.   {* g2 S% @- \5 P* P- h
  177.     sram_dev.init(type);
    6 L- g4 V- ^4 d# N0 l, k
  178.     return 1;// 未初始化5 N% @0 n. f1 Y5 m( \/ B0 _) H
  179.   }
    7 D/ k1 c; Z. G1 L: D8 J1 a8 R! g
  180.   if(offset < memsize[type]) // 偏移在内存池内.; p. }: I+ [! Z0 E3 o( X; q
  181.   {
    - D! t0 X. P6 f5 W( A9 K8 W' Z/ j. m
  182.     int index = offset / memblksize[type];    // 偏移所在内存块号码
    4 J+ X9 H8 X0 j5 E" m4 B9 K
  183.     int nmemb = sram_dev.memmap[type][index]; // 内存块数量
    . u3 F' e: X% b9 U* L5 l
  184.     for(i = 0; i < nmemb; i++)                // 内存块清零: @+ a* O1 i) K% Q
  185.     {
    $ ?, Q0 C8 W; b8 A. A* J1 a& J
  186.       sram_dev.memmap[type][index + i] = 0;6 a& s- |: ?4 W: D) M/ m
  187.     }1 {" W  B* ~; c& D% H+ Q1 [3 l
  188.     return 0;3 w, d) h' w; X$ f1 ]& T6 ~" c8 w
  189.   }* z( K8 K* t! @. u3 M. K% S
  190.   else
    1 v7 X; ~$ l! t5 b
  191.   {* E  `4 f8 R; V* r* x" D; K
  192.     return 2;  // 偏移超区了.
    ; z- J$ u$ x3 a% q. T% q. t
  193.   }
    7 ~4 f" z# D/ S
  194. }
    / r9 @/ u6 V* G# F
  195. ' ]! A9 [4 ]5 k( l0 {$ k
  196. void MemInit(uint8_t type), _$ v6 C% J& {* \" J
  197. {. H  i. u) {: I2 ]7 |+ l' C4 v
  198.   memset(sram_dev.memmap[type], 0, memtblsize[type] * 4); // 内存状态表数据清零
    " G' ?2 j. O+ g
  199.   sram_dev.memrdy[type] = 1;              // 内存管理初始化OK
    ' [. ?- f+ x1 h: j  G
  200. }/ s/ I7 k; R. J5 j
  201. " r2 H4 `+ r/ Z
  202. // 释放内存(外部调用)
    5 M) f& j% v, u  \* ~3 ^: X
  203. // type:所属内存块& \" _1 n% }) B" i4 c
  204. // ptr:内存首地址) Q  n( d* z9 b( `3 \8 C
  205. void MemFree(uint8_t type, void *ptr)
    " I1 g- X/ b: H% J7 @% O2 F
  206. {
    + f: d# I, n+ }5 e7 F( \
  207.   uint32_t offset;
    & X/ x3 R! z( s( ~9 a9 f/ S; O
  208.   if(ptr == NULL)
    & o5 y4 J: x7 |  v
  209.   {- p4 f8 \) [( n( Y1 g! {8 K, s5 ]
  210.     return;  // 地址为0.
    - r) u/ S* ~' U1 m" G: p! t! ~5 W/ P5 W
  211.   }
    8 u2 N# p. x$ R# s) J- Z: l% C
  212.   offset = (uint32_t)ptr - (uint32_t)sram_dev.membase[type];# ~. k: Q) T/ N7 Z
  213.   mymem_free(type, offset); // 释放内存1 Z- ]# A8 D% S6 e( M
  214. }4 S; Z+ c/ D; n5 j( o! R+ a
  215. ' b/ w  F% g% F. C+ L( Q2 c5 v
  216. // 分配内存3 \0 `- s; Y6 o; x
  217. void *MemAlloc(uint8_t type, uint32_t size)
    : O. Y% D7 d6 U7 U8 @0 b
  218. {
    0 f: t' y  G$ |' }; D
  219.   uint32_t offset;: O/ k4 w  K& G2 c) E
  220.   offset = mymem_malloc(type, size);
    4 o' Q. \( ~8 w0 I+ a( T3 q
  221.   if(offset == 0XFFFFFFFF)8 O0 ?3 ]) }6 Y' u+ A
  222.   {- i9 t' q3 Z1 g  f* K- h3 k
  223.     return NULL;7 ~. d2 b& O: ~5 G, u# }0 B
  224.   }
    ' @' |( _. [7 }$ w1 V
  225.   else
    . q) |+ P3 f& o/ f& S2 B* D2 g
  226.   {
    8 }! i. W/ J. o3 |, }
  227.     return (void*)((uint32_t)sram_dev.membase[type] + offset);! n  K3 S0 Z8 D3 n- g4 ~# E2 l8 y
  228.   }
    / R1 ^5 |" d; `0 Q& Z2 l$ [& a
  229. }6 {9 u$ Q  r* H
  230. 2 W& |1 S* s1 g
  231. // 重新分配内存
    , x; X" t/ R6 s
  232. void *MemRealloc(uint8_t type, void *ptr, uint32_t size)1 b$ G/ [; x  c* N
  233. {
    8 e5 |1 j" D" j- q% h+ M5 \
  234.   uint32_t offset;" c* \# _8 ]: _
  235.   offset = mymem_malloc(type, size);
    $ Q  i, a5 i8 _: {7 b# l# ]
  236.   if(offset == 0xFFFFFFFF)# ~% n- W7 w# R, ^
  237.   {$ m' O2 m$ E$ F! k2 ]
  238.     return NULL;
    $ e3 _0 A3 k1 }8 ^- R& h8 L3 F
  239.   }9 I/ H/ N- j. h4 S  p8 R$ n- F4 q
  240.   else
    9 l; i& J1 l/ Z6 F
  241.   {' \* |- ^9 H0 l2 }' z) v* H9 n# {" Y, R
  242.     memcpy((void*)((uint32_t)sram_dev.membase[type] + offset), ptr, size); // 拷贝旧内存内容到新内存# a0 u  _% c" V0 h8 h/ c/ c/ i
  243.     MemFree(type, ptr);                                                     // 释放旧内存) k7 X+ j" t4 N9 l5 z
  244.     return (void*)((uint32_t)sram_dev.membase[type] + offset);              // 返回新内存首地址
    * r8 J( r3 s& }3 L# h
  245.   }8 O5 p9 w8 C$ i8 D/ B3 x
  246. }
    * T5 J4 t% y( Y( T% c) F
  247. 0 N/ m3 c, K* g% {
复制代码
  T9 I2 y. [3 I: ?1 u6 S: I
收藏 评论0 发布时间:2021-12-11 12:00

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版