首頁>技術>

#微控制器##嵌入式程式設計##RTOS##程式設計師#

2、量化棧使用率

如何量化棧使用率,我們通常使用百分比來量化某些引數,比如考試100分滿分60分及格,這裡我們也使用百分比來量化棧使用率。量化公式如下:

棧使用率=100X歷史使用棧大小/分配棧大小

注意:下文計算棧使用率時計算單位為字而不是位元組(即四位元組為一個計量單位)。

特別規定,系統連續執行一定時間(如24小時)後“棧使用率”不超過60%為及格。要注意的是這裡我們是以不超60%為及格與考試不一樣喲,與考駕照更不一樣。要是達到90%及以上就等著系統崩潰吧。

3、堆疊的區別

在大部分時候我們都是將它拿到一起說的稱之為“堆疊”以至於分開來說還有些人不明白,事實上堆與棧是兩個不同的東西,即堆就是堆,棧就是棧。

堆:想象一下地面上有一堆沙,沙越多就堆得越高,如下圖所示:

堆的類比圖

如上圖,堆形象地說就像堆沙堆一樣,其地址從低到高向上增長,越堆越高,越拿走越低/少。

棧:其地址是從高到低向下增長的。想象有一條棧道,如下圖所示:

棧的類比圖

把堆與棧合併到一起如下圖所示(以一個工程例項分配說明)

堆與棧結構圖

上圖是我一個工程堆疊分配的地址值,不同專案,或者隨著專案功能的變化其值也會變化,或者改變S檔案中堆疊大小配置項,其值也會變化。此處僅舉例接近實現情況。

補充說明:上面說的向下或向上增長,指的都是地址。

計算棧使用率

5、測試棧使用率

為了測棧使用率,我定義兩個不同函式,其內部定義不同數量的區域性變數,呼叫函式前後統計棧使用率:我在配置棧總大小4096位元組,函式Test1()中定義區域性變數1000位元組(使用率約24%),函式Test1()中定義區域性變數3000位元組(使用率約73%)。如下圖所示:

