当它找到与请求数据单元相匹配的记录时,它将对应的地址先存起来,然后继续搜索。如果它找到另外一条匹配的记录,它就用新的地址代替刚才存储的地址。
当到达阵列结尾时,最终存储的地址将指向最近写入拷贝的请求记录。读函数随即在被调用时将这个数据拷贝到缓存。
复用存储器空间
现在,我们已经有了一种以读取为主的可行机制用于从存储阵列中存取记录。剩下只有一个问题:我们还没有建立起复用被废弃的记录拷贝占用的空间。(我们也还没有建立删除记录的机制,但由于是用在嵌入式应用中,这可能不是一个很重要的特性)
如果不恢复空间,分配的空间将很快用完。恢复空间意味着擦除整个页,因为闪存只能一次擦除一整页。但闪存页被随意擦除时将会出现删除有用信息的风险。唯一的方法是在擦除旧页时将有效信息拷贝到新的页。
从废弃记录恢复空间要分三步走:首先,打开新的闪存页,将每个数据单元的最新版拷贝到新的页;然后,删除旧页;最后,在新页上放置页标记以便读程序能找到它们。
www.55dianzi.com
第一步有些技巧,因此我们稍详细地进行介绍。执行这一步的简单方法是将它分成两小步:第一步,使用RAM阵列存储记录号和阵列中最新记录的地址;第二步,穿过RAM阵列将最新的记录拷贝到新的 闪存 页。这个过程很快,相对也比较顺利。
这种方案的问题是所用处理器(见图1)的RAM为1K字。这种方案将限制可存储进RAM中的单一数据数量,因为这个RAM还要节省下来用作缓存。这是明显不能接受的。
这种解决方案非常耗时,但不管存储阵列多大(在合理范围内)都能正常工作。该方案不会在RAM中创建一份指针列表,而是针对每个单一条目(entry)在源阵列中作多次穿越。因此压缩算法变为:
1. 从源阵列中读一个单元;
2. 在目标阵列中寻找该单元。如果找到了,表示这个单元已经被写入。增加源指针值,回到第(1)步;
3. 扫描源阵列寻找单元的最新拷贝;
4. 将数据单元的最新拷贝写入目标阵列;
5. 增加源指针,并回到第(1)步。
最终,在目标阵列中每个数据单元都有一个唯一的条目。图4描述了一个已填满的页。源页现在可以被安全地删除,页的头部被写入到目标阵列。
图4:在空间恢复之后的图2所示数据页内容
这个过程的构建使得存储的数据非常安全。在使用闪存器件时必须面对的危险是写入或擦除操作期间发生电源故障。
如果发生电源故障,则有可能一个或多个页被破坏(在写入时),或未被完全删除(在删除操作时)。但上述压缩操作本身是安全的。因为:
1. 如果在写入操作期间发生电源故障,源页是完全不受影响的。在电源恢复后,新写的页很容易被识别(它们没有页头),将其擦除后重新开始写入操作。
2. 如果在旧页被擦除期间发生电源故障,它们可能包含无效的头部。这些页可以被删除,然后将头部增加到新的页中。
3. 如果在页头部被写入新页时发生电源故障,数据是不受影响的。页头部的更新操作可以重新开始。
总之,应该没有什么情况能让意外事件造成无可挽救地破坏阵列数据。
性能增强
目前的存储子系统没有差错检测机制。在数据单元识别符中目前有6个比特是保留未用的。
设计师可以使用CRC6算法(x6+x+1)计算整个数据单元的CRC以确保不会产生任何读或写错误。虽然这不是一个特别可靠的算法(它会从64个多位差错中漏掉一个),但它能检测实际中可能发生的大多数差错。
上述系统的另外一个限制是读取访问时间必需很长。为了寻找最新的记录,每一次读取都必须读遍阵列中的每个记录。有三种方法可以用来改善访问时间:
1. 在数据单元中留一个空的字用于前向指针。当数值更新时,在前向指针中填入指向新条目的内容。这样这个表可以当作一个链接列表。
2. 向后穿越表格。现在你可以简单停留在第一次出现的请求单元上。
3. 如果只有少量的单一单元,可以在上电时就创建一个包含单元ID和指针的RAM阵列。随后的访问将非常迅速—只要读取RAM阵列就可以发现到哪里去获得数据单元。
本文关键字:用户 DSP/FPGA技术,单片机-工控设备 - DSP/FPGA技术
上一篇:基于单片机的数字正弦机研制