做嵌入式Linux移植,最常见也最郁闷的问题,就是自己新做的内核镜像,还没有神马把握,,就要忐忑不安地烧到板子上去测试。这个时候,我宁愿它突出一堆oops,甚至panic,心里觉得舒坦些。可是它要啥都不吐,那就抓瞎了。
这种情况,就是printk缓冲区的信息准备好了,但是串口console初始化失败或者还没执行,printk内存缓冲区吐不出来造成的。
一般内核开启会打印Linux version 2.6.xx (gcc version 4.2.2) #47 PREEMPT 这样的linux_banner信息。
见2.3.34.1,start_kernel 函数
printk(
KERN_NOTICE "%s"
,
linux_banner)
;
setup_arch(
&
command_line)
;
可以看到,这里是先printk,再setup_arch的。
我这里是powerpc的板子,很可能由于dts的配置导致板子不能识别或串口配置错误等,导致内核连个屁都吐不出来。
而检查dts的内容,是在setup_arch里进行的啊。我就不服气了,凭什么要因为后面函数的原因,导致我前面的printk出不来。
内核早期输出工具early_printk不是所有平台都能用。powerpc特有的早期调试机制,我尝试了半天也没成功。
使用ppc_md.progress ,貌似可以实现powrpc下的早期输出。但是ppc_md.progress的初始化,可是在
void __init chrp_setup_arch(void)
{
...
rtas_initialize();
if (rtas_token("display-character") >= 0)
ppc_md.progress = rtas_progress;
...
}
这里才被初始化的,此时start_kernel 我觉得早就开始执行了。也就是说第一个printk已经使用过,
ppc_md.progress的初始化才开始。
这里,我从Embedded Linux primer上汲取力量,得到一种强大的软件调试手段,让printk的东西吐出来。
前提条件:
1、板子有热重启键,或者其他热重启机制(Linux异常重启,默认时间180秒),或者使用仿真器重启。不过既然有仿真器,那就不用往下看了。
2、执行到了start_kernel 中printk(KERN_NOTICE "%s", linux_banner);这一步内核尚未异常。
3、拥有能够查看内存的bootloader,如 uboot或其前身ppcboot 的md命令。
查看内核的System.map文件,__log_buf这个符号的虚拟地址,如我这里
c032cf48 b __log_buf
将内核虚拟地址转换成物理内存地址很简单,因为大多数嵌入式平台不会使用984M以上的内存,内核虚拟地址仅仅是物理地址的一个线性偏移而已。
我的物理内存基址是0,所以物理内存地址很可能是0x0032cf48
boot内核,等待一会,然后热重启。其实内存上的信息还热乎着呢,马上使用uboot查看
=> md 32cf48
cmdtp 1ffc9b1c ,flag 0 ,argc 2,argv[0] md ,argv[1] 32cf48
0032cf48: 3c363e55 73696e67 204d5043 38333778 <6>Using MPC837x
0032cf58: 20524442 2f574c41 4e206d61 6368696e RDB/WLAN machin
0032cf68: 65206465 73637269 7074696f 6e0a3c35 e description.<5
0032cf78: 3e4c696e 75782076 65727369 6f6e2032 >Linux version 2
0032cf88: 2e362e33 342e3120 28787940 626e632d .6.34.1 (xy@bnc-
0032cf98: 79687029 20286763 63207665 7273696f yhp) (gcc versio
0032cfa8: 6e20342e 322e3320 28536f75 72636572 n 4.2.3 (Sourcer
0032cfb8: 7920472b 2b204c69 74652034 2e322d31 y G++ Lite 4.2-1
0032cfc8: 37312929 20233530 2053756e 204f6374 71)) #50 Sun Oct
0032cfd8: 20313020 32333a35 353a3239 20504454 10 23:55:29 PDT
0032cfe8: 20323031 300a3c37 3e466f75 6e64206c 2010.<7>Found l
0032cff8: 65676163 79207365 7269616c 20706f72 egacy serial por
0032d008: 74203020 666f7220 2f696d6d 72406530 t 0 for /immr@e0
0032d018: 30303030 30302f73 65726961 6c403435 000000/serial@45
0032d028: 30300a3c 373e2020 6d656d3d 65303030 00.<7> mem=e000
0032d038: 34353030 2c207461 6464723d 65303030 4500, taddr=e000
虽然条件艰苦了点,总比没有强啊。怎么也比点灯调试爽多了。
此方法非常imba,山穷水尽的时候可以一试。
同样适用于arm,之前测试过。
当然,最好能有仿真器。