介绍

系统中时常会分配一些NVM区存储掉电不丢失的数据。这时就会对NVM区进行读写操作, 未防止读写过程中数据的丢失, 所以可以设计备份机制提高系统的可靠性和稳定性。

在单片机系统中, 如果不带EEPROM, 则更多的把数据放置在flash中, 这种情况下需要规划好flash分配, 根据数据的大小, 一般放置于flash最后的空间。例如, flash大小为32k, 需要存放的数据为1k, 则NVM区地址为(32-1)k ~ (32k-1), 此时固件大小需要注意不能超过(32-1)k 。

向NVM区(Flash)写入数据可分为3步:

  • 第一步, 将目标扇区内原有数据读出到RAM中;
  • 第二步, 擦除NVM目标扇区内数据;
  • 第三步, 将新数据和RAM中的旧数据写入到该扇区中。

基于以上写操作的特点可以看出, 若执行写NVM区操作的第二步或第三步时芯片断电了, 就会造成NVM区内原有数据丢失, 而新数据写入失败, 表现出NVM区内数据错乱的现象。

操作

第一次写入数据

第一步:将NVM区地址0x0000 ~ 0x00FF定义为Block1, 将0x0200 ~ 0x02FF定义为Block2。

#define Block1 0x0000

#define Block2 0x0200

第二步:定义一个256字节的数组databuf和一个标志位变量cnt, 并将cnt赋值0。

unsigned char databuf[256];

Unsigned char cnt = 0;

第三步:将目标数据(待写入数据)拷贝到databuf数组中, 并将cnt+1拷贝到databuf+255的位置。

databuf[255] = cnt+1;

第四步:调用WriteNVM函数向Block1写入数据databuf, 写入长度256字节。调用WriteNVM函数向Block2+255位置写入cnt, 写入长度1字节

WriteNVM(Block1, databuf, 256);

WriteNVM(Block2+255, &cnt, 1);

更新数据

第一步:调用ReadNVM函数分别读取Block1和Block2的标志位(最后一字节)。

unsigned char flag1, flag2;

ReadNVM(Block1+255, &flag1, 1);

ReadNVM(Block2+255, &flag2, 1);

第二步:判断两个Block的标志位大小, 选取标志位数值小的Block进行更新。将目标数据(待写入数据)拷贝到databuf数组中, 并将标志位加2后拷贝到databuf+255的位置。

if(flag1 > flag2)
{
    cnt = flag2 + 2;

    databuf[255] = cnt;

    WriteNVM(Block2, databuf, 256);
}else{

    cnt = flag1 +2;

    databuf[255] = cnt;

    WriteNVM(Block1, databuf, 256);

}

读取数据

第一步:读取Block1和Block2的标志位数据。

ReadNVM(Block1+255, &flag1, 1);

ReadNVM(Block2+255, &flag2, 1);

第二步:判断标志位大小, 数值大的Block内为新数据, 数值小的Block内为旧数据。

if(flag1 > flag2)
{
    ReadNVM(Block1, databuf, 255);
}else{
    ReadNVM(Block2, databuf, 255);
}

转载:https://zhuanlan.zhihu.com/p/77334802

GitHub 加速计划 / nv / nvm
78.06 K
7.82 K
下载
nvm-sh/nvm: 是一个 Node.js 版本管理器,用于在不同的 Node.js 版本之间进行切换。它可以帮助开发者轻松管理多个 Node.js 版本,方便进行开发和测试。特点包括轻量级、易于使用、支持跨平台等。
最近提交(Master分支:2 个月前 )
9c9ff4ba Moved issue template into ISSUE_TEMPLATE folder 7 天前
51ea809d - 7 天前
Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