EFM(Embedded FLASH Module),就是云途MCU用来操作flash的外设,下面我们以LE0系列为例
• PFlash:Program Flash,用于存储代码和数据。
• DFlash:Data Flash,用于存储数据。
• NVR:Non-Volatile Register,用于存储特定信息,有特殊用途。
• OTP NVR:One Time Programmable,只能写一次,不能擦除。OTP_NVR可以用于保存一次性可编程数据,OTP(One Time Program)区域的特点是,只能一次写入,不支持擦写和二次写入。在具体应用中,可以在该区域保存产品ID信息或者永久固化的信息。注意,对该区域的读取并没有限制。
• HCU NVR:Hardware cryptography,用于存放加密密钥,不能被直接读取。
• CUS NVR:Customer,用于客户配置,比如关闭调试接接口,地址保护。CUS_NVR包含Flash擦写保护配置和调试端口禁用的特定的数据标签(相当于是配置寄存器的值),用户可以向该区域的特定地址写入特定值,以启用对Flash的擦写保护和禁用调试端口。CUS_NVR的剩余部分是用户可以自由使用的,但对CUS_NVR的读写操作需要先通过写入Customer Key来解锁。
• RWW:Read While Write,在写一个区域的同时读取另外一个区域。
这里补充说明一下RWW 特性(Read-While-Write):
RWW 特性的意思是在 Flash 执行擦写命令进入 Busy 状态期间(STS 寄存器 IDLE 位变状态 0)还能否继续响应非操作区域的读访问。
如果 STS[IDLE]=0 时还能够支持读访问,则该 Flash 支持 RWW,反之则不支持 RWW。
如果芯片不支持 RWW,擦写操作时需要关闭全局中断。
原理:支持 RWW 的芯片 Flash 物理存储中存在多个 Block 物理块。在擦写其中一个 Block 时,可以同时读取其他的Block 数据。
同理 NRWW(No Read-While-Write)的芯片,其 Flash 物理存储中只有一个 Block,因此不能边写边读。
Flash的特性是:擦除之后比特位的值变成1,写入操作是将相应的比特位的值改写成0
下面是大家最关心的两个操作:
• Erase Sector 操作,最小单元为 Sector Size 大小。
status_t FLASH_DRV_EraseSector(uint32_t dest, uint32_t size),dest 和 size 需要为 sector size 整数倍。
• Program 操作,最小单元为 Program Unit 大小。
status_t FLASH_DRV_Program( uint32_t dest, uint32_t size, const void * pData),dest 和 size 需要为 Program Unit 整数倍,pData 需要 4 字节对齐。
对Flash物理块的操作,在同一个时间,只能执行读取、写入或者擦除的任一操作,这就意味着用户在对一个物理块进行写入或者擦除操作时,不能读取Flash中的内容。也就是说,Flash在执行写入或者擦除的时候,处理器不能从Flash中继续读取程序执行代码,否则EFM模块会直接产生Bus Error(M0+中对应为hardfault)。这也是L系列MCU(仅有一块Flash物理存储块)在对Flash操作(包括DFlash)的时必须关闭中断的原因。
在ME的手册里面有一个地方值得注意一下,扇区擦除和块擦除时间一样,mcu支持一个block里面所有扇区一起选中擦除
YTM32 L 系列的芯片是 Cortex-M0+ 内核,不支持非对齐访问数据。传入 program 的 RAM buffer,注意需要 4 字节对齐
那么我怎么知道我的sector size和Program Unit多大呢,可以直接在YTM32B1LE0_features.h里面查看定义
地址保护
在默认情况下,EFM_PROTn寄存器中的所有寄存器位均为1,表示对应的存储区域可以正常擦写。一旦其中某个寄存器位被清零,表示对应的存储区域(2K)被保护起来,向这些区域的读写操作将被EFM忽视掉。
在程序运行过程中,只能对flash上锁,不能解锁,也就是说只能将ADDR_PROT寄存器清零,不能重新置位,想要重新置位必须重启
分享几个EFM调试过程中ACCERR被置1后的分析思路:
- 擦写地址没对齐
- 擦写的过程中打开了debug工具的memory窗口
- 没有关全局中断
- 调试的时候在flash底层函数里面加了断点