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

STM32F0xx_EEPROM_Emulation BUG的修正

[复制链接]
wenyangzeng 发布时间:2018-10-27 19:18
本帖最后由 wenyangzeng 于 2018-10-28 11:33 编辑 $ @$ z5 X) l) g2 K

, d6 b; c' m' c4 _6 a, q               STM32F0xx_EEPROM_Emulation BUG的修正" W% S4 k- i1 x7 ~9 s5 R6 ~
0 O# ~4 A: q7 `9 K: u
     应用中需要使用STM32F051C6T6的FLASH仿真EEPROM,以便在断电时保存部分数据。在ST官网下载固件库STM32F0xx_EEPROM_Emulation。http://www.stmcu.com.cn/Designr ... F&lang=EN&ver=1.0.0   
: ^& I1 d/ W, w% t- ], d  p1 x: t# r' }$ ]. c" \/ f. j
       首先在演示代码中编译下载原代码进行评估、验证。" u/ W/ a* R3 U" X$ {
      演示代码主函数中先对VarDataTab[0]-VarDataTab[2]写入,然后再读出:
# f. W7 w  ^3 v' C- [$ q
  1. for (VarValue = 1; VarValue <= 0x64; VarValue++)
    . `) s+ c1 a) N5 _, B
  2.   {
    6 h/ s2 j/ i7 O# |1 Q+ F; A
  3.     EE_WriteVariable(VirtAddVarTab[0], VarValue);6 }# F/ a+ X; k& P; m7 P; y
  4.   }
    1 N8 W% |% q% M1 ]" ^) G
  5. 再读出。
    4 }6 w! e" k9 _# W. D

  6. 6 @* Y5 u' @8 V7 A9 \& [5 N1 k/ u  l
  7.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
    , W; b4 K3 ~1 A6 J+ L

  8. - N! z# S8 w3 X0 X7 u1 h
  9. & ]( j# e7 Y1 K2 \
  10.   for (VarValue = 1; VarValue <= 0xC8; VarValue++)" u* s: l/ e# [# H
  11.   {; |$ o5 s1 E* f
  12.     EE_WriteVariable(VirtAddVarTab[1], VarValue);, J/ W+ y" R1 s9 w( l. A/ j0 C
  13.   }% j/ ~; C0 U$ C6 a
  14.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
    3 l' r* u1 S1 q7 a( K, q
  15.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
    % L, _( X" w$ P. _9 H# h! m
  16.   for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
    7 T0 I5 x5 o+ p* F/ m
  17.   {
    ) ~' q% c: ?6 U- T& }5 d
  18.     EE_WriteVariable(VirtAddVarTab[2], VarValue);
    0 ]$ Z; q8 v! {; P/ `6 I
  19.   }2 k5 t  B3 J0 a/ s
  20.   /* read the last stored variables data*/
    9 J: f: E/ D$ q$ m4 N+ c& l/ g
  21.   EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);9 I: V, B6 Z0 M4 [3 N  i
  22.   EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);/ {. o- R/ Z: C1 k
  23.   EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
复制代码
     编译下载后运行,检查VarDataTab[0]-VarDataTab[2]的内容,与写入数据一致。本以为一切正常,就移植到实际项目中。
  u  O$ j# T: Z( `( Z5 K6 M0 w. t     STM32F051C6T6的Flash长度为32K,仿真EEPROM需要使用2页,占用第8扇区和第9扇区,首址是0x08002000,每页长为0x400,(0X08002000到0x080027ff)。不料移植运行后,发现断电后重启,读出的数据均为空数据。
0 m. o; d2 O4 B5 `, K  C      用STM32 ST-LINK Utility工具读0x08002000,发现数据已经正确写入了。
" P7 v' h: \( A. m7 O& x/ B% K7 @) m  `6 F+ }* I. {
无标题.png
! N8 w) H/ p! L( n" r7 d1 }( E, D" K* {* W2 F& y: O7 _
    判断问题出在读数据操作。
2 A* n3 \& g7 D) g8 l) p1 b/ ]3 t* c
5 S* d% Y+ Z2 W5 }* e  查阅STM32F0xx_EEPROM_Emulation演示代码eeprom.h的描述:
' x% r' N2 p1 `4 X" m6 c4 [
  1. /* Exported constants --------------------------------------------------------*/, u9 j3 X4 ^7 Z8 ?: A
  2. /* Define the size of the sectors to be used */0 `- t" e" N8 ?/ b4 d
  3. #define PAGE_SIZE             ((uint32_t)0x0400)  /* Page size = 1KByte */& L8 [" i' Y8 q, H0 z
  4. : o/ t9 m) ]+ k# L
  5. /* EEPROM start address in Flash */3 g4 U1 X6 n7 x9 @( t
  6. #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:
    5 x$ ~) _3 p0 C2 i) ]
  7.                                                         from sector2, after 8KByte of used
    . d0 k9 e) c% q! l% k
  8.                                                         Flash memory */
    & Y. n5 X) ~$ k( |0 p

  9. ! B1 a; W: T  S/ d# @6 _$ ?. u
  10. /* Pages 0 and 1 base and end addresses */
    2 `; a" l) d& {- X3 \0 y
  11. #define PAGE0_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
    ( d. p% M8 G5 P1 m1 g; j! C
  12. #define PAGE0_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))$ H! }1 D2 B' B" O7 g; k
  13. 9 T* a" M. r! m* h/ t( U. r- h' ?5 B* r
  14. #define PAGE1_BASE_ADDRESS    ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
    ! g9 X4 R4 p* ^3 l6 Q* c) i
  15. #define PAGE1_END_ADDRESS     ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))0 _$ B7 s2 |2 }: R
  16. ( q" U$ ?& Z+ @5 H, E5 O. |$ ]
  17. /* Used Flash pages for EEPROM emulation */; Y# V& ^6 w7 Q  v( M7 Z: t4 }7 C
  18. #define PAGE0                 ((uint16_t)0x0000)* s" p% {5 L. p! ]; H( ]6 l
  19. #define PAGE1                 ((uint16_t)0x0001)
    8 U7 B# s. A" N: h/ |
  20. 1 P  {/ X4 y- [: K. s5 s5 S3 ]
  21. /* No valid page define */
    % S0 W7 N6 R) C  N, `1 @
  22. #define NO_VALID_PAGE         ((uint16_t)0x00AB)
    . n& C. V! v( J0 @6 E% y% h# _
  23.   t3 T) ^' N) i
  24. /* Page status definitions */! o0 K% W3 z  @
  25. #define ERASED                ((uint16_t)0xFFFF)     /* Page is empty */
      ^; B% }) d' s; \8 o" C% F
  26. #define RECEIVE_DATA          ((uint16_t)0xEEEE)     /* Page is marked to receive data */
    9 e, K8 G( i3 A" m/ p7 C( s
  27. #define VALID_PAGE            ((uint16_t)0x0000)     /* Page containing valid data */
复制代码
     看代码第6行,这里设定的地址是: EEPROM_START_ADDRESS  ((uint32_t)0x08002000)。
2 U" @9 Z0 \$ z7 I
; s* s' F: q0 ^4 ^: ~' ]STM32F0xx_EEPROM_Emulation演示代码中eeprom.c中关于读的函数:
; V- l% m, R9 s( }! F
* O  ?0 D, V+ u/ D& n# I, D
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
    ! {$ ~( \2 x% T9 i
  2. {) @$ W) b9 G: g3 m7 ?9 X1 N
  3.   uint16_t ValidPage = PAGE0;
    ! ^9 b/ a: X$ b9 v( i) C
  4.   uint16_t AddressValue = 0x7777, ReadStatus = 1;, g9 b! ~% p/ J& T: h
  5.   uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;
    ( X9 O+ n: h' D! I6 x. K
  6. .
    8 X; Y' w1 `! C
  7. .. ^4 M  }8 S" V, n
  8. }
