Chinaunix首页 | 论坛 | 博客
  • 博客访问: 718581
  • 博文数量: 140
  • 博客积分: 8196
  • 博客等级: 中将
  • 技术积分: 1350
  • 用 户 组: 普通用户
  • 注册时间: 2006-05-16 19:53
文章分类

全部博文(140)

文章存档

2011年(2)

2010年(2)

2009年(2)

2008年(20)

2007年(52)

2006年(62)

分类: LINUX

2007-02-03 05:15:53

昨天把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给改了,然后重新编译,顺利通过。

之后我发现了一个超级无敌的帖子,在此要严重感谢作者贡献此妙文,俺之所以能把u-boot移植成功,就是因为看了这个:
http://xianzilu.spaces.live.com/blog/
这里作者写了一篇关于nand flash驱动的文章,俺看了之后就照着去做,具体如下:
把下面代码放到common/cmd_nand.c中

#if (CONFIG_SMDK2410)
#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的命令,都挺好使,呵呵

接下来就是弄内核了,不过要想把内核调通了肯定还得是一场恶战啊

阅读(3041) | 评论(8) | 转发(0) |
0

上一篇:移植U-Boot手记

下一篇:控制面板真怪

给主人留下些什么吧!~~