YTM32的Flash控制器EFM模块详解

YTM32的Flash控制器EFM模块详解

文章目录

  • YTM32的Flash控制器EFM模块详解
    • Flash存储器控制器EFM模块概述
      • YTM32的Flash存储器特性
      • Flash的约定术语
      • 存储器的地址空间及定义
    • 使用Flash存储器
      • 擦写Flash的操作流
      • 操作Flash的时长
    • EFM的其他关于Flash的“骚操作”
      • 交换启动操作(Boot Swap Operation)
      • 禁用调试端口和Flash保护
      • 地址保护
    • 参考文献

Flash存储器控制器EFM模块概述

Flash(闪存)是一种可擦除的只读存储器,按照实现方式和运行特性Flash一般还会分为NORNAND两种。其中NOR Flash支持随机地址的读取方式,在读取操作上类似于RAM,比较适合程序的直接读取运行,而NAND Flash读取是基于页的方式,一般无法随机读取。在微控制器中,Flash需要存储程序和数据,所以大多使用NOR Flash

YTM32的Flash存储器特性

YTM32系列MCU中通过Flash控制器EFM(Embedded Flash Module)控制管理Flash存储器,这里以ME0x系列MCU为例,EFM模块支持如下的一些功能:

  • 512KB x 2 的程序存储区域PFlash,带有ECC功能,Sector大小为2K
  • 256KB 单独的数据存储块DFlash,带有ECC功能,Sector大小为1K
  • 4KB的NVR区域,带有ECC功能,Sector大小为1K
  • 支持Flash按区域(16KB单位)的写保护功能。YTM32的M系列设计写保护固定为32x2个区域,总Flash
  • 支持配置禁用调试器
  • 支持产生Flash命令执行结束和异常中断
  • 支持Block Swap的OTA升级功能
  • 支持ECC错误地址记录和单比特、多比特中断
  • 支持OTP(One Time Program,一次可编程)区域
  • 支持HCU 密钥存储(可擦写,不可读取)
  • 支持块擦除、扇区(Sector)擦除和整个Chip的擦除操作
  • 最小写入页大小为 8 Bytes

Flash的约定术语

这里梳理使用Flash过程中常用的一些约定术语:

  • PFlash,程序Flash,实际也可以保存数据,属于基于应用场景的一种约定名称。
  • DFlash,数据Flash,实际也可以运行程序,属于基于应用场景的一种约定名称。
  • Block,Flash块的存储映射空间,表示物理上的一个Flash块(PFlash0、PFlash1、DFlash等),不同物理块的Flash相互之间可以支持Read While Write(RWW)特性。
  • Sector,扇区,是Flash擦除的最小单位,属于Flash的物理特性,软件无法修改。
  • Page,Flash 编程的最小单位,同样属于Flash物理特性,软件无法修改。
  • RWW,Read While Write,在运行擦除或者编程Flash的操作时,同时支持读Flash的操作。
  • ECC校验,纠错算法的一种,可以纠正单比特错误,检测多比特错误。

存储器的地址空间及定义

以ME0x微控制器为例,芯片系统存储的映射地址空间,如表x所示。

表x YTM32微控制器片内存储映射空间
Flash Device Name Address Space Size(KB) Block Protect
PFlash0 0x0000_0000 - 0x0007_FFFF 512 KB 0 ADDR_PROT0
PFlash1 0x0008_0000 - 0x000F_FFFF 512 KB 1 ADDR_PROT1
DFlash 0x0010_0000 - 0x0013_FFFF 256 KB 2 ADDR_PROT2
AES_NVR / HCU_NVR 0x1000_0000 - 0x1000_03FF 1 KB 0 No Read + Customer Key
OTP_NVR 0x1001_0000 - 0x1001_03FF 1 KB 0 No Erase
BOOT_NVR 0x1002_0000 - 0x1002_03FF 1 KB 1 SWAP CMD only
CUS_NVR 0x1003_0000 - 0x1003_03FF 1 KB 1 Customer Key

表x中PFlash0PFlash1是两个物理存储设备,可用于存储用户程序。当使用OTA应用时,这两个Block可以通过物理地址的重映射互换(BOOT_SWAP),方便实现应用升级。

