MINI2440有一个2M的NOR FLASH,NOR FLASH在MINI2440上其实是一个容量较小的ROM,不过它比NAND要好的地方在于可以执行代码。当开关打在nor的时候,就选择从NOR FLASH启动,NOR FLASH是直接映射到0x00000000地址上开始工作的。关于nor和nand的区别以及在mini2440上启动时候的差别请参看CSDN上的帖子,分析的挺好,这里不赘述了。
一.追踪cfi_flash.c和jedec_flash.c找出nor型号
后面的移植工作参照网上大牛对tq2440的u-boot-2014.04的移植方法,在此对他们的工作表示感谢。
因为我们现在要在u-boot里面添加进去对我们板子上的nor flash的读写支持,
根据文件名,我查了下什么是cfi,什么是jedec,找到如下描述:
CFI为公共Flash接口[CommonFlash Interface], 用来帮助程序从Flash芯片中获取操作方式信息。
JEDEC用来帮助程序读取Flash的制造商ID和设备ID,以确定Flash的大小和算法。
首先在jedec_flash.c中添加mini2440的nor flash型号的内容。查阅mini2440用户手册知道mini2440使用的的nor flash型号为:SST39VF1602(AMD29LV160DB)与此引脚兼容。我们看到在jedec_flash.c的第47行:
#define SST39LF160 0x2782
#define SST39VF1601 0x234b
#define SST39LF512 0x00D4
同时与之兼容的AMD29LV160DB在第34行:
#define AM29LV160DT 0x22C4
#define AM29LV160DB 0x2249
#define AM29F017D 0x003D
但是我们在第一篇帖子启动的时候,最后出现的错误提示:
FLASH:***failed***
这里应该是FLASH部分出错了,我们在这两个文件里面追踪一下错误,打开DEBUG调试宏,可以看到调试信息。在两个文件头文件之前,记住一定要是头文件之前,打开DEBUG宏。
/* The DEBUG define must be before commonto enable debugging */
/*#define DEBUG*/
加入当前在u-boot的源码目录下,执行以下指令:
cd drivers/mtd/
vim jedec_flash.c
在头文件之前:defineDEBUG
另一个文件也是同样的操作,然后保存退出。重新回到源码目录重新编译。
生成的u-boot拷贝到tftpboot下。
tftp 0x30008000 u-boot.bin
go 0x30008000
结果出现如下信息:
U-Boot 2014.04 (Aug 24 2015 - 14:19:35)
CPUID: 32440001
FCLK: 400MHz
HCLK: 100MHz
PCLK: 50MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: fwc addr 00000000 cmd f0 00f0 16bit x16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16 bit
fwc addr 00005554 cmd 55 0055 16bit x 16 bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16 bit
fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID f0 ea00 0
fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
fwc addr 00000000 cmd 90 0090 16bit x 16 bit
fwc addr 00000000 cmd ff 00ff 16bit x 16 bit
JEDEC PROBE: ID 90 ea00 0
*** failed ***
### ERROR ### Please RESET the board ###
u-boot探测到的 norflash型号我们的列表里没有,ea00。难道是因为没有从norflash启动的原因,为此我在自己的nor flash里面烧写一个u-boot,然后从nor 启动再将编译好的u-boot按照上面的方法下载进去试试。
这时候打印信息如下:
U-Boot 2014.04 (Aug 24 2015 - 14:19:35)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16bit
fwc addr 00005554 cmd 55 0055 16bit x 16bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16bit
fwc addr 00000000 cmd f0 00f0 16bit x 16bit
JEDEC PROBE: ID 1 2249 0
fwc addr 00000000 cmd ff 00ff 16bit x 16bit
fwc addr 00000000 cmd 90 0090 16bit x 16bit
fwc addr 00000000 cmd ff 00ff 16bit x 16bit
JEDEC PROBE: ID 14 ea00 0
*** failed ***
### ERROR ### Please RESET the board ###
我们探测到了自己的norflash的device_id为2249,和我们的AM29LV160DB是匹配的。但是他还是提示出错误,FLASH:***failed****
使用grep “FLASH:”* -nR搜索,程序定位在arch/arm/lib/board.c
第557行:
puts("Flash: ");
flash_size = flash_init();
if (flash_size > 0)
{
******
} else { //557行
puts(failed);
hang();
}
也就是说,如果flash_size>0,才会进去,否则就输出failed,而flash_size=flash_init(),也就是说flash_init()出了问题,切过去。
flash_init()函数在文件cfi_flash.c里面,在第2332行:
unsignedlong flash_init (void)
{
unsigned long size = 0;
int i;
#ifdefCONFIG_SYS_FLASH_PROTECTION
/* read environment from EEPROM */
char s[64];
getenv_f("unlock", s,sizeof(s));
#endif
/* Init: no FLASHes known */
for (i = 0; i <CONFIG_SYS_MAX_FLASH_BANKS; ++i) {
flash_info[i].flash_id =FLASH_UNKNOWN;
/* Optionally write flashconfiguration register */
cfi_flash_set_config_reg(cfi_flash_bank_addr(i),
cfi_flash_config_reg(i));
if(!flash_detect_legacy(cfi_flash_bank_addr(i), i))
flash_get_size(cfi_flash_bank_addr(i),i);
size += flash_info[i].size;
if (flash_info[i].flash_id ==FLASH_UNKNOWN) {
#ifndef CONFIG_SYS_FLASH_QUIET_TEST
printf ("## Unknownflash on Bank %d "
"- Size =0x%08lx = %ld MB\n",
i+1,flash_info[i].size,
flash_info[i].size>> 20);
#endif /*CONFIG_SYS_FLASH_QUIET_TEST */
}
#ifdefCONFIG_SYS_FLASH_PROTECTION
else if ((s != NULL) &&(strcmp(s, "yes") == 0)) {
/*
* Only the U-Boot image and it's environment
* is protected, all other sectors are
* unprotected (unlocked) if flash hardware
* protection is used(CONFIG_SYS_FLASH_PROTECTION)
* and the environment variable"unlock" is
* set to "yes".
*/
if(flash_info[i].legacy_unlock) {
int k;
/*
* Disable legacy_unlock temporarily,
* since flash_real_protect would
* relock all other sectors again
* otherwise.
*/
flash_info[i].legacy_unlock= 0;
/*
* Legacy unlocking (e.g. Intel J3) ->
* unlock only one sector. This will
* unlock all sectors.
*/
flash_real_protect(&flash_info[i], 0, 0);
flash_info[i].legacy_unlock= 1;
/*
* Manually mark other sectors as
* unlocked (unprotected)
*/
for (k = 1; k <flash_info[i].sector_count; k++)
flash_info[i].protect[k]= 0;
} else {
/*
* No legancy unlocking -> unlock allsectors
*/
flash_protect(FLAG_PROTECT_CLEAR,
flash_info[i].start[0],
flash_info[i].start[0]
+ flash_info[i].size - 1,
&flash_info[i]);
}
}
#endif /*CONFIG_SYS_FLASH_PROTECTION */
}
这个函数看起来很长,其实分析起来很简单,根据几个CONFIG,就可以截取很大一段,最后在这一行:if(!flash_detect_legacy(cfi_flash_bank_addr(i), i)),我们进入flash_detect_legacy查看,找到如下信息:
flash_read_jedec_ids(info);
debug("JEDECPROBE: ID %x %x %x\n",
info->manufacturer_id,
info->device_id,
info->device_id2);
if (jedec_flash_match(info, info->start[0]))
break;
说明我们这里不成功是因为没有匹配成功,为什么没有成功,是因为在jedec_table的表中没有定义,要添加进去,就可以了。
修改jedec_flash.c,在函数amd_flash_info jedec_table[]添加AM29LV160DB的信息,这个信息在哪里找呢,可以打开j-flash就是我们用j-link烧写u-boot的时候,选择nor flash型号的时候,有相关的信息,尤其是这里的Num sectors。
打开软件j-flash,在options->project settings->flash->selectflash device里面可以看到如下图的信息:
二.修改jedec_flash.c,mini2440.h,cfi_flash.c
根据这部分的信息我们去修改,因为里面已经有相似的代码,可以拷贝512K*16部分的进行修改,添加代码如下:
#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16
{
.mfr_id = (u16)AMD_MANUFACT,
.dev_id = AM29LV160DB,
.name = "AMD AM29LV160DB,migrated by Deep_l_zh",
.uaddr = {
[1] =MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x04000, 1),
ERASEINFO(0x02000, 2),
ERASEINFO(0x08000, 1),
ERASEINFO(0x10000, 7),
}
},
#endif
接着,要在mini2440.h里面将这个配置加进去,在第153行,更改如下:
//#define CONFIG_SYS_FLASH_LEGACY_512Kx16
#define CONFIG_SYS_FLASH_LEGACY_1024Kx16
在下面,因为我们的sectors也要设置,所以还在mini2440.h里面第160行,更改如下:
//#define CONFIG_SYS_MAX_FLASH_SECT (19)
#define CONFIG_SYS_MAX_FLASH_SECT (35)
最后编译,拷贝到tftpboot目录,从nor flash启动,利用tftp0x30008000 u-boot.bin以及go 0x30008000启动,得到如下信息:
[u-boot@SMDK2440A]# go 0x30008000
## Starting application at 0x30008000 ...
U-Boot 2014.04 (Aug 24 2015 - 16:44:29)
CPUID: 32440001
FCLK: 400MHz
HCLK: 100MHz
PCLK: 50MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16 bit
fwc addr 00005554 cmd 55 0055 16bit x 16 bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16 bit
fwc addr 00000000 cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID 1 2249 0
Found JEDEC Flash: AMD AM29LV160DB,migratedby Deep_l_zh
unlock address index 1
unlock addresses are 0x555/0x2aa
erase_region_count = 1 erase_region_size = 16384
erase_region_count = 2 erase_region_size = 8192
erase_region_count = 1 erase_region_size = 32768
erase_region_count = 7 erase_region_size = 65536
512 KiB 这里出问题了
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: Noethernet found.
MINI2440 #
说明我们已经成功了,红色是我们修改希望看到的信息。下面根据u-boot的nor flash命令来测试一下是否成功,参考友善之臂2010的手册里面U-boot的命令熟悉,输入flinfo,看到如下信息:
MINI2440 # flinfo
Bank # 1: AMDAM29LV160DB,migrated by Deep_l_zh flash (16 x 16) Size: 512 kB in 11 Sectors
AMD Legacy command set, Manufacturer ID:0x01, Device ID: 0x2249
Erase timeout: 30000 ms, write timeout: 100ms
Sector Start Addresses:
00000000 RO 00004000 RO 00006000 RO 00008000 RO 00010000 RO
00020000 RO 00030000 00040000 00050000 00060000
00070000 RO
三.粗心大意绕弯子
这里发现一个错误,我们的nor应该是2M的,为什么这里打印的是512kB的,回去看之前的信息也是512K,这里首先关闭DEBUG宏,看一下编译输出的信息还是显示FLASH是512KB。这时候我从nor启动之后,直接在原先就有的u-boot里面输入flinfo,出现如下消息:
[u-boot@SMDK2440A]#flinfo
Bank #1: SST: 1x SST39VF1601 (2MB)
Size: 2 MB in 32 Sectors
Sector Start Addresses:
00000000 (RO) 00010000 (RO) 00020000 (RO)00030000 (RO) 00040000 (RO)
00050000 (RO) 00060000 00070000 00080000 00090000
000A0000 000B0000 000C0000 000D0000 000E0000
000F0000 00100000 00110000 00120000 00130000
00140000 00150000 00160000 00170000 00180000
00190000 001A0000 001B0000 001C0000 001D0000
001E0000 001F0000
这里的nor 型号居然变成了SST39VF1601,再回去修改。在jedec_flash.c里面,有SST39VF1601的device_id,如下#define SST39VF1601 0x234b,可是前面我们调试出来的是2249,由于SST39VF1601和AM29LV160DB的引脚相同,所以这里其实还是SST39VF1601,我一开始看到打印出来是AM29LV160DB的ID就认为是这个了,具体原因还不清楚,返回去修改jedec_flash.c。
将添加进去的代码修改如下:
#ifdef CONFIG_SYS_FLASH_LEGACY_1024Kx16
{
.mfr_id = (u16)SST_MANUFACT,
.dev_id = SST39VF1601,
.name = "SST SST39VF1601,migrated byDeep_l_zh",
.uaddr = {
[1]= MTD_UADDR_0x0555_0x02AA /* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions=4,
.regions = {
ERASEINFO(0x04000,1),
ERASEINFO(0x02000,2),
ERASEINFO(0x08000,1),
ERASEINFO(0x10000,7),
}
},
#endif
重新编译,报错,FLASH:failed.仔细一看,自己的这一行里面的代码没有修改, ERASEINFO(0x04000, 1),
ERASEINFO(0x02000,2),
ERASEINFO(0x08000,1),
ERASEINFO(0x10000,7),
这里应该是ERASEINFO(0x10000, 31),就是这么粗心的一个小错误让自己绕了一大圈,我将这部分写下来也是为了告诉各位同道,也许有时候错误就是这样子,细心细心再细心。
四.最终修改的jedec_flash.c
最终这部分修改成这样:
#ifdefCONFIG_SYS_FLASH_LEGACY_1024Kx16
{
.mfr_id = (u16)AMD_MANUFACT,
.dev_id = AM29LV160DB,
.name = "AMD AM29LV160DB,migrated by Deep_l_zh",
.uaddr = {
[1] = MTD_UADDR_0x0555_0x02AA/* x16 */
},
.DevSize = SIZE_2MiB,
.CmdSet = P_ID_AMD_STD,
.NumEraseRegions= 4,
.regions = {
ERASEINFO(0x04000, 1),
ERASEINFO(0x02000, 2),
ERASEINFO(0x08000, 1),
ERASEINFO(0x10000, 31),
}
},
#endif
编译,下载,运行,通过后如下:
U-Boot 2014.04 (Aug 24 2015 - 19:20:06)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: fwc addr 00000000 cmd f0 00f0 16bitx 16 bit
fwc addr 0000aaaa cmd aa 00aa 16bit x 16bit
fwc addr 00005554 cmd 55 0055 16bit x 16bit
fwc addr 0000aaaa cmd 90 0090 16bit x 16bit
fwc addr 00000000 cmd f0 00f0 16bit x 16bit
JEDEC PROBE: ID 1 2249 0
Found JEDEC Flash: AMDAM29LV160DB,migrated by Deep_l_zh
unlock address index 1
unlock addresses are 0x555/0x2aa
erase_region_count = 1 erase_region_size =16384
erase_region_count = 2 erase_region_size =8192
erase_region_count = 1 erase_region_size =32768
erase_region_count = 31 erase_region_size =65536
2 MiB
*** Warning - bad CRC, using defaultenvironment
In: serial
Out: serial
Err: serial
Net: No ethernet found.
五.读写测试
说明成功了,再进行测试,输入:flsinfo,输出如下信息:
Bank # 1: AMD AM29LV160DB,migrated byDeep_l_zh flash (16 x 16) Size: 2 MB in35 Sectors
AMDLegacy 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 00040000 00050000 00060000
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
测试flash读:
md.b 0x0 20
00000000: 14 00 00 ea 14 f0 9f e5 14 f0 9fe5 14 f0 9f e5 ................
00000010: 14 f0 9f e5 14 f0 9f e5 14 f0 9fe5 14 f0 9f e5 ................
成功。
测试写数据对比:
先解保护,protect on/off start end,这里读R0从0地址开始一段,所以:
protect off 0x0 0x00003fff
会提示:Un-Protected 1 sectors
我们只把R0解保护了,后面的这个end地址必须是sector的边缘地址,否则会报错。因为R1的起始地址是0x00004000,所以r1就是0x00003fff。
MINI2440 Deep_l_zh # cp.b 30008000 0 10
Copy to Flash... Flash not Erased
MINI2440 Deep_l_zh # cmp.b 0 30008000 10
byte at 0x00000000 (0x14) != byte at0x30008000 (0xf)
Total of 0 byte(s) were the same
说明写没有问题。
再来把刚才写的读出来对比:
MINI2440 Deep_l_zh # md.b 30008000 10
30008000: 0f 00 00ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................
MINI2440 Deep_l_zh# md.b 0 10
00000000: 14 00 00ea 14 f0 9f e5 14 f0 9f e5 14 f0 9f e5 ................
和刚才一样,两分数据相同,说明nor flash的读写移植已经成功。
就这样吧,如有不正的地方还请指出,共同进步!