一.引言
MCX A 系列是 NXP 提供的一種新的微控制器(MCU)型號,專為各種嵌入式應用而設計。該系列的重點在於增強的安全性、能效及性能表現,以滿足現代智能設備日益增長的需求。CDOG(Code Watchdog Timer)是MCX A 系列中的一個重要模組,用於監控程式執行流程的完整性,以確保軟體在預期範圍內運行。
CDOG 模組主要用於需要高安全性和穩定性的嵌入式應用,如工業控制系統、智慧家居設備和自動駕駛汽車等。其典型應用場景包括:
1.程式碼監控:透過設置指令計時器和安全計數器,CDOG 能夠在程式執行的各個關鍵節點進行檢查,確保執行流程的正確性。
2.錯誤管理:CDOG 的錯誤檢測和中斷機制有助於及時發現和處理潛在的安全威脅和系統異常,提升系統的可靠性。
3.開發與調試:在軟體開發階段,CDOG 可以設置為在錯誤發生時觸發中斷而非系統重置,這有助於開發者快速調試和優化程式。
4.安全防護:在應用中,CDOG 可設定不同類型的錯誤處理策略(如中斷或重置),提供靈活的錯誤應對措施,提高系統安全性。
二.技術原理介紹
CDOG 模組的主要功能是透過檢測程式碼執行流程中的意外變化(如錯誤)來保護軟體的完整性。它可以配置為在檢測到錯誤時重置或中斷處理器核心。CDOG 提供了兩種主要的錯誤檢測機制: Secure Counter 和 Instruction Timer 。
1.Secure Counter:這是一個32位元的記數器,用於動態儲存一個值,並能夠透過定期檢查 (CDOG_Check) 來確定程式是否按照預期執行。如果檢測到數值不匹配,則產生 MISCOMPARE 錯誤。
2.Instructon Timer:這是一個32位元的倒數計時器,用於設定預計執行的指令數目。若計時器在 CDOG 被呼叫前計數歸零,則產生 Timeout 錯誤。
CDOG 可以生成各種錯誤類型,如 TIMEOUT 錯誤、MISCOMPARE錯誤、SEQUENCE 錯誤、CONTROL 錯誤、STATE 錯誤和 ADDRESS 錯誤。每種錯誤類型都有一個相關的 Flag 和計數器,用於錯誤處理和統計分析。
三.工具準備、環境設定
以下為筆者使用環境
1.IDE:MCUXpresso 11.9.1
2.SDK:2.14.2
3.NXP 開發板:FRDM-MCXA153
四.範例程式介紹、功能展示
1.說明 SDK Example
選擇 MCXA 153 開發板
程式開始時先透過 CDOG_GetDefaultConfig 取得預設配置參數
修改預設配置方式
conf.timeout = kCDOG_FaultCtrl_EnableInterrupt; conf.miscompare = kCDOG_FaultCtrl_EnableInterrupt; conf.sequence = kCDOG_FaultCtrl_EnableInterrupt; conf.state = kCDOG_FaultCtrl_EnableInterrupt; conf.address = kCDOG_FaultCtrl_EnableInterrupt; conf.irq_pause = kCDOG_IrqPauseCtrl_Pause; //當中斷發生時 timer 暫停執行 conf.debug_halt = kCDOG_DebugHaltCtrl_Pause; // 當 DEBUG_HALT 狀態下 timer 暫停執行 conf.lock = kCDOG_LockCtrl_Unlock; //不鎖 COUNTROL 暫存器,鎖住狀態下直到系統重啟,CONTROL 暫存器無法讀寫
|
CDOG 提供以下 exception handler
Fault 名稱 |
產生原因 |
SEQUENCE |
1. 在 Start Command 發生前並未寫入 RELOAD 暫存器 2. 當在 Active 狀態下寫入 RELOAD 暫存器,僅可在 CDOG 為 IDLE 狀態下修改 3. 當在 Active 狀態下寫入 START 暫存器,僅可在 CDOG 為 IDLE 狀態下修改 4. 軟體嘗試對 COMMAND 群組的暫存器進行寫入操作,但不包括 START 暫存器。在 IDLE 狀態下,COMMAND 群組的暫存器應只有 START 暫存器是允許被寫入的 5. 在 Active 狀態試圖對 COMMAND 寫入操作 |
ADDRESS |
試圖讀/寫CONTROL 暫存器之外的地址 |
TIMEOUT |
下數計時器到達0 |
MISCOMPARE |
1. 寫入 STOP 暫存器時與 Secure Counter 數值不相等 2. 寫入 RESTART 暫存器中與 Secure Counter 數值不相等 3. 寫入 ASSERT16 暫存器中與 Secure Counter 低 16 位元數值不相等 |
CONTROL |
CONTROL 暫存器參數配置錯誤 |
STATE |
狀態機數值錯誤,僅可 0x5(IDLE) 或 0xA(ACTIVE) |
當錯誤發生時可選擇配置為進入中斷(kCDOG_FaultCtrl_EnableInterrupt) 、進行重啟(kCDOG_FaultCtrl_EnableReset)或者不動作(kCDOG_FaultCtrl_NoAction)
配置 secure counter 數值,並在後去透過 CDOG_Add、CDOG_Sub、CDOG_Add1 加減 secure counter 值,透過 CDOG_Check 確認 secure counter 數值與預期是否相符,再函示最後刻意在檢查時給予一個與 secure counter 不相同的數值,觸發 MISCOMPARE fault
void SecureCounterExample() { uint32_t reload = 0xFFFFFFU;
/* Sets start value for secure counter and reload value for instruction timer, */ /* which changes CDOG status to active */ CDOG_Start(CDOG, reload, s_start);
s_start += 42U; /* Add 42 to secure counter */ CDOG_Add(CDOG, s_start);
/* Check if secure counter have value is 42 */ CDOG_Check(CDOG, s_start);
s_start -= 2U; /* Substract 2 from secure counter */ CDOG_Sub(CDOG, 2U);
/* Check if secure counter have value 40 */ CDOG_Check(CDOG, s_start);
s_start++; /* Add 1 to secure counter */ CDOG_Add1(CDOG);
/* Check if secure counter have value 41, and stops CDOG */ CDOG_Stop(CDOG, s_start);
/* Start CDOG again with new secure counter value */ CDOG_Start(CDOG, reload, 0U);
/* Check if secure counter have value 0 */ CDOG_Check(CDOG, 0U);
/* Check if secure counter have value 1, which should trigger FAULT */ CDOG_Check(CDOG, 1U); }
|
while ((CDOG->STATUS & CDOG_STATUS_NUMTOF_MASK) <= 0x0U) { PRINTF("intruction timer:%08x\r\n", CDOG->INSTRUCTION_TIMER); }
|
透過 CDOG_Stop 停止 CDOG timer,使用者可透過 CDOG_Start 配置 instruction timer 數值。
下圖為本次 SDK Example 範例執行結果
2.修改 SDK Example
以下透過修改 SDK Example 以期讓讀者更加了解 CDOG 用途,在 CDOG_AppIRQHandler 前新增 Flag
char timerFlag = 0; |
在 timerout 中新增 flag 設定
PRINTF("* Timeout fault occured *\r\n\r\n"); timerFlag = 1;
|
在 main 前新增 function ,這用於假設有個功能需要執行,當執行完成後在 secure counter 記數加 1
void function(void){ //do something what you need CDOG_Add1(CDOG); } |
在main 中調整後段,移除 CDOG_Deinit 並新增 function。
// CDOG_Deinit(CDOG);
PRINTF("End of example\r\n"); /* End of example */
PRINTF("Customer Example\r\n"); int expectCount = 5; timerFlag = 0; CDOG_Start(CDOG, 0xFFFFFFU, 0U);
function(); function(); function(); function(); function();
CDOG_Check(CDOG, expectCount);
while (1) { if(timerFlag){ CDOG_Stop(CDOG, s_start); CDOG_Deinit(CDOG); } }
|
到此修改完畢,讀者可以看到執行結果似乎跟 example 相同
但讀者可以修改 function 數量或者修改中的 expectCount 數量,觀察會發生什麼,有助於讀者理解 CDOG 用途
五.參考文件
l.MCX A153, A152,A143, A142 Reference Manual Rev. 4,
參考來源