AES_NVR(也有的手册上使用HCU_NVR的命名)主要用于保存HCU(硬件加密单元)中使用的密钥,该部分占用1KB空间,可以存放32 x 256 bit的密钥数据。为了可以保证密钥的安全,该部分区域支持用户的擦除和写入,但是不支持读取操作。当HCU需要使用密钥的时候,软件可以直接调用Flash的命令(Load AES Key (0x20))将需要用到的Key直接载入到HCU中使用,整个过程中,软件只能选择Key(的索引)而不能读取或者修改Key(的内容)。注意,对AES Key区域的写入和擦除操作,都需要先用Customer Key解锁(向EFM_CUS_KEY寄存器中写一次0x4dff32)。

OTP_NVR可以用于保存一次性可编程数据,OTP(One Time Program)区域的特点是,只能一次写入,不支持擦写和二次写入。在具体应用中,可以在该区域保存产品ID信息或者永久固化的信息。注意,对该区域的读取并没有限制。

BOOT_NVR可用来保存与OTA升级相关的数据,例如,当前作为Block0的PFlash索引,软件应该避免对该区域进行操作。

CUS_NVR包含Flash擦写保护配置和调试端口禁用的特定的数据标签(相当于是配置寄存器的值),用户可以向该区域的特定地址写入特定值,以启用对Flash的擦写保护和禁用调试端口。CUS_NVR的剩余部分是用户可以自由使用的,但对CUS_NVR的读写操作需要先通过写入Customer Key来解锁。

使用Flash存储器

读取(Read)、写入(Program)和擦除(Erase)是使用MCU内部集成Flash存储器的基本操作,Flash的特性是:擦除之后比特位的值变成1,写入操作是将相应的比特位的值改写成0。

由于YTM32的MCU的存储器都有ECC的机制,YTM32系列MCU都不支持二次写入操作(Re-Program),即不支持在Flash页的数据有非1的情况(已经被编程过)时再次对页编程。EFM外设在执行写入命令之前,会先从Flash中读取页数据,验证其数据为全1才能执行编程操作,否则若验证失败(无法通过ECC验证)则该页无法编程。

对Flash物理块的操作,在同一个时间,只能执行读取、写入或者擦除的任一操作,这就意味着用户在对一个物理块进行写入或者擦除操作时,不能读取Flash中的内容。也就是说,Flash在执行写入或者擦除的时候,处理器不能从Flash中继续读取程序执行代码,否则EFM模块会直接产生Bus Error(M0+中对应为hardfault)。这也是L系列MCU(仅有一块Flash物理存储块)在对Flash操作(包括DFlash)的时必须关闭中断的原因。

而M系列MCU内部集成了多块Flash物理存储块(MD集成了2个PFlash存储块,ME集成了2个PFlash存储块和1个DFlash存储块),在使用过程中,按照上述原则,虽然处理器在不能对同一个Block同时进行读写操作,但可以相互从操作,避开读写冲突,所以典型的使用方式有如下几种:

  1. PFlash0PFlash1用于保存程序和运行数据,DFlash用于保存Bootloader程序和模拟EEPROM的代码(模拟EEPROM的存储器在PFlash上)。这样,在Boot模式下,软件可以直接对两块PFlash进行读写操作而不必禁用系统中断;而在应用软件运行过程中,软件可以直接操作模拟EEPROM区域而不必禁用系统中断。
  2. 在上述配置的基础上使用OTA功能,PFlash0PFlash1分别保存一套程序代码,通过BOOT_SWAP指令,决定下次复位之后从哪个Block启动。当使用OTA功能的时候,当前Block运行的程序可以直接对另一个Block的Flash存储器进行擦写操作而不用关闭中断,因为这个时候软件是不会跳转到另外一个Block运行的,当然,如果软件在操作另外一个Block时,对这个Block的读操作也是不允许的。

擦写Flash的操作流

读取Flash的内容,只要按照常规访问存储空间的方式,使用地址寻址读数即可。无论是编译器,还是人为指定访问空间均可。

对于Flash的擦除和写入操作,则都是基于专门的命令来执行的,有命令清单如表x所示。

表x EFM模块操作Flash的命令列表
Code Description Need Address
0x02 Program 64 bits Y
0x03 Program 64bits and read back verify Y
0x10 Sector erase Y
0x11 Sector erase and verify Y
0x12 Erase block (only main array) Y
0x13 Erase block and then verify (only main array) Y
0x1E Erase chip N
0x20 Load AES Key N (Y in MD1)
0x30 Boot Swap N
0x40 Program NVR Y
0x41 Erase NVR Y
0x42 Read NVR Y

