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

STM32F0xx_EEPROM_Emulation BUG的修正

[复制链接]
wenyangzeng 发布时间:2018-10-27 19:18
本帖最后由 wenyangzeng 于 2018-10-28 11:33 编辑
/ ^2 h( Z+ N0 Y% `
- T+ J; O& [( _  q" {               STM32F0xx_EEPROM_Emulation BUG的修正) \! X' B6 E! q3 w7 {( `2 n
9 s) K& n6 e. g  a; Q2 y
     应用中需要使用STM32F051C6T6的FLASH仿真EEPROM,以便在断电时保存部分数据。在ST官网下载固件库STM32F0xx_EEPROM_Emulation。http://www.stmcu.com.cn/Designr ... F&lang=EN&ver=1.0.0   
2 C8 N- o4 a, P2 j8 o6 E2 R; }4 [5 [3 L' \: f
       首先在演示代码中编译下载原代码进行评估、验证。
4 s3 x* ]- x1 C      演示代码主函数中先对VarDataTab[0]-VarDataTab[2]写入,然后再读出:: ~5 w& j+ y: c$ ?  B, D" B( o4 T4 v
  1. for (VarValue = 1; VarValue <= 0x64; VarValue++)
    7 b5 R! w) ]8 |+ z
  2.   {
    . V" a3 [: t5 G+ R9 R
  3.     EE_WriteVariable(VirtAddVarTab[0], VarValue);# {& A# K: B+ x9 b+ A* X% N
  4.   }5 P- N: \" H' A. S3 [9 T& Z
  5. 再读出。
    * F% L% c* [4 l  s5 b

  6. . B* ~& Q3 ~; Y: {
  7.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);+ o1 G% u/ v6 n4 Z1 d* X

  8. " @0 _" L! ]% l2 O

  9. - r# l: |+ ?/ `+ ]
  10.   for (VarValue = 1; VarValue <= 0xC8; VarValue++)
    / K" [; H& Y7 V: C" s% b
  11.   {" d0 S) |2 d+ c" u6 Q
  12.     EE_WriteVariable(VirtAddVarTab[1], VarValue);$ _3 a2 x3 w, r) B
  13.   }
    7 Z% W  L' {; k- J& N& B" c4 W
  14.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
      l( B$ c# e2 k1 }3 d/ S
  15.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
    , c2 B9 T: n; n
  16.   for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
    ) c# e- f; r1 m" A
  17.   {. M1 T! Q" z* f- Z
  18.     EE_WriteVariable(VirtAddVarTab[2], VarValue);
    6 J  X% u! }, N, q- t7 ^
  19.   }4 M6 e& \. [: w4 C2 n) w$ G* O
  20.   /* read the last stored variables data*/- {9 a8 D- ^# n) S0 q- Y
  21.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);3 O6 a6 S# q) h0 K" R0 ~( V
  22.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
    9 B, h: `' y! ?; k+ P8 V
  23.   EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
复制代码
     编译下载后运行,检查VarDataTab[0]-VarDataTab[2]的内容,与写入数据一致。本以为一切正常,就移植到实际项目中。3 I2 E6 h' h( F* i# r5 L3 j5 V
     STM32F051C6T6的Flash长度为32K,仿真EEPROM需要使用2页,占用第8扇区和第9扇区,首址是0x08002000,每页长为0x400,(0X08002000到0x080027ff)。不料移植运行后,发现断电后重启,读出的数据均为空数据。
9 P$ M, U, D* `3 X+ c  _      用STM32 ST-LINK Utility工具读0x08002000,发现数据已经正确写入了。- f, W8 v, B' o7 ~! |

3 G7 B; b/ g* f$ y% A 无标题.png
" m" a* f1 P' r: A9 I" D: t4 k+ p( b
    判断问题出在读数据操作。
