U-Boot调试神器:深挖rk平台atags.c,解决90%的ARM启动问题

电子说

1.4w人已加入

描述

 

 

 

ARM嵌入式开发中,U-Boot作为启动第一站,其向内核/可信固件(ATF/TOS)传递的参数是否正确,直接决定了后续系统能否正常启动。瑞芯微(Rockchip)平台下的atags.c,正是调试这类参数问题的金钥匙”——它不仅是ATAGS参数的解析器,更是嵌入式工程师定位启动故障的核心工具。

 

 

本文将结合实际开发板的atags命令输出,从atags.c的核心逻辑出发,拆解其功能、调试价值,并结合实战场景讲解如何利用该模块快速解决ARM启动类问题。

u-boot

一、ATAGS是什么?atags.c又做了什么?

 

 

基础:ATAGSARM Tags)是ARM架构下U-Boot与内核/下级固件的参数桥梁,类比x86SMBIOS,负责传递硬件配置、内存分区、启动设备等关键信息。

 

 

瑞芯微定制的atags.c,则是这套桥梁可视化调试工具,核心实现3项功能,结合实际开发板输出可更直观理解:

 

 

1. 结构化解析+打印所有ATAGS参数

 

 

遍历ATAGS_PHYS_BASE(实际开发板为0x001fe000)物理内存区域,解析瑞芯微定制的所有ATAG类型(除常见的串口、DDR内存、TOS/ATF内存等,还包含corepstoreboot1 param等特有Tag),并输出每个参数的具体值(如实际串口波特率1500000DDR 3个有效bank地址等)。

 

 

核心函数:atags_print_all_tags()(遍历所有Tag) atags_print_tag()(按Tag类型打印字段),实际开发板执行atags命令后,会依次输出coreserialddr_mem10Tag的完整参数。

 

 

2. 统计ATAGS内存使用状态

 

 

计算ATAGS区域的总大小、已用大小、可用大小,判断是否存在内存溢出(参数写入越界)。结合实际开发板输出,其ATAGS区域地址范围为0x001fe000 ~ 0x00200000,总大小0x000020008KB),已用仅0x000003e0,可用空间充足,无溢出风险。

 

 

核心函数:atags_stat()——通过累加每个Tag的占用字节(t->hdr.size << 2),输出内存使用占比,实际输出中“in use size”“available size”可直接判断内存状态。

 

 

3. 暴露U-Boot命令行调试接口

 

 

通过U_BOOT_CMD注册atags命令,开发者无需修改代码、无需重新编译,在U-Boot命令行输入atags即可触发上述解析和统计,是无侵入式调试的关键。实际开发板的所有ATAGS参数,均通过这一条命令直接获取,无需额外调试操作。

 

 

核心逻辑:do_dump_atags()绑定命令执行逻辑,一行命令就能拿到全量参数+内存状态,下文所有实战分析均基于开发板真实atags输出。

 

 

二、为什么atags.c是调试刚需

 

 

ARM平台启动故障80%以上与U-Boot传递的参数不匹配有关,而atags.c正是定位这类问题的终极武器。以下是高频调试场景及对应的价值:

 

 

调试场景

 

 

atags.c能解决什么问题?(结合实际板卡)

 

 

内核启动失败

 

 

验证core(核心参数)、ddr_mem(内存)、rootdev(根设备)是否正确,实际板卡corerootdev0x0,需核对内核配置;

 

 

TOS/ATF启动异常

 

 

查看atf_memATF内存,实际phy_addr=0x0size=0x100000)、tos_memTEE/DRM内存)是否地址冲突/配置异常;

 

 

串口调试乱码/无输出

 

 

核对serial Tag:波特率1500000、物理地址0xfeb50000、使能0x1,确认与内核串口配置一致;

 

 

启动设备识别错误(EMMC→SD

 

 

定位bootdev Tagdevtype=0x2devnum=0x0,对照瑞芯微手册判断设备类型是否匹配;

 

 

ATAGS参数丢失/溢出

 

 

通过实际ATAGS state判断:已用0x3e0 < 总大小0x2000,无溢出,若参数丢失可排查Tag写入逻辑;

 

 

固件版本/签名异常

 

 

验证fwver TagDDRSPLBL31BL32固件版本明确,可核对是否为目标版本;

 

 

自定义参数生效验证

 

 

新增/修改RAM分区、boot1参数后,可通过ddr_memboot1 param Tag快速验证写入成功;

 

 

pstore存储异常

 

 

查看pstore Tagtable参数,实际板卡前5项均为0x8000@0x110000,可验证持久化存储配置;

 

 

三、实战:用atags命令解决4类高频问题(基于真实板卡输出)

 

 

以下结合实际开发板的真实atags输出,讲解4类高频启动问题的定位方法,所有操作均基于板卡实际参数,可直接套用。

 

 

场景1:内核启动后内存识别错误

 

 

操作步骤:

 

 

1.U-Boot命令行执行atags,找到[ddr_mem]段:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
[ddr_mem]:     magic = 0x54410052      size = 0xc0
     count = 0x3   version = 0x0  bank[0] = 0x0  bank[1] = 0x100000000  bank[2] = 0x2f0000000  bank[3] = 0xf0000000  bank[4] = 0x100000000  bank[5] = 0x10000000  bank[6] = 0x0  bank[7] = 0x0  bank[8] = 0x0  bank[9] = 0x0  bank[10] = 0x0  bank[11] = 0x0  bank[12] = 0x0  bank[13] = 0x0  bank[14] = 0x0  bank[15] = 0x0  bank[16] = 0x0  bank[17] = 0x0  bank[18] = 0x0  bank[19] = 0x0     flags = 0x2  data[0] = 0x0  data[1] = 0x0      hash = 0xb713be00

1.对比内核设备树(DTS)中的内存配置,重点关注2点:
        

 

 

板卡count=0x3,说明有3个有效DDR bank,实际有效地址为bank[1]0x100000000)、bank[2]0x2f0000000)、bank[5]0x10000000),若DTS中内存地址/数量与这些值不一致 → 修正U-BootDDR初始化逻辑,重新生成ATAGS参数;

 

 

