Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2294853
  • 博文数量: 218
  • 博客积分: 5767
  • 博客等级: 大校
  • 技术积分: 5883
  • 用 户 组: 普通用户
  • 注册时间: 2008-03-01 14:44
文章存档

2012年(53)

2011年(131)

2009年(1)

2008年(33)

分类: 嵌入式

2011-11-04 14:31:04

u-boot-2011.09在ST2410上的移植之启用CS8900网卡功能

 

接上篇,启用CS8900网卡功能,实现tftp下载(红色部分为我添加的,蓝色为修改的)

u-boot本身有cs8900网卡驱动程序,所以需要修改的地方不多。由于数据通过总线传送,所以要注意地址空间的配置和总线的配置。

1)、首先修改include/configs/st2410.h文件

 57 #define CONFIG_NET_MULTI
 58 #define CONFIG_CS8900           /* 前文注释,这里再把它打开we have a CS8900 on-board */
 59 #define CONFIG_CS8900_BASE      0x19000300
 60 #define CONFIG_CS8900_BUS16     /* the Linux driver does accesses as shorts */

确定网卡的基地址,我的开发板CS8900接在nGCS3上,而且是A24引脚为高时使能CS8900A的IO模式,同这里配置的一样,所以代码不用修改。
117 #define CONFIG_ETHADDR          08:00:3e:26:0a:5b  //by add
118 #define CONFIG_NETMASK          255.255.255.0
119 #define CONFIG_IPADDR           192.168.1.200
120 #define CONFIG_SERVERIP         192.168.1.91

CONFIG_IPADDR     宏是你开发板的IP地址。tftp client
CONFIG_SERVERIP   宏是你安装tftp server的系统的IP
2) BWSCON寄存器的设置,BANKCON3寄存器的设置,这里不用修改,列出的目的是对不同网卡时要在这里修改,由于网卡占用的是nGCS3之上地址,所以需要设置/board/st2410/lowlevel.S文件中相应寄存器的值:
#define B3_BWSCON         (DW16 + WAIT + UBLB)
#define B3_Tacs             0x0    /* 0clk */
#define B3_Tcos             0x3    /* 4clk */
#define B3_Tacc             0x7    /* 14clk */
#define B3_Tcoh             0x1    /* 1clk */
#define B3_Tah             0x0    /* 0clk */
#define B3_Tacp             0x3 /* 6clk */
#define B3_PMC             0x0    /* normal */
3) 设置完毕后可以重新编译。

ST2410 # tftp 0x32000000 u-boot.bin
TFTP from server 192.168.1.91; our IP address is 192.168.1.200
Filename 'u-boot.bin'.
Load address: 0x32000000
Loading: #################################################################
         ############################
done
Bytes transferred = 474216 (73c68 hex)
ST2410 # go 0x32000000
## Starting application at 0x32000000 ...??

U-Boot 2011.09 (Oct 28 2011 - 07:27:57)

U-Boot code: 32000000 -> 3206B500  BSS: -> 320AEBE4
monitor len: 000AEBE4
ramsize: 04000000
TLB table at: 33ff0000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 698k for U-Boot at: 33f41000
Reserving 4160k for malloc() at: 33b31000
Reserving 24 Bytes for Board Info at: 33b30fe8
Reserving 120 Bytes for Global Data at: 33b30f70
New Stack Pointer is: 33b30f60
RAM Configuration:
Bank #0: 30000000 64 MiB
relocation Offset is: 01f41000
WARNING: Caches not enabled
monitor flash len: 00073C68
dram_bank_mmu_setup: bank: 0
Now running in RAM - U-Boot at: 33f41000
NAND:  board_nand_init()
end of nand_init
hwcontrol(): 0xff 0x83
hwcontrol(): 0xffffffff 0x81
raise: Signal # 8 caught
raise: Signal # 8 caught
dev_ready
hwcontrol(): 0x90 0x83
hwcontrol(): 0x00 0x85
hwcontrol(): 0xffffffff 0x81
raise: Signal # 8 caught
raise: Signal # 8 caught
dev_ready
hwcontrol(): 0x90 0x83
hwcontrol(): 0x00 0x85
hwcontrol(): 0xffffffff 0x81
raise: Signal # 8 caught
raise: Signal # 8 caught
dev_ready
hwcontrol(): 0xffffffff 0x80
64 MiB
*** Warning - bad CRC, using default environment