! f2 L% e" u( c2 m
0 b3 c' E; Z$ X2 W% k/ K% p  查阅STM32F0xx_EEPROM_Emulation演示代码eeprom.h的描述:
" V* j2 T- r: R
  1. /* Exported constants --------------------------------------------------------*/
    3 ^8 P! _) b) f" F) t$ y/ _
  2. /* Define the size of the sectors to be used */
    - [5 }: O; C2 ~9 D' A9 R4 F
  3. #define PAGE_SIZE             ((uint32_t)0x0400)  /* Page size = 1KByte */) y- n% ?8 \6 \+ Q' g

  4. * I7 G( y, B" d% e) k$ ^
  5. /* EEPROM start address in Flash */
    ( J3 G0 m' K/ l) e; T" ~
  6. #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:) _1 h9 m% p) X/ u/ _
  7.                                                         from sector2, after 8KByte of used
    . E+ t$ W0 H! F; H1 U4 Y) ]8 B1 h) H1 b
  8.                                                         Flash memory */$ z9 G! m& m8 l1 U+ f" `

  9. # Y+ q3 D7 t; y: j) N
  10. /* Pages 0 and 1 base and end addresses *// T2 p- R5 V8 C8 F( r- T
  11. #define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
    ( k8 O1 A" w: J
  12. #define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1))), m: @( h$ V1 F

  13. : Q0 F5 |. T# F* ?
  14. #define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
    % _- z+ D; I8 m
  15. #define PAGE1_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
    ) q) e  F4 w  k( O5 p2 j' }

  16. / V. r5 m! v# g- [; V
  17. /* Used Flash pages for EEPROM emulation */  R' K% k, B' y
  18. #define PAGE0                 ((uint16_t)0x0000)
    0 W2 h7 q: r+ w" [$ k; x  `, X
  19. #define PAGE1                 ((uint16_t)0x0001)
    5 b& I% Z1 x. u; O6 i- G
  20. 6 v% Y8 b1 g5 }& A3 |( }
  21. /* No valid page define */
    , j# d1 I9 O4 [8 K
  22. #define NO_VALID_PAGE         ((uint16_t)0x00AB)
    3 I) \0 i0 [$ X- J
  23. % u* j$ Y9 i5 `/ D7 c4 I
  24. /* Page status definitions */
    9 o* ~5 t; n* g% X' M
  25. #define ERASED                ((uint16_t)0xFFFF)     /* Page is empty */# I" l. I( M; `* J% V- }9 Q
  26. #define RECEIVE_DATA          ((uint16_t)0xEEEE)     /* Page is marked to receive data */# H& t  R& W( Y2 G
  27. #define VALID_PAGE            ((uint16_t)0x0000)     /* Page containing valid data */
复制代码
     看代码第6行,这里设定的地址是: EEPROM_START_ADDRESS  ((uint32_t)0x08002000)。
: B3 B! T. K+ }$ I2 i2 Z" ^! e, ^1 _4 N3 J
STM32F0xx_EEPROM_Emulation演示代码中eeprom.c中关于读的函数:
( ~' O; ?5 L6 ?3 M: v
$ s" |& h9 ?. O% `$ k# a7 R; k
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
    6 g. _, E( k' f0 T0 b
  2. {
    , c: S; m& |1 R
  3.   uint16_t ValidPage = PAGE0;
    / m$ E5 A2 A( b" n
  4.   uint16_t AddressValue = 0x7777, ReadStatus = 1;' ]( q% y/ g; F- g' y' n
  5.   uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;1 L* S4 @" L! ?% z
  6. .2 ]0 H- Q7 b' s0 U* R0 i
  7. .
    ! X! {2 N9 X4 F6 h
  8. }
复制代码

% r! y; o7 c, K. b! g! V5 v      这里的地址是:Address = 0x08001000PageStartAddress = 0x08001000;: g% ~, q) v9 J# \0 J! a4 W
      问题应该就出在这里。这个eeprom仿真代码是从STM32F1xx移植过来的。
' n& Z/ ?/ ?3 r4 E6 ?# t  ^, m. \, n
) g) ^, L6 O2 U3 Q5 g在STM32F1xx的eeprom.h中地址是这样的:& ?3 T+ w1 G1 w0 y- m
  1. /* EEPROM start address in Flash */
    & ^. v# A- L& d
  2. #define EEPROM_START_ADDRESS    ((uint32_t)0x08010000) /* EEPROM emulation start address:
    1 s' P3 E) P7 c% g5 ?
  3.                                                   after 64KByte of used Flash memory */
