整理了一份通用的內(nèi)存管理驅(qū)動代碼
來源:技術(shù)讓夢想更偉大
作者:李肖遙
malloc的全稱是memory allocation,即動態(tài)內(nèi)存分配,當無法知道內(nèi)存具體位置的時候,想要綁定真正的內(nèi)存空間的時候,就需要用到動態(tài)的分配內(nèi)存。
可以說動態(tài)內(nèi)存分配在嵌入式開發(fā)中是經(jīng)常用到的,也是比較容易出錯和被忽略的,經(jīng)常忘了free,導(dǎo)致分配失敗程序死機等等。
這里在工作的時候整理了一份通用的內(nèi)存管理驅(qū)動代碼。
一些基本定義
定義內(nèi)存池(32字節(jié)對齊)
__align(32) u8 mem1base[MEM1_MAX_SIZE]; //內(nèi)部SRAM內(nèi)存池
__align(32) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0XC01F4000))); //外部SDRAM內(nèi)存池,前面2M給LTDC用了(1280*800*2)
__align(32) u8 mem3base[MEM3_MAX_SIZE] __attribute__((at(0X10000000))); //內(nèi)部CCM內(nèi)存池
定義內(nèi)存管理表
u32 mem1mapbase[MEM1_ALLOC_TABLE_SIZE]; //內(nèi)部SRAM內(nèi)存池MAP
u32 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0XC01F4000+MEM2_MAX_SIZE))); //外部SRAM內(nèi)存池MAP
u32 mem3mapbase[MEM3_ALLOC_TABLE_SIZE] __attribute__((at(0X10000000+MEM3_MAX_SIZE))); //內(nèi)部CCM內(nèi)存池MAP
定義內(nèi)存管理參數(shù)
const u32 memtblsize[SRAMBANK]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE,MEM3_ALLOC_TABLE_SIZE}; //內(nèi)存表大小
const u32 memblksize[SRAMBANK]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE,MEM3_BLOCK_SIZE}; //內(nèi)存分塊大小
const u32 memsize[SRAMBANK]={MEM1_MAX_SIZE,MEM2_MAX_SIZE,MEM3_MAX_SIZE}; //內(nèi)存總大小
一個結(jié)構(gòu)體來定義內(nèi)存管理控制器
struct _m_mallco_dev mallco_dev=
{
my_mem_init, //內(nèi)存初始化
my_mem_perused, //內(nèi)存使用率
mem1base,mem2base,mem3base, //內(nèi)存池
mem1mapbase,mem2mapbase,mem3mapbase,//內(nèi)存管理狀態(tài)表
0,0,0, //內(nèi)存管理未就緒
};
重寫函數(shù)
需要復(fù)制的內(nèi)存長度(字節(jié)為單位),復(fù)制內(nèi)存,重寫一個memcpy
void mymemcpy(void *des,void *src,u32 n)
{
u8 *xdes=des;
u8 *xsrc=src;
while(n--)*xdes++=*xsrc++;
}
需要設(shè)置的內(nèi)存大小(字節(jié)為單位),設(shè)置內(nèi)存,重寫一個memset
void mymemset(void *s,u8 c,u32 count)
{
u8 *xs = s;
while(count--)*xs++=c;
}
常用模塊函數(shù)
獲取內(nèi)存使用率
u16 my_mem_perused(u8 memx)
{
u32 used=0;
u32 i;
for(i=0;i<memtblsize[memx];i++)
{
if(mallco_dev.memmap[memx][i])used++;
}
return (used*1000)/(memtblsize[memx]);
}
內(nèi)存分配(內(nèi)部調(diào)用)
u32 my_mem_malloc(u8 memx,u32 size)
{
signed long offset=0;
u32 nmemb; //需要的內(nèi)存塊數(shù)
u32 cmemb=0;//連續(xù)空內(nèi)存塊數(shù)
u32 i;
if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先執(zhí)行初始化
if(size==0)return 0XFFFFFFFF;//不需要分配
nmemb=size/memblksize[memx]; //獲取需要分配的連續(xù)內(nèi)存塊數(shù)
if(size%memblksize[memx])nmemb++;
for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整個內(nèi)存控制區(qū)
{
if(!mallco_dev.memmap[memx][offset])cmemb++;//連續(xù)空內(nèi)存塊數(shù)增加
else cmemb=0; //連續(xù)內(nèi)存塊清零
if(cmemb==nmemb) //找到了連續(xù)nmemb個空內(nèi)存塊
{
for(i=0;i<nmemb;i++) //標注內(nèi)存塊非空
{
mallco_dev.memmap[memx][offset+i]=nmemb;
}
return (offset*memblksize[memx]);//返回偏移地址
}
}
return 0XFFFFFFFF;//未找到符合分配條件的內(nèi)存塊
}
釋放內(nèi)存
u8 my_mem_free(u8 memx,u32 offset)
{
int i;
if(!mallco_dev.memrdy[memx])//未初始化,先執(zhí)行初始化
{
mallco_dev.init(memx);
return 1;//未初始化
}
if(offset<memsize[memx])//偏移在內(nèi)存池內(nèi).
{
int index=offset/memblksize[memx]; //偏移所在內(nèi)存塊號碼
int nmemb=mallco_dev.memmap[memx][index]; //內(nèi)存塊數(shù)量
for(i=0;i<nmemb;i++) //內(nèi)存塊清零
{
mallco_dev.memmap[memx][index+i]=0;
}
return 0;
}else return 2;//偏移超區(qū)了.
}
當然也可以把上面的函數(shù)封裝為外部調(diào)用的,方便使用,比如重新分配內(nèi)存(外部調(diào)用)
void *myrealloc(u8 memx,void *ptr,u32 size)
{
u32 offset;
offset=my_mem_malloc(memx,size);
if(offset==0XFFFFFFFF)return NULL;
else
{
mymemcpy((void*)((u32)mallco_dev.membase[memx]+offset),ptr,size); //拷貝舊內(nèi)存內(nèi)容到新內(nèi)存
myfree(memx,ptr); //釋放舊內(nèi)存
return (void*)((u32)mallco_dev.membase[memx]+offset); //返回新內(nèi)存首地址
}
}
版權(quán)聲明:本文來源網(wǎng)絡(luò),免費傳達知識,版權(quán)歸原作者所有。如涉及作品版權(quán)問題,請聯(lián)系我進行刪除。
???????????????? END ???????????????
關(guān)注我的微信公眾號,回復(fù)“加群”按規(guī)則加入技術(shù)交流群。
點擊“閱讀原文”查看更多分享,歡迎點分享、收藏、點贊、在看。
