今天,自己又重新移植了一遍内核。感受颇多,原本已经烂熟于心的东西,忽然都不明白了。
看来,随着时间的增长,人们看东西的视角也不同。原本是本着一颗,做东西的心情,移植
成功就好,好使就行,不会太关注,为什么,怎么来的。
今天移植想的问题却又不一样了。好吧,那就详细的讨论一下吧。
看本文之前,建议,先自己好好的做一遍内核移植
http://blog.csdn.net/zhaole20094463/article/details/6882266
按照上面链接写的,试一试,否则,看这篇博客就会云里雾里了。
好吧,我们来总结一下。
在上文的移植中,我们总共修改了这样几个文件。
Makefile 添加对arm的支持
arch/arm/mach-s3c2440/mach-smdk2440.c 修改平台时钟
arch/arm/tools/mach-types 修改机器码
arch/arm/plat-s3c24xx/commond-smdk.c 移植nandflash驱动
当然 我们还忘了一个最重要的,.config
也就是这一步
cp arch/arm/configs/s3c2410_defconfig .config 复制一下对于S3C2410/2440的通用配置
我在写上面博客的时候,对移植理解还不深,就是记下了一个成功的方法。
所以把这一步放在了很后面的步骤,不过现在看来,恰恰错了。
应该把这一步放在首位。现在我们来讨论一下,为什么要放在首位。
我们在配置内核的时候,要执行make menuconfig
这个命令调用的文件便是.config。它打开了我们移植内核的配置单。
长久以来,我们都在迷惑一些问题那就是为什么我们要修改以上几个文件中的内容,为什么修改别的不行。
这些问题在.config 文件中找到了答案。
正如我以上所说,我们在移植内核的时候先要进行配置,选择配置单,也就是make menuconfig的操作。我们
先进到内核源码中看看。
arch/arm/plat-s3c24xx/commond-smdk.c 移植nandflash驱动
先说这一项,进入到arch/arm/plat-s3c2440/目录
打开该目录下面的Makefile
在最后一行查看到有这样一行代码
obj-$(CONFIG_MACH_SMDK)+= common-smdk.o
这句话的意思是:
如果CONFIG_MACH_SMDK=y的话,就编译common-smdk.c
接着我们来看.config中是如何做的
打开.config 文件(gedit .config)
在192行我们找到了如下代码
CONFIG_MACH_SMDK=y
这样我们就明白了为什么修改nandflash驱动的时候修改
arch/arm/plat-s3c24xx/commond-smdk.c就可以了。
接着我们来看看哪些选项可以选择上CONFIG_MACH_SMDK=y呢?
执行
make menuconfig
输入/ 进入查找界面
输入CONFIG_MACH_SMDK
我们找到了如下说明
Symbol: MACH_SMDK [=y] │
│ Selected by: ARCH_SMDK2410 && ARCH_S3C2410 || MACH_SMDK2413 && ARCH_S3C2410 || ARCH_S3C2440 && ARCH_S3C2410
里面指到的Selected by的选项恰恰是我们在进行s3c2410/s3c2440时候移植时,配置单的默认选项,
这样关于为什么我们修改arch/arm/plat-s3c24xx/commond-smdk.c,我们就找到答案了。
同样对于
arch/arm/mach-s3c2440/mach-smdk2440.c 修改平台时钟
我们打开以上文件中的makefile
找到了如下代码:
obj-$(CONFIG_ARCH_S3C2440)+= mach-smdk2440.o
然后我们在.config文件中搜索一下
CONFIG_ARCH_S3C2440=y
我们执行make menuconfig 查找以上选项:
得到
Symbol: ARCH_S3C2440 [=y] │
│ Prompt: SMDK2440 │
│ Defined at arch/arm/mach-s3c2440/Kconfig:57 │
│ Depends on: ARCH_S3C2410 │
│ Location: │
│ -> System Type │
│ -> S3C2440 Machines │
│ Selects: CPU_S3C2440 && MACH_SMDK
上面的选项在
-> System Type
-> S3C2440 Machines 下默认是全部选择上的。
这样关于
arch/arm/mach-s3c2440/mach-smdk2440.c 修改平台时钟
的问题也解决了。
接着来看看
arch/arm/tools/mach-types 修改机器码
这个跟.config的关系就没有以上两个那么紧密了。
首先我们要知道
u-boot的机器码和linux的一致,才能引导。
linux内核的机器码,在arch/arm/tools/mach-types.h中,u-boot的机器码是在u-boot/include/asm-arm/mach-types.h文件中,
只要两者保持一致便可,所以可以任意修改其中之一。
我们来查看一下
arch/arm/mach-s3c2440/mach-smdk2440.c的代码
在该文件 的最后,我们找到了如下代码
MACHINE_START(S3C2440, "SMDK2440")
/* Maintainer: Ben Dooks
.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 = smdk2440_map_io,
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
MACHINE_END
把MACHINE_START、MACHINE_END扩展开来就是定义了一个名为__mach_desc_S3C2440的结构体变量:
const struct machine_desc __mach_desc_S3C2440 __used
__attribute__((__section__(".arch.info.init"))) =
{
.nr = MACH_TYPE_S3C2440, //开发板的机器类型ID
.name = "SMDK2440", //开发板名称
.phys_io = S3C2410_PA_UART, //起始IO物理地址
.io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
.boot_params = S3C2410_SDRAM_PA + 0x100, //内核启动参数的地址
.init_irq = s3c24xx_init_irq, //中断初始化函数
.map_io = smdk2440_map_io, //IO映射函数(在这里修改时钟频率)
.init_machine = smdk2440_machine_init,
.timer = &s3c24xx_timer,
};
MACH_TYPE_S3C2440可以看作是系统平台号,它包含在include/asm- arm/mach-types.h头文件中,不过这个头文件是在配置内核或编译内核时自动生成的,所以不能更改。。真正系统平台号
的定义位置在arch/arm/tools/mach-types文件中。
# machine_is_xxx CONFIG_xxxx MACH_TYPE_xxx number
s3c2440 ARCH_S3C2440 S3C2440 362
arch/arm/tools/mach-types中每一行定义一个系统平台号。 “machine_is_xxx”是用来判断当前的平台号是否正确的函数; “CONFIG_xxxx”是在内核配置时生成的; “MACH_TYPE_xxx”
是系统平台号的定义; “number”是系统平台的值。 __mach_desc_S3C2440结构体中的函数将在内核启动过程中,完成系统平台的初始化工作
这样我们打开
arch/arm/tools/mach-types
就看到了如下代码
s3c2440ARCH_S3C2440 S3C24401999
我的开发板是mini2440默认为1999,所以我把机器码修改为1999,同样也可以修改开发板的修改为原来默认的362。
备注:
既然我们现在知道了移植为什么修改以上的几个文件,那么我们来讨论一下,以上几个文件都有什么作用。
arch/arm/tools/mach-types 不必多说查看代码就知道里面全部是对机器码的定义。
mach-smdk2440.c 我们查看一下代码
里面有这样几个数据结构
static struct map_desc smdk2440_iodesc[] __initdata
static struct s3c2410_uartcfg smdk2440_uartcfgs[] __initdata
struct s3c2410fb_display smdk2440_lcd_cfg __initdata
struct s3c2410fb_mach_info smdk2440_fb_info __initdata
struct platform_device *smdk2440_devices[] __initdata
以及两个函数
static void __init smdk2440_map_io(void)
static void __init smdk2440_machine_init(void)
这样我们就可以大概推断出,该文件是关于平台设备数据结构的重要定义以及平台初始的文件
common-smdk.c struct s3c24xx_led_platdata smdk_pdata_led4
。。。。。
struct mtd_partition smdk_default_nand_part[]
struct s3c2410_nand_set smdk_nand_sets[]
struct s3c2410_platform_nand smdk_nand_info
struct platform_device __initdata *smdk_devs[]
以及一个函数
void __init smdk_machine_init(void)
这两个文件的代码结构是相同的,值得注意的是第二个文件,里面主要是关于nand flash 的驱动。
所以我们在进行驱动移植的时候,大部分都要修改这两个文件,但是驱动程序的实习,往往不再这里。
这两个文件中写的大都是驱动程序硬件的数据结构。