flags=0x2,需对照瑞芯微rk_atags.hflags的宏定义,确认DDR工作模式是否符合预期,模式错误也会导致内存识别失败。

 

 

场景2:内核串口乱码(U-Boot串口正常)

 

 

操作步骤:

 

 

1.执行atags找到[serial]段:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
[serial]:     magic = 0x54410050      size = 0x30
   version = 0x0    enable = 0x1      addr = 0xfeb50000  baudrate = 1500000    m_mode = 0x0        id = 0x2    res[0] = 0x0    res[1] = 0x0      hash = 0xf968b524

1.排查方向:
        

 

 

波特率 mismatch:板卡U-Boot传递的波特率为1500000,若内核cmdline/DTS中串口波特率配置为1152009600等,会直接导致乱码 → 要么修改U-BootATAGS串口参数,要么调整内核配置,保持一致;

 

 

串口物理地址错误:板卡串口基地址为0xfeb50000,需核对SOC手册,确认该地址对应串口控制器是否为内核配置的串口设备,若地址错误需修正U-Boot的串口基地址定义;

 

 

enable=0x1(串口已使能),id=0x2(串口编号),可核对内核是否配置了对应编号的串口设备,避免串口编号不匹配导致无输出。

 

 

场景3TOS/ATF启动异常

 

 

操作步骤:

 

 

1.执行atags找到[atf_mem][tos_mem]段:

 

 

  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
  •  
[atf_mem]:     magic = 0x54410055      size = 0x28
   version = 0x0  phy_addr = 0x0      size = 0x100000    res[0] = 0x0    res[1] = 0x0      hash = 0x1fe8a1b8
[tos_mem]:     magic = 0x54410053      size = 0x7c
   version = 0x10000   tee_mem:            name = tee.mem        phy_addr = 0x8400000            size = 0x1000000           flags = 0x1   drm_mem:            name = drm.mem        phy_addr = 0x0            size = 0x0           flags = 0x0   res[0] = 0x0   res[1] = 0x0   res[2] = 0x0   res[3] = 0x0   res[4] = 0x0   res[5] = 0x0   res[6] = 0x0     res1 = 0x0     hash = 0x949aa8bf

1.排查方向:
        

 

 

ATF启动异常:atf_mem.phy_addr=0x0,需确认ATF内存是否配置为自动分配地址未定义,若SOC要求ATF内存必须指定非0物理地址 → 修正U-BootATF内存配置,重新生成ATAGS

 

 

TOS启动异常:tee_mem.phy_addr=0x8400000size=0x100000016MB),查看该地址范围是否与ddr_mem中的有效bank地址冲突,若冲突 → 调整TEE内存分区的物理地址;

 

 

drm_mem.phy_addr=0x0size=0x0,说明未配置DRM内存,若板卡需要DRM功能,需在U-Boot中启用DRM内存配置,否则会导致TOSDRM模块初始化失败。

 

 

场景4ATAGS内存溢出导致参数丢失

 

 

操作步骤:

 

 

1.执行atags查看内存统计段:

  •  
  •  
  •  
  •  
  •  
ATAGS state:              addr = 0x001fe000 ~ 0x00200000        Total size = 0x00002000       in use size = 0x000003e0    available size = 0x00001c20

1.排查方向:
       

 

 

板卡实际已用大小(0x3e0)远小于总大小(0x2000),可用空间充足(0x1c20),可排除内存溢出导致的参数丢失问题;

 

 

若后续新增Tag(如自定义RAM分区、新增固件版本信息),导致已用大小接近总大小0x2000 → 需扩大ATAGS区域总大小,修改rk_atags.h中的ATAGS_SIZE宏(当前为0x2000),重新编译U-Boot

 

 

额外检查:addr=0x001fe000 ~ 0x00200000,需确认该内存区域未被DDRATF等其他模块占用,避免内存地址冲突导致ATAGS参数写入失败。

 

 

四、总结:atags.c的调试核心逻辑

 

 

瑞芯微atags.c的本质,是将U-Boot写入物理内存的ATAGS参数可视化”——结合实际开发板情况,无需通过JTAG调试、无需加临时打印,仅用atags一条命令,就能快速获取coreserialddr_mem10类核心参数,以及ATAGS内存使用状态,验证参数的正确性。

 

 

其调试核心逻辑可总结为:

 

 

  •  
执行atags命令  解析ATAGS内存区域(0x001fe000~0x00200000)  打印10类结构化参数 + 内存统计  对比预期配置(DTS/SOC手册/内核参数)  定位参数不匹配/内存冲突/溢出问题

对于该类开发板而言,掌握atags.c的解析逻辑和atags命令的使用,能大幅降低ARM启动类问题的调试成本——比如串口乱码可直接核对serial Tag的波特率和地址,内存识别错误可快速查看ddr_membank配置,TOS/ATF异常可定位atf_mem/tos_mem的参数问题,从盲猜问题精准定位,这也是嵌入式开发中工具化调试的核心价值。

 

 

最后

 

 

嵌入式调试的核心是可视化可验证,而atags.c正是U-Boot参数调试的可视化工具。本文结合实际开发板的真实atags输出,完善了所有示例和实战场景,可直接用于后续板卡调试。若开发板遇到特定启动问题(如bootdev识别错误、pstore存储异常),可结合本文思路,通过atags命令定位,也欢迎在评论区交流~

 

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分