基于嵌入式MCU数据Flash的数据存储及管理方法研究与实现
入式系统应用,通过数据分区的格式定义,对其某个数据的寻址非常简单。 数据读取操作 数据读取操作在最新数据分区上进行,首先通过数据条目的data id进行偏移地址查表,然后根据最新数据分区编号进行地址计算,计算公式如下: 地址=0号分区首地址+(最新数据分区编号*分区大小)+偏移地址 (2) 和EEPROM的读取方式一样,直接读取该地址便可以得到数据[5],读取操作不会改变最新数据分区及其状态字。其软件实现如下所示: void ReadEeprom(uint16_t data_id, void *dest_addr,uint16_t size) 数据写操作 在数据条目的设计中,将数据条目的data id存储地址同时做为数据状态字的存储地址,在写操作时通过数据状态字判断该数据条目地址是否执行过擦除操作,从而避免不必要的分区拷贝和扇区擦除操作,降低数据写操作代价[6]。首先根据公式(2)计算数据在最新数据分区的存储地址,读取其data id存储位置得到数据状态字,判断该数据在最新数据分区的写入地址是否已经被擦除。如果数据状态字等于0xff,表明写入地址已经被擦除,按照Flash的写操作命令序列在data id地址处写入data id,在data地址处写入data;如果数据状态字不等于0xff,表明写入地址未被擦除,需要进行分区拷贝操作,操作完成后更新最新分区及最新分区状态字。数据写操作流程如图2所示。 通过为每个数据建立状态字来表示是否已经在当前分区上进行了存储操作,数据1的存储操作便不会影响数据2的存储,数据2仍然能够在当前分区上进行存储,而不会每次只要有数据的写操作都会造成所有的数据在分区之间的搬移,这样不仅提高了写操作的效率,而且会进一步提高Flash的使用寿命[7]。 分区拷贝操作 在进行数据在分区间的拷贝操作时,首先备份当前最新分区状态字和最新数据分区编号,然后更新最新数据分区编号,查看最新数据分区首地址是否是Flash扇区首地址,如果是,执行扇区擦除操作[8],然后按照Flash的写操作命令序列在当前最新数据分区的data id地址处写入data id,在data地址处写入data,然后将备份数据分区内的其他数据复制到当前最新数据分区中。 最新数据分区及状态字更新 最新数据分区编号的更新算法为:将最新数据分区编号加一,判断其结果,如果最新数据分区编号等于分区个数,设置最新数据分区编号为0。状态字更新算法为:判断所备份最新数据分区状态字是否等于0xfe,如果等于0xfe,设置最新分区状态字为0,否则最新分区状态字加一,然后将最新分区状态字写入当前最新数据分区状态字地址,即数据分区首地址位置。 掉电存储 如果嵌入式系统在写操作期间掉电,由于在发生掉电时最新数据分区状态字还没有更新,再次上电时查找到的最新数据分区仍然是写操作进行前的那个数据分区,通过在写入操作完成后更新状态字的方式保证了即使发生了掉电,重新上电后数据仍能恢复为原来的数据分区中的数据。上电时通过分区状态字查找最新数据分区的算法如下: (1)当存在取值为0的分区状态字时,小于分区数的最大状态字代表的分区为最新数据分区; static void FindNewestBankByStatusWord(void)
{
u_EepromWord eedata;
uint16_t src_addr;
src_addr = GetDataAddrFromItsId(data_id);
src_addr += (Active_bank * EEPROM_SIZE_BYTES);
while(0 != size){
eedata.word = READFLASH16(src_addr);
*(uint8_t*)dest_addr = eedata.byte.msb;
((uint8_t*)dest_addr)++;
src_addr++;
size--;
}
}
(2)当不存在取值为0的分区状态字时,最大状态字代表的分区为最新数据分区;该算法实现流程如附图3所示,上电后经过该算法处理后,可以得到最新数据分区编号和最新数据分区状态字,其软件代码如下所示:
{
Bool roll_over;
uint8_t bank;
uint16_t bank_status;
uint16_t largest_status = 0;
Bool erased = TRUE;
roll_over = StatusWordIsRollover();
for(bank = 0;bank < EEPROM_BANKS;bank++){
bank_status = READFLASH16(EEPROM_START + (bank * EEPROM_SIZE_BYTES));
if(FLASH_ERASED_WORD != bank_status){
erased = FALSE;
if(TRUE == roll_over){
if((bank_status < EEPROM_BANKS) && (bank_status >= largest_status)){
Active_bank = bank;
largest_status = bank_status;
}
}else{
if(bank_status > largest_status){ Active_bank = bank;
largest_status = bank_status;
}
}
if(TRUE == erased){ Active_bank = 0;
(void)EraseEepromBank(EEPROM_START);
}
}
嵌入式 MCU Flash 数据存储 EEPROM 201310 相关文章:
- Linux嵌入式系统开发平台选型探讨(11-09)
- 基于Winodws CE的嵌入式网络监控系统的设计与实现(03-05)
- 嵌入式系统实时性的问题(06-21)
- 嵌入式实时系统中的优先级反转问题(06-10)
- 嵌入式Linux系统中MMC卡驱动管理技术研究(06-10)
- FPGA的DSP性能揭秘(06-16)
