色婷婷AⅤ一区二区三区|亚洲精品第一国产综合亚AV|久久精品官方网视频|日本28视频香蕉

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > 基于STM32原子戰(zhàn)艦板內(nèi)存管理源碼

          基于STM32原子戰(zhàn)艦板內(nèi)存管理源碼

          作者: 時間:2016-12-01 來源:網(wǎng)絡(luò) 收藏
          */
          //復(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個字節(jié)中,填充c,即把c寫入到*s為首地址的內(nèi)存中,個數(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個16位的數(shù)據(jù)是不是2個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個內(nèi)部內(nèi)存塊用以存儲u16類型指針,
          //“memtblsize[memx]”是什么呢?memtblsize[memx]即memtblsize[0]==1250個內(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,代表錯誤;其他,內(nèi)存偏移地址
          //向memx存儲器申請size個字節(jié)的連續(xù)存儲空間,并將size個字節(jié)中首個字節(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的一個成員,本句中就是對結(jié)構(gòu)體成員的引用,即執(zhí)行
          mem_init(u8 memx)函數(shù)的意思;如何引用結(jié)構(gòu)體中指向函數(shù)的指針變量成員?既然是指向函數(shù)的指針變量且有賦值,在引用時按照格式:
          結(jié)構(gòu)體變量名.指向函數(shù)的指針變量名(形參);
          */
          if(size==0)return 0XFFFFFFFF;//不需要分配 memblksize[memx]==32
          nmemb=size/memblksize[memx]; //獲取需要分配的連續(xù)內(nèi)存塊數(shù)
          /*
          c語言規(guī)定:除法的運算結(jié)果與運算對象的數(shù)據(jù)類型有關(guān),兩個數(shù)都是int則商(即結(jié)果)是int,若商(即結(jié)果)有小數(shù)則省略掉小數(shù)點部分。本例中
          size和memblksize[memx]都是int,所以結(jié)果只能是int。假設(shè)size<32,則nmemb==0;
          c語言規(guī)定取余運算的運算對象必須是int。當(dāng)小數(shù)對大數(shù)取余時余(即結(jié)果)是小數(shù)本身;例如,在“if(size%memblksize[memx])nmemb++;”中 ,
          假設(shè)size<32,則size%memblksize[memx]的結(jié)果是size值本身,所以執(zhí)行“nmemb++;”運算,這時運算結(jié)果是nmemb==1;如果size是32的整數(shù)倍則不執(zhí)行
          “nmemb++;”運算;
          memtblsize[0]==1250,memtblsize[1]==6250,
          mallco_dev.memmap[memx][offset]是什么意思?
          */
          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ù)增加,offset從1249->0變化
          /*
          如,{ memmap[0][149],memmap[0][148],...memmap[0][1],memmap[0][0]};實際上可以把“mallco_dev.memmap[memx][offset]”視為具有1250個變量的
          一維數(shù)組,每個元素對應(yīng)的實際意義是對應(yīng)的一個內(nèi)存塊,順序是offset從1249(高)->0(低)變化;如果哪個變量等于0(即空閑)就執(zhí)行
          “cmemb++;”操作,這樣就可以計算出連續(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)計值清零,這樣程序就會在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個內(nèi)存塊來存放65個字節(jié),再假設(shè)數(shù)組順序相連的變量值出現(xiàn)了類似“0,0,0,0,0”這樣的情況(即有
          連續(xù)4個空閑的內(nèi)存塊),這時就出現(xiàn)了符合“if(cmemb==nmemb)”條件的狀態(tài),即當(dāng)cmemb計數(shù)計到3的時候(即出現(xiàn)了連續(xù)相連的3個內(nèi)存塊)就
          符合“cmemb==nmemb”了,程序就自然進入“if(cmemb==nmemb)”語句。
          offset*memblksize[memx]代表什么呢?offset的取值范圍是0-1249,memblksize[memx]代表每個內(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個空內(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); //本句等價于“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個字節(jié)的連續(xù)空閑的內(nèi)存空間,并將連續(xù)空閑的內(nèi)存空間指針值標(biāo)注出來;返回值就是這個指針值
          /*
          mallco_dev.membase[memx]即mallco_dev.membase[0]代表MCU內(nèi)部存儲器的40K字節(jié)中的第一個字節(jié)變量的地址,是u8類型指針變量,也就是說一個字節(jié)占用一個地址;換句話說,把內(nèi)部存儲器的40K字節(jié)的地址定義為一個“u8 mem1base[MEM1_MAX_SIZE]”數(shù)組,指針類型數(shù)組“u8 *membase[2];”的賦值是{mem1base,mem2base},而“mem1base,mem2base”分別是內(nèi)部內(nèi)存池和外部內(nèi)存池的數(shù)組名,各自首元素的地址亦是個指針常量;因為事先已經(jīng)定義
          “u8 mem1base[MEM1_MAX_SIZE]”即“u8 mem1base[40K];”。如何理解“(void*)((u32)mallco_dev.membase[memx]+offset); ”呢?
          1),已經(jīng)說過mallco_dev.membase[memx]是首個變量的地址即40k字節(jié)中首個字節(jié)的地址值;
          2),“offset”是:向memx存儲器申請size個字節(jié)的連續(xù)空閑存儲空間,這個找到的連續(xù)空閑空間當(dāng)中首個字節(jié)的地址偏移值就是offset,offset==32(將32個字節(jié)空間組成一個內(nèi)存塊)*內(nèi)存塊號(如,假設(shè)向內(nèi)部存儲器申請64個字節(jié)的連續(xù)空閑存儲空間,通過“mem_malloc(memx,size); ”函數(shù)得到在第五個存儲塊開始有連續(xù)2個存儲快空閑可供使用(假設(shè)是5號和4號存儲快),因為每個存儲快有32個字節(jié)即有32個地址編號,4*32==128(這里的4是指第四塊),5*32==160(這里的5是指第五塊),那么這個160就是40K個字節(jié)編號當(dāng)中的地址偏移值offset,即128-192號就是第四塊和第五塊內(nèi)存塊所對應(yīng)的指針編號);注意offset是地址偏移值而不是地址;為什么要引入地址偏移值這個概念呢?假設(shè)第一個字節(jié)的地址值是0x0000 6800,那么就知道(0x0000 6800+160)的值就是第五塊內(nèi)存的指針。
          3),“(u32)mallco_dev.membase[memx]”代表指針類型數(shù)組,意義是內(nèi)部存儲器40K字節(jié)中的第一個字節(jié)變量的地址,原來存放的是u8類型數(shù)據(jù)的地址,現(xiàn)在強制類型轉(zhuǎn)換擴展為u32類型;
          4),(void*)((u32)mallco_dev.membase[memx]+offset); 轉(zhuǎn)換為無類型指針,指針值是32位,由此可知,“void *mymalloc(u8 memx,u32 size)”函數(shù)的返回值就是一個指針,即形參size所指向的由高向低的首個指針值;“void *mymalloc(u8 memx,u32 size)”是個指針類型函數(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個字節(jié)指針ptr復(fù)制到“((u32)mallco_dev.membase[memx]+offset)”,
          myfree(memx,ptr); //釋放舊內(nèi)存,因為在mem_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)存表大小

          評論


          技術(shù)專區(qū)

          關(guān)閉