Chinaunix首页 | 论坛 | 博客
  • 博客访问: 153996
  • 博文数量: 49
  • 博客积分: 45
  • 博客等级: 民兵
  • 技术积分: 545
  • 用 户 组: 普通用户
  • 注册时间: 2012-07-23 13:22
文章分类
文章存档

2017年(5)

2016年(18)

2015年(18)

2014年(8)

我的朋友

分类: 嵌入式

2014-02-23 13:48:22

8974 启动之初死在kernel里面的问题

现象: 

机器开机,起不来,串口log打印如下就没有了:

[1210] Updating device tree: done
[1220] booting linux @ 0x8000, ramdisk @ 0x2000000 (468121), tags/device tree @ 0x1e00000
Uncompressing Linux... done, booting the kernel.

分析:

1,有可能是kernel启动地址不对

2, 有可能是devices tree 不匹配

3,有可能是machine ID 不对 或者是processor ID 不对

4, 如果可以跑到start_kernel 表示以上假设都不成立

5,某些驱动的初始化出了问题

解决步骤:

首先,我们用T32 跟踪代码,打断点可以到start_kernel ,说明前面三点都不成立

其次,我们用T32一步步跟,可以跑到cpu_idle ,以为是内核初始化都跑完了,顿时无语了。

第三,其实可以跑到cpu_idle 并不表示内核初始化都跑完了,跑cpu_idle 的是进程0 ,在此之前已经在rest_init函数里面开了进程1 ,kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);

第四步,在进程1中会进行外设的初始化,代码如下:

do_basic_setup 中会先后调用driver_init初始化驱动模型 do_initcalls 初始化各种级别的外设驱动  

解决问题:

通过T32跟踪,我们可以确认,机器是跑在这一步do_initcalls 初始化某些驱动代码的时候挂掉了,但是具体是哪一个呢?用T32就不好跟了。

在上一步中提到各种级别的外设驱动初始化,这一点是解决这个问题的关键,因为截至到目前我们只能用T32来跟踪代码,要定位问题非常费力,如果有串口那就好了!但是没有,怎么办?

我们都知道外设驱动都是有级别的,代码如下:

static void __init do_initcalls(void)

{

int level;

for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)

do_initcall_level(level);

}

根据level级别来初始化驱动,串口的也在其中,如果我们把串口的初始化级别提高到最先初始化,那么串口log 就可以出来了。

打印出串口log 后,可以看到死机是内核panic引起的,引起panic的打印是:

L2 master port error detected

调查发现,在代码Cache_erp.c (arch\arm\mach-msm )中,有规定一旦出现该错误立即panic。

那么,为了让机器先起来,我们可以先把这个panic的判断规避掉,以后再来调查为什么会有L2 的error。

如此在代码中做如下修改即可:


#ifdef CONFIG_MSM_L2_ERP_PORT_PANIC 
#define ERP_PORT_ERR(a) panic(a) // 把这句改成ERP_PORT_ERR(a) WARN(1, a) 


阅读(2272) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~