移植linux-3.4.2内核到JZ2440

    移植之前,首先了解一下相关的一些理论知识。
    linux内核Makefile文件分类:

   1、顶层Makefile:他是所有Makefile文件的核心,从总体上控制着内核的编译、连接。

   2、.config文件: 配置文件,它在配置内核时生成。所有Makefile文件(包括顶层目录及各级子目录)都是根据.config来决定使用那些文件。

   3、arch/$(ARCH)/Makefile:对应体系结构的Makefile,它用来决定哪些体系结构相关的文件参与内核的生成,并提供一些规则来生成特定格式的内核映像。     

   4、scripts/Makefile.*: Makefile共用的通用规则,脚本等。      

   5、kbuild Makefile:各级子目录下的Makefile,它们相对简单,被上一层Makefile调用来编译当前目录下的文件。 

    根据make的时候最后输出的信息得到其链接脚本,arm/arm/kernel/vmlinux.lds,源码中没vmlinux.lds文件,能找到一个vmlinux.lds.S。内核编译过后可以找到vmlinux.lds文件(vmliunx.lds 由编译时候根据vmlinux.lds.S生成)总之,linux内核的第一个文件:arch/arm/kernel/head.S,链接脚本:arch/arm/kernel/vmlinux.lds。
    make的时候,最后输出的链接信息很有用,它说明了内核最后由那些.o生成,和这些.o的顺序。这些.o具体的代码段,数据段等,则由链接脚本决定。
    thekernel(0,bd->bi_arch_number,bd->bi_boot_parmas)函数会把这3个参数存在r0,r1,r2中。r5 = __arch_info_begin,     r6 = __arch_info_end(链接脚本中决定的地址)。
    machine_desc结构体含机器Id成员,params参数(一系列的tag结构体)等。这个结构体的段属性被强制为.arch.info.init,指定其链接位置。一个machine_decs结构体支持一种单板。编译内核的时候会构造一系列的machine_desc结构体以支持各种单板,内核启动的时候取出一系列的machine_desc结构与uboot保存在r0,r1,r2(主要比较机器ID)中的值进行比较。

内核启动:
1、判断是否支持这个CPU(处理器)
2、判断是否支持这个单板(机器ID)
3、创建页表
4、使能mmu
5、跳到:start_kernel(内核的第一个C函数)。 

    start_kernel调用setup_arch(char **cmdline_p)处理uboot传来的启动参数,把一个个tag取出来分析启动参数,即uboot中bootargs对应的启动参数,若Uboot没有传进来的话,内核会使用默认的命令行启动参数。还有setup_command_line(command_line)函数处理命令行参数。

内核启动调用过程:

arch/arm/kernel/head.S:
.....
start_kernel
setup_arch() //解析uboot传入的启动参数。
setup_command_line()    //解析uboot传入的命令行参数。
parse_early_param //这些东西分析处理启动参数,命令参数。__setup("root=",root_dev_setup)构造的
do_early_param //结构体有名字和函数指针,段属性是 .init.setup
从__setup_start 到 __setup_end,调用 early函数。
unknown_bootoption
obsolete_checksetup
从__setup_start 到 __setup_end,调用非early 函数。
rset_init()
kernel_thread(kernel_init,NULL,CLONE_FS|CLONE_SIGHAND)
kernel_init()
prepare_namespace()
mount_root() //挂接根文件系统,挂接到各个根文件系统,由uboot传来的
//bootargs参数指定:root=dev/mtdblock3
init_post()

//执行应用程序。


    uboot对nand设置的分区,不会传给内核,不会影响内核对nand的从新分区,但为方便使用,uboot的分区设置应与内核保持一致。

    内核的分区的设置是在arch/arm/plat-sec24xx/common-smdk.c中,                                                                           设置 static struct mtd_partition smdk_default_nand_part[]数组,数组元素格式为:

        [0] = {
.name = "Boot Agent",
.size = SZ_16K,
.offset = 0,

},


