堆栈使用测量
文章目錄
- 1 堆棧使用測量
- 1.1 問題概述
- 1.2 設(shè)計(jì)原理
- 1.3 設(shè)計(jì)實(shí)現(xiàn)
1 堆棧使用測量
1.1 問題概述
我們知道在當(dāng)前的設(shè)計(jì)中每個(gè)任務(wù)都配備一個(gè)有限的任務(wù)棧,用于保存各種關(guān)鍵性的數(shù)據(jù)。但是這個(gè)棧空間是有限的,實(shí)際有可能超出此空間。
可能出現(xiàn)如下錯(cuò)誤:
1.2 設(shè)計(jì)原理
設(shè)計(jì)原理如下:
注意事項(xiàng):
1.3 設(shè)計(jì)實(shí)現(xiàn)
清空堆棧空間:
統(tǒng)計(jì)堆棧使用情況:
需要修改task結(jié)構(gòu)體:
// 任務(wù)結(jié)構(gòu):包含了一個(gè)任務(wù)的所有信息 typedef struct _tTask {// 任務(wù)所用堆棧的當(dāng)前堆棧指針。每個(gè)任務(wù)都有他自己的堆棧,用于在運(yùn)行過程中存儲(chǔ)臨時(shí)變量等一些環(huán)境參數(shù)// 在tinyOS運(yùn)行該任務(wù)前,會(huì)從stack指向的位置處,會(huì)讀取堆棧中的環(huán)境參數(shù)恢復(fù)到CPU寄存器中,然后開始運(yùn)行// 在切換至其它任務(wù)時(shí),會(huì)將當(dāng)前CPU寄存器值保存到堆棧中,等待下一次運(yùn)行該任務(wù)時(shí)再恢復(fù)。// stack保存了最后保存環(huán)境參數(shù)的地址位置,用于后續(xù)恢復(fù)uint32_t * stack;// 堆棧的起即地址uint32_t * stackBase;// 堆棧的總?cè)萘?/span>uint32_t stackSize;// 連接結(jié)點(diǎn)tNode linkNode;// 任務(wù)延時(shí)計(jì)數(shù)器uint32_t delayTicks;// 延時(shí)結(jié)點(diǎn):通過delayNode就可以將tTask放置到延時(shí)隊(duì)列中tNode delayNode;// 任務(wù)的優(yōu)先級(jí)uint32_t prio;// 任務(wù)當(dāng)前狀態(tài)uint32_t state;// 當(dāng)前剩余的時(shí)間片uint32_t slice;// 被掛起的次數(shù)uint32_t suspendCount;// 任務(wù)被刪除時(shí)調(diào)用的清理函數(shù)void (*clean) (void * param);// 傳遞給清理函數(shù)的參數(shù)void * cleanParam;// 請求刪除標(biāo)志,非0表示請求刪除uint8_t requestDeleteFlag;// 任務(wù)正在等待的事件類型struct _tEvent * waitEvent;// 等待事件的消息存儲(chǔ)位置void * eventMsg;// 等待事件的結(jié)果uint32_t waitEventResult;// 等待的事件方式uint32_t waitFlagsType;// 等待的事件標(biāo)志uint32_t eventFlags; }tTask;// 任務(wù)相關(guān)信息結(jié)構(gòu) typedef struct _tTaskInfo {// 任務(wù)延時(shí)計(jì)數(shù)器uint32_t delayTicks;// 任務(wù)的優(yōu)先級(jí)uint32_t prio;// 任務(wù)當(dāng)前狀態(tài)uint32_t state;// 當(dāng)前剩余的時(shí)間片uint32_t slice;// 被掛起的次數(shù)uint32_t suspendCount;// 堆棧的總?cè)萘?/span>uint32_t stackSize;// 堆棧空余量uint32_t stackFree; }tTaskInfo;任務(wù)初始化函數(shù)和任務(wù)查詢接口也需要修改如下:
/********************************************************************************************************** ** Function name : tTaskInit ** Descriptions : 初始化任務(wù)結(jié)構(gòu) ** parameters : task 要初始化的任務(wù)結(jié)構(gòu) ** parameters : entry 任務(wù)的入口函數(shù) ** parameters : param 傳遞給任務(wù)的運(yùn)行參數(shù) ** Returned value : 無 ***********************************************************************************************************/ void tTaskInit (tTask * task, void (*entry)(void *), void *param, uint32_t prio, uint32_t * stack, uint32_t size) {uint32_t * stackTop;// 為了簡化代碼,tinyOS無論是在啟動(dòng)時(shí)切換至第一個(gè)任務(wù),還是在運(yùn)行過程中在不同間任務(wù)切換// 所執(zhí)行的操作都是先保存當(dāng)前任務(wù)的運(yùn)行環(huán)境參數(shù)(CPU寄存器值)的堆棧中(如果已經(jīng)運(yùn)行運(yùn)行起來的話),然后再// 取出從下一個(gè)任務(wù)的堆棧中取出之前的運(yùn)行環(huán)境參數(shù),然后恢復(fù)到CPU寄存器// 對于切換至之前從沒有運(yùn)行過的任務(wù),我們?yōu)樗渲靡粋€(gè)“虛假的”保存現(xiàn)場,然后使用該現(xiàn)場恢復(fù)。task->stackBase = stack;task->stackSize = size;memset(stack, 0, size);// 注意以下兩點(diǎn):// 1、不需要用到的寄存器,直接填了寄存器號(hào),方便在IDE調(diào)試時(shí)查看效果;// 2、順序不能變,要結(jié)合PendSV_Handler以及CPU對異常的處理流程來理解stackTop = stack + size / sizeof(tTaskStack);*(--stackTop) = (unsigned long)(1<<24); // XPSR, 設(shè)置了Thumb模式,恢復(fù)到Thumb狀態(tài)而非ARM狀態(tài)運(yùn)行*(--stackTop) = (unsigned long)entry; // 程序的入口地址*(--stackTop) = (unsigned long)0x14; // R14(LR), 任務(wù)不會(huì)通過return xxx結(jié)束自己,所以未用*(--stackTop) = (unsigned long)0x12; // R12, 未用*(--stackTop) = (unsigned long)0x3; // R3, 未用*(--stackTop) = (unsigned long)0x2; // R2, 未用*(--stackTop) = (unsigned long)0x1; // R1, 未用*(--stackTop) = (unsigned long)param; // R0 = param, 傳給任務(wù)的入口函數(shù)*(--stackTop) = (unsigned long)0x11; // R11, 未用*(--stackTop) = (unsigned long)0x10; // R10, 未用*(--stackTop) = (unsigned long)0x9; // R9, 未用*(--stackTop) = (unsigned long)0x8; // R8, 未用*(--stackTop) = (unsigned long)0x7; // R7, 未用*(--stackTop) = (unsigned long)0x6; // R6, 未用*(--stackTop) = (unsigned long)0x5; // R5, 未用*(--stackTop) = (unsigned long)0x4; // R4, 未用task->slice = TINYOS_SLICE_MAX; // 初始化任務(wù)的時(shí)間片計(jì)數(shù)task->stack = stackTop; // 保存最終的值task->prio = prio; // 設(shè)置任務(wù)的優(yōu)先級(jí)task->state = TINYOS_TASK_STATE_RDY; // 設(shè)置任務(wù)為就緒狀態(tài)task->suspendCount = 0; // 初始掛起次數(shù)為0task->clean = (void(*)(void *))0; // 設(shè)置清理函數(shù)task->cleanParam = (void *)0; // 設(shè)置傳遞給清理函數(shù)的參數(shù)task->requestDeleteFlag = 0; // 請求刪除標(biāo)記task->waitEvent = (tEvent *)0; // 沒有等待事件task->eventMsg = (void *)0; // 沒有等待事件task->waitEventResult = tErrorNoError; // 沒有等待事件錯(cuò)誤tNodeInit(&(task->delayNode)); // 初始化延時(shí)結(jié)點(diǎn)tNodeInit(&(task->linkNode)); // 初始化鏈接結(jié)點(diǎn)tTaskSchedRdy(task); // 將任務(wù)插入就緒隊(duì)列 }/********************************************************************************************************** ** Function name : tTaskGetInfo ** Descriptions : 獲取任務(wù)相關(guān)信息 ** parameters : task 需要查詢的任務(wù) ** parameters : info 任務(wù)信息存儲(chǔ)結(jié)構(gòu) ** Returned value : 無 ***********************************************************************************************************/ void tTaskGetInfo (tTask * task, tTaskInfo * info) {uint32_t * stackEnd;// 進(jìn)入臨界區(qū)uint32_t status = tTaskEnterCritical();info->delayTicks = task->delayTicks; // 延時(shí)信息info->prio = task->prio; // 任務(wù)優(yōu)先級(jí)info->state = task->state; // 任務(wù)狀態(tài)info->slice = task->slice; // 剩余時(shí)間片info->suspendCount = task->suspendCount; // 被掛起的次數(shù)info->stackSize = task->stackSize;// 計(jì)算堆棧使用量info->stackFree = 0;stackEnd = task->stackBase;while ((*stackEnd++ == 0) && (stackEnd <= task->stackBase + task->stackSize / sizeof(tTaskStack))){info->stackFree++;}// 轉(zhuǎn)換成字節(jié)數(shù)info->stackFree *= sizeof(tTaskStack);// 退出臨界區(qū)tTaskExitCritical(status); }參考資料:
總結(jié)
- 上一篇: 固定资产清理账务处理增值税税率怎么算(固
- 下一篇: CPU使用百分比测量