6、關鍵測試程式碼如下
#define APP_START_ADDRESS 		0x08000000			//開始地址(棧頂地址)#define RAM_START_ADDRESS 		0x20000000			//RAM開始地址#define APP_STACK_SIZE			0x1000				//棧大小(位元組數量)4KB#define APP_HEAP_SIZE			0x1000				//堆大小(位元組數量)4KB#define MCU_RAM_SIZE			0x5000				//20KB// --------------------------------------------------#define BUFF_SIZE				1024				//定義公共大小	char buff[BUFF_SIZE];								//定義公共變數int GetGloablVarSum(void){	int i,sum=0;									//區域性變數	for(i=0;i<BUFF_SIZE;i++)						//公共變數初始化			{		buff[i]=i;		sum+=buff[i];								//計算功能變數的和	}	return sum;										//返回計算和		}// --------------------------------------------------int GetHeapVarSum(void){	int i,sum=0;									//定義公共變數	char *p1,*p2=(char*)malloc(BUFF_SIZE);			//從堆區申請記憶體	p1=p2;	memcpy(p2,buff,BUFF_SIZE);						//將公共變數的值複製到申請的記憶體中			p1=p2;	for(i=0;i<BUFF_SIZE;i++)						//計算申請記憶體中值的和			{		sum+=*p2++;	}	return sum;										//返回計算和}// --------------------------------------------------void TellAboutRam(){	unsigned int StackTopAddr=(*(__IO u32*)APP_START_ADDRESS);				//獲取棧頂地址	unsigned int HeapTopAddr=StackTopAddr-APP_STACK_SIZE;					//獲取堆頂/棧底地址	unsigned int GlobalVarSize=HeapTopAddr-APP_HEAP_SIZE-RAM_START_ADDRESS;	//計算公共變數區域大小	unsigned int RamFreeSize=MCU_RAM_SIZE-(StackTopAddr-RAM_START_ADDRESS);	//計算空閒區大小	printf ("棧	頂\t=\t%08XH \n",StackTopAddr); 	printf ("堆	頂\t=\t%08XH \n",HeapTopAddr); 	printf ("未分配區\t=\t%d Byte\n",RamFreeSize);	printf ("棧	區\t=\t%d Byte\n",APP_STACK_SIZE);	printf ("堆	區\t=\t%d Byte\n",APP_HEAP_SIZE);	printf ("公共變數區\t=\t%0d Byte\n",GlobalVarSize);}// --------------------------------------------------u8 GetMcuStackUsePercent(u8 temp){	u8 StackUsePercent=0;							//棧使用百分比	u32 i;	u32 StackTopAddr=0;								//棧頂地址	u32 StackAddrNow=0;								//棧當前地址(讀值時用)	u32 StackTotalWordSize=0;						//棧的字大小	u32 StackData=0;								//棧中的資料	u32 StackUnuseWordSize=0;						//棧中未使用字數量統計	StackTotalWordSize=APP_STACK_SIZE/4;			//計算棧控制字數量	StackTopAddr=(*(__IO u32*)APP_START_ADDRESS);	//讀取棧頂地址	StackAddrNow=StackTopAddr-APP_STACK_SIZE;		//計算棧底地址	for(i=0;i<StackTotalWordSize;i++)	{		StackData=(*(__IO u32*)StackAddrNow);		//讀取棧地址處的值		StackAddrNow+=4;							//地址往棧頂增加				if(StackData==0)							//將棧資料與初始值比較		{			StackUnuseWordSize++;					//棧資料==初始值		}		else		{			break;									//棧資料不等於初始值,退出統計過程		}	}													//計算棧使用率	StackUsePercent=100*(StackTotalWordSize-StackUnuseWordSize)/StackTotalWordSize;	#if 0		printf(" ------------- %d -------------\r\n",temp);		printf(" 1 APP_START_ADDRESS=%08XH \r\n",APP_START_ADDRESS);		printf(" 2 Stack Addr Top=%08XH Buttom=%08XH\r\n",StackTopAddr,StackTopAddr-APP_STACK_SIZE);		printf(" 3 STACK_SIZE=%04XH %d Bytes\r\n",APP_STACK_SIZE,APP_STACK_SIZE);		printf(" 4 StackSize Total=%d Unuse=%d Used=%d\r\n",StackTotalWordSize,StackUnuseWordSize,StackTotalWordSize-StackUnuseWordSize);	#endif	return StackUsePercent;							//返回棧使用率}void Test1(void){	char temp[1000];			//區域性變數(1000/4096=0.244=24%)	int i,sum=0;				//區域性變數	for(i=0;i<1000;i++)										{		temp[i]=i;		sum+=temp[i];			//計算功能變數的和	}}void Test2(void){	char temp[3000];			//區域性變數(3000/4096=0.732=73.2%)	int i,sum=0;				//區域性變數	for(i=0;i<3000;i++)										{		temp[i]=i;		sum+=temp[i];			//計算功能變數的和	}}int main (void)  {              	SER_Init ();                  	printf ("------------- Hello World ------------\n");      	printf ("測試公共變數\t=\t%d \t\n",GetGloablVarSum());      	printf ("測	堆區\t=\t%d \t\n",GetHeapVarSum()); 	TellAboutRam();	printf(" Test1前 棧使用率=%d%%\r\n",GetMcuStackUsePercent(1));		Test1();	printf(" Test1後 棧使用率=%d%%\r\n",GetMcuStackUsePercent(1));	Test2();	printf(" Test2後 棧使用率=%d%%\r\n",GetMcuStackUsePercent(1));		while (1) 	{                   		DelayMs(1000);		}                           }
7、模擬測試

測試結果如下圖

模擬測試棧使用百分比

15
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • python版本管理神器miniconda使用指南,純乾貨