娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

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

發(fā)布者:腦力激蕩最新更新時(shí)間:2021-05-31 來源: eefocus關(guān)鍵字:STM32  原子戰(zhàn)艦板  內(nèi)存管理 手機(jī)看文章 掃描二維碼
隨時(shí)隨地手機(jī)看文章

簡介:走到今天,已經(jīng)開始涉及到計(jì)算機(jī)核心一點(diǎn)的東西了---內(nèi)存管理。通過本實(shí)驗(yàn)的學(xué)習(xí),能夠較為深刻體會(huì)到“指針是c語言的靈魂”這句話的分量。自然對c語言的能力要求就高很多了。本文是基于原子老師的c源碼,自己的學(xué)習(xí)的心得,只是對源碼作出自己的學(xué)習(xí)理解,同時(shí)也插補(bǔ)了一些涉及到的c語言知識(shí)。貼出本文不為別的,一來但愿能有有緣人看到本文,提出指正;二來,為了那些不眠的夜,安慰一下自己。


1, 內(nèi)存管理簡介

內(nèi)存管理,是指軟件運(yùn)行時(shí)對計(jì)算機(jī)內(nèi)存資源的分配和使用的技術(shù)。其最主要的目的是如何高效,快速的分配,并且在適當(dāng)?shù)臅r(shí)候釋放和回收內(nèi)存資源。內(nèi)存管理的實(shí)現(xiàn)方法有很多種,他們其實(shí)最終都是要實(shí)現(xiàn)2個(gè)函數(shù):malloc和free;malloc函數(shù)用于內(nèi)存申請,free函數(shù)用于內(nèi)存釋放。


先回顧一下c語言知識(shí):計(jì)算機(jī)內(nèi)存一般分為靜態(tài)存儲(chǔ)區(qū)用以存儲(chǔ)全局變量或常量和動(dòng)態(tài)存儲(chǔ)區(qū)用以存儲(chǔ)函數(shù)內(nèi)部變量或形參或函數(shù)運(yùn)算結(jié)果。malloc()函數(shù)的作用是請求系統(tǒng)在內(nèi)存的動(dòng)態(tài)存儲(chǔ)區(qū)分配若干個(gè)字節(jié)的存儲(chǔ)空間,函數(shù)的返回值是首字節(jié)地址,可見malloc()函數(shù)是指針類型。free(P)的作用是釋放指針變量P所指向的動(dòng)態(tài)空間。


本章,我們介紹一種比較簡單的辦法來實(shí)現(xiàn):分塊式內(nèi)存管理。下面我們介紹一下該方法的實(shí)現(xiàn)原理,如圖所示(示意圖):


內(nèi)存塊1 內(nèi)存塊2 內(nèi)存塊3 ……內(nèi)存塊n     內(nèi)存池
   |       |       |          |
第1項(xiàng)   第2項(xiàng)   第3項(xiàng)   ……第n項(xiàng)       內(nèi)存管理表
                       <<-----分配方向
                                 |
                        malloc,free等函數(shù)

圖解:從上圖可以看出,分塊式內(nèi)存管理由內(nèi)存池和內(nèi)存管理表兩部分組成。內(nèi)存池被等分為n塊,對應(yīng)的內(nèi)存管理表,大小也為n,內(nèi)存管理表的每一個(gè)項(xiàng)對應(yīng)內(nèi)存池的一塊內(nèi)存。


內(nèi)存管理表的項(xiàng)值代表的意義為:當(dāng)該項(xiàng)值為0的時(shí)候,代表對應(yīng)的內(nèi)存塊未被占用,當(dāng)該項(xiàng)值非零的時(shí)候,代表該項(xiàng)對應(yīng)的內(nèi)存塊已經(jīng)被占用,其數(shù)值則代表被連續(xù)占用的內(nèi)存塊數(shù)。比如某項(xiàng)值為10,那么說明包括本項(xiàng)對應(yīng)的內(nèi)存塊在內(nèi),總共分配了10個(gè)內(nèi)存塊給外部的某個(gè)指針。


