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

基于STM32L0的EEPROM读写经验分享

[复制链接]
攻城狮Melo 发布时间:2023-6-11 19:47
前言

STM32L0 系列产品都自带了 EEPROM ,使用保存数据起来特别方便,因为写 EEPROM 并不需要删除一篇扇区,可以直接在指定地址写入。

但是最近有某个产品反馈,有时候会莫名其妙的“死机”,这是最直观的现象:

如果在初次配置完成(配置需要对 EEPROM 进行读写)后上电没问题,那么就一直没问题,如果断电重启,有可能遇到问题,遇到问题也是可以靠多重启几次解决(上电会读取 EEPROM 的数据)。

) C2 y' l; k& R2 L& C5 E

我更新了好多次可以看出来,EEPROM 不止出了一次的问题。

所以本文的目的就在于,把 STM32L0 系列 EEPROM 读写使用注意事项说明清楚,供大家参考!

2 @, ^) T0 e- O0 j5 ]$ i% N. H
一、写入地址问题

在STM32L0 系列读取 EEPROM 的时候,需要注意:

字节操作,传入合理范围内的任何地址参数都可以;

半字操作,地址需要 2 字节对齐,就是 2的倍数;

全字操作,地址需要 4 字节对齐,就是 4 的倍数;

这个在以前的测试文章《STM32L051测试 (四、Flash和EEPROM的读写)》中已经做过测试和总结。

$ |+ k+ h" }1 f: p% r( \, `/ B
二、写入时候容易死机问题

上面的地址写入问题,通过自己的测试可以很容的一发现,但是接下来的这个莫名其妙程序卡死的问题,花了好一阵子功夫。


* w2 p0 O6 m  X! Z0 i1 S. A) f% y6 S2.1 问题的原因

这里我就不一步一步的说明我遇到的各种莫名其妙的程序卡死问题,当时虽然基本上猜测是 EEPROM 的写入有问题,因为读取直接取某个指针的值,速度快,也没有什么特别需要注意的,写 EEPROM 的时候需要时间,这个时间是必须等待的,所以基本上确定出问题就是在写入的时候。

虽然中间“优化”维护过程序好几次,但是莫名卡死的问题依然存在。。。。。

这里我直接说明最终原因,就是 在写入EEPROM 的时候,如果发生了串口中断,那么就很容易出问题。

这里非常感谢 ST 社区一篇文章:STM32L0擦写EEPROM,然后宕机了?

我在自己有限的范围搜索这个问题,有且只有这一篇文章真正的说到了电子上,给了极大的参考价值:

1 B# y( p7 E' J& e

$ s8 v' M% n0 \: e4 |) M' v+ n' {
微信图片_20230611194650.png
5 O6 k- G3 Y' P: a8 r) U9 q

+ E( t; e% x, }' D5 }

出问题之后,我并没有单步调试,因为我虽然知道写 EEPROM 的时候会出问题,但也发现不是每次都会出这个问题,而且问题不一定能够复现,对于这个问题,上文说到:

