S5PV210的kernel移植

1、先熟悉源码目录结构
2、然后通过源码分析,熟悉kernel执行过程
3、尝试进行修改添加kernel

kernel移植初体验
1)进入源码目录,在linux下解压,因为在windows下解压,会出现相同文件提示覆盖那些,因为windows不区分大小写,而且还有一些链接文件在。
2)修改 Makefile 中的体系结构 ARCH 和交叉编译器前缀 CROSS_COMPILE
vim Makefile
修改 191 和 192 行为如下:
ARCH ?= arm
CROSS_COMPILE ?= /usr/local/arm/arm-2009q3/bin/arm-none-linux-gnueabi-
3)使用 SMDKV210 的缺省配置文件
make arch/arm/configs/smdkv210_android_defconfig
若出现找不到 smdkv210_android_defconfig,则执行如下操作
cp arch/arm/configs/smdkv210_android_defconfig .config
make smdkv210_android_defconfig
4) 配置内核,修改串口
make menuconfig
若出现*** Unable to find the ncurses libraries or the 错误,则执行
解决方法:sudo apt-get install libncurses5-dev
修改底层消息和底层调试串行端口为 UART0:
System Type --->
(0) S3C UART to use for low-level messages
Kernel hacking --->
(0) S3C UART to use for low-level debug
通常要配的是:内核输出串口,对应的开发板型号
关于NAND flash分区,参考:
http://blog.chinaunix.net/uid-30227644-id-4993889.html
http://blog.csdn.net/yjp19871013/article/details/6933455
http://blog.chinaunix.net/uid-25119314-id-351866.html
5) 确定机器码
vim arch/arm/tools/mach-types
在 433 行可以看出,SMDKV210 评估板的机器码是 2456(16 进制是 0x998) :
2433 smdkv210 MACH_SMDKV210 SMDKV210 2456
6) 确定内核的加载地址和参数地址
vim arch/arm/mach-s5pv210/Makefile.boot
可以看出,内核的加载地址和参数地址分别为 0x20008000 和 0x20000100,bootloader
启动内核前应该将内核拷贝到 0x20008000,并将参数放到 0x20000100。
zreladdr-y += 0x20008000
params_phys-y := 0x20000100
7) 编译内核
make uImage -j 2
-j 2 指定了编译时的线程数,使用 2 个线程可加快编译的速度
注意:如果出错:没法生成uImage
拷贝mkimage到linux的/sbin  /bin 即可。
mkimage是把zImage生成uImage
内核的加载地址的确是 0x20008000,进入点地址也是 0x20008000,u-boot
支持的Linux内核映像uImage也可用了,否则不会进入到内核执行,引导不成功,
需要结合uboot里的设置而定。
如果内核启动出现这样的错误:can't run '/etc/init.d/rcS': No such file or directory;请用
vi 把/etc/init.d/rcS 文件中的乱码“^M”删掉。

进行简单源码分析
顶层makfile 执行make menuconfig
1.创建两个目录
mkdir -p include/linux include/config
2.进入scritps/kconfig目录下,编译出mconf
menuconfig: scripts/kconfig/mconf
3.直接执行mconf,并且将arch/arm/Kconfig当做参数送给mconf

然后mconf arch/arm/Kconfig到底做了什么?
1)画出可操作的菜单界面
2)界面可以交互
3)所有的界面操作是可以保存到.config文件
可以尝试自定义一个菜单。
实例:1
1、菜单的创建
# vim arch/arm/Kconfig
menu "hello world"
endmenu
保存退出,重新执行
#make menuconfig
看看有什么变化?只是生成了一个简单的菜单,里面没有选项。
2、选项的添加
在menu与endmenu之间加入以下代码
config HELLO
        bool "hello"
        default y
保存退出,重新执行
#make menuconfig
看下有什么变化
实例:2
1、修改源码
#vim arch/arm/kconfig
在文件的开头,添加发下内容
menu "helloworld"
source "helloworld/Kconfig"
endmenu
2、增加下级kconfig
在顶层的目录下,创建测试目录:
#mkdir helloworld
#vim helloworld/Kconfig
添加如下内容:
config HELLO
        tristate "printf hello"
default y
        ---help---
          Printf something such of gec210_hello
config WORLD
        tristate "printf world"
default y
        ---help---
          Printf something such of gec210_hello
