基于STM32原子戰(zhàn)艦板內(nèi)存管理源碼
*/
//復(fù)制內(nèi)存,作用是將源地址的內(nèi)容復(fù)制到目標(biāo)地址
//*des:目的地址
//*src:源地址
//n:需要復(fù)制的內(nèi)存長度(字節(jié)為單位)
void mymemcpy(void *des,void *src,u32 n)
{ //“void *des”無類型指針,不能指向具體的數(shù)據(jù),“void *des”無類型指針指向內(nèi)存中的數(shù)據(jù)類型由用戶自己確定
u8 *xdes=des;//目標(biāo)地址,“*xdes”轉(zhuǎn)換成u8類型,也可以理解為把目的地地址des存儲到xdes指針中
u8 *xsrc=src;
while(n--)*xdes++=*xsrc++;
}
//設(shè)置內(nèi)存
//*s:內(nèi)存首地址
//c :要設(shè)置的值
//count:需要設(shè)置的內(nèi)存大小(字節(jié)為單位)
void mymemset(void *s,u8 c,u32 count)
{
u8 *xs = s;
while(count--)*xs++=c;
} //以*s為內(nèi)存首地址的count個(gè)字節(jié)中,填充c,即把c寫入到*s為首地址的內(nèi)存中,個(gè)數(shù)多少由count值決定
//內(nèi)存管理初始化
//memx:所屬內(nèi)存塊,要么SRAMEX==1(外部內(nèi)存);要么SRAMIN(內(nèi)部內(nèi)存)==0
/*
const u32 memtblsize[2]={MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE};//內(nèi)存管理表大小
const u32 memblksize[2]={MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE}; //內(nèi)存分塊大小
const u32 memsize[2]={MEM1_MAX_SIZE,MEM2_MAX_SIZE}; //內(nèi)存總大小
*/
void mem_init(u8 memx) //如“mem_init(SRAMIN);”表示內(nèi)部內(nèi)存塊
{ //memmap,是16位的,mymemset,設(shè)置是針對8位的,那么1個(gè)16位的數(shù)據(jù)是不是2個(gè)8位組成的???!
mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//內(nèi)存狀態(tài)表數(shù)據(jù)清零
//把u8類型的數(shù)據(jù)“0”填充到u16類型指針元素memmap[0]中(根據(jù)結(jié)構(gòu)體定義“u16 *memmap[2]; ”),memmap[0]=mem1mapbase==1250,
//也就是說“mallco_dev.memmap[memx]”在這里表示1250個(gè)內(nèi)部內(nèi)存塊用以存儲u16類型指針,
//“memtblsize[memx]”是什么呢?memtblsize[memx]即memtblsize[0]==1250個(gè)內(nèi)部內(nèi)存管理表,
//而mallco_dev.memmap[memx]是16位的,為了將其全部清零,所以乘以2.
mymemset(mallco_dev.membase[memx], 0,memsize[memx]); //內(nèi)存池所有數(shù)據(jù)清零
//memsize[0]==40K字節(jié)空間, mallco_dev.membase[memx]==40K字節(jié)空間,
mallco_dev.memrdy[memx]=1; //內(nèi)存管理初始化OK
}
/*
*/
//獲取內(nèi)存使用率
//memx:所屬內(nèi)存塊,要么SRAMEX==1(外部內(nèi)存);要么SRAMIN(內(nèi)部內(nèi)存)==0
//返回值:使用率(0~100)
u8 mem_perused(u8 memx)
{
u32 used=0;
u32 i;
for(i=0;i {
if(mallco_dev.memmap[memx][i])used++;
} //mallco_dev.memmap[memx][i]是二維數(shù)組。當(dāng)內(nèi)存塊初始化后該值為0,
return (used*100)/(memtblsize[memx]); //used*100,乘以100是將小數(shù)變成整數(shù)
}
//內(nèi)存分配(內(nèi)部調(diào)用)
//memx:所屬內(nèi)存塊
//size:要分配的內(nèi)存大小(字節(jié)數(shù))
//返回值:0XFFFFFFFF,代表錯(cuò)誤;其他,內(nèi)存偏移地址
//向memx存儲器申請size個(gè)字節(jié)的連續(xù)存儲空間,并將size個(gè)字節(jié)中首個(gè)字節(jié)的地址偏移值標(biāo)注出來,注意是地址偏移值而不是地址。
u32 mem_malloc(u8 memx,u32 size)
{
signed long offset=0;
u16 nmemb; //需要的內(nèi)存塊數(shù)
u16 cmemb=0;//連續(xù)空內(nèi)存塊數(shù)
u32 i;
if(!mallco_dev.memrdy[memx])mallco_dev.init(memx);//未初始化,先執(zhí)行初始化
/*
“mallco_dev.init(memx);”是什么意思?mallco_dev.init(memx)是結(jié)構(gòu)體變量mallco_dev的一個(gè)成員,本句中就是對結(jié)構(gòu)體成員的引用,即執(zhí)行
mem_init(u8 memx)函數(shù)的意思;如何引用結(jié)構(gòu)體中指向函數(shù)的指針變量成員?既然是指向函數(shù)的指針變量且有賦值,在引用時(shí)按照格式:
結(jié)構(gòu)體變量名.指向函數(shù)的指針變量名(形參);
*/
if(size==0)return 0XFFFFFFFF;//不需要分配 memblksize[memx]==32
nmemb=size/memblksize[memx]; //獲取需要分配的連續(xù)內(nèi)存塊數(shù)
/*
c語言規(guī)定:除法的運(yùn)算結(jié)果與運(yùn)算對象的數(shù)據(jù)類型有關(guān),兩個(gè)數(shù)都是int則商(即結(jié)果)是int,若商(即結(jié)果)有小數(shù)則省略掉小數(shù)點(diǎn)部分。本例中
size和memblksize[memx]都是int,所以結(jié)果只能是int。假設(shè)size<32,則nmemb==0;
c語言規(guī)定取余運(yùn)算的運(yùn)算對象必須是int。當(dāng)小數(shù)對大數(shù)取余時(shí)余(即結(jié)果)是小數(shù)本身;例如,在“if(size%memblksize[memx])nmemb++;”中 ,
假設(shè)size<32,則size%memblksize[memx]的結(jié)果是size值本身,所以執(zhí)行“nmemb++;”運(yùn)算,這時(shí)運(yùn)算結(jié)果是nmemb==1;如果size是32的整數(shù)倍則不執(zhí)行
“nmemb++;”運(yùn)算;
memtblsize[0]==1250,memtblsize[1]==6250,
mallco_dev.memmap[memx][offset]是什么意思?
*/
if(size%memblksize[memx])nmemb++;
for(offset=memtblsize[memx]-1;offset>=0;offset--)//搜索整個(gè)內(nèi)存控制區(qū)
{
if(!mallco_dev.memmap[memx][offset])cmemb++;//連續(xù)空內(nèi)存塊數(shù)增加,offset從1249->0變化
/*
如,{ memmap[0][149],memmap[0][148],...memmap[0][1],memmap[0][0]};實(shí)際上可以把“mallco_dev.memmap[memx][offset]”視為具有1250個(gè)變量的
一維數(shù)組,每個(gè)元素對應(yīng)的實(shí)際意義是對應(yīng)的一個(gè)內(nèi)存塊,順序是offset從1249(高)->0(低)變化;如果哪個(gè)變量等于0(即空閑)就執(zhí)行
“cmemb++;”操作,這樣就可以計(jì)算出連續(xù)空閑內(nèi)存塊數(shù)cmemb;切記!目的是要獲取連續(xù)的空閑的內(nèi)存塊數(shù)!這樣就必須結(jié)合下一句
“else cmemb=0;”來分析;如果沒有出現(xiàn)連續(xù)的空閑內(nèi)存塊(即數(shù)組順序相連的變量值沒有出現(xiàn)類似“0,0,0,0,0”這樣的情況),程序會執(zhí)行下一語
句“else cmemb=0;”即把上面的“cmemb”統(tǒng)計(jì)值清零,這樣程序就會在for循環(huán)里面繼續(xù)尋找符合“if(cmemb==nmemb)”條件的狀態(tài)出現(xiàn),
如果for循環(huán)執(zhí)行完了還沒有出現(xiàn)符合“if(cmemb==nmemb)”條件的狀態(tài),則返回0XFFFFFFFF結(jié)束本函數(shù)表示沒有找到符合條件的內(nèi)存塊。假
設(shè):size=65,那么nmemb就是3即需要獲取連續(xù)3個(gè)內(nèi)存塊來存放65個(gè)字節(jié),再假設(shè)數(shù)組順序相連的變量值出現(xiàn)了類似“0,0,0,0,0”這樣的情況(即有
連續(xù)4個(gè)空閑的內(nèi)存塊),這時(shí)就出現(xiàn)了符合“if(cmemb==nmemb)”條件的狀態(tài),即當(dāng)cmemb計(jì)數(shù)計(jì)到3的時(shí)候(即出現(xiàn)了連續(xù)相連的3個(gè)內(nèi)存塊)就
符合“cmemb==nmemb”了,程序就自然進(jìn)入“if(cmemb==nmemb)”語句。
offset*memblksize[memx]代表什么呢?offset的取值范圍是0-1249,memblksize[memx]代表每個(gè)內(nèi)存塊的字節(jié)數(shù)即32,offset*memblksize[memx]就
是返回偏移地址值;也就是把連續(xù)空閑的內(nèi)存塊對應(yīng)的地址的首地址值標(biāo)注出來。
*/
else cmemb=0; //連續(xù)內(nèi)存塊清零
if(cmemb==nmemb) //找到了連續(xù)nmemb個(gè)空內(nèi)存塊
{
for(i=0;i {
mallco_dev.memmap[memx][offset+i]=nmemb;
}
return (offset*memblksize[memx]);//返回偏移地址
}
}
return 0XFFFFFFFF;//未找到符合分配條件的內(nèi)存塊
}
//釋放內(nèi)存(內(nèi)部調(diào)用)
//memx:所屬內(nèi)存塊
//offset:內(nèi)存地址偏移
//返回值:0,釋放成功;1,釋放失敗;
u8 mem_free(u8 memx,u32 offset)
{
int i;
if(!mallco_dev.memrdy[memx])//未初始化,先執(zhí)行初始化
{
mallco_dev.init(memx); //本句等價(jià)于“mem_init(memx);”
return 1;//未初始化
}
if(offset {
int index=offset/memblksize[memx]; //偏移所在內(nèi)存塊號碼 memblksize[memx]==32,
int nmemb=mallco_dev.memmap[memx][index]; //內(nèi)存塊數(shù)量
for(i=0;i {
mallco_dev.memmap[memx][index+i]=0;
}
return 0;
}else return 2;//偏移超區(qū)了.
}
//釋放內(nèi)存(外部調(diào)用)
//memx:所屬內(nèi)存塊
//ptr:內(nèi)存首地址
void myfree(u8 memx,void *ptr)
{
u32 offset;
if(ptr==NULL)return;//地址為0.
offset=(u32)ptr-(u32)mallco_dev.membase[memx];
mem_free(memx,offset);//釋放內(nèi)存
}
//分配內(nèi)存(外部調(diào)用)
//memx:所屬內(nèi)存塊
//size:內(nèi)存大小(字節(jié))
//返回值:分配到的內(nèi)存首地址.
//在memx存儲器中,找出size個(gè)字節(jié)的連續(xù)空閑的內(nèi)存空間,并將連續(xù)空閑的內(nèi)存空間指針值標(biāo)注出來;返回值就是這個(gè)指針值
/*
mallco_dev.membase[memx]即mallco_dev.membase[0]代表MCU內(nèi)部存儲器的40K字節(jié)中的第一個(gè)字節(jié)變量的地址,是u8類型指針變量,也就是說一個(gè)字節(jié)占用一個(gè)地址;換句話說,把內(nèi)部存儲器的40K字節(jié)的地址定義為一個(gè)“u8 mem1base[MEM1_MAX_SIZE]”數(shù)組,指針類型數(shù)組“u8 *membase[2];”的賦值是{mem1base,mem2base},而“mem1base,mem2base”分別是內(nèi)部內(nèi)存池和外部內(nèi)存池的數(shù)組名,各自首元素的地址亦是個(gè)指針常量;因?yàn)槭孪纫呀?jīng)定義
“u8 mem1base[MEM1_MAX_SIZE]”即“u8 mem1base[40K];”。如何理解“(void*)((u32)mallco_dev.membase[memx]+offset); ”呢?
1),已經(jīng)說過mallco_dev.membase[memx]是首個(gè)變量的地址即40k字節(jié)中首個(gè)字節(jié)的地址值;
2),“offset”是:向memx存儲器申請size個(gè)字節(jié)的連續(xù)空閑存儲空間,這個(gè)找到的連續(xù)空閑空間當(dāng)中首個(gè)字節(jié)的地址偏移值就是offset,offset==32(將32個(gè)字節(jié)空間組成一個(gè)內(nèi)存塊)*內(nèi)存塊號(如,假設(shè)向內(nèi)部存儲器申請64個(gè)字節(jié)的連續(xù)空閑存儲空間,通過“mem_malloc(memx,size); ”函數(shù)得到在第五個(gè)存儲塊開始有連續(xù)2個(gè)存儲快空閑可供使用(假設(shè)是5號和4號存儲快),因?yàn)槊總€(gè)存儲快有32個(gè)字節(jié)即有32個(gè)地址編號,4*32==128(這里的4是指第四塊),5*32==160(這里的5是指第五塊),那么這個(gè)160就是40K個(gè)字節(jié)編號當(dāng)中的地址偏移值offset,即128-192號就是第四塊和第五塊內(nèi)存塊所對應(yīng)的指針編號);注意offset是地址偏移值而不是地址;為什么要引入地址偏移值這個(gè)概念呢?假設(shè)第一個(gè)字節(jié)的地址值是0x0000 6800,那么就知道(0x0000 6800+160)的值就是第五塊內(nèi)存的指針。
3),“(u32)mallco_dev.membase[memx]”代表指針類型數(shù)組,意義是內(nèi)部存儲器40K字節(jié)中的第一個(gè)字節(jié)變量的地址,原來存放的是u8類型數(shù)據(jù)的地址,現(xiàn)在強(qiáng)制類型轉(zhuǎn)換擴(kuò)展為u32類型;
4),(void*)((u32)mallco_dev.membase[memx]+offset); 轉(zhuǎn)換為無類型指針,指針值是32位,由此可知,“void *mymalloc(u8 memx,u32 size)”函數(shù)的返回值就是一個(gè)指針,即形參size所指向的由高向低的首個(gè)指針值;“void *mymalloc(u8 memx,u32 size)”是個(gè)指針類型函數(shù),只能賦給指針。
*/
void *mymalloc(u8 memx,u32 size) //p=mymalloc(sramx,2048)
{
u32 offset;
offset=mem_malloc(memx,size);
if(offset==0XFFFFFFFF)return NULL;
else return (void*)((u32)mallco_dev.membase[memx]+offset);
}
//重新分配內(nèi)存(外部調(diào)用)
//memx:所屬內(nèi)存塊
//*ptr:舊內(nèi)存首地址
//size:要分配的內(nèi)存大小(字節(jié))
//返回值:新分配到的內(nèi)存首地址.
void *myrealloc(u8 memx,void *ptr,u32 size)
{
u32 offset;
offset=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)存
// 把size個(gè)字節(jié)指針ptr復(fù)制到“((u32)mallco_dev.membase[memx]+offset)”,
myfree(memx,ptr); //釋放舊內(nèi)存,因?yàn)樵趍em_malloc(memx,size)中已經(jīng)將連續(xù)空閑內(nèi)存塊標(biāo)注為1(已被占用),清除掉原來的標(biāo)記
return (void*)((u32)mallco_dev.membase[memx]+offset); //返回新內(nèi)存首地址,無類型指針
}
}
頭文件:
#ifndef __MALLOC_H
#define __MALLOC_H
typedef unsigned long u32;
typedef unsigned short u16;
typedef unsigned char u8;
#ifndef NULL
#define NULL 0
#endif
#define SRAMIN 0 //內(nèi)部內(nèi)存池
#define SRAMEX 1 //外部內(nèi)存池
//mem1內(nèi)存參數(shù)設(shè)定.mem1完全處于內(nèi)部SRAM里面
#define MEM1_BLOCK_SIZE 32 //內(nèi)存塊大小為32字節(jié)
#define MEM1_MAX_SIZE 40*1024 //最大管理內(nèi)存 40K
#define MEM1_ALLOC_TABLE_SIZE MEM1_MAX_SIZE/MEM1_BLOCK_SIZE //內(nèi)存表大小
//mem2內(nèi)存參數(shù)設(shè)定.mem2的內(nèi)存池處于外部SRAM里面,其他的處于內(nèi)部SRAM里面
#define MEM2_BLOCK_SIZE 32 //內(nèi)存塊大小為32字節(jié)
#define MEM2_MAX_SIZE 200*1024 //最大管理內(nèi)存200K
#define MEM2_ALLOC_TABLE_SIZE MEM2_MAX_SIZE/MEM2_BLOCK_SIZE //內(nèi)存表大小
看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人
(function(){
var bp = document.createElement('script');
var curProtocol = window.location.protocol.split(':')[0];
if (curProtocol === 'https') {
bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
}
else {
bp.src = 'http://push.zhanzhang.baidu.com/push.js';
}
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(bp, s);
})();
關(guān)鍵詞:
STM32原子戰(zhàn)艦板內(nèi)存管
相關(guān)推薦
技術(shù)專區(qū)
- FPGA
- DSP
- MCU
- 示波器
- 步進(jìn)電機(jī)
- Zigbee
- LabVIEW
- Arduino
- RFID
- NFC
- STM32
- Protel
- GPS
- MSP430
- Multisim
- 濾波器
- CAN總線
- 開關(guān)電源
- 單片機(jī)
- PCB
- USB
- ARM
- CPLD
- 連接器
- MEMS
- CMOS
- MIPS
- EMC
- EDA
- ROM
- 陀螺儀
- VHDL
- 比較器
- Verilog
- 穩(wěn)壓電源
- RAM
- AVR
- 傳感器
- 可控硅
- IGBT
- 嵌入式開發(fā)
- 逆變器
- Quartus
- RS-232
- Cyclone
- 電位器
- 電機(jī)控制
- 藍(lán)牙
- PLC
- PWM
- 汽車電子
- 轉(zhuǎn)換器
- 電源管理
- 信號放大器
評論