移植u-boot2012.04.1 -》2440 (五)支持 nand nor 两种启动方式(完结)

来源:互联网 发布:36芯三网合一网络箱 编辑:程序博客网 时间:2024/06/05 20:49

    前边4篇文章,成功将 u-boot2012 移植到了 2440 开发板上,但是它仅仅支持 norflash 启动并不够完善,下面我们设法让它支持两种启动方式。

    首先,我们得先分析一下目前的启动流程:

    链接地址为 0

    第一阶段:start.S中的汇编部分,包括时钟、sdram 等初始化

    第二阶段:board_init_f 先是调用了大量C函数进行串口什么的初始化,然后进行内存划分

    第三阶段:根据第二阶段的内存划分 start.S 中进行代码重定位,清BSS,修正位置有关码,跳到sdram里去执行 board_init_r 

   那么,如果我们想 nandflash 启动,那么我们必须在前4K代码中就进行 nandflash 的初始化,用nandflash的读函数将代码进行重定位到sdram里,现在有一个矛盾摆在我们面前。首先是,原来的重定位的地方在第三阶段,而且第二阶段调用了大量的C函数,重定位的时候早就在 4K 之外了。如果我们把重定位放在第一阶段和第二阶段之间,那么那时内存还没有进行划分,我们不知道重定位到哪里去。

   解决办法:采用 uboot1.1.6 那种老的方式,在第一阶段和第二阶段之间进行重定位,重定位到固定地址 0x33f00000 中去,第二阶段进行内存划分时,将u-boot的起始地址也固定为 0x33f0000 ,在链接时,指定链接地址为0x33f00000,这样,我们也可以去掉 *.rel 段,实际上是去掉编译时的 -pie 选项。

   还有一个问题,我们nandflash启动时,norflash对cpu是不可见的,因此我们根本无法对Norflash进行初始化,更无法将环境变量保存在Norflash上了。

   解决办法:判断如果是nandflash启动,不进行Norflash的初始化。无论那种方式启动,均将环境变量保存在nandflash上。

   1、去掉 -pie 选项

       grep "\-pie" * -nRw

       arch/arm/config.mk:75:LDFLAGS_u-boot += -pie

       直接注释掉即可。  

   2、指定链接地址

       grep "Ttext" * -nRw

       找到一个宏 CONFIG_SYS_TEXT_BASE 搜索这个宏,发现是在 smdk2440.h 中定义,修改为

       #define CONFIG_SYS_TEXT_BASE  0x33f00000

   3、在第二阶段内存划分时,固定u-boot的起始地址

       在 arch/aem/lib/board.c 中的

       addr -= gd->mon_len;
       addr &= ~(4096 - 1); 这两行后边,新增一行
       addr = 0x33f00000;//增加

   4、实现判断 nor 启动还是 nand 启动的 C 函数

       nor启动时,片内ram位于0x40000000处,可以直接读写,0-2M的空间可以直接读,但是没法直接写入。

       nand启动时,片内ram位于0x0处,0-4k,可以直接读写。

       我一开始尝试在 0x40000000 处写值,然后读取回来看是否成功,发现 nand 启动时访问0x40000000会触发异常直接死掉。那么只好尝试读写0地址了。

int isNandBoot(){#define     RAMSTART  (*(volatile unsigned long *)0x00000000)unsigned long temp = RAMSTART;RAMSTART = 0xbadc0de;if(RAMSTART == 0xbadc0de){RAMSTART = temp;return 1;}else{RAMSTART = temp;return 0;}}
    nand启动返回1,Nor启动返回0

   5、将nandflash的初始化函数、读函数和上边的判断函数统一放入 smdk2440.c 中,同时,我们需要改变链接顺序,将 smdk2440.o 尽量靠前放,索性放在 start.o 的后边好了。但是经过我的尝试,smdk2440.c 和 lowlevel_init.S 会被链接成 libsmdk2440.o ,只把smdk2440.o放到前面的话,会造成函数的重定义,解决办法就是把 libsmdk2440.o 放到前边。

    更改链接脚本:/arc/arm/cpu/u-boot.lds

    在 CPUDIR/start.o (.text) 后边添加一行
       board/samsung/smdk2440/libsmdk2440.o (.text)

    尝试编译一下,正常应该没问题。

   6、在第一阶段和第二阶段之间增加代码重定位等相关操作

#ifndef CONFIG_SKIP_LOWLEVEL_INITblcpu_init_crit#endif/******************此行之前的代码保持不变,增加*************************/ldrsp, =(CONFIG_SYS_INIT_SP_ADDR)bicsp, sp, #7 /* 8-byte alignment for ABI compliance *//* 判断是 nand 还是 nor 启动 */bl isNandBootmov r1,#0x01cmp r0,r1bne copy_nor/* 不相等nor 相等nand*/copy_nand:bl my_nand_initldr r0, =0x33f00000mov r1, #0x00ldr r2, =<span style="font-family: Arial, Helvetica, sans-serif;">_bss_start_ofs</span>bl my_nand_readbl  clear_bsscopy_nor:movr0, #0x00ldrr1, =0x33f00000/* r1 <- scratch for copy_loop */ldrr3, _bss_start_ofsaddr2, r0, r3/* r2 <- source end address    */copy_loop:ldmiar0!, {r9-r10}/* copy from source address [r0]    */stmiar1!, {r9-r10}/* copy to   target address [r1]    */cmpr0, r2/* until source end address [r2]    */blocopy_loopbl  clear_bss/*****************call_board_init_f 中去掉sp的设置***********************/call_board_init_f:ldrr0,=0x00000000blboard_init_f/*************** 将 clear_bss 提升至 relocate_code 的前面****************/clear_bss:#ifndef CONFIG_SPL_BUILDldrr0, _bss_start_ofsldrr1, _bss_end_ofsldrr4, =0x33f00000/* reloc addr */addr0, r0, r4addr1, r1, r4movr2, #0x00000000/* clear    */clbss_l:strr2, [r0]/* clear loop...    */addr0, r0, #4cmpr0, r1bneclbss_lldr pc, =call_board_init_f  // 增加跳转到sdram的指令#endif/*************** 去掉原有的代码重定位操作****************/.globlrelocate_coderelocate_code:movr4, r0/* save addr_sp */movr5, r1/* save addr of gd */movr6, r2/* save addr of destination */mov sp, r0  /* 设置栈 */  /* setup parameters for board_init_r */movr0, r5/* gd_t */movr1, r6/* dest_addr *//* jump to it ... */blboard_init_r/* ***********************之后代码保持不变********************************** * * CPU_init_critical registers * * setup important registers * setup memory timing * ************************************************************************* */
    7、在norflash初始化代码前,增加判断
        在 arch\arm\lib\board.c  -> board_init_r 中将

        #if !defined(CONFIG_SYS_NO_FLASH) 作用域之内的代码放入 if(!isNandBoot()) 条件语句。

    8、将环境变量存储到 nandflash

        首先,我查看了一下 common 目录下,env_flash.c 是被编译进u-boot了,但是 env_nand.c 并没有,看下makefile 它依赖于哪个宏。

        COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o

        COBJS-$(CONFIG_ENV_IS_IN_NAND)  += env_nand.o

        搜索一下,发现 CONFIG_ENV_IS_IN_FLASH 在 smdk2440.h 中定义

        去掉 #define CONFIG_ENV_IS_IN_FLASH

        增加 #defineCONFIG_ENV_IS_IN_NAND

        实际在编译测试的过程中,只定义 CONFIG_ENV_IS_IN_NAND 是不够的,会打印出错误信息 

        Need to define CONFIG_ENV_OFFSET when using CONFIG_ENV_IS_IN_NAND

        意思很明确,我们需要定义环境变量在 nandflash 中的偏移地址,如果对 u-boot 进行分区的话,环境变量应该是存在于 params 区域,为了和内核保持一致,我们干脆分区得了。

    9、查看内核启动打印信息

        0x00000000-0x00040000 : "bootloader"
        0x00040000-0x00060000 : "params"
        0x00060000-0x00260000 : "kernel"
        0x00260000-0x10000000 : "root"

        这是内核的分区划分,我们按照内核的分区,也给 u-boot 进行分区。

        添加分区,smdk2440.h 中要有一下宏定义:

        #define CONFIG_CMD_MTDPARTS
        #define CONFIG_MTD_DEVICE
        #define CONFIG_MTD_PARTITIONS
        加入MTD分区信息:
        #define MTDIDS_DEFAULT "nand0=2440_nand"
        #define MTDPARTS_DEFAULT            "mtdparts=2440_nand:256k@0(bootloader)," \
                                    "128k(params)," \
                                    "2M(kernel)," \
                                    "-(root)" 

        这个内核比较小,因此内核分区只有2M,如果内核比较大的话,在修改就是了。

        环境变量的位置确定了,我们需要在smdk2440.h中定义偏移地址

        #define CONFIG_ENV_OFFSET0x40000

        同时,在smdk2440.h 中定义的 CONFIG_ENV_SIZE 默认为 0x10000 修改为 0x20000

    10、剪裁u-boot

        我尝试nand启动时,发现启动不了,是因为我们的u-boot有400多K,而我们的 bootloader 只有256k,要么修改分区,要么剪裁u-boot,是它小于256k,如何剪裁,就是修改smdk2440.h宏咯。

        在 smdk2440.h 中去掉

        #define CONFIG_CMD_FAT
        #define CONFIG_CMD_EXT2
        #define CONFIG_CMD_UBI
        #define CONFIG_CMD_UBIFS
        #define CONFIG_YAFFS2
        #define CONFIG_RBTREE
        #define CONFIG_USB_OHCI
        #define CONFIG_USB_KEYBOARD
        #define CONFIG_USB_STORAGE
        #define CONFIG_DOS_PARTITION
        #define CONFIG_BOOTP_BOOTFILESIZE
        #define CONFIG_BOOTP_BOOTPATH
        #define CONFIG_BOOTP_GATEWAY
        #define CONFIG_BOOTP_HOSTNAME
        #define CONFIG_CMD_USB
        #define CONFIG_CMD_BSP

        make clean

        make

        编译完你会发现体积大大减小,不到200K

    11、烧写测试,不出意外,我们的 nor nand 都能启动了

       
    可以看到,我们的环境变量已经保存在 nandflash 中了,需要注意的是,我们需要使用 mtdparts default 命令将分区信息保存在环境变量中,才可以在命令中像使用变量一样引用分区名字。如果是第一次划分分区,或者擦出了 params 区,记得 mtdparts default 然后 save 一下。
   12、修改机器ID
        u-boot 在引导内核时,会向内核传递机器ID,机器ID不对,直接无法启动或者导致内核使用了其他单板的初始化函数,那么 u-boot2012 的机器ID 在哪里设置的呢?
        board\samsung\smdk2410\smdk2410.c -> board_init
        gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
        gd->bd->bi_boot_params = 0x30000100;
   13、个性化修改
        如果你想像上边那幅图一样,控制台每一样默认出现“MINI2440 #”该如何设置?
        在 smdk2440.h 中,修改宏定义
        #define CONFIG_SYS_PROMPT"MIMI2440 # "
   14、制作补丁文件
        将修改好的u-boot2012文件夹重命名为 u-boot2012.04.1_OK 然后再解压一份源码
        制作补丁前先清理生成的文件:
        make clean
        rm u-boot u-boot.bin u-boot.map u-boot.srec System.map
        find -name "*.depend*"|rm -rf
        diff -urNu-boot2012.04.1 u-boot2012.04.1_OK u-boot2012.04.1.patch

    OK ,整个 u-boot2012 的移植工作至此告一段落~,移植耗时2天,整理博客用了一天半~~醉醉的。

1 0
原创粉丝点击