添加Redboot的NAND Flash驱动

现在我的Redboot已经实现了从NAND启动,并加载了cs8900网卡的驱动,但是仍然无法对NAND Flash进行操作,如fconfig命令、fis命令还是无法完成的。于是,需要给Redboot加载NAND Flash的驱动。
eCos的源代码中并没有提供对NAND器件的支持,只是提供了一个flash抽象设备的接口,如fis和fconfig命令都是针对于flash抽象设备接口实现的。flash抽象设备接口驱动是置于io设备驱动下的。而具体的flash器件的驱动则放在devs目录下,在flash器件驱动中大多是实用于NOR Flash器件,只有Toshiba的TC58xxx是NAND Flash器件。而Flash驱动中与平台相关的部分则放在devs\flash\下的各平台目录下。
在网上转了一圈,想找找现成的NAND Flash驱动,发现了有一些对NAND驱动结构的意见。其主要有两种意见,一种是按照linux的结构来实现;一种则直接采用flash抽象设备接口的结构,而只是实现NAND器件的驱动。按照linux结构实现较为复杂,但是能够做到与linux兼容,对于用Redboot引导linux的系统来说比较合适。按后一种方式则实现较为简单,对eCos的目录结构的调整也不大,如Toshiba的TC58xxx那样,则对于fis、fconfig命令而言是透明的,无需修改。由于是初学,也没有必要做得太复杂,至于与linux的兼容性也就先丢到一边吧,呵呵。况且,在网上还找到Alexey Shusharin写的NAND Flash的patch( url:http://www.nabble.com/NAND-Flash-device-driver-td14252516.html),据他称已经在SAMSUNG的K9F5608U0D上测试通过。而我的开发板上的NAND Flash是SAMSUNG的K9F1208U0B,应该正好可以拿来用,呵呵。
Alexey的驱动主要由两个部分组成,一个是NAND器件的驱动,位于\devs\flash\nand\目录下,包括nand_flash.c,nand_flash_parts.inl,nand_flash.h文件,在nand_flash.cdl中实现了NAND Flash驱动的配置脚本文件,定义了CYGPKG_DEVS_FLASH_NAND包,以及相关的一些配置选项。另外一部分是与平台相关的,放在了\devs\flash\arm\leo2410\目录下了,包括flash_nand_leo2410.cdl和devs_flash_arm_leo2410.inl两个文件。
在nand_flash.c文件中实现了flash.c函数中所有相关的接口函数,如flash_query()、flash_hwr_init()、...等函数,这样fis、fconfig命令就可以通过这些函数访问到NAND Flash,当然这样的实现只能适合于只有NAND Flash的情况。nand_flash_parts.inl中定义了NAND器件的型号和参数;flash_nand_leo2410.cdl中对平台相关的包含文件devs_flash_arm_leo2410.inl做了连接,并定义了相关的宏以便能够使用NAND Flash驱动。而devs_flash_arm_leo2410.inl中则是平台对NAND控制器的实现。
在Alexey的这个patch中,实现了NAND Flash的驱动部分,平台相关部分给出了函数的空实现,以便于按照平台要求添加相应的代码。根据s3c2410的NAND控制器的访问方法,对这段代码进行了添加,如下所示:
 

#include <cyg/hal/s3c2410x.h> 
 
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))

//-----------------------------------------------------------------
// Platform specific access to control-lines 
//-----------------------------------------------------------------
#define CYGHWR_FLASH_NAND_PLF_RESET nand_plf_reset
#define CYGHWR_FLASH_NAND_PLF_INIT nand_plf_init 
#define CYGHWR_FLASH_NAND_PLF_CE nand_plf_ce 
#define CYGHWR_FLASH_NAND_PLF_WP nand_plf_wp 
#define CYGHWR_FLASH_NAND_PLF_CMD nand_plf_cmd 
#define CYGHWR_FLASH_NAND_PLF_ADDR nand_plf_addr 
#define CYGHWR_FLASH_NAND_PLF_WAIT nand_plf_wait 
 