Destroy Hash Table: 33fae068 table = (null)
Create Hash Table: N=79
INSERT: table 33fae068, filled 1/79 rv 33b32438 ==> name="bootdelay" value="5"
INSERT: table 33fae068, filled 2/79 rv 33b32378 ==> name="baudrate" value="115200"
INSERT: table 33fae068, filled 3/79 rv 33b32474 ==> name="ethaddr" value="08:00:3e:26:0a:5b"
INSERT: table 33fae068, filled 4/79 rv 33b32348 ==> name="ipaddr" value="192.168.1.200"
INSERT: table 33fae068, filled 5/79 rv 33b32450 ==> name="serverip" value="192.168.1.91"
INSERT: table 33fae068, filled 6/79 rv 33b325dc ==> name="netmask" value="255.255.255.0"
INSERT: free(data = 33b322a0)
INSERT: done
In:    serial
Out:   serial
Err:   serial
Net:   raise: Signal # 8 caught
CS8900-0
### main_loop entered: bootdelay=5

### main_loop: bootcmd=""
ST2410 #

 

去掉“raise: Signal # 8 caught”

http://blog.csdn.net/zhaocj/article/details/6667758

在开发板上电后,会出现“raise: Signal # 8 caught”。这虽然不影响系统的正常运行,但也是一个不小的bug,也许会影响以后u-boot-2011.06的移植,因此我们有必要把这个bug去除掉。

其实把这个bug去掉也很简单,就是把time.c(在arch/arm/cpu/arm920t/s3c24x0/目录下)这个文件中的四个全局变量用gd这个数据结构中的4个相关成员代替就可以了,具体的就是:
timer_load_val用gd->timer_rate_hz替代;
timer_clk用gd->tbl替代;
timestamp用gd->timer_reset_value替代;
lastdec用gd->lastinc替代。

 

下面我们就列出time.c这个文件具体需要修改的地方:

去掉第38行和第39行关于timer_load_val和timer_clk这两个变量的声明,并加上下面代码:
38:DECLARE_GLOBAL_DATA_PTR;
去掉第49行和第50行关于timestamp和lastdec这两个变量的声明;
去掉第60行至第68行语句(if (timer_load_val == 0)的判断内容),改为:
60:gd->timer_rate_hz = get_PCLK() /(2*16*100);
61:gd->tbl = get_PCLK() / (2 * 16);

剩下需要修改的内容就是具体的变量替换,其中每条语句前面的行号为源文件的行号:
70         gd->lastinc = gd->timer_rate_hz;//lastdec = timer_load_val;

71:writel(gd->timer_rate_hz,&timers->tcntb4);
78:gd->timer_reset_value = 0;

 

97         tmo *= (timer_load_val * 100);

108         return tmr / (gd->tbl / CONFIG_SYS_HZ);//return tmr / (timer_clk / CONFIG_SYS_HZ);

119                 tmo *= (gd->timer_rate_hz * 100);//tmo *= (timer_load_val * 100);

122                 tmo = usec * (gd->timer_rate_hz * 100);//tmo = usec * (timer_load_val * 100);

142         if (gd->lastinc >= now) {//if (lastdec >= now) {

144                 gd->timer_reset_value += gd->lastinc - now;//timestamp += lastdec - now;
147                 gd->timer_reset_value += gd->lastinc + gd->timer_rate_hz - now;//timestamp += lastdec + timer_load_val - now;
149         gd->lastinc = now;//lastdec = now;
150
151         return gd->timer_reset_value;//return timestamp;

163         tbclk = gd->timer_rate_hz * 100;//tbclk = timer_load_val * 100;
 

通过上述的修改,我们再上电启动后,就不会再有raise: Signal # 8 caught了。
4) tftp测试:

