STM32cubemx:version5.1ui
Chip: STM32F446REspa
IDE:Keil5code
Q:小項目上寫了個簡單的通訊包,波特率230400,數據量較大1600Byte/s,DMA的方式實現接收,量產後發現跑久了部分機器會有隻能發送不能接收的問題。blog
查了好久沒查到。中間加了斷線檢測,從新初始化串口,卻沒法解決。最後面發現,HAL的鍋。ip
部分代碼:io
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == UART4) { uint8_t ret=HAL_OK; if(frame_in_sync) { if(UART_Rx_Buffer.head == 0x55 && UART_Rx_Buffer.end == 0xAA) { // TODO: check check-sum UART_Rx_Data = UART_Rx_Buffer; ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer)); uart_updata_time= HAL_GetTick(); } else { // frame not in sync, drop coming bytes until read an end(0xAA) frame_in_sync = 0; ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1); } } else { if( *(uint8_t *)&UART_Rx_Buffer == 0xAA) { frame_in_sync = 1; ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer)); } else { ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1); } } } }
上述的代碼絕大多數時間都可以正常運行。可是,總會出現莫名奇妙的掉線問題。而且難以複線。查了很久,看到有相似的問題,HAL庫會不處理異常的行爲,要用戶處理。event
在某些狀況下,HAL_UART_Receive_IT 並無成功執行,返回了busy 或者erro,這時候整個流程就背打斷了。而且串口還會被莫名其妙鎖上。function
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == UART4) { uint8_t ret=HAL_OK; if(frame_in_sync) { if(UART_Rx_Buffer.head == 0x55 && UART_Rx_Buffer.end == 0xAA) { // TODO: check check-sum UART_Rx_Data = UART_Rx_Buffer; ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer)); uart_updata_time= HAL_GetTick(); } else { // frame not in sync, drop coming bytes until read an end(0xAA) frame_in_sync = 0; ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1); } } else { if( *(uint8_t *)&UART_Rx_Buffer == 0xAA) { frame_in_sync = 1; ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, sizeof(UART_Rx_Buffer)); } else { ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1); } } while(ret!=HAL_OK){ /*try to fix connection bug 20191225*/ printf("UART4:RECEIVE_IT:%d\r\n",ret); //for log huart->RxState = HAL_UART_STATE_READY; __HAL_UNLOCK(huart); ret=HAL_UART_Receive_IT(&huart4, (uint8_t *)&UART_Rx_Buffer, 1); } } } void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ if(huart->ErrorCode&HAL_UART_ERROR_ORE) { __HAL_UART_CLEAR_OREFLAG(huart); } /* NOTE : This function should not be modified, when the callback is needed, the HAL_UART_ErrorCallback can be implemented in the user file. */ }
修改後,出現busy或者erro時強制解鎖,從新接收。根據log,大約半小時會出現一次。三臺常常性出現的機子更新後運行一天,沒有出現這個問題。在log中查看到了對應的修正過程。class