今天flash终于可以正常识别了,找了一个星期的原因,原来是flash的头文件中定义有问题,导致flash不能读取ID,我的Flash型号是SST39LV6401B,16位总线宽度,8MByte存储空间。
详细问题是这样的:在u-boot启动时会提示
## Unknown FLASH on Bank 0。
我用Source Insight 3.5建立工程,看u-boot的源文件。说实在话,u-boot的文件可真是够乱的,实在是受不了其中的函数调用,要不断的切换文件路径,要不是有Source Insight可以跟踪查找,你要自己找函数的互相调用和定义,估计你可以叫救护车来给你守着了,u-boot编的真tmd费劲!!!
分析一下u-boot的启动过程。u-boot启动时先进入cpu/arm7tdmi/start.S文件,在这个文件中初始化了cpu的一些参数,设置了外围总线。然后又跳到lib_arm/board.c中的void start_armboot (void)中,在这个函数中,弄了一个init_fnc_t **init_fnc_ptr,这个怪怪的,反正是负责初始化各个外围器件,包括了串口、dram等;同时在此处显示了u-boot的版本,ram配置信息。然后又有几个函数做了些事情,着急,看与Flash无关,所以不管了。
接下来遇到一个size = flash_init (); 嗯,看名字flash_init ()这个就是负责初始化flash了,这个函数在board/lpc2294.c/flash.c中,flash_init ()开始后的第一个调用就是:
size_b0 = flash_get_size((vu_long *)CFG_FLASH_BASE, &flash_info[0]);
if (flash_info[0].flash_id == FLASH_UNKNOWN) {
printf ("## Unknown FLASH on Bank 0 - Size = 0x%08lx = %ld MB/n",
size_b0, size_b0<<20);
}
这里调用了flash_get_size函数,flash_get_size顾名思义就是得到flash的型号,大小的函数,而接下来的一句就打印出了提示信息。
我的flash不认识,显示“## Unknown FLASH on Bank 0 - Size = 0x00000000 = 0 MB"”可能就是因为通过flash_get_size后,返回的flash_info[0].flash_id是一个unknown,所以提示不识别flash。
跟踪进入flash_get_size()函数,
static ulong flash_get_size (vu_long *addr, flash_info_t *info){}
分析这些参数,vu_long在include/common.h中为
typedef volatile unsigned long vu_long; //易变的长整型,32位
第二个参数flash_info_t在include/flash.h中为:
typedef struct {
ulong size; /* total bank size in bytes */
……
uchar protect[CFG_MAX_FLASH_SECT]; /* sector protection status */
#ifdef CFG_FLASH_CFI
uchar portwidth; /* the width of the port */
……
ushort interface; /* used for x8/x16 adjustments */
#endif
} flash_info_t; //ok, 一个结构体
所以第一个入参是一个指针变量,它指向一个的易变的32位整形, 第二个是指向flash_info_t结构体类的指针变量。
接下来分析flash_get_size函数的具体内容:
volatile CFG_FLASH_WORD_SIZE *addr2 = (CFG_FLASH_WORD_SIZE *)addr;
这一句将传进来的addr的内容赋值给addr2,我理解addr2这个指针指向的地址为*addr,也就是flash的基地址。
接下来就是读ID函数了:
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00AA00AA; addr2[CFG_FLASH_ADDR1] = (CFG_FLASH_WORD_SIZE)0x00550055;
addr2[CFG_FLASH_ADDR0] = (CFG_FLASH_WORD_SIZE)0x00900090;
value = addr2[CFG_FLASH_READ0];
switch (value) {
case (CFG_FLASH_WORD_SIZE)AMD_MANUFACT:
info->flash_id = FLASH_MAN_AMD;
break;
……
default:
info->flash_id = FLASH_UNKNOWN;
info->sector_count = 0;
info->size = 0;
return (0); /* no or unknown flash */
}
CFG_FLASH_ADDR0在include/configs/lpc2294.h中定义为0x5555,同样ADDR1和READ0也都已经定义好。(CFG_FLASH_WORD_SIZE)0x00AA00AA在CFG_FLASH_WORD_SIZE不是32位是可以自动截断的,也不需要修改。这些是符合标准的flash接口定义的,其实都不需修改。
前三句分别在flash的地址上写入0x00AA,跟flash的手册对照一下,没有什么不同。接下来就应该能读出flash的ID了,可为什么我的info->flash_id是FLASH_UNKNOWN呢?
我在switch (value){}之后加一个printf函数输出value的值,发现value值根本就是flash在0x80000000的数据值,也就是定义的中断向量表。
晕啊,说明根本没有将软指令写进flash中,又将CFG_FLASH_READ0改为其他一个比较奇怪的地址,发现读出来的值和用ADS中显示的flash内容相同,说明读函数是没问题的。可是为啥写不进去值呢?
就这个问题,折腾了一个星期,才发现在/include/configs/lpc2294.h中对于flash宽度的定义有问题,原来定义位宽时是:
#define CFG_FLASH_WORD_SIZE unsigned long
后来我确实改过一次,当时根本没多想,就将unsigned long改成了unsigned int,看起来是减少了一半,事实上ARM作为32位CPU,其int型的也应当为32位,原来的long型把我给误导了!
在无数次阅读程序,改写程序,make distclean,;make lpc2294_config; make;烧写flash之后。一个星期都荒废过去了,终于在有一天发现CFG_FLASH_WORD_SIZE应该是unsigned short啊!
幡然醒悟,问题解决!
只是我的时间不再。
贴出来,望大家不要再犯我这样愚蠢的错误了。