記一次stm8l程序跑飛
阿新 • • 發佈:2018-12-19
return 開始 else if val 取出 按鍵 clas etc 解決辦法
項目使用stm8l051f3做主控,CC2500做數據接收,不發送。
跑飛的現象就是,剛開始能運行,經過一段未知長度的時間,有可能是3分鐘,有可能是30分鐘,指示燈不再閃爍,中斷按鍵單片機無反應。
接入調試器發現跑到了一個非常大的地址,已經超過了mcu的內部flash空間。可以確定是程序跑飛。
經驗是:
程序跑飛,查條件語句是否都有做處理。
程序跑飛,查內存溢出。
查了好久,查出是內存溢出導致。
因為發送端發送的數據固定是32字節,所以在接收端只開辟了一個32字節的buffer去讀取收到的數據。
/*******************************************************************************
* @brief GDO2中斷處理函
* @param None
* @retval None ****************************************************************Author:Liming**/ void GDO2_Int(void) { uint8_t temp; unsigned char RecvBuffer[0x20]={0};//開辟32字節緩存 unsigned char RecvLength; if(EXTI_GetITStatus(EXTI_IT_Pin6) != RESET) { EXTI_ClearITPendingBit(EXTI_IT_Pin6); DelayNms(1);//等待接收完成 RecvLength = CC2500Recv(RecvBuffer); //獲取收到的數據長度 temp = ProPacketCheck(RecvBuffer,RecvLength,0x0001,0x0003);//數據完整性校驗 if((temp == 0x04)||(temp==0xff)) // 本機和廣播信息需要處理 {
//數據處理
CC2500SetState(CC2500_STATUS_POWERDOWN_LEVEL2); }else CC2500SetState(CC2500_STATUS_RECEIVE); } }
//接收數據 unsigned char CC2500Recv(unsigned char *Buffer,unsigned char Mode) { unsigned char Result=0x00,Status=0x00; switch(CC2500State) { case 0x00: case 0x01: if(CC2500State) Delayms(0x07); else Delayus(0x30); Status=CC2500SpiReadStatus(RXBYTES); if(Status&0x80)//如果數據長度超過64字節 { CC2500SpiReadBuffer(FIFO,Buffer,0x40);//讀取64字節 Result=0x40; } else if(Status&0x7F) { CC2500SpiReadBuffer(FIFO,Buffer,Status&0x7F);//讀取收到的數據 Result=Status&0x7F; } CC2500SetState(Mode); break; } return Result;//返回讀取的數據長度 }
但由於無線信號的幹擾,CC2500可能會收到大於32字節的數據(雖然不是本系統需要的),
導致在從cc2500取出的時候,存入buffer的長度超過開辟的buffer空間。
解決辦法1:既然知道是32字節數據,可以在
CC2500Recv接收函數裏只接收32字節。
if(Status&0x80)//如果數據長度超過64字節
{
CC2500SpiReadBuffer(FIFO,Buffer,0x20);//讀取32字節
Result=0x20;
}
else if(Status&0x7F)
{
CC2500SpiReadBuffer(FIFO,Buffer,0x20);//讀取收到的數據
Result=0x20;
}
解決辦法2:
GDO2_Int函數裏開辟64字節空間即便是收到最多的數據也不會超出緩存空間。
unsigned char RecvBuffer[0x40]={0};//開辟64字節緩存
有了這次的程序跑飛的處理經歷,再次驗證了程序跑飛大部分都是內存溢出導致的說法。
記一次stm8l程序跑飛