內(nèi)寸分配方向如圖所示,是從頂à底的分配方向。即首先從最末端開始找空內(nèi)存。當(dāng)內(nèi)存管理剛初始化的時(shí)候,內(nèi)存表全部清零,表示沒有任何內(nèi)存塊被占用。


分配原理:

當(dāng)指針p調(diào)用malloc申請內(nèi)存的時(shí)候,先判斷p要分配的內(nèi)存塊數(shù)(m),然后從第n項(xiàng)開始,向下查找,直到找到m塊連續(xù)的空內(nèi)存塊(即對應(yīng)內(nèi)存管理表項(xiàng)為0),然后將這m個(gè)內(nèi)存管理表項(xiàng)的值都設(shè)置為m(標(biāo)記被用),最后,把最后的這個(gè)空內(nèi)存塊的地址返回指針p,完成一次分配。注意,如果當(dāng)內(nèi)存不夠的時(shí)候(找到最后也沒找到連續(xù)的m塊空閑內(nèi)存),則返回NULL(空指針)給p,表示分配失敗。


釋放原理:

當(dāng)p申請的內(nèi)存用完,需要釋放的時(shí)候,調(diào)用free函數(shù)實(shí)現(xiàn)。free函數(shù)先判斷p指向的內(nèi)存地址所對應(yīng)的內(nèi)存塊,然后找到對應(yīng)的內(nèi)存管理表項(xiàng)目,得到p所占用的內(nèi)存塊數(shù)目m(內(nèi)存管理表項(xiàng)目的值就是所分配內(nèi)存塊的數(shù)目),將這m個(gè)內(nèi)存管理表項(xiàng)目的值都清零,標(biāo)記釋放,完成一次內(nèi)存釋放。

關(guān)于分塊式內(nèi)存管理的原理,我們就介紹到這里。


2, 硬件設(shè)計(jì):

本章實(shí)驗(yàn)功能簡介:開機(jī)后,顯示提示信息,等待外部輸入。KEY0用于申請內(nèi)存,每次申請2K字節(jié)內(nèi)存。KEY1用于寫數(shù)據(jù)到申請到的內(nèi)存里面。KEY2用于釋放內(nèi)存。WK_UP用于切換操作內(nèi)存區(qū)(內(nèi)部內(nèi)存/外部內(nèi)存)。DS0用于指示程序運(yùn)行狀態(tài)。本章我們還可以通過USMART調(diào)試,測試內(nèi)存管理函數(shù)。


本實(shí)驗(yàn)用到的硬件資源有:

1) 指示燈DS0

2) 四個(gè)按鍵

3) 串口 //USMART

4) TFTLCD模塊

5) IS62WV51216


3, 軟件設(shè)計(jì):

本章,我們將內(nèi)存管理部分單獨(dú)做一個(gè)分組,在工程目錄下新建一個(gè)MALLOC的文件夾,然后新建malloc.c和malloc.h兩個(gè)文件,將他們保存在MALLOC文件夾下。


在MDK新建一個(gè)MALLOC的組,然后將malloc.c文件加入到該組,并將MALLOC文件夾添加到頭文件包含路徑。


打開malloc.c文件,輸入如下代碼:由于本實(shí)驗(yàn)涉及到的c語言知識(shí),尤其是指針知識(shí)較多,所以就邊用邊學(xué)

#include "malloc.h"

//內(nèi)存池(4字節(jié)對齊)

__align(4) u8 mem1base[MEM1_MAX_SIZE];//內(nèi)部SRAM內(nèi)存池

