邮箱:zhuimengcanyang@163.com 痴爱嵌入式技术的蜗牛
分类: 嵌入式
2015-07-14 16:45:54
点击(此处)折叠或打开
// 在nor启动的时候,同样打印错误的信息,这里flash_init函数没有起到检测作用,进去看看。
改为:
puts("0 kb\r\n")
U-Boot 2012.04.01 (Jul 13 2015 - 20:33:34) CPUID: 32440001 FCLK: 400 MHz HCLK: 100 MHz PCLK: 50 MHz DRAM: 64 MiB WARNING: Caches not enabled Flash: *** failed *** ### ERROR ### Please RESET the board ### |
看该型号的技术手册1. 读取flash的信息:static void flash_read_jedec_ids (flash_info_t * info)
开发板是用16位宽的连线连接到nor flash,所以发出的地址是word 类型的。
a. 如果读取 Manifacture ID,步骤为:
(1)向地址为 555 的地方发送数据为 AA (解锁地址1)
(2)向地址为 2AA 的地方发送数据为 55 (解锁地址2)
(3)向地址为 555 的地方发送数据为 90 (实际读取地址)
(4)读取地址为x00 的地方,返回的为:C2H,为厂家ID。(真正读取数据)
b. 读取设备ID,可以按照上面同样的方式,发送的信息见表格所示。
型号为MX29LV160DB的nor flash的设备ID为:0x2249
根据打印信息
U-Boot 2012.04.01 (Jul 13 2015 - 22:34:24)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: fwc addr (null) 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 (null) cmd f0 00f0 16bit x 16 bit
JEDEC PROBE: ID c2 2249 0
fwc addr (null) cmd ff 00ff 16bit x 16 bit
fwc addr (null) cmd 90 0090 16bit x 16 bit
fwc addr (null) cmd ff 00ff 16bit x 16 bit
JEDEC PROBE: ID 13 ea00 0
0KB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
SMDK2410 #
unsigned long flash_init (void)
static int flash_detect_legacy(phys_addr_t base, int banknum)
jedec_flash_match函数:
点击(此处)折叠或打开
- /*-----------------------------------------------------------------------
- * match jedec ids against table. If a match is found, fill flash_info entry
- */
- int jedec_flash_match(flash_info_t *info, ulong base)
- {
- int ret = 0;
- int i;
- ulong mask = 0xFFFF;
- if (info->chipwidth == 1)
- mask = 0xFF;
- for (i = 0; i < ARRAY_SIZE(jedec_table); i++) { // 遍历这个jedec_table[] 这个表里面是不是有匹配的选项,如果有,则进行信息的填充。
- if ((jedec_table[i].mfr_id & mask) == (info->manufacturer_id & mask) && // 貌似这里这是比较厂家ID和设备ID
- (jedec_table[i].dev_id & mask) == (info->device_id & mask)) {
- fill_info(info, &jedec_table[i], base); // 找到匹配的flash选项,则进行信息的填充。
- ret = 1;
- break;
- }
- }
- return ret;
- }
点击(此处)折叠或打开
- static const struct amd_flash_info jedec_table[] = {
- {
- .mfr_id = (u16)SST_MANUFACT,
- .dev_id = SST39LF040,
- .name = "SST 39LF040",
- .uaddr = {
- [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x01000,128),
- }
- },
- {
- .mfr_id = (u16)STM_MANUFACT,
- .dev_id = STM_ID_M29W040B,
- .name = "ST Micro M29W040B",
- .uaddr = {
- [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000,8),
- }
- },
- {
- .mfr_id = (u16)MX_MANUFACT,
- .dev_id = MX29LV040,
- .name = "MXIC MX29LV040",
- .uaddr = {
- [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000, 8),
- }
- },
- {
- .mfr_id = (u16)WINB_MANUFACT,
- .dev_id = W39L040A,
- .name = "WINBOND W39L040A",
- .uaddr = {
- [0] = MTD_UADDR_0x5555_0x2AAA /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000, 8),
- }
- },
- {
- .mfr_id = (u16)AMIC_MANUFACT,
- .dev_id = A29L040,
- .name = "AMIC A29L040",
- .uaddr = {
- [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000, 8),
- }
- },
- {
- .mfr_id = (u16)EON_MANUFACT,
- .dev_id = EN29LV040A,
- .name = "EON EN29LV040A",
- .uaddr = {
- [0] = MTD_UADDR_0x0555_0x02AA /* x8 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = P_ID_AMD_STD,
- .NumEraseRegions= 1,
- .regions = {
- ERASEINFO(0x10000, 8),
- }
- },
- #endif
- #ifdef CONFIG_SYS_FLASH_LEGACY_512Kx16
- {
- .mfr_id = (u16)AMD_MANUFACT,
- .dev_id = AM29F400BB,
- .name = "AMD AM29F400BB",
- .uaddr = {
- [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = CFI_CMDSET_AMD_LEGACY,
- .NumEraseRegions= 4,
- .regions = {
- ERASEINFO(0x04000, 1),
- ERASEINFO(0x02000, 2),
- ERASEINFO(0x08000, 1),
- ERASEINFO(0x10000, 7),
- }
- },
- {
- .mfr_id = (u16)AMD_MANUFACT,
- .dev_id = AM29LV400BB,
- .name = "AMD AM29LV400BB",
- .uaddr = {
- [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = CFI_CMDSET_AMD_LEGACY,
- .NumEraseRegions= 4,
- .regions = {
- ERASEINFO(0x04000,1),
- ERASEINFO(0x02000,2),
- ERASEINFO(0x08000,1),
- ERASEINFO(0x10000,7),
- }
- },
- {
- .mfr_id = (u16)AMD_MANUFACT,
- .dev_id = AM29LV800BB,
- .name = "AMD AM29LV800BB",
- .uaddr = {
- [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
- },
- .DevSize = SIZE_1MiB,
- .CmdSet = CFI_CMDSET_AMD_LEGACY,
- .NumEraseRegions= 4,
- .regions = {
- ERASEINFO(0x04000, 1),
- ERASEINFO(0x02000, 2),
- ERASEINFO(0x08000, 1),
- ERASEINFO(0x10000, 15),
- }
- },
- {
- .mfr_id = (u16)STM_MANUFACT,
- .dev_id = STM29F400BB,
- .name = "ST Micro M29F400BB",
- .uaddr = {
- [1] = MTD_UADDR_0x0555_0x02AA /* x16 */
- },
- .DevSize = SIZE_512KiB,
- .CmdSet = CFI_CMDSET_AMD_LEGACY,
- .NumEraseRegions = 4,
- .regions = {
- ERASEINFO(0x04000, 1),
- ERASEINFO(0x02000, 2),
- ERASEINFO(0x08000, 1),
- ERASEINFO(0x10000, 7),
- }
- },
- #endif
// 参照前面的,自己增加一项,板子用的是MT29LV160DB, 1Mx16位宽 = 2M in total
{
.mfr_id = (u16)MX_MANUFACT,
.dev_id = 0x2249, // 这是设备ID,看手册知道
.name = "MXIC MX29LV160DB", // 名字无所谓
.uaddr = { // nor flash看到的解锁地址,注意:在硬件连线上是板子的A1接到nor的A0口线上的。
//[0] = MTD_UADDR_0x0555_0x02AA // 数组下标为"0",表示8位线宽
[1] = MTD_UADDR_0x0555_0x02AA // 数组下标为"1",表示16位线宽,以此类推,这个"0x0555_0x02AA"表示解锁地址
},
.DevSize = SIZE_2MiB, // 注意:NOR flash总的大小为 2M
.CmdSet = P_ID_AMD_STD, // 擦除区域是指不同分区的个数。
//.NumEraseRegions= 1,
//.regions = {
// ERASEINFO(0x10000, 8),
修改为:
.NumEraseRegions= 4, // 比如MT29LV160DB 有16K X1, 8KX2, 32KX1, 64K X 31,所以有四个擦除区域
.regions = {
ERASEINFO(16*1024, 1),
ERASEINFO(8*1024, 2),
ERASEINFO(32*1024, 1),
ERASEINFO(64*1024, 31),
}
},
};
2440和nor的接线图
那2440内部怎么知道发出(555<<1)的信号呢??
include\Flash.h
/* Manufacturers inside bank 0 have ids like 0x00xx00xx */
#define AMD_MANUFACT 0x00010001 /* AMD manuf. ID in D23..D16, D7..D0 */
#define FUJ_MANUFACT 0x00040004 /* FUJITSU manuf. ID in D23..D16, D7..D0 */
#define ATM_MANUFACT 0x001F001F /* ATMEL */
#define STM_MANUFACT 0x00200020 /* STM (Thomson) manuf. ID in D23.. -"- */
#define SST_MANUFACT 0x00BF00BF /* SST manuf. ID in D23..D16, D7..D0 */
#define MT_MANUFACT 0x00890089 /* MT manuf. ID in D23..D16, D7..D0 */
#define INTEL_MANUFACT 0x00890089 /* INTEL manuf. ID in D23..D16, D7..D0 */
#define INTEL_ALT_MANU 0x00B000B0 /* alternate INTEL namufacturer ID */
//可以看到mx的厂家ID 为 C2 和这里对应。
#define MX_MANUFACT 0x00C200C2 /* MXIC manuf. ID in D23..D16, D7..D0 */
#define TOSH_MANUFACT 0x00980098 /* TOSHIBA manuf. ID in D23..D16, D7..D0 */
#define MT2_MANUFACT 0x002C002C /* alternate MICRON manufacturer ID*/
#define EXCEL_MANUFACT 0x004A004A /* Excel Semiconductor */
#define AMIC_MANUFACT 0x00370037 /* AMIC manuf. ID in D23..D16, D7..D0 */
#define WINB_MANUFACT 0x00DA00DA /* Winbond manuf. ID in D23..D16, D7..D0 */
重新编译烧写,打印信息:
U-Boot 2012.04.01 (Jul 13 2015 - 23:18:45)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: ERROR: too many flash sectors
2 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
SMDK2410 #
修改:在文件:include\configs\smdk2440.h
将 #define CONFIG_SYS_MAX_FLASH_SECT (19)重新编译,烧写进板子,该句信息消失。已经检测到nor flash的大小为2MB.
改为:
#define CONFIG_SYS_MAX_FLASH_SECT (128)
U-Boot 2012.04.01 (Jul 13 2015 - 23:31:59)
CPUID: 32440001
FCLK: 400 MHz
HCLK: 100 MHz
PCLK: 50 MHz
DRAM: 64 MiB
WARNING: Caches not enabled
Flash: 2 MiB
*** Warning - bad CRC, using default environment
In: serial
Out: serial
Err: serial
Net: CS8900-0
SMDK2410 #
3.1 查看nor的基本信息
输入命令,查看nor flash的信息,可以看到nor flash的情况,厂家ID,设备ID,分区情况,读取指令集等。
RO 表示为只读块,这只是软件上的一种限制,硬件上肯定是可以读和写的了。
SMDK2410 # flinfo
Bank # 1: MXIC MX29LV160DB flash (16 x 16) Size: 2 MB in 35 Sectors
AMD Legacy command set, Manufacturer ID: 0xC2, 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
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
3.2 解除nor的保护机制,全部变为可读可写
SMDK2410 # protect off all
Un-Protect Flash Bank # 1
3.3 测试
u-boot本身的大小大概512k左右,从nor flash上的零地址处开始存放,为了不破坏NOR上的uboot,这里擦除512k(512k = 80000)之后的64K大小进行试验。
(1) 擦除:必须以整块擦除NOR
80000:表示开始地址;8ffff: 表示结束地址 (注意和上面的分区大小一致:00080000 --> 00090000)
SMDK2410 # erase 80000 8ffff
. done
Erased 1 sectors
(2)拷贝数据从SDRAM到nor flash中
30000000:表示sdram的起始地址
80000: 表示nor flash的起始地址
10000:表示拷贝数据的大小,为64K
SMDK2410 # cp.b 30000000 80000 10000
Copy to Flash... 9....8....7....6....5....4....3....2....1....done
(3)比较数据是否正确
数据是一致的。
SMDK2410 # md.b 30000000
30000000: ff 5f d3 7e 7f db 5e d6 db fa 5e fa 5a 7f df 7b ._.~..^...^.Z..{
30000010: dd 7a ff df db fa 7d 5b bb 66 de d9 57 7e ff df .z....}[.f..W~..
30000020: 9f cb de a9 ff 6b 5b db e8 ff ff ff 7f 7b 5b 79 .....k[......{[y
30000030: dd 5e 9b 40 fa 5c 7f 5b fe fb 5b 7f 37 5b 7b 5e .^.@.\.[..[.7[{^
SMDK2410 # md.b 80000
00080000: ff 5f d3 7e 7f db 5e d6 db fa 5e fa 5a 7f df 7b ._.~..^...^.Z..{
00080010: dd 7a ff df db fa 7d 5b bb 66 de d9 57 7e ff df .z....}[.f..W~..
00080020: 9f cb de a9 ff 6b 5b db e8 ff ff ff 7f 7b 5b 79 .....k[......{[y
00080030: dd 5e 9b 40 fa 5c 7f 5b fe fb 5b 7f 37 5b 7b 5e .^.@.\.[..[.7[{^
(4)修改一个数据,看是否还一致。
mw.b命令只写一个byte,所以这里只写一个字节为0X78
SMDK2410 # mw.b 30000000 12345678
擦除
SMDK2410 # erase 80000 8ffff
. done
Erased 1 sectors
拷贝数据从SDRAM到nor flash
SMDK2410 # cp.b 30000000 80000 10000
Copy to Flash... 9....8....7....6....5....4....3....2....1....done
读nor flash数据(长度怎么没定??),数据0x78被写进去了。
SMDK2410 # md.b 80000
00080000: 78 5f d3 7e 7f db 5e d6 db fa 5e fa 5a 7f df 7b x_.~..^...^.Z..{
00080010: dd 7a ff df db fa 7d 5b bb 66 de d9 57 7e ff df .z....}[.f..W~..
00080020: 9f cb de a9 ff 6b 5b db e8 ff ff ff 7f 7b 5b 79 .....k[......{[y
00080030: dd 5e 9b 40 fa 5c 7f 5b fe fb 5b 7f 37 5b 7b 5e .^.@.\.[..[.7[{^
读SDRAM数据(同样长度没有定),0x78被拷贝过来了。
SMDK2410 # md.b 30000000
30000000: 78 5f d3 7e 7f db 5e d6 db fa 5e fa 5a 7f df 7b x_.~..^...^.Z..{
30000010: dd 7a ff df db fa 7d 5b bb 66 de d9 57 7e ff df .z....}[.f..W~..
30000020: 9f cb de a9 ff 6b 5b db e8 ff ff ff 7f 7b 5b 79 .....k[......{[y
30000030: dd 5e 9b 40 fa 5c 7f 5b fe fb 5b 7f 37 5b 7b 5e .^.@.\.[..[.7[{^
比较数据发现有不同的地方
SMDK2410 # cmp.b 30000000 80000 10000
byte at 0x30000b70 (0x01) != byte at 0x00080b70 (0x09)
Total of 2928 bytes were the same
数据比较不同,到底是什么原因,是源地址的数据改变了,还是怎么回事呢?这里修改源地址(SDRAM的地址)看看。
(5)修改源地址,重新拷贝,比较
将源地址30000000改为:32000000,比较发现相同。
SMDK2410 # erase 80000 8ffff
. done
Erased 1 sectors
SMDK2410 # cp.b 32000000 80000 10000
Copy to Flash... 9....8....7....6....5....4....3....2....1....done
SMDK2410 # cmp.b 32000000 80000 10000
Total of 65536 bytes were the same
发现原来程序一个bug,原来的程序只是在第一阶段设置了栈,sp = 0x3000 0f80,在调用C函数的时候,栈是在不断变化,导致30000000处的数据是不断变化的
在u-boot的第二阶段,应该重新设置栈到高的地址处。
修改代码:
(1)\arch\arm\cpu\arm920t\start.S
// 声明变量
.globl base_sp
base_sp:
.long 0
.....
/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
ldr r0,=0x00000000
bl board_init_f
ldr r1, _TEXT_BASE
ldr sp, base_sp /* 重新设置栈,其中base_sp是在上面的函数board_init_f中进行赋值的,它是C函数。怎么传递到汇编程序里面呢?*/
/* 调用第二阶段的代码*/
bl board_init_r
(2)\arch\arm\lib\Board.c
unsigned int board_init_f(ulong bootflag)
{
extern ulong base_sp;
.....
gd->relocaddr = addr;
gd->start_addr_sp = addr_sp;
gd->reloc_off = addr - _TEXT_BASE;
debug("relocation Offset is: %08lx\n", gd->reloc_off);
memcpy(id, (void *)gd, sizeof(gd_t));
//relocate_code(addr_sp, id, addr);
base_sp = addr_sp;
return (unsigned int)id;
}
问题:之前的做法是在0x30000000附近读取,比较数据有误,把SP指向高地址处,那如果现在读数据刚好也在高地址处的SP的话,不是同样有这个问题吗???
回答:
从前面第一阶段启动代码中的内存分布可以知道,在SDRAM的起始地址处分配了一段栈空间,但是这个空间大小太有限了。当将Nor中的数据拷贝到SDRAM的0X30000000处时,随着函数的调用执行,很可能函数内部定义的局部变量会重新覆盖这些栈空间,导致SDRAM的0x30000000处的拷贝数据被改写。
所以应该将SP的指针指向高地址处,因为那里有更广阔的内存空间,可以随便弄啊。。。。哈哈。
3.4 下载
使用超级终端,loady模式,以及现在的u-boot更新程序。按照前面测试步骤,重新测试就OK了。
a 先把数据发送到SDRAM中
b 再将数据拷贝到nor flash中的0地址开始处
c 启动开发板
SMDK2410 # flinfo
Bank # 1: MXIC MX29LV160DB flash (16 x 16) Size: 2 MB in 35 Sectors
AMD Legacy command set, Manufacturer ID: 0xC2, 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
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
Un-Protect Flash Bank # 1
SMDK2410 # flinfo
Bank # 1: MXIC MX29LV160DB flash (16 x 16) Size: 2 MB in 35 Sectors
AMD Legacy command set, Manufacturer ID: 0xC2, Device ID: 0x2249
Erase timeout: 30000 ms, write timeout: 100 ms
Sector Start Addresses:
00000000 00004000 00006000 00008000 00010000
00020000 00030000 00040000 00050000 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
SMDK2410 # erase 80000 8ffff
. done
Erased 1 sectors
SMDK2410 # cp.b 30000000 80000 10000
Copy to Flash... 9....8....7....6....5....4....3....2....1....done
SMDK2410 # md.b 30000000
30000000: 78 5f d3 7e 77 db 5e d6 db fa 5e fa 5a 7f df 7b x_.~w.^...^.Z..{
30000010: dd 7a ff df db fa 7d 5b bb 66 de d9 57 7e ff df .z....}[.f..W~..
30000020: 9f cb de a9 ff 6b 5b db e8 ef ff ff 7f 7b 5b 79 .....k[......{[y
30000030: dd 5c 9b 40 fa 5c 7f 5b fe fb 5b 7f 37 5b 7b 5e .\.@.\.[..[.7[{^
SMDK2410 # md.b 80000
00080000: 78 5f d3 7e 77 db 5e d6 db fa 5e fa 5a 7f df 7b x_.~w.^...^.Z..{
00080010: dd 7a ff df db fa 7d 5b bb 66 de d9 57 7e ff df .z....}[.f..W~..
00080020: 9f cb de a9 ff 6b 5b db e8 ef ff ff 7f 7b 5b 79 .....k[......{[y
00080030: dd 5c 9b 40 fa 5c 7f 5b fe fb 5b 7f 37 5b 7b 5e .\.@.\.[..[.7[{^
SMDK2410 # cmp.b 30000000 80000 10000
Total of 65536 bytes were the same
1. 分析源码中的NOR flash的检测流程
2. 根据自身的NOR flash,查看datasheet,看读写命令操作等。
3. 将NOR flash的信息添加到相应的表格
4. 测试