你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F0xx_EEPROM_Emulation BUG的修正

[复制链接]
wenyangzeng 发布时间:2018-10-27 19:18
本帖最后由 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]写入,然后再读出:
  1. for (VarValue = 1; VarValue <= 0x64; VarValue++)
  2.   {
  3.     EE_WriteVariable(VirtAddVarTab[0], VarValue);
  4.   }
  5. 再读出。

  6.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);


  7.   for (VarValue = 1; VarValue <= 0xC8; VarValue++)
  8.   {
  9.     EE_WriteVariable(VirtAddVarTab[1], VarValue);
  10.   }
  11.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
  12.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
  13.   for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
  14.   {
  15.     EE_WriteVariable(VirtAddVarTab[2], VarValue);
  16.   }
  17.   /* read the last stored variables data*/
  18.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
  19.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
  20.   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,发现数据已经正确写入了。

无标题.png

    判断问题出在读数据操作。

  查阅STM32F0xx_EEPROM_Emulation演示代码eeprom.h的描述:
  1. /* Exported constants --------------------------------------------------------*/
  2. /* Define the size of the sectors to be used */
  3. #define PAGE_SIZE             ((uint32_t)0x0400)  /* Page size = 1KByte */

  4. /* EEPROM start address in Flash */
  5. #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:
  6.                                                         from sector2, after 8KByte of used
  7.                                                         Flash memory */

  8. /* Pages 0 and 1 base and end addresses */
  9. #define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
  10. #define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))

  11. #define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
  12. #define PAGE1_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))

  13. /* Used Flash pages for EEPROM emulation */
  14. #define PAGE0                 ((uint16_t)0x0000)
  15. #define PAGE1                 ((uint16_t)0x0001)

  16. /* No valid page define */
  17. #define NO_VALID_PAGE         ((uint16_t)0x00AB)

  18. /* Page status definitions */
  19. #define ERASED                ((uint16_t)0xFFFF)     /* Page is empty */
  20. #define RECEIVE_DATA          ((uint16_t)0xEEEE)     /* Page is marked to receive data */
  21. #define VALID_PAGE            ((uint16_t)0x0000)     /* Page containing valid data */
复制代码
     看代码第6行,这里设定的地址是: EEPROM_START_ADDRESS  ((uint32_t)0x08002000)。

STM32F0xx_EEPROM_Emulation演示代码中eeprom.c中关于读的函数:

  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
  2. {
  3.   uint16_t ValidPage = PAGE0;
  4.   uint16_t AddressValue = 0x7777, ReadStatus = 1;
  5.   uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;
  6. .
  7. .
  8. }
复制代码

      这里的地址是:Address = 0x08001000PageStartAddress = 0x08001000;
      问题应该就出在这里。这个eeprom仿真代码是从STM32F1xx移植过来的。

在STM32F1xx的eeprom.h中地址是这样的:
  1. /* EEPROM start address in Flash */
  2. #define EEPROM_START_ADDRESS    ((uint32_t)0x08010000) /* EEPROM emulation start address:
  3.                                                   after 64KByte of used Flash memory */
复制代码

在STM32F10xx的eeprom.c中读函数是这样的:
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
  2. {
  3.   uint16_t ValidPage = PAGE0;
  4.   uint16_t AddressValue = 0x5555, ReadStatus = 1;
  5.   uint32_t Address =0x08010000, PageStartAddress =0x08010000;
  6. .
  7. .
  8. }
复制代码
       ST工程师在移植F1到F0时忘记将eeprom.c和eeprom.h的读写地址统一,在STM32F0xx_EEPROM_Emulation写入首址是0x08002000,读出首址是0x08001000:读非所写

       而执行帖子开头的演示代码为什么没有发现读出错呢?由于在演示代码中写完flash操作后并未清空数组变量,DEBUG进入跟踪可知:由于读地址错误,并未执行读操作而直接退出。所以执行
EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
这句时,实际上根本就没有读扇区、没有更新数组变量内容,数组变量里保留的是上次写操作留下的残余,所以运行的结果看上去是正确的,实际上读出错了。


      修改F0的eeprom.c函数中错误之处,
  1. uint32_t Address = 0x08002000, PageStartAddress = 0x08002000;
复制代码
     问题解决。这个固件库是2012年的古董,6年了,看来我是社区第一个成功使用STM32F0xx_EEPROM_Emulation的了!
      希望本贴对使用STM32F0xx_EEPROM_Emulation失败的网友有帮助,希望ST官方能更正错误的源码。










评分

参与人数 1 ST金币 +2 收起 理由
MrJiu + 2 很给力!

查看全部评分

收藏 1 评论4 发布时间:2018-10-27 19:18

举报

4个回答
STM1024 回答时间:2018-10-28 14:35:35
不错,分析的很仔细
wenyangzeng 回答时间:2018-10-28 19:23:25
stm1024 发表于 2018-10-28 14:35
不错,分析的很仔细

谢谢支持!
MrJiu 回答时间:2018-10-29 09:56:48
不错!!!
wenyangzeng 回答时间:2018-10-29 10:18:42

谢谢版主!

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版