在嵌入式MCU軟件開發過程中,通常我們需要先通過調試器(Debugger, 帶程序下載(Flash/EEPROM擦除、編程和校驗)功能)或者仿真器(Simulator,不帶目標MCU編程功能)對所寫代碼的功能進行在線調試(online- debug),驗證確認其功能符號設計需求后,在發布編程文件--S19/HEX/BIN給生成部門通過離線編程器(Offline/Stand-alone Flash Programmer)進行批量編程。批量(Mass Production,簡稱MP)的產品正常工作時是不需要/也不能連接調試器或者仿真器的(一方面,調試器和仿真器價格高昂,成本不允許,另一方面,無法滿足系統設計的產品重量和空間要求),因此,我們開發的嵌入式MCU應用軟件/程序必須保證其在拔掉調試器和編程器或仿真器后依然能夠功能運行正常,即離線工作(Offline,也稱作脫機工作)正常。
在實際工作中,大家常常會遇到,開發階段在線調試工作正常的代碼,離線工作時卻無法正常工作,這是為什么呢?
本文就基于NXP的汽車級MCU(S32K1xx/KEA, S12(X), MaginiV S12Z和Qorivva MPC56/57xx系列)為例,給大家介紹這類問題的可能原因和具體解決辦法,希望對大家有所幫助。
1.應用工程的編譯目標為debug_RAM,將代碼編譯鏈接到SARM而非Flash
在嵌入式MCU的軟件開發集成環境(IDE)中創建應用工程時,通常都會創建至少兩個編譯目標(build target)和調試目標(debug target),使用不同的連接文件,將編譯結果分別編譯鏈接到SRAM和Flash中。
比如,在NXP的S32DS IDE中,創建S32K1xx系列MCU的應用工程時,就會自動創建Debug、Debug_RAM和Release三個編譯目標,其差異和用途如下:
Tips:a. 由于S32DS是基于GNU的工具鏈,編譯器(gcc)優化這一塊目前還不是很完善,建議量產時還是使用Debug的編譯目標,以保證編譯結果能夠正常運行;
b. 編譯目標中工具鏈的調試信息等級(debug level)配置,只影響elf文件中包含調試信息的多少,不會影響最終生成的編程文件(S19/HEX/BIN)大小,因為編程文件中不包含任何調試信息;
c.一個S32DS工程可以有多個編譯目標,用戶可以通過工程屬性創建、配置不同的編譯目標實現應用工程的個性化編譯;
因此,若選擇使用Debug_RAM作為在線調試時的編譯目標,并通過Debug_RAM調試目標下載,則編譯結果未被下載到Flash中,因此,拔掉調試器,無法正常工作。
解決辦法:切換應用工程的編譯目標和調試目標為debug/release,將應用程序編譯鏈接并下載到掉電不丟失的Flash中。
2.啟動代碼(startup code)未對使用的SRAM進行ECC初始化
為了保證嵌入式MCU應用程序的正常運行,提高系統的抗干擾能力,越來越多的MCU在其存儲器中加入了單比特自動糾錯,多比特檢錯的ECC功能。
對于此類MCU,由于調試器的下載腳本(在線調試時會被自動調用和執行)會對其SRAM進行初始化,若應用工程的啟動代碼(startup code)未對其SRAM進行就去訪問(讀)SRAM,則會導致ECC錯誤,從而進入內核異常:
- ARM CM0+/CM4F 內核的HardFault異常;
- S12Z內核的Machine Check異常;
- PowerPC e200系列內核的IVOR1異常);
Tips:通常若MCU的SRAM帶有ECC功能,在新建應用工程的啟動代碼中都會添加相應的ECC初始化代碼,比如S32K1xx系列MCU的startup啟動流程如下,在startup的第③步即對SRAM進行了初始化:
Notes:需要注意的是,對RAM初始化時使用的起始地址和長度信息來自應用工程的鏈接文件定義,若在SRAM size小的MCU part number(比如S32K144, SRAM為60KB,起始地址為:0x1FFF_8000 ~ 0x2000_6FFF)的應用工程上移植SRAM size大的MCU part number(比如S32K146, SRAM為120KB,起始地址為:0x1FFF_0000 ~ 0x2000_EFFF)應用程序,若不替換使用相應part number MCU的鏈接文件,則會出現SRAM ECC未初始化即使的情況。
解決辦法:Double check應用工程的啟動代碼(startup codes),確保CPU內核在訪問(讀取)SRAM之前有對其使用的全部地址空間進行了ECC初始化。
3.FlexNVM(EEE--Emulated EEPROM)分區失敗
在NXP的S12XE系列MCU和S32K1xx系列MCU中都使用了EEE(Emulated EEPROM, 硬件狀態機模擬EEPROM),在訪問之前,必須對其進行分區(partion), 而能夠成功分區的前提是EEE所使用的D-Flash/FlexNVM和分區信息儲存區域(FIR)為擦除狀態。在CodeWarrior和S32DS IDE的下載腳本中,通常都會有相應的擦除命令(erase all block或者mass erase)完成這些操作,從而在線調試時,其分區一定能夠成功,而量產時,沒有調試器連接下載的過程,若在應用程序中未做相應的容錯處理,在EEE分區失敗的情況下,繼續使用EEE,則會到MCU工作異常。
Tips:關于NXP的S12XE系列MCU和S32K1xx系列MCU的EEE使用,請參考如下應用筆記和公眾號文章(點擊文章標題即可直接跳轉閱讀):
- AN11983, Using the S32K1xx EEPROM Functionality (REV 2):
https://www.nxp.com/docs/en/application-note/AN11983.pdf
- AN3490, Overview of the MC9S12XE Emulated EEPROM - Application Notes (REV 0):
https://www.nxp.com/docs/en/application-note/AN3490.pdf
- AN3743, Emulated EEPROM Quick Start Guide - Application Notes (REV 0):
解決辦法:在對此類MCU的EEE分區之前讀取分區信息,判斷是否已經分區,避免重復分區,添加容錯處理代碼,分區不成功時,不使用EEE,具體實現可參考以上應用筆記和公眾號文章。
4.RAM初始化時未關閉看門狗,導致看門狗超時復位
為了保證MCU應用程序能夠被正常下載并進行在線調試,在MCU的調試器下載腳本或者Flash算法文件中,會將目標MCU的片上看門狗(watchdog)關閉,以避免編程過程中,擦除和編程Flash所用時間過長導致看門狗超時異常復位。
離線工作時,這些下載腳本和Flash算法將不會被執行,若應用工程的啟動代碼(startup code)在進行RAM初始化(.data段和.bss段初始化)之前未關閉片上看門狗,而且應用工程中使用的全局變量又比較多的情況下,就極容易出現看門狗超時復位,從而無法正常執行應用程序。
解決辦法:Double check應用工程的啟動代碼(startup codes),確保在進行RAM初始化之前,MCU的片上看門狗已經被關閉(disabled)。
5.內部參考時鐘(IRC)沒有校準(trim),導致系統和外設時鐘誤差過大
通常為了降低系統成本和提高時鐘的穩定性,在嵌入式MCU中都集成了一定數量的內部參考時鐘(IRC-Internal Reference Clock)。但是,有工藝設計的限制,這些IRC時鐘源的頻率誤差都比較大,必須經過校準(trim)才能夠提高MCU datasheet中所規范的時鐘精度。
在MCU的調試器下載腳本或者Flash算法中,往往會提供MCU片內IRC trim的功能,從而保證,在線調試時,MCU能夠使用比較穩定的IRC參考時鐘。若在MCU的啟動代碼中缺少IRC trim的功能代碼,則會導致脫機運行時,依賴IRC時鐘的內核和外設模塊工作異常。
解決辦法:若使用IRC時鐘作為參考時鐘的外設模塊對時鐘精度要求比較高,請務必在應用工程的啟動代碼中添加IRC時鐘的trim代碼。
6.bootloader跳轉導致APP程序啟動或者時鐘、外設初始化失敗
在帶有bootloader功能的嵌入式MCU產品(比如汽車ECU)開發中,bootloader也是一個完整的應用工程,它也會對目標MCU的系統時鐘和外設模塊(至少bootloader獲取更新firmware需要的通信外設模塊(比如CAN或者UAR)T和定時器(比如看門狗或者用于通信超時的timeout硬件定時器模塊)以及GPIO模塊)進行初始化,這些時鐘資源和外設模塊,若在跳轉在應用程序(APP)之前未復位,則會影響APP功能代碼再次初始化系統時鐘和外設模塊,從而導致產品功能異常。
APP工程單獨下載在線調試時,不存在bootloader的影響,因此工作正常,而加入bootloader后,則必須考慮以上影響。
解決辦法:在bootloader初始化MCU系統時鐘和外設模塊之前(越早越好,可能的話在bootloader的復位函數中通過匯編指令實現最好),就讀取并判斷APP更新狀態,跳轉到APP。若有APP更新需求,在運行bootloader功能代碼完成APP firmware更新之后,通過看門狗或者軟件復位重新運行bootloader再跳轉,而不是更新完成后立即跳轉到APP。
7.使用調試器的半主機(semi-host)模式重定向printf()到debug console輸出調試信息
通過調試器的半主機(semi-host)模式重定向printf()到debug console輸出調試信息,從而可以調用printf()函數格式化打印調試信息,將在線調試時關心的寄存器和變量數據等輸出到debug console,從而提高調試效率。
這種方法可以避免對MCU外設資源的占用,但是斷開調試器,離線運行時,由于缺少debug_console的半主機模式響應,printf()將無法正常運行,從而影響應用程序正常工作。
解決辦法:在離線工作時,移除應用程序中使用printf()的相關代碼即可。也可以通過宏定義將printf()定義為空函數。
8.外設模塊凍結模式配置影響其功能配置失敗
除了以上列出的可能原因,為了在線調試時的減少CPU內核的中斷或者方便量產時產生生產,嵌入式MCU的很多外設模塊和存儲器控制器有凍結模式(Freeze mode,也就是調試模式)控制位,從而可能會導致外設模塊在調試模式和離線工作的正常模式下功能有所差異。
解決辦法:double check使用MCU的芯片參考手冊,確認相關外設模塊的凍結模式控制位配置正確,不允許其離線工作。
總結
本文以NXP的汽車級MCU(S32K1xx/KEA, S12(X), MaginiV S12Z和Qorivva MPC56/57xx系列)為例,給大家介紹MCU在線調試正常,但離線工作異常這類問題的可能原因和相應的解決辦法。
評論
查看更多