一、系统移植步骤 (以s5pc100加网络驱动为例)
1、首先去官网下载一个linux内核的源码包,让解压内核源码,
# tar xvflinux-3.9.8.tar.xz
2、选平台
(1)修改源码(linux-3.9.8文件夹下)顶层目录下的Makefile,
设置体系结构和交叉编译工具
ARCH= arm 体系结构
CROSS_COMPILE = arm-linux- 交叉编译工具(根据自己安装的
交叉编译工具路径来设置)
例如我安装的arm-cotexta8-gcc在/opt/arm-cortex_a8/bin下,上
面的设置为ARCH ?= arm
CROSS_COMPILE ?=/opt/arm-cortex_a8/bin/arm-cortex_a8-linux-gnueabi-
(2)缺省配置:相当于指定当前的板子,指定平台相关的目录
内核源码每个子目录中都有一个Makefile文件和Kconfig文件。
其中Kconfig用于配置内核,它就是各种配置界面的源文件(对应命令make menuconfig)。 由Kconfig界面配置后生成.config
make编译时,读取.config后进行编译。Kconfig里面配置只是为了在界面中显示,而在Makefile中设置是为了让源文件编译生成的.o文件加载入内核。
arch/arm/configs/s5pc100_defconfig
# makes5pc100_defconfig
拷贝到源码顶层目录下然后进行make s5pc100_defconfig 这样会将生成的配置文件加入到.comfig中,也是告诉内核当前的板级为s5pc100,则与s5pc100相关的所有配置会被编译进系统,也可以通过make menuconfig查看到当前CPU的型号为s5pc100。
3、定制板级文件
在arch/arm/mach-s5pc100/mach-smdkc100.c
//串口设备信息
/*Following are default values for UCON, ULCON and UFCON UART registers */
#defineSMDKC100_UCON_DEFAULT (S3C2410_UCON_TXILEVEL| \
S3C2410_UCON_RXILEVEL | \
S3C2410_UCON_TXIRQMODE | \
S3C2410_UCON_RXIRQMODE | \
S3C2410_UCON_RXFIFO_TOI | \
S3C2443_UCON_RXERR_IRQEN)
#defineSMDKC100_ULCON_DEFAULT S3C2410_LCON_CS8
#defineSMDKC100_UFCON_DEFAULT (S3C2410_UFCON_FIFOMODE| \
S3C2440_UFCON_RXTRIG8 | \
S3C2440_UFCON_TXTRIG16)
staticstruct s3c2410_uartcfg smdkc100_uartcfgs[] __initdata = {
[0] = {
.hwport = 0,
.flags = 0,
.ucon = SMDKC100_UCON_DEFAULT,
.ulcon = SMDKC100_ULCON_DEFAULT,
.ufcon = SMDKC100_UFCON_DEFAULT,
},
[1] = {
.hwport = 1,
.flags = 0,
.ucon = SMDKC100_UCON_DEFAULT,
.ulcon = SMDKC100_ULCON_DEFAULT,
.ufcon = SMDKC100_UFCON_DEFAULT,
},
[2] = {
.hwport = 2,
.flags = 0,
.ucon = SMDKC100_UCON_DEFAULT,
.ulcon = SMDKC100_ULCON_DEFAULT,
.ufcon = SMDKC100_UFCON_DEFAULT,
},
[3] = {
.hwport = 3,
.flags = 0,
.ucon = SMDKC100_UCON_DEFAULT,
.ulcon = SMDKC100_ULCON_DEFAULT,
.ufcon = SMDKC100_UFCON_DEFAULT,
},
};
#include<linux/dm9000.h>
//DM9000网络的设备信息:硬件信息(I/O、中断号)、参数
staticstruct resource smdkc100_dm9000_resources[] = {
[0] = {
.start = 0x88000000,
.end = 0x88000000+0x3,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = 0x88000000+0x4,
.end = 0x88000000+0x4+0x3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_EINT(10),
.end = IRQ_EINT(10),
.flags = IORESOURCE_IRQ|IRQ_TYPE_LEVEL_HIGH,
},
};
staticstruct dm9000_plat_data smdkc100_dm9000_platdata = {
.flags =DM9000_PLATF_16BITONLY | DM9000_PLATF_NO_EEPROM,
.dev_addr ={ 0x00, 0x09, 0xc0, 0xff, 0xec, 0x48 },
};
staticstruct platform_device smdkc100_dm9000 = {
.name ="dm9000",
.id =-1,
.num_resources = ARRAY_SIZE(smdkc100_dm9000_resources),
.resource =smdkc100_dm9000_resources,
.dev ={
.platform_data = &smdkc100_dm9000_platdata,
},
};
//platform_device设备列表
staticstruct platform_device *smdkc100_devices[] __initdata = {
&smdkc100_dm9000,//添加设备DM9000到内核
};
//map初始化(不要修改):I/O MAP、时钟设置、串口初始化
staticvoid __init smdkc100_map_io(void)
{
s5pc100_init_io(NULL, 0);
s3c24xx_init_clocks(12000000);
s3c24xx_init_uarts(smdkc100_uartcfgs,ARRAY_SIZE(smdkc100_uartcfgs));
}
//设备参数及设备主机端初始化
staticvoid __init smdkc100_machine_init(void)
{
platform_add_devices(smdkc100_devices,ARRAY_SIZE(smdkc100_devices));
}
//板级文件设置结构:被初始化代码回调的板级的初始化函数
MACHINE_START(SMDKC100,"SMDKC100")
/* Maintainer: Byungho Min<bhmin@samsung.com> */
.atag_offset =0x100, 内核启动参数放置的起始地址
.init_irq =s5pc100_init_irq,
.map_io =smdkc100_map_io,
.init_machine = smdkc100_machine_init,
.init_time =s3c24xx_timer_init,
.restart =s5pc100_restart,
MACHINE_END
4、选配模块
#make menuconfig
Bootoptions --->
[*] Provide old way to pass kernel parameters
[*]Networking support --->
Networking options --->
<*> Packet socket
[*] TCP/IP networking
[*] IP: kernel level autoconfiguration
DeviceDrivers --->
[*] Network device support --->
[*] Ethernet driver support (NEW) --->
<*> DM9000 support
Filesystems --->
[*] Network File Systems (NEW) --->
<*> NFS client support
<*> NFS client support for NFS version 2 (NEW)
<*> NFS client support for NFS version 3 (NEW)
[*] Root file system on NFS
二、定制板级文件中的一些知识点说明
arch/arm/mach-s5pc100/mach-smdkc100.c
1、三种结构体定义
---------------------------------------------------------
struct__data{
int i;
char *s;
};
struct__data data = {
.s = "hello world",
.i = 1,
};
struct__data data = {
1, "hello world",
};
...
data.i= 1;
data.s= "hello world";
以上三种是给结构体赋值的方式,区别在于,在定义时就赋值和先定义后赋值,. 这种方式赋值时不需要按照顺序,
2、设备信息及设备主机端初始化
#defineMACHINE_START(_type,_name) static conststruct machine_desc __mach_desc_##_type __used __attribute__((__section__(".arch.info.init")))= {
.nr =MACH_TYPE_##_type, \
.name =_name,
#defineMACHINE_END \
};
前面是宏定义 后面是一个结构体初始化
----相当于一个结构体 初始化 ##是宏连接符 __mach_desc_##_type 相当于将MACHINE_START(_type,_name)中_type的参数放到##_type中。
然后将type name替换struct里面的参数。
__section__(".arch.info.init")定义了一个段,取名为.arch.info.init
3、机器码
机器码出处
# arch/arm/tools/Makefile
include/generated/mach-types.h: $(src)/gen-mach-types$(src)/mach-types
@echo ' Generating $@'
@mkdir -p$(dir $@)
$(Q)$(AWK)-f $^ > $@ || { rm -f $@; /bin/false; }
4、关于机器码与CPUid号
CPUid号 是内核号,例如A8有一个ID号,在内部寄存器里面
机器码 应该是板子的标号,人为设置 例如三星S5PC的板子一个标号
华清的S5PC也有一个标号
5、内核出错信息分析
Oops信息 出错时可见内核当前信息
Cd proc
Cat 文件名称