调试SOC系统时候,在uboot下面烧写kernel到flash, 然后run bootcmd, 系统卡死在Starting kernel ...
做了如下排查验证,
1. 检查了 内核机器码,和uboot 机器码,都是一致,且我们的代码里面校验宏没有打开,不会校验机器码
2. 通过tftp把内核传到ram, run ramboot(bootz kernel dtb), 系统还是卡死
3. 打开内核调试开关 , Kernel hacking -> Kernel low-level debugging functions , 烧写内核,卡死,打印如下
Starting kernel ...
Uncompressing Linux...done, booting the kernel
4. 确认nand flash擦写成功, 在uboot环境, 烧写preloader,uboot,boot可正常启动,烧写内核卡死
5. 确认FPGA影响, 在开发板,uboot环境,擦除fpga镜像,boot启动内核,发现内核卡死,然后在开发板上烧写fpga镜像,内核可正常启动
6. 于是在新板子上面,先烧写fpga镜像,在烧写kernel, boot启动内核,发现内核卡死, 做了一个空的fpga镜像,和arm完全没有交互的,烧写fpga镜像,
再烧写kernel, boot启动内核,内核依旧卡死
7.用开发板的开发工程,修改硬件,和新板子一样,生成fpga镜像,烧写flash, boot启动内核,发现启动成功
最后对比开发板和新板的工程,发现fpga镜像没有问题,怀疑是dtb出了问题,对比dts文件,发现dts文件里面写了一些fpga例化出来的设备,内核的menuconfig
也打开了对应的驱动开关,而实际的硬件是没有这些设备的。
这个问题导致了内核在start_kernel 在 解析dts文件是出了错误,出现了死锁,从而内核挂起,由于在console_init之前内核卡死,所以整个start_kernel的打印都看不到。删掉驱动dts文件对应的几行,烧写dtb, zImage, 文件系统,boot启动,系统可以正常启动,进入shell.
开始很是不解:
1. 为何内核在Uncompressing Linux...done, booting the kernel之后,一行打印也没有,在start_kernel函数第一行加打印,也打印不出来
如上面所说,内核在console_init之前内核卡死,所以整个start_kernel的打印都看不到.
在start_kernel()中会调用console_init(),用来对控制台初始化,这个函数执行完成后,串口可以看到内核用printk()函数打印的信息
这里还有个问题就是,在console_ini()之前用printk()也能打印出来,这个因为,如果没有注册console,printk只是将信息放到缓冲区中 ,
console_init->con_init->register_console,在register_console时输出缓冲区中暂存的信息。
2. dts解析,驱动注册处理,为什么把内核卡死,而不是complain 错误
正确的做法应该是执行时候报错,比如板子没有rtc芯片,SPI芯片,驱动和dts里面都有对应代码,板子依旧可以正常启动,但是报错probe错误。
在我们调试的过程中出现卡死,是因为相应的驱动代码没有写好,驱动代码里面在访问的设备不存在时候,出现了死锁
这个问题的根本原因还是,驱动代码没有写好。
因此,在embedded的调试中,如果在console的初始化之前系统出了问题,不会有任何的输出。唯一可以使用的只能是led或jtag了。
阅读(10291) | 评论(0) | 转发(0) |