/*

" u8 mem1base[MEM1_MAX_SIZE];"該數(shù)組是定義拿出內(nèi)部內(nèi)存池的40K的空間來做實(shí)驗(yàn),為什么該數(shù)組是u8類型?計(jì)算機(jī)內(nèi)存是以字節(jié)為單位的存儲(chǔ)空間,內(nèi)存中的每個(gè)字節(jié)都有唯一的編號,這個(gè)編號就叫地址。在這里就是定義40K個(gè)元素,每個(gè)元素代表一個(gè)字節(jié)。整個(gè)數(shù)組就代表整個(gè)內(nèi)部SRAM內(nèi)存池的總?cè)萘考?0K個(gè)元字節(jié)的總空間容量。因?yàn)椴还苁谴鎯?chǔ)什么數(shù)據(jù)類型內(nèi)存中的地址編號都是32位的,即每個(gè)地址編號可以容納4個(gè)字節(jié),而不同的數(shù)據(jù)類型存儲(chǔ)在不同的內(nèi)存存儲(chǔ)區(qū),這就是為什么定義變量時(shí)一定要先聲明其數(shù)據(jù)類型的原因。存儲(chǔ)一個(gè)字符需要一個(gè)字節(jié)的存儲(chǔ)空間,存儲(chǔ)一個(gè)short類型需要2個(gè)字節(jié)的存儲(chǔ)空間,存儲(chǔ)一個(gè)int或float需要4個(gè)字節(jié)空間,就如同PLC內(nèi)存中的字節(jié),字,雙字的定義規(guī)則一樣(如字節(jié)MB0,MB1,MB0和MB1構(gòu)成MW0;MW0和MW2構(gòu)成32位的雙字DW0,DW4,DW8)。“__align(4)”就是規(guī)定4個(gè)字節(jié)對齊,即每個(gè)32的地址編號存儲(chǔ)一個(gè)數(shù)據(jù)類型?比如,字符存儲(chǔ)區(qū)中地址編號MB0可以存儲(chǔ)一個(gè)字節(jié)即8個(gè)位的數(shù)據(jù),而存儲(chǔ)MB0這個(gè)地址編號是以32位的空間來存儲(chǔ),也就是說不管是什么類型數(shù)據(jù),存儲(chǔ)它的地址編號都是32的,所以指針值一定是32位的。


//“#define MEM1_MAX_SIZE40*1024 //最大管理內(nèi)存 40K”,意思是mem1base[MEM1_MAX_SIZE]有40k個(gè)元素

*/

__align(4) u8 mem2base[MEM2_MAX_SIZE] __attribute__((at(0X68000000)));//外部SRAM內(nèi)存池

//#define MEM2_MAX_SIZE 200*1024 //最大管理內(nèi)存200K,意思是mem2base[MEM2_MAX_SIZE]數(shù)組有200K個(gè)u8類型元素,第一個(gè)元素的地址存儲(chǔ)在 //外部存儲(chǔ)器SRAM的0X68000000地址,

//內(nèi)存管理表

u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];//內(nèi)部SRAM內(nèi)存池MAP

