日期:2025/04/07 13:23来源:未知 人气:59
本文将依据ST官方提供的Flash编程手册,即文档编号为PM0059的资料,详细阐述STM32F207内部Flash 的编程方法。本文所涉及的Flash,特指STM32F207内部集成的Flash存储器。这种Flash存储器具备以下显著特点:最大可达到1M字节的存储容量,128位,即16字节宽度的数据读取能力,以及字节、半字、字和双字的写入操作。此外,还支持扇区擦除和批量擦除功能。关于存储器的构成,它主要包括4个16K字节扇区、1个64K字节扇区和7个128K字节扇区。
特别值得一提的是,系统存储器 专为系统boot模式启动设备而设计,这部分由ST预先保留,并包含了bootloader程序。该程序通过USART1、USART3、CAN2以及USB OTG FS设备模式(支持DFU:设备固件升级)等接口对Flash进行编程。在制造期间,ST会编写boot程序,以确保防止错误的写入和擦除操作。512个OTP(一次性编程)字节被专门用于存储用户数据。此外,还提供了16个额外的字节来锁定相应的OTP数据,确保其安全性。同时,系统还支持选项字节的读写保护功能,以及BOR水平、软件/硬件看门狗和复位等设置,以适应不同的待机和停机状态。此外,低功耗模式也是一项重要功能,用户可参考相关手册的PWR部分进行详细了解。
系统存储器专门用于系统启动,包含bootloader程序,支持多种接口进行编程。此外,128位OTP功能 用于安全存储用户数据。
当BOOT0设置为0时,系统将从主存储区运行;而当BOOT0为1且BOOT1为0时,系统则会切换至系统存储区进行运行。值得注意的是,系统存储区中运行的是ST出厂的bootloader代码,该代码会跳过用户的代码。若因应用层代码锁定了JTAG管脚(即JTAG管脚被用作普通GPIO功能),我们可以通过调整boot管脚的状态,进入系统存储区,从而进行调试。
由于内置的Flash与CortexM3的数据总线相连,因此可以在通用地址空间内对其进行寻址。执行任何32位数据的读操作时 ,均可访问到Flash上的数据。以下是一个简单的读取操作示例:
data32 = (__IO uint32_t)Address;
在这段代码中,我们将Address地址强制转换为32位整型指针,然后通过该指针获取该地址处的值,从而读取到位于Address地址上的32位数据。
Flash擦除操作 可以针对特定的扇区进行,也可以对整个Flash进行批量擦除。在执行批量擦除时,需要确保不会误删OTP扇区或配置扇区中的数据。接下来,我们将详细介绍扇区擦除的具体步骤。
首先,需要检查FLASH_SR寄存器中的BSY位,以确保当前没有其他Flash操作正在执行。接着,在FLASH_CR寄存器中,将SER位置设置为1,并选择需要擦除的扇区(SNB),也就是主存储器块中的12个扇区之一。然后,将FLASH_CR寄存器中的STRT位置设置为1,以启动擦除操作。最后,需要等待BSY位清零,表示擦除操作已经完成。
接下来,我们可以进行批量擦除的操作。首先,需要再次确认FLASH_SR寄存器中的BSY位是否清零,以确保当前没有其他Flash操作正在执行。接下来,在FLASH_CR寄存器中,将MER位置设置为1,以启动批量擦除操作。随后,将STRT位置设置为1,以启动擦除过程。同样地,我们需要等待BSY位清零,这表示擦除操作已经全部完成。
此外,ST还提供了相应的库函数接口,以便更方便地进行擦除操作。这些接口包括FLASH_EraseSector和FLASH_EraseAllSectors,它们分别用于擦除单个扇区和所有扇区。需要注意的是,这些函数中有一个特殊的参数VoltageRange,这是因为在不同的电压范围内,Flash的擦除特性可能会有所不同。
由于在不同电压下,数据访问的位数会有所差异,而我们的系统是采用3.3V电压,因此每次读取数据时需要一次性读取32位。这样的设计是为了确保数据的完整性和准确性。
写入数据之前 ,必须先进行擦除操作,这一点与NorFlash的操作方式是相同的。复位后,Flash控制器的寄存器(FLASH_CR)会处于不允许写入的状态,这是为了保护Flash闪存免受电气原因导致的意外操作。下面将介绍解锁写入操作的步骤。
在Flash密钥寄存器(FLASH_KEYR)中,依次写入KEY1 = 0x45670123和KEY2 = 0xCDEF89AB。将FLASH_CR寄存器中的LOCK位置为1,以锁定寄存器。此时,可通过软件调用FLASH_Unlock()函数来解锁FLASH_CR寄存器。完成写入操作后,再次将FLASH_CR寄存器中的LOCK位置为1,以重新锁定寄存器。此时,软件可以调用FLASH_Lock()函数来完成上锁操作。
若对写入操作有较高要求,可启用中断功能。这样,一旦写入完成或出现错误,系统将作出相应中断响应。具体细节,请参阅Flash编程手册的第15.5章。
Flash存储器提供 了读写保护机制,这种保护机制主要通过特定的选项地址来实现。此外,还支持一次性编程保护,以确保数据的安全性。选项字节的组成结构如下:
在执行此扇区的任何操作之前,必须清除Flash选项控制寄存器(FLASH_OPTCR)中的选项锁定位(OPTLOCK)。为了能够清除该位,您需要执行以下步骤:在解锁Flash的过程中,需要向Flash选项密钥寄存器(FLASH_OPTKEYR)写入特定的数值。首先,写入OPTKEY1 = 0x0819 2A3B,接着写入OPTKEY2 = 0x4C5D 6E7F。完成这些步骤后,软件可以通过设置OPTLOCK位来保护用户选项字节,以防止意外的擦除或编程操作。值得注意的是,ST提供了相应的库函数来简化这一过程,包括FLASH_OB_Unlock和FLASH_OB_Lock,分别用于解锁和锁定Flash选项。
读保护分为三个等级 ,从无保护状态到调试禁止与芯片读保护,不同级别提供不同访问权限。详细说明如下:
当将0xAA写入读保护选项字节(RDP)时,即设定了读保护级别为0,意味着无保护状态。在此状态下,无论是在自举配置(如Flash用户自举、调试自举或RAM自举)中,用户均可执行与Flash或备份SRAM相关的所有读/写操作(前提是没有设置写保护)。
在擦除选项字节后,闪存默认进入读保护级别1状态。通过将任意值(不包含用于设置级别0和级别2的0xAA和0xCC)写入RDP选项字节,即可激活该读保护级别。设置读保护级别1后,将出现以下限制:
在启用等级2的读保护后,JTAG端口将被永久禁用,这意味着无法通过JTAG进行任何调试操作。此外,FLASH_OB_RDPConfig 和FLASH_OB_GetRDP 等库函数将用于配置和查询读保护状态。
各用户扇区具有写保护功能 ,其擦除或编程操作被写保护位所禁止。当扇区i的非写保护位nWRPi(其中0 ≤ i ≤ 11)处于低电平状态时,对该扇区的擦除或编程操作将被禁止。因此,若某个扇区处于写保护状态,则无法执行批量擦除操作。
写保护库函数:
void FLASH_OB_WRPConfig(uint32_t OB_WRP, FunctionalState NewState);
查询写保护状态库函数:
uint16_t FLASH_OB_GetWRP(void);