0
\$\begingroup\$

I am using an STM32L4R5 board and am trying to configure the DMA on the UART2 line. I have managed to get the RX line to operate how I want, but when I follow "Transmission Using DMA" in section 44.5.19 of the "RM0432 Reference Manual" only one byte is transmitted and nothing else. This byte only gets sent when I explicitly write a byte to the TDR register. Afterwards, I can see the TC flag is cleared and the first byte of my DMA register is affected. How do I get the DMA to continously send out the data to the TDR for transmission?

Note: this problem seems to be simliar to an unanswered question here

The steps mentioned in the datasheet are as shown:

  1. Write the USART_TDR register address in the DMA control register to configure it as the destination of the transfer. The data is moved to this address from memory after each TXE (or TXFNF if FIFO mode is enabled) event.
  2. Write the memory address in the DMA control register to configure it as the source of the transfer. The data is loaded into the USART_TDR register from this memory area after each TXE (or TXFNF if FIFO mode is enabled) event.
  3. Configure the total number of bytes to be transferred to the DMA control register.
  4. Configure the channel priority in the DMA register
  5. Configure DMA interrupt generation after half/ full transfer as required by the application.
  6. Clear the TC flag in the USART_ISR register by setting the TCCF bit in the USART_ICR register.
  7. Activate the channel in the DMA register.

My code is here:

    //filling in dummy info into my DMA TX buffer
    memset((void*)DMA_USB_TXbuf, 0x55, 16);

    //ensuring my UART is configured for DMA Transfer
    huart2.Instance->CR3 |= USART_CR3_DMAT;

    //steps 1-4 taken care of within this funciton
    HAL_DMA_Start_IT(&hdma_usart2_tx, (uint32_t)&huart2.Instance->TDR, (uint32_t)&DMA_USB_TXbuf[0], DMA_USB_TX_SIZE);

    //step 5 (just ensuring that we have the flags we want after the previous function)
    __HAL_DMA_DISABLE(&hdma_usart2_tx);
    __HAL_DMA_ENABLE_IT(&hdma_usart2_tx, DMA_IT_HT);
    __HAL_DMA_ENABLE_IT(&hdma_usart2_tx, DMA_IT_TC);

    //step 6
    __HAL_UART_CLEAR_FLAG(&huart2, UART_CLEAR_TCF);

    //step 7
    __HAL_DMA_ENABLE(&hdma_usart2_tx);

    //I shouldn't need to do this, but this seems to be the only way
    // I get even 1 trasmission from DMA register
    WRITE_REG(huart2.Instance->TDR, 0x55);
\$\endgroup\$
4
  • \$\begingroup\$ Why don't you use HAL_USART_Transmit_DMA()? \$\endgroup\$
    – Codo
    Dec 10, 2019 at 15:51
  • 1
    \$\begingroup\$ @Codo I believe the function is called HAL_UART_Transmit_DMA() \$\endgroup\$
    – Maple
    Dec 10, 2019 at 16:00
  • \$\begingroup\$ The halfway mix between direct register access and library calls here is a bit suspect. Are there no DMA UART examples for your board? In general terms the HAL's xxx_IT functions are particularly notorious for doing something other than what their names or the perspective of typical application needs would imply they should, so many people end up attempting to use them in ways that won't do what is wanted. \$\endgroup\$ Dec 10, 2019 at 16:09
  • \$\begingroup\$ @Codo I was originally under the impression that function may do an undesirable pend, but now looking at the guts of the function I see that is not the case. I will try that out \$\endgroup\$
    – Beau R
    Dec 10, 2019 at 16:23

1 Answer 1

1
\$\begingroup\$

There were two parts to why this was not working as it should.

  1. As per comment by Codo, simply using this function worked for setting up and transmitting the UART DMA on the UART line
  2. My UART is configured with RTS/CTS flow control and my receiving line was not ready which was preventing more characters to be sent out.

Thank you Codo

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.