9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
76 lines
3.1 KiB
Markdown
76 lines
3.1 KiB
Markdown
# externalflash 模块说明(SPI4 外部 Flash)
|
||
|
||
> 本文档描述 `CCU621_M/BSP/externalflash` 模块的职责、接口、初始化位置以及 DMA + D-Cache 场景下的使用注意事项。
|
||
|
||
[返回主说明](./../../README.md)
|
||
|
||
## 1. 模块组成
|
||
|
||
- **底层驱动(SPI4 + GD25QXX)**
|
||
- `exflash_spi4_gd25qxx.c`
|
||
- `exflash_spi4_gd25qxx.h`
|
||
- **统一对外接口(业务层推荐使用)**
|
||
- `flash_external_data.c`
|
||
- `flash_external_data.h`
|
||
|
||
## 2. 初始化入口
|
||
|
||
- 系统硬件初始化入口:`BSP/sys_drv_init.c`
|
||
- `v_sys_hardware_init()` 中调用 `v_flash_dataflash_init()`,完成 SPI4/GPIO/DMA 初始化。
|
||
|
||
> 约束:业务层/测试层不要重复 init,避免初始化时序与资源重复配置。
|
||
|
||
## 3. 推荐对外接口(统一接口)
|
||
|
||
业务层请优先使用以下接口(位于 `flash_external_data.c/.h`):
|
||
|
||
- `U8_T v_flash_dataflash_init(void)`
|
||
- `U8_T s32_flash_dataflash_write(U32_T addr, U8_T *buf, U32_T len)`
|
||
- `U8_T s32_flash_dataflash_read(U32_T addr, U8_T *buf, U32_T len)`
|
||
- `U8_T s32_flash_dataflash_erase_sector(U32_T addr)`
|
||
- 兼容旧命名:`unsigned int SPI_flsh_ReadID(void)`
|
||
|
||
### 3.1 地址规划(摘自 `flash_external_data.h`)
|
||
|
||
- 全空间(4-byte 地址模式):`0x00000000 ~ 0x01FFFFFF`(32MB)
|
||
- OTA 区:`0x00000000 ~ 0x001FFFFF`
|
||
- 参数区:`0x210000 ~ ...`
|
||
- 业务记录区:`0x220000 ~ ...`
|
||
- FatFs 映射区:`0xA00000 ~ 0x01FFFFFF`
|
||
|
||
> 说明:以上为“线性地址”规划,调用统一接口时直接传该地址即可。
|
||
|
||
## 4. DMA + D-Cache 使用注意事项(非常重要)
|
||
|
||
当前 SPI4 外部 Flash 读写采用 **DMA** 方式提升性能;在 Cortex-M7 **开启 D-Cache** 的情况下,DMA 与 CPU 会出现数据一致性问题:
|
||
|
||
- DMA 写入内存后,CPU 可能仍读取到旧 cache 数据;
|
||
- DMA 从内存读取 TX 数据时,可能读不到 CPU 刚写入但未 clean 的 cache 内容。
|
||
|
||
### 4.1 当前工程的处理策略
|
||
|
||
- 底层 SPI4 DMA 传输在驱动内部做了 D-Cache clean/invalidate(按 32B cache line 对齐)。
|
||
- 统一接口 `s32_flash_dataflash_read/write` 额外做了一层保护:
|
||
- 如果业务传入的 `buf` **不是 32B 对齐**,内部会自动使用 **对齐 bounce buffer** 完成 DMA 传输,再 `memcpy` 到业务缓冲。
|
||
|
||
### 4.2 业务层建议
|
||
|
||
- 业务层可直接使用 `s32_flash_dataflash_read/write`,无需自行对齐或自行做 cache 维护。
|
||
- 若业务存在高频读写,可考虑在模块内复用一块“32B 对齐的工作缓冲”,减少 malloc/free 次数(后续可优化)。
|
||
|
||
## 5. 测试入口
|
||
|
||
- `app/app_init/app_test.c`
|
||
- 周期执行 flash 擦写读回校验
|
||
- 输出擦除/读写耗时与速度统计
|
||
- 新增 `u8_app_test_flash_32m_stride_rw()`:以 1MB 步长扫描 32MB 地址空间做擦写读回校验
|
||
|
||
## 6. 常见问题排查
|
||
|
||
- **读回校验失败**
|
||
- 首先确认是否走统一接口(避免绕过 bounce buffer)
|
||
- 其次检查 D-Cache 是否开启、MPU 区域属性是否覆盖了 DMA buffer
|
||
- **卡死在 SPI_FLAG_RP 等待**
|
||
- 通常表示 SPI 主机传输未启动或时钟未输出,需要检查 `spi_master_transfer_start` 是否调用、片选是否正确、外设时钟是否使能
|
||
|