ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

T2080 PowerPC平台U-BOOT与Linux内核移植:开发调试环境搭建全攻略

T2080 PowerPC平台U-BOOT与Linux内核移植:开发调试环境搭建全攻略 如果跟我一样第一次拿到 T2080 这块板子心里多少有点发怵。网上随手一搜STM32 移植 FreeRTOS、LVGL 的教程能翻几十页可到了 T2080 这种基于 PowerPC 架构、要跑完整 Linux 内核的高端平台资料突然就稀少了。我当初就是在这种状态下开始折腾 U-BOOT 与 OS 内核移植的。回过头看最耽误时间的其实不是改代码本身而是前期那套开发调试环境没捋顺。这篇准备篇一就把我搭建 T2080 开发调试环境的完整过程、选型逻辑和踩坑记录整理出来给后面要接手这块板子、做底层引导和系统移植的工程师做个参考。先说清楚这套环境要解决什么问题。T2080 平台的移植工作核心是让 U-BOOT 能从启动介质把固件拉起来再把操作系统内核以 Linux 为典型代表引导进内存、挂在根文件系统上完成启动。整个过程涉及交叉编译、镜像打包、串口交互、网络加载、JTAG 调试等多条链路。这些链条上任何一环断了现象都可能是板子没反应但原因五花八门。准备篇的意义就是在动手改 U-BOOT 源码之前先把这些链路的通断状态全部验证过一遍。1. 这块板子到底什么来头T2080平台规格与资源盘点1.1 折腾U-BOOT和内核移植之前先搞懂T2080的架构差异T2080 是 NXP QorIQ T 系列里的一款通信处理器核心是双 e5500基于 PowerPC 架构每个核支持双线程相当于 4 个逻辑线程主频能跑到 1.8GHz。抛开纸面参数对做移植的人来说它跟 ARM 平台最大的不同在于指令集架构和整机设计思路。ARM 平台比如 i.MX6ULL、STM32MP1 这些的 U-BOOT、Linux BSP 资料铺天盖地而 T2080 的 BSP 主要依赖 NXP 官方 SDK社区资料非常少。这意味着很多东西不能靠出问题了上网搜得自己从原理层面排查。e5500 核心支持 64 位但实际用 32 位还是 64 位模式取决于你拿到的 SDK 和内核配置。我手头这套 BSP 用的是 32 位工具链这也直接决定了后面所有编译命令里的ARCHpowerpc和CROSS_COMPILE前缀。另一个容易懵的地方是T2080 的平台里经常出现 HRCW、DPAA、SerDes 这些概念。这些不是简单的寄存器而是与启动流程、网络数据通路直接相关的硬件机制。准备阶段不一定需要全部吃透但至少要知道它们的存在以及它们在调试环境里扮演的角色否则后面遇到问题连排查方向都找不对。1.2 板级资源盘点真正决定调试方式的是这几个外设T2080 的平台典型参考板是 T2080RDB板级资源很丰富但从开发调试环境的角度看真正决定工作方式的其实就这几个资源调试角色说明调试串口信息输出U-BOOT 和内核启动日志都从这里出是板子活着没活着的最直接依据JTAG 接口底层干预U-BOOT 挂掉、Flash 被清空时救砖也能做硬件寄存器级调试以太网口镜像投递TFTP 加载内核、NFS 挂根文件系统移植阶段效率最高的路径NOR/NAND/SD 启动介质固件承载决定 U-BOOT 从哪里加载需要根据板卡拨码或跳线确认我建议拿到板子后先别急着连 U-BOOT、编译内核。对照板卡手册把板子上这几个关键接口的位置、拨码开关状态、串口引脚定义确认一遍。多数情况下板子没反应不是代码问题而是调试链路本身就断了。2. 交叉编译环境工具链选型与主机侧必备的依赖2.1 工具链版本有讲究不是越新越好说到交叉编译工具链有人可能觉得GCC 版本越新越好但在 T2080 这种老平台上这个观点要打个大问号。PowerPC 指令集虽然没变但较新版本的 GCC 在编译旧版 U-BOOT 或旧内核时经常会因为内联汇编语法、链接器脚本兼容性等问题报错。我最后用的是 NXP 官方 SDK 自带的工具链版本是 GCC 4.9 系列。这个选择不是因为它性能好而是因为官方 BSP 就是拿它验证过的。交叉编译工具链的命名通常是powerpc-linux-gnu-gcc如果做 64 位版本则可能是powerpc64-linux-gnu-gcc。拿到工具链后把它解压到固定目录通常是/opt下面然后设置环境变量export PATH/opt/freescale/2015.03/usr/bin:$PATH export ARCHpowerpc export CROSS_COMPILEpowerpc-linux-gnu-这里有个细节CROSS_COMPILE一定要带上最后的横杠GCC、LD、OBJCOPY 这些工具都会自动补全成powerpc-linux-gnu-gcc、powerpc-linux-gnu-ld等。少了这个横杠编译大概率直接失败。2.2 主机侧还要补齐的依赖项除了工具链本身宿主机上还需要装一批辅助软件很多第一次接触的人会漏掉。sudo apt update sudo apt install -y git make gcc libncurses-dev bison flex \ u-boot-tools device-tree-compiler lzop逐一说明一下它们在这里的用途libncurses-dev内核make menuconfig配置界面依赖的库不装会报ncurses.h找不到。bison和flexU-BOOT 和内核的配置系统Kconfig用它们做词法语法分析。u-boot-tools提供mkimage命令用来给内核镜像打上 U-BOOT 引导头部生成uImage。device-tree-compiler提供dtc命令用来把设备树源文件.dts编译成二进制.dtb。lzop内核压缩、U-BOOT 镜像处理时可能涉及的压缩工具。我见过有人在宿主机上装了一堆图形界面工具结果最关键的命令mkimage缺失内核编完了却生成不了可引导的uImage卡了半天。2.3 交叉编译环境的快速自检方法环境配好后先用简单方法自检一下不要等到 U-BOOT 编译到一半报错才回头查。powerpc-linux-gnu-gcc -v能正常输出版本信息说明工具链可执行。再写一个最小的 C 文件int main(void) { return 0; }powerpc-linux-gnu-gcc -o test test.c file testfile命令输出里应该能看到PowerPC或者32-bit MSB之类的字样说明工具链工作正常。这一步 5 分钟内能做完却能把工具链有没有装好这个变量从后面所有问题中彻底排除掉。3. 调试链路的铁三角串口、JTAG与网络加载的分工协作3.1 调试串口U-BOOT没起来之前它是唯一的信息通道T2080 平台的调试串口通常是板上引出的 UART 口通过 USB 转串口模块连到电脑波特率默认是115200 8N1。在 U-BOOT 完全跑起来之前任何显示设备都依赖这个串口所以它的优先级最高。Linux 下我习惯用minicom也可以直接用picocom更轻量sudo apt install picocom picocom -b 115200 /dev/ttyUSB0如果串口设备显示/dev/ttyUSB1而不是/dev/ttyUSB0以系统实际列出的为准。连接成功后按一下板子的复位键串口里应该能看到 U-BOOT 的启动信息。需要注意的是USB 转串口模块和板子之间最好共地否则乱码或者完全无输出的概率很高。3.2 JTAG调试器救砖与底层初始化串口能看到的是程序跑起来之后的输出。但如果 U-BOOT 在初始化早期就挂了Flash 里的固件也被改坏这时候串口往往一片寂静唯一能干预的就是 JTAG。T2080 平台常见的 JTAG 调试器有 Lauterbach TRACE32 和 CodeWarrior TAP。第一次使用需要建立目标配置文件指定 CPU 型号为 T2080、连接方式为 JTAG。连接成功后可以访问内存、读写寄存器、甚至可以手动把编译好的 U-BOOT 镜像加载到内存里启动。JTAG 不是每个人都有的东西价格也偏高。如果条件有限准备阶段可以先把 JTAG 驱动的安装和连接流程走一遍确认板子能被识别。这样真到救砖的时候就不会手忙脚乱。3.3 网络加载移植阶段效率最高的镜像投递方式串口适合看信息JTAG 适合救急但移植阶段最频繁的操作是把新编译的内核放进板子里运行这一步靠网络最合适。T2080 的以太网接口在 U-BOOT 阶段就能工作通过 TFTP 协议从宿主机拿镜像。配置思路是把宿主机当成 TFTP 服务器把编译好的uImage、设备树文件放到 TFTP 根目录板子在 U-BOOT 命令行下执行setenv ipaddr 192.168.1.100 setenv serverip 192.168.1.10 tftp 0x1000000 uImageipaddr是板子自己的 IPserverip是宿主机的 IP。0x1000000是内存加载地址T2080 的 DDR 空间映射要从具体平台的内存映射表确认。这一步跑通之后每次编译完内核只需要拷到 TFTP 目录再重启板子就能加载省去反复烧写 Flash 的时间。4. U-BOOT移植前的调试环境自查从Flash引导到网络引导的切换4.1 先搞清楚板子从哪启动启动设备与内存映射T2080 的参考板通常支持从 NOR Flash、NAND、SD 卡等介质启动具体选择由板卡上的拨码开关或者 HRCW 里的配置决定。准备阶段第一件事就是对照板卡手册确认当前板子处于哪种启动模式。我手上的板子默认从 NOR Flash 启动NOR Flash 里出厂时烧了可用的 U-BOOT。这带来一个好处即使后面把环境变量改坏了只要 NOR 里的 U-BOOT 还在就能通过串口进入命令行修复。内存映射也是必须提前查的。U-BOOT 里tftp加载内核的地址、内核设备树加载的地址、bootm跳转的地址全都要落在合法的内存区间内。T2080 的 Local Access Window 和 CCSR 映射关系在 NXP 参考手册里有明确说明第一次用的时候务必查清楚别照抄网上 ARM 平台的地址。4.2 备用启动介质给折腾留一条退路移植 U-BOOT 的过程里最常见的翻车就是把 Flash 里的 U-BOOT 覆盖成了有问题的版本然后板子彻底变砖。准备阶段最值得做的一件事就是准备一份已知可用的 U-BOOT 镜像并确认能通过 JTAG 或者备用启动介质把它恢复回来。我的做法是把原始 U-BOOT 的镜像备份出来同时研究清楚板子是否支持从 SD 卡启动。如果可以就在 SD 卡上也放一份可用的 U-BOOT。这样即使 Flash 内容被清空只要切换启动模式到 SD 卡板子依然能起来。很多人觉得我不会那么倒霉但实际操作中一次saveenv保存了错误的环境变量或者一次erase命令写错了 Flash 地址就可能让板子反复重启。留一条退路不是胆小是专业习惯。4.3 U-BOOT环境变量的最小可用配置在 U-BOOT 命令行下把网络引导相关的环境变量配置好是准备阶段的核心目标。下面这套配置可以作为一个起始模板setenv ipaddr 192.168.1.100 setenv serverip 192.168.1.10 setenv gatewayip 192.168.1.1 setenv netmask 255.255.255.0 setenv bootfile uImage setenv fdtfile t2080rdb.dtb setenv loadaddr 0x1000000 setenv fdtaddr 0x2000000 saveenv然后手动执行一次加载和引导tftp ${loadaddr} ${bootfile} tftp ${fdtaddr} ${fdtfile} bootm ${loadaddr} - ${fdtaddr}这段命令的含义是先把内核加载到loadaddr指定的内存位置再把设备树加载到fdtaddr指向的内存位置最后通过bootm启动内核。关于bootm的参数中间用-表示没有 initrd如果使用设备树第三个参数就是设备树的内存地址。建议第一次测试时先手动敲这些命令确认每一步都正常后再去改bootcmd做成自动启动。手动验证的好处是任何一步失败了能立刻定位是网络问题、镜像问题还是地址问题。5. 内核移植阶段的环境准备系统镜像与根文件系统的悬挂方式5.1 内核镜像与设备树uImage不是随便编出来就能跑的交叉编译内核之前需要明确一个基本概念T2080 平台要引导 Linux 内核镜像格式通常是uImage这是 U-BOOT 专有的镜像格式通过mkimage在普通内核镜像vmlinux或Image前面加了一段头部信息包含加载地址、入口地址、校验和等。编译命令大致如下export ARCHpowerpc export CROSS_COMPILEpowerpc-linux-gnu- make t2080rdb_defconfig make -j8 uImage make t2080rdb.dtbmake -j8是并行编译具体数字根据宿主机 CPU 核数调整。编完的arch/powerpc/boot/uImage就是需要拷到 TFTP 目录的文件。t2080rdb.dtb则是板卡的设备树二进制。这里特别容易踩坑的点是uImage的加载地址必须和 U-BOOT 里tftp的内存地址一致。这个一致性是由 Makefile 里的配置决定的改起来比较隐蔽。如果没有把握就保持 U-BOOT 的loadaddr跟内核编译时指定的地址一致不要两边各设各的。5.2 根文件系统怎么挂开发阶段首选NFS内核起来了之后必须挂在根文件系统上才能进入完整的系统环境。根文件系统的选择直接决定开发调试的体验方式优点缺点适用场景initramfs无需外部存储启动简单每次改文件都要重新打包快速验证内核能不能跑NFS 网络挂载修改宿主机文件即刻生效依赖网络板子必须有网口开发和调试阶段最常用SD 卡/eMMC 本地存储启动速度快不依赖网络反复烧写麻烦内核和文件系统稳定之后开发调试阶段我强烈推荐 NFS。做法是在宿主机上配置 NFS 服务导出一个目录作为根文件系统然后在 U-BOOT 的bootargs里指定setenv bootargs consolettyS0,115200 root/dev/nfs rw nfsroot192.168.1.10:/opt/t2080/rootfs ip192.168.1.100:192.168.1.10:192.168.1.1:255.255.255.0::eth0:offnfsroot后面跟的是宿主机 IP 和导出的目录路径ip那一串是板子的 IP、宿主机 IP、网关、掩码。如果板子的另一个网口连着路由而不是直连宿主机IP 配置要做相应调整。NFS 的好处是宿主机上改个程序、替换个库板子里立刻就能用完全不用重新烧写文件系统映像。这在调试应用层程序、交叉编译依赖库时效率提升巨大。5.3 一条完整的启动命令串起来看把前面的步骤串起来一次完整的网络引导过程大致是这样的setenv bootargs consolettyS0,115200 root/dev/nfs rw nfsroot192.168.1.10:/opt/t2080/rootfs ip192.168.1.100:192.168.1.10:192.168.1.1:255.255.255.0::eth0:off setenv bootcmd tftp ${loadaddr} ${bootfile}; tftp ${fdtaddr} ${fdtfile}; bootm ${loadaddr} - ${fdtaddr} saveenv之后每次重启板子U-BOOT 会自动从 TFTP 服务器加载内核和设备树再从 NFS 挂载根文件系统。整个过程不再需要人工干预非常适合反复修改内核代码、驱动模块的移植阶段。在准备阶段我建议先把这套流程完整跑通一遍哪怕内核还是出厂自带的也要确认从 U-BOOT 到内核、再到根文件系统的整条链路是通的。链路通了后面的移植工作才有一个可靠的验证平台。6. 准备阶段最容易翻车的地方一份实测避坑记录6.1 工具链版本太新引发的连锁反应我在一开始犯过的错误就是图省事直接从系统源里装了最新版 GCC然后指定它做交叉编译。编译 U-BOOT 的时候前几分钟一切正常到了链接阶段突然报出一堆莫名其妙的错误指向一些内联汇编代码和链接脚本。排查到最后发现问题出在较新版本的 GCC 对旧代码里某些内联汇编的约束处理更严格旧 BSP 的汇编代码没有跟上新 GCC 的语法要求。解决办法就是切回官方 SDK 自带的工具链。这里给大家的建议是做老平台移植工具链版本选择以官方 BSP 验证过的版本为最优解不要追求新版本。6.2 串口输出状态的解读无输出、乱码、卡住的含义串口是调试中最容易让人误判的一环。我总结了一下串口几种典型状态的含义完全无输出可能是串口线没接对、供电不足、启动介质里没有有效固件。先确认串口参数和线路再检查启动模式。输出乱码绝大多数情况是波特率不匹配。确认终端设置的波特率是不是 115200确认 USB 转串口模块质量没问题。输出一段后卡住说明 U-BOOT 已经起来了但执行到某个环节出错。看卡住之前的最后几行日志通常就是问题所在。有一次板子串口完全没反应我排查了半小时最后发现是 USB 转串口线内部断了一根线。所以排查顺序建议从最傻的可能性开始先确认硬件链路再怀疑软件问题。6.3 终端软件与串口权限的坑在 Ubuntu 下使用串口需要当前用户有访问串口设备的权限。常见做法是把用户加入dialout组sudo usermod -a -G dialout $USER改完之后需要重新登录一次才能生效。另外用 minicom 的时候要在配置界面里把Hardware Flow Control关闭否则板子的串口输出可能会出现只输出一半就停住的诡异现象。6.4 HRCWT2080平台绕不开的硬件复位配置最后想提一下 HRCW。T2080 这类平台在 CPU 复位时会读取一个硬件复位配置字它决定了核心时钟配置、启动方式、SerDes 协议选择等一系列非常基础的参数。这个配置字可以放在板载的 CPLD 里也可以由拨码开关的部分引脚决定。HRCW 如果不对U-BOOT 可能根本不会执行或者执行到一半就异常。准备阶段至少要做到能根据板卡手册找到 HRCW 的当前配置来源能确认它的值是否为厂家默认值。很多板子完全没动静的问题根源不在 U-BOOT 代码而在 HRCW 配置。在正式开始移植 U-BOOT 和 OS 内核之前我把上面这一整套开发调试环境完整搭建并验证了一遍前前后后花了两三天时间。这些准备里的每一步看上去都算不上核心工作但真的是它们决定了后面遇到问题时的排查效率。如果你也正准备接手 T2080 平台我建议把这篇里的检查项逐条过掉尤其是串口、TFTP、NFS 这三条链路的连通性确认没问题再动源码。链路通了折腾才有底气。后面我会继续写 U-BOOT 的编译实操和内核移植的第一步改动先把环境打磨好后面的事情会顺很多。
返回列表