1、問題:
在移植、使用安富萊的FreeRTOS堆棧溢出檢測例程的過程中,出現(xiàn)如下情況
串口數(shù)據(jù)并沒有打印完成,直接進(jìn)入了硬件報(bào)錯(cuò)。同時(shí)在仿真過程中,溢出檢測的vApplicationStackOverflowHook也沒有進(jìn)入。
2、解決方案:
通過修改vTaskDelay(1);改成vTaskDelay(10);之后,串口數(shù)據(jù)會全部打印,并且進(jìn)入vApplicationStackOverflowHook。
/*
*********************************************************************************************************
* 函 數(shù) 名: StackOverflowTest
* 功能說明: 任務(wù)棧溢出測試
* 形 參: 無
* 返 回 值: 無
*********************************************************************************************************
*/
static void StackOverflowTest(void)
{
int16_t i;
uint8_t buf[2048];
(void)buf; /* 防止警告 */
/*
1. 為了能夠模擬任務(wù)棧溢出,并觸發(fā)任務(wù)棧溢出函數(shù),這里強(qiáng)烈建議使用數(shù)組的時(shí)候逆著賦值。
因?yàn)閷τ贛3和M4內(nèi)核的MCU,堆棧生長方向是向下生長的滿棧。即高地址是buf[2047], 低地址
是buf[0]。如果任務(wù)棧溢出了,也是從高地址buf[2047]到buf[0]的某個(gè)地址開始溢出。
因此,如果用戶直接修改的是buf[0]開始的數(shù)據(jù)且這些溢出部分的數(shù)據(jù)比較重要,會直接導(dǎo)致
進(jìn)入到硬件異常。
2. 棧溢出檢測是在任務(wù)切換的時(shí)候執(zhí)行的,我們這里加個(gè)延遲函數(shù),防止修改了重要的數(shù)據(jù)導(dǎo)致直接
進(jìn)入硬件異常。
3. 任務(wù)vTaskTaskUserIF的棧空間大小是2048字節(jié),在此任務(wù)的入口已經(jīng)申請了棧空間大小
------uint8_t ucKeyCode;
------uint8_t pcWriteBuffer[500];
這里再申請如下這么大的棧空間
-------int16_t i;
-------uint8_t buf[2048];
必定溢出。
*/
for(i = 2047; i >= 0; i--)
{
buf[i] = 0x55;
vTaskDelay(10);
}
}
修改之后的結(jié)果:
3、原因分析
在一開始的串口打印過程中,因?yàn)檠訒r(shí)不夠,沒有將所有的數(shù)據(jù)打印出來,同時(shí),因?yàn)檠訒r(shí)時(shí)間太少,導(dǎo)致在進(jìn)入空閑線程之后,串口數(shù)據(jù)未打印未完成,并且產(chǎn)生溢出中斷,導(dǎo)致直接進(jìn)入硬件報(bào)錯(cuò)。