/*

//#define MEM1_ALLOC_TABLE_SIZEMEM1_MAX_SIZE/MEM1_BLOCK_SIZE //內(nèi)存表大小,MEM1_MAX_SIZE/MEM1_BLOCK_SIZE==1250

//#define MEM1_BLOCK_SIZE32 //內(nèi)存塊大小為32字節(jié);“MEM1_MAX_SIZE/MEM1_BLOCK_SIZE ”的含義是內(nèi)部SRAM內(nèi)存池總共40K字節(jié)的容量除以32個(gè)字節(jié),得到一共40K/32==1250個(gè)內(nèi)存塊;也就是說將內(nèi)部SRAM內(nèi)存池劃為1250個(gè)內(nèi)存塊。

“u16 mem1mapbase[MEM1_ALLOC_TABLE_SIZE];”實(shí)際上就等于“u16 mem1mapbase[1250];”意思是定義一個(gè)有1250個(gè)內(nèi)存塊(元素)的數(shù)組,每個(gè)元素是u16類型數(shù)據(jù);數(shù)組名“mem1mapbase”就是mem1mapbase[0](該數(shù)組的第一個(gè)元素它代表1250個(gè)內(nèi)存塊中的第一個(gè)內(nèi)存塊)的地址,也可以說是指針常量;結(jié)合與之關(guān)聯(lián)的結(jié)構(gòu)體成員“u16 *memmap[2]={ mem1mapbase,mem2mapbase}”指針類型數(shù)組;在這里“mem2mapbase”是外部內(nèi)存的第一個(gè)內(nèi)存塊的地址,是個(gè)指針常量用以存放u16類型數(shù)據(jù)的地址值;結(jié)合

“mymemset(mallco_dev.memmap[0], 0,memtblsize[0]*2);”函數(shù)分析:結(jié)合本程序和結(jié)構(gòu)體有關(guān)定義“u16 *memmap[2]; ”,首元素memmap[0]=mem1mapbase;也就是說“mallco_dev.memmap[0]”在這里表示1250個(gè)內(nèi)部內(nèi)存塊中第一個(gè)內(nèi)存塊的地址,根據(jù)“u16 *memmap[2]={ mem1mapbase,mem2mapbase}”推斷出“mallco_dev.memmap[0]”是u16類型指針;

“memtblsize[0]”是什么意思呢?根據(jù)“const u32 memtblsize[2]={1250,6250};”可以得知memtblsize[0]==1250即內(nèi)部內(nèi)存一共有1250個(gè)管理項(xiàng),

void mymemset(void *s,u8 c,u32 count)

{

u8 *xs = s;

while(count--)*xs++=c;

}//把u8類型數(shù)據(jù)c填充到以指針變量s為首地址的內(nèi)存空間中,填充多少個(gè)數(shù)由count值決定


該函數(shù)的意思是把u8類型的數(shù)據(jù)“c”填充到u16類型指針元素memmap[0]中(根據(jù)結(jié)構(gòu)體定義“u16 *memmap[2]; ”,而memmap[0]=mem1mapbase),說白了就是把u8類型的數(shù)據(jù)“c”填充到1250個(gè)內(nèi)存塊中的count個(gè)內(nèi)存塊中。


而mallco_dev.memmap[memx]是16位的,為了將其全部清零,所以乘以2.

本例中,用到了指針類型數(shù)組“u16 *memmap[2]={ mem1mapbase,mem2mapbase}”,為什么要定義指針類型數(shù)組呢?mem1mapbase是數(shù)組

“u16 mem1mapbase[1250];”的首個(gè)元素地址(即*mem1mapbase等價(jià)于mem1mapbase[0]),而mem1mapbase[0]就代表內(nèi)部存儲(chǔ)器1250個(gè)存儲(chǔ)塊中的第一個(gè)存儲(chǔ)塊;根據(jù)結(jié)構(gòu)體賦值定義可知:memmap[0]=mem1mapbase。所以mem1mapbase就是“mallco_dev.memmap[0]”,即mem1mapbase是函數(shù)mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2)的第一個(gè)形參,因?yàn)?mem1mapbase等價(jià)于mem1mapbase[0]),而mem1mapbase[0]就代表內(nèi)部存儲(chǔ)器1250個(gè)存儲(chǔ)塊中的第一個(gè)存儲(chǔ)塊。結(jié)合

void mymemset(void *s,u8 c,u32 count)函數(shù)分析, mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2)函數(shù)的意思是:把0寫入到1250個(gè)存儲(chǔ)塊中的第一個(gè)存儲(chǔ)塊中;這樣就將一個(gè)存儲(chǔ)塊的值賦值為0了。


推斷出“mallco_dev.memmap[0]”是u16類型指針;

*/

u16 mem2mapbase[MEM2_ALLOC_TABLE_SIZE] __attribute__((at(0X68000000+MEM2_MAX_SIZE)));

/*

“#define MEM2_ALLOC_TABLE_SIZEMEM2_MAX_SIZE/MEM2_BLOCK_SIZE”

“#define MEM2_BLOCK_SIZE32”

外部SRAM內(nèi)存池MAP,同理,“MEM2_MAX_SIZE/MEM2_BLOCK_SIZE”的含義是外部SRAM內(nèi)存池總共200K字節(jié)的容量除以32個(gè)字節(jié),得到一共200K/32==6250個(gè)內(nèi)存塊;也就是說將外部SRAM內(nèi)存池劃為6250個(gè)內(nèi)存塊。

*/

//內(nèi)存管理參數(shù)

/*

內(nèi)存管理表“MEM1_ALLOC_TABLE_SIZE,MEM2_ALLOC_TABLE_SIZE”分別是1250和6250個(gè)“項(xiàng)”.

每個(gè)內(nèi)存分塊大小即內(nèi)部和外部SRAM每個(gè)內(nèi)存塊占有32個(gè)字節(jié)空間“MEM1_BLOCK_SIZE,MEM2_BLOCK_SIZE”分別是32個(gè)字節(jié);

內(nèi)存總大小“MEM1_MAX_SIZE,MEM2_MAX_SIZE”,分別是40K和200K個(gè)字節(jié)的總?cè)萘靠臻g

mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);

*/

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)存總大小