复制代码

% P. \9 H# ]8 _      这里的地址是:Address = 0x08001000PageStartAddress = 0x08001000;
5 T- |' M. _2 c" G      问题应该就出在这里。这个eeprom仿真代码是从STM32F1xx移植过来的。
+ ]* D9 K0 i! p
: v2 ]0 i5 n$ T& d& Y! o在STM32F1xx的eeprom.h中地址是这样的:; s( I! f7 e% e* p
  1. /* EEPROM start address in Flash */7 K6 \4 e  A3 ]1 b6 ]4 R
  2. #define EEPROM_START_ADDRESS    ((uint32_t)0x08010000) /* EEPROM emulation start address:
    7 q; d6 L8 J: x7 ?
  3.                                                   after 64KByte of used Flash memory */
复制代码

4 v+ X9 J( h0 o3 z在STM32F10xx的eeprom.c中读函数是这样的:2 \, P3 x0 w$ G- J
  1. uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data): ^% @0 F% M5 X/ h8 k+ ~
  2. {
    ' e' `9 y) j$ {4 B; [. m
  3.   uint16_t ValidPage = PAGE0;
    ) _! D% n2 H9 {) `
  4.   uint16_t AddressValue = 0x5555, ReadStatus = 1;6 r* t9 q) n6 l, d+ n5 j
  5.   uint32_t Address =0x08010000, PageStartAddress =0x08010000;8 K( D4 w- V4 b# r' n
  6. .
    - g* V6 ~) e, F
  7. .
    ' O2 g! E1 J/ ?! P, w
  8. }
