You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在STM32H743XIH6的Cube IDE中向Flash写入变量

在STM32H743XIH6 Cube IDE中实现Flash变量掉电保存(C语言)

核心思路

STM32的Flash是只读存储,无法直接赋值修改,必须先擦除对应扇区,再写入数据。我们需要通过自定义Linker段将变量固定到Flash的空闲区域,再配合HAL库的Flash操作API完成读写。


步骤1:确定可用Flash区域

STM32H743XIH6的Flash总容量2MB,分为两个Bank:

  • Bank1:0x08000000 - 0x080FFFFF(通常用于存储程序代码)
  • Bank2:0x08100000 - 0x081FFFFF(默认未被程序占用,可用于存储非易失变量)

推荐选择Bank2的扇区24(起始地址0x08100000,大小128KB),可通过STM32H7参考手册RM0433确认扇区划分。


步骤2:修改Linker Script

在Cube IDE的项目中,打开STM32H743XIHx_FLASH.ld链接脚本,添加自定义段用于存放非易失变量:

/* 自定义非易失变量段 */
.nv_vars :
{
  . = ALIGN(4);          // 按4字节对齐
  *(.nv_vars)            // 匹配所有标记为.nv_vars的变量
  . = ALIGN(4);
} >FLASH AT>FLASH        // 指定段存放于Flash区域

确认MEMORY区块中的FLASH范围包含Bank2地址(默认配置已覆盖0x08000000到0x081FFFFF,无需额外修改)。


步骤3:声明Flash变量

使用__attribute__((section(".nv_vars")))将变量指定到自定义Flash段:

#include <stdint.h>

// 初始值会被烧录到Flash中,上电后直接读取
__attribute__((section(".nv_vars"))) int nv_int = 0;
__attribute__((section(".nv_vars"))) unsigned char nv_uchar = 0;
__attribute__((section(".nv_vars"))) uint8_t nv_uint8 = 0;

// 可选:用结构体统一管理所有非易失变量(更便于批量读写)
typedef struct {
    int nv_int;
    unsigned char nv_uchar;
    uint8_t nv_uint8;
} NV_Vars_t;
__attribute__((section(".nv_vars"))) NV_Vars_t nv_vars = {0, 0, 0};

步骤4:实现Flash操作函数

4.1 扇区擦除函数

Flash写入前必须先擦除对应扇区,擦除会清除整个扇区的数据:

#include "stm32h7xx_hal.h"

HAL_StatusTypeDef Flash_Erase_Bank2_Sector(uint32_t sector)
{
    FLASH_EraseInitTypeDef erase_init = {0};
    uint32_t sector_error = 0;

    erase_init.TypeErase = FLASH_TYPEERASE_SECTORS;
    erase_init.Banks = FLASH_BANK_2;                // 指定操作Bank2
    erase_init.Sector = sector;
    erase_init.NbSectors = 1;
    erase_init.VoltageRange = FLASH_VOLTAGE_RANGE_3; // 适配2.7V-3.6V电源(根据板子调整)

    HAL_FLASH_Unlock();                             // 解锁Flash
    HAL_StatusTypeDef status = HAL_FLASHEx_Erase(&erase_init, &sector_error);
    HAL_FLASH_Lock();                               // 操作完成后锁定Flash

    return status;
}

4.2 变量写入函数

Flash写入最小单位为32位(字),对于字节类型变量,需结合扇区擦除+批量写入避免数据丢失:

// 写入int类型变量
HAL_StatusTypeDef Flash_Write_Int(uint32_t flash_addr, int value)
{
    HAL_FLASH_Unlock();
    HAL_StatusTypeDef status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, flash_addr, (uint32_t)value);
    HAL_FLASH_Lock();
    return status;
}

// 更新uint8_t变量(需先保存其他变量值,擦除后重新写入)
void Update_NV_Uint8(uint8_t new_value)
{
    // 1. 保存当前扇区内的所有变量
    NV_Vars_t temp_vars = nv_vars;
    temp_vars.nv_uint8 = new_value;

    // 2. 擦除目标扇区
    if (Flash_Erase_Bank2_Sector(FLASH_SECTOR_24) != HAL_OK) {
        // 处理擦除错误(如打印日志、触发指示灯)
        return;
    }

    // 3. 重新写入所有变量
    Flash_Write_Int((uint32_t)&nv_vars, *(uint32_t*)&temp_vars);
    // 若结构体大于4字节,需分多次写入,或使用FLASH_TYPEPROGRAM_DOUBLEWORD写入64位数据
}

步骤5:读取变量

直接通过变量名读取即可,编译器会自动从Flash地址加载数据:

int current_int = nv_int;
uint8_t current_uint8 = nv_vars.nv_uint8;

关键注意事项

  1. Flash擦除寿命:Flash擦写次数约10万次,避免频繁写入(如每秒写入)。
  2. 解锁/锁定Flash:所有写操作前必须解锁,完成后立即锁定,防止误操作。
  3. 扇区占用检查:通过Cube IDE的Map文件确认自定义段未占用程序代码区域。
  4. 电源稳定性:Flash写入/擦除过程中不能掉电,否则会导致Flash损坏。

参考资料

  • ST官方STM32H743xx参考手册(RM0433):详细说明Flash控制器的寄存器配置与操作流程。
  • STM32Cube HAL库文档:查看FLASH模块的API参数与使用示例。
  • Cube IDE用户指南:了解链接脚本的结构与自定义段配置方法。

内容的提问来源于stack exchange,提问作者spino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 21:35:54