diff --git a/bsp/device/flash/flash_driver.cpp b/bsp/device/flash/flash_driver.cpp deleted file mode 100644 index c8a4d18..0000000 --- a/bsp/device/flash/flash_driver.cpp +++ /dev/null @@ -1,1375 +0,0 @@ -#include "flash_driver.h" -#include "config.h" -#include -#include - -/* 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; -} diff --git a/bsp/device/flash/flash_driver.h b/bsp/device/flash/flash_driver.h deleted file mode 100644 index b54b84f..0000000 --- a/bsp/device/flash/flash_driver.h +++ /dev/null @@ -1,181 +0,0 @@ -#ifndef __FLASH_DRIVER_H__ -#define __FLASH_DRIVER_H__ - -#include -#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__ */ \ No newline at end of file diff --git a/bsp/device/flash/flash_manager.cpp b/bsp/device/flash/flash_manager.cpp index 7a4eb60..f29c137 100644 --- a/bsp/device/flash/flash_manager.cpp +++ b/bsp/device/flash/flash_manager.cpp @@ -1,6 +1,56 @@ #include "flash_manager.h" +#include "config.h" #include #include +#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; } diff --git a/bsp/device/flash/flash_manager.h b/bsp/device/flash/flash_manager.h index f467f84..567c342 100644 --- a/bsp/device/flash/flash_manager.h +++ b/bsp/device/flash/flash_manager.h @@ -3,7 +3,6 @@ #include #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