GD5F 驱动增设 DMA 可达性运行时守卫,非 SRAM 缓冲拒走 DMA 回落轮询
This commit is contained in:
@@ -53,6 +53,15 @@ volatile uint8_t g_spi1_dma_done;
|
||||
* 页级大块传输(2048)仍走 DMA,源/目的全部为文件作用域静态缓冲。 */
|
||||
#define GD5F_DMA_THRESHOLD 1024
|
||||
|
||||
/* DMA 可达内存区间:必须与分散加载文件 RW_IRAM1(0x20000000,128KB,
|
||||
* SRAM1+SRAM2)一致。CCM(0x10000000,64KB)DMA1/DMA2 物理不可达,
|
||||
* RW_CCM 区任何缓冲都不得进 DMA。阈值只能挡住"当前已知的小栈缓冲",
|
||||
* 挡不住"将来新加的 >1024B 栈缓冲";gd5f_dma_buf_ok() 把这条约定
|
||||
* 升级为运行时强制检查(2026-09-21 加固)。若将来新增其它 DMA 可达
|
||||
* 内存(如外部 SDRAM),此处区间必须同步扩展。 */
|
||||
#define GD5F_DMA_RAM_BASE 0x20000000UL
|
||||
#define GD5F_DMA_RAM_END 0x20020000UL
|
||||
|
||||
/*
|
||||
* 函数功能:SPI1 TX DMA 完成回调(PROGRAM_LOAD 数据发送用)
|
||||
* 入口参数:hspi - 触发回调的 SPI 句柄 SPI_HandleTypeDef*
|
||||
@@ -91,6 +100,42 @@ static int gd5f_private_bbt_find_best(void);
|
||||
static int gd5f_bbt_load(void);
|
||||
static int gd5f_bbt_save(void);
|
||||
|
||||
/* DMA 可达性守卫(见下方实现) */
|
||||
static int gd5f_dma_buf_ok(const void *p_buf, size_t size);
|
||||
|
||||
/* ======================== DMA 可达性守卫 ======================== */
|
||||
|
||||
/*
|
||||
* 函数功能:判定缓冲是否位于 DMA 可达内存(SRAM1+SRAM2)
|
||||
* 入口参数:p_buf - 传输缓冲首地址 const void*
|
||||
* size - 传输字节数 size_t
|
||||
* 返回值:1 - 整段缓冲 DMA 可达;0 - 不可达(调用方须回落 CPU 轮询)
|
||||
* 限定条件:无
|
||||
* 函数说明:DMA1/DMA2 物理不可达 CCM(0x10000000)——以 CCM 缓冲做 DMA
|
||||
* 源/目的会静默不落地(2026-09-20 首轮 CCM 扩容实验实证根因)。
|
||||
* 本函数把"栈/堆缓冲禁入 DMA"的约定升级为运行时强制约束:
|
||||
* 起止地址任一越出 SRAM 区间即判不可达。
|
||||
*/
|
||||
static int gd5f_dma_buf_ok(const void *p_buf, size_t size) {
|
||||
uint32_t start = (uint32_t)(uintptr_t)p_buf;
|
||||
uint32_t end;
|
||||
|
||||
if (size == 0U) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
end = start + (uint32_t)size;
|
||||
if (end < start) { /* 地址回绕:不可能落在同一区间内 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((start < GD5F_DMA_RAM_BASE) || (end > GD5F_DMA_RAM_END)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ======================== SPI 原语定义 ======================== */
|
||||
|
||||
/*
|
||||
@@ -223,6 +268,17 @@ int gd5f_page_read(uint32_t page_addr) {
|
||||
int gd5f_read_from_cache(uint16_t column, uint8_t *p_buf,
|
||||
size_t size) {
|
||||
uint8_t cmd[4] = {0};
|
||||
uint8_t use_dma = 0U;
|
||||
|
||||
/* 守卫判定须在 CS 拉低之前完成:DBG_ERROR 走串口,不能占着 CS 窗口 */
|
||||
if (size > GD5F_DMA_THRESHOLD) {
|
||||
use_dma = (uint8_t)gd5f_dma_buf_ok(p_buf, size);
|
||||
if (use_dma == 0U) {
|
||||
DBG_ERROR("RX DMA buffer not DMA-reachable "
|
||||
"(p=0x%08lX size=%lu), fallback poll",
|
||||
(unsigned long)(uintptr_t)p_buf, (unsigned long)size);
|
||||
}
|
||||
}
|
||||
|
||||
cmd[0] = GD5F_CMD_READ_FROM_CACHE;
|
||||
cmd[1] = (column >> 8) & 0xFF;
|
||||
@@ -232,7 +288,7 @@ int gd5f_read_from_cache(uint16_t column, uint8_t *p_buf,
|
||||
GD5F_CS_LOW();
|
||||
HAL_SPI_Transmit(&hspi1, cmd, 4, GD5F_SPI_TIMEOUT);
|
||||
|
||||
if (size > GD5F_DMA_THRESHOLD) {
|
||||
if (use_dma != 0U) {
|
||||
uint32_t tick_start = HAL_GetTick();
|
||||
g_spi1_dma_done = 0U;
|
||||
if (HAL_SPI_Receive_DMA(&hspi1, p_buf, (uint16_t)size) != HAL_OK) {
|
||||
@@ -294,6 +350,18 @@ static int gd5f_page_program(uint32_t page_addr, uint16_t column,
|
||||
*/
|
||||
int gd5f_program_load(uint16_t column, const uint8_t *p_buf, size_t size) {
|
||||
uint8_t cmd[3];
|
||||
uint8_t use_dma = 0U;
|
||||
|
||||
/* 守卫判定须在 CS 拉低之前完成:DBG_ERROR 走串口,不能占着 CS 窗口 */
|
||||
if (size > GD5F_DMA_THRESHOLD) {
|
||||
use_dma = (uint8_t)gd5f_dma_buf_ok(p_buf, size);
|
||||
if (use_dma == 0U) {
|
||||
DBG_ERROR("TX DMA buffer not DMA-reachable "
|
||||
"(p=0x%08lX size=%lu), fallback poll",
|
||||
(unsigned long)(uintptr_t)p_buf, (unsigned long)size);
|
||||
}
|
||||
}
|
||||
|
||||
cmd[0] = GD5F_CMD_PROGRAM_LOAD;
|
||||
cmd[1] = (uint8_t)(column >> 8);
|
||||
cmd[2] = (uint8_t)(column);
|
||||
@@ -301,7 +369,7 @@ int gd5f_program_load(uint16_t column, const uint8_t *p_buf, size_t size) {
|
||||
GD5F_CS_LOW();
|
||||
HAL_SPI_Transmit(&hspi1, cmd, 3, GD5F_SPI_TIMEOUT);
|
||||
|
||||
if (size > GD5F_DMA_THRESHOLD) {
|
||||
if (use_dma != 0U) {
|
||||
uint32_t tick_start = HAL_GetTick();
|
||||
g_spi1_dma_done = 0U;
|
||||
if (HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)p_buf, (uint16_t)size)
|
||||
|
||||
Reference in New Issue
Block a user