cancel
Showing results for 
Search instead for 
Did you mean: 

CubeF4, when is a UART DMA transmission over ?

JulienD
Senior

Hello,

I'm sending data on UART using DMA with HAL_UART_Transmit_DMA().

As sometimes I need to send two messages consecutively, I'm testing if the previous

message is sent before preparing the new one. I do something like this:

void sendData(){
        uint8_t toSendCount;
        while (HAL_UART_GetState(usart) != HAL_UART_STATE_READY)
            ;
        s->size = 12;
        s->code = CommandConsts::GET_PARAMS;
        protocol->initTxFrame((uint8_t*)s, counter, txBuffer, &toSendCount);
        HAL_UART_Transmit_DMA(usart, txBuffer, toSendCount);
}

Generaly it works but sometimes, HAL_UART_GetState() never stop returning HAL_UART_STATE_BUSY_TX  

I'm using F446.

What should I do ? Which function(s) should I call? Which register should I check?

6 REPLIES 6
AvaTar
Lead

A DMA transmission is over when the last item (byte) is placed at the target address - the UART TX register in your case.

This, in turn, might depend on the hardware and your UART settings. If you use flow control, the other site can delay the transmissions.

Or you just run in one of Cube's randomly determined timeouts.

T J
Lead

this is how I check if the Tx DMA has completed,

works on F7 and F0 processors

void CheckTxDMABufferProgress(void) {
 if (TxDMABufHasData) {
  char uartState = HAL_UART_GetState(&huart7);
  if ((uartState == HAL_UART_STATE_READY) || (uartState == HAL_UART_STATE_BUSY_RX))    
  {
      TxDMABufHasData = false;	// sending now
      if (HAL_UART_Transmit_DMA(&huart7, (uint8_t *)Usart1TxDMABuffer + U1TxBufferPtrOUT,   
                                                                       U1TxBufferPtrIN - U1TxBufferPtrOUT) == HAL_OK) {
      		HAL_UART_Transmit_DMA_Status = UartDMAsuccess;
      		U1TxBufferPtrOUT = U1TxBufferPtrIN;
    	}

JulienD
Senior

@Community member​  Thanks, your method is a bit better than mine by chekcing busy_rx (but btw, I'm not using DMA for rx...)

T J
Lead

why not ?

the Rx DMA works very well and its endless.

Werner Dähn
Associate II

Is RX endless?

First, only if you set it to CIRCULAR, obviously.

Second, per my observation any error, even the slightest stops the "endless". Noise error, frame error, parity error.

So you need a place where you restart it. Agreed? Or is my observation wrong?

(I am still in the learning phase in regards to DMA, hence asking)

T J
Lead

I am not sure why my code is so stable.

I am not sure why I never fall into any error interrupt, probably not enabled.

I only initialise the DMA on startup, I have boards running here on test for over a year now.

Yes, you could probably check for the DMA "not ok" and restart it.

what that flag is, I am not sure, I never needed it.

I have a foreground process that checks some flags every mS and others every Second