本帖最后由 wenyangzeng 于 2018-10-28 11:33 编辑
STM32F0xx_EEPROM_Emulation BUG的修正
应用中需要使用STM32F051C6T6的FLASH仿真EEPROM,以便在断电时保存部分数据。在ST官网下载固件库STM32F0xx_EEPROM_Emulation。http://www.stmcu.com.cn/Designr ... F&lang=EN&ver=1.0.0
首先在演示代码中编译下载原代码进行评估、验证。
演示代码主函数中先对VarDataTab[0]-VarDataTab[2]写入,然后再读出:
- for (VarValue = 1; VarValue <= 0x64; VarValue++)
- {
- EE_WriteVariable(VirtAddVarTab[0], VarValue);
- }
- 再读出。
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
- for (VarValue = 1; VarValue <= 0xC8; VarValue++)
- {
- EE_WriteVariable(VirtAddVarTab[1], VarValue);
- }
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
- EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
- for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
- {
- EE_WriteVariable(VirtAddVarTab[2], VarValue);
- }
- /* read the last stored variables data*/
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
- EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
- EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
复制代码 编译下载后运行,检查VarDataTab[0]-VarDataTab[2]的内容,与写入数据一致。本以为一切正常,就移植到实际项目中。
STM32F051C6T6的Flash长度为32K,仿真EEPROM需要使用2页,占用第8扇区和第9扇区,首址是0x08002000,每页长为0x400,(0X08002000到0x080027ff)。不料移植运行后,发现断电后重启,读出的数据均为空数据。
用STM32 ST-LINK Utility工具读0x08002000,发现数据已经正确写入了。
判断问题出在读数据操作。
查阅STM32F0xx_EEPROM_Emulation演示代码eeprom.h的描述:
- /* Exported constants --------------------------------------------------------*/
- /* Define the size of the sectors to be used */
- #define PAGE_SIZE ((uint32_t)0x0400) /* Page size = 1KByte */
- /* EEPROM start address in Flash */
- #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:
- from sector2, after 8KByte of used
- Flash memory */
- /* Pages 0 and 1 base and end addresses */
- #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
- #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
- #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
- #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
- /* Used Flash pages for EEPROM emulation */
- #define PAGE0 ((uint16_t)0x0000)
- #define PAGE1 ((uint16_t)0x0001)
- /* No valid page define */
- #define NO_VALID_PAGE ((uint16_t)0x00AB)
- /* Page status definitions */
- #define ERASED ((uint16_t)0xFFFF) /* Page is empty */
- #define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
- #define VALID_PAGE ((uint16_t)0x0000) /* Page containing valid data */
复制代码 看代码第6行,这里设定的地址是: EEPROM_START_ADDRESS ((uint32_t)0x08002000)。
而STM32F0xx_EEPROM_Emulation演示代码中eeprom.c中关于读的函数:
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
- {
- uint16_t ValidPage = PAGE0;
- uint16_t AddressValue = 0x7777, ReadStatus = 1;
- uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;
- .
- .
- }
复制代码
这里的地址是:Address = 0x08001000。PageStartAddress = 0x08001000;
问题应该就出在这里。这个eeprom仿真代码是从STM32F1xx移植过来的。
在STM32F1xx的eeprom.h中地址是这样的:
- /* EEPROM start address in Flash */
- #define EEPROM_START_ADDRESS ((uint32_t)0x08010000) /* EEPROM emulation start address:
- after 64KByte of used Flash memory */
复制代码
在STM32F10xx的eeprom.c中读函数是这样的:
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
- {
- uint16_t ValidPage = PAGE0;
- uint16_t AddressValue = 0x5555, ReadStatus = 1;
- uint32_t Address =0x08010000, PageStartAddress =0x08010000;
- .
- .
- }
复制代码 ST工程师在移植F1到F0时忘记将eeprom.c和eeprom.h的读写地址统一,在STM32F0xx_EEPROM_Emulation写入首址是0x08002000,读出首址是0x08001000:读非所写。
而执行帖子开头的演示代码为什么没有发现读出错呢?由于在演示代码中写完flash操作后并未清空数组变量,DEBUG进入跟踪可知:由于读地址错误,并未执行读操作而直接退出。所以执行
EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
这句时,实际上根本就没有读扇区、没有更新数组变量内容,数组变量里保留的是上次写操作留下的残余,所以运行的结果看上去是正确的,实际上读出错了。
修改F0的eeprom.c函数中错误之处,
- uint32_t Address = 0x08002000, PageStartAddress = 0x08002000;
复制代码 问题解决。这个固件库是2012年的古董,6年了,看来我是社区第一个成功使用STM32F0xx_EEPROM_Emulation的了!
希望本贴对使用STM32F0xx_EEPROM_Emulation失败的网友有帮助,希望ST官方能更正错误的源码。
|
谢谢支持!
谢谢版主!