执行任何Flash编程操作(擦除或编程)时,CPU时钟频率(HCLK)不能低于1 MHz。如果 在Flash 操作期间发生器件复位,无法保证Flash中的内容。

在对STM32F4的Flash 执行写入或擦除操作期间,任何读取Flash的尝试都会导致总线阻 塞。只有在完成编程操作后,才能正确处理读操作。这意味着,写/擦除操作进行期间不能从Flash中执行代码或数据获取操作。

STM32F4 用户闪存的编程一般由6个32位寄存器控制,他们分别是:

⚫ FLASH访问控制寄存器(FLASH_ACR)

⚫ FLASH秘钥寄存器(FLASH_KEYR)

⚫ FLASH选项秘钥寄存器(FLASH_OPTKEYR)

⚫ FLASH状态寄存器(FLASH_SR)

⚫ FLASH控制寄存器(FLASH_CR)

⚫ FLASH选项控制寄存器(FLASH_OPTCR) STM32F4 复位后,FLASH编程操作是被保护的,不能写入FLASH_CR寄存器;通过写入 特定的序列(0x45670123和0xCDEF89AB)到 FLASH_KEYR寄存器才可解除写保护,只有在 写保护被解除后,我们才能操作相关寄存器。 FLASH_CR的解锁序列为:

(1)写0x45670123到FLASH_KEYR

(2)写0xCDEF89AB到FLASH_KEYR

通过这两个步骤,即可解锁FLASH_CR,如果写入错误,那么FLASH_CR将被锁定,直 到下次复位后才可以再次解锁。

STM32F4 闪存的编程位数可以通过 FLASH_CR 的 PSIZE 字段配置,PSIZE 的设置必须 和电源电压匹配,见表:

一、Flash 操作的关键限制条件

  1. CPU 时钟要求执行 Flash 擦除 / 编程时,HCLK(CPU 时钟)不能低于 1 MHz,否则操作会失败,甚至可能损坏 Flash。
  2. 复位风险如果在 Flash 操作过程中发生复位,Flash 中的数据 / 代码可能会损坏,因此操作时要尽量避免复位或断电。
  3. 总线阻塞问题在擦除 / 写入期间,任何对 Flash 的读取操作都会导致总线阻塞,直到操作完成才能恢复。这意味着:
    • 不能在擦除 / 写入时,同时从 Flash 中执行代码或读取数据
    • 通常需要把擦除 / 写入的关键代码放到 RAM 中执行,避免 “操作期间读取 Flash” 导致死锁

二、Flash 编程控制寄存器解析

STM32F4 的 Flash 操作主要由 6 个 32 位寄存器控制,每个寄存器的作用如下:

寄存器名 核心作用
FLASH_ACR Flash 访问控制寄存器,配置等待周期(LATENCY)、预取缓冲、缓存等
FLASH_KEYR Flash 密钥寄存器,用于解锁 Flash 写保护,必须按顺序写入特定密钥
FLASH_OPTKEYR 选项字节密钥寄存器,用于解锁选项字节的修改权限
FLASH_SR Flash 状态寄存器,标记操作是否完成、是否发生错误(如编程错误、擦除错误)
FLASH_CR Flash 控制寄存器,控制擦除 / 编程操作的启动、扇区选择、操作类型(字 / 半字 / 字节)
FLASH_OPTCR 选项控制寄存器,配置读保护、BOR 级别、看门狗等选项字节参数

三、Flash 编程的标准流程(关键步骤)

结合这些寄存器,Flash 擦除 / 写入的标准流程是:

  1. 解锁 Flash 写保护FLASH_KEYR 依次写入密钥 KEY1 = 0x45670123KEY2 = 0xCDEF89AB,解除 Flash 的写保护。
  2. 等待 Flash 操作空闲检查 FLASH_SR 寄存器的 BSY 位,确保没有正在进行的 Flash 操作。
  3. 擦除目标扇区FLASH_CR 中设置:
    • SER 位(扇区擦除模式)
    • SNB 位(选择要擦除的扇区号)
    • STRT 位(启动擦除)等待擦除完成(检查 BSY 位)。
  4. 写入数据FLASH_CR 中设置:
    • PG 位(编程模式)
    • PSIZE 位(设置数据宽度:字节 / 半字 / 字)向目标地址写入数据,等待操作完成。
  5. 上锁 Flash操作完成后,向 FLASH_CRLOCK 位写 1,重新锁定 Flash,防止意外修改。