; Z) l4 ~* P; D( g# C. m( a

微信图片_20230611194829.png

8 q3 L; w4 q# {& j( }) F. P4 Y4 I
2.2 问题的解决
2.2.1 不同的 Bank

在上面推荐文章中,给了一个很好的解决办法:在有的芯片中,有 2 块NVM (non-volatile memory 非易失性存储器),分为 Bank1 和 Bank2 ,两个区域都有 Flash 与 EEPROM区域, 对 Bank1 的读写操作并不会影响对 Bank2 的读写操作,说直白点,就是 CPU 不用再挂起等待了。

' S* q! z- ~+ f0 r1 J6 }! e

那么我们我们可以做到使得对 EEPROM 的操作的地址区域 与 我们存放程序的 Flash 地址区域处于不同的 Bank 就可以。


7 C2 J6 f: D9 b1 _. Q

那么这个怎么做到呢?首先,你得明白我们程序存放于 Flash 中一般都是从 0x0800 0000 开始存放,也就是 Bank1,除非你自己修改了偏移地址。


- `4 ~& T- |1 J

那么我们只要保证我们的 EEPROM 的读写地址为 Bank2 即可:


; \. C  S( d1 _1 j

微信图片_20230611194645.png


: h$ R- y: I7 c, ?# E: n1 v$ q# o

于是,在程序中,我简单做了修改:

  1. #define NVM2_EEPROM_START_ADDR     0x08080C00   //起始地址
    2 C( x+ K: \3 G  F* B+ U1 s

  2. ) k3 Z$ F& m4 u* [0 T; l
  3. /*) `8 h9 o, O1 P! U* V: L, B
  4.     EEPROM只有4页,每页512bytes,EEPROM使用方便,我们用它来保存数据
      r9 O0 C" D+ l
  5.     但是要注意,L051 falsh 和 eeprom没有数据的时候是 0,不是FFFFFFF
    / B; L) o8 L) |) G
  6.     L051C8 系列 和 L051R8 系列一样 - [' j, I8 Z) n2 P% t, [7 _9 N

  7. 7 Y4 B* T/ g9 {' t% ~) O* c
  8.     L071$ d' a8 `* q, i  l
  9. * Q3 l# u9 A: B, i4 e0 g
  10.     FALSH :     bank1 0x0800 0000 - 0x0800 FFFF) o+ @- m* W# m9 c. T  b
  11.                 bank2 0x0801 0000 - 0x0801 FFFF; p2 z/ U, m; t0 Q
  12.     EEPROM :    bank1 0x0808 0000 - 0x0808 0BFF
    5 \9 k/ Y* n* z9 N' [$ s
  13.                 bank2 0x0808 0C00 - 0x0808 17FF# j2 [" l4 w" z! a9 H. g+ V
  14. */8 s- t9 o" u5 U7 ~1 J. A

  15. 4 _2 d  P0 |8 s/ W
  16. 3 H& I6 f! N2 G) R, i. N: a6 Q+ `
  17. #define CH1_ID_ADDR     NVM2_EEPROM_START_ADDR + 0    3 N5 l. H6 i2 I; E8 e. M6 U) n4 \
  18. #define CH2_ID_ADDR     NVM2_EEPROM_START_ADDR + 42 H" w$ T, j. E; z" `- k8 b& S  G$ ?& z
  19. #define CH3_ID_ADDR     NVM2_EEPROM_START_ADDR + 84 W% q( ^* F+ ?8 y6 @& N* r
  20. #define CH4_ID_ADDR     NVM2_EEPROM_START_ADDR + 12$ y  T, D7 o0 w5 h1 h
  21. #define CH5_ID_ADDR     NVM2_EEPROM_START_ADDR + 16
    9 U) u3 o8 ]7 k% }5 g( [. A9 C- ]
  22. #define CH6_ID_ADDR     NVM2_EEPROM_START_ADDR + 20
    0 Z: X4 s2 i2 h. R
  23. #define CH7_ID_ADDR     NVM2_EEPROM_START_ADDR + 24
    ) j5 F1 W5 |* ]7 S  `
  24. #define CH8_ID_ADDR     NVM2_EEPROM_START_ADDR + 28
    ; k& N  b; t9 n# s: h4 A
  25. #define CH9_ID_ADDR     NVM2_EEPROM_START_ADDR + 32
    4 ?: s! W# ]# `
  26. #define CH10_ID_ADDR    NVM2_EEPROM_START_ADDR + 36
复制代码
0 E# w! _7 n  K% \( q6 v) E. @

那么有的小伙伴会说,如果我的程序特别大,超过了 Bank1 怎么办?

1、首先如果是使用的有2个Bank的芯片, Bank1有 64k 大小,一般来说程序足够了;

2、个人认为,对于中断程序来说,他们存在的位置一定是程序的前面,即便程序超过大小,存放在 Bank2 中的也是用户自己的一些程序,不可能回事中断响应程序。即便中断发生了,也是在 Bank1 中运行,无影响;

3、再者,即便不分 Bank ,我们可以屏蔽中断。下面我将介绍在没有两个 Bank 的芯片上的处理方式。


