移植u-boot2012.04.1 -》2440 (五)支持 nand nor 两种启动方式(完结)
2016-09-17 13:51
609 查看
前边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地址了。
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、在第一阶段和第二阶段之间增加代码重定位等相关操作
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天,整理博客用了一天半~~醉醉的。
首先,我们得先分析一下目前的启动流程:
链接地址为 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_INIT bl cpu_init_crit #endif /******************此行之前的代码保持不变,增加*************************/ ldr sp, =(CONFIG_SYS_INIT_SP_ADDR) bic sp, sp, #7 /* 8-byte alignment for ABI compliance */ /* 判断是 nand 还是 nor 启动 */ bl isNandBoot mov r1,#0x01 cmp r0,r1 bne copy_nor /* 不相等nor 相等nand*/ copy_nand: bl my_nand_init ldr r0, =0x33f00000 mov r1, #0x00 ldr r2, =<span style="font-family: Arial, Helvetica, sans-serif;">_bss_start_ofs</span> bl my_nand_read bl clear_bss copy_nor: mov r0, #0x00 ldr r1, =0x33f00000 /* r1 <- scratch for copy_loop */ ldr r3, _bss_start_ofs add r2, r0, r3 /* r2 <- source end address */ copy_loop: ldmia r0!, {r9-r10} /* copy from source address [r0] */ stmia r1!, {r9-r10} /* copy to target address [r1] */ cmp r0, r2 /* until source end address [r2] */ blo copy_loop bl clear_bss /*****************call_board_init_f 中去掉sp的设置***********************/ call_board_init_f: ldr r0,=0x00000000 bl board_init_f /*************** 将 clear_bss 提升至 relocate_code 的前面****************/ clear_bss: #ifndef CONFIG_SPL_BUILD ldr r0, _bss_start_ofs ldr r1, _bss_end_ofs ldr r4, =0x33f00000 /* reloc addr */ add r0, r0, r4 add r1, r1, r4 mov r2, #0x00000000 /* clear */ clbss_l:str r2, [r0] /* clear loop... */ add r0, r0, #4 cmp r0, r1 bne clbss_l ldr pc, =call_board_init_f // 增加跳转到sdram的指令 #endif /*************** 去掉原有的代码重定位操作****************/ .globl relocate_code relocate_code: mov r4, r0 /* save addr_sp */ mov r5, r1 /* save addr of gd */ mov r6, r2 /* save addr of destination */ mov sp, r0 /* 设置栈 */ /* setup parameters for board_init_r */ mov r0, r5 /* gd_t */ mov r1, r6 /* dest_addr */ /* jump to it ... */ bl board_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天,整理博客用了一天半~~醉醉的。
相关文章推荐
- 移植u-boot-2012.04.01到jz2440开发板之修改代码支持NAND启动
- 2.移植uboot-添加2440单板,并实现NOR、NAND启动
- TQ2440 u-boot-2012.10移植二支持NAND启动
- u-boot2010.03 移植篇(三)-----进一步修改start.S,smdk6410.h,支持nand启动及配置DM9000网卡
- 关于u-boot同时支持nand启动和Nor启动环境变量的保存位置
- 关于u-boot同时支持nand启动和Nor启动环境变量的保存位置
- TQ2440 u-boot-2012.04.01移植二支持NAND启动
- u-boot-2009.11在mini2440上的移植,关于SDRAM&NOR&NAND启动的几点疑惑
- u-boot-2012.04.01移植笔记——支持NAND启动
- TQ2440 u-boot-2012.10移植二支持NAND启动
- u-boot-2009.08在飞凌OK2440/FL2440上的移植(二)——让u-boot支持从nor flash 启动
- u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动 .
- <2012 12 06> FL2440开发板的U-boot-2010.09版本移植(九)NAND Flash启动支持的一种新型方法,利用U-Boot自带nand_spl/nand_boot.c
- u-boot-2011.03在TQ2440上的移植(5)—实现Nand/Nor 双启动
- U-boot移植 (v2012.04.1 S3C2440平台) (二) Nand flash 启动支持
- 关于u-boot同时支持nand启动和Nor启动 环境变量的保存位置
- u-boot2010.03 移植篇(二)-----修改start.S,支持nand启动
- u-boot-2009-11移植之stage1(支持从nand启动)
- 移植u-boot-2011.03到S3C2440(utu2440)的方法与步骤###4.支持内核启动
- u-boot-2012.04.01移植笔记——支持NAND启动