四、关键注意事项

  • 擦除是前提:Flash 只能把位从 1 改成 0,要修改已写入的数据,必须先擦除整个扇区(擦除会把扇区所有位恢复为 1)。
  • 地址对齐:写入数据的地址必须和数据宽度对齐(如 32 位写入时,地址必须是 4 字节对齐)。
  • 错误处理:操作后要检查 FLASH_SR 的错误标志(如 PGERRWRPERR),及时处理编程错误或写保护错误。

补充:

一.编程位数是什么?

编程位数(也叫并行位数 / PSIZE),是 STM32F4 Flash 写入操作时,一次能同时写入的数据宽度,它决定了每次编程操作的效率和硬件支持的电压范围。

1. 核心概念

PSIZEFLASH_CR 寄存器里的配置位,它的取值和供电电压强绑定,不同电压下,Flash 控制器能支持的 “并行写入位数” 不同:

  • PSIZE=00(x8):一次写入 8 位(1 字节),仅在 1.8V~2.1V 下支持
  • PSIZE=01(x16):一次写入 16 位(半字),仅在 2.1V~2.7V 下支持
  • PSIZE=10(x32):一次写入 32 位(字),仅在 2.7V~3.6V 下支持(开发板常用 3.3V 时用这个)
  • PSIZE=11(x64):一次写入 64 位(双字),仅在 2.7V~3.6V 且使用外部高压 Vpp 时支持

2. 为什么要这么设计?

Flash 存储单元的编程操作需要特定的电压和电流条件,供电电压越高,控制器能驱动的并行单元越多,一次写入的数据宽度就越大:

  • 电压低时,只能提供较弱的编程电流,一次只能驱动 8 位 / 16 位单元
  • 电压高时(如 3.3V),可以提供足够的电流,一次驱动 32 位甚至 64 位单元
  • 外部高压 Vpp 模式下,能提供更高的编程电压,支持 64 位并行写入,效率最高

3. 实际开发中的影响

  1. 写入效率并行位数越高,写入速度越快:

    • 同样写入 4 字节数据,x32 模式下只需要 1 次操作,x8 模式下需要 4 次操作
    • 开发板 3.3V 供电时,设置 PSIZE=10(x32)是效率最高的选择
  2. 地址对齐要求写入地址必须和并行位数对齐:

    • x32 模式:写入地址必须是 4 字节对齐(地址末 2 位为 0)
    • x16 模式:写入地址必须是 2 字节对齐(地址末 1 位为 0)
    • x8 模式:无对齐要求(可写入任意地址)
  3. 电压匹配限制必须严格按照表格设置 PSIZE

    • 3.3V 供电设置 PSIZE=10(x32),如果强行设置 PSIZE=11(x64),在无外部 Vpp 时会导致写入失败
    • 低电压下强行设置高并行位数,会因为电流不足导致写入错误或 Flash 损坏

    4. 代码配置示例(寄存器版)

// 解锁Flash
FLASH->KEYR = 0x45670123;
FLASH->KEYR = 0xCDEF89AB;

// 配置PSIZE(3.3V供电设置为x32,即PSIZE[1:0] = 10)
FLASH->CR &= ~(0x3 << 8); // 清除PSIZE位
FLASH->CR |= (0x2 << 8);  // 设置PSIZE=10(x32)

// 启动编程模式
FLASH->CR |= FLASH_CR_PG;

四.位数 和 地址 的强制规则(必须遵守)

规则 1:写多少位,地址就要按多少位对齐

编程位数 一次写多大 地址必须满足 例子(合法地址)
x8(8 位) 1 字节 任意地址 0x08000000、0x08000001、0x08000002
x16(16 位) 2 字节 地址能被 2 整除 0x08000000 ✅ 0x08000002 ✅
x32(32 位) 4 字节 地址能被 4 整除 0x08000000 ✅ 0x08000004 ✅
x64(64 位) 8 字节 地址能被 8 整除 0x08000000 ✅ 0x08000008 ✅

最关键(你 99% 会用到)

3.3V + x32 模式👉 地址必须是 4 的倍数!👉 地址最后两位必须是 00例如:

  • 0x0800 0000 → ✅ OK
  • 0x0800 0004 → ✅ OK
  • 0x0800 0008 → ✅ OK
  • 0x0800 0001 → ❌ 错误!不对齐
Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