現在非常多的的MCU性能都還不錯,同時用戶也會去擴展一些外部RAM,這樣如果高效便捷的管理這些內存是一個重要話題。
今天給大家分享一份源碼:基于無操作系統的STM32單片機開發,功能強大,可申請到地址空間連續的不同大小的內存空間,且用戶接口簡單,使用方便。
源碼說明
源碼包含memory.h 和 memory.c 兩個文件(嵌入式C/C++代碼的“標配”),其源碼中包含重要的注釋。 頭文件memory.h :包含結構體等定義,函數API申明等; 源文件memory.c :是實現內存管理相關API函數的原型。
頭文件memory.h
頭文件是相關的定義和申請:
#ifndef __MEMORY_H__ #define __MEMORY_H__ #include "stdio.h" #include "string.h" #include "includes.h" //用戶使用 typedef struct { void *addr; //申請到的內存的起始地址 uint32_t size; //申請到的內存的大小,按照塊大小分配,大于等于申請大小 uint16_t tb; //申請表序號,申請內存時分配,釋放內存時使用,用戶不使用 }DMEM; //若返回空,則申請失敗 DMEM *DynMemGet(uint32_t size); void DynMemPut(DMEM *pDmem); #endif //__MEMORY_H__
這里的代碼比較簡單,也是常規的寫法,重點是要理解結構體成員的含義。
源文件memory.c
源文件主要就是實現內存管理的函數,源碼比較多,這里才分為三部分。 1、相關的定義
#include "memory.h" #define DMEM_BLOCK_SIZE 256 //內存塊大小為128字節 #define DMEM_BLOCK_NUM 20 //內存塊個數為40個 #defineDMEM_TOTAL_SIZE(DMEM_BLOCK_SIZE*DMEM_BLOCK_NUM) //內存總大小 static uint8_t DMEMORY[DMEM_TOTAL_SIZE]; static DMEM_STATE DMEMS = {0}; typedef enum { DMEM_FREE = 0, DMEM_USED = 1, }DMEM_USED_ITEM; typedef struct { DMEM_USED_ITEM used; //使用狀態 uint16_t blk_s; //起始塊序號 uint16_t blk_num; //塊個數 }DMEM_APPLY; typedef struct { DMEM_USED_ITEM tb_blk[DMEM_BLOCK_NUM]; DMEM tb_user[DMEM_BLOCK_NUM]; //用戶申請內存信息 DMEM_APPLY tb_apply[DMEM_BLOCK_NUM]; //系統分配內存信息 uint16_t apply_num; //內存申請表占用數目 uint16_t blk_num; //內存塊占用數目 }DMEM_STATE;
2、內存分配函數DynMemGet
DMEM *DynMemGet(uint32_t size) { uint16_t loop = 0; uint16_t find = 0; uint16_t blk_num_want = 0; DMEM * user = NULL; DMEM_APPLY *apply = NULL; //申請內存大小不能為0 if(size == 0) { return NULL; } //申請內存不可超過總內存大小 if(size > DMEM_TOTAL_SIZE) { return NULL; } //申請內存不可超過剩余內存大小 if(size > (DMEM_BLOCK_NUM - DMEMS.blk_num) * DMEM_BLOCK_SIZE) { return NULL; } //申請表必須有空余 if(DMEMS.apply_num >= DMEM_BLOCK_NUM) { return NULL; } //計算所需連續塊的個數 blk_num_want = (size + DMEM_BLOCK_SIZE - 1) / DMEM_BLOCK_SIZE; //尋找申請表 for(loop = 0; loop < DMEM_BLOCK_NUM; loop++) { if(DMEMS.tb_apply[loop].used == DMEM_FREE) { apply = &DMEMS.tb_apply[loop]; //申請表已找到 user = &DMEMS.tb_user[loop]; //用戶表對應找到 user->tb = loop; //申請表編號記錄 user->size = blk_num_want * DMEM_BLOCK_SIZE; //分配大小計算 break; } } //沒有找到可用申請表,理論上是不會出現此現象的,申請表剩余已在上面校驗 if(loop == DMEM_BLOCK_NUM) { return NULL; } //尋找連續內存塊 for(loop = 0; loop < DMEM_BLOCK_NUM; loop++) { if(DMEMS.tb_blk[loop] == DMEM_FREE) {//找到第一個空閑內存塊 for(find = 1; (find < blk_num_want) && (loop + find < DMEM_BLOCK_NUM); find ++) {//找到下一個空閑內存塊 if(DMEMS.tb_blk[loop + find] != DMEM_FREE) {//發現已使用內存塊 break; } } if(find >= blk_num_want) {//尋找到的空閑內存塊數目已經夠用 user->addr = DMEMORY + loop * DMEM_BLOCK_SIZE; //計算申請到的內存的地址 apply->blk_s = loop; //記錄申請到的內存塊首序號 apply->blk_num = blk_num_want; //記錄申請到的內存塊數目 for(find = 0 ; find < apply->blk_num; find++) { DMEMS.tb_blk[loop + find] = DMEM_USED; } apply->used = DMEM_USED; //標記申請表已使用 DMEMS.apply_num += 1; DMEMS.blk_num += blk_num_want; return user; } else {//尋找到的空閑內存塊不夠用,從下一個開始找 loop += find; } } } //搜索整個內存塊,未找到大小適合的空間 return NULL; }3、內存釋放函數DynMemPut
void DynMemPut(DMEM *user) { uint16_t loop = 0; //若參數為空,直接返回 if(NULL == user) { return; } //釋放內存空間 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++) { DMEMS.tb_blk[loop] = DMEM_FREE; DMEMS.blk_num -= 1; } //釋放申請表 DMEMS.tb_apply[user->tb].used = DMEM_FREE; DMEMS.apply_num -= 1; }代碼中包含注釋,注釋描述的比較清楚,也比較容易理解。
-
單片機
+關注
關注
6035文章
44554瀏覽量
634642 -
內存
+關注
關注
8文章
3019瀏覽量
74003 -
STM32
+關注
關注
2270文章
10895瀏覽量
355740
原文標題:基于無操作系統的STM32內存管理模塊,附源碼
文章出處:【微信號:c-stm32,微信公眾號:STM32嵌入式開發】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論