内核如何启动第一个程序:
    首先打开/dev/console,sys_dup(0)两次,对应标准输入,输出,错误。console:终端,这里是串口0。
    然后 if(execute_command) //uboot传给内核的命令行参数:init=/linuxrc
         调用run_init_process(execute_command)执行这个命令,实际是第一个应用程序,run_init_process()函数成功后可能在里面循环不返回。退出的话执行下一个run_init_process()命令。
    run_init_process()的参数来自uboot传来的命令行参数 init=xxx,或者内核的/sbin/init,或etc/init或/bin/init 或/bin/sh。
  
      如果由于root分区没有保存实际的文件系统映像,会导致执行第一个应用程序不成功,输出像下面这些错误信息:
  unable to open an initial console.
  failed to execute /linuxrc. //uboot传来的init=xxx

  panic No init found. try pass init= option to kernel. 

    若已经分区,即使没有文件系统,也可以mount成功。


下面是移植的实验过程:

1.修改Makefile:
ARCH ?= arm

CROSS_COMPILE ?= arm-linux-

2.使用默认配置:                                                                                                                                                     make s3c2410_defconfig     //生成.config文件

3.编译:
make uImage


uboot传递机器ID给内核的方式:

    1、uboot使用默认机器ID:
         gd->bd->bi_arch_number = MACH_TYPE_SMDK2410 //193
    可在 uboot-2012.04.01/board/Samsung/smdk2440目录下 smdk2410.c:board_init()函数里
    设置gd->bd->bi_arch_number 默认值。
    2、uboot命令行下设置机器ID:
    如果uboot命令行下设置了机器ID,则uboot-2012.04.01/arch/arm/lib目录下 bootm.c里: s= getenv("machid");这句执行成功,则使用设置的机器ID,否则使用默认机器id gd->bd->bi_arch_number = MACH_TYPE_SMDK2410。
    可在Mach-types.h中查看支持的机器ID


4、启动uboot,在uboot命令行下设置传递给内核的机器ID,和其他启动参数:

set machid 16a // smdk2440 mach-smdk2440.c

set machid 7CF // mini2440 mach-mini2440.c
设置 uboot 启动参数的波特率:

set bootargs console=ttySAC0,115200

5、更新内核启动:

    a、如果 set machid 16a ,除了设置 uboot 启动参数的波特率以外还要修改外部晶振频率,
    在内核源码文件linux3.4.2\arch\arm\mach-s3c24xx\mach-smdk2440.c中 修改默认外部晶振,改为 12MHz
static void __init smdk2440_map_io(void)
{
s3c24xx_init_io(smdk2440_iodesc,ARRAY_SIZE(smdk2440_iodesc));
s3c24xx_init_clocks(120000000);//外部晶振设为12000000,原值:16934400
s3c24xx_init_uarts(smdk2440_uartcfgs,ARRAY_SIZE(smdk2440_uartcfgs));
}

    更新内核:
    make s3c410_defconfig //编译出的内核支持多种单板。
    重新编译:make uImage

   b、若使用 set machid 7cf,则只需uboot 设置波特率为115200,mach-mini2440.c里的晶振默认是12000000,不用修改。
    更新:
   make mini2440_defconfig //编译出的内核只支持2440单板

   make uImage

进一步修改,裁剪内核:

1、修改分区:                                                                                                                                                                  修改linux-3.4.2/arch/arm/mach-s3c24xx/common-smdk.c (不同版本,可能是arch/arm/plat-s3c24xx/common-smdk.c)中的struct mtd_partition smdk_default_nand_part[]数组。现在要把新内核对 NAND FLASH 的分区跟 uboot 划分一致(uboot 对分区的划分不会传进内核)。改为:

static struct mtd_partition smdk_default_nand_part[] = {
[0] = {
.name = "bootloader",
.size = SZ_256K,
.offset = 0,
},
[1] = {
.name = "params",
.offset = MTDPART_OFS_APPEND, //偏移值,紧接着上一个分区
.size = SZ_128k,
},
[2] = {
.name = "kernel",
.offset = MTDPART_OFS_APPEND,
.size = SZ_2M,
},
[3] = {
.name = "root",
.offset = MTDPART_OFS_APPEND,
.size = MTDPART_sIZ_FULL, //表示剩下的所有
}
};


    .config文件里说明了内核支持的文件系统,在这文件里面找不到对yaffs的支持。这个内核也不支持之前用老的内核制作的jffs2文件系统,能挂载之前的jffs2,但找不到 init 文件。

    用这个新内核制作jffs2根文件系统(我就不制作了,下面配置内核支持yaffs文件系统)。

