本帖最后由 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- for (VarValue = 1; VarValue <= 0x64; VarValue++)
. `) s+ c1 a) N5 _, B - {
6 h/ s2 j/ i7 O# |1 Q+ F; A - EE_WriteVariable(VirtAddVarTab[0], VarValue);6 }# F/ a+ X; k& P; m7 P; y
- }
1 N8 W% |% q% M1 ]" ^) G - 再读出。
4 }6 w! e" k9 _# W. D
6 @* Y5 u' @8 V7 A9 \& [5 N1 k/ u l- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
, W; b4 K3 ~1 A6 J+ L
- N! z# S8 w3 X0 X7 u1 h- & ]( j# e7 Y1 K2 \
- for (VarValue = 1; VarValue <= 0xC8; VarValue++)" u* s: l/ e# [# H
- {; |$ o5 s1 E* f
- EE_WriteVariable(VirtAddVarTab[1], VarValue);, J/ W+ y" R1 s9 w( l. A/ j0 C
- }% j/ ~; C0 U$ C6 a
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
3 l' r* u1 S1 q7 a( K, q - EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
% L, _( X" w$ P. _9 H# h! m - for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
7 T0 I5 x5 o+ p* F/ m - {
) ~' q% c: ?6 U- T& }5 d - EE_WriteVariable(VirtAddVarTab[2], VarValue);
0 ]$ Z; q8 v! {; P/ `6 I - }2 k5 t B3 J0 a/ s
- /* read the last stored variables data*/
9 J: f: E/ D$ q$ m4 N+ c& l/ g - EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);9 I: V, B6 Z0 M4 [3 N i
- EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);/ {. o- R/ Z: C1 k
- 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. {
! 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 [- /* Exported constants --------------------------------------------------------*/, u9 j3 X4 ^7 Z8 ?: A
- /* Define the size of the sectors to be used */0 `- t" e" N8 ?/ b4 d
- #define PAGE_SIZE ((uint32_t)0x0400) /* Page size = 1KByte */& L8 [" i' Y8 q, H0 z
- : o/ t9 m) ]+ k# L
- /* EEPROM start address in Flash */3 g4 U1 X6 n7 x9 @( t
- #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:
5 x$ ~) _3 p0 C2 i) ] - from sector2, after 8KByte of used
. d0 k9 e) c% q! l% k - Flash memory */
& Y. n5 X) ~$ k( |0 p
! B1 a; W: T S/ d# @6 _$ ?. u- /* Pages 0 and 1 base and end addresses */
2 `; a" l) d& {- X3 \0 y - #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
( d. p% M8 G5 P1 m1 g; j! C - #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))$ H! }1 D2 B' B" O7 g; k
- 9 T* a" M. r! m* h/ t( U. r- h' ?5 B* r
- #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
! g9 X4 R4 p* ^3 l6 Q* c) i - #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))0 _$ B7 s2 |2 }: R
- ( q" U$ ?& Z+ @5 H, E5 O. |$ ]
- /* Used Flash pages for EEPROM emulation */; Y# V& ^6 w7 Q v( M7 Z: t4 }7 C
- #define PAGE0 ((uint16_t)0x0000)* s" p% {5 L. p! ]; H( ]6 l
- #define PAGE1 ((uint16_t)0x0001)
8 U7 B# s. A" N: h/ | - 1 P {/ X4 y- [: K. s5 s5 S3 ]
- /* No valid page define */
% S0 W7 N6 R) C N, `1 @ - #define NO_VALID_PAGE ((uint16_t)0x00AB)
. n& C. V! v( J0 @6 E% y% h# _ - t3 T) ^' N) i
- /* Page status definitions */! o0 K% W3 z @
- #define ERASED ((uint16_t)0xFFFF) /* Page is empty */
^; B% }) d' s; \8 o" C% F - #define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
9 e, K8 G( i3 A" m/ p7 C( s - #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- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
! {$ ~( \2 x% T9 i - {) @$ W) b9 G: g3 m7 ?9 X1 N
- uint16_t ValidPage = PAGE0;
! ^9 b/ a: X$ b9 v( i) C - uint16_t AddressValue = 0x7777, ReadStatus = 1;, g9 b! ~% p/ J& T: h
- uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;
( X9 O+ n: h' D! I6 x. K - .
8 X; Y' w1 `! C - .. ^4 M }8 S" V, n
- }
复制代码
% P. \9 H# ]8 _ 这里的地址是:Address = 0x08001000。PageStartAddress = 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
- /* EEPROM start address in Flash */7 K6 \4 e A3 ]1 b6 ]4 R
- #define EEPROM_START_ADDRESS ((uint32_t)0x08010000) /* EEPROM emulation start address:
7 q; d6 L8 J: x7 ? - after 64KByte of used Flash memory */
复制代码
4 v+ X9 J( h0 o3 z在STM32F10xx的eeprom.c中读函数是这样的:2 \, P3 x0 w$ G- J
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data): ^% @0 F% M5 X/ h8 k+ ~
- {
' e' `9 y) j$ {4 B; [. m - uint16_t ValidPage = PAGE0;
) _! D% n2 H9 {) ` - uint16_t AddressValue = 0x5555, ReadStatus = 1;6 r* t9 q) n6 l, d+ n5 j
- uint32_t Address =0x08010000, PageStartAddress =0x08010000;8 K( D4 w- V4 b# r' n
- .
- g* V6 ~) e, F - .
' O2 g! E1 J/ ?! P, w - }
复制代码 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
- 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 |
谢谢支持!
谢谢版主!