本文主要探讨210官方kernel移植。
配置文件选择
选择配置文件smdkv210_android_defconfig(arch/arm/configs)
修改主Makefile
配置cpu架构和交叉编译工具链
vim Makefile
ARCH ?= arm
CROSS_COMPILE ?= /root/arm-2009q3/bin/arm-none-linux-gnueabi-
初步编译烧录
ubuntu:
make smdkv210_android_defconfig
make -j4
cp -r arch/arm/boot/zImage ~/tftp/
uboot:
tftp 30008000 zImage
bootm 30008000
结果显示(无法启动):
一阶段移植(head.s)
初步移植未有kernel信息打印则说明一阶段(汇编)异常
led调试一阶段,添加led熄灭代码逐步测试(初始led亮)
led亮且未显示解压zImage信息则解压部分异常(实际为物理地址错误)
vim arch/arm/kernel/head.s
/*
* Kernel startup entry point.
* ---------------------------
*
* This is normally called from the decompressor code. The requirements
* are: MMU = off, D-cache = off, I-cache = dont care, r0 = 0,
* r1 = machine nr, r2 = atags pointer.
*
* This code is mostly position independent, so if you link the kernel at
* 0xc0008000, you call this at __pa(0xc0008000).
*
* See linux/arch/arm/tools/mach-types for the complete list of machine
* numbers for r1.
*
* We're trying to keep crap to a minimum; DO NOT add any machine specific
* crap here - that's what the boot loader (or in extreme, well justified
* circumstances, zImage) is for.
*/
__HEAD
ENTRY(stext)
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9 @ ensure svc mode
//test
bl led_off
@ and irqs disabled
mrc p15, 0, r9, c0, c0 @ get processor id
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
beq __error_p @ yes, error 'p'
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
bl __vet_atags
bl __create_page_tables
/*
* The following calls CPU specific code in a position independent
* manner. See arch/arm/mm/proc-*.S for details. r10 = base of
* xxx_proc_info structure selected by __lookup_machine_type
* above. On return, the CPU will be ready for the MMU to be
* turned on, and r0 will hold the CPU control register value.
*/
ldr r13, __switch_data @ address to jump to after
@ mmu has been enabled
adr lr, BSYM(__enable_mmu) @ return (PIC) address
ARM( add pc, r10, #PROCINFO_INITFUNC )
THUMB( add r12, r10, #PROCINFO_INITFUNC )
THUMB( mov pc, r12 )
ENDPROC(stext)
//led off
led_off:
ldr r3, =0x11111111
ldr r4, = 0xE0200240
str r3, [r4]
ldr r3, =0xff
ldr r4, =0xE0200244
str r3, [r4]
mov pc, lr
修改物理地址
#define KERNEL_RAM_VADDR (PAGE_OFFSET + TEXT_OFFSET)
#define KERNEL_RAM_PADDR (PHYS_OFFSET + TEXT_OFFSET)
(arch/arm/include/asm/memory.h)#define PAGE_OFFSET UL(CONFIG_PAGE_OFFSET)
(.config)CONFIG_PAGE_OFFSET=0xC0000000
修改为
(arch/arm/mach-s5pv210/include/mach/memory.h)
#if defined(CONFIG_MACH_SMDKV210)
#define PHYS_OFFSET UL(0x30000000)
#else
#define PHYS_OFFSET UL(0x30000000)
#endif
修改解压地址
vim arch/arm/mach-spv210/Makefile.boot
# override for SMDKV210
zreladdr-$(CONFIG_MACH_SMDKV210) := 0x30008000
params_phys-$(CONFIG_MACH_SMDKV210) := 0x30000100
内核机器码确定分析
MACHINE_START宏定义机器码数据结构(硬件信息及其相关初始化函数等)
每个mach-xxx.c文件定义一个机器码machine_desc结构体变量且结构体变量被定义到段(.arch.info.init)
(arch/arm/mach-s5pv210/s5pc110.c)
#ifdef CONFIG_MACH_SMDKC110
MACHINE_START(SMDKC110, "SMDKC110")
#elif CONFIG_MACH_SMDKV210
MACHINE_START(SMDKV210, "SMDKV210")
#endif
/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkc110_map_io,
.init_machine = smdkc110_machine_init,
.timer = &s5p_systimer,
MACHINE_END
(.config)
CONFIG_MACH_SMDKV210=y
# CONFIG_MACH_SMDKC110 is not set
(arch/arm/include/asm/mach/arch.h)
#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 \
};
推导出():
static const struct machine_desc __mach_desc_SMDKV210 \
__used \
__attribute__((__section__(".arch.info.init"))) = { \
.nr = MACH_TYPE_SMDKV210, \
.name = "SMDKV210",
.phys_io = S3C_PA_UART & 0xfff00000,
.io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
.boot_params = S5P_PA_SDRAM + 0x100,
.init_irq = s5pv210_init_irq,
.map_io = smdkv210_map_io,
.init_machine = smdkv210_machine_init,
.timer = &s5p_systimer,
};
二阶段
修改电源异常
程序在dev_driver_string或max8698_pmic_probe异常
max8698_pmic_probe为电源管理IC驱动安装函数,210未使用电源IC
make menuconfig取消max8698编译进内核
修改网卡异常
修改网卡寄存器配置(移植mach-x210.c)
smdkc110_machine_init==>smdkc110_dm9000_set
#ifdef CONFIG_DM9000
static void __init smdkc110_dm9000_set(void)
{
unsigned int tmp;
s3c_gpio_cfgpin(S5PV210_GPH1(2), S3C_GPIO_INPUT);
s3c_gpio_setpull(S5PV210_GPH1(2), S3C_GPIO_PULL_NONE);
int ret = gpio_request(S5PV210_GPH1(2), "GPH1");
if(ret)
printk("mach-x210: request gpio GPH1(2) fail");
else
{
s3c_gpio_cfgpin(S5PV210_GPH1(2), 0xf);
s3c_gpio_setpull(S5PV210_GPH1(2), S3C_GPIO_PULL_NONE);
}
tmp = ((0<<28)|(0<<24)|(5<<16)|(0<<12)|(0<<8)|(0<<4)|(0<<0));
__raw_writel(tmp, S5P_SROM_BC1);
tmp = __raw_readl(S5P_SROM_BW);
tmp &= ~(0xf << 4);
tmp |= (1<<7) | (1<<6) | (1<<5) | (1<<4); // dm9000 16bit
__raw_writel(tmp, S5P_SROM_BW);
tmp = __raw_readl(S5PV210_MP01CON);
tmp &= ~(0xf << 4);
tmp |= (2 << 4);
__raw_writel(tmp, S5PV210_MP01CON);
}
修改网卡地址和中断号(arch/arm/plat-s5p/devs.c)
/* DM9000 registrations */
#ifdef CONFIG_DM9000
static struct resource s5p_dm9000_resources[] = {
[0] = {
.start = S5P_PA_DM9000,
.end = S5P_PA_DM9000,
.flags = IORESOURCE_MEM,
},
[1] = {
#if defined(CONFIG_DM9000_16BIT)
//.start = S5P_PA_DM9000 + 2,
//.end = S5P_PA_DM9000 + 2,
.start = S5P_PA_DM9000 + 4,
.end = S5P_PA_DM9000 + 4,
.flags = IORESOURCE_MEM,
#else
.start = S5P_PA_DM9000 + 1,
.end = S5P_PA_DM9000 + 1,
.flags = IORESOURCE_MEM,
#endif
},
[2] = {
//.start = IRQ_EINT9,
//.end = IRQ_EINT9,
.start = IRQ_EINT10,
.end = IRQ_EINT10,
.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL,
}
};
依据
struct platform_device s5p_device_dm9000 = {
.name = "dm9000",
.id = 0,
.num_resources = ARRAY_SIZE(s5p_dm9000_resources),
.resource = s5p_dm9000_resources,
.dev = {
.platform_data = &s5p_dm9000_platdata,
}
};
修改bank
(arch/arm/mach-s5pv210/include/mach/map.h)
//#define S5PV210_PA_DM9000 (0xA8000000)
#define S5PV210_PA_DM9000 (0x88000000)
#define S5P_PA_DM9000 S5PV210_PA_DM9000
结果显示