CIU32 Flash — 页擦除 + 字编程

CIU32 CIU32F003_STDLib V1.0.3 Flash 页擦除与字编程示例教学

Flash — 页擦除 + 字编程(Flash_PageErase_WordProgram)

固件库: CIU32F003_STDLib V1.0.3 芯片: CIU32F003(Cortex-M0) 源文件: CIU32/CIU32F003_STDLib_V1.0.3/Projects/FLASH/Flash_PageErase_WordProgram/Source/


一、功能简介

本示例演示内部 Flash 的擦除与编程:在第 32 页(起始地址 0x4000)上, 先把整页擦除,再连续写入 32 个字(每个字 4 字节,内容 0x5A5A5A5A), 每写一个字就读回校验是否正确,最后把 Flash 控制寄存器重新加锁。 这是把 Flash 当“掉电保存的数据区”使用的最标准流程。

务必注意:示例写入的是代码区之外的用户页(0x4000 起)。千万不要擦写正在运行程序的地址,否则会跑飞!

二、硬件准备

  • CIU32F003 开发板
  • 下载器(如 CMSIS-DAP / J-Link)用于烧录与在线调试
  • 可用调试器“Memory”窗口观察 0x4000 处的数据变化

关键参数(来自 main.c 宏定义):

1
2
3
4
#define PAGE_WORD_COUNT          (0x20)    /* 编程 32 个字 = 128 字节 */
#define FLASH_PAGE_NUM           (0x20)    /* 第 32 页 */
#define FLASH_ERASE_PROGRAM_ADDR (FLASH_MEM_BASE + (FLASH_PAGE_NUM * 0x200))
/* 0x200 = 512 字节/页 → 地址 = 0 + 32*512 = 0x4000 */

三、完整代码

3.1 主流程 main.c

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include "main.h"

#define PAGE_WORD_COUNT          (0x20)
#define FLASH_PAGE_NUM           (0x20)
#define FLASH_ERASE_PROGRAM_ADDR (FLASH_MEM_BASE + (FLASH_PAGE_NUM * 0x200))

int main(void)
{
    uint32_t program_data;
    uint32_t word_count;

    system_clock_config();                 /* 系统时钟 RCH 48MHz */

    program_data = 0x5A5A5A5A;             /* 要写入的数据 */

    std_flash_clear_flag(FLASH_FLAG_EOP | FLASH_FLAG_WRPERR); /* ① 清旧标志 */
    std_flash_unlock();                    /* ② 解锁 Flash 控制寄存器 */

    /* ③ 页擦除 */
    if (STD_OK != std_flash_erase(FLASH_MODE_PAGE_ERASE, FLASH_ERASE_PROGRAM_ADDR))
    {
        error_process();                   /* 擦除失败进入异常处理 */
    }

    /* ④ 字编程 + 立即校验 */
    for (word_count = 0; word_count < PAGE_WORD_COUNT; word_count++)
    {
        if (STD_OK != std_flash_word_program(
                (FLASH_ERASE_PROGRAM_ADDR + (word_count << 2)), program_data))
        {
            error_process();               /* 编程失败 */
        }
        /* 读回刚写的字进行校验 */
        if (*(uint32_t *)(FLASH_ERASE_PROGRAM_ADDR + (word_count << 2)) != program_data)
        {
            error_process();               /* 校验不一致,异常处理 */
        }
    }

    std_flash_lock();                      /* ⑤ 重新加锁,防止误写 */

    while (1) { }
}

3.2 异常处理 common.c(节选)

1
2
3
4
5
/* 用户自定义异常处理:卡死在此,便于调试定位 */
void error_process(void)
{
    while (1) { }
}

四、代码分段讲解

① 地址计算 word_count << 2word_count * 4(每个字 4 字节)。第 32 页起始 0x4000, 第 i 个字地址 = 0x4000 + i*4

② 解锁 / 加锁 Flash 控制寄存器上电后处于锁定状态,写/擦前必须 std_flash_unlock(), 操作结束后 std_flash_lock() 重新锁定,避免程序跑飞时意外改写 Flash。

③ 页擦除 Flash 只能“按页擦除、按字写”。写入前目标区必须是 0xFF...,所以先整页擦除。 std_flash_erase(FLASH_MODE_PAGE_ERASE, addr) 以页首地址为参数擦除整页(512 字节)。

④ 字编程与校验

  • std_flash_word_program(addr, data):向 addr 写入一个 32 位字;
  • 写完后用指针直接读回比较,确认写入成功(Flash 写慢,校验能及时发现写保护/寿命等问题);
  • 若返回非 STD_OK 或校验不符,进入 error_process() 卡死便于定位。

⑤ 标志位 开始时清掉 EOP(操作结束)与 WRPERR(写保护错误)标志,保证后续状态判断准确。

五、实验现象

  • 程序运行后,调试器查看 0x4000 ~ 0x407F:应全部为 5A 5A 5A 5A(小端排列);
  • 复位再运行,因先擦除后写入,数据保持一致;
  • error_process() 被触发(卡死),说明擦/写未成功(常见:地址落在受保护区或选项字节写保护)。

六、常见问题

现象 可能原因 解决办法
写入后读出不一致 没先擦除 写前必须整页擦除(Flash 只能 1→0)
擦除/编程返回错误 地址不在用户区/被写保护 选代码区外的页;检查选项字节
程序跑飞 擦写了正在运行的代码页 不要把 addr 指向当前程序所在页
反复写寿命耗尽 频繁擦写同一页 Flash 擦写次数有限(万次级),做磨损均衡/降低频率

七、小结

Flash 当 EEPROM 用的标准四步:解锁 → 页擦除 → 按字编程(并校验) → 加锁。 牢记三条铁律:① 最小擦除单位=页(512B);② 最小写入单位=字(4B);③ 写前必擦、写只能 1→0。

八、拓展应用

  • 保存校准参数/配置:上电从固定页读出,掉电不丢;
  • 实现“配置写入函数”:先备份整页到 RAM → 擦页 → 改后写回;
  • 修改读/写保护:配置选项字节(见 Flash_OptionByte_Update)。
世界是你们
使用 Hugo 构建
主题 StackJimmy 设计