9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
150 lines
3.6 KiB
C
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);
|
|
}
|
|
}
|