[综合信息] IAP之-操作内部flash

[复制链接]
3757|0
Puchou 发表于 2025-9-4 17:11 | 显示全部楼层 |阅读模式
引言
在嵌入式系统开发中,为了实现设备功能的更新与维护,In - Application Programming(IAP)技术应运而生。IAP 允许设备在运行自身程序的过程中,对内部 Flash 进行编程操作,实现固件的升级等功能。操作内部 Flash 作为 IAP 技术的核心环节,对于实现高效、可靠的系统更新具有至关重要的意义。

IAP 技术概述
IAP,即在应用编程,其主要作用是在产品发布后,借助预留的通信接口,如串口、USB、以太网等,对产品中的固件程序进行便捷的更新升级。在典型的 IAP 实现方案中,固件程序通常包含两个部分:一部分负责通过特定通信方式接收程序或数据,并执行对另一部分代码的更新操作;另一部分则是实现设备实际功能的代码。这两部分代码共同存储于 User Flash 中。设备上电后,首先运行的是负责更新的那部分代码,它会执行诸如接收升级文件、验证数据完整性等操作,之后再将新的功能代码写入 Flash,完成升级流程。

内部 Flash 基础
内部 Flash 结构
不同型号的微控制器,其内部 Flash 的容量与结构存在差异。以 HC32F460 系列为例,其内部 Flash 容量丰富,常见的有 256KB、512KB 等规格。可以吧内部 Flash 空间划分为多个区域,例如 Bootloader 区域以及用户应用程序区域等,其中 Bootloader 所需空间相对较小。HC32F460 的 Flash 还具有扇区划分特点,不同扇区大小可能不同,这对后续的擦除等操作有重要影响。

Flash 编程原理
HC32F460 内部 Flash 的编程操作由 Flash 控制器负责管控。无论是数据写入还是擦除操作,都需要通过对 Flash 控制器的相关寄存器进行设置来实现。Flash 控制器包含多个寄存器,如 Flash 控制寄存器、Flash 状态寄存器等。当 HC32F460 上电复位后,Flash 控制器会自动处于锁定状态,此时无法对相关控制寄存器进行写入操作。若要进行 Flash 编程,首先需要解锁 Flash 控制器,通过向特定的解锁寄存器写入特定的键值来实现,以确保只有授权操作才能对 Flash 进行修改,从而保障 Flash 中数据的安全性。

操作内部 Flash 的流程
解锁 Flash 控制器
在对内部 Flash 进行任何写入或擦除操作之前,必须先解锁 Flash 控制器。以 HC32F460 为例,需要操作寄存器(EFM_FAPRT 先写 0x0123,再写 0x3210)。只有完成解锁操作,才能成功解锁 Flash 控制器,允许后续对 Flash 的操作。

擦除操作
由于 Flash 的写入特性,在写入新数据之前,需要先对目标存储区域进行擦除。内部 Flash 通常按扇区进行划分,擦除操作的最小单位即为扇区。HC32F460 的扇区一般为8kb。擦除操作步骤如下:

检查 Flash 状态寄存器的忙标志位,确认当前没有正在进行的 Flash 操作。只有当忙标志位为 0 时,才表示 Flash 处于空闲状态,可以进行新的操作。
将 Flash 控制寄存器的扇区擦除位置 1,选择以扇区为单位进行擦除操作。
通过相关寄存器指定要擦除的扇区地址。
将 Flash 控制寄存器的启动擦除位置 1,启动擦除操作。
等待 Flash 状态寄存器的忙标志位变为 0,表明擦除操作完成。
写入操作
在完成擦除操作后,即可进行数据写入。在写入数据时,需要注意以下几点:

写入地址需满足对齐要求,具体对齐方式根据 HC32F460 的 Flash 编程特性确定,一般以字或半字为单位对齐。
每次写入需按照规定的单位进行。
写入操作的步骤如下:

再次检查 Flash 状态寄存器的忙标志位,确保没有其他正在进行的内部 Flash 操作。
将 Flash 控制寄存器的编程位置 1,使能编程操作。
向指定的 Flash 存储器地址执行数据写入操作,例如使用相应的语句将数据写入指定地址。
等待 Flash 状态寄存器的忙标志位变为 0,确认写入完成。
写入完成后,将 Flash 控制寄存器的编程位清零,关闭编程功能。
代码实现示例(RT-Thread FAL 组件+LL库)
初始化示例
#include <fal.h>
#include "hc32f460.h"

#include "hc32_ll_efm.h"

