ARTICLE DETAIL

资讯详情

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

飞腾D2000 U-Boot移植实战:从启动链路到内核引导

飞腾D2000 U-Boot移植实战:从启动链路到内核引导 接到飞腾D2000开发板U-Boot移植任务时我第一反应是先翻了一遍网上能找到的资料结果发现大部分帖子都停留在“能用官方BSP编出来”这一步很少有人把启动链路、设备树、烧录和排错串成一条完整的流程。这篇文章就把我自己从拿到板子、建立环境、编译U-Boot到最终在串口里看到内核跑起来全过程做一个完整复盘。内容面向的是要上手飞腾D2000平台的嵌入式工程师、系统软件工程师也适合那些之前只玩过ARM32平台想了解ARM64 U-Boot移植完整路径的朋友。整篇文章不绕弯子直接按我实际操作中的顺序来写过程中踩过的坑、为什么这样配置、遇到异常时怎么收缩排查范围都会交代清楚。1. 动手之前的摸底飞腾D2000的启动链路与必备资料1.1 平台基础D2000这颗SoC有什么移植难点飞腾D2000是一颗8核ARMv8架构的处理器核心是飞腾自研的FTC663主频一般在2.3GHz级别不同型号会有差异。对于U-Boot移植这件事有几个特点直接决定了工作量第一它是ARM64架构U-Boot、内核、设备树都必须按64位模式编译交叉工具链要用aarch64的不能沿用32位ARM那套arm-linux-gnueabihf。第二D2000在实际硬件方案里通常和X100 IO套片搭配使用不少外设控制器挂在X100上比如GMAC网卡、PCIe、SATA、USB等。U-Boot驱动开发时要意识到这不再是传统认知里“CPU SoC直接集成所有外设”的模式外设基地址、中断号、时钟域的划分都要参考两颗芯片共同组成的地址映射关系。第三内存控制器集成在D2000内部支持DDR4但DDR初始化往往有比较强的板级相关性。U-Boot需要完成DRAM控制器配置和训练这通常是移植时最容易翻车的部分。我见过很多开发板日志打印到DRAM检测就停了问题基本都出在内存参数配置上。另外U-Boot本身是一个裸机程序它跑在内核之前要负责时钟、串口、DDR、存储介质、网络这些最基本资源的初始化。飞腾平台往下还依赖BootROM芯片上电后先由固化在内部的BootROM加载U-BootU-Boot再做高级初始化。搞清这条链路后面所有排查才有方向。1.2 启动链条从芯片上电到U-Boot接管再引导内核在开始编译之前我建议先画清楚目标板卡的启动链路。飞腾D2000上电后的典型顺序是这样的1.芯片内部BootROM执行完成最基础的时钟和存储控制器早期初始化。 2.根据启动模式引脚BOOT_MODE选择从SPI NOR Flash、SD/eMMC、SATA等介质读取BootLoader镜像。 3.U-Boot被加载到芯片内部SRAM或预留的RAM区域运行。 4.U-Boot初始化DDR控制器完成DDR training。 5.U-Boot将自身代码重定位到DDR里继续执行。 6.U-Boot执行board_init_r阶段加载各类驱动进入命令行交互。 7.根据bootcmd环境变量从网络、eMMC或SATA加载内核镜像和设备树。 8.跳转到内核入口把控制权交给Linux。理解这条链路的实际价值在于当串口完全没有打印时不要一上来就怀疑U-Boot要先排查BootROM阶段的电源、时钟、启动模式引脚和启动介质内容当输出版本信息后停止时重点怀疑DDR初始化和板级外设驱动当U-Boot命令行能进但内核加载失败时问题往往出在引导参数、内核镜像格式或设备树上。三个阶段对应三类完全不同的调试思路越早建立这个框架越不会被表面现象带偏。1.3 开工前的资料清单别等板子到手才发现缺东西移植工程和软件开发不一样硬件参考手册是绕不开的。我这次开工前专门对照检查了一遍必备资料列出来供参考1.飞腾D2000处理器数据手册和用户手册重点看启动流程、DDR控制器、地址映射、串口控制器寄存器的章节。 2.X100 IO套片资料如果板卡用了X100GMAC、PCIe、SATA这些外设的寄存器说明都在这份文档里。 3.目标板卡的原理图至少要知道串口对应哪个UART、DDR颗粒型号和容量、启动拨码开关状态、SPI Flash型号。 4.U-Boot BSP源码包飞腾官方对外有开源仓库也可以通过代理商FAE获取带板级补丁的BSP。 5.参考设计或原厂提供的defconfig、设备树dts样例这是移植时最值钱的参照。引导介质相关情况也要提前确认。D2000开发板一般支持通过拨码开关选择SPI NOR或eMMC启动我用的板子是SPI NOR为主后面烧录也会围绕这个来写。硬件准备方面需要准备一根TTL转USB串口线、一个可以接SPI NOR Flash的编程器我用的是CH341A也有人用DediProg、一台Ubuntu开发主机。2. 交叉编译链与构建依赖别让工具链拖后腿2.1 为什么必须用ARM64交叉编译链U-Boot最终要运行在D2000的ARMv8 CPU上而编译它通常是在x86_64的Ubuntu主机上完成所以必须使用交叉编译工具链让x86机器生成aarch64指令集的二进制。这个道理很多初学者清楚但实际操作中常常栽在“工具链版本过新”和“宿主机依赖缺失”两个问题上。ARM64的工具链要基于glibc的ARM版本工作如果直接在Ubuntu上执行native gcc去编U-Boot得到的是x86_64格式的可执行文件一上板必然跑不起来。所以第一件事就是确认最终产物格式。我在编译平台验证工具链时会写一个简单的hello.c用它交叉编译后执行file命令看输出格式aarch64-linux-gnu-gcc hello.c -o hello file hello正常输出会包含“ELF 64-bit LSB executable, ARM aarch64”字样如果显示x86-64说明工具链或编译前缀没用对。2.2 工具链选型与快速验证目前主流选择有三个Linaro发布的aarch64-linux-gnu工具链、ARM官方GNU-A工具链、Ubuntu/Debian自带的gcc-aarch64-linux-gnu软件包。对U-Boot这种体量不大的项目来说三者都够用。我个人偏向先用发行版自带的工具链理由是无脑、方便升级、和系统库兼容性好。如果BSP文档里对gcc版本有强制要求再换Linaro的特定版本。安装发行版自带工具链只需要一条命令sudo apt install gcc-aarch64-linux-gnu安装完成后验证版本aarch64-linux-gnu-gcc -v我的经验是工具链版本不要刻意追新。太新的gcc有时会把源码头文件里的细微警告升级成错误导致老版本BSP编译失败太老的又可能不支持某些ARM64扩展指令。用BSP文档出现年代附近的工具链版本往往最省事。2.3 宿主机构建依赖很多断崖式报错的根源U-Boot从2017年以后的版本开始构建过程依赖不少宿主机软件缺了哪个都会在make阶段报出莫名其妙的问题。我这次遇到的第一个报错就是缺python3-dev错误提示隐藏在很长的编译日志中间不仔细看根本发现不了。建议编译前一次性装齐sudo apt install bison flex swig python3-dev libssl-dev \ device-tree-compiler make gcc g pkg-config \ libncurses5-dev这几项的用途分别是bison和flex用于生成dtc和UBI相关语法解析器swig和python3-dev用于U-Boot的Python工具和binman打包脚本libssl-dev用于FIT image签名和verified boot功能device-tree-compiler是编译设备树必须的dtc工具libncurses5-dev用于menuconfig图形化配置界面。如果跳过这些检查强行编译后面每走一步都可能被奇怪的错误卡住。我建议在干净系统上先把依赖装好避免把时间浪费在环境问题上。3. 板级配置与设备树U-Boot眼中的D2000世界3.1 从defconfig入手理解配置裁剪思路U-Boot不是一个把所有驱动都编进去的“全家桶”项目而是通过config文件选择目标平台和需要的功能。飞腾BSP里通常会提供现成的defconfig文件我这边拿到的是d2000_defconfig这个名字不同BSP版本也可能叫phytium_d2000_defconfig以实际源码包为准。打开defconfig后至少要关注这么几类内容1.CONFIG_TARGET_xxx这块决定了board目录下哪一套板级代码参与编译。 2.CONFIG_SYS_TEXT_BASE这是U-Boot在DDR里的链接地址必须和实际DDR地址布局匹配。 3.CONFIG_DEFAULT_DEVICE_TREE指定默认设备树名称。 4.CONFIG_NET、CONFIG_CMD_TFTP决定是否支持网络命令。 5.CONFIG_BOOTDELAY、CONFIG_BOOTCOMMAND决定开机自动启动行为。每个平台需要的功能不一样比如纯eMMC启动的板子可以不编SPI Flash驱动降低体积开发调试阶段的板子则建议保留dhcp、tftp、ping这些网络命令后面用网络引导内核会非常方便。3.2 设备树串口、内存和外设都长什么样ARM64平台下U-Boot已经全面引入设备树来描述硬件。飞腾D2000的设备树位置通常在arch/arm/dts/目录下会有SoC级dtsi和板级dts两层。SoC级dtsi描述芯片内部所有控制器板级dts则负责内存大小、具体外设是否使能、引脚状态这些和板卡强相关的信息。我这次重点检查了三个节点。第一个是chosen节点里面的stdout-path指定U-Boot诊断串口使用的设备如果串口没输出可以先看这里是不是指向了正确的UART节点。第二个是memory节点它告诉U-Boot板上有多少物理内存D2000通常支持多通道DDR4容量从2GB到16GB不等设备树里写的reg属性地址和大小必须和实际硬件一致。第三个是ethernet节点和mdio节点其中PHY的地址、复位GPIO等细节经常导致“U-Boot其他都正常就是网络不通”的现象。一个典型的板级dts片段类似这样/ { chosen { stdout-path uart0; }; memory80000000 { device_type memory; reg 0x0 0x80000000 0x2 0x00000000; }; };这里reg里有两个64位数前两个32位字表示起始地址0x80000000后两个32位字表示大小8GB。写成0x2 0x00000000这类格式时一旦大小对齐算错U-Boot可能只识别出一部分内存严重的会在启动内核后出现内存映射冲突。3.3 DDR初始化移植过程中最隐蔽的深水区U-Boot能否正常启动很大程度取决于DDR控制器初始化是否正确。D2000的内存控制器需要在上电后完成PHY配置和training流程这个过程的参数通常来自EEPROM或者板级代码里的默认配置。我用的板子做法是把DDR颗粒的SPD信息和training参数存放在EEPROM中U-Boot启动时读取配置并执行DDR初始化。如果EEPROM里是空白U-Boot会使用代码里编译时写死的默认参数。这里最容易踩的坑是新板卡的EEPROM没有烧录过任何内容U-Boot读出来全是0xFFDDR控制器按错误参数去训练表现就是U-Boot版本号能打印但到“DRAM: ”检测阶段就停住而且没有任何报错。排查这个问题的思路我后面专门写一节这里先提醒一句如果手上的板子是全新的先确认EEPROM或Flash里有没有有效的DDR配置不然会把大量时间浪费在改动根本无关的代码上。4. 完整编译实战从源码到uboot.bin4.1 获取源码与确认目录结构我的习惯是把BSP源码放在~/workspace/phytium/下解压后先看README和doc目录。飞腾BSP的README一般会写清楚依赖的工具链版本、编译命令和产物格式。有些BSP会把ATFARM Trusted Firmware和OP-TEE一起集成进来编译流程会比纯U-Boot复杂需要先编译BL31再用mkimage或binman打包成FIP镜像。U-Boot源码目录里重点关注这几个位置board/目录存放板级初始化代码飞腾相关的board文件就在这里。arch/arm/dts/目录存放设备树源文件。configs/目录存放所有defconfig文件。include/configs/目录存放头文件形式的配置老一些的BSP仍保留了这种配置方式。arch/arm/mach-phytium/或类似目录存放SoC初始化、DDR初始化代码。先花半小时浏览这些目录比直接敲make命令更能避免后续走弯路。4.2 实际执行编译三条命令跑通基本流程编译前先设置环境变量export ARCHarm64 export CROSS_COMPILEaarch64-linux-gnu-然后进入源码根目录执行make distclean make d2000_defconfig make -j$(nproc)第一句distclean清掉所有旧配置和编译产物确保从不干净的构建状态恢复。第二句按目标板defconfig生成.config文件。第三句正式编译-j$(nproc)用所有CPU核并行编译U-Boot整体编译量不大8核机器一般几分钟就能结束。如果defconfig名字不同可以先执行ls configs/ | grep -i d2000确认实际名称再编译。这一步不丢人经常有BSP版本命名改了但文档没更新的情况。4.3 产物确认与镜像打包格式编译成功后重点关注这几个文件文件含义用途u-boot.bin原始不带头部信息的U-Boot镜像可直接烧写或继续打包u-boot.itbFIT image格式的打包镜像可同时包含U-Boot、ATF BL31、optee等u-boot.dtbU-Boot自带设备树与镜像配套烧写idbloader.img部分平台使用的引导加载镜像如果BSP要求则需合成如果BSP集成了ATF最后烧写的往往不是u-boot.bin而是mkimage打包后的FIP或ITB。判断方法很简单查看BSP源码里的Makefile或README搜索“fip”、“itb”这些关键词。我在移植时第一次只烧了u-boot.bin结果BootROM找不到有效镜像串口完全没有输出后来才发现这个平台需要把bl31.bin和u-boot.bin合并成FIP文件才能被识别。编译完成后用file命令确认格式file u-boot.bin正常会看到ARM aarch64相关的描述如果结果是data或x86格式一定要回头检查CROSS_COMPILE是否设置正确。4.4 编译报错最常见的三类问题与应对第一类是我前面说的缺依赖症状是make到一半报“flex: command not found”或“python3: No module named setuptools”解决办法就是补齐依赖然后重新make。第二类是源码与编译器版本不兼容常见报错是“error: ‘struct foo’ has no member named ‘bar’”或者一些-Werrorxxx的告警被当成错误处理。这类问题优先尝试换用BSP文档推荐的编译器版本不要硬改源码。实在要改也要先把-Werror去掉确认还有没有其他问题。第三类是设备树编译报错通常是dts语法写错或引用节点不存在。报错信息会给出具体文件和行号针对性修改即可。每次修改dts后不需要全量重新编译执行make -j$(nproc)时会增量编译重新生成dtb这对快速迭代非常有帮助。5. 烧录上板第一次看到U-Boot日志5.1 把镜像写进SPI NOR Flash我用的D2000板卡通过SPI NOR Flash启动。烧录工具有两类选择软件方式在U-Boot命令行里用update命令配合tftp下载镜像写入Flash硬件方式用编程器直接夹在Flash芯片引脚上烧写。开发初期我强烈建议用硬件编程器。原因很简单如果U-Boot本身没跑起来软件烧写无从谈起。用CH341A编程器配合其烧录软件把u-boot.bin写入SPI Flash的0地址过程相对直接。烧写前用编程器读出原Flash内容并保存备份万一芯片里本来有出厂U-Boot或备份固件还能恢复。烧录时有几个细节值得注意1.SPI Flash型号要选对不同厂商芯片的读写命令可能存在差异。 2.地址对齐U-Boot镜像一般烧写在Flash起始地址偏移量要格外小心。 3.烧完后把Flash从编程器上取下来重新焊接到板卡或者用夹子夹好检查连接可靠再上电。 4.确认板卡的启动模式拨码开关选的是SPI NOR启动而不是eMMC或SD启动。5.2 串口控制台连接115200 8N1是基本盘串口是U-Boot和Linux启动阶段唯一的交互窗口。D2000调试串口一般是板卡上的某个UART通常板卡上会丝印标注“DEBUG”或“UART0”。用TTL转USB线连接时注意TX和RX要交叉地线必须共地。准备工作完成后在Ubuntu主机上识别设备节点ls /dev/ttyUSB*一般会显示ttyUSB0。用minicom连接sudo minicom -D /dev/ttyUSB0 -b 115200U-Boot控制台参数通常是115200、8N18数据位、无校验、1停止位不同板卡可能用到其他波特率以原理图和BSP代码里的定义为准。我的一个经验教训如果设备节点频繁消失大概率是USB转串口芯片驱动没装好或者用的是劣质线材。另一个容易被忽略的点是RX/TX方向很多新手连好后发现没输出把线序调转一下就好了。这些不是方案问题但浪费的时间一点不比方案问题少。5.3 第一次上电看懂U-Boot日志的关键节点烧录完成后给板上电如果一切正常串口会先打印U-Boot版本、编译时间、厂商信息接着执行DDR初始化、检测内存容量然后枚举MMC、SPI Flash、网卡等设备最后进入“Hit any key to stop autoboot”倒计时此时按任意键进入U-Boot命令行。正常日志大致是U-Boot 2020.04-gXXX (Build time) CPU: Phytium D2000 DRAM: 8 GiB MMC: ... SF: Detected ... Net: eth0: ethernet... Hit any key to stop autoboot: 3 看到“”提示符说明U-Boot已经正常启动。到了这一步移植的第一阶段就算完成了。接下来要做的是验证驱动是否都工作正常比如输入sf probe、mmc list、dhcp这几条命令分别测试SPI Flash、MMC和网络驱动。5.4 启动失败排查链路一个串口完全无输出的真实案例我这次移植过程中第一次上电串口完全没输出连U-Boot版本号都没有。这里分享一下完整的排查链路都是可以直接复现的思路。第一步排除最基础问题。检查板卡供电是否正常、电流表数值是否在预期范围。然后检查串口线序和波特率用示波器或万用表测量串口TX引脚电压。U-Boot启动时会大量打印TX引脚电压会出现频繁翻转如果没有翻转说明U-Boot或者BootROM根本没有运行到这个阶段。第二步确认启动介质内容。我用CH341A把SPI Flash里的内容读出来和编译生成的u-boot.bin做二进制对比确认烧写没有遗漏。这里关键检查点是BootROM是否真的在Flash起始地址找到了有效镜像头。不同平台的BootROM对镜像头部格式有要求如果只烧了u-boot.bin而没有按BSP要求打包成FIPBootROM会直接判定“未找到可启动镜像”然后静默死亡串口当然什么都没打印。第三步核对启动模式引脚。D2000的BootROM从哪个介质加载镜像是由一系列配置引脚决定的。我对照原理图逐一量了板卡上BOOT_MODE相关电阻的焊接情况发现其中两个电阻被贴错了位置导致BootROM认为应该从eMMC启动而eMMC是空的。修正电阻后串口立刻出现了U-Boot日志。从这个案例能提炼出一点当串口完全无输出时问题几乎都在BootROM阶段跟U-Boot自身代码关系不大。不要闷头查代码应该按“电源→串口→镜像格式→BootROM加载顺序→启动模式引脚”的顺序排查。90%的“U-Boot完全没起来”最后都是这类物理或打包层面的问题。6. 从U-Boot启动Linux引导内核的全流程与常见问题6.1 三种加载内核的方式U-Boot起来只是第一步最终目标是引导Linux。D2000平台常用的加载方式有三种适合的阶段各不相同。第一种是网络启动U-Boot通过TFTP从开发主机下载内核镜像和设备树通过NFS挂载根文件系统。这种方式最适合开发调试因为内核、设备树、文件系统都在主机上迭代只需重新拷贝文件不用反复烧写Flash。缺点是依赖网络链路U-Boot里的网卡驱动必须工作正常。第二种是存储介质启动把内核和设备树放到eMMC、SD卡或SATA硬盘的某个分区U-Boot用fatload或ext4load命令读取镜像然后booti启动。适合做固定部署开发后期或者量产阶段优先用这种方式。第三种是SPI Flash直接启动把内核镜像和设备树也烧进SPI FlashU-Boot用sf read命令读到内存后启动。优点是启动介质单一缺点是Flash容量有限存储大内核镜像比较吃力。我开发阶段的习惯是网络启动为主、存储介质启动为辅。网络启动快速迭代到驱动全部稳定后再把最终镜像落到eMMC或SATA上验证一遍部署流程。6.2 环境变量与启动参数直接影响内核能否正常起来U-Boot的环境变量里最关键的就是bootcmd和bootargs。bootcmd是自动启动时要执行的命令序列。一个典型的网络启动bootcmd类似setenv bootcmd dhcp 0x90000000 tftp-path/Image; dhcp 0x90080000 tftp-path/phytium-d2000.dtb; booti 0x90000000 - 0x90080000booti是ARM64平台使用的引导命令后面依次是内核镜像地址、ramdisk地址没有就写“-”、设备树地址。注意不能沿用32位平台的bootzD2000是64位ARM必须使用booti。bootargs是传给内核的命令行参数。基础配置至少包含setenv bootargs consolettyS0,115200 root/dev/nfs rw nfsroot192.168.1.100:/srv/nfs/rootfs ipdhcp这里consolettyS0要和你设备树里stdout-path指向的串口一致root指明根文件系统位置ipdhcp让内核自己获取IP。如果内核早期日志丢失可以在bootargs里临时加earlycon参数这样内核在标准串口驱动注册前就能输出早期启动信息对定位“内核启动卡死”非常有效。6.3 内核镜像与设备树匹配性常见的启动异常源头ARM64内核通常编译成Image格式U-Boot只能引导Image、uImage或FIT格式。如果手头拿到的是zImage格式飞腾D2000上基本无法直接引导。检查方法是file命令看镜像格式或者直接按名字识别ARM64的Image是一个没有额外头信息的普通ELF或原始二进制zImage是给32位ARM压缩内核用的。设备树匹配也很重要设备树必须和实际硬件匹配而且最好和内核源码编译时代保持同源。内核、U-Boot、设备树三者版本相差过大时经常出现外设无中断、串口没输出、网卡枚举不到这些奇怪现象。一个非常常见的错误提示是ERROR: Did not find a cmdline Flattened Device Tree这通常意味着booti命令中的设备树地址传成了0或者地址无效。另一个常见错误是Machine model: N/A说明设备树的model字段没有正确设置或者dtb内容不完整。6.4 引导阶段三类经典失败日志与对策我把这个阶段出现最多的问题整理成了表格方便遇到时对照排查。失败现象直接原因快速对策串口有earlycon日志但console没输出console参数与设备树串口节点不匹配核对bootargs consolettySx与dts的uart别名必要时先去掉earlyconTFTP加载内核后“Invalid image format”内核镜像不是ARM64 Image或镜像损坏用file检查镜像格式确认使用booti且加载的是Image内核启动后“VFS: Unable to mount root fs”root参数错误或根文件系统驱动未编入内核先用NFS或initramfs验证内核可用性再检查存储驱动启动卡在中途无任何报错设备树与内核不匹配或外设时钟配置错误打开earlycon缩小到具体驱动初始化阶段优先查串口、时钟、Cache相关节点我这次在“根文件系统挂载失败”上栽了一次原因是eMMC的mmcblk编号和我bootargs里写的root/dev/mmcblk0p2对不上。这种问题在eMMC、SD、SATA设备同时存在时尤其容易出现。解决方法是启动后先进入U-Boot命令行用mmc list、part list mmc 0查看设备枚举顺序和分区编号再回头修正bootargs不要瞎猜。7. 踩坑记录与效率提升心得7.1 开发阶段用网络引导能省一半时间我刚上手那几天一直在重复“改设备树→编译→烧写Flash→重启看日志”的循环每次烧写拆装Flash夹子都费不少时间。后来改成网络引导把Image和dtb放在宿主机的tftp目录下U-Boot里敲几条命令直接下载启动整个迭代周期从十几分钟缩短到一两分钟效率提升非常明显。网络引导也方便回滚编译出错或者内核panic了只要在主机上替换文件重新启动板卡再加载一次就行。Flash烧写的频率降到最低也减少了SPI Flash被反复擦写造成损坏的风险。7.2 U-Boot命令行里几个顺手到不行的调试命令U-Boot本身自带完善的调试命令很多问题在命令行里就能定位不用反复修改代码。查看内存内容用md修改内存用mm或mw。启动异常时可以先用md直接看DDR里内核镜像位置的头部字节确认内存内容是否被正确加载。检查网络PHY状态用mii info和mii dump能看到PHY的link状态、速率、双工模式网络不通时非常有用。查询环境变量用printenv修改用setenv保存用saveenv。还有一个很实用的小技巧在bootcmd里临时加入bootargs打印或者在uboot源码中打开CONFIG_CMD_BOOTI等调试选项能够把U-Boot跳转内核时的寄存器值和参数完整打印出来对定位“为什么Linux异常”帮助极大。7.3 把这次移植经验迁移到其他ARM64平台的思路D2000的U-Boot移植和树莓派、RK3588、ST、NXP等ARM64平台在整体框架上是一致的拿到BSP、配置工具链、理解SoC启动顺序、修改defconfig和设备树、编译烧录、看串口日志、配启动参数。硬件细节不同但排查思维几乎可以复用。有三点经验在任何平台都成立一是尊重BootROM阶段先解决“能不能找到U-Boot”的问题再谈“U-Boot完不完善”二是设备树是硬件和软件之间的契约任何硬件差异都要先在设备树里对齐而不是急着改驱动代码三是调试信息永远是最重要的线索U-Boot的DEBUG宏、内核的earlycon、动态调试开关每一层都能再挖出更多细节。我还额外验证了一下同样的方法同样适用于把U-Boot从开源社区分支移植到D2000上只不过要重新确认DDR初始化代码、串口驱动、GMAC驱动这三个最容易和官方BSP不一致的部分。只要先做到能进命令行后面所有功能验证都有了下手点。移植工作做到这一步回头看最有价值的不是那几行编译命令而是对整个启动链路和调试方法论的理解。每次遇到“为什么没输出”这类问题顺着BootROM→U-Boot→DDR→驱动→内核这条链条逐层排查基本都能找到病灶所在。如果让我给刚开始做D2000移植的朋友一个建议我会说先花半天时间认真读一遍原理图和启动流程文档再动手编译调试这半天投入的回报率远比想象中高。
返回列表