本帖最后由 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 |- for (VarValue = 1; VarValue <= 0x64; VarValue++)
/ V6 e5 r& W6 f/ p& y - {& u0 |" Z& c4 v. k3 v" p
- EE_WriteVariable(VirtAddVarTab[0], VarValue);
. S8 n4 y8 y* d5 v5 ? - }
$ T0 ~/ T2 m9 }/ b - 再读出。# \6 g9 ~( h+ b% u
- , F) p" j, G/ Q) \! R: Z: F' w5 ~) Z
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
% J2 c" R) W% b
4 Q9 Z' ~* T0 E( k6 F1 D1 J
0 q6 t# c* Z! P- for (VarValue = 1; VarValue <= 0xC8; VarValue++)5 o: C2 F6 P0 N: k+ [* e
- {
# v2 \0 Y! j6 B8 D - EE_WriteVariable(VirtAddVarTab[1], VarValue);
1 K4 N& {: K W1 A3 t5 Y$ ^ - }
) f! l& ?5 ^2 w* I - EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
; q/ }: x" Z: a# T$ _% P - EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);1 C6 i. k3 g- H
- for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
0 b+ {0 {" ], B, j3 Z - {/ h1 Q6 [# k- g% ? s
- EE_WriteVariable(VirtAddVarTab[2], VarValue);' z# `" l" c1 @* L
- }
3 I: i! `* p5 o, v0 ^7 b' F - /* read the last stored variables data*/: G; v, @; }; L( o8 Q" |- |$ F
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);6 E4 L8 _( F" E5 c0 ^2 J
- EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
* d+ F- X7 S# c+ ~7 a3 `7 A - 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
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 |
- /* Exported constants --------------------------------------------------------*/
, }, y9 L8 b" L; C0 f- K# e - /* Define the size of the sectors to be used */
8 p# q" \) q9 v) B% p - #define PAGE_SIZE ((uint32_t)0x0400) /* Page size = 1KByte */
! p9 O. u( ^& i/ W; G* A& W - 8 R9 Y$ G& g9 a7 a6 ~# k! [% ?% e' S3 [
- /* EEPROM start address in Flash */
4 f) J# R/ T' z, q4 l3 G - #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:/ r6 \) N; e7 u3 ~1 p
- from sector2, after 8KByte of used
. S4 ?; u0 Y( A# j/ K - Flash memory */
2 M% h" k, B( x3 E3 J3 T7 P
3 [9 v/ z: y1 e+ x( h, |- /* Pages 0 and 1 base and end addresses */
6 V# V* R7 C, {# W - #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))5 O4 T! F' H$ _. N" T
- #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))
2 C9 |8 e( X, e) L# s. `: _
( H& M' T, y6 U- #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))( L- E% L/ I9 j: G; q1 T
- #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
# K- o6 N4 @$ S1 X7 p - ( z/ Q7 `5 N( t1 L
- /* Used Flash pages for EEPROM emulation */% a1 b. `) P! _' s
- #define PAGE0 ((uint16_t)0x0000)
3 W) ^0 t2 f7 L; x* l6 [ - #define PAGE1 ((uint16_t)0x0001)7 J! d6 M) V; @
! E% I" d- X: Z# `2 n( a- /* No valid page define */
, W, M% J/ W0 ~1 x5 Z - #define NO_VALID_PAGE ((uint16_t)0x00AB)
& H0 q/ @+ ?1 L5 F
: G5 R! b7 ^% M& q' F- f5 k5 E- /* Page status definitions */
5 F0 P3 J, Q6 Q' H+ v - #define ERASED ((uint16_t)0xFFFF) /* Page is empty */1 t( W1 q$ f3 b6 l$ v- L
- #define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
5 Q# [0 E% K" Z- U - #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
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
$ `1 a# R, h( q/ d/ O7 x1 N - {
* j A9 A/ O. Y# ^$ Q/ q - uint16_t ValidPage = PAGE0;8 G+ G) ]! y9 N, W6 D4 ], |6 d
- uint16_t AddressValue = 0x7777, ReadStatus = 1;9 ]6 ?. j- h& I" Y
- uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;. A; Z0 j+ n: j( f3 A5 R
- .
+ { o5 T4 W( u! A& K' [ - .
5 y$ u1 O0 x3 g' U7 b+ f - }
复制代码 ' 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
- /* EEPROM start address in Flash */, O8 R0 @2 U: v0 J9 d
- #define EEPROM_START_ADDRESS ((uint32_t)0x08010000) /* EEPROM emulation start address:
" s! c' n+ Q2 c/ j4 J; a+ \$ j - after 64KByte of used Flash memory */
复制代码 9 y E- L% e2 r% b7 x. K
在STM32F10xx的eeprom.c中读函数是这样的:& Y0 H7 e* l% ~6 c
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data). P2 X1 p t3 [4 o
- {
1 H: H5 m ^3 b' x - uint16_t ValidPage = PAGE0;
( H: _$ w2 D! o; x. F - uint16_t AddressValue = 0x5555, ReadStatus = 1;9 v# b }% h" H6 `0 H
- uint32_t Address =0x08010000, PageStartAddress =0x08010000;
+ Q& @, |' |' {+ M - .+ ~# L8 j# Z: q1 |+ V
- .
! ^2 k6 n0 \9 Y" O9 J: K - }
复制代码 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- 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 ] |
谢谢支持!
谢谢版主!