/*

struct _m_mallco_dev //內(nèi)存管理控制器,定義一個(gè)結(jié)構(gòu)體類型數(shù)據(jù),或結(jié)構(gòu)體變量,

{

void (*init)(u8);//初始化

u8 (*perused)(u8); //內(nèi)存使用率

u8 *membase[2];//內(nèi)存池 管理2個(gè)區(qū)域的內(nèi)存 mem1base,mem2base內(nèi)存池

u16 *memmap[2]; //內(nèi)存管理狀態(tài)表 mem1mapbase(==1250塊),mem2mapbase(6250), //內(nèi)存管理狀態(tài)表

u8 memrdy[2]; //內(nèi)存管理是否就緒

};

1,結(jié)構(gòu)體成員“void (*init)(u8);”是定義了一個(gè)指向函數(shù)的指針變量,該指針變量名是init;void表示該函數(shù)沒有返回值(函數(shù)的數(shù)據(jù)類型由返回值決定);u8是函數(shù)的形參。指向函數(shù)的指針變量格式:數(shù)據(jù)類型 + (*變量名)(形參)

本例中:

void mem_init(u8 memx)

{

mymemset(mallco_dev.memmap[memx], 0,memtblsize[memx]*2);//內(nèi)存狀態(tài)表數(shù)據(jù)清零 memx:所屬內(nèi)存塊,即幾號內(nèi)存塊

mymemset(mallco_dev.membase[memx], 0,memsize[memx]);//內(nèi)存池所有數(shù)據(jù)清零

mallco_dev.memrdy[memx]=1;//內(nèi)存管理初始化OK

}

也就是說,本例中用指向函數(shù)的指針變量來表示函數(shù)。c語言規(guī)定函數(shù)名就是函數(shù)的入口地址,也就是說函數(shù)名也是一個(gè)指針,指向函數(shù)的入口,根據(jù)這個(gè)原理,可以將指向函數(shù)的指針作為函數(shù)的參數(shù)調(diào)用,可以在不同的情況調(diào)用不同的函數(shù);如果一個(gè)指向函數(shù)的指針變量等于函數(shù)名就可以說該指向函數(shù)的指針變量指向了該函數(shù),那么指針變量與函數(shù)就是一樣的了。比如:“mem_init(memx);”就等同于“mallco_dev.init(memx);”

2,指針類型數(shù)組“u8 *membase[2];”,意思是該指針類型數(shù)組有兩個(gè)“char *”類型的指針元素或者說有兩個(gè)“u8 *”類型指針元素;為什么要定義“u8 *”類型呢?因?yàn)閮?nèi)存存儲(chǔ)區(qū)是根據(jù)數(shù)據(jù)類型來劃分的,如果不明確聲明類型就亂套了。

在C語言和C++語言中,數(shù)組元素全為指針的數(shù)組稱為指針數(shù)組。一維指針數(shù)組的定義形式為:“類型名 *數(shù)組標(biāo)識(shí)符[數(shù)組長度]”。

例如,一個(gè)一維指針數(shù)組的定義:int *ptr_array[10]。該指針數(shù)組有10個(gè)元素,每個(gè)元素都是int類型的指針即“int *”類型;

指針類型數(shù)組“u8 *membase[2];”的賦值是mem1base,mem2base,“mem1base,mem2base”分別是內(nèi)部內(nèi)存池和外部內(nèi)存池的數(shù)組名,是指針常量即首元素的地址;因?yàn)槭孪纫呀?jīng)定義“u8 mem1base[MEM1_MAX_SIZE]”即“u8 mem1base[40K];”。

*/

//內(nèi)存管理控制器,結(jié)構(gòu)體變量賦值,即初始化

struct _m_mallco_dev mallco_dev=

