把Linux下nand读操作搞定了


最后还是用了实地址和虚地址转换的函数,正确读出了写入的信息,挂载了cramfs分区

终于在最后一天晚上吧nand驱动的读取部分做好了,现在可以从cramfs启动文件系统,write应该也快了吧,ECC校验和yaffs还需要时间。简单记录下这几天和LM兄调试nand的痛苦经历。

我加入Linux项目组时LM兄已经开始着手看nand驱动的相关内容,所以主要程序都是他写的,我只是一起开发,解决问题。一开始是串口不能输出和2.6不能启动这些历史遗留问题,不再赘述。记得遇到了以下问题:

(1)DMA操作一定要对实地址进行操作,我们刚开始不懂,填虚地址,导致最简单的DMA程序都跑不了,幸亏张师兄提醒才恍然大悟。

(2)编译NAND驱动后,proc目录里没有和mtd和mtdblock,这个很傻的问题我们排查了一整天,包括按照三星2410的方法重新注册驱动,结果发现Make menuconfig时有一些MTD选项没有选,傻ToT

(3)写write指令,检测nand控制器,始终为0(忙)。按常理nand写完了就应当空闲才对,我们去读取却发现始终为忙。最后发现没有重载nand_base.c里面的write_byte函数,导致给32位寄存器的最低位赋值80时,赋值结果成了80808080,而nand控制器启动命令为80000080,也就是我们在写命令时就启动了nand控制器,导致nand控制器一直为忙。

(4)linux的MTD层读写NAND一般都是读512B和读16B的OOB区,我们的nand控制器特别特殊,必须一次读取528B的内容或者16B的OOB,一次写入528B的内容。导致调用write_buf(512)函数时,我们也得读528B,写512时,可能还得读取16B的OOB再写入528,写入暂时还没有完成。

(5) 对DMA读写,我们一直采用的方法是在内存最开始开辟一片区域,从dma中读出数据到这,linux再用实地址+0x90000000的虚地址去取。但是这样总是读的不正确,刚开始我以为是延时不够,加了很长的延时,好多了,但还是会有错误,于是不停读一块区域的oob区来测试,发现大概有15%的概率读成坏块,读错的概率更大吧。最后还是用了dma_alloc_coherent()来解决虚拟地址和实际地址映射的问题,终于全部读取正确,能够挂载cramfs文件系统了。

其实很多麻烦都是由我们这款nand控制器一定要采用DMA读写导致的,别人很简单的read_buf函数,到我们这里变得异常复杂ToT,第一次接触4020这款处理器非常不熟悉,导致出了很多问题,要继续努力!

相关内容