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

STM32F0xx_EEPROM_Emulation BUG的修正

[复制链接]
wenyangzeng 发布时间:2018-10-27 19:18
本帖最后由 wenyangzeng 于 2018-10-28 11:33 编辑 3 F2 W- x6 E, p

, b$ S& E% s1 r               STM32F0xx_EEPROM_Emulation BUG的修正
! n) `0 |  r, m) p3 U/ R+ @( x. a5 d. l- l6 f7 o
     应用中需要使用STM32F051C6T6的FLASH仿真EEPROM,以便在断电时保存部分数据。在ST官网下载固件库STM32F0xx_EEPROM_Emulation。http://www.stmcu.com.cn/Designr ... F&lang=EN&ver=1.0.0    ; k8 |. _3 N, \$ G3 \
$ x, B) y' {+ ]1 O& N  }/ C  ^
       首先在演示代码中编译下载原代码进行评估、验证。
) f6 \: X' T; M9 l6 A      演示代码主函数中先对VarDataTab[0]-VarDataTab[2]写入,然后再读出:
  D- O/ J( K& |% K6 D9 |
  1. for (VarValue = 1; VarValue <= 0x64; VarValue++)
    / V6 e5 r& W6 f/ p& y
  2.   {& u0 |" Z& c4 v. k3 v" p
  3.     EE_WriteVariable(VirtAddVarTab[0], VarValue);
    . S8 n4 y8 y* d5 v5 ?
  4.   }
    $ T0 ~/ T2 m9 }/ b
  5. 再读出。# \6 g9 ~( h+ b% u
  6. , F) p" j, G/ Q) \! R: Z: F' w5 ~) Z
  7.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
    % J2 c" R) W% b

  8. 4 Q9 Z' ~* T0 E( k6 F1 D1 J

  9. 0 q6 t# c* Z! P
  10.   for (VarValue = 1; VarValue <= 0xC8; VarValue++)5 o: C2 F6 P0 N: k+ [* e
  11.   {
    # v2 \0 Y! j6 B8 D
  12.     EE_WriteVariable(VirtAddVarTab[1], VarValue);
    1 K4 N& {: K  W1 A3 t5 Y$ ^
  13.   }
    ) f! l& ?5 ^2 w* I
  14.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
    ; q/ }: x" Z: a# T$ _% P
  15.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);1 C6 i. k3 g- H
  16.   for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
    0 b+ {0 {" ], B, j3 Z
  17.   {/ h1 Q6 [# k- g% ?  s
  18.     EE_WriteVariable(VirtAddVarTab[2], VarValue);' z# `" l" c1 @* L
  19.   }
    3 I: i! `* p5 o, v0 ^7 b' F
  20.   /* read the last stored variables data*/: G; v, @; }; L( o8 Q" |- |$ F
  21.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);6 E4 L8 _( F" E5 c0 ^2 J
  22.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
    * d+ F- X7 S# c+ ~7 a3 `7 A
  23.   EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
复制代码
     编译下载后运行,检查VarDataTab[0]-VarDataTab[2]的内容,与写入数据一致。本以为一切正常,就移植到实际项目中。
