Chinaunix首页 | 论坛 | 博客
  • 博客访问: 2756978
  • 博文数量: 102
  • 博客积分: 1444
  • 博客等级: 中尉
  • 技术积分: 13891
  • 用 户 组: 普通用户
  • 注册时间: 2012-03-29 10:58
文章分类

全部博文(102)

文章存档

2014年(29)

2013年(14)

2012年(59)

分类: LINUX

2012-08-17 13:56:58

上一节我们介绍过nand flash一些特性和基本的命令序列操作方法,下面我们看看如何擦除、写nand flash

一、擦除nand flash

k9f1208U0M是按块擦除nand flash 的,1 block = 32 page = 32 * 512 byte= 16KB
这里有注意的是擦除的地址绝对要是块对其的,即addr % block == 0

看看datasheet上面擦除block的时序



代码如下:

//擦除一个block块
int erase_one_block(int addr)
{
int statu;

addr = addr >> 9;
WRITE_CMD(0x60);//setup cmd
WRITE_ADDR(addr&0xff);//1st Cycle
WRITE_ADDR((addr >> 8)&0xff);//2st Cycle
WRITE_ADDR((addr >> 16)&0xff);//3rd Cycle
WRITE_CMD(0xd0);//erase cmd
while(!NFREADY());//wait ready
statu = read_statu();
if((statu & 0x1) != 0)
return -1;

return 0;
}

/*
 * 对nand flash 的一个块进行擦除
 * 1 page_size = 512 bye;
 * 1 block_size = 32 * page_size = 32 * 512 / 1024 = 16bye;
 */
int nand_erase(int addr,int size)
{
int n = size / BLOCK_SIZE;
int i = 0;
//判断是否是块对齐的地址
if(addr % BLOCK_SIZE != 0)
{
uart0_printf("The addr is invalid,must addr %% 16byte == 0.\r\n");
return -1;
}
if(n < 1) 
n = 1;
uart0_printf("Start %#x will %d blocks will be erased.\r\n",addr,n);
NFChipEn();

for(i = 1;i <= n;i ++)
{
if(erase_one_block(addr) < 0)
uart0_printf("Erase failed.\r\n");

uart0_printf("%d block is erased\r",i);
addr = addr +  BLOCK_SIZE;
}

uart0_printf("\n");

NFChipDs();
return 0;
}

关于状态的读取



int read_statu()
{
int statu;

WRITE_CMD(0x70);
delay_mtime(1000);
statu = READ_DATA();
#ifdef  _DEBUG_
uart0_printf("statu = %#x.\r\n",statu);
#endif
return statu;
}

二、写nand flash

k9f1208U0M是按页写nand flash 的,1 page = 512 byte
这里有注意的是擦除的地址绝对要是页对其的,即addr % page == 0

看看datasheet上面写一个页的时序



代码如下:

//发送命令和地址
int write_cmd_addr(int addr)
{
int column_addr,page_address;
column_addr = addr % PAGE_SIZE;
page_address = addr >> 9;

WRITE_CMD(0x80);
WRITE_ADDR(column_addr & 0xff);
WRITE_ADDR(page_address & 0xff);
WRITE_ADDR((page_address >> 8) & 0xff);
WRITE_ADDR((page_address >> 16) & 0xff);

return 0;
}

/*
 *注意:不管你要写多少个字节,每次写占用的最少
 *是一个页的大小。
 */
int write_nand_page(int addr,char str[])
{
int statu,new_addr = addr;
int i = 0,j = 0;
int nbyte = my_strlen(str),n;

uart0_printf("write %d pages.\n",nbyte/PAGE_SIZE);

if(addr % PAGE_SIZE != 0)
{
uart0_printf("The addr is invalid.\r\n");
return -1;
}
/*
 *不够一页的按一页处理
 *超过一页的按两页处理
 */
n = nbyte / PAGE_SIZE;
if(nbyte % PAGE_SIZE != 0) n ++;
if(n < 1) n = 1;

NFChipEn();
for(i = 0;i < n;i ++)
{
write_cmd_addr(new_addr);
for(j = 0;j < PAGE_SIZE && *str != '\0';j ++,str ++)
{
WRITE_DATA(*str);
}

WRITE_CMD(0x10);
while(!NFREADY());
statu = read_statu();
if((statu & 0x1) != 0)
{
uart0_printf("write error.\r\n");
return -1;
}

new_addr += PAGE_SIZE;
}

#ifdef  _DEBUG_
uart0_printf("*str = %c n = %d nbyte = %d.\r\n",*str,n,nbyte);
#endif
uart0_printf("write %d bytes at addr : %#x.\r\n",nbyte,addr);
NFChipDs();

return ;
}
阅读(11606) | 评论(0) | 转发(5) |
给主人留下些什么吧!~~