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

基于无操作系统的STM32内存管理模块

[复制链接]
STMCU小助手 发布时间:2022-9-17 17:40
现在非常多的的MCU性能都还不错,同时用户也会去扩展一些外部RAM,这样如果高效便捷的管理这些内存是一个重要话题。
    今天给大家分享一份源码:基于无操作系统的STM32单片机开发,功能强大,可申请到地址空间连续的不同大小的内存空间,且用户接口简单,使用方便。
源码说明
    源码包含memory.h 和 memory.c 两个文件(嵌入式C/C++代码的“标配”),其源码中包含重要的注释。    头文件memory.h :包含结构体等定义,函数API申明等;    源文件memory.c :是实现内存管理相关API函数的原型。
头文件memory.h
    头文件是相关的定义和申请:
  1. #ifndef __MEMORY_H__, m5 d* \' J" h7 q8 t
  2. #define __MEMORY_H__
    " ?% j6 N' N5 h0 @1 W  I
  3. 5 t$ m' O3 s9 x$ a8 k& c
  4. #include "stdio.h"- c& ?8 Z; G9 G$ B) B
  5. #include "string.h"1 h+ l7 B0 [* S8 R6 _  @* m
  6. #include "includes.h"$ G# R' `- [& {# s! u2 X3 _
  7. //用户使用
    - \# v) i% \1 w, I& c/ @
  8. typedef struct
    " M* Y) k0 u% Q. Q' ?- ?" U
  9. {7 B4 E  g: }$ z% q  u
  10.     void    *addr;      //申请到的内存的起始地址, s) c+ n! Z! q
  11.     uint32_t size;      //申请到的内存的大小,按照块大小分配,大于等于申请大小
    - o( C4 V8 z3 P7 w8 {5 d- q: O
  12.     uint16_t  tb;        //申请表序号,申请内存时分配,释放内存时使用,用户不使用
    # X/ I/ D! k& a" [5 |
  13. }DMEM;: Z! K, y4 \* G
  14. //若返回空,则申请失败
    - `: u+ c5 K! D
  15. DMEM *DynMemGet(uint32_t size);
    * I# f" S" \" @9 [( u

  16. ! D; A3 O) k  m5 P: s8 j5 M/ z
  17. void DynMemPut(DMEM *pDmem);7 Z$ Q! ?' y5 ^. `* U9 K

  18. % o$ {) f/ u) O, R8 I
  19. #endif //__MEMORY_H__
复制代码

. d3 F% S9 s1 V) o" s) Y  F# g
    这里的代码比较简单,也是常规的写法,重点是要理解结构体成员的含义。
' T* t( M! |. I8 x$ O  c
源文件memory.c
    源文件主要就是实现内存管理的函数,源码比较多,这里才分为三部分。