保存退出。
3、执行make menuconfig
看一下是否出现相应的内容。
再看.config 
实例3:
1、在顶层makefile中添加
drivers-y       := drivers/  sound/  firmware/  helloworld/
2、在二级目录中添加makefile
#cd helloworld/
添加以下内容:
obj-$(CONFIG_HELLO)       += hello.o
obj-$(CONFIG_WORLD)       += world.o
保存退出。
3、添加源代码
#vim hello.c
添加以下内容
#include <linux/kernel.h>
int test_hello(void)
{
        printk(">>>>>>>>>>>>>>>>>>>>>> hi,hello <<<<<<<<<<<<<<<<<<\n");
        return 0;
}
保存退出。
同理创建world.c
#include <linux/kernel.h>
int test_world(void)
{
        printk(">>>>>>>>>>>>>>>>>>>>>> hi,world <<<<<<<<<<<<<<<<<<\n");
        return 0;

}

内核启动过程分析

顶层Makefile
 arch/arm/kernel/head.S
 arch/arm/kernel/head-common.S
 ...
 arch/arm/kernel/vmlinux.lds 


 ENTRY(stext) // 代码入口
setmode PSR_F_BIT | PSR_I_BIT | SVC_MODE, r9
1.查看是否支持处理器编号
mrc p15, 0, r9, c0, c0 @ 处理器的ID号 
bl __lookup_processor_type @ r5=procinfo r9=cpuid
movs r10, r5 @ invalid processor (r5=0)?
beq __error_p @ yes, error 'p'

2.查看是否支持机器编号
bl __lookup_machine_type @ r5=machinfo
movs r8, r5 @ invalid machine (r5=0)?
beq __error_a @ yes, error 'a'
3.获取启动参数 bootargs 
bl __vet_atags
4.创建页表
bl __create_page_tables
5.
ldr r13, __switch_data
.long __mmap_switched

__mmap_switched:
.....
b start_kernel     // init/main.c 

start_kernel:
/* 详细的各个模块的初始化 */
setup_arch(&command_line);
sched_init();
init_IRQ();
init_timers();
......
console_init(); // 控制台初始化
.....

/* 创建两个方向的线程 */
rest_init();
kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND);
kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);

kernel_init  // 用于启动1号进程 init
kthreaddd    // 内核进程的管理线程
schedule();  
cpu_idle();

kernel_init
1. 驱动部分初始化
do_basic_setup();
2. rootfs的控制台初始化
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)
printk(KERN_WARNING "Warning: unable to open an initial console.\n");
(void) sys_dup(0);
(void) sys_dup(0);

3.挂载文件系统到dram
prepare_namespace();
mount_root();
4.启动1号进程 
init_post();
run_init_process("/sbin/init");

总结:

1、arch/arm/kernel/head.S是第一个文件,总的入口就在这个文件

2、uImage是uboot专用的镜像文件,它是在zImage之前加上一个长度为0x40的头信息(tag),

在头信息内说明了该镜像文件的类型、加载 位置、生成时间、大小等信息.换句话说,若直接从uImage的0x40位置开始执行,则zImage和uImage没有任何区别

启动方式不一样
手动启动:tftp 40000000 zImage ;go 0x40000000
自动启动:tftp 40000000 uImage ;bootm 0x40000000

注意:

1、机器码对应
只要保持两个文件(u­boot的board/fs2410/fs2410.c与linux内核的arch/arm/machs3c2410/mach­smdk2410.c)参照对象的码值一样就可以了!

2、启动到kernel starting ...停止的话,参考:

http://www.linuxidc.com/Linux/2011-04/34796.htm
http://blog.sina.com.cn/s/blog_6340cd9c010106pu.html
http://www.mcuzone.com/bbs/simple/?t9071.html
http://www.aichengxu.com/view/38299

3、如果编译出的是zImage转为uImage就在内核源码的arch/arm/boot/下执行如下命令 

mkimage -A arm -O linux -T kernel -C none -a 20008000 -e 20008000 -n xxkernel -d zImage uImage
注意-a 和-e
二是在性能微调选项选择tab键补全功能。 ->Busybox Settings  ->Busybox library Tuning   ->Command line editing    ->Tab completion

4、编译内核或uboot时
lib/asm-offsets.c:1: error: bad value (armv4) for -mtune= switch
make[1]: *** [lib/asm-offsets.s] Error 1
没有指定交叉编译工具链。设置环境变量,或者make时带上CROSS_COMPILE参数。如make CROSS_COMPILE=arm-none-linux-gnueabi-
http://bbs.csdn.net/topics/390769229

5、有内核启动信息输出终端后,如果到最后说5秒自动重启,可能是因为没有移植LCD驱动,而且保证下有文件系统在。

内核移植完之后,有些还需要一些接口模块功能的移植。
还要检查下u-boot的环境变量bootargs启动参数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值