CONFIG_DRIVER_CS8900的定义使得cs8900.c可以被编译(当然还得定义CFG_CMD_NET才行),因为 cs8900.c中在函数定义的前面就有编译条件判断:#ifdef CONFIG_DRIVER_CS8900 如果这个选项没有定义,整个cs8900.c就不会被编译了。
而常数参量CS8900_BASE则用在cs8900.h头文件中定义各个功能寄存器的地址。u-boot的CS8900工作在IO模式下,只要给定IO寄存器在内存中映射的基地址,其余代码就与平台无关了。
 
  u-boot的命令也是通过目标板的配置头文件来配置的,比如要添加ping命令,就必须添加CFG_CMD_NET和CFG_CMD_PING才行。不然common/cmd_net.c就不会被编译了。
 从这里我可以这么认为,u-boot工程可配置性和移植性可以分为两层:
 一是由makefile来实现,配置工程要包含的文件和文件夹上,用什么编译器。
 二是由目标板的配置头文件来实现源码级的可配置性,通用性。主要使用的是#ifdef #else #endif 之类来实现的。
注意:一定要将引导代码烧写到flash中引导,直接在内存调试阶段不能初始化网卡。

二)网络测试及tftp下载
在CentOS 6.0 下安装配置tftp服务 过程如下:
1. 挂载CDROM
[root@localhost mnt]# ls /dev/cdrom
/dev/cdrom
[root@localhost mnt]# mount /dev/cdrom /mnt/cdrom/

2. 安装xinetd
[root@localhost cdrom]# cd CentOS/

[root@localhost CentOS]# ls *inet*
xinetd-2.3.14-10.el5.i386.rpm
[root@localhost CentOS]# rpm -ivh xinetd-2.3.14-10.el5.i386.rpm

3. 安装tftp
[root@localhost CentOS]# ls *ftp*
ftp-0.17-35.el5.i386.rpm    tftp-0.42-3.1.el5.centos.i386.rpm
gftp-2.0.18-3.2.2.i386.rpm  tftp-server-0.42-3.1.el5.centos.i386.rpm
lftp-3.5.1-2.fc6.i386.rpm   vsftpd-2.0.5-12.el5.i386.rpm
[root@localhost CentOS]# rpm -ivh tftp-server-0.42-3.1.el5.centos.i386.rpm
[root@localhost CentOS]# rpm -ivh tftp-0.42-3.1.el5.centos.i386.rpm

4. 安装完成,查看一下
[root@localhost CentOS]# rpm -qa|grep tftp
tftp-server-0.42-3.1.el5.centos
tftp-0.42-3.1.el5.centos

5. 修改配置文件
[root@localhost CentOS]# vim /etc/xinetd.d/tftp
# default: off
# description: The tftp server serves files using the trivial file transfer \
#       protocol.  The tftp protocol is often used to boot diskless \
#       workstations, download configuration files to network-aware printers, \
#       and to start the installation process for some operating systems.
service tftp
{
        socket_type             = dgram
        protocol                = udp
        wait                    = yes
        user                    = root
        server                  = /usr/sbin/in.tftpd
        server_args             = -s /tftpboot
        disable                 = no
        per_source              = 11
        cps                     = 100 2
        flags                   = IPv4
}

6. 重启xinetd,并配置tftp开机启动
[root@localhost CentOS]# service xinetd restart
[root@localhost CentOS]# setup
修改权限:
[root@localhost /]# chmod 777 /tftpboot/
重启:
[root@localhost ~]# service xinetd restart

7.测试
[root@localhost ~]# cd /tftpboot/
[root@localhost tftpboot]# ls
a.txt  ramdisk_sjx_0.7.3.gz
[root@localhost tftpboot]# vim a.txt
[root@localhost tftpboot]# cd
[root@localhost ~]# tftp 192.168.1.91

tftp> get a.txt
tftp> q
[root@localhost ~]# ls
a.txt                    install.log         remove20090915        work
[root@localhost ~]# more a.txt
aaaaaaaaaaaaaa

成功!
ST2410 # ping 192.168.1.91

host 192.168.1.91 is alive
然后使用lokkit命令关闭防火墙,sellinux
ST2410 # tftp 0x30008000 u-boot.bin                                            
TFTP from server 192.168.1.91; our IP address is 192.168.1.200                  
Filename 'u-boot.bin'.                                                         
Load address: 0x30008000                                                       
Loading: ##########################                                            
done                                                                           
Bytes transferred = 132096 (20400 hex)     

测试成功,然后将board/configs/st2410.h里的宏CONFIG_SKIP_LOWLEVEL_INIT去掉和board/st2410/config.mk的TEXT_BASE修改为0x33f80000,下载到nor flash既可。下一篇中我们还用调试的方法来调试支持Nand Flash的读写操作。