用户可以写这些命令到EFM_CMD[CMD]寄存器字段中生效。如图x所示。
YTM32的Flash控制器EFM模块详解_第1张图片

图x EFM CMD寄存器中可以生效的命令

表x中,需要传入地址的命令(Need Address一栏中为Y),获取地址参数的方式可分为两类:

  • 写PFlash和DFlash,是由EFM通过用户写特定地址的操作中提取出地址信息,作为EFM命令引擎中的地址参数。
  • 写NVR(各种NVR区域),通过向EFM_NVR_ADDR寄存器写地址值,再向EFM_NVR_DATA寄存器写将要写入的数值。之后再执行擦除或者写入NVR的命令。

以写入Flash的操作为例,执行一次64 bits数据的写入操作,并验证的命令流程如下:

  • 确认EFM的时钟参数设置合适,配置寄存器包括:EFM_TIMING1[TPREPROG]EFM_TIMING1[TPROG]EFM_TIMING2[TERASE]EFM_TIMING2[TERASE_RETRY]EFM_CTRL[PRESCALER]。(编程手册中并没有明确讲述确切的指标,但可参见SDK中的样例代码进行配置,大致是要确保操作Flash的时钟频率低于某个频率,24Mhz ???)。
  • 跳转到RAM中执行代码,并根据需要决定是否需要关闭全局中断。(如果是不同的Flash物理存储块之间相互操作,就不需要将代码复制到RAM中了,也不需要关中断)
  • 读取EFM_STS寄存器,判断EFM在当前是否正在执行命令。如果正忙就原地等一等。
  • 向需要写入Flash存储器的地址写入64bit长度数据。此时,将要写入的地址和数据,都被缓存在EFM的缓冲区中。
  • 0xfd9573f5EFM_CMD_UNLOCK寄存器,解锁EFM的命令引擎。每次解锁后只能执行一次命令,然后自动上锁。
  • 0x03EFM_CMD寄存器,开始执行写入并验证的命令。
  • 轮询读取EFM_STS寄存器,等待命令执行结束,并验证命令执行结果正常。

注意,若是执行擦除操作,用户仍需要通过写数到Flash地址空间的方式传入将要擦除Sector的地址,其中写数操作的数值无所谓,例如在SDK的驱动中,就随便用了一个0x12345678

操作Flash的时长

有些应用中对于Flash的写入和擦写的时间比较敏感,需要通过配合其他功能的时序完成功能,此处列写Flash基本操作的典型时间参数。如表x所示。

图x Flash操作的典型时长
操作 M系列 L系列
Sector Erase 16ms 4.5ms
Block Erase 16ms 35ms
Chip Erase 16ms 35ms
Page Program 45us 50us

操作Flash的时间同预分频和EFM_TIMING寄存器配置有关,上述表格的数据是在Prescaler预分频正确配置和TIMING保持默认值下的数据(参见SDK代码中的配置)。

M系列MCU擦除的时间都是16ms,Flash array支持多扇区同时擦写,所以整个Block块甚至整个芯片的擦除时间都是16ms,当采用Erase Retry的擦除方式时,EFM会按照800us的周期对Flash进行擦除尝试,这种方式下擦写的时间是800us~16ms。Erase Retry仅支持单个Sector的擦写。

L系列MCU只有一个Block的缘故,Block Erase和Chip Erase并没有什么区别,也不支持erase retry功能,另外L系列的DFlash实际和PFlash属于同一个Block,所以对DFlash进行擦写操作时候,也不支持对PFlash进行读操作。因此用DFlash模拟eeprom的时,仍然需要禁用系统中断。

EFM的其他关于Flash的“骚操作”

交换启动操作(Boot Swap Operation)

YTM32的两块PFlash(PFlash0PFlash1)会映射到两个地址Block块(Block0Block1),并且按照顺序映射地址空间。

在默认情况下,访问Block0的地址区间,在物理上就是访问PFlash0存储器。但若执行了BOOT_SWAP命令后(向EFM_CMD[CMD]寄存器字段中写命令码0x30,如图x所示),再复位重新上电,则会交换地址空间向PFlash0PFlash1的映射区间,Block0将会映射到PFlash1Block1将会映射到PFlash0
YTM32的Flash控制器EFM模块详解_第2张图片

图x 向`EFM_CMD`寄存器中写`BOOT_SWAP`命令

