方案适用flash存储器
在工作中总是遇到关于flash操作的问题,nandflash写之前必须先擦除,擦除还必须是页擦除,就写几个字节,页擦不全没了!真是不方便。
这里记录一下自己的实现,以便日后开发,也便利大家,如果有好的建议,欢迎大家讨论
先写一下思路:
由于flash的工作原理,故支持从1写0,不支持从0写1,利用这一点,最终只要保证我们要擦除、或将来写数据的地址为全ff即可。
- 判断自己需要擦除多长的地址,需要连续处理几页。
- 准备1~2页缓冲区(这里看内存可以大),擦除。
- 将原始数据全部存放到缓冲区。
- 擦除原始区,将本页要擦除地址之前的数据写回,需要计算偏移地址。
- 操作地址偏移增加要擦除的长度。
- 将本次要擦除地址之后的数据写回。
- 操作结果为:擦除指定地址起始指定长度的数据区。
代码区:
//擦除指定地址、指定长度数据,length为字节数
#define FLASH_TMP(120 * FLASH_PAGE_SIZE)//交换区起始地址
BOOL flash_erase_byte(UINT32 start_addr, UINT32 length)
{
UINT8 i = 0;
UINT32 start_page = 0, page_cnt = 0;//起始页、操作的页数
UINT32 op_addr = 0, op_len = 0;//数据写回操作的偏移地址
//计算起始扇区号&扇区数
start_page = start_addr / FLASH_PAGE_SIZE;//除以扇区大小
page_cnt = (length / FLASH_PAGE_SIZE);//判断输入长度是否超扇区长度
op_addr =(start_page * FLASH_PAGE_SIZE;
//准备交换区,将原数据读出
for(i = 0; i < page_cnt; i++)
if(!FLASH_Eraser_Page(page_cnt, FLASH_TMP))//准备1页交换区
return FALSE;
if(!FLASH_Read(op_addr,(UINT32*)FLASH_TMP,(page_cnt * FLASH_ PAGE_SIZE)))//数据转存交换区
return FALSE;//擦除起始扇区&扇区数
for(i = 0; i < page_cnt; i++)
if(!FLASH _Eraser_Page(page_cnt, op_addr))//擦除源数据
return FALSE;//将数据写回,除输入地址开始~长度之外
if(!FLASH_Read(FLASH_TMP,(UINT32*)op_addr,(start_addr - op addr)/4))
return FALSE;
op_addr +=(start_addr - op_addr);
if(op_addr != start_addr)
return FALSE;
op_addr += length;
op_len =(page_cnt * FLASH_PAGE_SIZE)-(op_addr -(start_page * FLASH_PAGB_SIZE));//剩余需要写回的数据长度
if(!FLASH_Read((FLASH_TMP + (op_addr - (start_page * FLASH PAGE_SIZE))),(UINT32*)op_addr, op_Ien/4))
return FALSE;
//返回结果
return TRUE;
}