Linux内核版本:
VERSION = 3 PATCHLEVEL = 0 SUBLEVEL = 53
Linux内核编译完成后会形成zImage内核文件,下载到开发板的处理器上面运行。
由Bootloader将内核镜像拷贝到ram中运行,通过call_linux(0, machine_type, kernel_params_base)。
其中,machine_tpye 是Bootloader检测出来的处理器类型, kernel_params_base 是启动参数在 RAM 的地址。通过这种方式将 Linux 启动需要的参数从 bootloader传递到内核。
对于ARM 系列处理器来说,zImage 的入口程序即为 arch/arm/boot/compressed/head.S。它依次完成以下工作:开启 MMU 和Cache,调用 decompress_kernel()解压内核,最后通过调用 call_kernel()进入非压缩内核 Image 的启动。
最重要的内核启动函数是start_kernel()//在init/main.c中定义的。
Start_kernel(),完成内核的启动。
主要完成一些硬件的初始化,一系列的与内核相关的初始化,调用用户的第一个进程“init”,并等待用户的进程执行,整个Linux内核启动完成。调用setup_arch()是其中的一个工作。
Setup_arch(),是与体系结构相关的函数,通过查找Linux下面arch目录下的文件我们会找到我们的bsp文件。那么就可以将我们的bsp文件的“去处”找到了。
掉过头来看一下bsp文件。以smdk-2440.c为例。
Bsp文件是为了创建一个machine_desc关于开发板的结构体,然后添加到.arch.info.init的段中,作为内核启动的初始化数据。machine_desc关于开发板的结构体然后到了setup_arch()中被“瓜分”,被赋值到相应的结构体中,在系统启动时,不同的函数调用。machine_desc关于开发板的结构体,创建过程参见代码。
MACHINE_START(S3C2440,"SMDK2440")
/* Maintainer: Ben Dooks<ben-linux@fluff.org> */
.boot_params = S3C2410_SDRAM_PA + 0x100,
.init_irq = s3c24xx_init_irq,
.map_io =smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer =&s3c24xx_timer,
MACHINE_END
(在bsp文件中定义)
struct machine_desc {
unsigned int nr; /* architecture number */
const char *name; /* architecture name */
unsigned long boot_params; /* tagged list */
const char **dt_compat; /* array of device tree
* 'compatible' strings */
unsigned int nr_irqs; /* number of IRQs */
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 (*reserve)(void);/*reserve mem blocks */
void (*map_io)(void);/*IO mapping function */
void (*init_early)(void);
void (*init_irq)(void);
struct sys_timer *timer; /* system tick timer */
void (*init_machine)(void);
#ifdefCONFIG_MULTI_IRQ_HANDLER
void (*handle_irq)(structpt_regs *);
#endif
};
#defineMACHINE_START(_type,_name) \
staticconst struct machine_desc __mach_desc_##_type \
__used \
__attribute__((__section__(".arch.info.init")))= { \
.nr =MACH_TYPE_##_type, \
.name =_name,
#defineMACHINE_END \
};
(在arch.h文件中定义)
Linux 内核对每种支持的开发板都会使用宏MACHINE_START,MACHINE_END来定义一个machine_desc结构。
Machine_desc存储与开发板相关的信息:开发板的机器类型号(mach_type),开发板的名称(machine_is_),其实io物理地址,内核启动参数的地址(.boot_params),中断初始化函数,io映射函数等。