0 e4 |$ B1 g4 u) p8 ]1 }  x! r1、相关的定义
2 S$ V) P) ?" T3 E# F% J
  1. #include "memory.h"
    ' j/ S# s( Z, q0 H) D+ s) K$ x
  2. $ I1 {( i* B0 C( ?9 k8 Z" U
  3. #define DMEM_BLOCK_SIZE         256      //内存块大小为128字节
    . \: D5 K1 f: K& U
  4. #define DMEM_BLOCK_NUM          20       //内存块个数为40个8 G; @  v: N. t
  5. #define DMEM_TOTAL_SIZE         (DMEM_BLOCK_SIZE*DMEM_BLOCK_NUM) //内存总大小
    6 L9 \+ C0 N7 h, D+ D

  6. % A. U6 W- o  r( r8 R& d+ ?6 Y0 x3 l
  7. static uint8_t DMEMORY[DMEM_TOTAL_SIZE];7 |  \2 x& c- y* X9 e( Z  m3 Y
  8. static DMEM_STATE DMEMS = {0};6 A. j8 ~  T+ z" r

  9. 3 A3 }, Z& v0 ~
  10. typedef enum1 Y, g, I; E( ]% d
  11. {
    - n6 L' L) z: O( f+ K: [; U* E
  12.     DMEM_FREE   = 0,
    , n; e3 d3 C: S. v8 A% b/ ^( c2 a
  13.     DMEM_USED   = 1,
    3 \( C2 j4 s& }3 ?
  14. }DMEM_USED_ITEM;
    # A) }" S/ u" M" Z& U' h1 p

  15. 2 A% G7 Z) r+ s7 w
  16. typedef struct4 Z, O' [5 k) R9 H2 F1 @
  17. {
    1 o5 S9 Q! }9 j$ c5 a8 \
  18.     DMEM_USED_ITEM   used;       //使用状态
    7 c# f/ a: v+ |
  19.     uint16_t         blk_s;      //起始块序号( d& a8 n0 f& n  L4 G% C
  20.     uint16_t         blk_num;    //块个数$ S; e, r$ h" U7 f7 D
  21. }DMEM_APPLY;; P2 T  e' `6 l/ r% P6 t$ z. l5 K

  22. # T0 i7 S7 f/ }) c, l
  23. typedef struct
    0 \" t4 j. R. j! b  {5 N
  24. {6 K0 c& _" P8 K' ^) d
  25.     DMEM_USED_ITEM  tb_blk[DMEM_BLOCK_NUM];
    $ v) [' g" |8 k8 }+ O
  26.     DMEM            tb_user[DMEM_BLOCK_NUM];        //用户申请内存信息
    ; l& b3 [% w  T4 c6 Y$ |
  27.     DMEM_APPLY      tb_apply[DMEM_BLOCK_NUM];       //系统分配内存信息
    , P* Z9 @5 \2 b: t+ P, t3 H# I
  28.     uint16_t        apply_num;      //内存申请表占用数目
    / E9 ^, H! a( O
  29.     uint16_t        blk_num;        //内存块占用数目
    ) g0 N8 I% x: L6 W5 }, U7 s
  30. }DMEM_STATE;
复制代码
- b2 X3 M7 N/ a4 s5 r  q; ]9 S
2、内存分配函数DynMemGet
, D2 E) L, H+ D1 F- S
  1. DMEM *DynMemGet(uint32_t size)
    - {- Y- a" i1 p  ?( k) T
  2. {# E% b( x4 |0 U9 h
  3.     uint16_t loop = 0;/ h& n9 ^% P8 n7 J: p8 Q2 {. B
  4.     uint16_t find = 0;
    + B1 `7 k; ^$ K+ f8 ?
  5.     uint16_t blk_num_want = 0;
    % D$ n4 v4 F. ^, |
  6.     DMEM * user = NULL;
    8 D3 O- [% Y# |8 ^$ g( g* P0 k
  7.     DMEM_APPLY *apply = NULL;
    + I7 |8 l" ]1 {; u: ]) }9 x
  8. 6 Y7 p: `3 F% x$ |! y3 f* Q% x3 H) {
  9.     //申请内存大小不能为04 n% n+ m( L' Z# R1 K9 w. a
  10.     if(size == 0)               {   return NULL;    }
    7 U. n& y0 V9 ^. m8 u- M# }. Q
  11.     //申请内存不可超过总内存大小0 o' ~3 E% R8 ~7 b$ _" T
  12.     if(size > DMEM_TOTAL_SIZE)  {   return NULL;    }# n  |( n( Y- y
  13.     //申请内存不可超过剩余内存大小' u+ j+ d" J8 {9 H  F2 ^
  14.     if(size > (DMEM_BLOCK_NUM - DMEMS.blk_num) * DMEM_BLOCK_SIZE)   {   return NULL;    }8 B& T% @2 G% C* y# q" J3 s  y
  15.     //申请表必须有空余% A5 y% t6 k+ o) F- M. S* C
  16.     if(DMEMS.apply_num >= DMEM_BLOCK_NUM)   {   return NULL;    }! M- Q* T6 }& m5 ]

  17. # X2 }, Z% Q: x- M4 S
  18.     //计算所需连续块的个数$ {3 K. E2 U, _4 ]) H. z
  19.     blk_num_want = (size + DMEM_BLOCK_SIZE - 1) / DMEM_BLOCK_SIZE;9 E; H  `/ N- o/ B* d

  20. , E$ A( D- t  L; ?# B
  21.     //寻找申请表, }. B1 r7 |  }7 Y
  22.     for(loop = 0; loop < DMEM_BLOCK_NUM; loop++)$ d9 l3 O5 \9 m$ m8 Q& M  o
  23.     {
    6 v+ \( v7 C8 A9 R
  24.         if(DMEMS.tb_apply[loop].used == DMEM_FREE). t3 u( S+ K& [, y2 V5 F/ u
  25.         {2 j! f* {* t8 I. K  S* K4 L3 ~. c8 |
  26.             apply = &DMEMS.tb_apply[loop];                  //申请表已找到9 F3 ~( M7 A$ P! y! L1 }+ o
  27.             user = &DMEMS.tb_user[loop];                    //用户表对应找到
    + U& x3 v2 L. b6 J' L, r
  28.             user->tb = loop;                                //申请表编号记录
    9 u3 P( ~; T- F6 |  I* R4 ~$ J- K
  29.             user->size = blk_num_want * DMEM_BLOCK_SIZE;    //分配大小计算
    6 P" N- S) @1 L1 r* b$ S
  30.             break;$ L) l& w# I( M1 s
  31.         }5 A9 j. s9 h+ O: U* j9 g
  32.     }$ y& v. l; C; y; @- @, E0 R6 f

  33.   l( [- s  T( ~6 D
  34.     //没有找到可用申请表,理论上是不会出现此现象的,申请表剩余已在上面校验
    4 K5 ~4 I: M0 K
  35.     if(loop == DMEM_BLOCK_NUM)  {   return NULL;    }0 ?' Z! j6 J- z  `1 ?! l/ P& J
  36. 8 R3 e1 R) c# Z# y7 l/ \
  37.     //寻找连续内存块+ `' n: C9 A0 ?6 E' g4 D
  38.     for(loop = 0; loop < DMEM_BLOCK_NUM; loop++)! L' F- j/ c) }. L( O) G# C
  39.     {
    ' K* {( Q# w$ ^6 f# C
  40.         if(DMEMS.tb_blk[loop] == DMEM_FREE)
    . n4 U3 y$ I) |# @7 }0 B
  41.         {//找到第一个空闲内存块6 `7 `. Z8 c$ `) }6 G! F
  42.             for(find = 1; (find < blk_num_want) && (loop + find < DMEM_BLOCK_NUM); find ++)  a; C; ^) P' A+ F3 F$ g! u1 O
  43.             {//找到下一个空闲内存块1 l6 G& D/ n! W) @- M* g1 ^
  44.                 if(DMEMS.tb_blk[loop + find] != DMEM_FREE)
    * U$ q" n* P& h) }  N# U
  45.                 {//发现已使用内存块7 B0 W) A. ]; G- H* w+ m
  46.                     break;* ]: p! [$ A1 E* ]1 I: A
  47.                 }
    " \: I* E! R( M5 Q) A
  48.             }
    2 g0 d! l& |/ y3 L' }: y
  49.             if(find >= blk_num_want)0 w+ B6 k" t) g
  50.             {//寻找到的空闲内存块数目已经够用
    9 f7 V9 M- W) P" i& U9 u" f
  51.                 user->addr = DMEMORY + loop * DMEM_BLOCK_SIZE;  //计算申请到的内存的地址! D4 B( t- M- X: {, v4 a! k
  52.                 apply->blk_s = loop;                            //记录申请到的内存块首序号9 p3 Q, ]1 H  n3 Y' B
  53.                 apply->blk_num = blk_num_want;                  //记录申请到的内存块数目
    8 [7 y$ }7 D/ d- i
  54.                 for(find = 0 ; find < apply->blk_num; find++)
    ( q2 n0 G0 q. M( L1 x
  55.                 {; j$ d: x& A( \/ j% j) q; h
  56.                     DMEMS.tb_blk[loop + find] = DMEM_USED;6 k! |7 ]2 H/ X- r9 o9 D1 a! d+ y
  57.                 }
    1 S% F: x- }: I9 ]5 Q( p
  58.                 apply->used = DMEM_USED;                        //标记申请表已使用
    4 f/ u1 `, y# j+ ~% r4 b
  59.                 DMEMS.apply_num += 1;& T- F/ f0 ^" T( e
  60.                 DMEMS.blk_num += blk_num_want;5 L+ n* Z' X, @( V- i! t

  61. / p8 J' ^6 u& \* n0 \
  62.                 return user;
    8 T5 }2 \; G. e) \. @3 \1 u
  63.             }
    4 ]  P' U; X: P% |% ?
  64.             else
    ( w+ |8 w; m# M) q
  65.             {//寻找到的空闲内存块不够用,从下一个开始找5 e# E  }7 R; t0 |  P
  66.                 loop += find;
    1 u% G  i. I6 q& \
  67.             }: B3 I. K: h( `) ?* P: U2 w  ?
  68.         }4 G' z0 `' G5 @6 b6 S9 Y. j
  69.     }- G0 g) j# X7 ?- o4 t* Z7 `$ {8 |! X

  70. ( c' U6 }  R" X
  71.     //搜索整个内存块,未找到大小适合的空间  A1 K% I4 q; v$ x% _: _
  72.     return NULL;% Y5 J2 N$ l5 s* ~9 h( K8 i- i% Q
  73. }
复制代码
. g0 o" |. i7 k& g2 x

! ^, y: {- _1 @; i' G0 i3 R' w3、内存释放函数DynMemPut( W3 H1 s$ x, j( U) K" z( J( L
  1. void DynMemPut(DMEM *user)
    * U! n% U  D! i+ `: v! Q$ A( j
  2. {; N. X6 @( d& [: D) |5 O; |
  3.     uint16_t loop = 0;
    6 @$ X* j6 L" h( ^
  4.     //若参数为空,直接返回& P6 M: s3 D. t: ^4 F6 `
  5.     if(NULL == user)    {   return; }
    - Z9 T3 {$ c9 e! m; l
  6. 6 c7 _2 W6 ~! Y5 o7 \  m7 a) p. T8 F
  7.     //释放内存空间
    ) w. J1 G: I3 A5 M4 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++)
    ! x2 I  {% B& C
  9.     {
    1 e# K0 E2 Y5 ]- n5 H. ]/ r" A& G
  10.         DMEMS.tb_blk[loop] = DMEM_FREE;; ^, J& c) `) b
  11.         DMEMS.blk_num -= 1;
    - F- l; _0 S; z3 y4 Q: W
  12.     }
    1 H, R4 _" u8 y$ P& r. X& j( I- u
  13.     //释放申请表
    1 z" n# w9 z1 r' X8 Z( m& `! E7 s
  14.     DMEMS.tb_apply[user->tb].used = DMEM_FREE;* n: B' z. [6 L
  15.     DMEMS.apply_num -= 1;$ `  O+ w; L# X( N& b2 F
  16. }
复制代码
/ W5 g* J! P  I8 }/ ?
代码中包含注释,注释描述的比较清楚,也比较容易理解。
6 K  D' R7 R& B9 V1 F5 C( `2 ]
8 Q! l/ M! y0 E' ?2 W- Y
. Q+ M2 O- m# @
! [5 z8 L% n' b4 y. N3 r+ n5 p
转载自:STM32嵌入式开发
( x# v9 _8 {: y
赞 收藏 评论0 发布时间:2022-9-17 17:40

举报

0个回答

所属标签

相似技术帖

官网相关资源

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