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

【经验分享】基于无操作系统的STM32内存管理模块

[复制链接]
STMCU小助手 发布时间:2022-6-3 19:15
   现在非常多的的MCU性能都还不错,同时用户也会去扩展一些外部RAM,这样如果高效便捷的管理这些内存是一个重要话题。
    今天给大家分享一份源码:基于无操作系统的STM32单片机开发,功能强大,可申请到地址空间连续的不同大小的内存空间,且用户接口简单,使用方便。

' f0 N) X% M, S$ n' P9 |
源码说明
    源码包含memory.h 和 memory.c 两个文件(嵌入式C/C++代码的“标配”),其源码中包含重要的注释。    头文件memory.h :包含结构体等定义,函数API申明等;    源文件memory.c :是实现内存管理相关API函数的原型。0 F1 E3 j. C+ {+ k+ A' T
头文件memory.h
    头文件是相关的定义和申请:
8 ]9 r/ t( u1 j! [
  1. #ifndef __MEMORY_H__5 k5 A+ D9 r) C, o8 Q
  2. #define __MEMORY_H__
    5 h9 s$ t0 Z) M+ R

  3. : c/ ~) Q0 `9 m) |9 q
  4. #include "stdio.h"
    : ^7 Q: n9 X4 _4 I
  5. #include "string.h") m7 c  ?+ f: ]' T4 ^$ `! A
  6. #include "includes.h"
    & j; c5 T' F1 b
  7. //用户使用
    " g5 \# i- I  T# ~2 u
  8. typedef struct
    # V, ]# q  Q* |, j, y
  9. {
    ( b+ Z* }9 M' ?/ T  |6 \. n1 Y4 x  |
  10.     void    *addr;      //申请到的内存的起始地址
    2 t; \% l! {7 ]: ]# ?9 _* Y; ^- k% t
  11.     uint32_t size;      //申请到的内存的大小,按照块大小分配,大于等于申请大小
    ) Q: r) Q! x; X$ y2 B) \
  12.     uint16_t  tb;        //申请表序号,申请内存时分配,释放内存时使用,用户不使用
    + B' L7 D8 v* }' f7 a
  13. }DMEM;
    + }7 a) J4 b! ^# Y% Z( N! I
  14. //若返回空,则申请失败! M% c$ G/ q) q0 L9 X# l
  15. DMEM *DynMemGet(uint32_t size);* n8 h  A# z* q' F5 }. y4 [
  16. 5 J: |7 z4 o1 ?
  17. void DynMemPut(DMEM *pDmem);
    " h/ r6 O2 q: g# h4 i3 V
  18.   w# H( a9 I( m
  19. #endif //__MEMORY_H__
复制代码