3 ?4 e/ N, Y1 q$ q     STM32F051C6T6的Flash长度为32K,仿真EEPROM需要使用2页,占用第8扇区和第9扇区,首址是0x08002000,每页长为0x400,(0X08002000到0x080027ff)。不料移植运行后,发现断电后重启,读出的数据均为空数据。
+ \/ g/ ]8 k7 V& v) W8 b9 M      用STM32 ST-LINK Utility工具读0x08002000,发现数据已经正确写入了。
' i# ]# W% q" e* w# p. G$ a- y$ y9 ]8 b$ B: q: ~1 r
无标题.png 8 ?  \4 j1 s: X
: ~. Z7 Y/ E3 A% p4 z) Q
    判断问题出在读数据操作。% ^" F+ w- a' e0 f% @3 h
) }& }8 g- Y- b1 S. u% j( w6 L
  查阅STM32F0xx_EEPROM_Emulation演示代码eeprom.h的描述:, m+ ~  C; P$ u% n  |
  1. /* Exported constants --------------------------------------------------------*/
    , }, y9 L8 b" L; C0 f- K# e
  2. /* Define the size of the sectors to be used */
    8 p# q" \) q9 v) B% p
  3. #define PAGE_SIZE             ((uint32_t)0x0400)  /* Page size = 1KByte */
    ! p9 O. u( ^& i/ W; G* A& W
  4. 8 R9 Y$ G& g9 a7 a6 ~# k! [% ?% e' S3 [
  5. /* EEPROM start address in Flash */
    4 f) J# R/ T' z, q4 l3 G
  6. #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:/ r6 \) N; e7 u3 ~1 p
  7.                                                         from sector2, after 8KByte of used
    . S4 ?; u0 Y( A# j/ K
  8.                                                         Flash memory */
    2 M% h" k, B( x3 E3 J3 T7 P

  9. 3 [9 v/ z: y1 e+ x( h, |
  10. /* Pages 0 and 1 base and end addresses */
    6 V# V* R7 C, {# W
  11. #define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))5 O4 T! F' H$ _. N" T
  12. #define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
    2 C9 |8 e( X, e) L# s. `: _

  13. ( H& M' T, y6 U
  14. #define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))( L- E% L/ I9 j: G; q1 T
  15. #define PAGE1_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
    # K- o6 N4 @$ S1 X7 p
  16. ( z/ Q7 `5 N( t1 L
  17. /* Used Flash pages for EEPROM emulation */% a1 b. `) P! _' s
  18. #define PAGE0                 ((uint16_t)0x0000)
    3 W) ^0 t2 f7 L; x* l6 [
  19. #define PAGE1                 ((uint16_t)0x0001)7 J! d6 M) V; @

  20. ! E% I" d- X: Z# `2 n( a
  21. /* No valid page define */
    , W, M% J/ W0 ~1 x5 Z
  22. #define NO_VALID_PAGE         ((uint16_t)0x00AB)
    & H0 q/ @+ ?1 L5 F

  23. : G5 R! b7 ^% M& q' F- f5 k5 E
  24. /* Page status definitions */
    5 F0 P3 J, Q6 Q' H+ v
  25. #define ERASED                ((uint16_t)0xFFFF)     /* Page is empty */1 t( W1 q$ f3 b6 l$ v- L
  26. #define RECEIVE_DATA          ((uint16_t)0xEEEE)     /* Page is marked to receive data */
    5 Q# [0 E% K" Z- U
  27. #define VALID_PAGE            ((uint16_t)0x0000)     /* Page containing valid data */
复制代码
     看代码第6行,这里设定的地址是: EEPROM_START_ADDRESS  ((uint32_t)0x08002000)。
$ p: V4 s1 K; o; l& B4 I/ }% c2 o. v1 x+ B1 z
而STM32F0xx_EEPROM_Emulation演示代码中eeprom.c中关于读的函数:
+ w6 S% g) i0 i1 q7 @& o4 }9 K# O+ G6 @. K# D
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
    $ `1 a# R, h( q/ d/ O7 x1 N
  2. {
    * j  A9 A/ O. Y# ^$ Q/ q
  3.   uint16_t ValidPage = PAGE0;8 G+ G) ]! y9 N, W6 D4 ], |6 d
  4.   uint16_t AddressValue = 0x7777, ReadStatus = 1;9 ]6 ?. j- h& I" Y
  5.   uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;. A; Z0 j+ n: j( f3 A5 R
  6. .
    + {  o5 T4 W( u! A& K' [
  7. .
    5 y$ u1 O0 x3 g' U7 b+ f
  8. }
复制代码
' n5 t" }6 k! ^
      这里的地址是:Address = 0x08001000。PageStartAddress = 0x08001000;
( q- z( P5 e4 T      问题应该就出在这里。这个eeprom仿真代码是从STM32F1xx移植过来的。& D2 b' ~3 f& I6 `* |4 V
, k) |: l& ?' Z
在STM32F1xx的eeprom.h中地址是这样的:7 v7 A& ]! k9 Z* y/ v( L
  1. /* EEPROM start address in Flash */, O8 R0 @2 U: v0 J9 d
  2. #define EEPROM_START_ADDRESS    ((uint32_t)0x08010000) /* EEPROM emulation start address:
    " s! c' n+ Q2 c/ j4 J; a+ \$ j
  3.                                                   after 64KByte of used Flash memory */
复制代码
9 y  E- L% e2 r% b7 x. K
在STM32F10xx的eeprom.c中读函数是这样的:& Y0 H7 e* l% ~6 c
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data). P2 X1 p  t3 [4 o
  2. {
    1 H: H5 m  ^3 b' x
  3.   uint16_t ValidPage = PAGE0;
    ( H: _$ w2 D! o; x. F
  4.   uint16_t AddressValue = 0x5555, ReadStatus = 1;9 v# b  }% h" H6 `0 H
  5.   uint32_t Address =0x08010000, PageStartAddress =0x08010000;
    + Q& @, |' |' {+ M
  6. .+ ~# L8 j# Z: q1 |+ V
  7. .
    ! ^2 k6 n0 \9 Y" O9 J: K
  8. }
复制代码
       ST工程师在移植F1到F0时忘记将eeprom.c和eeprom.h的读写地址统一,在STM32F0xx_EEPROM_Emulation写入首址是0x08002000,读出首址是0x08001000:读非所写。
: v! f$ ^% U6 i: e) n  h, {. u' K8 a2 ?( M/ _
       而执行帖子开头的演示代码为什么没有发现读出错呢?由于在演示代码中写完flash操作后并未清空数组变量,DEBUG进入跟踪可知:由于读地址错误,并未执行读操作而直接退出。所以执行/ E6 L! e7 [( {, \& E& x3 C
EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);6 m1 W0 e1 k) t  s% r
这句时,实际上根本就没有读扇区、没有更新数组变量内容,数组变量里保留的是上次写操作留下的残余,所以运行的结果看上去是正确的,实际上读出错了。5 k6 p& a5 \. e, R6 i! y- T; K1 E

4 K6 E* A  h9 j7 }$ t- d1 r) x* ?4 w  I8 [7 `( M
      修改F0的eeprom.c函数中错误之处,
/ M1 l! \; d7 x$ n4 y' }5 A7 Q
  1. uint32_t Address = 0x08002000, PageStartAddress = 0x08002000;
复制代码
     问题解决。这个固件库是2012年的古董,6年了,看来我是社区第一个成功使用STM32F0xx_EEPROM_Emulation的了!2 Z5 D9 V9 g* q; S- t: {$ Y) |
      希望本贴对使用STM32F0xx_EEPROM_Emulation失败的网友有帮助,希望ST官方能更正错误的源码。9 x+ K/ C9 H. j4 G: P

- W7 Y2 L0 T0 v) V+ Q7 H& B' f- w0 V) z4 _, m% E

$ }/ B6 r1 U: f& G3 U) |/ |8 s( c: ^2 R
* Y' L7 k: Z- [9 W6 P  p2 R5 o7 |  U
: G  {# E" k3 j7 U# y- Q5 s' C
0 w6 e; Q/ ]) F* u" B
9 n4 J3 g7 L& q" T+ v$ ~. }9 @& r

) B* n+ s/ \% M/ K; L
& n& q; [" U2 A0 ]

评分

参与人数 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
9 I9 w- `/ {% R不错,分析的很仔细
4 ]* p0 P1 ]/ w8 b
谢谢支持!
MrJiu 回答时间:2018-10-29 09:56:48
不错!!!
wenyangzeng 回答时间:2018-10-29 10:18:42
MrJiu 发表于 2018-10-29 09:56
7 T; R! ~4 |. O! X8 G9 X不错!!!
! L2 y) n1 J* O4 S4 E8 l, l
谢谢版主!

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版