STM32H7使用函数SCB_InvalidateDCache_by_Addr,SCB_CleanDCache_by_Addr等函数注意事项
特别注意下面这三个函数的形参addr和dsize:addr : 操作的地址一定要是32字节对齐的。
dsize :一定要是32字节的整数倍
static/image/hrline/4.gif
/**
\brief D-Cache Invalidate by address
\details Invalidates D-Cache for the given address
\param addr address (aligned to 32-byte boundary)
\param dsize size of memory block (in number of bytes)
*/
__STATIC_INLINE void SCB_InvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
int32_t op_size = dsize;
uint32_t op_addr = (uint32_t)addr;
int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
__DSB();
while (op_size > 0) {
SCB->DCIMVAC = op_addr;
op_addr += (uint32_t)linesize;
op_size -= linesize;
}
__DSB();
__ISB();
#endif
}
/**
\brief D-Cache Clean by address
\details Cleans D-Cache for the given address
\param addr address (aligned to 32-byte boundary)
\param dsize size of memory block (in number of bytes)
*/
__STATIC_INLINE void SCB_CleanDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
int32_t op_size = dsize;
uint32_t op_addr = (uint32_t) addr;
int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
__DSB();
while (op_size > 0) {
SCB->DCCMVAC = op_addr;
op_addr += (uint32_t)linesize;
op_size -= linesize;
}
__DSB();
__ISB();
#endif
}
/**
\brief D-Cache Clean and Invalidate by address
\details Cleans and invalidates D_Cache for the given address
\param addr address (aligned to 32-byte boundary)
\param dsize size of memory block (in number of bytes)
*/
__STATIC_INLINE void SCB_CleanInvalidateDCache_by_Addr (uint32_t *addr, int32_t dsize)
{
#if defined (__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
int32_t op_size = dsize;
uint32_t op_addr = (uint32_t) addr;
int32_t linesize = 32; /* in Cortex-M7 size of cache line is fixed to 8 words (32 bytes) */
__DSB();
while (op_size > 0) {
SCB->DCCIMVAC = op_addr;
op_addr += (uint32_t)linesize;
op_size -= linesize;
}
__DSB();
__ISB();
#endif
}
dsize :一定要是32字节的整数倍
这条要求,貌似从来没有注意过,现在是不管什么大小都往里面填 文档里写了cache是32字节对齐的,之前确实有时候用有时候没用{:18:},偶尔就会出点问题 研究越来越透彻了啊,之前只主要地址是 32对齐,数据大小还没有怎么注意过啊,看来以后也得多多注意才行 这个问题要特别引起注意。 Solution example 3: Use Cache maintenance functionsTransmitting data:#define TX_LENGTH(16)
uint8_t tx_buffer;
/* Write data */
tx_buffer = 0x0;
tx_buffer = 0x1;
/* Clean D-cache */
/* Make sure the address is 32-byte aligned and add 32-bytes to length, in case it overlaps cacheline */
SCB_CleanDCache_by_Addr((uint32_t*)(((uint32_t)tx_buffer) & ~(uint32_t)0x1F), TX_LENGTH+32);
/* Start DMA transfer */
HAL_UART_Transmit_DMA(&huart1, tx_buffer, TX_LENGTH);Receiving data:#define RX_LENGTH(16)
uint8_t rx_buffer;
/* Invalidate D-cache before reception */
/* Make sure the address is 32-byte aligned and add 32-bytes to length, in case it overlaps cacheline */
SCB_InvalidateDCache_by_Addr((uint32_t*)(((uint32_t)rx_buffer) & ~(uint32_t)0x1F), RX_LENGTH+32);
/* Start DMA transfer */
HAL_UART_Receive_DMA(&huart1, rx_buffer, RX_LENGTH);
/* No access to rx_buffer should be made before DMA transfer is completed */Please note that in case of reception there can be problem if rx_buffer is not aligned to the size of cache-line (32-bytes), because during the invalidate operation another data sharing the same cache-line(s)with rx_buffer can be lost.
参考文献:https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices
la9998372 发表于 2020-9-3 14:32
Solution example 3: Use Cache maintenance functionsTransmitting data:Receiving datalease note that ...
除了你帖的这个,还要注意H7的串口DMA有个硬件bug,务必要使用最新的HAL库
/* Work around for Errata 2.22: UART/USART- DMA transfer lock: DMA stream could be
lock when transfering data to/from USART/UART */
#if (STM32H7_DEV_ID == 0x450UL)
if((DBGMCU->IDCODE & 0xFFFF0000U) >= 0x20000000U)
{
#endif /* STM32H7_DEV_ID == 0x450UL */
if(IS_DMA_UART_USART_REQUEST(hdma->Init.Request) != 0U)
{
registerValue |= DMA_SxCR_TRBUFF;
}
#if (STM32H7_DEV_ID == 0x450UL)
}
#endif /* STM32H7_DEV_ID == 0x450UL */
la9998372 发表于 2020-9-3 14:32
Solution example 3: Use Cache maintenance functionsTransmitting data:Receiving datalease note that ...
另外他这个接收数据回复有问题,应该是DMA接收后做无效化而不是DMA接收前作无效化。他们这个文章这部分有问题,应该给他们提出下。 eric2013 发表于 2020-9-3 15:28
另外他这个接收数据回复有问题,应该是DMA接收后做无效化而不是DMA接收前作无效化。他们这个文章这部分有 ...
是不是就是说,DMA接收完一帧数据之后,需要进行数据解析之前,进行Cache无效话处理? la9998372 发表于 2020-9-6 21:34
是不是就是说,DMA接收完一帧数据之后,需要进行数据解析之前,进行Cache无效话处理?
对,一般是这样的。 本帖最后由 zhoudn 于 2021-12-14 16:02 编辑
E:\123.pngV5.1.1版core_cm7.h文件好像已经对dsize做了字节对齐操作 zhoudn 发表于 2021-12-14 15:53
V5.1.1版core_cm7.h文件好像已经对dsize做了字节对齐操作
修改了好,更规范了。 eric2013 发表于 2021-12-14 16:19
修改了好,更规范了。
搞不清楚为啥既然采用do..while形式对dsize做了32字节对齐,但是op_addr地址32字节对齐却注释掉了? eric2013 发表于 2021-12-14 16:19
修改了好,更规范了。
这句话是不是说SCB->DCCIMVAC寄存器仅31-5位是有效的,本身已经强制32位对齐了,那以后是不是可以直接传入地址和数据了,不需要再对地址和数据进行32位对齐了,我在编程手册上也没找到对DCCIMVAC寄存器的详细描述
谁知道 这个 SCB_InvalidateDCache_by_Addr和 SCB_CleanInvalidateDCache_by_Addr 这个两个的区别是什么 zhoudn 发表于 2021-12-16 11:54
这句话是不是说SCB->DCCIMVAC寄存器仅31-5位是有效的,本身已经强制32位对齐了,那以后是不是可以直接传 ...
他这个的设置来的,还不够全面,最好按照楼主位的再设置下。 dghwjh 发表于 2021-12-21 13:17
谁知道 这个 SCB_InvalidateDCache_by_Addr和 SCB_CleanInvalidateDCache_by_Addr 这个两个的区别是什 ...
SCB_CleanInvalidateDCache_by_Add比SCB_InvalidateDCache_by_Addr多了Clean操作,Clean操作的含义是将Cache里面的新内容刷到实际存储器中。 如果dsize没有32字节对齐,是不是会出现将变量前面或者后面的数据也刷掉,改变前后变量的值 addr:我看到STM32代码好像也是有自动向前对齐这个操作,哎。。。。 eric2013 发表于 2018-11-10 01:27
这个问题要特别引起注意。
我们HAL库版本不一样?实际使用发现这玩意有bug{:20:},感谢向前偏移会导致数据刷新错误
嵌入式菜鸟^_^ 发表于 2024-1-30 18:46
如果dsize没有32字节对齐,是不是会出现将变量前面或者后面的数据也刷掉,改变前后变量的值
如果不能保证整数倍和对齐,不要使用这个函数控制。 eric2013 发表于 2024-1-31 00:43
如果不能保证整数倍和对齐,不要使用这个函数控制。
求教一下哪使用什么函数比较好 嵌入式菜鸟^_^ 发表于 2024-1-31 09:39
求教一下哪使用什么函数比较好
函数SCB_InvalidateDCache或者SCB_CleanInvalidateDCache
页:
[1]