關注+星標公眾號,不錯過精彩內容
作者 | strongerHuang
使用斷言(Assert)
什么是Assert斷言?這里舉一個栗子來說明吧。
int Array[5] = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5};intFun(char i){return Array[i];}
int a;
a = Fun(8);有經驗的朋友肯定都猜到了,在Fun函數中增加斷言(Assert)機制,就可以避免出錯。
斷言(Assert)是代碼中最常見的一種容錯設計,很多源碼庫都能看到斷言的身影,比如STM32外設庫:
voidGPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct){/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));/* ... */}
明確返回值和錯誤碼
大家常用的協議棧、外設庫、操作系統等,它們的API大多設計的很完美,為函數設計合理的返回值,用于反饋操作的成功或失敗。例如,使用0表示成功,非0值表示特定的錯誤代碼。
比如RTOS創建任務函數:
INT8U OSTaskCreate(void (*task)(void *p_arg),void *p_arg,OS_STK *ptos,INT8U prio){OS_STK *psp;INT8U err;OS_CPU_SR cpu_sr = 0u;if (OSSafetyCriticalStartFlag == OS_TRUE) {OS_SAFETY_CRITICAL_EXCEPTION();return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);}if (prio > OS_LOWEST_PRIO) { /* Make sure priority is within allowable range */return (OS_ERR_PRIO_INVALID);}OS_ENTER_CRITICAL();if (OSIntNesting > 0u) { /* Make sure we don't create the task from within an ISR */OS_EXIT_CRITICAL();return (OS_ERR_TASK_CREATE_ISR);}/* ... */}
為函數設計合理的返回值和錯誤碼,也會讓你的代碼更健壯,特別是找bug時更容易。
日志記錄
我們為什么要記錄日志?記錄詳細的日志信息,包括錯誤發生的時間、位置、原因等,以便在有bug出現時進行追蹤和分析。
我們學嵌入式之初,基本都會學習 printf 這種打印輸出的功能,這種打印對應的另一種功能就是日志記錄。
除了存儲在本地的日志之外,也可以使用 printf 打印輸出至另外終端(比如上位機)進行存儲日志。

致命Bug重啟策略
我們軟件遇到一些致命的bug時,比如硬件故障(HardFault)、內存溢出(MemManage)等,這個時候可以選擇重啟策略。
當然,重啟也要根據項目實際情況,選擇什么方式重啟,比如:內核復位、系統復位。
1. 內核復位
只復位Cortex-M內核,不會復位UART這些片內外設。
在Cortex-M內核文檔中大概有這樣的描述:通過設置 NVIC 中應用程序中斷與復位控制寄存器(AIRCR)的VECTRESET 位,可只復位處理器內核而不復位其它片上設施。
內核復位函數(參考內核代碼修改而來):
voidNVIC_CoreReset(void){__DSB();SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |SCB_AIRCR_VECTRESET_Msk); //置位 VECTRESET__DSB();while(1) { __NOP(); }}
2. 系統復位
軟件復位中的系統復位操作的寄存器位(SYSRESETREQ)不同,復位的對象為整個芯片(除后備區域)。
系統復位函數:
voidNVIC_SysReset(void){__DSB();SCB->AIRCR = ((0x5FA << SCB_AIRCR_VECTKEY_Pos) |(SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |SCB_AIRCR_SYSRESETREQ_Msk); //置位 SYSRESETREQ__DSB();while(1) { __NOP(); }}
靜態分析工具
使用靜態分析工具檢查代碼中的潛在問題,如未初始化的變量、內存泄漏、緩沖區溢出等。這些工具可以在編譯前發現許多問題,從而提高代碼質量。
雖然這算不上容錯設計,但這也是開發過程中重要的一個環節,其作用在一定程度上超過常規的容錯設計。
這里推薦閱讀:嵌入式開發常用的代碼靜態分析工具
