MACHINE_START与MACHINE_END

来源:互联网 发布:万能票据软件 编辑:程序博客网 时间:2024/05/16 08:59
 

注:Linux2.6.29

在移植Linux时,有个结构体需要填写,它以MACHINE_START开始并以MACHINE_END结束,如下mini2440开发板的移植为示例

MACHINE_START(MINI2440, "Mini2440 ")

       .phys_io  = S3C2410_PA_UART,

       .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,

       .boot_params  = S3C2410_SDRAM_PA + 0x100,

 

       .init_irq   = s3c24xx_init_irq,

       .map_io          = mini2440_map_io,

       .init_machine  = mini2440_machine_init,

       .timer             = &s3c24xx_timer,

MACHINE_END

其中MACHINE_START、MACHINE_END都是定义的宏,代码如下

#define MACHINE_START(_type,_name)                 \

static const struct machine_desc __mach_desc_##_type       \

 __used                                             \

 __attribute__((__section__(".arch.info.init"))) = {    \

       .nr          = MACH_TYPE_##_type,           \

       .name             = _name,

 

#define MACHINE_END                          \

};

由上代码可知这两个宏一起定义了一个类型为struct machine_desc的变量,结构体定义如下

struct machine_desc {

       /*

        * Note! The first four elements are used

        * by assembler code in head.S, head-common.S

        */

       unsigned int           nr;          /* architecture number   */

       unsigned int           phys_io;  /* start of physical io     */

       unsigned int           io_pg_offst;    /* byte offset for io

                                           * page tabe entry  */

 

       const char              *name;           /* architecture name      */

       unsigned long        boot_params;  /* tagged list          */

 

       unsigned int           video_start;     /* start of video RAM    */

       unsigned int           video_end;      /* end of video RAM     */

 

       unsigned int           reserve_lp0 :1;       /* never has lp0      */

       unsigned int           reserve_lp1 :1;       /* never has lp1      */

       unsigned int           reserve_lp2 :1;       /* never has lp2      */

       unsigned int           soft_reboot :1;       /* soft reboot         */

       void               (*fixup)(struct machine_desc *,

                                    struct tag *, char **,

                                    struct meminfo *);

       void               (*map_io)(void);/* IO mapping function     */

       void               (*init_irq)(void);

       struct sys_timer      *timer;           /* system tick timer       */

       void               (*init_machine)(void);

};

这个类型的变量放在内核代码段.arch.info.init中,在内核运行初期,被函数lookup_machine_type(此函数用汇编实现,在汇编文件中)取出,读取流程为

Start_kernel()àsetup_arch()àsetup_machine()àlookup_machine_type()

在函数setup_machine()中,利用这个结构体类型的变量初始化一些全局变量,以备内核运行时使用,比如

init_arch_irq = mdesc->init_irq;

       system_timer = mdesc->timer;

       init_machine = mdesc->init_machine;

 

这个结构体中,成员init_machine保存的是开发板资源注册的初始化代码,init_irq保存的是中断初始化指针,timer保存的是一个struct sys_timer类型的指针…..如果我们要给自己的开发板定制内核,那么我们必须自己实现以上成员函数,其中函数init_machine()是我们向内核传递开发板设备信息的重要的常规途径,分析mini2440开发板内核移植代码知道,在这个函数中,注册了开发板所用到的所有设备的相关硬件信息!!如下所示:

Usb(USB host)、rtc(real time clock)、lcd、wdt(watch dog)、i2c、iis、dm9k(DM9000)、cs8900、uda134x、nand、sdi、usbgadget(USB device)

那么成员函数init_machine什么时候被调用呢?

在函数setup_machine()中有一条语句init_machine = mdesc->init_machine;其中init_machine为全局函数指针变量,此变量在函数customize_machine()中被调用,代码如下所示:

static int __init customize_machine(void)

{

       /* customizes platform devices, or adds new ones */

       if (init_machine)

              init_machine();

       return 0;

}

arch_initcall(customize_machine);

还记得arch_initcall吗?没忘记的话,关于他,现在啥都不用说了~~~~

 

在MACHINE_START与MACHINE_END之间还要填写一些参数,参照结构体注释小心填写即可,最好找个例子参考参考。