在ARM嵌入式開發(fā)中,U-Boot作為“啟動(dòng)第一站”,其向內(nèi)核/可信固件(ATF/TOS)傳遞的參數(shù)是否正確,直接決定了后續(xù)系統(tǒng)能否正常啟動(dòng)。瑞芯微(Rockchip)平臺(tái)下的atags.c,正是調(diào)試這類參數(shù)問題的“金鑰匙”——它不僅是ATAGS參數(shù)的解析器,更是嵌入式工程師定位啟動(dòng)故障的核心工具。
本文將結(jié)合實(shí)際開發(fā)板的atags命令輸出,從atags.c的核心邏輯出發(fā),拆解其功能、調(diào)試價(jià)值,并結(jié)合實(shí)戰(zhàn)場景講解如何利用該模塊快速解決ARM啟動(dòng)類問題。

一、ATAGS是什么?atags.c又做了什么?
基礎(chǔ):ATAGS(ARM Tags)是ARM架構(gòu)下U-Boot與內(nèi)核/下級固件的“參數(shù)橋梁”,類比x86的SMBIOS,負(fù)責(zé)傳遞硬件配置、內(nèi)存分區(qū)、啟動(dòng)設(shè)備等關(guān)鍵信息。
瑞芯微定制的atags.c,則是這套“橋梁”的“可視化調(diào)試工具”,核心實(shí)現(xiàn)3項(xiàng)功能,結(jié)合實(shí)際開發(fā)板輸出可更直觀理解:
1.結(jié)構(gòu)化解析+打印所有ATAGS參數(shù)
遍歷ATAGS_PHYS_BASE(實(shí)際開發(fā)板為0x001fe000)物理內(nèi)存區(qū)域,解析瑞芯微定制的所有ATAG類型(除常見的串口、DDR內(nèi)存、TOS/ATF內(nèi)存等,還包含core、pstore、boot1 param等特有Tag),并輸出每個(gè)參數(shù)的具體值(如實(shí)際串口波特率1500000、DDR 3個(gè)有效bank地址等)。
核心函數(shù):atags_print_all_tags()(遍歷所有Tag)+atags_print_tag()(按Tag類型打印字段),實(shí)際開發(fā)板執(zhí)行atags命令后,會(huì)依次輸出core、serial、ddr_mem等10類Tag的完整參數(shù)。
2.統(tǒng)計(jì)ATAGS內(nèi)存使用狀態(tài)
計(jì)算ATAGS區(qū)域的總大小、已用大小、可用大小,判斷是否存在內(nèi)存溢出(參數(shù)寫入越界)。結(jié)合實(shí)際開發(fā)板輸出,其ATAGS區(qū)域地址范圍為0x001fe000 ~ 0x00200000,總大小0x00002000(8KB),已用僅0x000003e0,可用空間充足,無溢出風(fēng)險(xiǎn)。
核心函數(shù):atags_stat()——通過累加每個(gè)Tag的占用字節(jié)(t->hdr.size << 2),輸出內(nèi)存使用占比,實(shí)際輸出中“in use size”“available size”可直接判斷內(nèi)存狀態(tài)。
3.暴露U-Boot命令行調(diào)試接口
通過U_BOOT_CMD注冊atags命令,開發(fā)者無需修改代碼、無需重新編譯,在U-Boot命令行輸入atags即可觸發(fā)上述解析和統(tǒng)計(jì),是“無侵入式調(diào)試”的關(guān)鍵。實(shí)際開發(fā)板的所有ATAGS參數(shù),均通過這一條命令直接獲取,無需額外調(diào)試操作。
核心邏輯:do_dump_atags()綁定命令執(zhí)行邏輯,一行命令就能拿到全量參數(shù)+內(nèi)存狀態(tài),下文所有實(shí)戰(zhàn)分析均基于開發(fā)板真實(shí)atags輸出。
二、為什么atags.c是調(diào)試“剛需”?
ARM平臺(tái)啟動(dòng)故障80%以上與U-Boot傳遞的參數(shù)不匹配有關(guān),而atags.c正是定位這類問題的“終極武器”。以下是高頻調(diào)試場景及對應(yīng)的價(jià)值:
|
調(diào)試場景
|
用atags.c能解決什么問題?(結(jié)合實(shí)際板卡)
|
|
內(nèi)核啟動(dòng)失敗
|
驗(yàn)證core(核心參數(shù))、ddr_mem(內(nèi)存)、rootdev(根設(shè)備)是否正確,實(shí)際板卡core的rootdev為0x0,需核對內(nèi)核配置;
|
|
TOS/ATF啟動(dòng)異常
|
查看atf_mem(ATF內(nèi)存,實(shí)際phy_addr=0x0,size=0x100000)、tos_mem(TEE/DRM內(nèi)存)是否地址沖突/配置異常;
|
|
串口調(diào)試亂碼/無輸出
|
核對serial Tag:波特率1500000、物理地址0xfeb50000、使能0x1,確認(rèn)與內(nèi)核串口配置一致;
|
|
啟動(dòng)設(shè)備識別錯(cuò)誤(EMMC→SD)
|
定位bootdev Tag:devtype=0x2、devnum=0x0,對照瑞芯微手冊判斷設(shè)備類型是否匹配;
|
|
ATAGS參數(shù)丟失/溢出
|
通過實(shí)際ATAGS state判斷:已用0x3e0 總大小0x2000,無溢出,若參數(shù)丟失可排查Tag寫入邏輯;
|
|
固件版本/簽名異常
|
驗(yàn)證fwver Tag:DDR、SPL、BL31、BL32固件版本明確,可核對是否為目標(biāo)版本;
|
|
自定義參數(shù)生效驗(yàn)證
|
新增/修改RAM分區(qū)、boot1參數(shù)后,可通過ddr_mem、boot1 param Tag快速驗(yàn)證寫入成功;
|
|
pstore存儲(chǔ)異常
|
查看pstore Tag的table參數(shù),實(shí)際板卡前5項(xiàng)均為0x8000@0x110000,可驗(yàn)證持久化存儲(chǔ)配置;
|
三、實(shí)戰(zhàn):用atags命令解決4類高頻問題(基于真實(shí)板卡輸出)
以下結(jié)合實(shí)際開發(fā)板的真實(shí)atags輸出,講解4類高頻啟動(dòng)問題的定位方法,所有操作均基于板卡實(shí)際參數(shù),可直接套用。
場景1:內(nèi)核啟動(dòng)后內(nèi)存識別錯(cuò)誤
操作步驟:
1.在U-Boot命令行執(zhí)行atags,找到[ddr_mem]段:
[ddr_mem]:magic = 0x54410052size = 0xc0count = 0x3version = 0x0bank[0] = 0x0bank[1] = 0x100000000bank[2] = 0x2f0000000bank[3] = 0xf0000000bank[4] = 0x100000000bank[5] = 0x10000000bank[6] = 0x0bank[7] = 0x0bank[8] = 0x0bank[9] = 0x0bank[10] = 0x0bank[11] = 0x0bank[12] = 0x0bank[13] = 0x0bank[14] = 0x0bank[15] = 0x0bank[16] = 0x0bank[17] = 0x0bank[18] = 0x0bank[19] = 0x0flags = 0x2data[0] = 0x0data[1] = 0x0hash = 0xb713be00
1.對比內(nèi)核設(shè)備樹(DTS)中的內(nèi)存配置,重點(diǎn)關(guān)注2點(diǎn):
?板卡count=0x3,說明有3個(gè)有效DDR bank,實(shí)際有效地址為bank[1](0x100000000)、bank[2](0x2f0000000)、bank[5](0x10000000),若DTS中內(nèi)存地址/數(shù)量與這些值不一致→修正U-Boot的DDR初始化邏輯,重新生成ATAGS參數(shù);
?flags=0x2,需對照瑞芯微rk_atags.h中flags的宏定義,確認(rèn)DDR工作模式是否符合預(yù)期,模式錯(cuò)誤也會(huì)導(dǎo)致內(nèi)存識別失敗。
場景2:內(nèi)核串口亂碼(U-Boot串口正常)
操作步驟:
1.執(zhí)行atags找到[serial]段:
[serial]:magic = 0x54410050size = 0x30version = 0x0enable = 0x1addr = 0xfeb50000baudrate = 1500000m_mode = 0x0id = 0x2res[0] = 0x0res[1] = 0x0hash = 0xf968b524
1.排查方向:
?波特率mismatch:板卡U-Boot傳遞的波特率為1500000,若內(nèi)核cmdline/DTS中串口波特率配置為115200、9600等,會(huì)直接導(dǎo)致亂碼→要么修改U-Boot的ATAGS串口參數(shù),要么調(diào)整內(nèi)核配置,保持一致;
?串口物理地址錯(cuò)誤:板卡串口基地址為0xfeb50000,需核對SOC手冊,確認(rèn)該地址對應(yīng)串口控制器是否為內(nèi)核配置的串口設(shè)備,若地址錯(cuò)誤需修正U-Boot的串口基地址定義;
?enable=0x1(串口已使能),id=0x2(串口編號),可核對內(nèi)核是否配置了對應(yīng)編號的串口設(shè)備,避免串口編號不匹配導(dǎo)致無輸出。
場景3:TOS/ATF啟動(dòng)異常
操作步驟:
1.執(zhí)行atags找到[atf_mem]和[tos_mem]段:
[atf_mem]:magic = 0x54410055size = 0x28version = 0x0phy_addr = 0x0size = 0x100000res[0] = 0x0res[1] = 0x0hash = 0x1fe8a1b8[tos_mem]:magic = 0x54410053size = 0x7cversion = 0x10000tee_mem:name = tee.memphy_addr = 0x8400000size = 0x1000000flags = 0x1drm_mem:name = drm.memphy_addr = 0x0size = 0x0flags = 0x0res[0] = 0x0res[1] = 0x0res[2] = 0x0res[3] = 0x0res[4] = 0x0res[5] = 0x0res[6] = 0x0res1 = 0x0hash = 0x949aa8bf
1.排查方向:
?ATF啟動(dòng)異常:atf_mem.phy_addr=0x0,需確認(rèn)ATF內(nèi)存是否配置為“自動(dòng)分配”或“地址未定義”,若SOC要求ATF內(nèi)存必須指定非0物理地址→修正U-Boot中ATF內(nèi)存配置,重新生成ATAGS;
?TOS啟動(dòng)異常:tee_mem.phy_addr=0x8400000、size=0x1000000(16MB),查看該地址范圍是否與ddr_mem中的有效bank地址沖突,若沖突→調(diào)整TEE內(nèi)存分區(qū)的物理地址;
?drm_mem.phy_addr=0x0、size=0x0,說明未配置DRM內(nèi)存,若板卡需要DRM功能,需在U-Boot中啟用DRM內(nèi)存配置,否則會(huì)導(dǎo)致TOS中DRM模塊初始化失敗。
場景4:ATAGS內(nèi)存溢出導(dǎo)致參數(shù)丟失
操作步驟:
1.執(zhí)行atags查看內(nèi)存統(tǒng)計(jì)段:
ATAGSstate:addr=0x001fe000 ~0x00200000Totalsize =0x00002000inuse size =0x000003e0availablesize =0x00001c20
1.排查方向:
?板卡實(shí)際已用大小(0x3e0)遠(yuǎn)小于總大?。?/span>0x2000),可用空間充足(0x1c20),可排除內(nèi)存溢出導(dǎo)致的參數(shù)丟失問題;
?若后續(xù)新增Tag(如自定義RAM分區(qū)、新增固件版本信息),導(dǎo)致已用大小接近總大小0x2000 →需擴(kuò)大ATAGS區(qū)域總大小,修改rk_atags.h中的ATAGS_SIZE宏(當(dāng)前為0x2000),重新編譯U-Boot;
?額外檢查:addr=0x001fe000 ~ 0x00200000,需確認(rèn)該內(nèi)存區(qū)域未被DDR、ATF等其他模塊占用,避免內(nèi)存地址沖突導(dǎo)致ATAGS參數(shù)寫入失敗。
四、總結(jié):atags.c的調(diào)試核心邏輯
瑞芯微atags.c的本質(zhì),是將U-Boot寫入物理內(nèi)存的ATAGS參數(shù)“可視化”——結(jié)合實(shí)際開發(fā)板情況,無需通過JTAG調(diào)試、無需加臨時(shí)打印,僅用atags一條命令,就能快速獲取core、serial、ddr_mem等10類核心參數(shù),以及ATAGS內(nèi)存使用狀態(tài),驗(yàn)證參數(shù)的正確性。
其調(diào)試核心邏輯可總結(jié)為:
執(zhí)行atags命令→解析ATAGS內(nèi)存區(qū)域(0x001fe000~0x00200000)→打印10類結(jié)構(gòu)化參數(shù)+內(nèi)存統(tǒng)計(jì)→對比預(yù)期配置(DTS/SOC手冊/內(nèi)核參數(shù))→定位參數(shù)不匹配/內(nèi)存沖突/溢出問題
對于該類開發(fā)板而言,掌握atags.c的解析邏輯和atags命令的使用,能大幅降低ARM啟動(dòng)類問題的調(diào)試成本——比如串口亂碼可直接核對serial Tag的波特率和地址,內(nèi)存識別錯(cuò)誤可快速查看ddr_mem的bank配置,TOS/ATF異??啥ㄎ?/span>atf_mem/tos_mem的參數(shù)問題,從“盲猜問題”到“精準(zhǔn)定位”,這也是嵌入式開發(fā)中“工具化調(diào)試”的核心價(jià)值。
最后
嵌入式調(diào)試的核心是“可視化”和“可驗(yàn)證”,而atags.c正是U-Boot參數(shù)調(diào)試的“可視化工具”。本文結(jié)合實(shí)際開發(fā)板的真實(shí)atags輸出,完善了所有示例和實(shí)戰(zhàn)場景,可直接用于后續(xù)板卡調(diào)試。若開發(fā)板遇到特定啟動(dòng)問題(如bootdev識別錯(cuò)誤、pstore存儲(chǔ)異常),可結(jié)合本文思路,通過atags命令定位,也歡迎在評論區(qū)交流~
-
嵌入式
+關(guān)注
關(guān)注
5200文章
20458瀏覽量
334323 -
u-boot
+關(guān)注
關(guān)注
0文章
135瀏覽量
39798 -
瑞芯微
+關(guān)注
關(guān)注
27文章
795瀏覽量
54360
發(fā)布評論請先 登錄
U-boot的基本介紹
U-Boot的啟動(dòng)及移植分析
嵌入式U-BOOT的啟動(dòng)流程及移植
基于ARM9的U-Boot自動(dòng)識別啟動(dòng)實(shí)現(xiàn)
fireflyAIO-3399C主板U-Boot介紹
在Vitis中調(diào)試ARM可信固件和U-boot
解析Rockchip平臺(tái)U-Boot核心文件:boot_rkimg.c到底做了什么?
深入理解?RK3506 U-Boot?重定位:從代碼到原理
深入解析U-Boot image.c:RK平臺(tái)鏡像處理核心邏輯
U-Boot調(diào)試神器:深挖rk平臺(tái)atags.c,解決90%的ARM啟動(dòng)問題
評論