電子產(chǎn)業(yè)一站式賦能平臺(tái)

PCB聯(lián)盟網(wǎng)

搜索
查看: 13|回復(fù): 0
收起左側(cè)

嵌入式代碼常見(jiàn)的容錯(cuò)設(shè)計(jì)

[復(fù)制鏈接]

459

主題

459

帖子

2319

積分

三級(jí)會(huì)員

Rank: 3Rank: 3

積分
2319
跳轉(zhuǎn)到指定樓層
樓主
發(fā)表于 2024-9-13 11:38:00 | 只看該作者 |只看大圖 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
關(guān)注+星標(biāo)公眾號(hào),不錯(cuò)過(guò)精彩內(nèi)容

作者 | strongerHuang
微信公眾號(hào) | strongerHuang
如果一個(gè)大型嵌入式項(xiàng)目,代碼沒(méi)有做容錯(cuò)設(shè)計(jì),你能想象后果是什么嗎?
有經(jīng)驗(yàn)的朋友肯定能想到,這樣的項(xiàng)目會(huì)有無(wú)數(shù)bug,而且有些bug很難查找。
今天就來(lái)聊聊嵌入式代碼常見(jiàn)的一些容錯(cuò)設(shè)計(jì)方法。
使用斷言(Assert)
什么是Assert斷言?這里舉一個(gè)栗子來(lái)說(shuō)明吧。

有這么一個(gè)數(shù)組和函數(shù):
  • int Array[5] = {0xA1, 0xB2, 0xC3, 0xD4, 0xE5};
    int Fun(char i){    return Array;}
    假如按下下面方式調(diào)用Fun函數(shù),你覺(jué)得會(huì)出錯(cuò)嗎?
  • int a;
    a = Fun(8);
    有經(jīng)驗(yàn)的朋友肯定都猜到了,在Fun函數(shù)中增加斷言(Assert)機(jī)制,就可以避免出錯(cuò)。

    斷言(Assert)是代碼中最常見(jiàn)的一種容錯(cuò)設(shè)計(jì),很多源碼庫(kù)都能看到斷言的身影,比如STM32外設(shè)庫(kù):
  • void GPIO_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));  /* ... */}
    明確返回值和錯(cuò)誤碼
    大家常用的協(xié)議棧、外設(shè)庫(kù)、操作系統(tǒng)等,它們的API大多設(shè)計(jì)的很完美,為函數(shù)設(shè)計(jì)合理的返回值,用于反饋操作的成功或失敗。例如,使用0表示成功,非0值表示特定的錯(cuò)誤代碼。

    比如RTOS創(chuàng)建任務(wù)函數(shù):
  • INT8U  OSTaskCreate (void   (*task)(void *p_arg),                     void    *p_arg,                     OS_STK  *ptos,                     INT8U    prio){    OS_STK     *psp;    INT8U       err;#if OS_CRITICAL_METHOD == 3u                 /* Allocate storage for CPU status register               */    OS_CPU_SR   cpu_sr = 0u;#endif
    #ifdef OS_SAFETY_CRITICAL_IEC61508    if (OSSafetyCriticalStartFlag == OS_TRUE) {        OS_SAFETY_CRITICAL_EXCEPTION();        return (OS_ERR_ILLEGAL_CREATE_RUN_TIME);    }#endif
    #if OS_ARG_CHK_EN > 0u    if (prio > OS_LOWEST_PRIO) {             /* Make sure priority is within allowable range           */        return (OS_ERR_PRIO_INVALID);    }#endif    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);    }    /* ... */}為函數(shù)設(shè)計(jì)合理的返回值和錯(cuò)誤碼,也會(huì)讓你的代碼更健壯,特別是找bug時(shí)更容易。
    日志記錄
    我們?yōu)槭裁匆涗浫罩?記錄詳?xì)的日志信息,包括錯(cuò)誤發(fā)生的時(shí)間、位置、原因等,以便在有bug出現(xiàn)時(shí)進(jìn)行追蹤和分析。
    我們學(xué)嵌入式之初,基本都會(huì)學(xué)習(xí) printf 這種打印輸出的功能,這種打印對(duì)應(yīng)的另一種功能就是日志記錄。

    除了存儲(chǔ)在本地的日志之外,也可以使用 printf 打印輸出至另外終端(比如上位機(jī))進(jìn)行存儲(chǔ)日志。

    致命Bug重啟策略
    我們軟件遇到一些致命的bug時(shí),比如硬件故障(HardFault)、內(nèi)存溢出(MemManage)等,這個(gè)時(shí)候可以選擇重啟策略。

    當(dāng)然,重啟也要根據(jù)項(xiàng)目實(shí)際情況,選擇什么方式重啟,比如:內(nèi)核復(fù)位、系統(tǒng)復(fù)位。

    1. 內(nèi)核復(fù)位
    只復(fù)位Cortex-M內(nèi)核,不會(huì)復(fù)位UART這些片內(nèi)外設(shè)。

    在Cortex-M內(nèi)核文檔中大概有這樣的描述:通過(guò)設(shè)置 NVIC 中應(yīng)用程序中斷與復(fù)位控制寄存器(AIRCR)的VECTRESET 位,可只復(fù)位處理器內(nèi)核而不復(fù)位其它片上設(shè)施。
    內(nèi)核復(fù)位函數(shù)(參考內(nèi)核代碼修改而來(lái)):
  • void NVIC_CoreReset(void){  __DSB();  SCB->AIRCR  = ((0x5FA                  (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |                 SCB_AIRCR_VECTRESET_Msk);       //置位 VECTRESET  __DSB();  while(1) { __NOP(); }}
    2. 系統(tǒng)復(fù)位
    軟件復(fù)位中的系統(tǒng)復(fù)位操作的寄存器位(SYSRESETREQ)不同,復(fù)位的對(duì)象為整個(gè)芯片(除后備區(qū)域)。

    系統(tǒng)復(fù)位函數(shù):
  • void NVIC_SysReset(void){  __DSB();  SCB->AIRCR  = ((0x5FA                  (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |                  SCB_AIRCR_SYSRESETREQ_Msk);     //置位 SYSRESETREQ  __DSB();  while(1) { __NOP(); }}
    靜態(tài)分析工具
    使用靜態(tài)分析工具檢查代碼中的潛在問(wèn)題,如未初始化的變量、內(nèi)存泄漏、緩沖區(qū)溢出等。這些工具可以在編譯前發(fā)現(xiàn)許多問(wèn)題,從而提高代碼質(zhì)量。

    雖然這算不上容錯(cuò)設(shè)計(jì),但這也是開(kāi)發(fā)過(guò)程中重要的一個(gè)環(huán)節(jié),其作用在一定程度上超過(guò)常規(guī)的容錯(cuò)設(shè)計(jì)。

    這里推薦閱讀:嵌入式開(kāi)發(fā)常用的代碼靜態(tài)分析工具
    最后,代碼bug千千萬(wàn),除了常規(guī)的容錯(cuò)設(shè)計(jì),代碼規(guī)范其實(shí)也很重要。
    最最后,你們平時(shí)寫(xiě)代碼,有考慮哪些容錯(cuò)設(shè)計(jì),歡迎留言評(píng)論。
    猜你喜歡:
    WiFi6+藍(lán)牙+星閃,三合一開(kāi)發(fā)板,真香!
    Github上熱門(mén) C 語(yǔ)言項(xiàng)目匯總!
    嵌入式,可測(cè)試性軟件設(shè)計(jì)!
    一些低功耗軟件設(shè)計(jì)的要點(diǎn)!
    嵌入式 C 保護(hù)結(jié)構(gòu)體的方式
    實(shí)用 | 10分鐘教你通過(guò)網(wǎng)頁(yè)點(diǎn)燈
    談?wù)勄度胧杰浖募嫒菪裕?/strong>
  • 發(fā)表回復(fù)

    本版積分規(guī)則


    聯(lián)系客服 關(guān)注微信 下載APP 返回頂部 返回列表