{

mem_init,//內(nèi)存初始化,將函數(shù)名“mem_init”賦給結(jié)構(gòu)體成員“void (*init)(u8);”即指向函數(shù)的指針變量,

mem_perused,//內(nèi)存使用率

mem1base,mem2base,//內(nèi)存池

mem1mapbase,mem2mapbase, //內(nèi)存管理狀態(tài)表,mem1mapbase(1250項(xiàng)),mem2mapbase(6250項(xiàng))

0,0, //內(nèi)存管理未就緒

};

/*

1,“void *des”無類型指針,不能指向具體的數(shù)據(jù),“void *des”無類型指針指向內(nèi)存中的數(shù)據(jù)類型由用戶自己確定,如malloc()函數(shù)的返回值就是“void *des”無類型指針,因?yàn)閙alloc()函數(shù)的返回值是不確定的是根據(jù)形參的數(shù)據(jù)類型確定的

2,“void mymemcpy(void *des,void *src,u32 n) ”函數(shù)的理解:

des是指針,但是不確定指向什么類型的數(shù)據(jù),換句話說des指針存儲(chǔ)的什么類型數(shù)據(jù)不確定,“u8 *xdes=des;”將des指針存儲(chǔ)的數(shù)據(jù)

存儲(chǔ)到一個(gè)新的“u8 *”類型指針xdes中;“u8 *xsrc=src;”同理。

“*xdes++=*xsrc++; ”,當(dāng)*xsrc++(自增)時(shí),即指針“src”指針自增,也就是說把“src”指針逐位復(fù)制到des目標(biāo)指針去了。復(fù)制個(gè)數(shù)就是n。

3,“*P”的意義:a),“*P”就是以指針變量P的內(nèi)容(P的內(nèi)容就是指針變量P里存儲(chǔ)的某一類型數(shù)據(jù)的指針值)為地址的變量;b),指針運(yùn)算符“*”如果是在定義變量時(shí)候加在前面,意思是這個(gè)變量是指針變量,如 char *a;如果是在訪問指針變量的時(shí)候加在前面(如*a),意思是取指針變量指向的值,如 char b=*a; 上面定義了a是一個(gè)字符指針,這里就是把指針變量a指向的值取出來并賦給b。

*/

//復(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存儲(chǔ)到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)存塊用以存儲(chǔ)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存儲(chǔ)器申請size個(gè)字節(jié)的連續(xù)存儲(chǔ)空間,并將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í)行

[1] [2] [3]
關(guān)鍵字:STM32  原子戰(zhàn)艦板  內(nèi)存管理 引用地址:基于STM32原子戰(zhàn)艦板內(nèi)存管理源碼詳解

上一篇:STM32 4-20mA輸出電路
下一篇:基于STM32的電池管理系統(tǒng)觸摸屏設(shè)計(jì)方案

推薦閱讀最新更新時(shí)間:2025-06-01 06:00

