快乐虾
http://blog.csdn.net/lights_joy/
欢迎转载,但请保留作者信息
在使用合众达DVS6467T开发板时遇到一个问题,在内核选项中加上initramfs的支持,结果在bootm时内核加载失败:
## Booting image at 8e000000 ...
Image Name: Linux-2.6.10_mvl401-davinci_evm-
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 3479208 Bytes = 3.3 MB
Load Address: 80008000
Entry Point: 80008000
Verifying Checksum ... OK
OK
Starting kernel ...
UncompressingLinux..........................................................................................................................................................done, booting the kernel.
然后就没有下文了。
这种情况其实在刚开始调试内核时经常会遇到,通常也只能通过内核功能的添加和删除来初步判断问题的位置。但我们现在有仿真器这个神器,就不再需要这么摸索了。
下面有请仿真器大神上场。
首先启动uboot并将内核tftp到板上。Bootm后出现上文所提的现象。
在 ccs 下用仿真器连接设备:很显然pc跑飞了,但此时已经无法得到更多信息了。
再来一次。
用uboot将内核tftp下载到设备上,在bootm之前用ccs连接到设备,此时ccs将在uboot的代码中中断下来:
添加两个断点:
因为0x80008000这个地址是Linux内核的入口地址。
在ccs中继续执行,uboot继续工作,我们也可以通过串口和uboot进行交互。
在串口中输入bootm,此时仿真器将在内核入口处中断下来:
通过单步执行,很容易发现程序跑飞的位置:
/*
* The following fragment of code is executedwith the MMU on, and uses
* absolute addresses; this is not positionindependent.
*
* r0 = cp#15 control register
* r1 = machine ID
* r9 = processor ID
*/
.type __mmap_switched, %function
__mmap_switched:
adr r3,__switch_data + 4
ldmia r3!,{r4, r5, r6, r7}
cmp r4,r5 @ Copy data segment if needed
1: cmpne r5,r6
ldrne fp,[r4], #4
strne fp,[r5], #4
bne 1b
mov fp,#0 @ Clear BSS (and zero fp)
1: cmp r6,r7
strcc fp,[r6],#4
bcc 1b
在这里清除BSS段时程序飞了。通过检查各寄存器的值感觉并没有什么异常,但当内核执行到这里时,可以发现mmu已经启用了,那么问题估计和这个有关了。
看看之前执行的MMU相关的一段代码:
/*
* Setup the initial page tables. We only setup the barest
* amount which are required to get the kernelrunning, which
* generally means mapping in the kernel code.
*
* r8 =machinfo
* r9 =cpuid
* r10 = procinfo
*
* Returns:
* r0,r3, r5, r6, r7 corrupted
* r4 =physical page table address
*/
.type __create_page_tables, %function
__create_page_tables:
ldr r5,[r8, #MACHINFO_PHYSRAM] @ physram
pgtbl r4,r5 @ page table address
………..
/*
* Nowsetup the pagetables for our kernel direct
*mapped region. We round TEXTADDR down tothe
*nearest megabyte boundary. It is assumedthat
* thekernel fits within 4 contigous 1MB sections.
*/
add r0,r4, #(TEXTADDR & 0xff000000)>> 18 @ start of kernel
str r3,[r0, #(TEXTADDR & 0x00f00000) >> 18]!
add r3,r3, #1 << 20
str r3,[r0, #4]! @ KERNEL + 1MB
add r3,r3, #1 << 20
str r3,[r0, #4]! @ KERNEL + 2MB
add r3,r3, #1 << 20
str r3,[r0, #4] @ KERNEL + 3MB
……
很显然这里只配置了内核代码开始的3M空间,而我们的内核在加上initramfs之后,bss段的一部分数据是处于3M之外的,这也是正是内核跑飞的原因!!
知道原因就好办了,修改下这段代码:
/*
* Nowsetup the pagetables for our kernel direct
*mapped region.
*/
add r0,r4, #(TEXTADDR & 0xff000000)>> 18
str r3,[r0, #(TEXTADDR & 0x00f00000) >> 18]!
ldr r6,=(TEXTADDR + 0x01000000 - 1)
add r0,r0, #4
add r6,r4, r6, lsr #18
1: cmp r0,r6
add r3,r3, #1 << 20
strls r3,[r0], #4
bls 1b
再编译运行,搞定!!