//----------------------------------------------------------------
// Global variables 
//-----------------------------------------------------------------
// The device-specific data 

static cyg_nand_dev nand_device = 
{ 
    .flash_base = (void*) (0x80000000), 
    .addr_r = (void*) NFDATA,
    .addr_w = (void*) NFDATA, 
     
    .delay_cmd = 1, 
    .delay_rst = 500, 
}; 

//-----------------------------------------------------------------
// Reset platform nand 
//-----------------------------------------------------------------
static inline void nand_plf_reset(void)
{
    int i;
        
    __REGi(NFCONF) &= ~(1<<11);
    __REGi(NFCMD) = 0xFF;               /* reset command */        
    for(= 0; i < 10; i++);            /* tWB = 100ns. */
    while (!(__REGi(NFSTAT) & (1<<0))); /* wait 200~500us; */
    __REGi(NFCONF) |= (1<<11);
}
 
//-----------------------------------------------------------------
// Init platform nand 
//-----------------------------------------------------------------
static inline void nand_plf_init(void) 
{ 
    // Init NAND Flash platform stuff 

#if 1
    #define TACLS 0
    #define TWRPH0 1
    #define TWRPH1 0
#else
    #define TACLS 0
    #define TWRPH0 4
    #define TWRPH1 2

#endif

    __REGi(NFCONF) = ((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
    /* 1 1 1 1, 1 xxx, r xxx, r xxx */
    /* En 512B 4step ECCR nFCE=H tACLS tWRPH0 tWRPH1 */

    nand_plf_reset();
} 
//-----------------------------------------------------------------
// Enable/disable nand chip 
//-----------------------------------------------------------------
static inline void nand_plf_ce(int state) 
{ 
    if(state) 
    { 
        // Enable CE line 
        __REGi(NFCONF) &= ~(1<<11);
    } 
    else 
    { 
        // Disable CE line 
        __REGi(NFCONF) |= (1<<11);
    } 
} 
 
//-----------------------------------------------------------------
// Enable/disable write protect 
//-----------------------------------------------------------------
static inline void nand_plf_wp(int nowrite) 
{ 
    if(nowrite) 
    { 
        // Enable WP 
    } 
    else 
    { 
        // Disable WP 
    } 
} 
//-----------------------------------------------------------------

// Write nand command 
//-----------------------------------------------------------------
static inline void nand_plf_cmd(int cmd) 
{ 
    // Enable CLE line 
    // Write command 
    // Disable CLE line 
    __REGi(NFCMD) = cmd;
} 
 
//-----------------------------------------------------------------

// Write nand address 
//-----------------------------------------------------------------

static inline void nand_plf_addr(int addr) 
{ 
    // Enable ALE line 
    // Write address 
    // Disable ALE line 
    __REGi(NFADDR)    = addr;
} 
//-----------------------------------------------------------------
// Wait device ready pin 
//-----------------------------------------------------------------
static inline void nand_plf_wait(void) 
{ 
    // Wait while device is not ready 
    while (!(__REGi(NFSTAT) & (1<<0)));
} 

其中nand_plf_wp没有实现,是因为我的开发板上写保护线是直接接的高电平,故无需控制。而nand_plf_cmd和nand_plf_addr的实现没有考虑CLE和ALE的控制是由于s3c2410的控制器是由硬件直接控制的,无需由软件控制。

这样,在eCos.db的leo2410 target中加入下面几行:

CYGPKG_IO_FLASH
CYGPKG_DEVS_FLASH_NAND
CYGPKG_DEVS_FLASH_ARM_LEO2410_NAND

就可以用configureTool进行配置、编译了。下载之后启动,Redboot发现了NAND Flash器件,但是fconfig初始化错误,NAND驱动中的bbm也无法初始化。使用fconfig命令、fis命令发现完全没有作用。于是将nand_flash.c文件中的NAND_DEBUG_LEVEL设置为3,以打印出调试信息。重新编译,下载,发现打印出的调试信息都是success,这就奇怪了,为什么无法执行操作却返回成功呢?

左思右想没有结果,怎么办呢,只有借鉴成功经验了。一开始想在vivi中找,却发现vivi对NAND器件的驱动不是很清晰,看起来比较费劲。又分析了一下,发现erase、write甚至read命令都无法正常工作,因此猜想应该是底层命令的原因,第一个怀疑的就是command命令了。这时候,突然想到用来刷NAND Flash的SJF2410也有源代码,于是打开将command的实现进行了一下比较,才发现Alexey代码中少了一段page地址的设置,s3c2410的控制方法不一致,如下列代码中红色部分所示。

// Write page address if needed 
if(page_addr >= 0) 
{ 
   CYGHWR_FLASH_NAND_PLF_ADDR(page_addr & 0xFF); 
   CYGHWR_FLASH_NAND_PLF_ADDR((page_addr >> 8) & 0xFF); 
   CYGHWR_FLASH_NAND_PLF_ADDR((page_addr >> 16) & 0xFF); 
}

page地址没有写对,那么当然无法正常工作,但是并没有影响到NAND控制器的状态改变,所以总是返回成功了。重新编译、下载,启动,终于没有报初始化不成功的错误了,试验了一下fconfig命令,也可以正确的设置了,这样修改ip地址等变得很方便了。

+NAND FLASH Device probed: Samsung K9F1208U0B, size 64MB

... Read from 0x03ffc000-0x04000000 at 0x83f7c000:

.

... Read from 0x03ffb000-0x03ffc000 at 0x83f7f000:

.

CS8900A[0x19000300] - type: 0x630e, rev: 0x0a00

CS8900 - status: 0x0ad6 (EEPROM present)

Got hardcoded ESA

ESA 00:21:85:92:d5:0e

Ethernet eth0: MAC address 00:21:85:92:d5:0e

IP: 192.168.0.4/255.255.255.0, Gateway: 192.168.0.1

Default server: 192.168.1.21

 

RedBoot(tm) bootstrap and debug environment [NAND]

Non-certified release, version UNKNOWN - built 11:48:11, Jan 14 2009

 

Platform: LEO2410 system (ARM9)

Copyright (C) 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.

Copyright (C) 2003, 2004, 2005, 2006 eCosCentric Limited

 

RAM: 0x00000000-0x04000000, [0x0002d568-0x03ff5000] available

FLASH: 0x80000000 - 0x83f80000, 4064 blocks of 0x00004000 bytes each.

RedBoot>

其中NAND器件的信号是自己在nand_flash_parts.inl的结构中添加的,并在nand_flash.c的flash_hwr_init()函数添加了以下代码而实现的打印NAND Flash器件的信息:

flash_info.pf("NAND FLASH Device probed: %s, size %dMB\n", 
            name,
            flash_info.block_size * dev->blocks_count / 0x100000);

fis命令也能工作了,用fis list命令看了一下,发现有三个image,如下:

RedBoot> fis list

... Read from 0x03ffc000-0x03fff000 at 0x83f7c000:

.

Name              FLASH addr  Mem addr    Length      Entry point

RedBoot           0x80000000  0x80000000  0x00020000  0x00000000

FIS directory     0x83F7C000  0x83F7C000  0x00003000  0x00000000

RedBoot config 0x83F7F000  0x83F7F000  0x00001000  0x00000000

这样,我的Redboot就可以使用NAND驱动了,通过配置可以直接用load命令将映像文件下载到NAND Flash中去,采用tftp速度飞快,再也不需要在SJF2410下载时经历那样漫长的等待了,呵呵!

原文见:http://blog.chinaunix.net/uid-20802172-id-458568.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值