当前位置:文档之家› 15_片内flash模拟EEPROM

15_片内flash模拟EEPROM

Le i)LTK女娲STM32开发板使用手册修订历史L TK (Le iT ek )目录第15 片内flash 模拟EEPROM (3)章 Flash 和EEPROM (3)15.1 Flash 和EEPROM 对比 .......................................................... 3 15.1.1 内部Flash 模拟EEPROM 原理.............................................. 3 15.1.2 Flash 掉电数据恢复 ................................................................ 5 15.1.3 内部flash 应用实例 ----- 模拟EEPROM .. (6)15.2 实例描述 ................................................................................ 6 15.2.1 实验效果 ................................................................................ 6 15.2.2 硬件设计 ................................................................................ 6 15.2.3 软件设计 .. (6)15.2.4k )片内flash 模拟EEPROM第15章 Flash 和EEPROM15.1 Flash 和EEPROM 对比15.1.1为了节省成本,STM32内部没有集成EEPROM ,当我们需要存储一些数据时,可使用内部flash 来模拟EEPROM 。

不像flash 存储器,EEPROM 在向存储空间重新写入数据时,不需要做擦除操作。

由于外部EEPROM 和内部flash 模拟的EEPROM 的写入方式有所不同,所以使用内部flash 模拟EEPROM 时,要使用掉电恢复机制。

以下表格是他们的主要区别。

内部Flash 模拟EEPROM 原理15.1.2考虑到flash 存储器的局限性以及产品的需求,模拟EEPROM 至少需要两页容量大小完全相等的flash ,其中第0页已经擦除过,可以进行写操作。

当第0页写满了以后,第1页需要回收第0页内的有效数据,若此时需要新写入的数据,也会写入第1页。

每一页的开头16位都有一个状态标志,描述当前页的状态。

每页的状态可能为下面3个状态中的一个: ERASED: 该页为空L TK(Le iT ek )● RECEIVE_DATA: 该页正在从另外一个已满的页接收数据● VALID_PAGE: 该页包含有效数据,该页的状态一直保持不变,直到所有有效数据完全传输到另外一个 ERASED 的页。

第0页和第1页的状态转换如下图所示:每个存储在flash 内变量都定义了一个虚拟地址和一个数值,该数值以后可以读取和更新,当该数值改变后,该数值连同其对应的虚拟地址一起存储到一个新的flash 存储地址。

当需要读取该数值时,返回的是最近修改的数值。

在本实例中,虚拟地址和该数值都是16位。

其格式如下:下图描述了内部flash 模拟EEPROM 存储三个变量的流程,其中三个变量名及其对应的值分别为: var1(0x5555),var2(0x6666),var3(0x7777)。

L TK (Le iT e k )Flash 掉电数据恢复15.1.3当正在更新flash 数据时,这时候掉电,有可能会损坏flash 数据。

为了检测到这种数据损坏,并且恢复数据,在开机的时候立马执行ltk_ee_init ,其原理是,该函数使用存储数据页的状态,来判断该页数据是否已经损坏,如果数据损坏了,则修复数据。

页头的状态有9个可能的组合,其中的3个组合为有效组合,如下图所示:L TK (Le iT ek )内部flash 应用实例 ----- 模拟EEPROM15.2 实例描述15.2.1本实例使用STM32内部的flash 来模拟EEPROM 。

解锁flash 后,便可以操作内部flash ,一开始要做掉电恢复,通过函数ltk_ee_init 来实现,然后向内部flash 写入/读取三个变量,通过串口输出变量的值来检测flash 模拟EEPROM 读写是否成功。

实验效果15.2.2烧录该软件后,用USB 线连接到开发板上标有UART 的USB 口,在电脑的串口终端工具(如 secureCRT )内会输出该三个变量的值。

硬件设计15.2.3该实例使用内部flash 来模拟EEPROM ,无需外部电路。

软件设计15.2.4我们先从main 开始,该函数在应用层文件eeprom_emulation_main.c 内实现,主函数首先初始化串口。

