u-boot移植随笔(10):解决引导内核遇到undefined instruction的错误 | 迟思堂工作室
当前位置: 首页 > U-Boot随笔 > 正文

u-boot移植随笔(10):解决引导内核遇到undefined instruction的错误

前天解决了内核不能引导的问题了。在网上搜索了一些资料,才有点明白这个是怎么回事。
不能引导内核时提示的信息各种各样。像ERROR: can’t get kernel image!、Bad Magic Number、 Bad Data CRC这些。这些有时出现,有时又不出现,很是诡异。
不过最严重的还是遇到undefined instruction的错误。经典地,一般启动过程如下:

LATE2440 $ bootm 30008000
## Booting kernel from Legacy Image at 30008000 …
Image Name: linux-2.6.30.2
Created: 2011-03-05 15:40:19 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1979780 Bytes = 1.9 MiB
Load Address: 30008000
Entry Point: 30008000
Verifying Checksum … OK
XIP Kernel Image … OK
OK
Starting kernel …
undefined instruction
pc : [<3000801c>] lr : [<33f95030>]
sp : 33f4fb60 ip : 000000ff fp : 00000000
r10: 00000000 r9 : 33edc6d0 r8 : 33f4ffe0
r7 : 30008000 r6 : 33f4ffc4 r5 : fffff200 r4 : 000003f0
r3 : 00000000 r2 : 30000100 r1 : ea000012 r0 : 33f98305
Flags: nzCv IRQs off FIQs off Mode SVC_32
Resetting CPU …
resetting …

遇到了undefined instruction问题。后来在网上找到一篇文章,说要将制作uImage的参数改一改,即入口地址(entry point)要比加载地址(load address)多加0x40个字节。于是我在使用mkimage时的参数改成如下:
mkimage -n ‘linux-2.6.30.2′ -A arm -O linux -T kernel -C none -a 0x30007fc0 -e 0x30008000 -d zImage uImage
因为内核期望的入口地址为0x30008000,所以将加载地址向前减去0x40个字节,变成0x30007fc0(0x30008000-0x40=0x30007fc0)。结果可以成功引导。我找到这篇文章:

http://blog.csdn.net/liangkaiming/archive/2010/11/04/5986680.aspx

里面讲到两种方式。当内核加载地址与入口地址一样时,如果使用tftp或cp命令下载/复制到内存的0x30008000,再使用bootm启动,是不能成功的,事实上,前面的例子就是这样的。
我又将加载地址和入口地址修改为一样的,但是,uImage在内存的地址却不是0x30008000,再使用bootm,亦可以。

LATE2440 $ bootm
## Booting kernel from Legacy Image at 33000000 …
Image Name: linux-2.6.30.2
Created: 2011-03-05 15:40:19 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1979780 Bytes = 1.9 MiB
Load Address: 30008000
Entry Point: 30008000
Verifying Checksum … OK
Loading Kernel Image … OK
OK
Starting kernel …
Uncompressing Linux……………………………………………………………………………………………………………. done, booting the kernel.

在cmd_bootm.c中定义DEBUG宏时的输出(加载uImage到内存的地址与前面的不同,但是却不为0x30008000):

* kernel: cmdline image address = 0x30007fc0
## Booting kernel from Legacy Image at 30007fc0 …
Image Name: linux-2.6.30.2
Created: 2011-03-05 15:40:19 UTC
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 1979780 Bytes = 1.9 MiB
Load Address: 30008000
Entry Point: 30008000
Verifying Checksum … OK
kernel data at 0x30008000, len = 0x001e3584 (1979780)
Loading Kernel Image … OK
OK
kernel loaded at 0x30008000, end = 0x301eb584
images.os.start = 0x30007FC0, images.os.end = 0x301eb584
images.os.load = 0x30008000, load_end = 0x301eb584
Starting kernel …
Uncompressing Linux……………………………………………………………………………………………………………. done, booting the kernel.

这里得出一个结论:
1、当bootm的参数为0x30008000时,uImage的加载地址与入口地址需要相差0x40个字节。
2、当uImage加载地址与入口地址均为0x30008000时,bootm的参数可以是除0x30008000以外的地址(实际上,这个地址却不是“任意”的)。
注:bootm addr是启动位于addr处的内核uImage,这个内核可以使用tftp从主机中下载,也可以使用cp命令从nor flash中复制,事实上,本文所作实验就是使用cp命令的。
PS:今天日期减去2等于u-boot引导内核出现的日期。

                                                                                                                                      木草山人于3.07记

本文固定链接: /porting-uboot/u-boot-porting-booting-kernel.html

目前暂无评论

发表评论

快捷键:Ctrl+Enter