7 `8 A: N( O- L5 {6 v5 z
8 V( s. e" y6 ~( p4 b* |
    这里的代码比较简单,也是常规的写法,重点是要理解结构体成员的含义。

: b1 j/ A. k# Z/ M/ G
源文件memory.c
    源文件主要就是实现内存管理的函数,源码比较多,这里才分为三部分。
: X# B, V# {! O- Z1、相关的定义" f% i. @: _2 v2 [3 p
  1. #include "memory.h"
      f/ _2 m1 h' y. y- h

  2. + B+ z& }$ b5 i+ U6 w
  3. #define DMEM_BLOCK_SIZE         256      //内存块大小为128字节! e+ w' r4 g' x& @" u
  4. #define DMEM_BLOCK_NUM          20       //内存块个数为40个9 W: `+ N/ ?7 t0 I( L' x+ D) [
  5. #define DMEM_TOTAL_SIZE         (DMEM_BLOCK_SIZE*DMEM_BLOCK_NUM) //内存总大小
    " A- a# Q( V9 t8 J0 [

  6.   [; X( A+ M6 l
  7. static uint8_t DMEMORY[DMEM_TOTAL_SIZE];
    1 r& ~3 r+ E. `5 B
  8. static DMEM_STATE DMEMS = {0};
    & T; j  x, U& e0 d& c* \/ A5 u4 y9 w

  9. $ }; L5 x! z/ @) h& L* f
  10. typedef enum
    " u6 c( _4 {+ s' K% s
  11. {
    * \" b# U$ Z9 v7 N
  12.     DMEM_FREE   = 0,; e6 g- I5 @" g4 l4 g! e4 U
  13.     DMEM_USED   = 1,
    6 I6 ^3 V2 v2 `" m
  14. }DMEM_USED_ITEM;4 e" W& m: ^8 \, |
  15. 6 h' P8 Z3 m/ L0 z& |
  16. typedef struct+ ^3 J- Q1 \* m( k- Z& |
  17. {
    ' a0 k- r9 A; y! |+ j
  18.     DMEM_USED_ITEM   used;       //使用状态
    & ^: v4 Q0 D2 X# k
  19.     uint16_t         blk_s;      //起始块序号5 r0 J) t& s" f
  20.     uint16_t         blk_num;    //块个数
      P$ q# `% l  ~- o) V9 W
  21. }DMEM_APPLY;
    " P$ @- A/ d8 z+ T  Y! |. A: W
  22. ( M% A% @. T1 K% S: T' S
  23. typedef struct
    6 v' S3 y. L6 M% ?: b* S/ f9 X: ?
  24. {5 C; Z- ^; ^/ E+ H6 j1 J
  25.     DMEM_USED_ITEM  tb_blk[DMEM_BLOCK_NUM];
    % n2 M" n/ T" r& [8 ?; v( A( Q
  26.     DMEM            tb_user[DMEM_BLOCK_NUM];        //用户申请内存信息* x# |( Q* u0 K7 B  t: a
  27.     DMEM_APPLY      tb_apply[DMEM_BLOCK_NUM];       //系统分配内存信息/ r( j) w; l( b2 \4 s8 _# `
  28.     uint16_t        apply_num;      //内存申请表占用数目0 D  A# ]6 d2 D8 V% S' D! j
  29.     uint16_t        blk_num;        //内存块占用数目. d& ?, h" Q0 K$ x: v5 B; _3 P. J
  30. }DMEM_STATE;
复制代码
, k8 o- ?0 R" {6 q

3 W6 H3 [; K2 x/ `2、内存分配函数DynMemGet
$ H! S- U6 w& k0 @8 T* n+ U
  1. DMEM *DynMemGet(uint32_t size)
    $ ~( u4 U. W$ |+ ^* c- L. Y
  2. {  _. l6 R' G, m1 N$ |; \
  3.     uint16_t loop = 0;2 Q" Z4 M: p2 H& M8 i/ d7 @* a  v; k! a
  4.     uint16_t find = 0;
    ; I9 J6 F/ j+ W6 v+ Y6 W8 S5 r6 q
  5.     uint16_t blk_num_want = 0;
    / b+ ~  Q- j& s& m3 j
  6.     DMEM * user = NULL;( \0 Z$ Q; X3 C3 B0 Z! I
  7.     DMEM_APPLY *apply = NULL;
    ( Z: D0 n8 o" i) ]3 O, S) n

  8. 1 K" o7 J+ R8 L0 S4 i
  9.     //申请内存大小不能为0
    * B. v. R/ D' |; B3 L9 y
  10.     if(size == 0)               {   return NULL;    }
    * k2 O  |4 `; c1 z4 j! M
  11.     //申请内存不可超过总内存大小
    2 v# H# ^& d% ]) H2 b+ r( l. a- i- d
  12.     if(size > DMEM_TOTAL_SIZE)  {   return NULL;    }' e1 c9 Z# A9 X& d8 L
  13.     //申请内存不可超过剩余内存大小% p0 A/ b  w0 {1 ]
  14.     if(size > (DMEM_BLOCK_NUM - DMEMS.blk_num) * DMEM_BLOCK_SIZE)   {   return NULL;    }  \" j! c1 C& Y8 a  J) y3 g
  15.     //申请表必须有空余
    ' a% h  V6 J2 y, I
  16.     if(DMEMS.apply_num >= DMEM_BLOCK_NUM)   {   return NULL;    }4 D# p* N( R7 Q( Z& H

  17. " }" d) J: F% {9 X3 ^
  18.     //计算所需连续块的个数
    ) v2 P# W' t$ d; ~% {/ ^& j* T! N% S
  19.     blk_num_want = (size + DMEM_BLOCK_SIZE - 1) / DMEM_BLOCK_SIZE;. ^" i2 {+ f8 o
  20. 6 U, a1 o8 T4 U5 q, ]- ^; A% f+ Q$ o
  21.     //寻找申请表' }1 b& Q3 L- f' q+ V
  22.     for(loop = 0; loop < DMEM_BLOCK_NUM; loop++)0 k# i; H9 F$ f- r) u
  23.     {0 o0 w% a: H0 O0 J4 E1 ?
  24.         if(DMEMS.tb_apply[loop].used == DMEM_FREE)
    1 C5 k, ?' ]/ D5 m. h5 R9 U7 L
  25.         {" E/ @, r" W" v/ }
  26.             apply = &DMEMS.tb_apply[loop];                  //申请表已找到; s& {1 N/ ~' M. t7 B- d& g
  27.             user = &DMEMS.tb_user[loop];                    //用户表对应找到
    . M: U! J2 \# C' n4 J, f$ l$ g. |+ ]
  28.             user->tb = loop;                                //申请表编号记录
    ! Q7 R' T% Y7 e% Q1 y" q; q
  29.             user->size = blk_num_want * DMEM_BLOCK_SIZE;    //分配大小计算
    ; z5 T" f8 W' n% f6 ~# C. K
  30.             break;
    0 K9 J& C' B" i) {
  31.         }' u* Z9 e* o  ?  ?; Z! B
  32.     }
    2 b; B" X9 \* j. \  }( U* U- W

  33.   u- s+ O) B& J  F
  34.     //没有找到可用申请表,理论上是不会出现此现象的,申请表剩余已在上面校验
    7 A5 z4 b0 Y& v6 u" a; p6 N
  35.     if(loop == DMEM_BLOCK_NUM)  {   return NULL;    }8 @1 [% ~( C( N% _/ E  X

  36.   K5 e$ ^1 Y# a3 p' h
  37.     //寻找连续内存块
    7 v, w! r7 G$ s6 M/ }$ i6 u
  38.     for(loop = 0; loop < DMEM_BLOCK_NUM; loop++)- n. k# h7 |% G9 n3 U5 i7 m
  39.     {
    3 I0 Y9 t1 q1 E1 n% a* k
  40.         if(DMEMS.tb_blk[loop] == DMEM_FREE)) L. R9 u/ |/ k# F
  41.         {//找到第一个空闲内存块7 d+ z6 z; o0 R$ h  X+ h
  42.             for(find = 1; (find < blk_num_want) && (loop + find < DMEM_BLOCK_NUM); find ++)
    " ~; ~4 M; y; k+ m0 ]
  43.             {//找到下一个空闲内存块
    ) o3 ]: `' s" L1 V% e
  44.                 if(DMEMS.tb_blk[loop + find] != DMEM_FREE)2 s( t3 x: B: ?4 h
  45.                 {//发现已使用内存块1 u. h4 M+ o9 T3 \, S- E
  46.                     break;$ G; A# z6 M7 D0 Y4 h
  47.                 }
    * r6 i: b5 a# H) j1 c* d9 S
  48.             }# F0 g0 m/ k; J5 v: {" r/ M6 `
  49.             if(find >= blk_num_want)' m9 h0 ], l( L
  50.             {//寻找到的空闲内存块数目已经够用
    ' ~# O3 k% `1 t* v
  51.                 user->addr = DMEMORY + loop * DMEM_BLOCK_SIZE;  //计算申请到的内存的地址
      k* t: q  Y& x! M7 g+ l4 j8 ^
  52.                 apply->blk_s = loop;                            //记录申请到的内存块首序号
    % k/ D! ?: f  j9 G, ^% d. E$ g' F
  53.                 apply->blk_num = blk_num_want;                  //记录申请到的内存块数目; q- D, Z9 c- X9 a" y6 z/ s
  54.                 for(find = 0 ; find < apply->blk_num; find++)
    $ T& _, y" e0 u  a% Y/ g5 A
  55.                 {
    ( G; r3 }5 ?9 B# q5 l5 w
  56.                     DMEMS.tb_blk[loop + find] = DMEM_USED;$ D9 D# l1 n' Z+ T* \
  57.                 }
    2 ~9 M. {" O4 h9 T6 l$ W
  58.                 apply->used = DMEM_USED;                        //标记申请表已使用
    ) m/ x. m/ M+ M0 Z" Z  C, W4 @( f
  59.                 DMEMS.apply_num += 1;
    & e& P" B% _3 o" Y% o& s; t. X
  60.                 DMEMS.blk_num += blk_num_want;
    % f/ B7 L% C) x$ [$ H, Y
  61. 4 c! g; p2 T5 H5 I- f
  62.                 return user;/ [2 U3 {; o0 B; g: c4 H
  63.             }
    , }6 h3 D, L/ v* t" T, ^2 ~
  64.             else
    - L! }' X+ {3 v/ |4 d
  65.             {//寻找到的空闲内存块不够用,从下一个开始找
    , b6 P4 [4 V' h; l% T4 o8 i: k# L
  66.                 loop += find;
    " m2 A0 E& U8 r* R
  67.             }6 ?' Q. L; p' v+ [* [
  68.         }" u2 A& C- e/ i& v* U$ g
  69.     }
    - B; p+ E( o3 G- t' M$ y

  70. # c4 d- w, y# D' d( M
  71.     //搜索整个内存块,未找到大小适合的空间
    & a2 F6 }' l  ^
  72.     return NULL;7 P: |! ^# {6 g1 ^- w
  73. }
复制代码

; ]3 y3 L1 [/ n+ b" t" b
! m% C! P" A( y3、内存释放函数DynMemPut
: ~6 n/ t7 W2 g& N0 w! ^
  1. void DynMemPut(DMEM *user)
    ) s* Y' M! ]9 Q6 j6 R
  2. {
      ?/ g0 z& T3 S& J% G; i8 p
  3.     uint16_t loop = 0;0 [$ C4 V; D+ |/ \0 x
  4.     //若参数为空,直接返回8 ^$ X) K+ {/ C/ u# t" a5 U
  5.     if(NULL == user)    {   return; }
    : ]9 I7 u" M$ D  @+ e* _

  6. 0 q# P/ q* ]7 ^  c' N2 x
  7.     //释放内存空间
    ( `  e' j3 h8 }+ P( ?0 Q' ~; e/ u
  8.     for(loop = DMEMS.tb_apply[user->tb].blk_s; loop < DMEMS.tb_apply[user->tb].blk_s + DMEMS.tb_apply[user->tb].blk_num; loop++)
    & D" ?* d$ n0 n# c, o7 W
  9.     {
    % Z0 i% J* x% [" L7 o% q+ |
  10.         DMEMS.tb_blk[loop] = DMEM_FREE;9 p/ @! q0 a8 i) G3 e$ R
  11.         DMEMS.blk_num -= 1;! k" Y& h$ w/ T6 A& V  }( U5 e0 |
  12.     }: {, N, _3 F* T
  13.     //释放申请表7 X$ |$ y# K# G/ }$ U
  14.     DMEMS.tb_apply[user->tb].used = DMEM_FREE;
    / O# l2 L% O$ n3 k% ^1 _
  15.     DMEMS.apply_num -= 1;+ D1 X1 t+ b- _; @
  16. }
复制代码
; G. m1 s- Q, |) y) O7 l1 B

+ C4 q! x' B) @7 H
+ v4 L$ v# j9 f
: y' G/ C. o( E$ M2 @
代码中包含注释,注释描述的比较清楚,也比较容易理解。! c% o: @  }# W7 t$ v1 C# m1 w

& ^5 V& k" e$ \. I$ ~+ N+ @
赞 收藏 评论0 发布时间:2022-6-3 19:15

举报

0个回答

所属标签

相似技术帖

官网相关资源

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