//EFM基地址
#define FLASH_BASE_ADDR (0x40010400UL)
/**
* @brief 初始化Flash
* @return 0:成功
*/
static int init(void)
{
    uint32_t frmc_value = 0x00000000UL;

    // 设置 FLWT[3:0] 为 5 个等待周期(0101b)
    frmc_value |= (0x05UL << 4); // FLWT[3:0] 对应 b7-b4,所以左移 4 位

    // 写入 EFM_FRMC 寄存器
    *(volatile uint32_t *)(FLASH_BASE_ADDR + 0x08UL) |= frmc_value;

    return 0;
}



读取示例
/**
* @brief 读取Flash数据
* @param offset 相对于Flash起始地址的偏移量
* @param buf 数据缓冲区
* @param size 读取大小(字节)
* @return 实际读取大小
*/
static int read(long offset, uint8_t *buf, size_t size)
{
    // uint32_t addr = 0x00000000 + offset;
    uint32_t addr = hc32f460_onchip_flash.addr + offset;
    /* 直接读取Flash数据 */
    for (size_t i = 0; i < size; i++) {
        buf = *(volatile uint8_t *)(addr + i);
    }

    return size;
}



擦除函数示例
/**
* @brief 擦除Flash扇区
* @param offset 相对于Flash起始地址的偏移量
* @param size 擦除大小(字节)
* @return 实际擦除大小(-1:失败)
*/
static int erase(long offset, size_t size)
{
    // uint32_t addr = 0x00000000 + offset;
    uint32_t addr = hc32f460_onchip_flash.addr + offset;

    //关闭中断
    __disable_irq();

    EFM_FWMC_Cmd(ENABLE);

    /* 解锁EFM寄存器 */
    EFM_REG_Unlock();

    /* 擦除扇区 */
    EFM_SectorErase(addr);

    /* 锁定EFM寄存器 */
    EFM_REG_Lock();

     EFM_FWMC_Cmd(DISABLE);
    //开启中断
    __enable_irq();

    return size;
}



写入函数示例
/**
* @brief 写入Flash数据
* @param offset 相对于Flash起始地址的偏移量
* @param buf 待写入数据缓冲区
* @param size 写入大小(字节)
* @return 实际写入大小(-1:失败)
*/
static int write(long offset, const uint8_t *buf, size_t size)
{
    // uint32_t addr = 0x00000000 + offset;
    uint32_t addr = hc32f460_onchip_flash.addr + offset;
    //关闭中断
    __disable_irq();

    EFM_FWMC_Cmd(ENABLE);

    /* 解锁EFM寄存器 */
    EFM_REG_Unlock();

    EFM_Program(addr, (uint8_t *)buf, size);

    /* 锁定EFM寄存器 */
    EFM_REG_Lock();

    EFM_FWMC_Cmd(DISABLE);
    //开启中断
    __enable_irq();
    return size;
}



注意事项
Flash 寿命:Flash 具有一定的擦写寿命限制。频繁进行擦写操作会逐渐缩短其使用寿命。HC32F460 的 Flash 也不例外,在设计 IAP 系统时,需要充分考虑这一因素,合理规划数据存储与更新策略,尽量减少不必要的擦写操作。
操作同步:在执行 Flash 写操作时,任何对 Flash 的读操作都会受到影响,直到写操作完成后读操作才能正确进行。因此,在进行 IAP 操作时,必须确保每次操作的顺序正确性,在每次操作之前,都要等待上一次操作完成,才能开始新的操作,以避免数据冲突和错误。
空间管理:在使用内部 Flash 存储数据和程序时,需要仔细规划 Flash 空间的使用。HC32F460 的 Flash 有特定的地址范围和扇区划分,要避免因空间分配不合理导致程序无法正常更新或数据丢失。在进行 IAP 升级时,要确保新的固件程序有足够的空间写入,同时避免覆盖重要的系统数据和配置信息。
总结
IAP 技术中操作内部 Flash 是实现设备固件更新和功能升级的关键手段。以 HC32F460 为例,通过深入理解其内部 Flash 的结构与编程原理,严格按照解锁、擦除、写入和读取的操作流程,并注意相关的注意事项,开发者能够实现高效、可靠的 IAP 系统。这不仅有助于提升产品的可维护性和用户体验,还能为产品的持续改进和功能扩展提供有力支持。随着嵌入式技术的不断发展,IAP 操作内部 Flash 的技术也将不断演进,为嵌入式系统的开发带来更多的便利与创新。
————————————————
版权声明:本文为CSDN博主「时光呀时光慢慢走」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/XdaDC/article/details/149774684

您需要登录后才可以回帖 登录 | 注册

本版积分规则

77

主题

240

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部