學完本章你將能夠:

  • 替關鍵任務做心跳,用獨立看門狗復位「沉默的死亡」。

  • 分清 HardFault、assert、業務 FAULT,並留下復位原因。

  • 在閒置時進入 Stop 模式,用 RTC 或 EXTI(含 UART/麥檢測)喚醒。

  • 說明雙槽(A/B)OTA 的最小可靠流程,並完成 UART 模擬升級。

實驗室 demo 與產品的差距,通常不在辨識率,而在「半夜死機沒人按重置」 「電池兩天就沒電」「升級磚機」。本章把這三件事做到最小可用。

分層的失敗

失敗要上報到哪一層
層級 例子與動作
可恢復 I2C NACK 一次:重試,三次才 |EVT_FAULT|
降級 麥克風 DMA 失敗:關語音,設備仍可用按鍵/UART
安全態 未知嚴重錯誤:|dev_all_off| + 故障 LED
復位 心跳停止、IWDG 逾時:整系統重來,並記錄原因

|configASSERT| 在開發期應開啟。進產線可改成記錄後復位,但不要變成 空巨集——靜默略過不變量會讓現場無法除錯。

獨立看門狗

IWDG 掛 LSI,逾時公式見參考手冊。建議 2 s。Monitor 任務每 200 ms 檢查:

void vTaskMonitor(void *arg) (void)arg; for (;;) if (heartbeat_all_fresh(pdMS_TO_TICKS(1500)) && (xEventGroupGetBits(g_evt) & EVT_FAULT) == 0) HAL_IWDG_Refresh(&hiwdg); vTaskDelay(pdMS_TO_TICKS(200));

CubeMX 打開 IWDG 後,若你停在斷點超過逾時,板子會自己復位——除錯時 可先不啟動 IWDG,或調長逾時。不要用軟體定時器無條件 Refresh。

復位後讀 |RCC->CSR| 的 IWDG RST 旗標,UART 印 boot reason: iwdg,再清除旗標。這是現場維修的第一句話。

HardFault 最小處理

在 |HardFault_Handler| 裡不要 printf(可能已壞)。可點亮紅 LED、 寫 RTC backup register 一個魔術數,然後 |NVIC_SystemReset()|。 開發期用 debugger 看堆疊裡的 PC,對照 .map。

低功耗

語音產品多數時間在 Idle。策略:

  1. 無 |EVT_LISTEN|、無通訊排程、無 OTA 時,允許睡眠。

  2. Idle Hook 或專用任務呼叫 |HAL_PWR_EnterSTOPMode|。

  3. 喚醒源:使用者按鍵 EXTI、RTC 週期(更新感測)、UART RX(模組 喚醒碼)、或 I2S DMA(路徑 B 通常不能深睡,可改 Standby 只留 模組供電)。

  4. 離開 Stop 後必須重新設定時鐘(Cube 的 |HAL_PWR_EnterSTOPMode| 範例有 |SystemClock_Config|)。

路徑 A 更適合低功耗:外部模組可自行做低功耗聆聽,STM32 睡死,模組拉 一根 WAKE 腳。這是選模組時的重要規格。

OTA 最小可靠集

磚機通常發生在「只擦了自己還在跑的那塊 Flash」。雙槽規則:

  1. Slot A 跑目前版本;映像寫入 Slot B。

  2. 寫完算 CRC32/SHA-256,與標頭核對。

  3. 標記 B 為 pending,復位。Bootloader 跳 B。

  4. 新韌體在 30 s 內回報 healthy(餵狗 + 特定旗標),再把 B 標為 valid。否則下次開機回 A。

課堂用 UART YMODEM 或自訂 1 KB 封包把測試映像寫進 Bank B(F429 雙 Bank Flash 正好適合)。完整安全啟動(簽章)超出時數,但標頭應預留 簽名欄位,避免日後格式不相容。

typedef struct uint32_t magic; /* ’VHOM’ */ uint32_t version; uint32_t size; uint32_t crc32; uint32_t flags; /* pending / valid */ ota_hdr_t;

OTA 期間關閉語音與繼電器輸出。升級到一半掉電靠雙槽與 CRC,不靠祈禱。 課堂禁止對 ST-LINK 所在 Bank 做晶片全面抹除的「假 OTA」。

最終專案驗收

firmware/lab11_watchdog_lpm_ota/ 示範 IWDG、睡眠與 UART 假升級(寫 backup register 當版本號)。 firmware/voice_home_final/ 是課程總成:任務表、指令表、 遙測、心跳、安全關斷全部打開。

展示當天請準備 3 分鐘口頭說明:架構圖、一條指令的資料路徑、一次你修過 的 bug。評分建議:硬體穩定 20%、RTOS 正確性 25%、語音體驗 25%、 產品化機制 20%、程式可讀與抽象 10%。

故意在 Device 任務寫空的忙碌迴圈卡死,證實 IWDG 復位且 boot reason 正確。再做一次「升級成功但 CRC 錯」應回退的演練(可只改 flag)。最後 量 Idle 與 Stop 的電流,把數字寫進報告——沒有數字的低功耗等於沒做。

你走到哪了

從時鐘樹到看門狗,學員已經走完一條接近量產的嵌入式 AI 路徑。接下來 可以換更好的麥克風陣列、加聲源定位、把模型換成 ST 最新的 NPU 系列, 或把 MQTT 接到真正的家用 Hub。骨架不必重寫——這正是本課程把 cmd_msg_t 與 dev_* 守得那麼死的原因。下一章立刻 驗證這件事:同一台裝置,原封不動交給 Siri、Alexa 與 OK Google。