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