三、支持norflash读写操作

三、改代码:
1. NOR FLASH的初始化函数为flash_init
2. 新版u-boot-2011.09中的flash_init在drivers/mtd/cfi_flash.c定义(老版本的还在board/smdk2410/flash.c中有定义board/smdk2410/flash.c的代码,它只支持AMD_LV400和AMD_LV800两种芯片)看drivers/mtd/Makefile的代码,发现它要配置CONFIG_FLASH_CFI_DRIVER才会被编译

COBJS-$(CONFIG_FLASH_CFI_DRIVER) += cfi_flash.o

分析flash_detect_legacy,发现如下代码,只能继续深入了解flash_init : 

  if (!flash_detect_legacy(cfi_flash_bank_addr(i), i))// 使用旧方法来识别
   flash_get_size(cfi_flash_bank_addr(i), i);// 如果旧方法不成功,则使用新方法
并且CONFIG_FLASH_CFI_LEGACY未定义:
#ifdef CONFIG_FLASH_CFI_LEGACY
static void flash_read_jedec_ids (flash_info_t * info)
{
。。。。。。。。。。。。。。。。。。。。。。。

}

static int flash_detect_legacy(phys_addr_t base, int banknum)

{

。。。。。。。。。。。。。。。。。。。

}
#else
static inline int flash_detect_legacy(phys_addr_t base, int banknum)
{
 return 0; /* use CFI */
}
#endif

 

可知:现在的u-boot使用新方法来识别FLASH。

3. 决定使用drivers/mtd/cfi_flash.c的代码:
   在include/configs/smdk2410.h里:
#define CONFIG_SYS_FLASH_CFI
#define CONFIG_FLASH_CFI_DRIVER
#define CONFIG_FLASH_CFI_LEGACY

然后重新make

ST2410 # go 0x32000000
## Starting application at 0x32000000 ...??

U-Boot 2011.09 (Nov 07 2011 - 09:33:10)

U-Boot code: 32000000 -> 3206F4F4  BSS: -> 320B3524
monitor len: 000B3524
ramsize: 04000000
TLB table at: 33ff0000
Top of RAM usable for U-Boot at: 33ff0000
Reserving 717k for U-Boot at: 33f3c000
Reserving 4160k for malloc() at: 33b2c000
Reserving 24 Bytes for Board Info at: 33b2bfe8
Reserving 120 Bytes for Global Data at: 33b2bf70
New Stack Pointer is: 33b2bf60
RAM Configuration:
Bank #0: 30000000 64 MiB
relocation Offset is: 01f3c000
WARNING: Caches not enabled
monitor flash len: 0007830C
dram_bank_mmu_setup: bank: 0
Now running in RAM - U-Boot at: 33f3c000
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 f0 ea00 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 90 ea00 0
*** failed ***
### ERROR ### Please RESET the board ###

没有识别出NOR FLASH

可知,确定flash_read_jedec_ids读出了FLASH的ID:JEDEC PROBE: ID f0 ea00 0
分析jedec_flash_match:根据读出的厂家ID、设备ID,在jedec_table数组里找到对应项。
UBOOT未识别出NOR FLASH的原因:jedec_table里没有SST39VF1601的信息

drivers/mtd/jedec_flash.c

11. 在jedec_table数组里加入SST39VF1601的信息:

