存储的乒乓操作

首先,要明确的是,数据写的过程包括

  1. 擦除,下图为NAND FLASH一个block(128K+7K)的时间,若擦除时被打断,数据会残缺
    在这里插入图片描述

  2. 写入,下图为NAND FLASH写入一个page(2K+112Byte)的时间,所以一个block的写入需要64 x 300us = 19.2ms 的时间,若写入时被打断,数据会残缺
    在这里插入图片描述

数据读的过程时间不计,因为读过程被打断,并不会造成数据的损坏
综上所述,对擦除,写入的失败都要进行处理(会造成数据损坏)


接下来,对乒乓操作进行解释,对于擦除和写入的处理有两种方式,先介绍

第一种

对于读写都放在一个接口内

函数
{
	//擦写为一个任务
	擦除任务
	写入任务
	
	//读取为一个任务
	读取任务
	若读取校验失败,屏蔽擦写任务,读取另一个块
}

在这里插入图片描述
首先,使用两个块作为乒乓块
关于写操作: 写入数据时,先指向块A,对其进行擦除并写入的操作。其中,若擦除时断电,或者写入时断电了,不做处理。若擦除和写入都完成的话,将写指针指向另一个块。
关于读取: 读取时读取不是写指针所指的那块,比如写指针指向A,则读取B

  1. 第一次上电初始化时,先对AB块进行擦除
  2. 收到数据后,将数据写入A块(上电初始化时擦除了,所以现在不用擦),然后将写指针指向B块。(若此时要读取数据的话,就读取A块,即不是写指针指向的那块)
  3. 再次收到数据,将数据写入B块,同理,上电初始化的时候擦除过了,所以现在不擦,然后将写指针指向A块(若此时要读取数据的话,就读取B块,即不是写指针指向的那块)

现在假设两块都有数据,那么接下来分析各种失败的情况
4. 擦除时掉电,不做处理,因为还有另一块做备份,上电时读取另一块数据就好
5. 写入时掉电,不做处理,同上
6. 读取时掉电,此时对数据不会有影响,不处理


第二种

函数
{
  	写入任务				//和擦除为一个任务
  	
  	读取任务				//读取为一个任务
  	若读取校验失败,屏蔽擦写操作,读取另一个块
  	
  	擦除任务				//和写入为一个任务
}

关于写操作: 假设数据已经写入两块,现在写入数据时,先指向块A,将数据写入块A,然后擦除块B,然后将写指针指向块B
关于读取: 读取时读取不是写指针所指的那块,比如写指针指向A,则读取B

现在假设两块都有数据,那么接下来分析各种失败的情况

  1. 写入时掉电,不做处理,因为还有另一块做备份,上电时读取另一块数据就好
  2. 擦除时掉电,不做处理,因为还有另一块做备份,上电时读取另一块数据就好
  3. 读取时掉电,此时对数据不会有影响,不处理

那么以上两种方式有何区别?
首先,不讨论写操作时掉电的情况,因为两种方式,写操作掉电的话,都只能读取旧的备份数据。所以以下默认写操作没问题。
区别在擦除操作和写操作的顺序,
第一种方式,由于SPI_FLASH的擦除时间偏长,所以掉电时很大概率落在擦除中,所以当进行写入操作时,万一掉电了,最新的数据没有写入到FLASH中,重新上电后读取的是上次备份的数据
第二种方式,由于每次都是先写入再擦除另一块,所以写入最新数据后,擦除的是备份的数据,当擦除备份数据掉电后,重新上电读取的是最新的数据。

其他问题
读取和写入会冲突吗?
就算使用FREE_RTOS,要需要保证读取 和 写入不能被打断,擦除和读取同时只能有一个在进行

若两个块读取的数据都校验失败怎么办?
重新初始化,擦除两个块的数据

猜你喜欢

转载自blog.csdn.net/Hao_Zhen/article/details/83748718