cancel
Showing results for 
Search instead for 
Did you mean: 

How to run HAL_UART_Transmit_DMA this for a second time?

vishnu_illikkal
Associate III

I am trying to send data from a buffer to a GSM module. The buffer contains the AT commands. For each communication this will vary. If i use the Circular mode the transfer will not end. But when i am trying to use the Normal mode so that i can control when to send data I cannot use the  HAL_UART_Transmit_DMA  function. This function only works once. Please Help.

4 REPLIES 4
FBL
ST Employee

Hello @vishnu_illikkal 

 

This one shot mode is suitable when the DMA is programmed to transfer a fixed number of data.

 

If the amount of data you need to send to the GSM module varies for each communication, then it may be more appropriate to use DMA in circular mode. This allows you to continuously transfer data from the buffer to the GSM module without having to specify a fixed number of data items. 

 

If you need to stop the transfer at some point, you can call the HAL_UART_DMAStop function to disable the DMA controller.

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

Pavel A.
Evangelist III

@vishnu_illikkal Transmit and receive are not symmetrical. You want to transmit in normal mode, each span separately - otherwise you are not able to stop the transmit after sending the last byte. In MCUs that have advanced DMA with transfer lists it would be done with several spans of random size and address, but not on STM32H7.

I am sending data to the GSM module using the normal polling mode.
And i am receiving data using 

HAL_UARTEx_ReceiveToIdle_DMA
in Normal Mode because in Circular mode i cannot get the call back

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)

Also I had a problem when the buffer to receive is in another file than the main.c file the data is not getting received


 

#ifdef USE_UART_DMA_FOR_TALKING_WITH_GSM

uint8_t RxBuf[GSM_RESPONSE_BUFFER_SIZE];

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size){

 

print_text("Inside HAL_UARTEx_RxEventCallback", GSM_TRACE);

strcpy((char *)gsm_response_buffer, (char *)RxBuf);

for(int i = 0; i <= Size; i++ ){

RxBuf[i] = '\0';

}

HAL_UARTEx_ReceiveToIdle_DMA(&huart8, RxBuf, GSM_RESPONSE_BUFFER_SIZE);

__HAL_DMA_DISABLE_IT(&hdma_uart8_rx, DMA_IT_HT);

}

#endif

 

This is the callback function

 

#ifdef USE_UART_DMA_FOR_TALKING_WITH_GSM

HAL_UARTEx_ReceiveToIdle_DMA(&huart8, RxBuf, GSM_RESPONSE_BUFFER_SIZE);

__HAL_DMA_DISABLE_IT(&hdma_uart8_rx, DMA_IT_HT);

#endif

This is the starting function that initially sets up the uart

I needed to use 2 buffers RxBuf and gsm_response_buffer which finally holds the data
Any idea why this happens?

 

LCE
Principal

But when i am trying to use the Normal mode so that i can control when to send data I cannot use
> the  HAL_UART_Transmit_DMA  function. This function only works once.

Please debug and find out where it fails.

DMA in circular mode for UART TX doesn't make sense (or I can't see it), normal mode is working here without problems.

 

in UART TX complete callback:	
/* DMA NORMAL mode */
	if( hdma->Init.Mode == DMA_NORMAL )
	{
		/* disable the DMA TX request by resetting the DMAT bit in UART CR3 register */
		ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);

		/* enable the UART Transmit Complete Interrupt */
		ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
	}

 

You also have to take care not to start another DMA TX until the current is complete, maybe that's your problem.