! X: O+ e* Z, [' d! f7 Q2.2.2 临界区的保护

临界区的保护,是不是特别熟悉了, 我们在讲 FreeRTOS 或者 RT-Thread 的时候都讲到过 临界区保护。

上面我们介绍了直接把 EEPROM 的操作地址与程序地址区分开的解决方式,但是对于大部分产品上我使用的 STM32L051C8 来说,没有两块 NVM ,那么只能是做临界区保护了。

查看自己的 STM32L0 系列芯片有没有两块 NVM, 可以通过 J-Flash 工具查看他们的内存情况:

  Q! H5 N& k5 X( w" {
微信图片_20230611194638.png

3 f# ^' f% Y2 A& h5 r) H+ R% A3 q' D# s1 X

那知道了原因,我们只要在程序有 EEPROM 写的位置加上临界区保护即可,比如:


) o9 Y5 a, o. I) W  \

% r3 A# i( b$ D+ F: d7 _
微信图片_20230611194635.png

' T2 L2 O  ]* {% Q4 ~8 X% @4 V7 u0 W7 v( W( |6 b* Z
* u5 A' N  w1 _% G, N5 M& r

7 ^# h1 N3 f1 m3 T, V# C

如果使用裸机操作,我们可以直接在写 EEPROM 的时候屏蔽中断,使用下面2个函数:

  1. __enable_irq(void);7 z# c( @$ l4 |& O0 x/ y- l
  2. __disable_irq(void);
复制代码
8 M& g4 k* q2 J6 `% d8 Q# _" ^- m

如图:


3 U) a. H* _& Z9 e

( d! z+ Z( O/ x3 I9 j
微信图片_20230611194628.png

5 W; B4 }/ B1 F/ u, z( ]9 X$ X7 n5 g# C% U* _

虽然写需要花时间,但是该等还是得等。

因为我使用的串口通讯是收无线的报文,虽然在屏蔽中断的时候有一定的概率丢数据,但是偶尔丢数据是可以接收的,至少比写数据的时候发生中断程序卡死来得好。

而且,EEPROM 虽然写方便,也不建议频繁的写入,往往需要写的时候都是第一次设置或者特殊情况设置的时候才用到。

! b7 e2 Z$ k% r: d6 m8 Z
2.2.3 关键程序放到 RAM 中执行

除了上面 2 种比较简单的解决办法,还有一种。

在网上看到有提问者说过,官方曾有过建议,把关键程序 放到 RAM 中执行,避免冲突。

把程序放到 RAM 中执行,如果有时间,我会单独写一篇博文说明,这里只是提一下解决这种问题的可行办法。

$ m4 }/ h9 I' w
三、官方文档

这个问题告诉我们,要想真正用好一个芯片不出问题,还是得了解好对应的芯片文档。

即便我们已经很熟悉同类型的 STM32F103 系列,使用 STM32CUbeMX 可以快速简单的上手类似系列的芯片产品,但是在有些细节问题的处理上还是容易存在问题,此时官方的文档应该是首要想到的参考文档。

那么文档资料哪里下载,在 ST 社区可以通过站内搜索,关于 STM32L0 系列(后缀 1 ,3在这里应该都可以)有关的文档:RM0377文档,关如下图:


: ~  ?+ Z, _4 ?1 T1 p
0 ~. R; K8 D, G$ i
微信图片_20230611194620.png
) i  v! l( Y( z% F
5 c7 M: a0 w7 a; I

在文档中有一整个章节单独介绍存储设备 Flash 和 EEPROM:


( i3 t- ~' A6 N+ S0 P5 q, _
8 F  ~' o* e1 ^, L$ z6 G+ o
微信图片_20230611194612.png

) G' O# i( z  y3 U" y* ^& m3 r' o2 f1 \1 A+ |. y# X2 E- j

其实对于产品遇到的这些问题,文档里面其实有详细的说明以及解决方式,当然,即便是到现在,我也没有 详细的全部看完,因为知道了一些注意事项,还是偷懒,文档没看那么仔细= =!

但是这里比必须强调一次官方文档的重要性。

( ^6 d( i; {- I; _! L* h

2 }2 Y" g1 f/ O转载自:矜辰所致
& b8 t$ n) O- i- C9 p8 @如有侵权请联系删除; U+ x& R- o0 u

+ i( S# I1 K/ R6 O1 w% m+ |( t9 \( {* z
收藏 评论0 发布时间:2023-6-11 19:47

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版