Skip to main content
Graduate II
July 18, 2025
Question

UART DMA not transmitting data properly

  • July 18, 2025
  • 6 replies
  • 914 views

Hi,

I am working on a project and having the following problem:
My UART DMA is not working. I am transmitting a string, that should be visible in the terminal but it is not. The TX complete callback function is being triggered, so it looks like it works but there is nothing in the terminal.

Previously, I was using UART without DMA and things were working fine. It confirms that the hardware connections and the VCP connections are correctly set up.

 

What I have done so far:

- I enabled UART2, tested UART (without DMA). It worked well.

- I enabled DMA which gave me:

fa31_0-1752840534623.png

 

- Then I set up GPDMA1 for huart2_TX and huart2_RX. My TX configs are:

Screenshot 2025-07-18 140925.png

 

My main function:

int main(void)
{
 HAL_Init();
 SystemClock_Config();

 MX_GPIO_Init();
 MX_GPDMA1_Init();
 MX_ICACHE_Init();
 MX_USART2_UART_Init();


 /* Infinite loop */
 while (1)
 {
	 static uint32_t counter = 0;
	 sprintf((char *)pTxBuff, "Count: %lu\r\n", counter++);
	 if (huart2.gState == HAL_UART_STATE_READY) {
	 HAL_UART_Transmit_DMA(&huart2, pTxBuff, strlen((char *)pTxBuff));
	 }
	 HAL_Delay(1000);
 }
}

 

Does anyone have insights into why UART2 DMA transmission is not functioning correctly and why no output is appearing on the terminal, despite the transmission complete callback being triggered?

Thanks!

 

    This topic has been closed for replies.

    6 replies

    Technical Moderator
    July 18, 2025

    Hello,

    What product are you using and what board are you using?

    Super User
    July 18, 2025

    @fa31 wrote:

    Previously, I was using UART without DMA and things were working fine.


    If you go back to that, does it still work?

    fa31Author
    Graduate II
    July 20, 2025

    Yes it does. I remove the "_DMA" from the hal transmit function and I am able to send data and I can see it on the terminal.

    fa31Author
    Graduate II
    July 18, 2025

    I am using:

    CubeMX: to generate the code        Version: 6.14.1

    CubeIDE: to debug the code            Version: 1.18.1

    Board: Nucleo WBA65RI

    Super User
    July 18, 2025
    fa31Author
    Graduate II
    July 19, 2025

    I am using:

    CubeMX: to generate the code        Version: 6.14.1

    CubeIDE: to debug the code            Version: 1.18.1

    Board: Nucleo WBA65RI

    fa31Author
    Graduate II
    July 21, 2025

    Even though I had trustzone disabled in my initial project, I noticed that trustzone option byte is enabled on my microcontroller. I tried disabling it using CubeProgrammer but was unable to do so. So instead, I generated a trustzone project with secure and nonsecure project. And now I have enabled both, the uart and DMA, on the nonsecure side. But it is still reacting the exact same way, transmit and transmit_IT works but transmit_DMA prints nothing to the terminal. 

    Are there any GTZS or SAU configs I need to fix? Does the DMA not working properly have something to do with the permissions around being able to access the memory?

    fa31Author
    Graduate II
    July 30, 2025

    Noticed the following:

    The following code does not work. It prints nothing to the terminal, but is able to trigger the callback function:

    uint8_t transmission_buffer[20];
    strcpy((char *)transmission_buffer, "Hello World");
    HAL_UART_Transmit_DMA(&huart2, transmission_buffer, strlen((char *)transmission_buffer));
    HAL_Delay(1000);



    While the following works perfectly:

    HAL_UART_Transmit_DMA(&huart2, (uint8_t *)"Hello World", 12);
    HAL_Delay(1000);

     

    Why does the second implementation works as expected, but the first one does not produce any output?

    Super User
    July 30, 2025

    In your first code, is the transmission_buffer local to a function?

    If it is, it effectively ceases to exist when that function exits.

    Your buffer needs to remain until the transmission completes - so make it global, or static.

    fa31Author
    Graduate II
    July 30, 2025

    Thank you for the reply @Andrew Neil !
    Yes, the variable is local to the function. And I have tried the following:

    • Local to the function (without static)
    • Local to the function (with static)
    • Globally
    • Static to the file

    But nothing seems to be working. 

    Visitor II
    July 30, 2025

    Hey! It sounds like you’ve done a solid job narrowing things down—especially confirming that UART works without DMA and that the TX complete callback fires. That rules out hardware and basic UART config, which is a strong starting point.

     

    That said, one common issue is buffer accessibility. Make sure pTxBuff is in a memory region that's accessible by DMA. If you’re using cacheable memory or regions like DTCM on certain STM32 devices, the DMA controller might not be able to read from it reliably. Also, ensure your DMA stream is properly configured—check the direction (memory-to-peripheral), addresses, and length. Even if the TX complete callback is triggered, it doesn’t guarantee that data was successfully pushed out; it just means the DMA operation completed.

     

    Another thing worth reviewing is whether the peripheral (USART2) itself is receiving the buffer content correctly. Try with a static string like "Hello\r\n" to rule out formatting issues from sprintf. If that works, then dynamic string handling or memory alignment might be at fault.

     

    Also, take caching into account. If you're on STM32H7 or U5, and cache is enabled, you might need to clean or invalidate the cache before DMA can reliably access the memory. Adding HAL functions like SCBCleanDCachebyAddr() for the buffer before calling HALUARTTransmitDMA can sometimes resolve this.

     

    Lastly, make sure you’re not missing DMA IRQ enabling or callback linking. Review MXGPDMA1Init to ensure nothing is misconfigured and confirm your HALUARTTxCpltCallback is implemented and doesn’t suppress errors silently.