refactor: 完整C++面向对象重构(FlashManager)

This commit is contained in:
2026-04-26 22:26:54 +08:00
parent 128852dd0e
commit e369d1ccaf
4 changed files with 715 additions and 1614 deletions
-1375
View File
@@ -1,1375 +0,0 @@
#include "flash_driver.h"
#include "config.h"
#include <cstring>
#include <cstdio>
/* GD32F4xx头文件 */
#include "gd32f4xx.h"
#include "gd32f4xx_fmc.h"
/* SPI驱动层接口 */
#include "spi_driver.h"
/* 内部Flash私有数据结构体 */
typedef struct
{
uint32_t base_address; /* Flash基地址 */
bool write_enabled; /* 写使能状态 */
} internal_flash_private_t;
/* 外部SPI Flash私有数据结构体 */
typedef struct
{
bool write_enabled; /* 写使能状态 */
uint32_t manufacturer_id; /* 制造商ID */
uint32_t device_id; /* 设备ID */
} external_spi_flash_private_t;
/* 外部NOR Flash私有数据结构体 */
typedef struct
{
uint32_t exmc_bank; /* EXMC Bank编号 */
uint32_t base_address; /* 基地址 */
bool write_enabled; /* 写使能状态 */
} external_nor_flash_private_t;
/* 通用Flash私有数据联合体 */
typedef union
{
internal_flash_private_t internal;
external_spi_flash_private_t external_spi;
external_nor_flash_private_t external_nor;
} flash_private_data_t;
/* 静态函数声明 */
static ret_code_t init_external_spi_flash(flash_handle_t *handle);
static ret_code_t read_external_spi_flash(flash_handle_t *handle, uint32_t address, void *buffer, uint32_t length);
static ret_code_t write_external_spi_flash(flash_handle_t *handle, uint32_t address, const void *data, uint32_t length);
static ret_code_t erase_external_spi_flash_sector(flash_handle_t *handle, uint32_t address);
/* SPI辅助函数声明 */
static ret_code_t spi_flash_select(void);
static ret_code_t spi_flash_deselect(void);
static ret_code_t spi_flash_send_command(uint8_t cmd);
static ret_code_t spi_flash_read_status(uint8_t *status);
static ret_code_t spi_flash_wait_idle(void);
static ret_code_t spi_flash_write_enable(void);
/* 外部NOR Flash静态函数声明 */
static ret_code_t init_external_nor_flash(flash_handle_t *handle);
static ret_code_t read_external_nor_flash(flash_handle_t *handle, uint32_t address, void *buffer, uint32_t length);
static ret_code_t write_external_nor_flash(flash_handle_t *handle, uint32_t address, const void *data, uint32_t length);
static ret_code_t erase_external_nor_flash_sector(flash_handle_t *handle, uint32_t address);
/* 内部Flash定义 */
#define INTERNAL_FLASH_BASE_ADDR 0x08000000U
/* GD32F470ZGT6 Flash信息(1MB */
#define INTERNAL_FLASH_TOTAL_SIZE (1024 * 1024) /* 1MB */
#define INTERNAL_FLASH_SECTOR_SIZE (16 * 1024) /* 16KB扇区 */
#define INTERNAL_FLASH_PAGE_SIZE 256 /* 256字节页 */
#define INTERNAL_FLASH_BLOCK_SIZE (64 * 1024) /* 64KB块 */
/* Flash操作超时 */
#define FLASH_TIMEOUT 50000000U /* 进一步增加超时值,Flash扇区擦除可能需要200ms以上 */
/* 外部SPI Flash定义 (W25Qxx系列) */
#define EXTERNAL_SPI_FLASH_BASE_ADDR 0x00000000U
/* W25Qxx系列SPI Flash命令 */
#define SPI_FLASH_CMD_WRITE_ENABLE 0x06
#define SPI_FLASH_CMD_WRITE_DISABLE 0x04
#define SPI_FLASH_CMD_READ_STATUS_REG 0x05
#define SPI_FLASH_CMD_WRITE_STATUS_REG 0x01
#define SPI_FLASH_CMD_READ_DATA 0x03
#define SPI_FLASH_CMD_FAST_READ 0x0B
#define SPI_FLASH_CMD_PAGE_PROGRAM 0x02
#define SPI_FLASH_CMD_SECTOR_ERASE 0x20
#define SPI_FLASH_CMD_BLOCK_ERASE_32K 0x52
#define SPI_FLASH_CMD_BLOCK_ERASE_64K 0xD8
#define SPI_FLASH_CMD_CHIP_ERASE 0xC7
#define SPI_FLASH_CMD_POWER_DOWN 0xB9
#define SPI_FLASH_CMD_RELEASE_POWER_DOWN 0xAB
#define SPI_FLASH_CMD_READ_MANUFACTURER_ID 0x90
#define SPI_FLASH_CMD_READ_JEDEC_ID 0x9F
#define SPI_FLASH_CMD_READ_UNIQUE_ID 0x4B
/* W25Qxx状态寄存器位 */
#define SPI_FLASH_STATUS_BUSY (1 << 0)
#define SPI_FLASH_STATUS_WRITE_ENABLE (1 << 1)
#define SPI_FLASH_STATUS_BP0 (1 << 2)
#define SPI_FLASH_STATUS_BP1 (1 << 3)
#define SPI_FLASH_STATUS_BP2 (1 << 4)
#define SPI_FLASH_STATUS_BP3 (1 << 5)
#define SPI_FLASH_STATUS_SRWD (1 << 7)
/* 默认SPI Flash配置 (W25Q128FV - 16MB) */
#define EXTERNAL_SPI_FLASH_TOTAL_SIZE (16 * 1024 * 1024) /* 16MB */
#define EXTERNAL_SPI_FLASH_SECTOR_SIZE (4 * 1024) /* 4KB扇区 */
#define EXTERNAL_SPI_FLASH_PAGE_SIZE 256 /* 256字节页 */
#define EXTERNAL_SPI_FLASH_BLOCK_SIZE (64 * 1024) /* 64KB块 */
/* SPI Flash操作超时 */
#define SPI_FLASH_TIMEOUT 20000000U /* 增加超时时间,扇区擦除可能需要100ms以上 */
/* 默认内部Flash句柄 */
static flash_handle_t internal_flash_handle = {
.type = FLASH_TYPE_INTERNAL,
.config = {
.type = FLASH_TYPE_INTERNAL,
.base_address = INTERNAL_FLASH_BASE_ADDR,
.clock_freq = 0,
.cs_pin = 0,
.spi_port = 0,
.exmc_bank = 0},
.info = {
.total_size = INTERNAL_FLASH_TOTAL_SIZE, .sector_size = INTERNAL_FLASH_SECTOR_SIZE, .page_size = INTERNAL_FLASH_PAGE_SIZE, .block_size = INTERNAL_FLASH_BLOCK_SIZE, .manufacturer_id = 0x20, /* GD32制造商ID */
.device_id = 0x470 /* GD32F470 */
},
.initialized = false,
.private_data = NULL};
/* 默认外部SPI Flash句柄 (基于梁山派开发板实际硬件 - SPI4连接) */
static flash_handle_t external_spi_flash_handle = {
.type = FLASH_TYPE_EXTERNAL_SPI,
.config = {
.type = FLASH_TYPE_EXTERNAL_SPI,
.base_address = EXTERNAL_SPI_FLASH_BASE_ADDR,
.clock_freq = 1562500, /* APB2(100MHz)/64 = 1.5625MHz */
.cs_pin = GPIO_PIN_6, /* GPIOF PIN_6 (PF6 - 梁山派开发板硬件CS) */
.spi_port = 4, /* SPI4 (PF6-PF9复用映射) */
.exmc_bank = 0},
.info = {
.total_size = EXTERNAL_SPI_FLASH_TOTAL_SIZE, .sector_size = EXTERNAL_SPI_FLASH_SECTOR_SIZE, .page_size = EXTERNAL_SPI_FLASH_PAGE_SIZE, .block_size = EXTERNAL_SPI_FLASH_BLOCK_SIZE, .manufacturer_id = 0xEF, /* Winbond制造商ID */
.device_id = 0x4017 /* W25Q64设备ID (8MB,实际检测时修正) */
},
.initialized = false,
.private_data = NULL};
/* SPI Flash硬件引脚定义 (梁山派: PF6-CS, PF7-SCK, PF8-MISO, PF9-MOSI, SPI4, AF5) */
#define SPI_FLASH_CS_PORT GPIOF
#define SPI_FLASH_CS_PIN GPIO_PIN_6
/* SPI驱动对象 */
static SpiBus s_spi_flash_bus(SpiPort::_4);
static SpiDevice s_spi_flash_device(SPI_FLASH_CS_PORT, SPI_FLASH_CS_PIN);
/* 私有数据实例 */
static flash_private_data_t internal_flash_private;
static flash_private_data_t external_spi_flash_private;
/**
* @brief 等待Flash操作完成
* @param 无
* @return 操作结果
*/
static ret_code_t wait_flash_operation(void)
{
uint32_t timeout = FLASH_TIMEOUT;
while (fmc_flag_get(FMC_FLAG_BUSY) != RESET)
{
if (timeout-- == 0)
{
return RET_TIMEOUT;
}
}
/* 检查错误标志 */
if (fmc_flag_get(FMC_FLAG_OPERR) != RESET)
{
fmc_flag_clear(FMC_FLAG_OPERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_WPERR) != RESET)
{
fmc_flag_clear(FMC_FLAG_WPERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_PGMERR) != RESET)
{
fmc_flag_clear(FMC_FLAG_PGMERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_PGSERR) != RESET)
{
fmc_flag_clear(FMC_FLAG_PGSERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_RDDERR) != RESET)
{
fmc_flag_clear(FMC_FLAG_RDDERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_END) != RESET)
{
fmc_flag_clear(FMC_FLAG_END);
}
return RET_OK;
}
/**
* @brief 解锁内部Flash
* @param 无
* @return 操作结果
*/
static ret_code_t unlock_internal_flash(void)
{
/* 解锁主Flash */
fmc_unlock();
/* 解锁选项字节 */
ob_unlock();
/* 等待解锁完成 */
return wait_flash_operation();
}
/**
* @brief 锁定内部Flash
* @param 无
* @return 操作结果
*/
static ret_code_t lock_internal_flash(void)
{
fmc_lock();
ob_lock();
return RET_OK;
}
/**
* @brief 将内存地址转换为FMC扇区编号编码
* @param address 绝对内存地址 (如0x08000000)
* @return CTL_SN编码的扇区号,无效地址返回0xFFFFFFFF
*/
static uint32_t address_to_sector_code(uint32_t address)
{
uint32_t offset = address - INTERNAL_FLASH_BASE_ADDR;
uint32_t sector_num;
if (offset >= INTERNAL_FLASH_TOTAL_SIZE) {
return 0xFFFFFFFFU;
}
if (offset < 0x10000U) {
sector_num = offset / 0x4000U;
} else if (offset < 0x20000U) {
sector_num = 4;
} else {
sector_num = 5 + (offset - 0x20000U) / 0x20000U;
if (sector_num > 11) {
sector_num = 11;
}
}
return CTL_SN(sector_num);
}
/**
* @brief 擦除内部Flash扇区
* @param sector_address 扇区起始地址
* @return 操作结果
*/
static ret_code_t erase_internal_flash_sector(uint32_t sector_address)
{
ret_code_t ret;
uint32_t sector_code;
sector_code = address_to_sector_code(sector_address);
if (sector_code == 0xFFFFFFFFU) {
return RET_INVALID_PARAM;
}
ret = unlock_internal_flash();
if (ret != RET_OK) {
return ret;
}
fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR |
FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
fmc_sector_erase(sector_code);
ret = wait_flash_operation();
lock_internal_flash();
return ret;
}
/**
* @brief 写入内部Flash数据
* @param address 写入地址
* @param data 数据指针
* @param length 数据长度(字节)
* @return 操作结果
*/
static ret_code_t write_internal_flash(uint32_t address, const void *data, uint32_t length)
{
ret_code_t ret;
const uint8_t *src = (const uint8_t *)data;
uint32_t bytes_written = 0;
/* 检查地址对齐(字对齐,4字节) */
if ((address % 4) != 0)
{
return RET_INVALID_PARAM;
}
/* 检查数据长度对齐 */
if ((length % 4) != 0)
{
return RET_INVALID_PARAM;
}
/* 解锁Flash */
ret = unlock_internal_flash();
if (ret != RET_OK)
{
return ret;
}
/* 逐字写入 */
while (bytes_written < length)
{
uint32_t word_data;
/* 组装32位字 */
word_data = (uint32_t)src[bytes_written] |
((uint32_t)src[bytes_written + 1] << 8) |
((uint32_t)src[bytes_written + 2] << 16) |
((uint32_t)src[bytes_written + 3] << 24);
/* 写入Flash */
fmc_word_program(address + bytes_written, word_data);
/* 等待写入完成 */
ret = wait_flash_operation();
if (ret != RET_OK)
{
lock_internal_flash();
return ret;
}
bytes_written += 4;
}
/* 锁定Flash */
lock_internal_flash();
return RET_OK;
}
/**
* @brief 初始化内部Flash
* @param handle Flash句柄指针
* @return 操作结果
*/
static ret_code_t init_internal_flash(flash_handle_t *handle)
{
(void)handle; /* 目前不需要句柄特定配置 */
/* 解锁Flash以进行初始化 */
ret_code_t ret = unlock_internal_flash();
if (ret != RET_OK)
{
return ret;
}
/* 锁定Flash */
lock_internal_flash();
/* 初始化私有数据 */
internal_flash_private.internal.base_address = INTERNAL_FLASH_BASE_ADDR;
internal_flash_private.internal.write_enabled = false;
return RET_OK;
}
/* 公共函数实现 */
ret_code_t flash_init(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
return init_internal_flash(handle);
case FLASH_TYPE_EXTERNAL_SPI:
return init_external_spi_flash(handle);
case FLASH_TYPE_EXTERNAL_NOR:
return init_external_nor_flash(handle);
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_deinit(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
if (!handle->initialized)
{
return RET_NOT_INITIALIZED;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
/* 锁定Flash */
lock_internal_flash();
break;
case FLASH_TYPE_EXTERNAL_SPI:
break;
case FLASH_TYPE_EXTERNAL_NOR:
break;
default:
return RET_INVALID_PARAM;
}
handle->initialized = false;
handle->private_data = NULL;
return RET_OK;
}
ret_code_t flash_read(flash_handle_t *handle, uint32_t address, void *buffer, uint32_t length)
{
if (handle == NULL || buffer == NULL)
{
return RET_INVALID_PARAM;
}
if (length == 0)
{
return RET_OK;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
/* 内部Flash直接内存读取 */
uint32_t actual_address;
if (address < INTERNAL_FLASH_BASE_ADDR)
{
/* 相对地址 */
actual_address = INTERNAL_FLASH_BASE_ADDR + address;
}
else
{
/* 绝对地址 */
actual_address = address;
}
/* 检查地址范围 */
if (actual_address < INTERNAL_FLASH_BASE_ADDR ||
actual_address + length > INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE)
{
return RET_INVALID_PARAM;
}
/* 直接内存复制 */
memcpy(buffer, (void *)actual_address, length);
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI:
return read_external_spi_flash(handle, address, buffer, length);
case FLASH_TYPE_EXTERNAL_NOR:
return read_external_nor_flash(handle, address, buffer, length);
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_write(flash_handle_t *handle, uint32_t address, const void *data, uint32_t length)
{
if (handle == NULL || data == NULL)
{
return RET_INVALID_PARAM;
}
if (length == 0)
{
return RET_OK;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
uint32_t actual_address;
if (address < INTERNAL_FLASH_BASE_ADDR)
{
/* 相对地址 */
actual_address = INTERNAL_FLASH_BASE_ADDR + address;
}
else
{
/* 绝对地址 */
actual_address = address;
}
/* 检查地址范围 */
if (actual_address < INTERNAL_FLASH_BASE_ADDR ||
actual_address + length > INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE)
{
return RET_INVALID_PARAM;
}
/* 检查地址对齐 */
if ((actual_address % 4) != 0 || (length % 4) != 0)
{
return RET_INVALID_PARAM;
}
/* 写入Flash */
return write_internal_flash(actual_address, data, length);
}
case FLASH_TYPE_EXTERNAL_SPI:
return write_external_spi_flash(handle, address, data, length);
case FLASH_TYPE_EXTERNAL_NOR:
return write_external_nor_flash(handle, address, data, length);
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_erase(flash_handle_t *handle, uint32_t address, uint32_t size)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
if (size == 0)
{
return RET_OK;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
uint32_t actual_address;
if (address < INTERNAL_FLASH_BASE_ADDR)
{
/* 相对地址 */
actual_address = INTERNAL_FLASH_BASE_ADDR + address;
}
else
{
/* 绝对地址 */
actual_address = address;
}
/* 检查地址范围 */
if (actual_address < INTERNAL_FLASH_BASE_ADDR ||
actual_address + size > INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE)
{
return RET_INVALID_PARAM;
}
/* 检查大小对齐(扇区对齐) */
if ((actual_address % INTERNAL_FLASH_SECTOR_SIZE) != 0 ||
(size % INTERNAL_FLASH_SECTOR_SIZE) != 0)
{
return RET_INVALID_PARAM;
}
/* 擦除扇区 */
uint32_t sector_count = size / INTERNAL_FLASH_SECTOR_SIZE;
ret_code_t ret = RET_OK;
for (uint32_t i = 0; i < sector_count; i++)
{
ret = erase_internal_flash_sector(actual_address + i * INTERNAL_FLASH_SECTOR_SIZE);
if (ret != RET_OK)
{
return ret;
}
}
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI:
{
/* 检查大小对齐(扇区对齐) */
if ((address % EXTERNAL_SPI_FLASH_SECTOR_SIZE) != 0 ||
(size % EXTERNAL_SPI_FLASH_SECTOR_SIZE) != 0)
{
return RET_INVALID_PARAM;
}
/* 擦除扇区 */
uint32_t sector_count = size / EXTERNAL_SPI_FLASH_SECTOR_SIZE;
ret_code_t ret = RET_OK;
for (uint32_t i = 0; i < sector_count; i++)
{
ret = erase_external_spi_flash_sector(handle, address + i * EXTERNAL_SPI_FLASH_SECTOR_SIZE);
if (ret != RET_OK)
{
return ret;
}
}
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部NOR Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_erase_all(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
/* 擦除整个Flash */
return flash_erase(handle, INTERNAL_FLASH_BASE_ADDR, INTERNAL_FLASH_TOTAL_SIZE);
case FLASH_TYPE_EXTERNAL_SPI:
/* 擦除整个SPI Flash */
return flash_erase(handle, 0, EXTERNAL_SPI_FLASH_TOTAL_SIZE);
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部NOR Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_read_status(flash_handle_t *handle, uint32_t *status)
{
if (handle == NULL || status == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
/* 读取FMC状态寄存器 */
*status = FMC_STAT;
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI:
{
uint8_t status_byte;
ret_code_t ret = spi_flash_read_status(&status_byte);
if (ret == RET_OK)
{
*status = status_byte;
}
return ret;
}
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部NOR Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_write_enable(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
/* 内部Flash解锁即为写使能 */
return unlock_internal_flash();
}
case FLASH_TYPE_EXTERNAL_SPI:
{
return spi_flash_write_enable();
}
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部NOR Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_write_disable(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
/* 内部Flash锁定即为写禁用 */
return lock_internal_flash();
}
case FLASH_TYPE_EXTERNAL_SPI:
{
ret_code_t ret = spi_flash_send_command(SPI_FLASH_CMD_WRITE_DISABLE);
if (ret == RET_OK)
{
external_spi_flash_private.external_spi.write_enabled = false;
}
return ret;
}
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部NOR Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_get_info(flash_handle_t *handle, flash_info_t *info)
{
if (handle == NULL || info == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
/* 复制内部Flash信息 */
*info = internal_flash_handle.info;
return RET_OK;
case FLASH_TYPE_EXTERNAL_SPI:
/* 复制外部SPI Flash信息 */
*info = external_spi_flash_handle.info;
return RET_OK;
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部NOR Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_self_test(flash_handle_t *handle, uint32_t test_size)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
switch (handle->type)
{
case FLASH_TYPE_INTERNAL:
{
/* 选择测试区域(使用Flash末尾的16KB扇区) */
uint32_t test_address = INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE - INTERNAL_FLASH_SECTOR_SIZE;
/* 限制测试大小 */
if (test_size > INTERNAL_FLASH_SECTOR_SIZE)
{
test_size = INTERNAL_FLASH_SECTOR_SIZE;
}
/* 对齐到4字节 */
test_size = (test_size + 3) & ~3;
/* 测试缓冲区 */
uint8_t write_buffer[256];
uint8_t read_buffer[256];
/* 生成测试数据 */
for (uint32_t i = 0; i < sizeof(write_buffer); i++)
{
write_buffer[i] = (uint8_t)(i & 0xFF);
}
/* 擦除测试扇区 */
ret_code_t ret = flash_erase(handle, test_address, INTERNAL_FLASH_SECTOR_SIZE);
if (ret != RET_OK)
{
return ret;
}
/* 写入测试数据 */
ret = flash_write(handle, test_address, write_buffer, sizeof(write_buffer));
if (ret != RET_OK)
{
return ret;
}
/* 读取测试数据 */
ret = flash_read(handle, test_address, read_buffer, sizeof(read_buffer));
if (ret != RET_OK)
{
return ret;
}
/* 验证数据 */
if (memcmp(write_buffer, read_buffer, sizeof(write_buffer)) != 0)
{
return RET_ERROR;
}
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI:
case FLASH_TYPE_EXTERNAL_NOR:
/* 外部Flash暂不支持 */
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
ret_code_t flash_internal_default_init(void)
{
/* 使用默认句柄进行初始化 */
ret_code_t ret = flash_init(&internal_flash_handle);
if (ret == RET_OK)
{
internal_flash_handle.initialized = true;
internal_flash_handle.private_data = &internal_flash_private;
}
return ret;
}
/* SPI Flash辅助函数 */
/**
* @brief 选择SPI Flash芯片
* @param private_data 私有数据指针
* @return 操作结果
*/
static ret_code_t spi_flash_select(void)
{
gpio_bit_reset(SPI_FLASH_CS_PORT, SPI_FLASH_CS_PIN);
for (volatile uint32_t i = 0; i < 5000; i++)
;
printf("[SPI Flash] CS拉低 (选择芯片)\r\n");
return RET_OK;
}
static ret_code_t spi_flash_deselect(void)
{
gpio_bit_set(SPI_FLASH_CS_PORT, SPI_FLASH_CS_PIN);
for (volatile uint32_t i = 0; i < 5000; i++)
;
printf("[SPI Flash] CS拉高 (取消选择芯片)\r\n");
return RET_OK;
}
static ret_code_t spi_flash_send_command(uint8_t cmd)
{
printf("[SPI Flash] 发送命令: 0x%02X\r\n", cmd);
spi_flash_select();
BusTransfer tr = {&cmd, nullptr, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr);
spi_flash_deselect();
for (volatile uint32_t i = 0; i < 1000; i++)
;
return RET_OK;
}
static ret_code_t spi_flash_read_status(uint8_t *status)
{
if (status == NULL)
{
return RET_INVALID_PARAM;
}
spi_flash_select();
uint8_t cmd = SPI_FLASH_CMD_READ_STATUS_REG;
BusTransfer tr_cmd = {&cmd, nullptr, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_cmd);
uint8_t dummy = 0x00;
BusTransfer tr_data = {&dummy, status, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_data);
spi_flash_deselect();
return RET_OK;
}
static ret_code_t spi_flash_wait_idle(void)
{
uint32_t timeout = SPI_FLASH_TIMEOUT;
uint8_t status = 0;
uint32_t last_report = timeout;
printf("[SPI Flash] 开始等待Flash空闲 (超时: %lu)\r\n", timeout);
while (timeout-- > 0)
{
ret_code_t ret = spi_flash_read_status(&status);
if (ret != RET_OK)
{
printf("[SPI Flash] 读取状态寄存器失败: %d\r\n", ret);
return ret;
}
if ((status & SPI_FLASH_STATUS_BUSY) == 0)
{
printf("[SPI Flash] Flash已空闲,状态: 0x%02X, 剩余超时: %lu\r\n", status, timeout);
return RET_OK;
}
if ((timeout % 10000) == 0 && timeout != last_report)
{
printf("[SPI Flash] 等待Flash空闲,状态: 0x%02X, 剩余超时: %lu\r\n", status, timeout);
last_report = timeout;
}
}
printf("[SPI Flash] 等待Flash空闲超时,最终状态: 0x%02X\r\n", status);
return RET_TIMEOUT;
}
static ret_code_t spi_flash_write_enable(void)
{
spi_flash_select();
uint8_t cmd = SPI_FLASH_CMD_WRITE_ENABLE;
BusTransfer tr = {&cmd, nullptr, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr);
spi_flash_deselect();
for (volatile uint32_t i = 0; i < 1000; i++)
;
external_spi_flash_private.external_spi.write_enabled = true;
printf("[SPI Flash] 写使能命令已发送\r\n");
return RET_OK;
}
/**
* @brief 初始化外部SPI Flash
* @param handle Flash句柄指针
* @return 操作结果
*/
static ret_code_t init_external_spi_flash(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
external_spi_flash_private_t *private_data = &external_spi_flash_private.external_spi;
private_data->write_enabled = false;
printf("[SPI Flash] 配置SPI4引脚: PF6(CS), PF8(MISO), PF7(CLK), PF9(MOSI)\r\n");
printf("[SPI Flash] 使用AF5配置 (SPI4)\r\n");
SpiConfig config;
config.speed_hz = handle->config.clock_freq;
config.mode = 0;
config.data_width = 8;
ret_code_t ret = s_spi_flash_bus.init(config);
if (ret != RET_OK)
{
printf("[SPI Flash] SPI4初始化失败: %d\r\n", ret);
return ret;
}
s_spi_flash_device.init();
for (volatile uint32_t i = 0; i < 10000; i++)
;
printf("[SPI Flash] SPI4初始化完成\r\n");
printf("[SPI Flash] 执行SPI基本功能测试...\r\n");
uint8_t test_tx = 0x5A;
uint8_t test_rx = 0xFF;
BusTransfer tr_test = {&test_tx, &test_rx, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_test);
printf("[SPI Flash] SPI测试: 发送=0x%02X, 接收=0x%02X\r\n", test_tx, test_rx);
if (test_rx == 0xFF)
{
printf("[SPI Flash] 警告: 接收到0xFF,可能MISO线被拉高或未连接\r\n");
}
uint8_t tx_data[4] = {SPI_FLASH_CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00};
uint8_t rx_data[4] = {0xFF, 0xFF, 0xFF, 0xFF};
printf("[SPI Flash] 开始读取设备ID,命令: 0x%02X\r\n", SPI_FLASH_CMD_READ_JEDEC_ID);
spi_flash_select();
for (volatile uint32_t i = 0; i < 5000; i++)
;
BusTransfer tr_jedec = {tx_data, rx_data, 4, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_jedec);
for (volatile uint32_t i = 0; i < 1000; i++)
;
spi_flash_deselect();
for (volatile uint32_t i = 0; i < 1000; i++)
;
private_data->manufacturer_id = rx_data[1];
private_data->device_id = (rx_data[2] << 8) | rx_data[3];
printf("[SPI Flash] 读取结果 - 制造商ID: 0x%02lX, 设备ID: 0x%04lX\r\n",
private_data->manufacturer_id, private_data->device_id);
handle->info.manufacturer_id = private_data->manufacturer_id;
handle->info.device_id = private_data->device_id;
switch (private_data->device_id)
{
case 0x4017:
handle->info.total_size = 8 * 1024 * 1024;
printf("[SPI Flash] 检测到 W25Q64 (8MB)\r\n");
break;
case 0x4018:
handle->info.total_size = 16 * 1024 * 1024;
printf("[SPI Flash] 检测到 W25Q128 (16MB)\r\n");
break;
case 0x4019:
handle->info.total_size = 32 * 1024 * 1024;
printf("[SPI Flash] 检测到 W25Q256 (32MB)\r\n");
break;
default:
handle->info.total_size = EXTERNAL_SPI_FLASH_TOTAL_SIZE;
printf("[SPI Flash] 未知设备ID: 0x%04lX,使用默认容量 %lu MB\r\n",
private_data->device_id, handle->info.total_size / (1024 * 1024));
break;
}
handle->info.sector_size = EXTERNAL_SPI_FLASH_SECTOR_SIZE;
handle->info.page_size = EXTERNAL_SPI_FLASH_PAGE_SIZE;
handle->info.block_size = EXTERNAL_SPI_FLASH_BLOCK_SIZE;
return RET_OK;
}
static ret_code_t read_external_spi_flash(flash_handle_t *handle, uint32_t address, void *buffer, uint32_t length)
{
if (handle == NULL || buffer == NULL || length == 0)
{
return RET_INVALID_PARAM;
}
ret_code_t ret = spi_flash_wait_idle();
if (ret != RET_OK)
{
return ret;
}
uint8_t tx_buffer[4];
tx_buffer[0] = SPI_FLASH_CMD_READ_DATA;
tx_buffer[1] = (address >> 16) & 0xFF;
tx_buffer[2] = (address >> 8) & 0xFF;
tx_buffer[3] = address & 0xFF;
spi_flash_select();
BusTransfer tr_addr = {tx_buffer, nullptr, 4, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_addr);
BusTransfer tr_data = {nullptr, (uint8_t *)buffer, length, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_data);
spi_flash_deselect();
return RET_OK;
}
/**
* @brief 写入外部SPI Flash数据
* @param handle Flash句柄指针
* @param address 地址(相对地址)
* @param data 数据指针
* @param length 数据长度
* @return 操作结果
*/
static ret_code_t write_external_spi_flash(flash_handle_t *handle, uint32_t address, const void *data, uint32_t length)
{
if (handle == NULL || data == NULL || length == 0)
{
return RET_INVALID_PARAM;
}
const uint8_t *src = (const uint8_t *)data;
uint32_t page_size = EXTERNAL_SPI_FLASH_PAGE_SIZE;
uint32_t page_offset = address % page_size;
if (page_offset + length > page_size)
{
return RET_NOT_SUPPORTED;
}
ret_code_t ret = spi_flash_wait_idle();
if (ret != RET_OK)
{
return ret;
}
ret = spi_flash_write_enable();
if (ret != RET_OK)
{
return ret;
}
uint8_t tx_buffer[4 + page_size];
tx_buffer[0] = SPI_FLASH_CMD_PAGE_PROGRAM;
tx_buffer[1] = (address >> 16) & 0xFF;
tx_buffer[2] = (address >> 8) & 0xFF;
tx_buffer[3] = address & 0xFF;
for (uint32_t i = 0; i < length; i++)
{
tx_buffer[4 + i] = src[i];
}
spi_flash_select();
BusTransfer tr_write = {tx_buffer, nullptr, 4 + length, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_write);
spi_flash_deselect();
ret = spi_flash_wait_idle();
return ret;
}
/**
* @brief 擦除外部SPI Flash扇区
* @param handle Flash句柄指针
* @param address 扇区地址
* @return 操作结果
*/
static ret_code_t erase_external_spi_flash_sector(flash_handle_t *handle, uint32_t address)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
printf("[SPI Flash] 开始擦除扇区 0x%06lX\r\n", address);
ret_code_t ret = spi_flash_wait_idle();
if (ret != RET_OK)
{
printf("[SPI Flash] 等待空闲失败: %d\r\n", ret);
return ret;
}
printf("[SPI Flash] Flash空闲,开始写使能\r\n");
ret = spi_flash_write_enable();
if (ret != RET_OK)
{
printf("[SPI Flash] 写使能失败: %d\r\n", ret);
return ret;
}
uint8_t tx_buffer[4];
tx_buffer[0] = SPI_FLASH_CMD_SECTOR_ERASE;
tx_buffer[1] = (address >> 16) & 0xFF;
tx_buffer[2] = (address >> 8) & 0xFF;
tx_buffer[3] = address & 0xFF;
printf("[SPI Flash] 发送扇区擦除命令: 0x%02X 0x%02X 0x%02X 0x%02X\r\n",
tx_buffer[0], tx_buffer[1], tx_buffer[2], tx_buffer[3]);
spi_flash_select();
BusTransfer tr_erase = {tx_buffer, nullptr, 4, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_erase);
spi_flash_deselect();
printf("[SPI Flash] 扇区擦除命令已发送,等待擦除完成...\r\n");
ret = spi_flash_wait_idle();
if (ret != RET_OK)
{
printf("[SPI Flash] 等待擦除完成失败: %d\r\n", ret);
}
else
{
printf("[SPI Flash] 扇区擦除完成\r\n");
}
return ret;
}
ret_code_t flash_external_spi_default_init(void)
{
/* 使用默认句柄进行初始化 */
ret_code_t ret = flash_init(&external_spi_flash_handle);
if (ret == RET_OK)
{
external_spi_flash_handle.initialized = true;
external_spi_flash_handle.private_data = &external_spi_flash_private;
}
return ret;
}
flash_handle_t *flash_get_external_spi_handle(void)
{
if (!external_spi_flash_handle.initialized)
{
return NULL;
}
return &external_spi_flash_handle;
}
uint32_t flash_get_internal_base_address(void)
{
return INTERNAL_FLASH_BASE_ADDR;
}
uint32_t flash_get_internal_total_size(void)
{
return INTERNAL_FLASH_TOTAL_SIZE;
}
uint32_t flash_get_internal_sector_size(void)
{
return INTERNAL_FLASH_SECTOR_SIZE;
}
/* =============== 外部NOR Flash驱动实现 =============== */
/**
* @brief 初始化外部NOR Flash
* @param handle Flash句柄指针
* @return 操作结果
*/
static ret_code_t init_external_nor_flash(flash_handle_t *handle)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
/* 外部NOR Flash暂未实现,返回成功以允许编译 */
handle->initialized = true;
return RET_OK;
}
/**
* @brief 读取外部NOR Flash数据
* @param handle Flash句柄指针
* @param address 地址(相对地址)
* @param buffer 数据缓冲区
* @param length 数据长度
* @return 操作结果
*/
static ret_code_t read_external_nor_flash(flash_handle_t *handle, uint32_t address, void *buffer, uint32_t length)
{
if (handle == NULL || buffer == NULL || length == 0)
{
return RET_INVALID_PARAM;
}
/* 外部NOR Flash暂未实现 */
return RET_NOT_SUPPORTED;
}
/**
* @brief 写入外部NOR Flash数据
* @param handle Flash句柄指针
* @param address 地址(相对地址)
* @param data 数据指针
* @param length 数据长度
* @return 操作结果
*/
static ret_code_t write_external_nor_flash(flash_handle_t *handle, uint32_t address, const void *data, uint32_t length)
{
if (handle == NULL || data == NULL || length == 0)
{
return RET_INVALID_PARAM;
}
/* 外部NOR Flash暂未实现 */
return RET_NOT_SUPPORTED;
}
/**
* @brief 擦除外部NOR Flash扇区
* @param handle Flash句柄指针
* @param address 扇区地址
* @return 操作结果
*/
static ret_code_t erase_external_nor_flash_sector(flash_handle_t *handle, uint32_t address)
{
if (handle == NULL)
{
return RET_INVALID_PARAM;
}
/* 外部NOR Flash暂未实现 */
return RET_NOT_SUPPORTED;
}
-181
View File
@@ -1,181 +0,0 @@
#ifndef __FLASH_DRIVER_H__
#define __FLASH_DRIVER_H__
#include <cstdint>
#include "common_types.h"
/* Flash类型定义 */
typedef enum {
FLASH_TYPE_INTERNAL = 0, /* 内部Flash(片上Flash */
FLASH_TYPE_EXTERNAL_SPI, /* 外部SPI Flash */
FLASH_TYPE_EXTERNAL_NOR, /* 外部并行NOR Flash(通过EXMC */
FLASH_TYPE_MAX
} flash_type_t;
/* Flash操作模式定义 */
typedef enum {
FLASH_OP_READ = 0, /* 读取操作 */
FLASH_OP_WRITE, /* 写入操作 */
FLASH_OP_ERASE, /* 擦除操作 */
FLASH_OP_READ_STATUS, /* 读取状态寄存器 */
FLASH_OP_WRITE_ENABLE, /* 写使能 */
FLASH_OP_WRITE_DISABLE, /* 写禁用 */
FLASH_OP_MAX
} flash_operation_t;
/* Flash容量信息结构体 */
typedef struct {
uint32_t total_size; /* 总容量(字节) */
uint32_t sector_size; /* 扇区大小(字节) */
uint32_t page_size; /* 页大小(字节) */
uint32_t block_size; /* 块大小(字节) */
uint32_t manufacturer_id; /* 制造商ID */
uint32_t device_id; /* 设备ID */
} flash_info_t;
/* Flash配置结构体 */
typedef struct {
flash_type_t type; /* Flash类型 */
uint32_t base_address; /* 基地址(对于内部Flash是0x08000000 */
uint32_t clock_freq; /* 时钟频率(Hz,仅对外部Flash有效) */
uint32_t cs_pin; /* 片选引脚(仅对外部SPI Flash有效) */
uint32_t spi_port; /* SPI端口(仅对外部SPI Flash有效) */
uint32_t exmc_bank; /* EXMC Bank(仅对外部NOR Flash有效) */
} flash_config_t;
/* Flash句柄结构体 */
typedef struct {
flash_type_t type; /* Flash类型 */
flash_config_t config; /* Flash配置 */
flash_info_t info; /* Flash信息 */
bool initialized; /* 初始化标志 */
void *private_data; /* 私有数据指针 */
} flash_handle_t;
/* 函数声明 */
/**
* @brief 初始化Flash
* @param handle Flash句柄指针
* @return 操作结果
*/
ret_code_t flash_init(flash_handle_t *handle);
/**
* @brief 反初始化Flash
* @param handle Flash句柄指针
* @return 操作结果
*/
ret_code_t flash_deinit(flash_handle_t *handle);
/**
* @brief 读取Flash数据
* @param handle Flash句柄指针
* @param address 地址(绝对地址或相对地址,取决于Flash类型)
* @param buffer 数据缓冲区
* @param length 数据长度(字节)
* @return 操作结果
*/
ret_code_t flash_read(flash_handle_t *handle, uint32_t address, void *buffer, uint32_t length);
/**
* @brief 写入Flash数据
* @param handle Flash句柄指针
* @param address 地址(绝对地址或相对地址,取决于Flash类型)
* @param data 数据指针
* @param length 数据长度(字节)
* @return 操作结果
*/
ret_code_t flash_write(flash_handle_t *handle, uint32_t address, const void *data, uint32_t length);
/**
* @brief 擦除Flash扇区
* @param handle Flash句柄指针
* @param address 扇区起始地址
* @param size 擦除大小(字节),必须为扇区大小的整数倍
* @return 操作结果
*/
ret_code_t flash_erase(flash_handle_t *handle, uint32_t address, uint32_t size);
/**
* @brief 擦除整个Flash
* @param handle Flash句柄指针
* @return 操作结果
*/
ret_code_t flash_erase_all(flash_handle_t *handle);
/**
* @brief 读取Flash状态寄存器
* @param handle Flash句柄指针
* @param status 状态值输出指针
* @return 操作结果
*/
ret_code_t flash_read_status(flash_handle_t *handle, uint32_t *status);
/**
* @brief 写使能
* @param handle Flash句柄指针
* @return 操作结果
*/
ret_code_t flash_write_enable(flash_handle_t *handle);
/**
* @brief 写禁用
* @param handle Flash句柄指针
* @return 操作结果
*/
ret_code_t flash_write_disable(flash_handle_t *handle);
/**
* @brief 读取Flash信息
* @param handle Flash句柄指针
* @param info Flash信息输出指针
* @return 操作结果
*/
ret_code_t flash_get_info(flash_handle_t *handle, flash_info_t *info);
/**
* @brief 验证Flash读写功能
* @param handle Flash句柄指针
* @param test_size 测试数据大小(字节)
* @return 操作结果
*/
ret_code_t flash_self_test(flash_handle_t *handle, uint32_t test_size);
/**
* @brief 默认内部Flash初始化
* @return 操作结果
*/
ret_code_t flash_internal_default_init(void);
/**
* @brief 默认外部SPI Flash初始化
* @return 操作结果
*/
ret_code_t flash_external_spi_default_init(void);
/**
* @brief 获取内部Flash基地址
* @return 内部Flash基地址(0x08000000
*/
uint32_t flash_get_internal_base_address(void);
/**
* @brief 获取内部Flash总大小
* @return 内部Flash总大小(字节)
*/
uint32_t flash_get_internal_total_size(void);
/**
* @brief 获取内部Flash扇区大小
* @return 内部Flash扇区大小(字节)
*/
uint32_t flash_get_internal_sector_size(void);
/**
* @brief 获取默认外部SPI Flash句柄指针
* @return Flash句柄指针,如果未初始化则返回NULL
*/
flash_handle_t *flash_get_external_spi_handle(void);
#endif /* __FLASH_DRIVER_H__ */
+668 -52
View File
@@ -1,6 +1,56 @@
#include "flash_manager.h"
#include "config.h"
#include <cstdio>
#include <cstring>
#include "gd32f4xx.h"
#include "gd32f4xx_fmc.h"
#include "spi_driver.h"
#define INTERNAL_FLASH_BASE_ADDR 0x08000000U
#define INTERNAL_FLASH_TOTAL_SIZE (1024 * 1024)
#define INTERNAL_FLASH_SECTOR_SIZE (16 * 1024)
#define INTERNAL_FLASH_PAGE_SIZE 256
#define INTERNAL_FLASH_BLOCK_SIZE (64 * 1024)
#define FLASH_TIMEOUT 50000000U
#define EXTERNAL_SPI_FLASH_BASE_ADDR 0x00000000U
#define SPI_FLASH_CMD_WRITE_ENABLE 0x06
#define SPI_FLASH_CMD_WRITE_DISABLE 0x04
#define SPI_FLASH_CMD_READ_STATUS_REG 0x05
#define SPI_FLASH_CMD_WRITE_STATUS_REG 0x01
#define SPI_FLASH_CMD_READ_DATA 0x03
#define SPI_FLASH_CMD_FAST_READ 0x0B
#define SPI_FLASH_CMD_PAGE_PROGRAM 0x02
#define SPI_FLASH_CMD_SECTOR_ERASE 0x20
#define SPI_FLASH_CMD_BLOCK_ERASE_32K 0x52
#define SPI_FLASH_CMD_BLOCK_ERASE_64K 0xD8
#define SPI_FLASH_CMD_CHIP_ERASE 0xC7
#define SPI_FLASH_CMD_POWER_DOWN 0xB9
#define SPI_FLASH_CMD_RELEASE_POWER_DOWN 0xAB
#define SPI_FLASH_CMD_READ_MANUFACTURER_ID 0x90
#define SPI_FLASH_CMD_READ_JEDEC_ID 0x9F
#define SPI_FLASH_CMD_READ_UNIQUE_ID 0x4B
#define SPI_FLASH_STATUS_BUSY (1 << 0)
#define SPI_FLASH_STATUS_WRITE_ENABLE (1 << 1)
#define SPI_FLASH_STATUS_BP0 (1 << 2)
#define SPI_FLASH_STATUS_BP1 (1 << 3)
#define SPI_FLASH_STATUS_BP2 (1 << 4)
#define SPI_FLASH_STATUS_BP3 (1 << 5)
#define SPI_FLASH_STATUS_SRWD (1 << 7)
#define EXTERNAL_SPI_FLASH_TOTAL_SIZE (16 * 1024 * 1024)
#define EXTERNAL_SPI_FLASH_SECTOR_SIZE (4 * 1024)
#define EXTERNAL_SPI_FLASH_PAGE_SIZE 256
#define EXTERNAL_SPI_FLASH_BLOCK_SIZE (64 * 1024)
#define SPI_FLASH_TIMEOUT 20000000U
#define SPI_FLASH_CS_PORT GPIOF
#define SPI_FLASH_CS_PIN GPIO_PIN_6
static SpiBus s_spi_flash_bus(SpiPort::_4);
static SpiDevice s_spi_flash_device(SPI_FLASH_CS_PORT, SPI_FLASH_CS_PIN);
FlashManager &FlashManager::instance()
{
@@ -9,35 +59,165 @@ FlashManager &FlashManager::instance()
}
FlashManager::FlashManager()
: handle_{
.type = FLASH_TYPE_INTERNAL,
.config = {
.type = FLASH_TYPE_INTERNAL,
.base_address = flash_get_internal_base_address(),
.clock_freq = 0,
.cs_pin = 0,
.spi_port = 0,
.exmc_bank = 0},
.info = {
.total_size = flash_get_internal_total_size(),
.sector_size = flash_get_internal_sector_size(),
.page_size = 256,
.block_size = 64 * 1024,
.manufacturer_id = 0x20,
.device_id = 0x470},
.initialized = false,
.private_data = nullptr
},
info_{
.total_size = flash_get_internal_total_size(),
.sector_size = flash_get_internal_sector_size(),
.page_size = 256,
.block_size = 64 * 1024,
.manufacturer_id = 0x20,
.device_id = 0x470}
: type_(FLASH_TYPE_INTERNAL)
, info_{
.total_size = INTERNAL_FLASH_TOTAL_SIZE,
.sector_size = INTERNAL_FLASH_SECTOR_SIZE,
.page_size = INTERNAL_FLASH_PAGE_SIZE,
.block_size = INTERNAL_FLASH_BLOCK_SIZE,
.manufacturer_id = 0x20,
.device_id = 0x470
}
, total_size_(INTERNAL_FLASH_TOTAL_SIZE)
, sector_size_(INTERNAL_FLASH_SECTOR_SIZE)
, initialized_(false)
, write_enabled_(false)
{
}
RetCode FlashManager::waitFlashOperation()
{
uint32_t timeout = FLASH_TIMEOUT;
while (fmc_flag_get(FMC_FLAG_BUSY) != RESET) {
if (timeout-- == 0) {
return RET_TIMEOUT;
}
}
if (fmc_flag_get(FMC_FLAG_OPERR) != RESET) {
fmc_flag_clear(FMC_FLAG_OPERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_WPERR) != RESET) {
fmc_flag_clear(FMC_FLAG_WPERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_PGMERR) != RESET) {
fmc_flag_clear(FMC_FLAG_PGMERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_PGSERR) != RESET) {
fmc_flag_clear(FMC_FLAG_PGSERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_RDDERR) != RESET) {
fmc_flag_clear(FMC_FLAG_RDDERR);
return RET_ERROR;
}
if (fmc_flag_get(FMC_FLAG_END) != RESET) {
fmc_flag_clear(FMC_FLAG_END);
}
return RET_OK;
}
RetCode FlashManager::unlockInternalFlash()
{
fmc_unlock();
ob_unlock();
return waitFlashOperation();
}
RetCode FlashManager::lockInternalFlash()
{
fmc_lock();
ob_lock();
return RET_OK;
}
uint32_t FlashManager::addressToSectorCode(uint32_t address)
{
uint32_t offset = address - INTERNAL_FLASH_BASE_ADDR;
uint32_t sector_num;
if (offset >= INTERNAL_FLASH_TOTAL_SIZE) {
return 0xFFFFFFFFU;
}
if (offset < 0x10000U) {
sector_num = offset / 0x4000U;
} else if (offset < 0x20000U) {
sector_num = 4;
} else {
sector_num = 5 + (offset - 0x20000U) / 0x20000U;
if (sector_num > 11) {
sector_num = 11;
}
}
return CTL_SN(sector_num);
}
RetCode FlashManager::eraseInternalFlashSector(uint32_t sector_address)
{
uint32_t sector_code = addressToSectorCode(sector_address);
if (sector_code == 0xFFFFFFFFU) {
return RET_INVALID_PARAM;
}
RetCode ret = unlockInternalFlash();
if (ret != RET_OK) {
return ret;
}
fmc_flag_clear(FMC_FLAG_END | FMC_FLAG_OPERR | FMC_FLAG_WPERR |
FMC_FLAG_PGMERR | FMC_FLAG_PGSERR);
fmc_sector_erase(sector_code);
ret = waitFlashOperation();
lockInternalFlash();
return ret;
}
RetCode FlashManager::writeInternalFlash(uint32_t address, const void *data, uint32_t length)
{
const uint8_t *src = (const uint8_t *)data;
uint32_t bytes_written = 0;
if ((address % 4) != 0 || (length % 4) != 0) {
return RET_INVALID_PARAM;
}
RetCode ret = unlockInternalFlash();
if (ret != RET_OK) {
return ret;
}
while (bytes_written < length) {
uint32_t word_data = (uint32_t)src[bytes_written] |
((uint32_t)src[bytes_written + 1] << 8) |
((uint32_t)src[bytes_written + 2] << 16) |
((uint32_t)src[bytes_written + 3] << 24);
fmc_word_program(address + bytes_written, word_data);
ret = waitFlashOperation();
if (ret != RET_OK) {
lockInternalFlash();
return ret;
}
bytes_written += 4;
}
lockInternalFlash();
return RET_OK;
}
RetCode FlashManager::initInternalFlash()
{
RetCode ret = unlockInternalFlash();
if (ret != RET_OK) {
return ret;
}
lockInternalFlash();
write_enabled_ = false;
return RET_OK;
}
RetCode FlashManager::init()
{
if (initialized_) {
@@ -45,49 +225,485 @@ RetCode FlashManager::init()
}
printf("[FlashManager] Initializing...\r\n");
RetCode ret = flash_init(&handle_);
if (ret == RET_OK) {
flash_get_info(&handle_, &info_);
initialized_ = true;
printf("[FlashManager] Init OK: %lu KB, sector=%lu KB\r\n",
info_.total_size / 1024, info_.sector_size / 1024);
} else {
printf("[FlashManager] Init failed: %d\r\n", ret);
RetCode ret = RET_OK;
switch (type_) {
case FLASH_TYPE_INTERNAL:
ret = initInternalFlash();
break;
case FLASH_TYPE_EXTERNAL_SPI:
ret = initExternalSpiFlash();
break;
case FLASH_TYPE_EXTERNAL_NOR:
ret = initExternalNorFlash();
break;
default:
return RET_INVALID_PARAM;
}
return ret;
}
RetCode FlashManager::erase(uint32_t address, uint32_t size)
{
if (!initialized_) return RET_NOT_INITIALIZED;
return flash_erase(&handle_, address, size);
}
if (ret != RET_OK) {
printf("[FlashManager] Init failed: %d\r\n", ret);
return ret;
}
RetCode FlashManager::write(uint32_t address, const void *data, uint32_t length)
{
if (!initialized_) return RET_NOT_INITIALIZED;
return flash_write(&handle_, address, data, length);
initialized_ = true;
printf("[FlashManager] Init OK: %lu KB, sector=%lu KB\r\n",
total_size_ / 1024, sector_size_ / 1024);
return RET_OK;
}
RetCode FlashManager::read(uint32_t address, void *buffer, uint32_t length)
{
if (!initialized_) return RET_NOT_INITIALIZED;
return flash_read(&handle_, address, buffer, length);
if (buffer == NULL || length == 0) return RET_INVALID_PARAM;
switch (type_) {
case FLASH_TYPE_INTERNAL: {
uint32_t actual_address;
if (address < INTERNAL_FLASH_BASE_ADDR) {
actual_address = INTERNAL_FLASH_BASE_ADDR + address;
} else {
actual_address = address;
}
if (actual_address < INTERNAL_FLASH_BASE_ADDR ||
actual_address + length > INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE) {
return RET_INVALID_PARAM;
}
memcpy(buffer, (void *)actual_address, length);
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI:
return readExternalSpiFlash(address, buffer, length);
case FLASH_TYPE_EXTERNAL_NOR:
return readExternalNorFlash(address, buffer, length);
default:
return RET_INVALID_PARAM;
}
}
RetCode FlashManager::write(uint32_t address, const void *data, uint32_t length)
{
if (!initialized_) return RET_NOT_INITIALIZED;
if (data == NULL || length == 0) return RET_INVALID_PARAM;
switch (type_) {
case FLASH_TYPE_INTERNAL: {
uint32_t actual_address;
if (address < INTERNAL_FLASH_BASE_ADDR) {
actual_address = INTERNAL_FLASH_BASE_ADDR + address;
} else {
actual_address = address;
}
if (actual_address < INTERNAL_FLASH_BASE_ADDR ||
actual_address + length > INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE) {
return RET_INVALID_PARAM;
}
if ((actual_address % 4) != 0 || (length % 4) != 0) {
return RET_INVALID_PARAM;
}
return writeInternalFlash(actual_address, data, length);
}
case FLASH_TYPE_EXTERNAL_SPI:
return writeExternalSpiFlash(address, data, length);
case FLASH_TYPE_EXTERNAL_NOR:
return writeExternalNorFlash(address, data, length);
default:
return RET_INVALID_PARAM;
}
}
RetCode FlashManager::erase(uint32_t address, uint32_t size)
{
if (!initialized_) return RET_NOT_INITIALIZED;
if (size == 0) return RET_OK;
switch (type_) {
case FLASH_TYPE_INTERNAL: {
uint32_t actual_address;
if (address < INTERNAL_FLASH_BASE_ADDR) {
actual_address = INTERNAL_FLASH_BASE_ADDR + address;
} else {
actual_address = address;
}
if (actual_address < INTERNAL_FLASH_BASE_ADDR ||
actual_address + size > INTERNAL_FLASH_BASE_ADDR + INTERNAL_FLASH_TOTAL_SIZE) {
return RET_INVALID_PARAM;
}
if ((actual_address % INTERNAL_FLASH_SECTOR_SIZE) != 0 ||
(size % INTERNAL_FLASH_SECTOR_SIZE) != 0) {
return RET_INVALID_PARAM;
}
uint32_t sector_count = size / INTERNAL_FLASH_SECTOR_SIZE;
for (uint32_t i = 0; i < sector_count; i++) {
RetCode ret = eraseInternalFlashSector(actual_address + i * INTERNAL_FLASH_SECTOR_SIZE);
if (ret != RET_OK) return ret;
}
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI: {
if ((address % EXTERNAL_SPI_FLASH_SECTOR_SIZE) != 0 ||
(size % EXTERNAL_SPI_FLASH_SECTOR_SIZE) != 0) {
return RET_INVALID_PARAM;
}
uint32_t sector_count = size / EXTERNAL_SPI_FLASH_SECTOR_SIZE;
for (uint32_t i = 0; i < sector_count; i++) {
RetCode ret = eraseExternalSpiFlashSector(address + i * EXTERNAL_SPI_FLASH_SECTOR_SIZE);
if (ret != RET_OK) return ret;
}
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_NOR:
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
RetCode FlashManager::self_test(uint32_t test_size)
{
if (!initialized_) return RET_NOT_INITIALIZED;
printf("[FlashManager] Running self-test (%lu bytes)...\r\n", test_size);
return flash_self_test(&handle_, test_size);
switch (type_) {
case FLASH_TYPE_INTERNAL: {
uint32_t test_address = INTERNAL_FLASH_BASE_ADDR + total_size_ - sector_size_;
if (test_size > sector_size_) {
test_size = sector_size_;
}
test_size = (test_size + 3) & ~3;
uint8_t write_buffer[256];
uint8_t read_buffer[256];
for (uint32_t i = 0; i < sizeof(write_buffer); i++) {
write_buffer[i] = (uint8_t)(i & 0xFF);
}
RetCode ret = erase(test_address, sector_size_);
if (ret != RET_OK) return ret;
ret = write(test_address, write_buffer, sizeof(write_buffer));
if (ret != RET_OK) return ret;
ret = read(test_address, read_buffer, sizeof(read_buffer));
if (ret != RET_OK) return ret;
if (memcmp(write_buffer, read_buffer, sizeof(write_buffer)) != 0) {
return RET_ERROR;
}
return RET_OK;
}
case FLASH_TYPE_EXTERNAL_SPI:
case FLASH_TYPE_EXTERNAL_NOR:
return RET_NOT_SUPPORTED;
default:
return RET_INVALID_PARAM;
}
}
uint32_t FlashManager::total_size() const
RetCode FlashManager::spiFlashSelect()
{
return info_.total_size;
gpio_bit_reset(SPI_FLASH_CS_PORT, SPI_FLASH_CS_PIN);
for (volatile uint32_t i = 0; i < 5000; i++);
printf("[SPI Flash] CS拉低 (选择芯片)\r\n");
return RET_OK;
}
uint32_t FlashManager::sector_size() const
RetCode FlashManager::spiFlashDeselect()
{
return info_.sector_size;
gpio_bit_set(SPI_FLASH_CS_PORT, SPI_FLASH_CS_PIN);
for (volatile uint32_t i = 0; i < 5000; i++);
printf("[SPI Flash] CS拉高 (取消选择芯片)\r\n");
return RET_OK;
}
RetCode FlashManager::spiFlashSendCommand(uint8_t cmd)
{
printf("[SPI Flash] 发送命令: 0x%02X\r\n", cmd);
spiFlashSelect();
BusTransfer tr = {&cmd, nullptr, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr);
spiFlashDeselect();
for (volatile uint32_t i = 0; i < 1000; i++);
return RET_OK;
}
RetCode FlashManager::spiFlashReadStatus(uint8_t *status)
{
if (status == NULL) return RET_INVALID_PARAM;
spiFlashSelect();
uint8_t cmd = SPI_FLASH_CMD_READ_STATUS_REG;
BusTransfer tr_cmd = {&cmd, nullptr, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_cmd);
uint8_t dummy = 0x00;
BusTransfer tr_data = {&dummy, status, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_data);
spiFlashDeselect();
return RET_OK;
}
RetCode FlashManager::spiFlashWaitIdle()
{
uint32_t timeout = SPI_FLASH_TIMEOUT;
uint8_t status = 0;
uint32_t last_report = timeout;
printf("[SPI Flash] 开始等待Flash空闲 (超时: %lu)\r\n", timeout);
while (timeout-- > 0) {
RetCode ret = spiFlashReadStatus(&status);
if (ret != RET_OK) {
printf("[SPI Flash] 读取状态寄存器失败: %d\r\n", ret);
return ret;
}
if ((status & SPI_FLASH_STATUS_BUSY) == 0) {
printf("[SPI Flash] Flash已空闲,状态: 0x%02X, 剩余超时: %lu\r\n", status, timeout);
return RET_OK;
}
if ((timeout % 10000) == 0 && timeout != last_report) {
printf("[SPI Flash] 等待Flash空闲,状态: 0x%02X, 剩余超时: %lu\r\n", status, timeout);
last_report = timeout;
}
}
printf("[SPI Flash] 等待Flash空闲超时,最终状态: 0x%02X\r\n", status);
return RET_TIMEOUT;
}
RetCode FlashManager::spiFlashWriteEnable()
{
spiFlashSelect();
uint8_t cmd = SPI_FLASH_CMD_WRITE_ENABLE;
BusTransfer tr = {&cmd, nullptr, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr);
spiFlashDeselect();
for (volatile uint32_t i = 0; i < 1000; i++);
write_enabled_ = true;
printf("[SPI Flash] 写使能命令已发送\r\n");
return RET_OK;
}
RetCode FlashManager::initExternalSpiFlash()
{
write_enabled_ = false;
printf("[SPI Flash] 配置SPI4引脚: PF6(CS), PF8(MISO), PF7(CLK), PF9(MOSI)\r\n");
printf("[SPI Flash] 使用AF5配置 (SPI4)\r\n");
SpiConfig config;
config.speed_hz = 1562500;
config.mode = 0;
config.data_width = 8;
RetCode ret = s_spi_flash_bus.init(config);
if (ret != RET_OK) {
printf("[SPI Flash] SPI4初始化失败: %d\r\n", ret);
return ret;
}
s_spi_flash_device.init();
for (volatile uint32_t i = 0; i < 10000; i++);
printf("[SPI Flash] SPI4初始化完成\r\n");
printf("[SPI Flash] 执行SPI基本功能测试...\r\n");
uint8_t test_tx = 0x5A;
uint8_t test_rx = 0xFF;
BusTransfer tr_test = {&test_tx, &test_rx, 1, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_test);
printf("[SPI Flash] SPI测试: 发送=0x%02X, 接收=0x%02X\r\n", test_tx, test_rx);
if (test_rx == 0xFF) {
printf("[SPI Flash] 警告: 接收到0xFF,可能MISO线被拉高或未连接\r\n");
}
uint8_t tx_data[4] = {SPI_FLASH_CMD_READ_JEDEC_ID, 0x00, 0x00, 0x00};
uint8_t rx_data[4] = {0xFF, 0xFF, 0xFF, 0xFF};
printf("[SPI Flash] 开始读取设备ID,命令: 0x%02X\r\n", SPI_FLASH_CMD_READ_JEDEC_ID);
spiFlashSelect();
for (volatile uint32_t i = 0; i < 5000; i++);
BusTransfer tr_jedec = {tx_data, rx_data, 4, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_jedec);
for (volatile uint32_t i = 0; i < 1000; i++);
spiFlashDeselect();
for (volatile uint32_t i = 0; i < 1000; i++);
uint32_t manufacturer_id = rx_data[1];
uint32_t device_id = (rx_data[2] << 8) | rx_data[3];
info_.manufacturer_id = manufacturer_id;
info_.device_id = device_id;
printf("[SPI Flash] 读取结果 - 制造商ID: 0x%02lX, 设备ID: 0x%04lX\r\n",
manufacturer_id, device_id);
switch (device_id) {
case 0x4017:
total_size_ = 8 * 1024 * 1024;
info_.total_size = total_size_;
printf("[SPI Flash] 检测到 W25Q64 (8MB)\r\n");
break;
case 0x4018:
total_size_ = 16 * 1024 * 1024;
info_.total_size = total_size_;
printf("[SPI Flash] 检测到 W25Q128 (16MB)\r\n");
break;
case 0x4019:
total_size_ = 32 * 1024 * 1024;
info_.total_size = total_size_;
printf("[SPI Flash] 检测到 W25Q256 (32MB)\r\n");
break;
default:
total_size_ = EXTERNAL_SPI_FLASH_TOTAL_SIZE;
info_.total_size = total_size_;
printf("[SPI Flash] 未知设备ID: 0x%04lX,使用默认容量 %lu MB\r\n",
device_id, total_size_ / (1024 * 1024));
break;
}
info_.sector_size = EXTERNAL_SPI_FLASH_SECTOR_SIZE;
info_.page_size = EXTERNAL_SPI_FLASH_PAGE_SIZE;
info_.block_size = EXTERNAL_SPI_FLASH_BLOCK_SIZE;
sector_size_ = info_.sector_size;
return RET_OK;
}
RetCode FlashManager::readExternalSpiFlash(uint32_t address, void *buffer, uint32_t length)
{
if (buffer == NULL || length == 0) return RET_INVALID_PARAM;
RetCode ret = spiFlashWaitIdle();
if (ret != RET_OK) return ret;
uint8_t tx_buffer[4];
tx_buffer[0] = SPI_FLASH_CMD_READ_DATA;
tx_buffer[1] = (address >> 16) & 0xFF;
tx_buffer[2] = (address >> 8) & 0xFF;
tx_buffer[3] = address & 0xFF;
spiFlashSelect();
BusTransfer tr_addr = {tx_buffer, nullptr, 4, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_addr);
BusTransfer tr_data = {nullptr, (uint8_t *)buffer, length, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_data);
spiFlashDeselect();
return RET_OK;
}
RetCode FlashManager::writeExternalSpiFlash(uint32_t address, const void *data, uint32_t length)
{
if (data == NULL || length == 0) return RET_INVALID_PARAM;
const uint8_t *src = (const uint8_t *)data;
uint32_t page_size = EXTERNAL_SPI_FLASH_PAGE_SIZE;
uint32_t page_offset = address % page_size;
if (page_offset + length > page_size) {
return RET_NOT_SUPPORTED;
}
RetCode ret = spiFlashWaitIdle();
if (ret != RET_OK) return ret;
ret = spiFlashWriteEnable();
if (ret != RET_OK) return ret;
uint8_t tx_buffer[4 + EXTERNAL_SPI_FLASH_PAGE_SIZE];
tx_buffer[0] = SPI_FLASH_CMD_PAGE_PROGRAM;
tx_buffer[1] = (address >> 16) & 0xFF;
tx_buffer[2] = (address >> 8) & 0xFF;
tx_buffer[3] = address & 0xFF;
for (uint32_t i = 0; i < length; i++) {
tx_buffer[4 + i] = src[i];
}
spiFlashSelect();
BusTransfer tr_write = {tx_buffer, nullptr, 4 + length, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_write);
spiFlashDeselect();
ret = spiFlashWaitIdle();
return ret;
}
RetCode FlashManager::eraseExternalSpiFlashSector(uint32_t address)
{
printf("[SPI Flash] 开始擦除扇区 0x%06lX\r\n", address);
RetCode ret = spiFlashWaitIdle();
if (ret != RET_OK) {
printf("[SPI Flash] 等待空闲失败: %d\r\n", ret);
return ret;
}
printf("[SPI Flash] Flash空闲,开始写使能\r\n");
ret = spiFlashWriteEnable();
if (ret != RET_OK) {
printf("[SPI Flash] 写使能失败: %d\r\n", ret);
return ret;
}
uint8_t tx_buffer[4];
tx_buffer[0] = SPI_FLASH_CMD_SECTOR_ERASE;
tx_buffer[1] = (address >> 16) & 0xFF;
tx_buffer[2] = (address >> 8) & 0xFF;
tx_buffer[3] = address & 0xFF;
printf("[SPI Flash] 发送扇区擦除命令: 0x%02X 0x%02X 0x%02X 0x%02X\r\n",
tx_buffer[0], tx_buffer[1], tx_buffer[2], tx_buffer[3]);
spiFlashSelect();
BusTransfer tr_erase = {tx_buffer, nullptr, 4, 0};
s_spi_flash_bus.transfer(&s_spi_flash_device, &tr_erase);
spiFlashDeselect();
printf("[SPI Flash] 扇区擦除命令已发送,等待擦除完成...\r\n");
ret = spiFlashWaitIdle();
if (ret != RET_OK) {
printf("[SPI Flash] 等待擦除完成失败: %d\r\n", ret);
} else {
printf("[SPI Flash] 扇区擦除完成\r\n");
}
return ret;
}
RetCode FlashManager::initExternalNorFlash()
{
return RET_OK;
}
RetCode FlashManager::readExternalNorFlash(uint32_t address, void *buffer, uint32_t length)
{
(void)address; (void)buffer; (void)length;
return RET_NOT_SUPPORTED;
}
RetCode FlashManager::writeExternalNorFlash(uint32_t address, const void *data, uint32_t length)
{
(void)address; (void)data; (void)length;
return RET_NOT_SUPPORTED;
}
RetCode FlashManager::eraseExternalNorFlashSector(uint32_t address)
{
(void)address;
return RET_NOT_SUPPORTED;
}
+47 -6
View File
@@ -3,7 +3,6 @@
#include <cstdint>
#include "common_types.h"
#include "flash_driver.h"
class FlashManager {
public:
@@ -15,8 +14,8 @@ public:
RetCode read(uint32_t address, void *buffer, uint32_t length);
RetCode self_test(uint32_t test_size);
uint32_t total_size() const;
uint32_t sector_size() const;
uint32_t total_size() const { return total_size_; }
uint32_t sector_size() const { return sector_size_; }
bool is_initialized() const { return initialized_; }
private:
@@ -25,9 +24,51 @@ private:
FlashManager(const FlashManager &) = delete;
FlashManager &operator=(const FlashManager &) = delete;
flash_handle_t handle_;
flash_info_t info_;
bool initialized_ = false;
enum FlashType : uint8_t {
FLASH_TYPE_INTERNAL = 0,
FLASH_TYPE_EXTERNAL_SPI,
FLASH_TYPE_EXTERNAL_NOR,
};
struct FlashInfo {
uint32_t total_size;
uint32_t sector_size;
uint32_t page_size;
uint32_t block_size;
uint32_t manufacturer_id;
uint32_t device_id;
};
RetCode waitFlashOperation();
RetCode unlockInternalFlash();
RetCode lockInternalFlash();
uint32_t addressToSectorCode(uint32_t address);
RetCode eraseInternalFlashSector(uint32_t sector_address);
RetCode writeInternalFlash(uint32_t address, const void *data, uint32_t length);
RetCode initInternalFlash();
RetCode spiFlashSelect();
RetCode spiFlashDeselect();
RetCode spiFlashSendCommand(uint8_t cmd);
RetCode spiFlashReadStatus(uint8_t *status);
RetCode spiFlashWaitIdle();
RetCode spiFlashWriteEnable();
RetCode initExternalSpiFlash();
RetCode readExternalSpiFlash(uint32_t address, void *buffer, uint32_t length);
RetCode writeExternalSpiFlash(uint32_t address, const void *data, uint32_t length);
RetCode eraseExternalSpiFlashSector(uint32_t address);
RetCode initExternalNorFlash();
RetCode readExternalNorFlash(uint32_t address, void *buffer, uint32_t length);
RetCode writeExternalNorFlash(uint32_t address, const void *data, uint32_t length);
RetCode eraseExternalNorFlashSector(uint32_t address);
FlashType type_;
FlashInfo info_;
uint32_t total_size_;
uint32_t sector_size_;
bool initialized_;
bool write_enabled_;
};
#endif