当执行了BOOT_SWAP命令后,可通过查看标志位置位EFM_STS[BOOT_INFO]=1,确认BOOT_SWAP命令已生效。

当再次向EFM发送BOOT_SWAP命令后,两个Flash的Block块地址映射会再次反转,恢复成默认的情况,同时标志位清零EFM_STS[BOOT_INFO]=0

需要特别注意的是,如果刚执行BOOT_SWAP命令后,标志位被置位EFM_STS[BOOT_INFO]=1,则CUS_NVR存储区中的数据将被清除,这就意味着用户需要重新配置其中的选项,包括禁用SWD端口和地址保护等功能。

禁用调试端口和Flash保护

为了保护用户的软件代码不会被恶意地读取到芯片外面(被破解),ME系列支持通过EFM模块禁用芯片调试端口,这个过程是在芯片执行ROM中的初始化过程中通过硬件操作序列生效的。同样,为了避免程序在运行过程中对Flash进行意外操作,Flash同样支持基于地址的擦写保护,应用程序可以根据实际应用需求限制。

在YTM32B1ME0x中,CUS_NVR的起始地址是0x1001_0000U ,这部分NVR区域中数据定义如下:

Region(32bits) Address Description
Debugger Disable Tag 0 0x10010000 TAG=0x5a5a5a5a Disable debugger
Debugger Disable Tag 1 0x10010004 TAG=0x5a5a5a5a Disable debugger
PROT0 Tag 0x10010008 TAG=0x5a5a5a5a
PROT0 Value 0x1001000C ADDR_PROT0 Init value
PROT1 Tag 0x10010010 TAG=0x5a5a5a5a
PROT1 Value 0x10010014 ADDR_PROT1 Init value
PROT2 Tag 0x10010018 TAG=0x5a5a5a5a
PROT2 Value 0x1001001C ADDR_PROT2 Init value
User NVR User can use other left space

因为NVR区域的页大小也是8 Bytes(64bits),实际单次至少写入两个32b字。例如,若需要在上电后禁用调试端口,需要向0x10010000U地址写入0x5a5a5a5a, 0x5a5a5a5a,如此,下次芯片复位后,调试端口默认就不会开启了。

需要特别注意,使用禁用JTAG/SWD模块的功能要特别小心,一旦关停之后,用户将不能通过调试器连处理器内核。建议用户在使用关停JTAG/SWD模块之前,先预留好“后门”,可通过使用其他通信端口的Bootloader更新Flash中的固件,或者能够通过预先准备好的程序擦除该区域以恢复使用JTAG/SWD模块。

表x中,ROT相应的tagvalue也是一起编程的,当tag匹配的时候(验证写数有效),下次上电对应的value就会自动载入到相应的寄存器(EFM_ADDR_PROT)实现对Flash的保护。

地址保护

可以通过配置EFM_PROTn寄存器(EFM_ADDR_PROTn),为Flash的地址存储区设置写保护,防止Flash中的关键存储区被意外篡改。以YTM32B1ME05 MCU为例,其中集成了1MB Flash存储区,设计了EFM_PROT0EFM_PROT1两个寄存器,分别对应两个地址块Block0和Block1,每个Block分为32个小块(对应EFM_PROTn寄存器中的每个寄存器位),每个小块对应16KB的存储区。

在默认情况下,EFM_PROTn寄存器中的所有寄存器位均为1,表示对应的存储区域可以正常擦写。一旦其中某个寄存器位被清零,表示对应的存储区域被保护起来,向这些区域的读写操作将被EFM忽视掉。

这组寄存器有Flash的特性,即仅能从1写0,不能从0写1。实际上,EFM_PROTn寄存器的物理存储地址,就映射在CUR_NVM区域中。因此,向EFM_PROTn寄存器中写数的方式有两种:

  • 直接向EFM_PROTn寄存器中写数。
  • CUR_NVM区域中偏移地址为0x10、0x18的区域中写入值,这些值将作为EFM_PROTn寄存器的初值(在上电复位后生效),每次写入的值都是64位,其中高32位必须为0x5A5A5A5A,低32位则位数则为指定的设置值。

参考文献

  • YTM32B1ME0x_RM_v1.3.pdf
  • 《YTM32系列MCU Flash模块功能详解》,https://www.linmingjie.cn/index.php/archives/378/

你可能感兴趣的:(YTM32,YTM32,Flash,MCU)