复制代码
       ST工程师在移植F1到F0时忘记将eeprom.c和eeprom.h的读写地址统一,在STM32F0xx_EEPROM_Emulation写入首址是0x08002000,读出首址是0x08001000:读非所写, O& h% j1 B0 ~6 B/ E4 i1 R
, x5 x8 J& J6 H  z6 o3 h+ T, s
       而执行帖子开头的演示代码为什么没有发现读出错呢?由于在演示代码中写完flash操作后并未清空数组变量,DEBUG进入跟踪可知:由于读地址错误,并未执行读操作而直接退出。所以执行
7 B. {" v1 N9 i& TEE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
0 ]& B" j  g7 j/ B这句时,实际上根本就没有读扇区、没有更新数组变量内容,数组变量里保留的是上次写操作留下的残余,所以运行的结果看上去是正确的,实际上读出错了。& q. p! A) q# K

: c( U, E6 E7 T( \- Y
  w4 B/ }$ {% y  y1 v      修改F0的eeprom.c函数中错误之处,: x- T* S+ N) ~* i  C
  1. uint32_t Address = 0x08002000, PageStartAddress = 0x08002000;
复制代码
     问题解决。这个固件库是2012年的古董,6年了,看来我是社区第一个成功使用STM32F0xx_EEPROM_Emulation的了!7 i. e5 @$ Q) k' n+ i: m
      希望本贴对使用STM32F0xx_EEPROM_Emulation失败的网友有帮助,希望ST官方能更正错误的源码。: n& M0 _0 ?( D* E7 _+ u
4 U2 f- G  J8 t" @
9 F+ c7 }& h4 j

1 v6 @( F) J- I* m
+ J6 o4 s. W2 c/ X) a5 M9 z) ~3 H5 C. o9 W
8 e: R" V5 o. a, [3 [

2 x1 _9 ?+ g6 }  }- p  I
0 e" ?7 c9 x6 g( B
2 H4 ^, U, c6 _! c2 F
- u$ ?$ d5 X8 R/ X* A) E

评分

参与人数 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
7 k" D% k" z; R" y' |; @不错,分析的很仔细

& R3 R( y9 P. n$ T谢谢支持!
MrJiu 回答时间:2018-10-29 09:56:48
不错!!!
wenyangzeng 回答时间:2018-10-29 10:18:42
MrJiu 发表于 2018-10-29 09:56# V; a5 L4 N& M
不错!!!
* r" \. ]( V/ _8 k: x
谢谢版主!
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版