本帖最后由 wenyangzeng 于 2018-10-28 11:33 编辑
0 _# W: }) \* _5 w- ?/ \
7 a( Y- A7 e- M- Z$ E- f/ q STM32F0xx_EEPROM_Emulation BUG的修正9 i' ~0 ?( K; l; }
|+ M3 f& d' L) T% i
应用中需要使用STM32F051C6T6的FLASH仿真EEPROM,以便在断电时保存部分数据。在ST官网下载固件库STM32F0xx_EEPROM_Emulation。http://www.stmcu.com.cn/Designr ... F&lang=EN&ver=1.0.0 7 z$ V0 o2 G3 s& X& O
5 L% q$ h: G) \/ W
首先在演示代码中编译下载原代码进行评估、验证。
) Q4 S8 o1 k+ i; x/ z 演示代码主函数中先对VarDataTab[0]-VarDataTab[2]写入,然后再读出:
/ q* ~( ~; J. A/ n1 Y# k- for (VarValue = 1; VarValue <= 0x64; VarValue++)
1 p2 h5 }, q7 ?+ P. D4 C - {
7 j {, n1 ?% \# } - EE_WriteVariable(VirtAddVarTab[0], VarValue);, c* d1 _7 ~' o3 T3 o# F- ]
- }
) H0 _3 p6 S) O - 再读出。( F$ K0 t0 i( J) j5 A
- . w$ P+ f& Y1 `" _: f
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
+ ]8 ` N5 B$ ~6 Q - 9 n$ z* L5 w6 G, E3 i: l, k
/ G/ ?: N- }" j) X1 ]' j9 j" e- for (VarValue = 1; VarValue <= 0xC8; VarValue++): ]0 h' e/ a) n+ @% f$ a1 \
- {% E. B% g1 n- z* q& k# v* J( u% i
- EE_WriteVariable(VirtAddVarTab[1], VarValue);. m- n; ~5 X! w! c% t- m$ r
- }2 p5 x5 q$ x0 c- @( j9 [
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
7 U- C2 ?% j* [& N - EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
. x l! {* k6 s: l - for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
1 I, k2 H# l3 y: R - {
9 v: B# p. o& _/ C/ z$ U - EE_WriteVariable(VirtAddVarTab[2], VarValue);6 ]3 m% B6 Y- B9 y4 q$ ]
- }* ^6 G0 {9 `& b0 ^ k4 l
- /* read the last stored variables data*/3 {2 {$ t: e( H) J
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);' N) j! n8 p' v
- EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
" d; g4 q4 z1 Z j! w - EE_ReadVariable(VirtAddVarTab[2], &VarDataTab[2]);
复制代码 编译下载后运行,检查VarDataTab[0]-VarDataTab[2]的内容,与写入数据一致。本以为一切正常,就移植到实际项目中。
2 C" k. u( }9 \# \ STM32F051C6T6的Flash长度为32K,仿真EEPROM需要使用2页,占用第8扇区和第9扇区,首址是0x08002000,每页长为0x400,(0X08002000到0x080027ff)。不料移植运行后,发现断电后重启,读出的数据均为空数据。- U; E3 U7 u$ b% ?5 t, ]' J+ P9 I' G
用STM32 ST-LINK Utility工具读0x08002000,发现数据已经正确写入了。 ~) ?9 O* M6 c! s7 a% o
k) s5 i" q5 ~# c! ^' J
- x6 k' C8 C3 @ S4 B: C
: N: M0 U) Y: ]0 h 判断问题出在读数据操作。" Q! m' P* @5 u) z
' E/ {( n! w2 e2 y' N+ i( ` 查阅STM32F0xx_EEPROM_Emulation演示代码eeprom.h的描述:
: O( N9 @1 ^1 U, f- /* Exported constants --------------------------------------------------------*/, E1 Q0 e8 h2 x" ]
- /* Define the size of the sectors to be used */
9 A! L# T9 X" z3 Z% u - #define PAGE_SIZE ((uint32_t)0x0400) /* Page size = 1KByte */8 L% `* [; f+ J( V! v
1 u) U* r" y, t+ i- /* EEPROM start address in Flash */+ S2 `" l1 {' h% j; D
- #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:
* P& E9 A, w% Q# u - from sector2, after 8KByte of used
4 \. E7 z7 c$ w$ q$ I) p0 K - Flash memory */
0 F5 M- g0 q7 y; z5 V8 E* P, F+ Q3 Z - 4 r* X* c, ?/ w/ E- K1 q; e
- /* Pages 0 and 1 base and end addresses */3 d9 {' }& L7 P ?( G! s8 i' X9 s
- #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))4 I$ W; |1 F- _8 u
- #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1)))8 B: k3 t4 E% C9 p
* j: [- L( {8 ~/ ~: s0 C, g- #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))8 J! i) p" b1 ~8 O7 p% X5 O# c7 j
- #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))' F! {+ t; Y. R% v
- " c- p ?; P% j, u( a' \' [
- /* Used Flash pages for EEPROM emulation */
9 k0 |( c$ S1 Z& u# q - #define PAGE0 ((uint16_t)0x0000)
4 }4 B: Q( U; \- G - #define PAGE1 ((uint16_t)0x0001)4 z# U9 M0 J5 n) U
9 B0 A s7 j: Q8 p. Q; l* o0 z- /* No valid page define */) Y! K0 s* N4 l( q* T* m
- #define NO_VALID_PAGE ((uint16_t)0x00AB)
* [* u' f4 N& n4 r4 v; B! j
/ {3 H: B) H) \* H4 q) C, h- /* Page status definitions */7 R: o! h6 l& w# O. T; P# q/ e# m
- #define ERASED ((uint16_t)0xFFFF) /* Page is empty */
6 G& z4 b& R! N3 Y9 l - #define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */
! n8 _' ~6 u* V7 Z) u$ [- w6 I; Q - #define VALID_PAGE ((uint16_t)0x0000) /* Page containing valid data */
复制代码 看代码第6行,这里设定的地址是: EEPROM_START_ADDRESS ((uint32_t)0x08002000)。
) U! T$ N3 S) \% K
. X6 s5 V7 |0 t: j* f5 [7 I$ |. f而STM32F0xx_EEPROM_Emulation演示代码中eeprom.c中关于读的函数:- p+ P+ F7 D( o, P
7 n* _! v2 q+ h" t0 f5 U& w- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)* c1 _! b, l) N9 [! K% u t- [
- {
, K2 q" ^" L% K5 J% o8 U, U- q - uint16_t ValidPage = PAGE0;
, B! B6 J+ l7 r - uint16_t AddressValue = 0x7777, ReadStatus = 1;/ }8 Q$ i$ m* A5 ?
- uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;
' v' A" O+ P" _$ a* N - .
+ M% ^0 F' v6 A% _9 d - .) N7 _& \; P. K$ X" n4 X7 S& `# y' k" k
- }
复制代码 ' [9 e; I! O. [) Y
这里的地址是:Address = 0x08001000。PageStartAddress = 0x08001000;
3 q% d. }, o4 N7 Y 问题应该就出在这里。这个eeprom仿真代码是从STM32F1xx移植过来的。
% a0 Q5 a: ~ r4 C! V- j0 a
K! x4 O. k+ g$ X! {+ F在STM32F1xx的eeprom.h中地址是这样的:$ ^2 i( }1 _4 k. o4 ~1 Q5 Z
- /* EEPROM start address in Flash */# y' R% j$ j2 Q
- #define EEPROM_START_ADDRESS ((uint32_t)0x08010000) /* EEPROM emulation start address:
( t( i4 W6 ]" W% Q2 K6 @: p& c - after 64KByte of used Flash memory */
复制代码 2 t# R# r& k4 a6 H
在STM32F10xx的eeprom.c中读函数是这样的:8 E1 S B. P* B$ X5 c6 c& h
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)1 R) b L3 m1 `/ m% K
- { k9 F4 d4 `2 |8 a
- uint16_t ValidPage = PAGE0;
9 s+ K q+ R: t; u0 y( f2 E/ X; Y: S) x - uint16_t AddressValue = 0x5555, ReadStatus = 1;: ?, {$ y' w% H* B; Q
- uint32_t Address =0x08010000, PageStartAddress =0x08010000;
8 H# Z% P% g& `! X" L4 k$ I7 L - .
. j% Q. I; K0 H {5 C - .
( o8 V5 _: M7 G" O' e9 c, j$ H3 L - }
复制代码 ST工程师在移植F1到F0时忘记将eeprom.c和eeprom.h的读写地址统一,在STM32F0xx_EEPROM_Emulation写入首址是0x08002000,读出首址是0x08001000:读非所写。
7 F9 R; @, D0 g0 A: p7 ?! d5 ?$ [8 V x$ |5 Y4 k
而执行帖子开头的演示代码为什么没有发现读出错呢?由于在演示代码中写完flash操作后并未清空数组变量,DEBUG进入跟踪可知:由于读地址错误,并未执行读操作而直接退出。所以执行
1 T6 c c% D+ f, IEE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);, I) Z6 ]7 p1 v9 o
这句时,实际上根本就没有读扇区、没有更新数组变量内容,数组变量里保留的是上次写操作留下的残余,所以运行的结果看上去是正确的,实际上读出错了。 $ o* R- N7 r* j, ^1 m6 p
6 u+ N$ s! A; x; g7 J* m5 y0 _) H+ a) ?8 ]' p6 T
修改F0的eeprom.c函数中错误之处,3 Z4 q- y1 X! t( F+ X
- uint32_t Address = 0x08002000, PageStartAddress = 0x08002000;
复制代码 问题解决。这个固件库是2012年的古董,6年了,看来我是社区第一个成功使用STM32F0xx_EEPROM_Emulation的了! " B8 ?! \4 B# Q2 Q" E3 r4 [
希望本贴对使用STM32F0xx_EEPROM_Emulation失败的网友有帮助,希望ST官方能更正错误的源码。# t. j. y2 e* n
! _9 U" U) Q; B v+ [
6 T* q' J1 q, A$ k* V9 f+ D/ J2 F: H+ O2 B4 J* k \& k- C( Q/ S
% |: K8 ^& a- ?6 I# U5 H
5 W7 V+ B& e1 S/ Z6 d* r' w
0 p1 u; }& y4 X" I! v
( j) p' u# K6 p, I/ T. f% ~/ }, [2 A5 O$ |; A8 P. {
& p: k" i8 h! K3 a# X2 M/ L3 k4 _: l) d$ k
|
谢谢支持!
谢谢版主!