Linux 内核移植之 BSP

2016-1-13 chenhui 移植

本文通过 S3C2440 的 BSP 的部分实现来介绍 Linux 内核移植的 BSP 部分,S3C2440 是 ARM 初学者大多会经历的一个芯片,所以通过他来学习是比较好的 。


U-Boot 在启动内核时,会传入几个参数,其中一个是存放在 R1 寄存器的 " 机器代码 ",这个机器代码非常重要,他告诉内核当前主板应该使用哪个 BSP。Linux 启动后(汇编),会在系统中寻找两个对象,代码如下:


bl	__lookup_processor_type		
//检查与自身处理器一致的处理器信息
movs	r10, r5					
beq	__error_p					
//未找到,错误提示一个p
bl	__lookup_machine_type		
//检查与自身机器一致的机器信息
movs	r8, r5			
beq	__error_a					
//未找到,就错误提示一个a


这两个对象,一个用来描述处理器也就是 S3C2440 的处理器的信息,使用存放在 .proc.info.init 段的 proc_info_list 结构体描述另一个用来描述当前 Linux 运行的主板的信息,使用存放在 .arch.info.init 段的 struct machine_desc 结构体描述


__lookup_machine_type 就是根据存放在 R1 寄存器里的机器代码从 .arch.info.init 段中找到一个相对应的 machine_desc 对象。具体代码就不贴了,就是遍历 .arch.info.init 段然后拿 R1 和存放在 machine_desc 对象里的机器代码值相比较,一致就表示成功。

下面是 struct machine_desc 的定义:


struct machine_desc {
	
	/* 机器代码	*/
	unsigned int		nr;				
	/* ram开始物理地址	*/	
	unsigned int		phys_io;			
	/* io内存页表偏移值 */
	unsigned int		io_pg_offst;		
	
	/* 主板名	*/
	const char			*name;				
	/* 启动参数地址	*/
	unsigned long		boot_params;		

	unsigned int		video_start;		 
	unsigned int		video_end;			 

	unsigned int		reserve_lp0 :1;	
	unsigned int		reserve_lp1 :1;	
	unsigned int		reserve_lp2 :1;		
	unsigned int		soft_reboot :1;	
	void				(*fixup)(struct machine_desc *,
						 struct tag *, char **,
						 struct meminfo *);
	/* 映射所有外设 */
	void				(*map_io)(void);	
	/* 初始化中断 */
	void				(*init_irq)(void);
	/* 时钟初始化 */
	struct sys_timer	*timer;				
	/* 一般注册了一些平台设备和电源初始化 */
	void				(*init_machine)(void);
};


这个结构体是 BSP 的核心结构体,他非常重要。

如果我们要定义一个 machine_desc 对象,那么可以使用 MACHINE_START 宏,MACHINE_START 宏的定义如下:


#define MACHINE_START(_type,_name)			\
static const struct machine_desc __mach_desc_##_type	\
 __used							\
 __attribute__((__section__(".arch.info.init"))) = {	\
	.nr		= _type,		\
	.name		= _name,

#define MACHINE_END				\
};


我们可以发现,当我们使用 MACHINE_START() 来定义一个 machine_desc 对象时,他会自动把这个对象放在 .arch.info.init 段里方便查找。

_type 这个参数是机器代码,_name 是主板名。


我们为了分析 S3C2440 的 BSP,就必须查看他是怎么定义这个 machine_desc,在源代码中一番查找后,我们能找到如下定义:


MACHINE_START(SMDK2410, "MINI2440")
     MAINTAINER("Jonas Dietsche")
     BOOT_MEM(S3C2410_SDRAM_PA, S3C2410_PA_UART, S3C2410_VA_UART)
     BOOT_PARAMS(S3C2410_SDRAM_PA + 0x100)
     MAPIO(smdk2410_map_io)
     INITIRQ(smdk2410_init_irq)
	.timer		= &s3c24xx_timer,
MACHINE_END


上面这个 machine_desc 是 MINI2440 这块开发板的 machine_desc 的定义,他展开后的定义如下:


static const struct machine_desc __mach_desc_361	
	__used	__attribute__((__section__(".arch.info.init"))) = {	
	
	.nr	  = 361,		
	.name = "MINI2440",
	
	.phys_ram	= 0x30000000,		
	.phys_io	= 0x50000000,			
	.io_pg_offst	= ((0x50000000)>>18)&0xfffc,
	
	.param_offset	= 0x30000100,
	
	.map_io		= smdk2410_map_io,
	
	.init_irq	= smdk2410_init_irq,
	
	.timer		= &s3c24xx_timer,
	
#define MACHINE_END				
};


这个对象会在什么时候被用到呢?答案是 start_kernel() 调用的 setup_arch(),关于这个 setup_arch(),可以查看:Linux 的启动过程详解(C部分)


setup_arch() 会调用 paging_init(),paging_init() 又会调用 devicemaps_init() 来映射所有外设,就在这里,调用了 machine_desc 对象里最重要的函数:map_io。


对于 2440 来说,如上所示,map_io() 这个函数指针指向了 smdk2410_map_io(),其实现如下:


void __init smdk2410_map_io(void)
{
    //映射外设
    s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc)); 
    //初始化时钟,参数就是晶振的频率,若我们的是12M,那他就是12000000。若串口输出乱码,就是这里出问题。
    s3c24xx_init_clocks(0);
    //初始化串口,如果串口无法输出信息,就是这里出了问题
    s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs)); 
    //初始化单板
    s3c24xx_set_board(&smdk2410_board); 
}


关于更深入的实现,就设计到硬件操作,这里就不多说了。大家只需要了解 map_io() 究竟干了些什么事就可以了。



评论:

STEWGrag
2018-07-03 08:11
There are different ways to fry tomatoes, but each of them will require the hostess to spend several hours in the kitchen, so this dish is usually better correct  prepare on weekends or for special occasions. When tomatoes are roasted, they get a deep taste and are combined with seafood, antipasto and other roasted vegetables. Moreover, they are perfectly suitable for application in the baking industry, in making bread or cake with custard.
<a href=http://stewedtomatoes.top/how-to-cook-sweet-stewed-tomatoes-at-home>http://stewedtomatoes.top/how-to-cook-sweet-stewed-tomatoes-at-home</a>

发表评论:

Copyright ©2015-2016 freehui All rights reserved