#include "flash_external_data.h" #include #include #include #include "app_init/app_init.h" #include "exflash_spi4_gd25qxx.h" #include "FreeRTOS.h" #include "portable.h" #define FLASH_IO_ALIGN (32u) #define FLASH_IO_GUARD_SIZE (32u) static uint8_t *align_up_u8(uint8_t *p, uint32_t align) { uintptr_t v = (uintptr_t)p; v = (v + (align - 1U)) & ~(uintptr_t)(align - 1U); return (uint8_t *)v; } static uint8_t need_bounce_buf(const void *p) { return (((uintptr_t)p) & (FLASH_IO_ALIGN - 1U)) ? 1U : 0U; } /** * @brief 外部 Flash 初始化(统一接口)。 * @return 0 成功。 */ U8_T v_flash_dataflash_init(void) { spi_flash_init(); printf("[EXFLASH] JEDEC ID: 0x%06X\r\n", (unsigned int)spi_flash_read_id()); return 0U; } /** * @brief 外部 Flash 写接口(统一接口)。 * @param addr 24bit 线性地址。 * @param buf 写入数据缓冲区。 * @param len 写入长度(字节)。 * @return 0 成功,1 参数错误,2 长度超驱动接口上限。 */ U8_T s32_flash_dataflash_write(U32_T addr, U8_T *buf, U32_T len) { uint8_t *raw; uint8_t *aligned; uint32_t alloc_size; if ((buf == NULL) || (len == 0U)) { return 1U; } /* 底层驱动 write 接口长度参数为 uint16_t。 */ if (len > 0xFFFFu) { return 2U; } /* 若用户缓冲未按 32B 对齐,使用 bounce buffer,避免 DMA/DCache 维护影响堆头或触发一致性问题 */ if (need_bounce_buf(buf) == 0U) { spi_flash_buffer_write(buf, addr, (U16_T)len); return 0U; } alloc_size = len + FLASH_IO_ALIGN + FLASH_IO_GUARD_SIZE; raw = (uint8_t *)pvPortMalloc(alloc_size); if (raw == NULL) { return 3U; } aligned = align_up_u8(raw, FLASH_IO_ALIGN); memcpy(aligned, buf, len); spi_flash_buffer_write(aligned, addr, (U16_T)len); vPortFree(raw); return 0U; } /** * @brief 外部 Flash 读接口(统一接口)。 * @param addr 24bit 线性地址。 * @param buf 读出数据缓冲区。 * @param len 读取长度(字节)。 * @return 0 成功,1 参数错误,2 长度超驱动接口上限。 */ U8_T s32_flash_dataflash_read(U32_T addr, U8_T *buf, U32_T len) { uint8_t *raw; uint8_t *aligned; uint32_t alloc_size; if ((buf == NULL) || (len == 0U)) { return 1U; } if (len > 0xFFFFu) { return 2U; } if (need_bounce_buf(buf) == 0U) { spi_flash_buffer_read(buf, addr, (U16_T)len); return 0U; } alloc_size = len + FLASH_IO_ALIGN + FLASH_IO_GUARD_SIZE; raw = (uint8_t *)pvPortMalloc(alloc_size); if (raw == NULL) { return 3U; } aligned = align_up_u8(raw, FLASH_IO_ALIGN); spi_flash_buffer_read(aligned, addr, (U16_T)len); memcpy(buf, aligned, len); vPortFree(raw); return 0U; } /** * @brief 擦除指定地址所在扇区。 * @param addr 扇区起始地址(建议 4KB 对齐)。 * @return 0 成功。 */ U8_T s32_flash_dataflash_erase_sector(U32_T addr) { spi_flash_sector_erase(addr); return 0U; } /** * @brief 读取外部 Flash JEDEC ID(兼容旧命名)。 */ unsigned int SPI_flsh_ReadID(void) { return (unsigned int)spi_flash_read_id(); } /** * @brief 擦除 FatFs 映射区全部扇区。 */ void v_flash_dataflash_fatfs_esaes_sectot(void) { U32_T i; U32_T sector_addr; for (i = 0U; i < FATFS_TOTAL_SECTORS; i++) { sector_addr = FATFS_PHYSICAL_START_ADDR + (i * SPI_SECTOR_SIZE); printf("SPI flash erase sector: 0x%08X\r\n", (unsigned int)sector_addr); spi_flash_sector_erase(sector_addr); mSleep(1U); } }