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

【经验分享】STM32L0 内部EEPROM写读

[复制链接]
STMCU小助手 发布时间:2021-11-17 23:02
STM32L0 内部EEPROM写读9 E" ]2 S/ O& \1 p
说明  p  z0 u: B% s# s, a/ u. q
STM32L0内部的EEPROM写操作由解锁,写入,加锁过程组成,读过程则无需解锁。至于STM32L0内部的非易失空间区分为FLASH和EEPROM,主要体现在用ST-LINK等工具进行整片擦除时,只擦除FLASH的空间,EEPROM的部分不会被擦除,如同外部EEPROM芯片,MPU的代码升级不影响EEPROM的内容。后面以内部EEPROM的写读作为范例。
2 j, E3 X& _& j/ v/ S. Y0 v! w0 Q8 `6 U/ z3 \5 ]/ l
基础写读函数
( t7 \1 {: D# a3 ^9 X定义内部EEPROM的地址空间:
. O; W- A7 F) E/ n
  1. //STM32L031K6T6% _- ~# f. U6 |- w
  2. #define EEPROM_BASE_ADDR        0x08080000
    - ]5 j$ W7 c5 x& S& X3 c1 K- h  u
  3. #define EEPROM_BYTE_SIZE        0x03FF
复制代码

+ J% m, h1 i3 u1 k5 D" _( \基础字节写函数
& `7 f5 p3 M4 d+ l- v
  1. //Byte write% M9 J, k5 \! ]3 B
  2. void EEPROM_WRITE(uint16_t BiasAddress, uint8_t *Data, uint16_t len)7 D0 U8 l8 G1 O
  3. {4 m- m3 H3 Q. `  l" D
  4.         uint16_t i;" P/ J! @0 X- t1 N2 D6 ~: g
  5.         HAL_StatusTypeDef status = HAL_OK;
    - w4 a# Q) r# o! K( s2 p

  6. . A2 `3 ?% t" |; u
  7.         HAL_FLASHEx_DATAEEPROM_Unlock();9 H! N& t9 Y2 Q. V
  8.         for(i=0;i<len;i++)4 `% r/ p9 @4 F0 i/ |; b2 }
  9.         {* t; n4 U8 U' v0 X3 X; ?' ^
  10.                 status +=HAL_FLASHEx_DATAEEPROM_Program(FLASH_TYPEPROGRAMDATA_BYTE, EEPROM_BASE_ADDR+BiasAddress+i, *Data);
    , Q' h) }  k2 z* Y: `" v  h7 f
  11.                 Data++;  e& d' C- x5 X# _# W
  12.         }/ b; \) G& x7 ^' U  P
  13.         HAL_FLASHEx_DATAEEPROM_Lock();
    & b/ X% b# \! L, n3 B" ]; j% W& z
  14. }
