關(guān)于stm32 HardFault_Handler 異常的處理 死機(jī)
一般來(lái)說(shuō)運(yùn)行操作系統(tǒng) 是以下幾個(gè)問(wèn)題
1.開始的時(shí)候給ucos分配的堆棧太小了,隨著項(xiàng)目做多了,這類問(wèn)題一般很容易解決
#define TASK_IO_SIZE 300
#define TASK_IO_PRIO 6
OS_STK TASK_IO_STK[TASK_IO_SIZE];
比如修改300到 1000,做開發(fā)的時(shí)候 如果ram允許,盡量大些,免的麻煩
2.數(shù)組溢出
這類問(wèn)題一般在通信中,接受數(shù)據(jù)的時(shí)候,特別是長(zhǎng)度不定的時(shí)候
比如協(xié)議為 :開始 功能碼 長(zhǎng)度 數(shù)據(jù)1 數(shù)據(jù)2 。。結(jié)束
長(zhǎng)度決定了后面的數(shù)據(jù)多少,在分配接受緩沖的時(shí)候 ,突然來(lái)了個(gè)錯(cuò)誤的長(zhǎng)度比如255
但是我們分配buffer[100],只定義了100,這樣數(shù)組就溢出了
所有在放數(shù)據(jù)之前要對(duì)長(zhǎng)度進(jìn)行判斷是否合理,以后 如果有長(zhǎng)度 或者索引就要想到溢出。。
3.使用了非法的指針 ,比如空指針 ,編譯對(duì)的但是運(yùn)行就錯(cuò)了
u8 *p = null;
*p = 1; 把0地址的數(shù)據(jù)強(qiáng)制設(shè)置為1, 不錯(cuò)才怪
4.使用 OS_ENTER_CRITICAL();
使用了 OS_ENTER_CRITICAL(); 卻忘了OS_EXIT_CRITICAL(); 退出臨界區(qū)
特別是在這個(gè)函數(shù)OS_ENTER_CRITICAL(); 調(diào)用了子函數(shù)也有的這類情況,很容易忘記關(guān)閉的這樣就造成了“死機(jī)現(xiàn)象”
因此如果調(diào)用的話 建議在函數(shù)中加入OS_CPU_SR cpu_sr = 0u;局部變量 在管理臨界區(qū) os的內(nèi)核程序也是這么用的 ,而且要注意,臨界區(qū)一般用于全局變量的寫操作,時(shí)間要非??斓?,任務(wù)中的變量可以不用添加。
常見的就上面幾種了,說(shuō)說(shuō)硬件異常了 怎么來(lái)發(fā)現(xiàn),這個(gè)才是主要的
舉個(gè)例子:
a.仿真,運(yùn)行程序的時(shí)候點(diǎn)紅色X進(jìn)入異常
b.調(diào)出堆棧窗口,也就是黑匣子
c.查找問(wèn)題
d.找出出錯(cuò)的函數(shù)
e.解決問(wèn)題
f 一些思考
很久之前在研究stm32 庫(kù)源碼的時(shí)候 發(fā)現(xiàn)基本上 每個(gè)函數(shù)進(jìn)入之前都做了參數(shù)的檢測(cè),當(dāng)初還覺得檢查不檢查貌似沒什么大的作用,自己使用的時(shí)候注意就好了,現(xiàn)在是不是改變看法了嗎?編程的時(shí)候很多問(wèn)題,在參數(shù)檢查的時(shí)候被過(guò)濾掉了,這樣在開發(fā)大型項(xiàng)目的時(shí)候,可以給您免去很多不必要的麻煩,反而會(huì)提供開發(fā)效率哦
當(dāng)然網(wǎng)上也有很多,檢查寄存器LR SP等地址 來(lái)反推出最后運(yùn)行的匯編函數(shù)調(diào)用地址的,但是肯定沒有上面的直觀。
評(píng)論