2、配置内核,使支持 eabi 接口:
    编译器编译的应用程序是 eabi 接口,内核也需要支持 eabi 接口才行。
    重新配置内核支持 EABI:
    搜索 EABI:
    [*] Use the ARM EABI to compile the kernel

    重新 make uImage_eabi

3、支持、移植yaffs文件系统:
下载yaffs 源码:
git clone git://www.alwph1.co.uk/yaffs2
打补丁:
cd yaffs-dir // 进入yaffs目录
./patch-ker.sh c m linux-tree  比如 ./patch-ker.sh c m /work/system/linux-3.4.2 // 打补丁
配置内核支持yaffs
mak menuconfig
 <*> yaffs2 file systme support
编译:make uImage
出现一大堆错误,都是函数名的问题,改一下就可以了(添加下划线)。如:新的内核没有实现d_alloc_root函数,却使用的是d_make_root,把d_alloc_root改为d_make_root。直至最后make uImage 成功。

4、mkyaffs2image工具制作:
将 Development_util_ok 上传到 ubuntu,进入 Development_util_ok\yaffs2\utils 目录:
编译
make
生成 mkyaffs2image 工具:
将 mkyaffs2image 复制到/usr/local/bin 目录里:
sudo cp mkyaffs2imag /usr/local/bin
添加可执行权限:
sudo chmod +x /usr/local/bin/mkyaffs2imag

5、制作一个 yaffs2 文件映像:
mkyaffs2image fs_mini_mdev_new fs_mini_mdev_new.yaffs2

其中:fs_mini_mdev_new是制作的根文件系统

6、修改uboot:
if (!need_skip && !(flags & WITH_DROP_FFS)) 
改为
if (!need_skip && !(flags & WITH_DROP_FFS) && !(flags & WITH_YAFFS_OOB)) 

修改后重新制作uboot,启动。记得修改启动参数:把rootfstype=jffs2去掉


内核裁剪:make menuconfig
1、单板仅保留:
[*] MINI2440 development board
[*] SMDK2440
[*] SMDK2440 with S3C2440 CPU module
文件系统可去掉:
<> Second extended fs support
<> Ext3 journalling file system support

2、继续去掉下面这些:
[] Keyboards --->
[] Mice --->
[] Provide legacy /dev/psaux device
[] ISO 9660 CDROM file system support
[] Compressed ROM file system support (cramfs)
[] Include support for ZLIB compressed file system
[] ROM file system support

CONFIG_S3C2440_XTAL_16824400
CONFIG_TOUCHSCREEN_USB
CONFIG_SSB_POSSIBLE
CONFIG_BCMA)_POSSIBLE
CONFIG_SND_USB
CONFIG_USB_LIBUSUAL
CONFIG_LEDS_TRIGGERS

<>Samsung S3C2410/generic touchscreen input driver
<>usb sound devices --->
[] The shared table of common (or usual) storage devices

如果实在剪裁不到 2M 以下,就需要修改 NAND FLASH 分区,将分区放大一点。

3、制作补丁和新内核。(制作纯净内核的补丁,要把刚配置好的.config文件保留下来)
首先 cp .config config_ok
diff 生成补丁,
patch -p1 < ../linux-3.4.2_100ask.patch
cp config_ok .config //确保纯净配置
make uImage

4、更新内核,启动,输出信息:
Image Name:   Linux-3.4.2
Created:      Tue Jan 16 04:23:59 2018
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    2085048 Bytes = 2036.18 kB = 1.99 MB
Load Address: 0x30008000
Entry Point:  0x30008000
Image arch/arm/boot/uImage is ready 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值