要读写内部flash ,首先要解锁flash ,然后做掉电检测,通过调用函数ltk_ee_init 来检测flash 的内容是否有损坏。

最后调用函数ltk_ee_write_variable 来向内部flash 写入数据,再调用函数ltk_ee_read_variable 读取内部flash 内保存的变量的值,通过串口打印出来。

1 /**2 * 描述: 主函数,连续保存多个数据到 EEPROM ,然后读出,检查保存和读取出来的数据3 * 是否一致4 * 参数: 无5 * 返回: 无6 */7 int main(void )L TK (Le iT ek )9 uint16_t var_value = 0; 10 uint16_t read_value[3]; 11 uint8_t i; 1213 ltk_usart_init(); 1415 USART_Cmd(USART1, ENABLE); 16 /* 解锁 flash 编程擦除控制器 */ 17 FLASH_Unlock(); 1819 /* EEPROM 初始化 */ 20 ltk_ee_init(); 2122 /* 连续保存多个数据到 EEPROM */23 /* 保存 1000 个 Variable1 到 EEPROM */24 for (var_value = 0; var_value < 1000; var_value++)25 {26 ltk_ee_write_variable(VirtAddVarTab[0], var_value); 27 } 2829 /* 保存 500 个 Variable2 到 EEPROM */30 for (var_value = 0; var_value < 500; var_value++) 31 { 32 ltk_ee_write_variable(VirtAddVarTab[1], var_value);33 } 3435 /* 保存 800 个 Variable3 到 EEPROM */36 for (var_value = 0; var_value < 800; var_value++)37 { 38 ltk_ee_write_variable(VirtAddVarTab[2], var_value);39 } 4041 /* 读取保存的变量,在串口打印出来 */ 42 for (i = 0; i < 3; i++) 43 {44 ltk_ee_read_variable(VirtAddVarTab[i], &(read_value[i]));45 ltk_printf("%d: %d\n", i, read_value[i]); 46 } 4748 while (1) 49 { 50 }L TK(Le iT ek )内部flash 模拟EEPROM 的实现主要在文件ltk_eeprom_emulation.c 内。

在头文件ltk_eeprom_emulation.h 内,定义了一些有用的常量。

首先是要模拟成EEPROM 的内部flash 的页地址,女娲STM32开发板使用STM32F103C8T6,为中容量产品,flash 大小为64K bytes ,总共有64页(0 – 63),本实例中,我们使用第62页和第63页的flash 来模拟EEPROM 。

PAGE0使用内部flash 的62页,地址为:0x0800 0000 + 62 * 1024 = 0x0800 F800PAGE1使用内部flash 的63页,地址为:0x0800 0000 + 63 * 1024 = 0x0800 FC001 /* EEPROM start address in Flash */2 #define EEPROM_START_ADDRESS ((uint32_t)0x0800F800) /* EEPROM emulation start address:3 after 62KByte ofused Flash memory */ 45 /* Pages 0 and 1 base and end addresses */6 #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS+ 0x000))7 #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS+ (PAGE_SIZE - 1))) 89 #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + PAGE_SIZE))10 #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))我们还定义了页状态,有以下四种状态,状态PAGE_NOT_CORRUPTED 指示该页没有损坏。

官方例程每次上电都要擦除页,加入这个状态是避免不必要的页擦除,提高flash 的寿命。

当检测到页状态为PAGE_NOT_CORRUPTED ,表明该页没有被损坏,没有必要进行也擦除。

其它三种状态在上面都有详细的描述。

1 /* Page status definitions */2 #define ERASED ((uint16_t)0xFFFF) /* PAGE is empty */3 #define RECEIVE_DATA ((uint16_t)0xEEEE) /* PAGE is marked to receive data */4 #define VALID_PAGE ((uint16_t)0x0000) /* PAGE containing valid data */5 #define PAGE_NOT_CORRUPTED ((uint16_t)0xAAAA) /* PAGE is NOT corrupted */L TK(Le iT ek )掉电flash 损坏由函数ltk_ee_init 实现,一上电就需要调用该函数检测。

相关主题