VSCode+arm-none-eabi+msys使用Make實(shí)現(xiàn)STM32交叉編譯
記錄一下在Windows平臺(tái)下,利用VSCode的arm-none-eabi擴(kuò)展和msys使用Make實(shí)現(xiàn)STM32的交叉編譯。 準(zhǔn)備: 1.安裝arm-none-eabi擴(kuò)展 在VSCode的擴(kuò)展窗口,搜索eabi,安裝windows-arm-none-eabi擴(kuò)展 需要注意:我最開始安裝的0.1.6版本,但是編譯到最后copy的時(shí)候出錯(cuò),安裝0.1.2版本后,就正常,目前沒有去詳細(xì)分析原因。 這里搜索出來的時(shí)候,只能安裝最新版本,安裝成功后,可以點(diǎn)擊“設(shè)置”- “Install Another Version...” 來安裝舊版本。有的時(shí)候“Install Another Version...”不可點(diǎn)擊,重啟一下
[單片機(jī)]
Archlinux下 stm32 燒寫工具配置
1. 使用的開發(fā)板子 使用的開發(fā)板是好幾年好幾年前買的了,板子一直在家里睡覺。最近閑著沒事,所以打算學(xué)習(xí)一下stm32. 板子是普中STM32-PZ6806L開發(fā)板。開發(fā)板的圖見下 puzhongkaifaban.png 2. stm32 燒入程序原理 我們這里使用ISP(In-System Programming)燒入. ISP 燒入使用串口. 這個(gè)開發(fā)板子提供了上圖的6的位置是一個(gè)miniUSB,5的位置是一個(gè)usb轉(zhuǎn)串口的芯片。5,6的原理圖見下: yuanli.png 其中串口的 DTR引腳控制STM32的重置。 RTS引腳控制STM32的boot選擇。 我們要想燒入程序:要把開發(fā)版上面的34的位置的跳冒 BOOT
[單片機(jī)]
Arduino IDE 編寫STM32代碼無下載器 串口下載
準(zhǔn)備用STM32的開發(fā)板寫一個(gè)直流無刷電機(jī)BLDC的驅(qū)動(dòng)程序,對Arduino IDE的編程模式比較熟悉,通過相應(yīng)的插件,Arduino IDE同樣可以支持STM32。 另外因?yàn)槭诸^沒有STM32的下載器,需要通過串口燒錄程序。準(zhǔn)備先用一個(gè)Samples中的點(diǎn)亮LED的示例來跑通這個(gè)STM32的開發(fā)流程,沒想到竟然折騰了差不多一天的時(shí)間,不懈努力,不輕言放棄,最后才在STM32開發(fā)板上,通過Arduino IDE,串口燒錄程序,成功點(diǎn)亮了IDE。看到IDE一閃一閃,體驗(yàn)了成功的喜悅。 記錄一下折騰的過程。 手頭的STM32開發(fā)板的型號為STM32F401CxUx。本來準(zhǔn)備買來做USB聲卡的。 STM32F401.JPG
[單片機(jī)]
stm32的RTC
兩個(gè)分離的時(shí)鐘:用于APB1接口的PCLK1和RTC時(shí)鐘的(RTC時(shí)鐘的頻率必須小于PCLK1時(shí)鐘頻率的四分之一); RTC的時(shí)鐘源的配置可以使用函數(shù)庫中的函數(shù)進(jìn)行配置; RTC的中斷也是使用函數(shù)庫中的額函數(shù)進(jìn)行配置的; void RTC_Configuration(void) {//RTC的時(shí)鐘為兩個(gè)分離的時(shí)鐘:用于APB1的PCLK1和RTC時(shí)鐘(RTC的時(shí)鐘的頻率必須小于PCLK1時(shí)鐘頻率的四分之一以上 RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR|RCC_APB1Periph_BKP,ENABLE); //PWR和BKP時(shí)鐘使能 PWR_BackupAccessCmd(ENAB
[單片機(jī)]
<font color='red'>stm32</font>的RTC
STM32添加看門狗
通過 MX_IWDG_Init 時(shí), 已經(jīng)開啟IWDG. 剩下就是在合適的時(shí)機(jī) HAL_IWDG_Refresh(&hiwdg); 由專門的低速時(shí)鐘(LSI)驅(qū)動(dòng),即便是主時(shí)鐘發(fā)生故障它仍能夠有效,所以此狗狗可以工作在與主時(shí)鐘無關(guān)的要求下,或者待機(jī)模塊下等,所以它叫獨(dú)立看門狗,注意一旦開啟此看門狗則只能由MCU復(fù)位后才清除,讓它不再工作。 它的時(shí)鐘是一個(gè)內(nèi)部RC時(shí)鐘,它會(huì)在30KHZ到60KHZ之間變化,并非是精確的40KHZ,而只是一般計(jì)算時(shí)取40KHZ。 點(diǎn)擊(此處)折疊或打開 ##### How to use this driver ##### ===============================
[單片機(jī)]
STM32芯片存儲(chǔ)器映射概述
STM32系統(tǒng)構(gòu)架 當(dāng)你拿到一款芯片后,怎樣可以快速了解到它具有哪些功能?了解單片機(jī)的系統(tǒng)架構(gòu)是使用款芯片的基礎(chǔ),這些信息在芯片手冊上都會(huì)有詳細(xì)的說明,并且它們會(huì)被安排在最前面的章節(jié),目的就是讓用戶最開始就能夠關(guān)注到該款芯片具有哪些功能,特點(diǎn)。 STM32F103系統(tǒng)結(jié)構(gòu) 從上圖我們可以了解到STM32F103系列的主要系統(tǒng)組成單元: CPU核:使用ARM Cortex-M3內(nèi)核; 存儲(chǔ)器: STM32F103系列微控制器采用經(jīng)典的哈佛架構(gòu),程序存儲(chǔ)和數(shù)據(jù)存儲(chǔ)采用獨(dú)立的存儲(chǔ)器空間; ICode:指令代碼,F(xiàn)lash存儲(chǔ)器用于存儲(chǔ)程序; DCode:數(shù)據(jù)代碼,SRAM用于存儲(chǔ)數(shù)據(jù); 外設(shè): GPIO;
[單片機(jī)]
<font color='red'>STM32</font>芯片存儲(chǔ)器映射概述
基于STM32的智能飲水機(jī)系統(tǒng)設(shè)計(jì)
一、項(xiàng)目背景 隨著智能化的迅速發(fā)展,人們對于生活中的各類設(shè)備也越來越有智能化的需求,其中智能飲水機(jī)是一種比較常見的設(shè)備。智能飲水機(jī)不僅可以提供飲用水,還可以通過智能化的技術(shù)滿足人們對于水質(zhì)、水溫、出水量等方面的需求。因此,當(dāng)前設(shè)計(jì)了一種基于STM32的智能飲水機(jī)系統(tǒng),以滿足人們對智能化飲水機(jī)的需求。 智能飲水機(jī)系統(tǒng)其主要功能包括: 【1】控制加熱芯片:通過繼電器模塊控制加熱芯片,在水燒開后自動(dòng)斷電。 【2】液位感應(yīng):使用液位傳感器感應(yīng)水箱水位,當(dāng)水位過低時(shí)通過語音模塊進(jìn)行播報(bào)提示。 【3】移動(dòng)端控制:Android手機(jī)端可以顯示當(dāng)前雙水箱內(nèi)的水溫,設(shè)置出水溫度及出水量,并且還可以控制出水操作。 【4】主控芯片:采用STM32F
[單片機(jī)]
基于<font color='red'>STM32</font>的智能飲水機(jī)系統(tǒng)設(shè)計(jì)
STM32有哪些國產(chǎn)替代者?
說起MCU,ST(意法半導(dǎo)體)的STM32單片機(jī)十幾年來已經(jīng)銷售了幾十億顆,在國內(nèi)幾乎占有50%的市場,會(huì)使用STM32單片機(jī)也基本成為電子工程師的標(biāo)配職業(yè)技能,然而2018年下半年的供貨緊張,以及中興事件,給我們硬件工程師敲了敲警鐘,假如有一天我們必須替換下STM32單片機(jī),國產(chǎn)芯有哪些是可以替代的呢? 北京兆易創(chuàng)新-GD32系列 GD32作為中國32位通用MCU領(lǐng)域的主流之選,以累計(jì)超過2億顆的出貨數(shù)量、超過1萬的用戶數(shù)量、20個(gè)系列300余款產(chǎn)品型號選擇的廣闊應(yīng)用覆蓋率穩(wěn)居市場前列。GD32使用的是Cortex-M3內(nèi)核,型號做到了與STM32相同型號的全兼容,方便替換,主頻頻率更高。 GD32F103是GD早期的產(chǎn)
[單片機(jī)]
<font color='red'>STM32</font>有哪些國產(chǎn)替代者?
小廣播
設(shè)計(jì)資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機(jī)文章
隨便看看

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機(jī)器人開發(fā)圈

電子工程世界版權(quán)所有 京B2-20211791 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 新晃| 互助| 平安县| 应用必备| 罗源县| 陇西县| 临沭县| 科尔| 阿拉善盟| 新民市| 无棣县| 华蓥市| 海兴县| 和林格尔县| 洛南县| 河东区| 建湖县| 湾仔区| 伊宁市| 白银市| 延边| 香格里拉县| 崇文区| 盐池县| 和田县| 白银市| 南宁市| 湘潭市| 大田县| 苗栗县| 垣曲县| 丰宁| 邛崃市| 郁南县| 西乌珠穆沁旗| 望奎县| 迁安市| 通渭县| 颍上县| 塘沽区| 连州市|