Files

150 lines
3.6 KiB
C

#include "flash_external_data.h"
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#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);
}
}