Chinaunix首页 | 论坛 | 博客
  • 博客访问: 581134
  • 博文数量: 70
  • 博客积分: 3736
  • 博客等级: 中校
  • 技术积分: 1728
  • 用 户 组: 普通用户
  • 注册时间: 2008-07-08 09:15
文章分类
文章存档

2014年(1)

2012年(21)

2011年(7)

2010年(28)

2009年(13)

分类: LINUX

2009-11-25 21:11:30

今天研究init/main.c文件中的代码,发现了一个问题:
本来我的代码是ok的,我的linux内核在开发版上是可以正常起来的。我将init/main.c文件里start_kernel()函数里边的console_init()函数注释掉,大家猜怎么样?居然还可以启动!查看console_init()函数的代码,实现在drivers/char/tty_io.c文件里边,核心代码如下:
initcall_t *call;
call = __con_initcall_start;/*zswan*/
while (call < __con_initcall_end) {
(*call)();
call++;
}
注:
__con_initcall_start和__con_initcall_end的虚拟地址arch/arm/kernel/vmlinux.lds.S文件里定义.这段代码其实就是去执行在 __con_initcall_start和__con_initcall_end之间的initcall_t,而这个虚拟地址范围里边的initcall_t是什么怎么添加进来的呢?通过console_init()函数!你调用了几次console_init(),那么此处(*call)()就调用几次.大家可以看到,我们的console驱动程序就是通过console_init()函数而非module_init()来注册的.所以说整个console_init函数的作用就是初始化系统中注册的所有的console口驱动.
但为什么我把console_init()注释掉以后,内核还能起来呢?希望知道的朋友可以告诉我.
另外,即使此处调用了console_init(),假如把后边的do_basic_setup()函数注释掉,那么内核也是启不来的.
不知道这又是何原因?
革命尚未成功,同志还需努力.

今天为了测试,将以下代码放在了rest_init()的前面(reset_init()为start_kernel()所执行的最后一个函数)。按我的理解来说,执行到rest_init的前面,系统体系相关的初始化已经完成了,应该可以使用ioremap了,但是依然出错。加了如下代码以后,系统刮起在Uncompressing Linux.......................阶段),所加代码如下:
/*这短代码的功能是驱动buzzer,其实很简单,就是写寄存器*/
    void *paddr;
    paddr = ioremap(0x51000000, 0x10);
    if (!paddr) {
        printk(KERN_ERR "Buzzer: Failed to ioremap region\n");
    }
    paddr += 2;
    *((u8 volatile *)paddr) = 0x8;
只有将此段代码加在do_initcalls()函数的最后执行才可以,靠前放则不可以执行。因为do_initcalls()所完成的是对驱动部分的初始化工作。感觉buzzer依赖于某个驱动,所以,放在do_initcalls的最后,当其他驱动初始化完成以后,它才可以工作。但不太清楚它需要依赖哪个驱动?最有可能的就是ioremap可能需要某个东东初始化以后才可以用(例如,内存初始化?),但是内存的初始化早在rest_init以前就应该完成了阿。
不知道这又是何原因?
革命尚未成功,同志还需努力.

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