关于NAND FLASH写入错误

[复制链接]
6454|17
 楼主| hao01222 发表于 2008-7-18 21:18 | 显示全部楼层 |阅读模式
这几天用SAM9260写nandflsh的底层驱动,已经能实现读FLASH&nbsp;ID,读和擦写,但是写就是实现不了。<br />每次我进行写一页,读取状态时,是显示正确的(返回0xc0),但是读的时候读的数据总是1,不知道各位有没有遇到过这种情况<br />我用的NAND&nbsp;FLASH的芯片是三星的K9F1208U0B,读写命令我均是按照官方手册上的时序说明进行
香水城 发表于 2008-7-18 22:43 | 显示全部楼层

如果写完一页后,第一次读出的状态时显示就绪,基本表示

用示波器看看吧。
 楼主| hao01222 发表于 2008-7-19 09:42 | 显示全部楼层

手头没有示波器啊,有没有其它方法

  
香水城 发表于 2008-7-19 12:05 | 显示全部楼层

做这样的底层驱动一定要有相应的仪器设备

这样才能保证正确的时序和最优的效率。
 楼主| hao01222 发表于 2008-7-21 10:55 | 显示全部楼层

问下,有没有可能是我的程序有问题

程序只是用来实验的,所以一些地方不规范,&nbsp;wait()是延时5个指令周期<br />写页之前已经将所在块擦除,返回信息是0xC0,但读出来的信息是全部为0x01<br /><br /><br />AT91F_NandWriteSector(unsigned&nbsp;int&nbsp;uSectorAddr,&nbsp;char&nbsp;*pOutBuffer)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;int&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;char&nbsp;bRet=1;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;NAND_ENABLE_CE();<br />&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_COMMAND(CMD_WRITE_1);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_ADDRESS(0x00);<br />&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_ADDRESS((uSectorAddr&nbsp;&gt&gt&nbsp;&nbsp;0)&nbsp;&&nbsp;0xFF);<br />&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_ADDRESS((uSectorAddr&nbsp;&gt&gt&nbsp;&nbsp;8)&nbsp;&&nbsp;0xFF);<br />&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_ADDRESS((uSectorAddr&nbsp;&gt&gt&nbsp;16)&nbsp;&&nbsp;0xFF);<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;wait();<br />&nbsp;&nbsp;&nbsp;&nbsp;for(i=0;&nbsp;i&lt512;&nbsp;i++)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND(*(pOutBuffer++));<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;wait();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_COMMAND(CMD_WRITE_2);<br />&nbsp;&nbsp;&nbsp;&nbsp;NAND_WAIT_READY();<br />&nbsp;&nbsp;&nbsp;&nbsp;NAND_WAIT_READY();<br />&nbsp;&nbsp;&nbsp;&nbsp;WRITE_NAND_COMMAND(CMD_STATUS);<br />&nbsp;&nbsp;&nbsp;&nbsp;wait();<br />&nbsp;&nbsp;&nbsp;&nbsp;NAND_WAIT_READY();<br />&nbsp;&nbsp;&nbsp;&nbsp;NAND_WAIT_READY();<br />&nbsp;&nbsp;&nbsp;&nbsp;bRet=READ_NAND();<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;NAND_DISABLE_CE();<br />&nbsp;&nbsp;&nbsp;&nbsp;return(bRet);<br />}
lomeisi_99 发表于 2008-7-21 11:18 | 显示全部楼层

时序问题

感觉是时序问题,板子主频是多少?你如何配置时序的?<br />
 楼主| hao01222 发表于 2008-7-21 15:17 | 显示全部楼层

应该不是时序问题吧

