昨天把u-boot给勉强跑通了,但是还无法读写Nand Flash和启动内核。今天忙活了一天,最后终于没坚持住,放弃了u-boot 1.2.0 + arm-linux 3.3.2,改用1.1.4 + arm-linux 2.95.3,在网上借鉴,copy了无数高手之成果,u-boot终于TNND被俺给整成能读写Nand的了。下面请听详细~~~报道:
今天已开始就接着昨天的弄,昨天发现1.2.0的u-boot变化挺大,但是网上很多都是说1.1.4或之前的版本。低版本的u-boot里有个void nand_init(void)函数没有实现(在lib_arm/board.c中),自然,把这个给实现了就完事了。但是在1.2.0里,整出来了drivers/nand和drivers/nand_legacy两个目录,里面因该是nand的驱动吧,上网上查了一圈,发现cu的pywj777兄给了比较明确的解释,原文链接如下:
文中提到了nand_legacy的问题,说是有个叫CFG_NAND_LEGACY的宏,如果没定义这个宏,就是按照默认规定,调用drivers/nand/nand.c中的nand_init函数(该函数在1.2.0已经被实现),但还有个board_nand_init给咱留着呢,咱的任务就是把这个函数给填上。那么如果定义了CFG_NAND_LEGACY,就变成了不使用默认的nand_init,得自己写nand_init了。于是按照文中的做法,自己加了一些代码,不过由于俺对2410的硬件是在是太不了解了,一直都没调明白,加上对1.2.0代码中那些nand的驱动没彻底弄明白,混乱的很,最后不得已,放弃了1.2.0,改用1.1.4的u-boot,这个版本里对nand的支持似乎很少,但是也决定了这个版本在移植的过程中思路会很清晰。
下载了之后改用2.95.3的交叉编译器,上来还是像以前那么做,自己弄个board/py2410出来,修改各种参数,不在话下。一些妥当之后,make了一下,然后就是错误,是那个apcs-gnu什么的那个选项无效。这也是个经典问题了,所以直接按网上说的,把cpu/arm920t/config.mx给改了,然后重新编译,顺利通过。
#include
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE;
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)
{
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)
{
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)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1<<12);
}
static inline u32 NF_Read_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFECC);
}
extern ulong nand_probe(ulong physadr);
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);
}
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();
}
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);
}
#endif /* (CONFIG_SMDK2410) */
不过我把#if CONFIG_SMDK2410/#endif给去掉了,因为感觉没啥必要,还多打些字
再把以下代码放到include/configs/py2410.h中
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#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 */
/* This definition above is commented by Lu Xianzi. 2006.05.28
Because there's no definition of a macro called __mem_pci,
there will be a link error.
*/
#define CONFIG_MTD_NAND_ECC_JFFS2 1
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
其中红字是作者发现的一个问题,说得把CONFIG_MTD_NAND_VERIFY_WRITE这个宏给注释掉,要不链接时会出问题。
整个思路非常清晰,步骤也很简单,弄完之后重新make一遍,把生成的u-boot.bin通过串口下载到板子上,然后再板子的旧u-boot中执行这个新的u-boot,结果大跌眼镜,没出现Nand: 64 MB的字样,打help命令也没出现nand的命令解释,nand command没加上,但是编译的时候CFG_CMD_NAND已经开开了啊,怎么会这样,百思不解。后来突然想到以前在厂家给的bootloader中运行从Nand启动的u-boot时也不好使,后来把u-boot用jtag烧到板子上就好了。于是再次使用jtag把u-boot烧到nand flash中,reset开发板,这次ok了,然后随便执行了几个nand的命令,都挺好使,呵呵
接下来就是弄内核了,不过要想把内核调通了肯定还得是一场恶战啊