个人笔记_FLASH性质存储器扇区边界擦除算法

大部分FLASH性质存储器都有很多相似的操作规则,比如擦除方式就很特殊,最小擦出单位必须按照扇区来操作,而数据的写入地址的内容必须是擦除状态。这也是为什么EEPROM还能存在的一方面的原因吧(可以字节擦除)。由于这种特殊的性质,导致我们在利用FLASH存储数据的时候必须注意对扇区擦除的操作。这里我总结个人的两个操作技巧(以下内容是针对不带文件系统的存储器说明的,带文件系统的也可以参考)。


技巧1:如果可以,尽可能将协议长度定义为2的N次方,这样的话能保证每次要操作的一个新的扇区的时候地址刚好是新扇区的起始位置,那么这种擦除方式就很简单了,方式如下(假设扇区大小4KB):
if(wrAddr%4096 == 0)//刚好上次写到了上个扇区的末尾
{
wrAddrCmp = wrAddr;
while(Sst25_RdOneByte(wrAddrCmp++) == 0xFF)
{
if(wrAddrCmp ==(wrAddr +4096))
break;
}
if(wrAddrCmp <(wrAddr +4096))
Sst25_EraseSector(wrAddr);
}
讲解:先判断是不是新的扇区地址,是的情况下读出扇区数据,判断是否都在擦除状态,否的情况下擦除该扇区。


技巧2:如果我们定义的协议长度不是2的N次方,或者写入长度完全不是固定的,那就可以参考下列方式来处理:
if((wrAddr%4096 == 0) || ((4096 - (wrAddr%4096)) < RecordLength))
{
if(wrAddr%4096 == 0)//刚好上次写到了上个扇区的末尾
{
wrAddrCmp = wrAddr;
while(Sst25_RdOneByte(wrAddrCmp++) == 0xFF)
{
if(wrAddrCmp ==(wrAddr +4096))
break;
}
if(wrAddrCmp <(wrAddr +4096))
Sst25_EraseSector(wrAddr);
}
else if((4096 - (wrAddr%4096)) < RecordLength)//这次写入的数据会占用一个新的扇区
{
wrAddrCmp = wrAddr%4096 + 4096;
while(Sst25_RdOneByte(wrAddrCmp++) == 0xFF)
{
if(wrAddrCmp ==(wrAddr%4096 + 4096 + 4096))
break;
}
if(wrAddrCmp <(wrAddr%4096 + 4096 + 4096))
Sst25_EraseSector(wrAddr%4096 + 4096);
}
}
讲解:这里同样添加了技巧1的计算方式是因为会有技巧1的情况出现比如40960(每次写40B,40960%40==0)。后面的思路是
先判断这次写入的数据从开始写入的地址算起到写入的长度结束,是不是超过了原先的扇区,如果超过了,就需要在写入之前对下一个扇区
做擦除处理。先获取下一个扇区的首地址,然后从首地址开始读取该扇区所有数据,是否都在擦除状态,如果有数据不在擦除状态就对下一个扇区
进行一次擦除操作。

后续需要考虑的问题就是,存储器数据存满的处理方式,一般会选择回绕,将最旧的数据删除掉,再开始存储新的数据,有时间再考虑。


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
题目描述 有 $n$ 种不同面额的硬币,每种硬币的数量无限。假设硬币面额为 $a_1,a_2,...,a_n$,现在要用这些硬币来找零 $m$ 元,求最少需要的硬币个数。 样例 输入:5,[1,2,5] 输出:2 算法1 (动态规划) $O(nm)$ 很明显,这是一道动态规划的问题。 设 $f[i][j]$ 为只考虑 $i$ 种硬币,总面值为 $j$ 元时所需的最少硬币数。 显然,对于 $f[i][j]$,我们可以选择不取第 $i$ 种硬币,此时 $f[i][j]=f[i-1][j]$。也可以选择取第 $i$ 种硬币,此时 $f[i][j]=f[i][j-a_i]+1$。 于是,状态转移方程为: $$f[i][j]=\min(f[i-1][j],f[i][j-a_i]+1)$$ 注意,当 $j<a_i$ 时,显然不能取第 $i$ 种硬币,因此 $f[i][j]=f[i-1][j]$。 最终答案即为 $f[n][m]$。 时间复杂度 状态数为 $nm$,转移复杂度为 $O(1)$,故总时间复杂度为 $O(nm)$。 参考文献 无 C++ 代码 class Solution { public: int coinChange(vector<int>& coins, int amount) { int n = coins.size(); vector<vector<int>> f(n+1,vector<int>(amount+1,0x3f3f3f3f)); for(int i=0;i<=n;++i) f[i][0] = 0; for(int i=1;i<=n;++i){ for(int j=1;j<=amount;++j){ if(j<coins[i-1]) f[i][j] = f[i-1][j]; else f[i][j] = min(f[i-1][j],f[i][j-coins[i-1]]+1); } } return f[n][amount]>=0x3f3f3f3f?-1:f[n][amount]; } }; Java 代码 class Solution { public int coinChange(int[] coins, int amount) { int n = coins.length; int[][] f = new int[n+1][amount+1]; for(int i=0;i<=n;++i) f[i][0] = 0; for(int i=1;i<=n;++i){ for(int j=1;j<=amount;++j){ if(j<coins[i-1]) f[i][j] = f[i-1][j]; else f[i][j] = Math.min(f[i-1][j],f[i][j-coins[i-1]]+1); } } return f[n][amount]>=0x3f3f3f3f?-1:f[n][amount]; } }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值