复制代码

1 `% N& W* _+ I' m) f) E在STM32F10xx的eeprom.c中读函数是这样的:9 D0 z+ m3 l5 s5 \
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
    / ~" n+ p/ }6 L8 V3 O* J( L# S
  2. {& n( u2 i% @- ]- r1 e3 o
  3.   uint16_t ValidPage = PAGE0;
    / Y" P  T8 y, Y2 T; M; e! H# I
  4.   uint16_t AddressValue = 0x5555, ReadStatus = 1;$ C! ]' ]9 a: A' V. v
  5.   uint32_t Address =0x08010000, PageStartAddress =0x08010000;+ @; Y5 K3 v0 M( z, r
  6. .: a! b( P/ r5 a1 r0 y% k
  7. .+ J( n& v. a7 b1 J$ ?6 X5 ]
  8. }
复制代码
       ST工程师在移植F1到F0时忘记将eeprom.c和eeprom.h的读写地址统一,在STM32F0xx_EEPROM_Emulation写入首址是0x08002000,读出首址是0x08001000:读非所写) Y0 q3 }! K! a+ D4 x

4 b% q4 S0 m0 w3 ]       而执行帖子开头的演示代码为什么没有发现读出错呢?由于在演示代码中写完flash操作后并未清空数组变量,DEBUG进入跟踪可知:由于读地址错误,并未执行读操作而直接退出。所以执行
" Q7 }3 R# ~5 gEE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
" Z, B6 i# Y9 v" l1 Q# r这句时,实际上根本就没有读扇区、没有更新数组变量内容,数组变量里保留的是上次写操作留下的残余,所以运行的结果看上去是正确的,实际上读出错了。
" ^2 g5 Q. r8 T3 z) s: Q& b* S- e9 e0 x
6 Z) q, K1 a0 |4 e
6 B) U3 a2 m5 o      修改F0的eeprom.c函数中错误之处,- S- I1 v2 M" \" ]
  1. uint32_t Address = 0x08002000, PageStartAddress = 0x08002000;
复制代码
     问题解决。这个固件库是2012年的古董,6年了,看来我是社区第一个成功使用STM32F0xx_EEPROM_Emulation的了!
, s" j5 b9 M9 P& V7 n: b  N      希望本贴对使用STM32F0xx_EEPROM_Emulation失败的网友有帮助,希望ST官方能更正错误的源码。
+ G$ T, d( J! U1 |& M7 y/ U0 a* J7 D" n' p7 P
1 O5 o9 t$ S9 a. P; [' N
" k4 R- _* h2 f+ d
( @9 O) ^0 G( }9 }/ I, O

* @4 x6 r/ B. f1 h" K2 z; c
3 K# I3 C3 L# Z- z, T) x1 F# R* n( }3 `' R$ G0 d
' l1 V: K6 {; V# ]  a
! U8 S, {+ s4 J9 H# W
! ^! ~8 N  g( y0 q! j, a+ q

评分

参与人数 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
& i% `# P( c; w3 X! Q+ k不错,分析的很仔细

% Z5 `& P, }6 B5 |$ @. e* D! T谢谢支持!
MrJiu 回答时间:2018-10-29 09:56:48
不错!!!
wenyangzeng 回答时间:2018-10-29 10:18:42
MrJiu 发表于 2018-10-29 09:56
( w& G3 _7 C' N6 C  J  [不错!!!

9 X: s  G' c* {$ r- N' J* {6 d谢谢版主!
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版