1.2.1. 涉及文件
Lib_arm/board.c
Board/smdk2410/smdk2410.c
Board/smdk2410/smdk2410.h
Driver/Nand_legacy/ Nand_legacy.c
Include/configs/smdk2410.h
1.2.2. 具体分析
Lib_arm/board.c
u-boot运行至第二阶段进入start_armboot()函数。其中nand_init()函数是对nand flash的最初初始化函数。Nand_init()函数在两个文件中实现。其调用与CFG_NAND_LEGACY宏有关,如果定义了这个宏,系统调用drivers/nnd/nand.c中的nand_init();否则调用自己在board/smdk2410/smdk2410.c中的nand_init()函数。这里我们选择第二种方式。
Board/smdk2410/smdk2410.h
这个头文件中实现了对nand flash各个寄存器的设置工作。把原程序列出来更直观些。
static inline void NF_Conf(u16 conf) /* 控制寄存器设置 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd) /* 命令寄存器传递命令 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd) /* 命令寄存器写操作 */
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr) /* 地址寄存器设置 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void NF_SetCE(NFCE_STATE s) /* 设置nand flash的片选信号 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1<<11);
break;
case NFCE_HIGH:
nand->NFCONF |= (1<<11);
break;
}
}
static inline void NF_WaitRB(void) /* 等待 nand flash处于 Ready状态 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
while (!(nand->NFSTAT & (1<<0)));
}
static inline void NF_Write(u8 data) /* 写数据操作 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFDATA = data;
}
static inline u8 NF_Read(void) /* 读数据操作 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void NF_Init_ECC(void) /* 初始化ECC */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1<<12);
}
static inline u32 NF_Read_ECC(void) /* 读取ECC值 */
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFECC);
}
Board/smdk2410/smdk2410.c
前面提到了nand_init()函数的实现就是在smdk2410.c中,下面我们就来看看nand flash 是怎么初始化的。
void
nand_init(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
NF_Init();
#ifdef DEBUG
printf("NAND flash probing at 0x%.8lX\n", (ulong)nand);
#endif
printf ("%4lu MB\n", nand_probe((ulong)nand) >> 20);
}
static inline void NF_Init(void)
{
#if 0 /* a little bit too optimistic */
#define TACLS 0
#define TWRPH0 3
#define TWRPH1 0
#else
#define TACLS 0
#define TWRPH0 4
#define TWRPH1 2
#endif
NF_Conf((1<<15)|(0<<14)|(0<<13)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0));
/*nand->NFCONF = (1<<15)|(1<<14)|(1<<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 */
NF_Reset();
}
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i < 10; i++); /* tWB = 100ns. */
NF_WaitRB(); /* wait 200~500us; */
NF_SetCE(NFCE_HIGH);
}
可以看到nand_init()调用 NF_Init()函数,使能nand flash控制器和nand flash;调用NF_Reset()函数置位,NF_WaitRB()查询nand flash的状态,最后在调用nand_probe((ulong)nand)函数探测nand flash.
Driver/Nand_legacy/ Nand_legacy.c
这个文件中的函数由u-boot 中对nand flash 操作的命令函数调用。
Include/configs/smdk2410.h
此文件中主要是对nand flash相关的一些参数进行设置。贴出来看下,有些感性的认识。
/*-----------------------------------------------------------------------
* NAND flash settings
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_NAND_LEGACY
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
#define NAND_WAIT_READY(nand) NF_WaitRB()
#define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH)
#define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW)
#define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d)
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
#define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d)
#define WRITE_NAND(d, adr) NF_Write(d)
#define READ_NAND(adr) NF_Read()
/* the following functions are NOP's because S3C24X0 handles this in hardware */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define CONFIG_MTD_NAND_ECC_JFFS2 1
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
http://blog.ednchina.com/icexiong/126067/message.aspx