FLASH页块分析
一般flash存储器以页和块为单位,页是最小单位,以多少字节为一页,读也是以页为最小单位读,在一个页内读取某个地址的数据
而一块里面又分为多少页,一般块为最小擦除单元
FLASH的读和写分析
读:
FLASH的读取一般是先发出页地址,再发出行地址,页地址代表在哪个页,行地址代表在页内哪个地址
如果是连续读取的话,只需要发出起始地址即可,后面直接读就可以了,如果是超出了一页要重新发出地址读取写一页
写
一般是先擦除再写,地址发出同上,擦除是以块为单位,并且有的flash还要去除写保护
写基本和读差不多,但是写要先擦除,擦除地址和长度必须是块的整数倍
读FLASH代码
void nand_read(unsigned int addr, unsigned char *buf, unsigned int len)
{
int i = 0;
int page = addr / 2048;
int col = addr & (2048 - 1);
nand_select();
while (i < len)
{
/* 发出00h命令 */
nand_cmd(00);
/* 发出地址 */
/* col addr */
nand_addr_byte(col & 0xff);
nand_addr_byte((col>>8) & 0xff);
/* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff);
/* 发出30h命令 */
nand_cmd(0x30);
/* 等待就绪 */
wait_ready();
/* 读数据 不能超过一页,不能超过数据长度*/
for (; (col < 2048) && (i < len); col++)
{
buf[i++] = nand_data();
}
if (i == len)
break;
col = 0;
page++; //超过一页,往下一页读取
}
nand_deselect();
}
写FLASH代码
nt nand_erase(unsigned int addr, unsigned int len)
{
int page = addr / 2048;
if (addr & (0x1FFFF)) //起始地址必须是块的整数倍
{
printf("nand_erase err, addr is not block align\n\r");
return -1;
}
if (len & (0x1FFFF)) //长度是块的整数倍
{
printf("nand_erase err, len is not block align\n\r");
return -1;
}
nand_select();
while (1)
{
page = addr / 2048;
nand_cmd(0x60);
/* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff);
nand_cmd(0xD0);
wait_ready();
len -= (128*1024);
if (len == 0)
break;
addr += (128*1024); //擦除下一块
}
nand_deselect();
return 0;
}
void nand_write(unsigned int addr, unsigned char *buf, unsigned int len)
{
int page = addr / 2048;
int col = addr & (2048 - 1);
int i = 0;
nand_select();
while (1)
{
nand_cmd(0x80);
/* 发出地址 */
/* col addr */
nand_addr_byte(col & 0xff);
nand_addr_byte((col>>8) & 0xff);
/* row/page addr */
nand_addr_byte(page & 0xff);
nand_addr_byte((page>>8) & 0xff);
nand_addr_byte((page>>16) & 0xff);
/* 发出数据 */
for (; (col < 2048) && (i < len); )
{
nand_w_data(buf[i++]);
}
nand_cmd(0x10);
wait_ready();
if (i == len)
break;
else
{
/* 开始下一个循环page */
col = 0;
page++;
}
}
nand_deselect();
}