复制代码
- y7 S) N$ I- E2 e3 i8 }; Z
基础字节读函数/ o) n  \  o; h4 ]8 C4 N' k
  1. <span style="background-color: rgb(255, 255, 255);">/</span>/Byte read
    9 `: t7 I3 z2 F& [7 }
  2. void EEPROM_READ(uint16_t BiasAddress,uint8_t *Buffer,uint16_t Len)5 J8 n/ S( s& P3 i* A
  3. {: [7 B( t" Q0 }* t  A
  4.         uint8_t *wAddr;+ {, I5 {, ]2 k0 b
  5.         wAddr=(uint8_t *)(EEPROM_BASE_ADDR+BiasAddress);
    0 t/ i( h0 A( a2 M& W
  6.         while(Len--)# ]7 t: L4 I( L" ~
  7.         {
    5 R! z1 _2 j) W& H8 a7 ~4 F
  8.                 *Buffer++=*wAddr++;
    ) ]/ I7 R) G" g; M+ P: t$ n. k& _
  9.         }1 Q# o6 F+ a6 Q
  10. }
复制代码
0 a. x! L8 |7 ^4 A. U! l( y; b
带校验写读函数
/ i+ q, U/ I. j. K7 Y, x如果考虑到写读过程中,可以出现错误的情况,为了保证操作的正确性,需要采用校验方式进行写读。
- S7 i- {1 T4 w" }  t: E2 E  J! n对于写过程,需要将写入的数据,读回做比较。) q2 T- e- x! @: ?, R9 P% I
对于读过程,需要将两次读回的数据,进行比较。7 d: a& e& v) \1 z0 L
如果比较正确,则操作完成。9 Z7 U! W3 j7 r* n! v* a6 _& R
如果错误,可重新进行写或读操作,并在设定的重新操作次数范围内,进行重新操作识别,如果正确,则报告正确,如果错误,则报告错误。
! n; H( T  M6 R
4 X$ C4 C. L6 _6 X设定重复校验次数
6 v6 M6 \9 b- W7 N0 a
  1. #include <string.h>
    ( F- W$ y9 b2 ~0 m6 S3 p9 ]
  2. #define iEEPROM_CHECK_NUM 2
复制代码
( F3 c* w( F2 y6 g( O* ^

+ L9 V2 A  b( Z5 `/ W带操作校验的写函数
' }0 d( e3 S9 a2 C* _
  1. HAL_StatusTypeDef EEPROM_WRITE_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    ( e5 {- i' f& Q4 M/ E' P; S- k! X
  2. {
    ( T8 L% U1 W( h3 Q% O2 y
  3.         uint8_t buff[len];
    5 m1 F) m# o( t: i. |; I
  4.         uint16_t i;
      q6 p; ^  r7 X; t3 u
  5.         for (i=0;i<iEEPROM_CHECK_NUM;i++)+ }: u3 W% o9 T
  6.         {! p5 E: g; F3 [  z0 t
  7.                 EEPROM_WRITE(BiasAddress, Data, len);3 M7 p/ B# L1 s' V/ I0 K4 S7 [. W& i
  8.                 EEPROM_READ(BiasAddress, buff, len);4 p1 f* [! g& t
  9.                 if (memcmp(Data, buff, len)==0)
    " u5 C5 p" I- n8 \: ~  O& _
  10.                 {9 Z8 y' V& t5 ^' ?% W5 G8 S
  11.                         return HAL_OK;
    9 M; N' t- ?0 A2 O) Z
  12.                 }' ]# `7 m% O0 P* n# A& d/ U3 ?
  13.         }
    ; G0 |: ^+ A- }

  14. 3 h/ p6 g) i% Q& Z1 P# [3 i
  15.         return HAL_ERROR;0 |7 J; Y; U! W( b8 i
  16. }
复制代码
/ t: T7 ~/ D: n9 f
带操作校验的读函数! h2 }* |: m6 n
  1. HAL_StatusTypeDef EEPROM_Read_W_CHECK(uint16_t BiasAddress, uint8_t *Data, uint16_t len)
    , d9 P6 ?, Q6 w8 ]
  2. {
    0 o7 e9 [: }. {* J" o/ V
  3.         uint8_t buff0[len];
    9 O3 M' X' F: H8 V2 ^+ _  e  c
  4.         uint8_t buff1[len];/ a$ ^7 y( g$ C! [! _; J+ r
  5.         uint16_t i;
    " Q0 g$ I5 i1 ?9 W
  6.         for (i=0;i<iEEPROM_CHECK_NUM;i++)
    / [: Y6 G  N/ _) H
  7.         {4 W0 ^% m( R( Q0 A
  8.                 EEPROM_READ(BiasAddress, buff0, len);2 R: S9 d; g  A* a
  9.                 EEPROM_READ(BiasAddress, buff1, len);) @& P7 k4 ~0 D" M5 K
  10. 4 o: _2 a% d5 ^' J
  11.                 if (memcmp(buff0, buff1, len)==0)  w; `! u; W+ T6 \! O3 B' Y2 B0 W8 D1 \
  12.                 {! y, r# v. j# M
  13.                         memcpy(Data, buff0, len);0 u7 R: j9 Z2 e/ x' _* V! r  N
  14.                         return HAL_OK;
    8 q* T5 w* Y" h( }0 }% d
  15.                 }
    9 Z/ X; `5 d1 U" h7 A/ l( E8 h/ j. z$ P
  16.         }
    , T/ F; z) f2 @! j( v

  17. $ ~! [* ~5 E/ W+ I$ y; {
  18.         return HAL_ERROR;
      D& V- l& [5 W/ C2 u" B+ }
  19. }
复制代码
$ P' h+ N; h  b) G; j  r* K
其中BiasAddress为0对应内部EEPROM的0地址(EEPROM_BASE_ADDR定义了其基址),Data为数据字节指针,len为操作字节长度。
0 A+ c  F. i' }  l0 _7 k% G* d- l' [  i; H% p# A0 ]
需要注意的是,基于工艺制程和设计,EEPROM的使用也分为两种,其中一种和FRAM相似,可以直接进行写入而不需要提前擦除,STM32内部的EEPROM也是这一种;另外一种和FLASH相似,需要先进行基于Page的擦除后才能正确写入,对于有的EEPROM,支持基于Page最小为Byte单元的擦除。7 X1 ^" u3 M- |! ]* n7 y
- `& a# o4 Y1 g8 b. u( s* r
HAL提供的内部EEPROM擦除函数, 只是进行一个word的擦除,即在某个地址上将数据改写为0x00000000, 和直接调用写函数在该地址写入0x00000000效果一样。HAL的内部EEPROM擦除函数如下:# S$ p& _9 f0 ?; y2 A' d

' a% i& i* V1 G  j1 c
  1. /**+ g' c, }) {3 e+ y# R( B
  2.   * @brief  Erase a word in data memory.
    9 i: l2 j) k' l) q4 ?
  3.   * @param  Address specifies the address to be erased.% S% j1 a. W; r. j5 ?6 Z
  4.   * @note   To correctly run this function, the @ref HAL_FLASHEx_DATAEEPROM_Unlock() function4 |. b* N& c0 Z7 z8 ^
  5.   *         must be called before.
    9 E! e1 K5 X7 _4 [
  6.   *         Call the @ref HAL_FLASHEx_DATAEEPROM_Lock() to the data EEPROM access
    9 j4 U2 c% i2 h. u! S
  7.   *         and Flash program erase control register access(recommended to protect ) c/ Q; z, C6 W! q$ w: v
  8.   *         the DATA_EEPROM against possible unwanted operation).
    / G/ D4 N/ m4 V: o' V" {* E- s$ t1 [
  9.   * @retval HAL_StatusTypeDef HAL Status2 D$ b- F) Z+ v, H' J  ^2 o! E
  10.   */
    8 i4 a/ o' _2 z( R: j* i
  11. HAL_StatusTypeDef HAL_FLASHEx_DATAEEPROM_Erase(uint32_t Address)2 S: u* w  m% t$ Y7 e
  12. {, }7 Y& ^# q* x& o% V  Z
  13.   HAL_StatusTypeDef status = HAL_OK;, C5 _' v5 \' X7 d: I5 c( c" a

  14. 5 D7 ^& q0 S8 s3 o
  15.   /* Check the parameters */! _! O. [* h0 l' ~, p+ z- R
  16.   assert_param(IS_FLASH_DATA_ADDRESS(Address));
    7 A* \3 L3 I4 ~4 ~5 z/ ~5 c

  17. 3 x' `) A" H( m
  18.   /* Wait for last operation to be completed */+ [: H6 z' M% z: _4 e6 D. Z1 B
  19.   status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    4 u! s9 z( N$ p! {+ y& ^. ]

  20. # @$ x/ \' M  ?* T2 O
  21.   if(status == HAL_OK)- U$ y, V* F: C! Z. K7 d' @
  22.   {9 t+ Q( x. J9 U+ [$ D, ~" y) t& V
  23.     /* Clean the error context */3 r1 E6 V; u, W4 o/ E% V
  24.     pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;/ m# I& w$ i8 d& Z
  25. $ I. J, F( v; c. \
  26.       /* Write 00000000h to valid address in the data memory */
    ) G' j+ ^2 b+ r) P, F
  27.       *(__IO uint32_t *) Address = 0x00000000U;
    ' Z# [$ C( ?9 b4 d$ c; u
  28. $ e$ [& N& g3 e4 \, D
  29.     status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
    / `. Q( r; H& {. p$ f- P0 C; q
  30.   }
    # y+ |- A5 c: D3 N. w; w) O# r" Z8 g
  31. 3 }, S/ ~0 l3 ^# L
  32.   /* Return the erase status */! i) a5 x0 B1 u8 r6 B1 }$ b
  33.   return status;
    , d" ]1 t9 Q% M: Y& y7 [' s( T
  34. }  
复制代码
" ~/ s  i  p9 `1 Z1 P8 D
上述的代码,如果要用于STM32内部FLASH的操作,还需要增加页擦除操作。0 r0 r. t3 {2 H% [- b+ }" p

5 X# H3 I, P8 W! A, V: u) e7 v! ]- M5 y& X. h% X5 I
赞 收藏 评论0 发布时间:2021-11-17 23:02

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版