首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Zedboard-解决经验之外问题要向侦探学习

Zedboard-解决经验之外问题要向侦探学习

1、出现错误:
U-boot向zynq上引导linux系统时出现的错误:
reading uImage
** Unable to read "uImage" from mmc 0:1 **
reading devicetree.dtb
7284 bytes read
reading uramdisk.image.gz
** Unable to read " uramdisk.image.gz " from mmc 0:1 **
由提示信息:不能读取内核镜像(文件系统镜像情况相同,只取内核镜像为例进行分析)

2、利用经验初步尝试
我们处理问题往往倾向于从已有经验开始。在之前就不只一次遇到过Xilinx要我们修改名称的,例如:将编译好的u-boot修改为u-boot.elf以在生成u-boot.bin时SDK能识别出来;将u-boot.bin修改为boot.bin以让zynq上的BOOTROM识别出来。所以我们第一想法就是将zImage重命名为uImage。

但这样做了之后这一关是过了,但接着会出现下面的问题:
Wrong Image Format for bootm command
ERROR: can't get kernel image!

说明不行,那就要重新寻找解决方案,既然我们拿zImage没办法,那就从u-boot角度去寻找解决方案。研究一下u-boot是怎么实现内核的加载的以及相关参数是怎么设置的。
3、经验范围之外尝试
u-boot源码之前我们并不熟悉,说研究但不是说拿着源码就挨个开始了,得知道从哪里下手。从哪里下手呢?从侦探那里学习由相关事物中去定位问题,顺藤摸瓜去解决问题。

定位问题
正如侦探破案首先查的肯定是和受害者最近接触的人,初步从中确定出嫌疑人,然后再逐个排除或者从中发现新的线索去顺藤摸瓜最终找出真凶。回想一下我们编译生成u-boot整个过程,我们每个阶段都做了什么?各阶段又有哪些东西和我们的工作发生了关系呢?Bootloader移植源更多的是修改配置以让它支持我们的目标平台,所以我们就从其配置文件入手(很幸运我们的想法这次是对的)。输入以下命令打开配置文件:

[wicoboy@localhost u-boot-xlnx]$ vi include/configs/zynq_common.h
在我们的配置文件中会找到如下内容:(我们选择从SD启动,所以只关心sdboot这段代码,若是以其它方式启动就修改相应代码,比如noodboot/jtagboot等等)
/*Default environment */
183 #define CONFIG_EXTRA_ENV_SETTINGS \
184 "ethaddr=00:0a:35:00:01:22\0" \
185 "kernel_image=uImage\0" \
186 "ramdisk_image=uramdisk.image.gz\0" \
187 "devicetree_image=devicetree.dtb\0" \
206 "sdboot=echo Copying Linux from SD to RAM...;" \
207 "mmcinfo;" \
208 "fatload mmc 0 0x3000000 ${kernel_image};" \
209 "fatload mmc 0 0x2A00000 ${devicetree_image};" \
210 "fatload mmc 0 0x2000000 ${ramdisk_image};" \
211 "bootm 0x3000000 0x2000000 0x2A00000\0" \

在这里就找到了uImage的来源,将其修改为zImage,保存退出,重新编译生成u-boot,通过SDK重新制作boot.bin,再次启动加载系统。会发现依然是提示:
Wrong Image Format for bootm command
ERROR: can't get kernel image!

错误的镜像格式对于bootm命令。再次返回u-boot的配置文件,就是bootm那一行命令,但不了解bootm这个命令怎么办?查资料
顺藤摸瓜
bootm : 执行内存中的二进制代码,要求二进制代码为指定格式的。使用bootm命令启动的内核必须是经过mkimage工具处理过的内核映像文件(通常名为uImage)

通过mkimage这个工具(在u-boot代码的tools目录中)可以给zImage添加一个header,也就是使得通常编译的内核zImage添加一个数据头,把添加头后的image通常叫uImage,uImage是可以被U-boot直接引导的内核镜像。
看来如果想使用这条命令就必须对内核镜像稍做修改使其成为uImage格式,由于之后还需要加载ramdisk.image.gz文件系统,同样需要利用mkimage工具修改使其成为uramdisk.image.gz格式。该工具使用可以上网搜索。
按以上思路可以解决问题,但稍微麻烦一点。U-boot是支持多种方式启动内核的:
go : 执行内存中的二进制代码,简单地跳转到指定地址,执行该地址处的代码
run:该命令可以执行设置好的脚本
bootp:通过网络启动,需要提前设置好硬件地址
kgo:启动没有压缩的Linux内核,用法同run
于是这里就取了个巧,换了个命令实现系统引导:go

4、最终解决方案:
/*Default environment */
183 #define CONFIG_EXTRA_ENV_SETTINGS \
184 "ethaddr=00:0a:35:00:01:22\0" \
185 "kernel_image=zImage\0" \
186 "ramdisk_image=ramdisk32M.image.gz\0" \
187 "devicetree_image=devicetree.dtb\0" \
206 "sdboot=echo Copying Linux from SD to RAM...;" \
207 "mmcinfo;" \
208 "fatload mmc 0 0x3000000 ${kernel_image};" \
209 "fatload mmc 0 0x2A00000 ${devicetree_image};" \
210 "fatload mmc 0 0x2000000 ${ramdisk_image};" \
211 "go 0x3000000 \0" \

5、经验总结
当我们所遇到的问题牵涉到的是我们所不熟悉的事物时。其实很多情况下问题就在我们涉及到的那一小部分,即便牵扯到一些其它的东西,只要我们顺藤摸瓜最终问题也是可以解决的。关键是我们能否把问题定位到这一小部分。

那么如何让自己能将问题定位到这部分呢?首先整理一下我们工作的整个过程,基本分为哪些阶段哪些步骤等?然后想想每个阶段或步骤又涉及到了哪些事物?什么事物最有可能导致了现在的情况?就从这些相关的事物入手。

来源:用心做技术
记录学习中的点点滴滴,让每一天过的更加有意义!
返回列表