本帖最后由 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
- for (VarValue = 1; VarValue <= 0x64; VarValue++)
7 b5 R! w) ]8 |+ z - {
. V" a3 [: t5 G+ R9 R - EE_WriteVariable(VirtAddVarTab[0], VarValue);# {& A# K: B+ x9 b+ A* X% N
- }5 P- N: \" H' A. S3 [9 T& Z
- 再读出。
* F% L% c* [4 l s5 b
. B* ~& Q3 ~; Y: {- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);+ o1 G% u/ v6 n4 Z1 d* X
" @0 _" L! ]% l2 O
- r# l: |+ ?/ `+ ]- for (VarValue = 1; VarValue <= 0xC8; VarValue++)
/ K" [; H& Y7 V: C" s% b - {" d0 S) |2 d+ c" u6 Q
- EE_WriteVariable(VirtAddVarTab[1], VarValue);$ _3 a2 x3 w, r) B
- }
7 Z% W L' {; k- J& N& B" c4 W - EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);
l( B$ c# e2 k1 }3 d/ S - EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
, c2 B9 T: n; n - for (VarValue = 1; VarValue <= 0x1C2; VarValue++)
) c# e- f; r1 m" A - {. M1 T! Q" z* f- Z
- EE_WriteVariable(VirtAddVarTab[2], VarValue);
6 J X% u! }, N, q- t7 ^ - }4 M6 e& \. [: w4 C2 n) w$ G* O
- /* read the last stored variables data*/- {9 a8 D- ^# n) S0 q- Y
- EE_ReadVariable(VirtAddVarTab[0], &VarDataTab[0]);3 O6 a6 S# q) h0 K" R0 ~( V
- EE_ReadVariable(VirtAddVarTab[1], &VarDataTab[1]);
9 B, h: `' y! ?; k+ P8 V - 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
" 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- /* Exported constants --------------------------------------------------------*/
3 ^8 P! _) b) f" F) t$ y/ _ - /* Define the size of the sectors to be used */
- [5 }: O; C2 ~9 D' A9 R4 F - #define PAGE_SIZE ((uint32_t)0x0400) /* Page size = 1KByte */) y- n% ?8 \6 \+ Q' g
* I7 G( y, B" d% e) k$ ^- /* EEPROM start address in Flash */
( J3 G0 m' K/ l) e; T" ~ - #define EEPROM_START_ADDRESS ((uint32_t)0x08002000)/* EEPROM emulation start address:) _1 h9 m% p) X/ u/ _
- from sector2, after 8KByte of used
. E+ t$ W0 H! F; H1 U4 Y) ]8 B1 h) H1 b - Flash memory */$ z9 G! m& m8 l1 U+ f" `
# Y+ q3 D7 t; y: j) N- /* Pages 0 and 1 base and end addresses *// T2 p- R5 V8 C8 F( r- T
- #define PAGE0_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0000))
( k8 O1 A" w: J - #define PAGE0_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (PAGE_SIZE - 1))), m: @( h$ V1 F
: Q0 F5 |. T# F* ?- #define PAGE1_BASE_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + 0x0400))
% _- z+ D; I8 m - #define PAGE1_END_ADDRESS ((uint32_t)(EEPROM_START_ADDRESS + (2 * PAGE_SIZE - 1)))
) q) e F4 w k( O5 p2 j' }
/ V. r5 m! v# g- [; V- /* Used Flash pages for EEPROM emulation */ R' K% k, B' y
- #define PAGE0 ((uint16_t)0x0000)
0 W2 h7 q: r+ w" [$ k; x `, X - #define PAGE1 ((uint16_t)0x0001)
5 b& I% Z1 x. u; O6 i- G - 6 v% Y8 b1 g5 }& A3 |( }
- /* No valid page define */
, j# d1 I9 O4 [8 K - #define NO_VALID_PAGE ((uint16_t)0x00AB)
3 I) \0 i0 [$ X- J - % u* j$ Y9 i5 `/ D7 c4 I
- /* Page status definitions */
9 o* ~5 t; n* g% X' M - #define ERASED ((uint16_t)0xFFFF) /* Page is empty */# I" l. I( M; `* J% V- }9 Q
- #define RECEIVE_DATA ((uint16_t)0xEEEE) /* Page is marked to receive data */# H& t R& W( Y2 G
- #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- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
6 g. _, E( k' f0 T0 b - {
, c: S; m& |1 R - uint16_t ValidPage = PAGE0;
/ m$ E5 A2 A( b" n - uint16_t AddressValue = 0x7777, ReadStatus = 1;' ]( q% y/ g; F- g' y' n
- uint32_t Address = 0x08001000, PageStartAddress = 0x08001000;1 L* S4 @" L! ?% z
- .2 ]0 H- Q7 b' s0 U* R0 i
- .
! X! {2 N9 X4 F6 h - }
复制代码
% r! y; o7 c, K. b! g! V5 v 这里的地址是:Address = 0x08001000。PageStartAddress = 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
- /* EEPROM start address in Flash */
& ^. v# A- L& d - #define EEPROM_START_ADDRESS ((uint32_t)0x08010000) /* EEPROM emulation start address:
1 s' P3 E) P7 c% g5 ? - after 64KByte of used Flash memory */
复制代码
1 `% N& W* _+ I' m) f) E在STM32F10xx的eeprom.c中读函数是这样的:9 D0 z+ m3 l5 s5 \
- uint16_t EE_ReadVariable(uint16_t VirtAddress, uint16_t* Data)
/ ~" n+ p/ }6 L8 V3 O* J( L# S - {& n( u2 i% @- ]- r1 e3 o
- uint16_t ValidPage = PAGE0;
/ Y" P T8 y, Y2 T; M; e! H# I - uint16_t AddressValue = 0x5555, ReadStatus = 1;$ C! ]' ]9 a: A' V. v
- uint32_t Address =0x08010000, PageStartAddress =0x08010000;+ @; Y5 K3 v0 M( z, r
- .: a! b( P/ r5 a1 r0 y% k
- .+ J( n& v. a7 b1 J$ ?6 X5 ]
- }
复制代码 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" \" ]
- 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
|
谢谢支持!
谢谢版主!