【嵌入式】STM32H743, D-cache, DMA注意事项
·
1. 问题
STM32H743开启D-cache以后,如果使用DMA会导致数据错乱。
2. 原因
DMA访问的是RAM, 实际的数据可能还在D-cache中,没有与RAM同步。
3. 解决方法
3.1 使用前同步
- DMA发送前将cache中的数据写会RAM
SCB_CleanDCache_by_Addr()
- DMA接收数据后,cache获取RMA的数据
SCB_InvalidateDCache_by_Addr()
- 详情
//用于将 D-Cache 数据回写到 SRAM 里面
SCB_CleanDCache_by_Addr((uint32_t *)buf, len);
//用于重新从 SRAM 获取数据, 丢弃 D-Cache 当前数据,
SCB_InvalidateDCache_by_Addr((uint32_t *)buf, len);
//写回数据到 SRAM, 并重新获取 D-Cache数据
SCB_CleanInvalidateDCache_by_Addr((uint32_t *)buf, len);
3.2 MPU方式(推荐)

-
通过MPU关闭一块SRAM的Cache功能
- 例如:以
0x30000000为首地址的128K(SRAM1) - 为什么不用
0x24000000(AXI SRAM)这一块?因为这块ram的速度快,关闭Cache太浪费。 
- 例如:以
-
DMA使用到的内存需要定义到关闭Cache的内存范围内
步骤
1. 开启MPU并设置
void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct = {0};
/* Disables the MPU */
HAL_MPU_Disable();
/** Initializes and configures the Region and the memory to be protected
*/
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.BaseAddress = 0x30000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_128KB;
MPU_InitStruct.SubRegionDisable = 0x0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);
/* Enables the MPU */
HAL_MPU_Enable(MPU_HFNMI_PRIVDEF);
}
2. Keil工程设置Linker

3 STM32H743_DMA.sct
; STM32H743IITx
; Flash 2MB
; AXI SRAM(D1) 512KB
; SRAM1+SRAM2+SRAM3(D2) 288KB
LR_IROM1 0x08000000 0x00200000
{
ER_IROM1 0x08000000 0x00200000
{
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
; 普通RW/ZI变量
RW_RAM_D1 0x24000000 0x00080000
{
.ANY (+RW +ZI)
}
; DMA专用区域
RW_DMA 0x30000000 0x00048000
{
*(.dma_buffer)
}
}
4. 使用
#define __DMA_RAM \
__attribute__((section(".dma_buffer"))) \
__attribute__((aligned(32)))
//注意,这里buf需要是全局变量或static变量
__DMA_RAM uint8_t buf[512] = {0}; //buf在0x30000000 sram段
3.3 D-Cache 的透写模式
- 缺点: 会损失一些性能,因为每次都要从从Cache写会数据。
/**
* @brief 使能 STM32H7 的 L1-Cache, 同时开启 D cache 的强制透写
* @param 无
* @retval 无
*/
void sys_cache_enable(void)
{
SCB_EnableICache(); /* 使能 I-Cache,函数在 core_cm7.h 里面定义 */
SCB_EnableDCache(); /* 使能 D-Cache,函数在 core_cm7.h 里面定义 */
SCB->CACR |= 1 << 2; /* 强制 D-Cache 透写,如不开启透写,实际使用中可能遇到各种问题 */
}
更多推荐


所有评论(0)