試與OTA部署)
1. 項目緣起一次看似簡單的固件升級最近在折騰一塊基于瑞芯微RV1126芯片的開發(fā)板核心任務(wù)是給它升級固件。這聽起來是個常規(guī)操作對吧無非就是找個燒錄工具選好鏡像點一下“升級”按鈕。但實際情況是從準(zhǔn)備鏡像、選擇升級模式到處理升級過程中的各種“幺蛾子”每一步都可能藏著坑。RV1126作為一款面向視覺AI應(yīng)用的SoC其固件升級流程相比一些簡單的MCU要復(fù)雜得多它涉及到Bootloader、分區(qū)表、內(nèi)核、文件系統(tǒng)等多個層面的協(xié)同工作。我這次的目標(biāo)不僅僅是把新固件刷進(jìn)去更是要徹底搞清楚整個升級鏈路的來龍去脈以及當(dāng)升級失敗時如何通過有限的調(diào)試手段比如串口快速定位問題。如果你也在玩RV1126、RK3568或者其他Rockchip平臺的設(shè)備并且對“燒寫鏡像”、“OTA升級”、“串口調(diào)試”這些關(guān)鍵詞感到既熟悉又頭疼那么我踩過的這些坑和總結(jié)的經(jīng)驗或許能幫你省下不少折騰的時間。2. 升級前的“戰(zhàn)備”工作工具與環(huán)境梳理在動手升級之前把工具和環(huán)境理順了能避免至少一半的莫名其妙的問題。很多人一上來就急著連板子、開軟件結(jié)果卡在第一步。2.1 核心工具三件套燒寫、調(diào)試與鏡像對于Rockchip平臺尤其是RV1126下面這三個工具是你的必備武器RKDevTool / Upgrade Tool這是瑞芯微官方的燒錄工具。不同芯片型號、不同版本的工具可能存在兼容性問題。一個常見的坑是你從某個論壇下載的“通用版”工具可能根本不識別你的RV1126板子。我的經(jīng)驗是優(yōu)先從板卡供應(yīng)商或方案商那里獲取配套的工具。如果找不到可以去Rockchip的官方Wiki或開發(fā)者社區(qū)尋找對應(yīng)芯片型號的專用版本。工具界面通常有“Loader”和“Maskrom”兩種燒錄模式這個我們后面會詳細(xì)講。串口調(diào)試助手這是你的“眼睛”和“嘴巴”。在升級過程中尤其是當(dāng)系統(tǒng)無法正常啟動時串口是獲取Bootloader和內(nèi)核日志的唯一通道。sscom、xcom、putty、minicom都可以。關(guān)鍵參數(shù)就三個波特率RV1126通常為1500000、數(shù)據(jù)位8、停止位1、無校驗。這里有個細(xì)節(jié)一定要確保串口線的驅(qū)動正確安裝并且在設(shè)備管理器中確認(rèn)了正確的COM口號。我遇到過無數(shù)次因為COM口選錯導(dǎo)致看著一片空白的終端發(fā)呆的情況。固件鏡像文件通常是一個.img文件或者由多個分區(qū)鏡像打包而成的update.img。你需要確認(rèn)這個鏡像是否與你的硬件版本如DDR型號、PMIC配置完全匹配。用不匹配的鏡像輕則功能異常重則直接“變磚”。在拿到鏡像后可以嘗試用7zip或binwalk工具簡單查看一下內(nèi)部結(jié)構(gòu)確認(rèn)它包含boot.img、rootfs.img等關(guān)鍵分區(qū)。2.2 系統(tǒng)環(huán)境與驅(qū)動確認(rèn)如果你的工作機(jī)是Windows那么DriverAssitant驅(qū)動助手這個工具必須安裝。它包含了Rockchip芯片進(jìn)入升級模式Maskrom或Loader時所需的USB驅(qū)動。安裝后最好在設(shè)備管理器中手動檢查一下當(dāng)板子進(jìn)入升級模式并連接USB后是否會正確識別為“Rockchip USB Device”或類似的設(shè)備。如果是Linux環(huán)境進(jìn)行升級則需要配置udev規(guī)則讓普通用戶也能訪問USB設(shè)備并且使用rkdeveloptool等命令行工具進(jìn)行操作。這部分的坑在于權(quán)限和工具鏈的版本匹配。注意在連接板子之前先打開串口調(diào)試助手并設(shè)置好參數(shù)然后再給板子上電。這樣你才能捕獲到最完整的啟動日志從Bootloader的第一行輸出開始看起。這是判斷板子狀態(tài)的第一手資料。3. 深入RV1126的升級模式Loader與Maskrom的區(qū)別這是理解Rockchip平臺升級的關(guān)鍵。很多升級失敗根源就在于模式?jīng)]選對。3.1 Loader模式常態(tài)化的升級入口當(dāng)RV1126板子里的Bootloader通常是U-Boot正常運行時并且這個U-Boot支持rockusb或rkusb命令時就可以進(jìn)入Loader模式。如何進(jìn)入通常有兩種方式在串口終端中在U-Boot的倒計時階段按下任意鍵打斷自動啟動然后輸入命令rkusb或rockusb。板子上可能有專門的“升級鍵”Recovery鍵在板上電瞬間按住此鍵U-Boot會檢測到并自動進(jìn)入Loader模式。表現(xiàn)進(jìn)入Loader模式后串口可能會輸出Enter rockusb mode之類的提示同時Windows電腦會識別到一個新的USB設(shè)備。此時在RKDevTool中設(shè)備列表會顯示為一個“發(fā)現(xiàn)一個LOADER設(shè)備”。特點Loader模式依賴于板載Bootloader的正常工作。如果Bootloader本身損壞了這個模式就進(jìn)不去了。3.2 Maskrom模式救磚的終極手段Maskrom是芯片內(nèi)部固化的一段只讀啟動代碼。當(dāng)系統(tǒng)檢測不到任何有效的可啟動設(shè)備如eMMC、SPI Flash為空或損壞時或者通過特殊引腳強(qiáng)制觸發(fā)時芯片會自動 fallback 到 Maskrom 模式。如何進(jìn)入這是重點也是硬件操作。短路Flash找到板載eMMC或SPI Flash芯片的數(shù)據(jù)引腳通常是D0或CLK在上電瞬間將其與地GND短接。這模擬了Flash無法識別的狀態(tài)迫使芯片進(jìn)入Maskrom。這是最通用的方法但需要一定的硬件動手能力并要查詢你板子的原理圖。專用測試點有些開發(fā)板會設(shè)計一個標(biāo)記為“Maskrom”或“M”的測試點將其在上電瞬間與地短接即可。按鍵組合極少數(shù)板子可能有通過按住多個按鍵上電的方式觸發(fā)。表現(xiàn)進(jìn)入Maskrom模式后芯片會等待主機(jī)通過USB發(fā)送下載指令。在RKDevTool中設(shè)備會顯示為“發(fā)現(xiàn)一個MASKROM設(shè)備”。特點這是最底層的模式不依賴任何外部存儲器的代碼。只要芯片本身沒壞就能通過Maskrom模式重新燒寫B(tài)ootloader從而實現(xiàn)“救磚”。3.3 模式選擇與實戰(zhàn)策略理解了這兩種模式你的升級策略就清晰了常規(guī)升級板子能正常啟動到U-Boot或系統(tǒng) - 優(yōu)先嘗試進(jìn)入Loader模式進(jìn)行升級。這種方式最安全、最方便。救磚/首次燒錄板子無法啟動、Flash為空、或升級中途失敗導(dǎo)致Bootloader損壞 - 必須使用Maskrom模式。我遇到的一個典型場景是在Loader模式下升級中途因為USB線松動或電源波動導(dǎo)致升級中斷結(jié)果Bootloader被寫壞了一半。此時板子既無法正常啟動也無法再次進(jìn)入Loader模式。唯一的辦法就是拆開機(jī)殼找到Flash引腳用鑷子短接進(jìn)入Maskrom模式重新燒寫完整的固件。4. 固件鏡像的構(gòu)成與燒寫流程拆解知道怎么連接板子了我們再來看看要燒寫的“固件”到底是什么。一個完整的RV1126升級鏡像通常不是單一文件而是一個遵循特定格式的包。4.1 標(biāo)準(zhǔn)update.img的解析使用RKDevTool燒寫時我們常選擇一個update.img文件。這個文件其實是一個容器里面打包了多個分區(qū)鏡像和一份分區(qū)表信息。你可以使用Rockchip提供的afptool和img_unpack工具對其進(jìn)行解包# 假設(shè)在Linux環(huán)境下 ./afptool -unpack update.img update/ ./img_unpack update.img rockimg/解包后你可能會看到如下關(guān)鍵組件parameter.txt分區(qū)表文件。這是升級的“地圖”定義了eMMC上各個分區(qū)如bootrootfsuserdata的起始位置、大小和名稱。升級前務(wù)必確認(rèn)此分區(qū)表與板子原有分區(qū)布局兼容否則可能導(dǎo)致數(shù)據(jù)錯亂。boot.img包含內(nèi)核kernel.img和設(shè)備樹resource.img或dtb等。負(fù)責(zé)啟動Linux系統(tǒng)。rootfs.img根文件系統(tǒng)包含了操作系統(tǒng)的基礎(chǔ)命令、庫和你的應(yīng)用程序。misc.img用于OTA升級時傳遞狀態(tài)信息的分區(qū)。userdata.img用戶數(shù)據(jù)分區(qū)。4.2 RKDevTool燒寫步驟詳解在RKDevTool中燒寫流程是這樣的工具讀取update.img中的parameter.txt。根據(jù)分區(qū)表將boot.img、rootfs.img等逐個通過USB傳輸?shù)桨宥说腂ootloaderLoader模式或Maskrom。Bootloader/Maskrom程序?qū)⑦@些鏡像寫入eMMC對應(yīng)的物理地址。這里有一個至關(guān)重要的選項“擦除Flash”和“擦除IDB”。擦除Flash會清空整個存儲設(shè)備eMMC的所有數(shù)據(jù)。相當(dāng)于格式化整個硬盤。擦除IDBIDB是存儲在Flash前幾個塊的信息塊包含了Bootloader和分區(qū)表信息。擦除IDB會破壞Bootloader和分區(qū)表。實操心得首次燒錄或徹底重刷可以勾選“擦除Flash”確保一個干凈的狀態(tài)。常規(guī)升級千萬不要勾選“擦除Flash”特別是你的userdata分區(qū)里有重要數(shù)據(jù)時。標(biāo)準(zhǔn)的升級流程只會覆蓋boot、rootfs等系統(tǒng)分區(qū)保留userdata分區(qū)。RKDevTool在加載update.img后通常默認(rèn)只勾選需要更新的分區(qū)如bootrootfs這是安全的。“擦除IDB”要慎用只有在分區(qū)表損壞或需要徹底更換Bootloader類型如從舊版U-Boot換成新版時才使用。誤操作會導(dǎo)致板子無法啟動必須進(jìn)Maskrom。4.3 命令行燒寫更底層的控制在Linux主機(jī)上你可以使用rkdeveloptool進(jìn)行更靈活的燒寫。這對于自動化腳本或深入了解流程非常有幫助。# 1. 查看連接的設(shè)備 rkdeveloptool ld # 輸出示例DevNo1 Vid0x2207,Pid0x350b,LocationID106 Maskrom # 2. 下載并運行Loader用于Maskrom模式初始化 rkdeveloptool db rkbin/RK1126_Loader.bin # 3. 燒寫整個update.img rkdeveloptool wl 0 update.img # 4. 或者分別燒寫各個分區(qū)更靈活 rkdeveloptool ppt # 查看分區(qū)信息 rkdeveloptool wl boot boot.img rkdeveloptool wl rootfs rootfs.img命令行工具讓你對每個步驟都有清晰的控制當(dāng)圖形化工具出錯時命令行輸出的錯誤信息往往更直接。5. 串口調(diào)試當(dāng)升級出錯時你的診斷利器升級過程很少一帆風(fēng)順。當(dāng)RKDevTool卡住、報錯或者燒寫成功后板子依然無法啟動時串口調(diào)試終端就是你的救命稻草。你需要學(xué)會解讀這些日志。5.1 Bootloader啟動日志分析上電后串口最先輸出的是BootloaderU-Boot的信息。健康的日志鏈?zhǔn)沁@樣的U-Boot 2017.09 (Mar 01 2023 - 10:00:00 0800) Model: Rockchip RV1126 Evaluation Board DRAM: 1 GiB MMC: dwmmcffc50000: 1, dwmmcffc60000: 0 In: serial Out: serial Err: serial ... Hit any key to stop autoboot: 3如果在這里就卡住了比如DRAM初始化失敗那可能是DDR配置不對鏡像與板子硬件不匹配或者板子硬件有問題。5.2 內(nèi)核啟動日志與常見故障Bootloader之后會將控制權(quán)交給內(nèi)核。內(nèi)核啟動日志非常詳細(xì)能暴露大部分問題[ 0.000000] Booting Linux on physical CPU 0x0 [ 0.000000] Linux version 4.19.111 (buildserver) ... [ 0.000000] Machine model: Rockchip RV1126 Evaluation Board ... [ 1.234567] dwmmc_ffc50000: voltage-ranges unspecified [ 1.234568] dwmmc_ffc50000: 1, dwmmc_ffc60000: 0 [ 1.567890] mmc0: new high speed SDHC card at address aaaa [ 1.567891] mmcblk0: mmc0:aaaa SL32G 29.7 GiB ... [ 2.345678] VFS: Mounted root (ext4 filesystem) on device 179:2. [ 2.345679] devtmpfs: mounted [ 2.456789] Freeing unused kernel memory: 1024K [ 2.456790] Run /sbin/init as init process常見錯誤及排查方向卡在Starting kernel ...之后沒有任何輸出最可能的原因設(shè)備樹dtb錯誤。Bootloader加載了錯誤的內(nèi)核或設(shè)備樹文件導(dǎo)致內(nèi)核無法識別硬件而崩潰。解決方法檢查boot.img中的設(shè)備樹是否與你的板型完全匹配。回退到已知正常的舊版本鏡像進(jìn)行對比。內(nèi)核恐慌Kernel Panic[ 3.000000] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)原因內(nèi)核找不到根文件系統(tǒng)。可能是rootfs鏡像損壞、分區(qū)表錯誤導(dǎo)致根文件系統(tǒng)分區(qū)位置不對、或者內(nèi)核缺少對應(yīng)的文件系統(tǒng)驅(qū)動如ext4。排查首先確認(rèn)parameter.txt中rootfs分區(qū)的名稱和編號是否正確。在U-Boot中使用mmc part或part list mmc 0命令查看實際分區(qū)表。確認(rèn)內(nèi)核配置包含了對應(yīng)的文件系統(tǒng)支持。MMC/SD卡初始化失敗[ 1.500000] dwmmc_ffc50000: error -110 whilst initialising MMC card原因存儲設(shè)備初始化失敗。可能是eMMC芯片虛焊、損壞或者內(nèi)核驅(qū)動中的時序配置如dwmmc節(jié)點的clock-frequency與硬件不匹配。排查檢查硬件連接。對比正常板子的內(nèi)核設(shè)備樹中MMC控制器的配置。5.3 文件系統(tǒng)掛載失敗與Init進(jìn)程問題即使內(nèi)核啟動成功也可能在掛載根文件系統(tǒng)或啟動第一個用戶進(jìn)程init時失敗。[ 2.500000] List of all partitions: [ 2.500001] ... (分區(qū)列表正常) ... [ 2.500002] VFS: Cannot open root device mmcblk0p5 or unknown-block(0,0): error -6 [ 2.500003] Please append a correct root boot option; here are the available partitions: ...這明確指出了根設(shè)備mmcblk0p5無法打開。你需要檢查U-Boot的bootargs環(huán)境變量中root參數(shù)指定的設(shè)備是否正確例如root/dev/mmcblk0p5。對應(yīng)的分區(qū)這里是第5分區(qū)是否存在且包含有效的文件系統(tǒng)鏡像。如果掛載成功但最后卡在Run /sbin/init as init process然后沒有下文通常是根文件系統(tǒng)里的/sbin/init鏈接通常指向systemd或busybox損壞或者文件系統(tǒng)本身不完整。這通常意味著rootfs.img在制作或燒寫過程中出了問題。6. OTA升級遠(yuǎn)程部署的關(guān)鍵機(jī)制對于量產(chǎn)設(shè)備我們不可能每次都拆機(jī)短接用USB升級。OTAOver-The-Air升級是必須的。RV1126的OTA升級核心是recovery系統(tǒng)。6.1 Recovery系統(tǒng)與A/B分區(qū)一種常見的OTA方案是使用recovery分區(qū)。當(dāng)系統(tǒng)需要升級時會重啟進(jìn)入recovery分區(qū)一個精簡的Linux系統(tǒng)由recovery來完成對主系統(tǒng)分區(qū)boot,system,vendor等的更新。 Rockchip也支持A/B分區(qū)無縫更新方案即有兩套完整的系統(tǒng)分區(qū)A槽和B槽當(dāng)前運行A槽后臺更新B槽下次啟動時從B槽啟動。這需要Bootloader如U-Boot和系統(tǒng)Android Things或某些Linux發(fā)行版的支持。6.2 制作OTA升級包OTA升級包ota_update.zip或update.zip不同于完整的update.img。它通常是一個差分包或全量包只包含需要更新的分區(qū)鏡像并附帶一個升級腳本updater-script用于Android兼容的recovery或自定義的更新邏輯。 制作OTA包通常需要使用SDK中的編譯腳本例如build.sh或mkupdate.sh它會根據(jù)版本差異生成對應(yīng)的包。6.3 OTA升級流程與調(diào)試下載設(shè)備從服務(wù)器下載OTA升級包到緩存分區(qū)如cache或數(shù)據(jù)分區(qū)。驗證驗證包的簽名和完整性防止被篡改。進(jìn)入Recovery系統(tǒng)重啟Bootloader根據(jù)升級標(biāo)志常存儲在misc分區(qū)決定啟動到recovery系統(tǒng)。安裝更新recovery系統(tǒng)解壓升級包根據(jù)腳本擦寫對應(yīng)的系統(tǒng)分區(qū)。重啟更新完成后清除升級標(biāo)志重啟進(jìn)入主系統(tǒng)。調(diào)試OTA的難點在于更新過程發(fā)生在recovery里而recovery的串口日志可能和主系統(tǒng)不同或者根本沒有輸出。你需要確保recovery鏡像本身包含了串口驅(qū)動和輸出功能。在recovery的初始化腳本如init.rc中確保console被正確設(shè)置到串口。仔細(xì)檢查升級腳本的邏輯確保分區(qū)掛載、文件拷貝、權(quán)限設(shè)置的每一步都正確。我遇到過一個典型的OTA失敗案例升級包制作時文件路徑使用了絕對路徑/system/bin/app但recovery環(huán)境下/system可能并未掛載導(dǎo)致文件拷貝失敗。正確的做法是在腳本中先掛載system分區(qū)到某個臨時目錄如/tmp/system再進(jìn)行操作。7. 進(jìn)階排查當(dāng)基礎(chǔ)手段都失效時如果串口沒有任何輸出或者輸出亂碼問題就更底層了。7.1 串口無輸出排查硬件連接TX/RX線是否接反串口板如USB轉(zhuǎn)TTL的電壓是否是3.3VRV1126通常是3.3V電平地線是否接好波特率嘗試最常見的1500000也試試115200。有些Bootloader早期階段可能用低速波特率。Bootloader損壞如果完全無輸出且確認(rèn)串口硬件和設(shè)置無誤那很可能是Bootloader代碼區(qū)域IDB完全損壞。此時必須嘗試Maskrom模式。7.2 使用示波器或邏輯分析儀對于更棘手的啟動問題比如DDR無法初始化軟件日志無能為力。這時需要硬件工具。測量時鐘和電源用示波器檢查核心電壓如VDD_LOGIC、DDR電壓是否穩(wěn)定且在正確范圍內(nèi)。檢查主晶振是否起振。抓取eMMC引腳波形在啟動瞬間用邏輯分析儀抓取eMMC的CLK和CMD線波形看Bootloader是否在嘗試讀取Flash。如果沒有讀寫活動說明芯片可能沒跑起來或者BootROMMaskrom在更早階段就失敗了。7.3 利用TrustZone調(diào)試輸出如果有RV1126的Arm Cortex-A7核心通常運行在非安全世界Linux而安全世界TrustZone可能運行著OP-TEE等安全OS。有些調(diào)試信息可能會輸出到安全世界的UART上而這個UART可能和Linux使用的不是同一個物理串口。如果你的板子有多個UART接口可以嘗試連接其他UART引腳看看是否有不同的輸出。這需要查閱芯片的TRM技術(shù)參考手冊和板子的原理圖。整個RV1126的升級調(diào)試是一個從軟件到硬件、從上層應(yīng)用到底層硬件的全鏈路認(rèn)知過程。最深刻的體會就是日志是你的第一線索理解流程是你分析線索的地圖而硬件操作如Maskrom是你最后的保障。每次升級前做好備份確認(rèn)鏡像匹配理解你每一步操作的意義這樣才能在遇到問題時從容不迫一步步縮小范圍最終找到那個搗鬼的“小妖精”。