STM32H7B3i上USART DMA模式下收發數據異常問題


問題描述:開啟D-Cache后,從USART DMA通道口接收、發送的數據與實際數據不對;

原因分析:1.D-Cach內部緩存報錯數據,而沒有寫入RAM

                  2.DMA從RAM內存加載數據

4種解決方案:1.禁用D-Cache,操作最簡單,但會犧牲一部分性能;可以用於調試,分析問題是否與D-Cache有關。

                        2.關閉部分內存的D-Cache。 這可以通過配置內存保護單元(MPU)來實現。 缺點是MPU區域有特定的對齊限制,您需要將DMA緩沖區放置到內存的特定部分。 每個工具鏈(GCC、IAR、KEIL)需要以不同的方式配置。
                           注意MPU區域可以重疊,高的區域號優先。 與子區域禁用位一起,這可以用來軟化對齊和大小限制。
                           注意,設備和強順序內存類型不允許對內存的非對齊訪問。
                        3.將部分內存配置為透寫。 只能用於TX DMA。 類似於前面的選項。
                        4.使用緩存維護操作。 對於特定的地址范圍,可以將存儲在緩存中的數據寫回內存("clean"操作),也可以丟棄存儲在緩存中的數據("invalidate"操作)。 缺點是這些操作的緩存行大小是32個字節,所以你不能從緩存中清除單個字節或使其失效。 當RX緩沖區與其他數據或TX緩沖區“共享”緩存線時,這可能會導致錯誤(請參見下圖)。

 

 

 


                           注意,對於未初始化的D-Cache,維護操作“clean”或“clean and invalidate”可能會導致BusFault異常。 這是由於上電復位后ECC(糾錯碼)未初始化造成的。 如果你的項目需要大量的維護操作,想要暫時關閉D-Cache,你可以使用SCB_InvalidateDCache功能,它會清理緩存,設置正確的ECC,而不是啟用它。

 

我使用了第四種方法:

     接收使用:Invalid

DMABuffer_t rxBuffer;

getRxBuffer(&buffer);

SCB_InvalidateDCache_by_Addr((uint32_t *)rxBuffer.addr,rxBuffer.size);
if (HAL_UART_Receive_DMA(huart, (uint8_t *)rxBuffer.addr, rxBuffer.size) != HAL_OK)
{
/* Transfer error in transmission process */
Error_Handler();
}

       發送使用:Clean

static DMABuffer_t buffer;
getTxBuffer(&buffer);

SCB_CleanDCache_by_Addr((uint32_t *)buffer.addr,buffer.size);//SCB_CleanDCache();
if (HAL_UART_Transmit_DMA(huart, (uint8_t *)buffer.addr, buffer.size) != HAL_OK)//
{
/* Transfer error in transmission process */
Error_Handler();
}

    數據使用32byte對齊

uint8_t m_rxBuffer[MAX_RX_BUFFER_SIZE] __attribute__ ((aligned (32)));
uint8_t m_txBuffer[MAX_TX_BUFFER_SIZE] __attribute__ ((aligned (32)));

 

 

參考引用出處,詳見:https://community.st.com/s/article/FAQ-DMA-is-not-working-on-STM32H7-devices


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM