# ef_flash **Repository Path**: YANFUBING/ef_flash ## Basic Information - **Project Name**: ef_flash - **Description**: No description available - **Primary Language**: C - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-22 - **Last Updated**: 2026-07-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # ef_flash — STM32 Flash 硬件抽象层 ## 概述 本模块为 STM32 片内 Flash 提供统一的硬件抽象层(HAL),屏蔽不同芯片的 Flash 操作差异,上层(EasyFlash / OTA / 文件系统)通过统一 API 操作 Flash,无需关心底层硬件细节。 ## 架构 ``` 上层 (EasyFlash / OTA / 文件系统) ↓ #include "hal_flash.h" ↓ 调用 hal_flash_read/write/erase (无 dev 参数) hal_flash (抽象层) — 单例管理 + 锁管理 + 参数校验 ↓ 通过唯一实例的内嵌 ops 调用 芯片驱动 (drv_stm32f4_flash / drv_stm32g4_flash / ...) ↓ #include "hal_flash_base.h" ↓ 调用 STM32 HAL 库 硬件 ``` **依赖方向(严格单向):** ``` hal_flash.h → hal_flash_base.h ← drv_stm32xx_flash.h (上层 API) (基础契约) (底层驱动) ``` - `hal_flash_base.h`:纯类型与接口定义,不声明任何 API 函数 - 芯片驱动只 include `hal_flash_base.h`,不依赖上层 API - 上层只 include `hal_flash.h`,不直接 include 芯片驱动头文件 **设计要点:** - 单例模式:编译时选型,运行时只有一个设备实例 - 芯片驱动内聚:每个驱动定义自己的 `xxx_dev` 设备实例(含 ops + caps + priv),HAL 层通过 extern 引用 - ops 内嵌:操作函数表直接内嵌在设备实例中,无额外指针跳转 - 锁与校验在 HAL 层统一处理,芯片驱动只做纯粹的硬件操作 ## 文件说明 | 文件 | 作用 | include | |------|------|---------| | `hal_flash_base.h` | 基础契约:类型定义 (err_t, caps_t, ops_t, dev_t) | `` 等 | | `hal_flash.h` | 上层 API:include base + API 声明 + 选型宏 | `hal_flash_base.h` | | `hal_flash.c` | 抽象层实现:单例引用、锁管理、参数校验、薄转发 | `hal_flash.h` + 芯片驱动 `.h` | | `drv_stm32f4_flash.h/c` | STM32F407 Flash 驱动(定义 `f4_dev`) | `hal_flash_base.h` | | `drv_stm32g4_flash.h/c` | STM32G474 Flash 驱动(定义 `g4_dev`) | `hal_flash_base.h` | ## 芯片选型 编译时通过宏选择目标芯片,未选中的驱动文件编译为空: ```cmake # CMakeLists.txt 中添加 target_compile_definitions(app PRIVATE HAL_FLASH_CHIP_STM32F4) # 或 target_compile_definitions(app PRIVATE HAL_FLASH_CHIP_STM32G4) ``` 若未定义任何选型宏,默认选择 `HAL_FLASH_CHIP_STM32F4`。 ## 快速上手 ### 1. 初始化 ```c #include "hal_flash.h" hal_flash_init(); ``` ### 2. 读 Flash ```c uint8_t buf[64]; hal_flash_err_t err = hal_flash_read(0x10000, buf, sizeof(buf)); ``` ### 3. 擦除 + 写入 ```c /* 计算擦除范围 (兼容不均匀扇区) */ size_t erase_size = 0; uint32_t cur = offset; while (cur < offset + len) { uint32_t blk = hal_flash_erase_size_at(cur); if (blk == 0) break; erase_size += blk; cur += blk; } hal_flash_erase(offset, erase_size); hal_flash_write(offset, data, len); ``` ### 4. 查询能力 ```c const hal_flash_caps_t *caps = hal_flash_get_caps(); printf("总容量: %lu KB\n", caps->total_size >> 10); printf("最小擦除块: %lu KB\n", caps->erase_size >> 10); printf("编程粒度: %u bit\n", caps->write_gran); ``` ### 5. 原子操作 (手动加锁) ```c hal_flash_lock(); hal_flash_erase(offset, erase_size); hal_flash_write(offset, data, len); hal_flash_unlock(); ``` ### 6. RTOS 锁替换 ```c void my_lock(void) { xSemaphoreTakeRecursive(mutex, portMAX_DELAY); } void my_unlock(void) { xSemaphoreGiveRecursive(mutex); } hal_flash_set_lock_cb(my_lock, my_unlock); hal_flash_init(); ``` ## API 列表 ### 基础操作 | API | 说明 | |-----|------| | `hal_flash_init()` | 初始化 Flash 设备 | | `hal_flash_read(offset, buf, size)` | 读取数据 | | `hal_flash_write(offset, buf, size)` | 写入数据 | | `hal_flash_erase(offset, size)` | 擦除区域 | | `hal_flash_cache_invalidate()` | 刷新缓存 | | `hal_flash_erase_size_at(offset)` | 查询指定偏移的擦除块大小 | ### 扩展操作 (H7 等芯片) | API | 说明 | |-----|------| | `hal_flash_write_protect(offset, size, enable)` | 设置/清除写保护 | | `hal_flash_crc_verify(offset, size, &crc)` | 硬件 CRC 校验 | | `hal_flash_otp_read(offset, buf, size)` | 读取 OTP 区域 | | `hal_flash_otp_write(offset, buf, size)` | 编程 OTP 区域 | | `hal_flash_erase_async(offset, size)` | 异步擦除 | ### 辅助 | API | 说明 | |-----|------| | `hal_flash_dev()` | 获取设备单例指针 | | `hal_flash_get_caps()` | 获取能力描述 | | `hal_flash_lock()` | 手动加锁 | | `hal_flash_unlock()` | 手动解锁 | | `hal_flash_set_lock_cb(lock, unlock)` | 替换锁回调 | | `hal_flash_set_event_cb(cb, arg)` | 注册事件回调 | ## 错误码 | 错误码 | 值 | 说明 | |--------|-----|------| | `HAL_FLASH_OK` | 0 | 成功 | | `HAL_FLASH_ERASE_ERR` | -1 | 擦除失败 | | `HAL_FLASH_READ_ERR` | -2 | 读取失败 | | `HAL_FLASH_WRITE_ERR` | -3 | 编程失败 | | `HAL_FLASH_PARAM_ERR` | -4 | 通用参数错误 | | `HAL_FLASH_OFFSET_ERR` | -5 | 偏移越界 | | `HAL_FLASH_ALIGN_ERR` | -6 | 未对齐 | | `HAL_FLASH_SIZE_ERR` | -7 | 大小非法 | | `HAL_FLASH_NOT_INIT_ERR` | -8 | 未初始化 | | `HAL_FLASH_ECC_ERR` | -9 | ECC 错误 | | `HAL_FLASH_WP_ERR` | -10 | 写保护失败 | | `HAL_FLASH_OTP_ERR` | -11 | OTP 操作失败 | | `HAL_FLASH_CRC_ERR` | -12 | CRC 校验失败 | ## 扩展新芯片 1. 新建 `drv_stm32h7_flash.h`,`#include "hal_flash_base.h"`,导出 `extern hal_flash_dev_t h7_dev` 2. 新建 `drv_stm32h7_flash.c`,实现各操作函数,定义 `h7_dev` 设备实例 3. 在 `hal_flash.h` 的选型宏中增加 `HAL_FLASH_CHIP_STM32H7` 分支 4. 在 `hal_flash.c` 中增加 `extern h7_dev` 和 `#define FLASH_DEV h7_dev` 驱动只需 include `hal_flash_base.h` 并定义一个 `hal_flash_dev_t` 设备实例: ```c #include "hal_flash_base.h" hal_flash_dev_t h7_dev = { .name = "stm32h7", .ops = { .init = h7_init, .read = h7_read, .write = h7_write, .erase = h7_erase, .erase_size_at = h7_erase_size_at, /* 可选 */ .cache_invalidate = h7_cache_invalidate, .write_protect = h7_write_protect, /* 可选 */ .crc_verify = h7_crc_verify, /* 可选 */ .otp_read = h7_otp_read, /* 可选 */ .otp_write = h7_otp_write, /* 可选 */ .erase_async = h7_erase_async, /* 可选 */ }, .caps = { .addr = 0x08000000U, .total_size = 0x00200000U, .erase_size = 0x20000U, .write_gran = 256, .erase_size_uniform = false, .has_ecc = true, .has_write_protect = true, .has_crc = true, }, .priv = &h7_priv, }; ```