移植uboot到TQ2440出现No NAND device found!!!的解决办法
在增加Nand读写支持的时候,曾经一度出现下面的错误信息:
NAND:No NAND device found!!!? 0MiB 这个信息曾经困扰了我很久,终于在某一天成功的解决了。在此写下以记录教训! 首先,用Source Insight搜索这个信息的打印出处,在drivers/mtd/nand/nand_base.c文件: intnand_scan_ident(struct mtd_info *mtd,int maxchips) { ?????? int i,busw,nand_maf_id; ?????? struct nand_chip *chip = mtd->priv; ?????? struct nand_flash_dev *type; ?????? …… ?????? type = nand_get_flash_type(mtd,chip,&nand_maf_id); ? ?????? if (IS_ERR(type)) { #ifndefCONFIG_SYS_NAND_QUIET_TEST ????????????? printk(KERN_WARNING "No NAND device found!!!n"); #endif ?????? …… } 根据打印条件,判断是type返回值出错,于是分析nand_get_flash_type函数,可以发现在函数中有这么两行: ?????? if (!type) ????????????? return ERR_PTR(-ENODEV); 因此猜测是type出错了,于是向上查找type的赋值情况,在紧挨着上述两行代码前面有这么几行: ?????? /* Lookup the flash id */ ?????? for (i = 0; nand_flash_ids[i].name !=NULL; i++) { ????????????? if (dev_id ==nand_flash_ids[i].id) { ???????????????????? type =? &nand_flash_ids[i]; ???????????????????? break; ????????????? } ?????? } 这段代码是Nand ID的匹配查找工作,在源代码的文件drivers/mtd/nand/nand_ids.c文件中定义了常见的Nand Flash厂商号和设备号,上述代码就是把从硬件Flash中读取到的设备号与源码中的Nand Flash ID列表进行比对,如果有一个ID与从硬件NAND上读取的ID匹配,说明找到了外设Nand,否则就没找到。根据这个信息,我们在这个函数的前面找到了读取硬件ID的代码: ?????? chip->cmdfunc(mtd,NAND_CMD_RESET,-1,-1); ?????? /* Send the command for reading device ID*/ ?????? chip->cmdfunc(mtd,NAND_CMD_READID,0x00,-1); ?????? /* Read manufacturer and device IDs */ ?????? *maf_id = chip->read_byte(mtd); ?????? dev_id = chip->read_byte(mtd); ?????? /*下面这行是我后来加上的,目的就是看看读取的ID号到底是多少。*/ ?????? printf("In %s,*maf_id is 0x%x,dev_idis 0x%x.n",__func__,*maf_id,dev_id); 重新编译并下载之后看到如下打印信息: NAND:In nand_get_flash_type,*maf_id is 0x95,dev_id is 0x95. No NAND device found!!! 0 MiB ?? ?依然是找不到Nand。不过从这句话我们可以看出,读取Nand的厂商号和设备号出了问题。实际上的厂商号是0xEC,设备号是0xDA。 ?? 于是定位到读取ID代码上,搜索chip->read_byte函数的赋值语句发现是在本文件中的nand_read_byte函数,再起里面加上打印语句: ?????? static uint8_t nand_read_byte(structmtd_info *mtd) ?????? { ?????? ??????struct nand_chip *chip = mtd->priv; ?????? ???????printf("Innand_read_byte,chip->IO_ADDR_R is %pn",chip->IO_ADDR_R); ?????? ???????return readb(chip->IO_ADDR_R); ?????? } 接着搜索发送命令/地址的函数,chip->cmdfunc,发现该函数调用了chip->cmd_ctrl函数,而这个函数正好是自己在nand_flash函数中实现的函数,也加上打印语句: 25static void s3c2440_hwcontrol(struct mtd_info *mtd,int cmd,unsigned int ctrl) 26 { ?????????? …… 56???????? printf("Ins3c2440_hwcontrol.ctrl is 0x%x,cmd is 0x%xn",ctrl,cmd); 57???????? if (cmd != NAND_CMD_NONE) 58???????????????? writeb(cmd,chip->IO_ADDR_W); 59 } 上述函数是在board_nand_init函数中赋值的,在这个函数也加上打印信息。另外,在函数s3c2440_dev_ready中也增加打印信息,判断一下读取硬件是否出现问题,为此修改如下: 61static int s3c2440_dev_ready(struct mtd_info *mtd) 62 { 63???????? struct s3c2440_nand *nand =s3c2440_get_base_nand(); 64???????? unsigned int ready=0; 65???????? ready = readl(&nand->NFSTAT)& 0x01; 66???????? printf("Ins3c2440_dev_ready,dev is %s ready.n",ready?"":"not"); 67???????? return ready; 68 } 重新编译并下载之后看到的信息如下图所示:可以看到,虽然基本断定函数调用没有问题,但是厂商号和设备号依然是0x95,依旧找不到NAND!!!因此,肯定的说,是Nand的发送命令和地址的地方出现了错误。该功能的实现在nand->cmd_ctrl函数中,回去仔细研究,发现问题就是出在这里: 49???????????????? if (ctrl & NAND_NCE) 50????????????????????????writel(readl(&nand->NFCONF)& ~S3C2440_NFCONT_nCE, 51??????????????????????????????? &nand->NFCONF); 52???????????????? else 53????????????????????????writel(readl(&nand->NFCONF)| S3C2440_NFCONT_nCE, 54???????????????????????? ???????&nand->NFCONF); ?? S3C2410和S3C2440的寄存器是不相同的,原先的S3C2410使用的是NFCONF寄存器,而S3C2440使用的是NFCONT寄存器,修改成NFCONT,重新编译下载,成功!!(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |