u-boot移植中flash无法读id的问题

时间:2022-08-03 04:26:52

今天flash终于可以正常识别了,找了一个星期的原因,原来是flash的头文件中定义有问题,导致flash不能读取ID,我的Flash型号是SST39LV6401B16位总线宽度,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_longinclude/common.h中为

typedef volatile unsigned long       vu_long;         //易变的长整型,32

第二个参数flash_info_tinclude/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_ADDR0include/configs/lpc2294.h中定义为0x5555,同样ADDR1READ0也都已经定义好。(CFG_FLASH_WORD_SIZE)0x00AA00AACFG_FLASH_WORD_SIZE不是32位是可以自动截断的,也不需要修改。这些是符合标准的flash接口定义的,其实都不需修改。

前三句分别在flash的地址上写入0x00AA,跟flash的手册对照一下,没有什么不同。接下来就应该能读出flashID了,可为什么我的info->flash_idFLASH_UNKNOWN呢?

我在switch (value){}之后加一个printf函数输出value的值,发现value值根本就是flash0x80000000的数据值,也就是定义的中断向量表。

晕啊,说明根本没有将软指令写进flash中,又将CFG_FLASH_READ0改为其他一个比较奇怪的地址,发现读出来的值和用ADS中显示的flash内容相同,说明读函数是没问题的。可是为啥写不进去值呢?

就这个问题,折腾了一个星期,才发现在/include/configs/lpc2294.h中对于flash宽度的定义有问题,原来定义位宽时是:

#define CFG_FLASH_WORD_SIZE     unsigned long

后来我确实改过一次,当时根本没多想,就将unsigned long改成了unsigned int,看起来是减少了一半,事实上ARM作为32CPU,其int型的也应当为32位,原来的long型把我给误导了!

在无数次阅读程序,改写程序,make distclean,make lpc2294_config make;烧写flash之后。一个星期都荒废过去了,终于在有一天发现CFG_FLASH_WORD_SIZE应该是unsigned short啊!

幡然醒悟,问题解决!

只是我的时间不再。

 

贴出来,望大家不要再犯我这样愚蠢的错误了。