#ifdef CONFIG_SYS_FLASH_LEGACY_SST39VF1601
   {
        .mfr_id     = 0xf0,
        .dev_id     = 0xea00,
        .name       = "SST39VF1601",
        .uaddr      = {
            [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */
            [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
        },
        .DevSize    = SIZE_2MiB,
        .CmdSet     = P_ID_AMD_STD,
        .NumEraseRegions= 2,
        .regions    = {
                ERASEINFO(0x1000,256),
                ERASEINFO(0x1000,256)
        }
    },
#endif

再在include/configs/st2410.h中添加下面宏定义

#define CONFIG_SYS_FLASH_LEGACY_SST39VF1601

编译、烧写、重启,输出信息为:
U-Boot 1.3.4 (May 13 2011 - 15:56:13)
DRAM:  64 MB
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 bf 234b 0
ERROR: too many flash sectors
ERROR: too many flash sectors
Flash:  2 MB
In:    serial
Out:   serial
Err:   serial


在源码里搜"ERROR: too many flash sectors",可得:
            if (sect_cnt >= CFG_MAX_FLASH_SECT) {
                printf("ERROR: too many flash sectors\n");
                break;
            }

在include/configs/smdk2410.h里修改CFG_MAX_FLASH_SECT的值,取个比较大的,比如1024
重新编译即可
使用"save"命令时,出现很多调试信息,所以要关闭打印信息:
在drivers/mtd/cfi_flash.c的第1行去掉以下语句:
#define DEBUG 1

背景知识:
1. 使用u-boot的命令熟悉NOR FLASH的操作
1.1 读ID
mw.w AAAA AA
mw.w 5554 55
mw.w AAAA 90
md.l 0

退出读ID的状态:
mw.w 0 f0


1.2 往NOR FLASH地址为0x70000的地方写入0x1234 (操作过程中可以用 md.l 70000 查看结果)
a. 先擦除
mw.w AAAA AA
mw.w 5554 55
mw.w AAAA 80
mw.w AAAA AA
mw.w 5554 55
mw.w 70000  30

b. 再写
mw.w AAAA AA
mw.w 5554 55
mw.w AAAA A0
mw.w 70000 1234


 

7.

在driver/mtd/Makefile

 

从u-boot 1.1.6中拷贝flash.c

cp ../u-boot-1.1.6/board/st2410/flash.c board/samsung/st2410/

 

然后修改board/samsung/st2410/Makefile

COBJS:= st2410.o

修改为

COBJS:= st2410.o flash.o

修改u-boot以支持SST39VF1601:
一、下载源码,编译
make distclean
make smdk2410_config
make

make distclean
make smdk2410_config
make


出现错误:
make: arm-linux-gcc: Command not found
原因:
1. 确实没有这个命令
2. 有这个命令,但是PATH没有设这个命令所在的目录

修改Makefile, 把arm-linux-改为arm-linux-gnu-

二、烧写u-boot.bin,启动结果为:
Flash: 512K
*** Warning - bad CRC, using default environment

执行: save 提示出错

原因:UBOOT不支持SST39VF1601

三、改代码:
1. NOR FLASH的初始化函数为flash_init
2. flash_init在两个地方定义:board/smdk2410/flash.c
                             drivers/mtd/cfi_flash.c
   看board/smdk2410/flash.c的代码,发现它只支持AMD_LV400和AMD_LV800两种芯片
   看drivers/mtd/cfi_flash.c的代码,发现它被"#ifdef CFG_FLASH_CFI_DRIVER"包含起来
3. 决定使用drivers/mtd/cfi_flash.c的代码:
   在include/configs/smdk2410.h里:
#define CFG_FLASH_CFI_DRIVER 1
然后重新make
出错:
arm-linux-gnu-gcc -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000 -I/home/farsight/wei/u-boot/u-boot-1.3.4/include -fno-builtin -ffreestanding -nostdinc -isystem /opt/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/lib/gcc/arm-linux-gnu/3.4.5/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes  -c -o cfi_flash.o cfi_flash.c
cfi_flash.c: In function `flash_map':
cfi_flash.c:286: error: structure has no member named `portwidth'


4. 找到出错的结构体的定义:
typedef struct {
    ulong   size;           /* total bank size in bytes     */
    ushort  sector_count;       /* number of erase units        */
    ulong   flash_id;       /* combined device & manufacturer code  */
    ulong   start[CFG_MAX_FLASH_SECT];   /* physical sector start addresses */
    uchar   protect[CFG_MAX_FLASH_SECT]; /* sector protection status    */
#ifdef CFG_FLASH_CFI
    uchar   portwidth;      /* the width of the port        */
    uchar   chipwidth;      /* the width of the chip        */
    ushort  buffer_size;        /* # of bytes in write buffer       */
    ulong   erase_blk_tout;     /* maximum block erase timeout      */
    ulong   write_tout;     /* maximum write timeout        */
    ulong   buffer_write_tout;  /* maximum buffer write timeout     */
    ushort  vendor;         /* the primary vendor id        */
    ushort  cmd_reset;      /* vendor specific reset command    */
    ushort  interface;      /* used for x8/x16 adjustments      */
    ushort  legacy_unlock;      /* support Intel legacy (un)locking */
    uchar   manufacturer_id;    /* manufacturer id          */
    ushort  device_id;      /* device id                */
    ushort  device_id2;     /* extended device id           */
    ushort  ext_addr;       /* extended query table address     */
    ushort  cfi_version;        /* cfi version              */
    ushort  cfi_offset;     /* offset for cfi query         */
    ulong   addr_unlock1;       /* unlock address 1 for AMD flash roms  */
    ulong   addr_unlock2;       /* unlock address 2 for AMD flash roms  */
    const char *name;       /* human-readable name                  */
#endif

可知原因为:CFG_FLASH_CFI未定义
于是:
   在include/configs/smdk2410.h里:
#define CFG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_CFI        1

再make

5. 再次出错:
arm-linux-gnu-gcc -g  -Os   -fno-strict-aliasing  -fno-common -ffixed-r8 -msoft-float -malignment-traps -D__KERNEL__ -DTEXT_BASE=0x33F80000 -I/home/farsight/wei/u-boot/u-boot-1.3.4/include -fno-builtin -ffreestanding -nostdinc -isystem /opt/crosstool/gcc-3.4.5-glibc-2.3.6/arm-linux-gnu/lib/gcc/arm-linux-gnu/3.4.5/include -pipe  -DCONFIG_ARM -D__ARM__ -march=armv4 -mapcs-32 -Wall -Wstrict-prototypes  -c -o cfi_flash.o cfi_flash.c
cfi_flash.c: In function `flash_init':
cfi_flash.c:1985: error: `CFG_MONITOR_BASE' undeclared (first use in this function)

CFG_MONITOR_BASE 是要保护的FLASH的起始地址,这只是u-boot里提供的软件保护机制,避免使用u-boot的命令
                 误擦除FLASH上的u-boot

可以如下试验:
md.l 0
erase 0 fff
md.l 0

protect off all
erase 0 fff
md.l 0


于是:
   在include/configs/smdk2410.h里:
#define CFG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_CFI        1
#define CFG_MONITOR_BASE     0

6. 没有出错,把u-boot.bin重烧、启动:
U-Boot 1.3.4 (May 13 2011 - 14:59:37)

DRAM:  64 MB
## Unknown FLASH on Bank 1 - Size = 0x00000000 = 0 MB
Flash:  0 kB


没有识别出NOR FLASH
只能继续深入了解flash_init :
        if (!flash_detect_legacy (BANK_BASE(i), i)) // 使用旧方法来识别
            flash_get_size (BANK_BASE(i), i);       // 如果旧方法不成功,则使用新方法


7. 分析flash_detect_legacy,发现如下代码,并且CONFIG_FLASH_CFI_LEGACY未定义:
#ifdef CONFIG_FLASH_CFI_LEGACY
static inline int flash_detect_legacy(ulong base, int banknum)
{
    ........
}
#else
static inline int flash_detect_legacy(ulong base, int banknum)
{
    return 0; /* use CFI */
}
#endif

可知:现在的u-boot使用新方法来识别FLASH。

8. 尝试通过修改新方法来识别FLASH
flash_init
    flash_get_size
        flash_detect_cfi
            __flash_detect_cfi

CFI(common flash interface):
flash的信息(工作电压、时间参数、容量、可擦除块)保存在FLASH内部;
平时是不可见的;
可以发出特定的命令来读出这些信息
从芯片手册上,这些命令为:
5555H AAH
2AAAH 55H
5555H 98H

从u-boot的代码上看,命令为(发现没有"解锁"):
flash_write_cmd (info, 0, flash_offset_cfi[cfi_offset], FLASH_CMD_CFI);

所以:SST39VF1601不是百分百遵循CFI规范,我们退回"旧的方法"
       
9. 分析旧的方法:flash_detect_legacy
要使用flash_detect_legacy, 先在include/configs/smdk2410.h里面:
#define CONFIG_FLASH_CFI_LEGACY 1
#define CFG_FLASH_CFI_DRIVER 1
#define CFG_FLASH_CFI        1
#define CFG_MONITOR_BASE     0

执行make, 出错:
drivers/mtd/libmtd.a(cfi_flash.o)(.text+0x1878): In function `flash_init':
/home/farsight/wei/u-boot/u-boot-1.3.4/drivers/mtd/cfi_flash.c:1544: undefined reference to `board_flash_get_legacy'

修改board/smdk2410/flash.c,去掉所有的代码,改为:

#include
#include

ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
{
    info->portwidth  = FLASH_CFI_16BIT;
    info->chipwidth  = FLASH_CFI_16BIT;
    info->interface = FLASH_CFI_X8X16;
    return 1;
}

然后make、烧写、启动:
U-Boot 1.3.4 (May 13 2011 - 15:56:13)
DRAM:  64 MB
Flash:  0 kB
In:    serial
Out:   serial
Err:   serial
SMDK2410 #
SMDK2410 #

10. 深入分析flash_detect_legacy:
flash_detect_legacy
    board_flash_get_legacy   board/samsung/smdk2410/smdk2410.c
    flash_read_jedec_ids    1639
    jedec_flash_match

为方便观察,把调试信息打开:
在drivers/mtd/cfi_flash.c的第1行加入:
#define DEBUG 1

重新编译、运行uboot,输出信息如下:
U-Boot 1.3.4 (May 13 2011 - 15:56:13)
DRAM:  64 MB
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 bf 234b 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 12 0 0
Flash:  0 kB
In:    serial
Out:   serial
Err:   serial


可知,确定flash_read_jedec_ids读出了FLASH的ID:JEDEC PROBE: ID bf 234b 0
分析jedec_flash_match:根据读出的厂家ID、设备ID,在jedec_table数组里找到对应项。
UBOOT未识别出NOR FLASH的原因:jedec_table里没有SST39VF1601的信息

drivers/mtd/jedec_flash.c

11. 在jedec_table数组里加入SST39VF1601的信息:

{
        .mfr_id     = 0xbf,
        .dev_id     = 0x234b,
        .name       = "SST39VF1601",
        .uaddr      = {
            [0] = MTD_UADDR_0x5555_0x2AAA, /* x8 */
            [1] = MTD_UADDR_0x5555_0x2AAA /* x16 */
        },
        .DevSize    = SIZE_2MiB,
        .CmdSet     = P_ID_AMD_STD,
        .NumEraseRegions= 2,
        .regions    = {
                ERASEINFO(0x1000,256),
                ERASEINFO(0x1000,256)
        }
    }

编译、烧写、重启,输出信息为:
U-Boot 1.3.4 (May 13 2011 - 15:56:13)
DRAM:  64 MB
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 bf 234b 0
ERROR: too many flash sectors
ERROR: too many flash sectors
Flash:  2 MB
In:    serial
Out:   serial
Err:   serial


在源码里搜"ERROR: too many flash sectors",可得:
            if (sect_cnt >= CFG_MAX_FLASH_SECT) {
                printf("ERROR: too many flash sectors\n");
                break;
            }

在include/configs/smdk2410.h里修改CFG_MAX_FLASH_SECT的值,取个比较大的,比如1024
重新编译即可
使用"save"命令时,出现很多调试信息,所以要关闭打印信息:
在drivers/mtd/cfi_flash.c的第1行去掉以下语句:
#define DEBUG 1

背景知识:
1. 使用u-boot的命令熟悉NOR FLASH的操作
1.1 读ID
mw.w AAAA AA
mw.w 5554 55
mw.w AAAA 90
md.l 0

退出读ID的状态:
mw.w 0 f0


1.2 往NOR FLASH地址为0x70000的地方写入0x1234 (操作过程中可以用 md.l 70000 查看结果)
a. 先擦除
mw.w AAAA AA
mw.w 5554 55
mw.w AAAA 80
mw.w AAAA AA
mw.w 5554 55
mw.w 70000  30

b. 再写
mw.w AAAA AA
mw.w 5554 55
mw.w AAAA A0
mw.w 70000 1234

2. CFI(common flash interface):
flash的信息(工作电压、时间参数、容量、可擦除块)保存在FLASH内部;
平时是不可见的;
可以发出特定的命令来读出这些信息
从芯片手册上,这些命令为:
5555H AAH
2AAAH 55H
5555H 98H

四、支持nandflash启动及读写操作

阅读(3906) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~