都能正确的进行读ID和擦,应该不是时序问题吧<br />时钟是将近100M<br /><br />#define&nbsp;AT91C_SM_NWE_SETUP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(0&nbsp;&lt&lt&nbsp;0)<br />#define&nbsp;AT91C_SM_NCS_WR_SETUP&nbsp;&nbsp;&nbsp;&nbsp;(0&nbsp;&lt&lt&nbsp;8)<br />#define&nbsp;AT91C_SM_NRD_SETUP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(0&nbsp;&lt&lt&nbsp;16)<br />#define&nbsp;AT91C_SM_NCS_RD_SETUP&nbsp;&nbsp;&nbsp;&nbsp;(0&nbsp;&lt&lt&nbsp;24)<br />&nbsp;&nbsp;<br />#define&nbsp;AT91C_SM_NWE_PULSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3&nbsp;&lt&lt&nbsp;0)<br />#define&nbsp;AT91C_SM_NCS_WR_PULSE&nbsp;&nbsp;&nbsp;&nbsp;(4&nbsp;&lt&lt&nbsp;8)<br />#define&nbsp;AT91C_SM_NRD_PULSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3&nbsp;&lt&lt&nbsp;16)<br />#define&nbsp;AT91C_SM_NCS_RD_PULSE&nbsp;&nbsp;&nbsp;&nbsp;(4&nbsp;&lt&lt&nbsp;24)<br />&nbsp;&nbsp;<br />#define&nbsp;AT91C_SM_NWE_CYCLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5&nbsp;&lt&lt&nbsp;0)<br />#define&nbsp;AT91C_SM_NRD_CYCLE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(5&nbsp;&lt&lt&nbsp;16)<br /><br />#define&nbsp;AT91C_SM_TDF&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(0&nbsp;&lt&lt&nbsp;16)<br />
 楼主| hao01222 发表于 2008-7-23 11:52 | 显示全部楼层

写正确了,擦有出现问题

写确实是时序错误<br /><br />现在遇到一个问题,我写入数据后对该页所在块进行擦写,确不能擦掉该页的内容,而且再次在该页写也不能实现了<br /><br />请问是什么问题
lomeisi_99 发表于 2008-7-23 13:50 | 显示全部楼层

哈哈

时序哪错了?<br />不能擦除?不是坏块吧,之前你不是说可以擦吗?
 楼主| hao01222 发表于 2008-7-24 10:04 | 显示全部楼层

就是数据写入之后就不能擦了

就是数据写入之后就不能擦了<br />写入之前是可以擦的<br />任何一页的数据写入之后,我想擦除整个块,但发送擦除命令后,读出该页还是原来的数据<br /><br />但是在那些未写入数据的页确可以擦除,不知道这是一个什么缘故。<br /><br />时序上是<br />#define&nbsp;AT91C_SM_NWE_PULSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3&nbsp;&lt&lt&nbsp;0)<br />#define&nbsp;AT91C_SM_NCS_WR_PULSE&nbsp;&nbsp;&nbsp;&nbsp;(4&nbsp;&lt&lt&nbsp;8)<br />#define&nbsp;AT91C_SM_NRD_PULSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3&nbsp;&lt&lt&nbsp;16)<br />#define&nbsp;AT91C_SM_NCS_RD_PULSE&nbsp;&nbsp;&nbsp;&nbsp;(4&nbsp;&lt&lt&nbsp;24)<br />应该改成<br />#define&nbsp;AT91C_SM_NWE_PULSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(3&nbsp;&lt&lt&nbsp;0)<br />#define&nbsp;AT91C_SM_NCS_WR_PULSE&nbsp;&nbsp;&nbsp;&nbsp;(3&nbsp;&lt&lt&nbsp;8)<br />#define&nbsp;AT91C_SM_NRD_PULSE&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;(4&nbsp;&lt&lt&nbsp;16)<br />#define&nbsp;AT91C_SM_NCS_RD_PULSE&nbsp;&nbsp;&nbsp;&nbsp;(4&nbsp;&lt&lt&nbsp;24)
 楼主| hao01222 发表于 2008-7-30 16:32 | 显示全部楼层

问题已经解决

是我程序里的问题,现已解决,谢谢
lomeisi_99 发表于 2008-7-31 12:46 | 显示全部楼层

恭喜

  
温wenwen 发表于 2012-8-28 16:31 | 显示全部楼层
你怎么解决的也说一下啊
yf823547490 发表于 2014-11-20 11:08 | 显示全部楼层
O(∩_∩)O~,比较鄙视这种  自己有问题了,伸手问大家意见,
自己解决问题了,甩甩尾巴走人,狗屁经验资料都不留下的人,有时候你的一句两句指点,够别人折腾好几天了。
yf823547490 发表于 2014-11-20 12:28 | 显示全部楼层
这个问题也折腾我好几天了,问题描述和LZ基本一致,
我是在Nand上移植FATFS,总是不大成功,各种错误都报了,最后自己从各方面测试nand的驱动函数,
才发现,根源问题是  某些BLOCK擦除不成功,我拿到的K9F1G08中
uint32_t Nand_BlockErase(uint32_t Block)
{
  if (Block >= NAND_BLOCK_NUM)return 0;
  
  nand_cmd(NAND_CMD_ERASE0);
  nand_addr(Block & 0xff);
  nand_addr((Block >> 8) & 0xff);
  nand_cmd(NAND_CMD_ERASE1);       
  nand_waitready();
  
  while (!(nand_readstatus() & (1 << 6)));
  if (nand_readstatus() & 0x01) {
    return 0;
  }  
  return 1
}
yf823547490 发表于 2014-11-20 12:54 | 显示全部楼层
注意他传送Block地址的时候,直接低8位,再高8位,
这实际上page号的传送方式,因为K9F1G08包含1024*64=65536个page所以需要 16位的地址数据

再看BLOCK仅仅含有1024个,仅需要11位就够了,那么这11位是怎么传的呢?直接先低八位,再高八位么?
查找数据手册:
The Erase operation is done on a block basis. Block address loading is accomplished in two cycles initiated by an Erase Setup command(60h). Only address A18to A 27(X8) or A17 to A 26(X16) is valid while A12 to A17(X8) or A11to A16(X16) is ignored.

所以说只有A18~A27的数据是有效的,对比
3rd Cycle A12 A13 A14 A15 A16 A17 A18 A19    Row Address
4th Cycle A20 A21 A22 A23 A24 A25 A26 A27    Row Address

所以Block的数据不能像page一样直接先传低8为再高8位,
必须先将BLOCK号向左移动6位,跟数据手册上说的额A18~A27对正,才能传过去。修改代码如下:
uint32_t Nand_BlockErase(uint32_t Block)
{
  if (Block >= NAND_BLOCK_NUM)return 0;
  
        Block=Block<<6;
  nand_cmd(NAND_CMD_ERASE0);
  nand_addr(Block & 0xff);
  nand_addr((Block >> 8) & 0xff);
  nand_cmd(NAND_CMD_ERASE1);       
  nand_waitready();
  
  while (!(nand_readstatus() & (1 << 6)));
  if (nand_readstatus() & 0x01) {
    return 0;
  }  
  return 1;
}

测试后一切OK了, FATFS也能正常跑起来了
yf823547490 发表于 2014-11-20 12:57 | 显示全部楼层
最后啰嗦一下,也是希望如果碰到相同问题的人能更轻松地解决。

为什么会出现类似  

写入之前是可以擦的
任何一页的数据写入之后,我想擦除整个块,但发送擦除命令后,读出该页还是原来的数据

但是在那些未写入数据的页确可以擦除,不知道这是一个什么缘故。


这样的问题呢?
yf823547490 发表于 2014-11-20 13:03 | 显示全部楼层
分析如下:

如上所述,如果ERACE BLOCK传送的地址是不正确的,那么例如我擦除BLOCK 1000,实际上擦除的是BLock 2;
可能拿到板子的时候,nandflash已经全部擦除过一次,也可能是nand flash出厂就是这样,所有BLOCK 都是oxff,

这样的话就是第一条描述 ,写入前都是可以擦的,因为本来就是0xff,擦出是否成功都是0xff,所以误认为写入前是可以擦除的,实际上没有擦除

因为刚开始是0xff,所以数据是可以写入的,但是写入之后,想要擦除却擦除不掉,读出来的页还是之前写入的数据,这正是因为传送的BLOCK地址错误,导致该BLOCK没有正确擦除啊

未写入数据的页还是0xff,所以还是会被认为是可以擦除

最终现象就是,和LZ描述的一样      一旦写入一次就无法再次擦除和写入
您需要登录后才可以回帖 登录 | 注册

本版积分规则

17

主题

49

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部