上一节中讲到,以spl方式启动的uboot和以NorFlash启动的代码不能共用一套u-boot代码,所以这一节讲解修改目前的uboot代码支持NorFlash启动。当然你得先保存修改到目前的uboot代码,并且由于有前面修改的铺垫,这一节修改尽量言简意赅。
压缩命令:
tar zcvf u-boot-2015.07rc3-serial_ok.tar.gz u-boot-2015.07-rc3
|
在修改之前啰嗦两句,uboot从NandFlash启动的主流程是:垫脚石中的代码拷贝NandFlash中的u-boot代码到内存A处并跳转到A处运行,在A处的uboot自动计算新的内存地址B并把A处的uboot代码拷贝至B处,跳转到B处执行。
uboot从NorFlash启动时由于cpu在NorFlash中就可以完成寻址、取指,所以uboot直接就可以在NorFlash中运行。因此uboot从NorFlash启动的话就没必要把NorFlash中的代码拷贝到内存A处了,NorFlash启动的uboot直接在NorFlash中运行后会自动计算出一个内存地址B,然后把NorFlash中的uboot拷贝到内存B处并跳转到B处的uboot执行。
下面就来修改现有的代码以支持NorFlash启动:
make menuconfig 取消SPL启动
Boot images --->
[ ] SUPPORT_SPL
|
smdk2440.h中:
23 #define CONFIG_S3C2440
24 #define CONFIG_SMDK2440
25 #define CONFIG_SYS_TEXT_BASE 0x0
|
start.S中:
取消在start.S中添加的CONFIG_SPL_BUILD宏开关
53 /*#if defined(CONFIG_SPL_BUILD)*/
54 #ifdef CONFIG_S3C24X0
55 /* turn off the watchdog */
56
57 # if defined(CONFIG_S3C2400)
58 # define pWTCON 0x15300000
128 /*#endif*/ /* CONFIG_SPL_BUILD */
129
130 bl _main
|
lowlevel_init.S中:
118 ldr r0, =SMRDATA
119 ldr r1, =CONFIG_SYS_TEXT_BASE
120 /*ldr r1, =0x0*/
121 sub r0, r0, r1
|
crt0.S
100 sub sp, sp, #CONFIG_SYS_MALLOC_F_LEN
101 str sp, [r9, #GD_MALLOC_BASE]
102 #endif
103 /*
104 #if defined(CONFIG_SPL_BUILD)
105
106 ldr r0, = CONFIG_UBOOT_NAND_ADDR
107 ldr r1, =CONFIG_SYS_TEXT_BASE
108 ldr r2, =CONFIG_UBOOT_LENGTH
109
110 bl copy_code_to_sdram
111
112 ldr pc, =CONFIG_SYS_TEXT_BASE
113
114 #else
115 */
116 /* mov r0, #0 not needed due to above code */
117 ldr r0,=0x00000000
118 bl board_init_f
119
120 /*#endif*/
121
122 #if ! defined(CONFIG_SPL_BUILD)
|
修改到这里,make编译,编译通过。使用JLink/JTag下载到NorFlash中,以nor启动就能看到uboot已经正常输出了。同样的,在drivers/mtd/cfi_flash.c中添加debug的宏定义以输出uboot读取到的NorFlash信息:
drivers/mtd/cfi_flash.c中
#include <common.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/byteorder.h>
#include <asm/unaligned.h>
#include <environment.h>
#include <mtd/cfi_flash.h>
#include <watchdog.h>
//#define _DEBUG 1
#define debug(fmt, args...) printf(fmt, ##args)
|
在上图中我们可以看到读取到NorFlash的ID已经不是f0 ea00 0了,现在读取到的是1 2249 0,对比这张NorFlash芯片的命令时序图可以确定现在读取到的NorFlash信息已经正确:
在上一节中我们讲到,uboot是拿读取到的这个Manufacturer ID、Device ID与drivers/mtd/jedec_flasf.c文件中的jedec_table[]数组比较,有匹配的数组元素uboot就认为支持这款NorFlash芯片,并根据数组元素中的信息来操作NorFlash。那么我们现在根据NorFlash的信息自己来添加一个数组元素,为了这个元素一定会被遍历到,把这个元素添加在宏开关之外。
drivers/mtd/jedec_flash.c文件中:
403 #endif
404
405 //MiNi2440 USE SPANSION's S29AL016J70TFI02
406 {
407 .mfr_id = (u16)0x00010001,
408 .dev_id = 0x2249,
409 .name = "SPANSION's S29AL016J70TFI02",
410 .uaddr = {
411 [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
412 },
413 .DevSize = SIZE_2MiB, /*set SIZE_1MiB is OK*/
414 .CmdSet = P_ID_AMD_STD,
415 .NumEraseRegions= 4,
416 .regions = {
417 ERASEINFO(16*1024,1),
418 ERASEINFO(8*1024,2),
419 ERASEINFO(32*1024,1),
420 ERASEINFO(64*1024,31),
421 }
422 },
423
424
425 };
426
427 static inline void fill_info(flash_info_t *info, const struct amd_flash_info *j edec_entry, ulong base)
|
现在解释每一项的含以及为什么这么填:
.mfr_id 是厂商ID 读取到的是0x01,观察数组中其他这一项的写法赋值(u16)0x00010001
.dev_id 设备ID 读取到的是2249,类比其他项赋值0x2249
.name 不重要,随便填
.uaddr 观察数组元素其他这一项的写法,可以知道16位时需要填1,8位填0,而我们的NorFlash采用的是16根数据线,所以是1;后面的MTD_UADDR_0x0555_0x02AA由于绝大多是这一项都是这么填的,先这样填,错了再回来修改
.DevSize NorFlash大小,当然是2M
.CmdSet 先设置成 P_ID_AMD_STD,错了再改
.NumEraseRegions如果NorFlash由10块128k的区域、20块256k的区域组成,那么这个值就该填2,如果全部的块都是一样大的,那么就填1,查看手册可以看到这段话:
Flexible Sector Architecture
– One 16 Kbyte, two 8 Kbyte, one 32 Kbyte, and thirty-one 64 Kbyte
sectors (byte mode)
– One 8 Kword, two 4 Kword, one 16 Kword, and thirty-one 32 Kword
sectors (word mode)
所以这一项填4
.regions 就是对.NumEraseRegions的具体表述,根据上面手册中的那段话就应该把这一项配置成
ERASEINFO(16*1024,1),
ERASEINFO(8*1024,2),
ERASEINFO(32*1024,1),
ERASEINFO(64*1024,31),
|
修改jedec_flash.c后保存make,把u-boot.bin下载到NorFlash中,可以看到已经能正常识别NorFlash大小了,但是有这么一句错误提示:
Flash: ERROR: too many flash sectors
遇到这种莫名的问题就是要grep把这句话的源码出处查出来分析原因:
root@ubuntu:/home/uboot/u-boot-2015.07-rc3# grep "too many flash sectors" * -nR
drivers/mtd/cfi_flash.c:2149: printf("ERROR: too many flash sectors\n");
Binary file drivers/mtd/cfi_flash.o matches
Binary file drivers/mtd/jedec_flash.o matches
drivers/mtd/jedec_flash.c:482: printf("ERROR: too many flash sectors\n");
打开两个文件,两个都把问题指向CONFIG_SYS_MAX_FLASH_SECT宏,这个宏原先定义的值太小,我们把这个值修改为128
smdk2440.h文件:
#define CONFIG_SYS_MAX_FLASH_SECT (128)
|
结果上面的修改,uboot已经能支持NorFlash读写了,现在来测试一下:
终端下:
SMDK2410 # flinfo //查看NorFlash信息
Bank # 1: SPANSION's S29AL016J70TFI02 flash (16 x 16) Size: 2 MB in 35 Sectors
AMD Legacy command set, Manufacturer ID: 0x01, Device ID: 0x2249
Erase timeout: 30000 ms, write timeout: 100 ms
Sector Start Addresses:
00000000 RO 00004000 RO 00006000 RO 00008000 RO 00010000 RO
00020000 RO 00030000 RO 00040000 RO 00050000 RO 00060000 RO
00070000 RO 00080000 00090000 000A0000 000B0000
000C0000 000D0000 000E0000 000F0000 00100000
00110000 00120000 00130000 00140000 00150000
00160000 00170000 00180000 00190000 001A0000
001B0000 001C0000 001D0000 001E0000 001F0000
SMDK2410 # protect off all //取消NorFlash保护
Un-Protect Flash Bank # 1
SMDK2410 # erase 80000 8ffff //擦除80000到8ffff的数据 目前u-boot.bin大
//小为509kb,80000就是512k大小,不能擦到uboot
. done
Erased 1 sectors
SMDK2410 # cp.b 30000000 80000 1000 //从0x30000000拷贝大小为0x1000的数据
//到NorFlash中0x80000处
Copy to Flash... 9....8....7....6....5....4....3....2....1....done
SMDK2410 # cmp.b 30000000 80000 1000 //比较刚才拷贝的数据是否正确
Total of 4096 byte(s) were the same //全部相同说明读写都没问题
SMDK2410 #
|
本节实现了uboot从NorFlash启动,并能够支持NorFlash读写,往后的uboot移植包括NandFlash支持、DM9000支持、mtdparts命令支持、uboot裁剪及启动参数修改、yaffs文件系统烧写支持,在后面这些移植过程中就不区分spl启动还是NorFlash启动了,两种启动方式修改的过程和地方是完全一样的。
下一节修改代码支持NandFlash读写命令。