继续创作,加快生长!这是我参与「日新计划 10 月更文挑战」的第3天,点击检查活动概况
STM32L0 系列EEPROM读写,运用进程有必要留意到的问题,踩坑史 = =!......by 矜辰所致
前言
由于曾经芯片的涨价,运用 STM32L051 和 STM32L071 替换 STM32 有很长时刻了,替换完结以后还依据自己产品的需求写了几篇记载博文:
STM32L051测验 (一、运用CubeMX生成工程文件 — ST系列芯片通用)
STM32L051测验 (二、开始增加需求的代码)
STM32L051测验 (三、I2C协议设备的增加测验)
STM32L051测验 (四、Flash和EEPROM的读写)
STM32L051测验 (五、Enocean模块串口通讯问题)
STM32L0 系列产品都自带了 EEPROM ,运用保存数据起来特别便利,由于写 EEPROM 并不需求删除一篇扇区,能够直接在指定地址写入。
可是最近有某个产品反应,有时分会不可思议的“死机”,这是最直观的现象:
假如在初次配置完结(配置需求对 EEPROM 进行读写)后上电没问题,那么就一直没问题,假如断电重启,有或许遇到问题,遇到问题也是能够靠多重启几回处理(上电会读取 EEPROM 的数据)。
这个问题花了一些时刻,其实便是 EEPROM 的读写问题,从曾经的这篇文章
STM32L051测验 (四、Flash和EEPROM的读写)
我更新了好多次能够看出来,EEPROM 不止出了一次的问题。
所以本文的意图就在于,把 STM32L0 系列 EEPROM 读写运用留意事项阐明清楚,供咱们参阅!
一、写入地址问题
在STM32L0 系列读取 EEPROM 的时分,需求留意:
字节操作,传入合理规模内的任何地址参数都能够;
半字操作,地址需求 2 字节对齐,便是 2的倍数;
全字操作,地址需求 4 字节对齐,便是 4 的倍数;
这个在曾经的测验文章《STM32L051测验 (四、Flash和EEPROM的读写)》中现已做过测验和总结。
二、写入时分容易死机问题
上面的地址写入问题,经过自己的测验能够很容的一发现,可是接下来的这个不可思议程序卡死的问题,花了好一阵子功夫。
2.1 问题的原因
这儿我就纷歧步一步的阐明我遇到的各种不可思议的程序卡死问题,其时尽管基本上猜测是 EEPROM 的写入有问题,由于读取直接取某个指针的值,速度快,也没有什么特别需求留意的,写 EEPROM 的时分需求时刻,这个时刻是有必要等候的,所以基本上确认出问题便是在写入的时分。
尽管中间“优化”维护进程序好几回,可是莫名卡死的问题依然存在。。。。。
这儿我直接阐明最终原因,便是 在写入EEPROM 的时分,假如产生了串口中止,那么就很容易出问题。
这儿非常感谢 ST 社区一篇文章:STM32L0擦写EEPROM,然后宕机了?
我在自己有限的规模搜索这个问题,有且只要这一篇文章真实的提到了电子上,给了极大的参阅价值:
出问题之后,我并没有单步调试,由于我尽管知道写 EEPROM 的时分会出问题,但也发现不是每次都会出这个问题,并且问题纷歧定能够复现,关于这个问题,上文提到:
2.2 问题的处理
2.2.1 不同的 Bank
在上面引荐文章中,给了一个很好的处理办法:在有的芯片中,有 2 块NVM (non-volatile memory 非易失性存储器),分为 Bank1 和 Bank2 ,两个区域都有 Flash 与 EEPROM区域, 对 Bank1 的读写操作并不会影响对 Bank2 的读写操作,说直白点,便是 CPU 不必再挂起等候了。
那么咱们咱们能够做到使得对 EEPROM 的操作的地址区域 与 咱们寄存程序的 Flash 地址区域处于不同的 Bank 就能够。
那么这个怎样做到呢? 首要,你得理解咱们程序寄存于 Flash 中一般都是从 0x0800 0000 开始寄存,也便是 Bank1,除非你自己修改了偏移地址。不理解这个,能够参阅文章:
STM32的发动进程 — startup_xxxx.s文件解析(MDK和GCC双环境
那么咱们只要保证咱们的 EEPROM 的读写地址为 Bank2 即可:
所以,在程序中,我简略做了修改:
#define NVM2_EEPROM_START_ADDR 0x08080C00 //开始地址
/*
EEPROM只要4页,每页512bytes,EEPROM运用便利,咱们用它来保存数据
可是要留意,L051 falsh 和 eeprom没有数据的时分是 0,不是FFFFFFF
L051C8 系列 和 L051R8 系列一样
L071
FALSH : bank1 0x0800 0000 - 0x0800 FFFF
bank2 0x0801 0000 - 0x0801 FFFF
EEPROM : bank1 0x0808 0000 - 0x0808 0BFF
bank2 0x0808 0C00 - 0x0808 17FF
*/
#define CH1_ID_ADDR NVM2_EEPROM_START_ADDR + 0
#define CH2_ID_ADDR NVM2_EEPROM_START_ADDR + 4
#define CH3_ID_ADDR NVM2_EEPROM_START_ADDR + 8
#define CH4_ID_ADDR NVM2_EEPROM_START_ADDR + 12
#define CH5_ID_ADDR NVM2_EEPROM_START_ADDR + 16
#define CH6_ID_ADDR NVM2_EEPROM_START_ADDR + 20
#define CH7_ID_ADDR NVM2_EEPROM_START_ADDR + 24
#define CH8_ID_ADDR NVM2_EEPROM_START_ADDR + 28
#define CH9_ID_ADDR NVM2_EEPROM_START_ADDR + 32
#define CH10_ID_ADDR NVM2_EEPROM_START_ADDR + 36
那么有的小伙伴会说,假如我的程序特别大,超过了 Bank1 怎样办?
程序大小怎样算,可检查文章:
STM32的内存管理相关(内存架构,内存管理,map文件剖析)
<3 1、首要假如是运用的有2个Bank的芯片, Bank1有 64k 大小,一般来说程序足够了;
2、个人认为,关于中止程序来说,他们存在的位置一定是程序的前面,即便程序超过大小,寄存在 Bank2 中的也是用户自己的一些程序,不或许回事中止响应程序。即便中止产生了,也是在 Bank1 中运转,无影响;
3、再者,即便不分 Bank ,咱们能够屏蔽中止。下面我将介绍在没有两个 Bank 的芯片上的处理方式。 <3
2.2.2 临界区的维护
临界区的维护,是不是特别熟悉了, 咱们在讲 FreeRTOS 或者 RT-Thread 的时分都讲到过 临界区维护。
上面咱们介绍了直接把 EEPROM 的操作地址与程序地址区分开的处理方式,可是关于大部分产品上我运用的 STM32L051C8 来说,没有两块 NVM ,那么只能是做临界区维护了。
检查自己的 STM32L0 系列芯片有没有两块 NVM, 能够经过 J-Flash 工具检查他们的内存情况:
那知道了原因,咱们只要在程序有 EEPROM 写的位置加上临界区维护即可,比方:
假如运用裸机操作,咱们能够直接在写 EEPROM 的时分屏蔽中止,运用下面2个函数:
__enable_irq(void);
__disable_irq(void);
如图:
尽管写需求花时刻,可是该等仍是得等。
由于我运用的串口通讯是收无线的报文,尽管在屏蔽中止的时分有一定的概率丢数据,可是偶然丢数据是能够接收的,至少比写数据的时分产生中止程序卡死来得好。
并且,EEPROM 尽管写便利,也不主张频频的写入,往往需求写的时分都是第一次设置或者特殊情况设置的时分才用到。
2.2.3 要害程序放到 RAM 中履行
除了上面 2 种比较简略的处理办法,还有一种。
在网上看到有发问者说过,官方曾有过主张,把要害程序 放到 RAM 中履行,防止冲突。
把程序放到 RAM 中履行,假如有时刻,我会独自写一篇博文阐明,这儿仅仅提一下处理这种问题的可行办法。
三、官方文档
<3 这个问题告诉咱们,要想真实用好一个芯片不出问题,仍是得了解好对应的芯片文档。
即便咱们现已很熟悉同类型的 STM32F103 系列,运用 STM32CUbeMX 能够快速简略的上手类似系列的芯片产品,可是在有些细节问题的处理上仍是容易存在问题,此刻官方的文档应该是首要想到的参阅文档。 <3
那么文档资料哪里下载,在 ST 社区能够经过站内搜索,关于 STM32L0 系列(后缀 1 ,3在这儿应该都能够)有关的文档:RM0377文档,关如下图:
在文档中有一整个章节独自介绍存储设备 Flash 和 EEPROM:
其实关于产品遇到的这些问题,文档里面其实有具体的阐明以及处理方式,当然,即便是到现在,我也没有 具体的全部看完,由于知道了一些留意事项,仍是偷懒,文档没看那么细心= =!
可是这儿比有必要着重一次官方文档的重要性。
由于在网上我找了很久这个问题,在 ST 社区也找了很久,除了上面给出的链接那篇文章,再也没有第二篇 有问题也有处理办法的文章,那么这时分,咱们就只能自己去啃官方文档了!
结语
一个简略的芯片,一个便利运用的 EEPROM ,前前后后出了这么多问题,也不得不感叹,细节问题还真是不能偷一点懒 = =!
做事情不要想当然,要想产品无 bug ,该看的资料仍是得看到位,期望 EEPROM 这个问题是产品更换后最终的问题。ヾ(◍∇◍)ノ゙
本文就到这儿,谢谢咱们!