AnsweredAssumed Answered

HAL_UART_Transmit_DMA issues

Question asked by baker.michael on Jun 2, 2015
Latest reply on Feb 25, 2018 by Roberto Roman
I am trying a simple test. I want to output a single character to the UART using DMA. 

I am using system workbench for stm32

First I tried configuring the DMA in normal mode.

huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
 
hdma_usart2_tx.Instance = DMA1_Stream6;
hdma_usart2_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_tx.Init.Mode = DMA_NORMAL;
hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart2_tx);
 
 __HAL_LINKDMA(huart,hdmatx,hdma_usart2_tx);

The only code I have added is this and code to blink LEDs in the while (1) loop:

/* USER CODE BEGIN 2 */
  HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"a",1);
  HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"b",1);
/* USER CODE END 2 */

In normal mode it outputs the character 'a' once then the lights begin to blink. The character 'b' is never put out to the uart.

If I do something like this
char testMessage[] = "test output of a longer string\r\n";

HAL_UART_Transmit_DMA(&huart2,(uint8_t*)&testMessage,sizeof(testMessage)-1);
HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"a",1);
HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"b",1);

I only get the testMessage array output. 'a' and 'b' are never put out to the uart

If I setup my code to use the DMA in circular mode as follows:

huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
 
hdma_usart2_tx.Instance = DMA1_Stream6;
hdma_usart2_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart2_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart2_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart2_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart2_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart2_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart2_tx.Init.Mode = DMA_CIRCULAR;
hdma_usart2_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart2_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
HAL_DMA_Init(&hdma_usart2_tx);
 
__HAL_LINKDMA(huart,hdmatx,hdma_usart2_tx);

Then run the first set out outputs again:

HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"a",1);
HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"b",1);

It outputs a continuous stream of the letter 'a' continuing while the lights are being blinked. 'b' is never output

When I output the string as well:

char testMessage[] = "test output of a longer string\r\n";
 
HAL_UART_Transmit_DMA(&huart2,(uint8_t*)&testMessage,sizeof(testMessage)-1);
HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"a",1);
HAL_UART_Transmit_DMA(&huart2,(uint8_t*)"b",1);

The testMessage array is sent repeatedly while the leds blink. 'a' and 'b are never output

Clearly I am missing something minor here. Reading document UM1725 "Description of STM32F4xx HAL drivers" page 846 has this to say about DMA on the uart:

"Send an amount of data in non blocking mode (DMA) using
HAL_UART_Transmit_DMA()
At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and
user can add his own code by customization of function pointer
HAL_UART_TxHalfCpltCallback
At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
add his own code by customization of function pointer HAL_UART_TxCpltCallback"

So what am I missing here? Why does circular mode just keep repeating the output and normal mode simply output once then stop all other outputs? 

Thank you for your assistance in this matter

Outcomes