cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F07X using DMA transmit UART fail

AMP HF
Associate II
Posted on August 01, 2017 at 04:08

First, I introduce the background simply. I have program the STM32F072RB for somedays. I do this project start with STM32CubeMX.

It�s going well until now. I have using the 2 DMA for SPI transmit before. And I want to reduce MCU�s work, so I change MCU transmit function (HAL_UART_Transmit) to DMA transmit (HAL_UART_Transmit_DMA). But the MCU would do nothing when it executes this code.

The uart works well before I change the uart transmit to DMA transmit.

The DMA configuration is shown below.

0690X00000607mBQAQ.png

The code:

static void MX_DMA_Init(void)

{

/* DMA controller clock enable */

__HAL_RCC_DMA1_CLK_ENABLE();

/* DMA interrupt init */

/* DMA1_Channel2_3_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Channel2_3_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);

/* DMA1_Channel4_5_6_7_IRQn interrupt configuration */

HAL_NVIC_SetPriority(DMA1_Channel4_5_6_7_IRQn, 0, 0);

HAL_NVIC_EnableIRQ(DMA1_Channel4_5_6_7_IRQn);

}

My question is, what�s wrong with the DMA transmit?

#dma-transfer #uart #stm32f0
7 REPLIES 7
Posted on August 01, 2017 at 04:49

Hard to say, you're going to have to dig into the code a little to understand what the auto-mated tool generated.

I'd suggest looking at the IRQ Handler, and how that dispatches things. And then look at the registers, see if the DMA is flagging errors, or has some issue.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
Zt Liu
Senior III
Posted on August 01, 2017 at 06:05

You may check:

   In your xxx_msp.c, is the corresponding dma configured as you setup in cubeMx

/* Configure the DMA handler for Transmission process */

hdma_tx.Instance = USARTx_TX_DMA_CHANNEL;

hdma_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_tx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_tx.Init.MemInc = DMA_MINC_ENABLE;

hdma_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_tx.Init.Mode = DMA_NORMAL;

hdma_tx.Init.Priority = DMA_PRIORITY_LOW;

HAL_DMA_Init(&hdma_tx);

/* Associate the initialized DMA handle to the UART handle */

__HAL_LINKDMA(huart, hdmatx, hdma_tx);

Posted on August 01, 2017 at 09:29

Thanks for your reply.

The code in XX_hal_msp.c :

/* Peripheral DMA init*/

hdma_usart1_tx.Instance = DMA1_Channel2;

hdma_usart1_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;

hdma_usart1_tx.Init.PeriphInc = DMA_PINC_DISABLE;

hdma_usart1_tx.Init.MemInc = DMA_MINC_ENABLE;

hdma_usart1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

hdma_usart1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;

hdma_usart1_tx.Init.Mode = DMA_NORMAL;

hdma_usart1_tx.Init.Priority = DMA_PRIORITY_LOW;

if (HAL_DMA_Init(&hdma_usart1_tx) != HAL_OK)

{

Error_Handler();

}

__HAL_LINKDMA(huart,hdmatx,hdma_usart1_tx);

It's consistent with my setting in MXCube.

AMP HF
Associate II
Posted on August 01, 2017 at 11:51

I have found the resaon that DMA transmit fail.

I use MAX3088 as RS485 interface between MCU and PC. But MAX3088 is a half-duplex device. So, if I need to transmit data, I would enable the DE PIN firstly.

The code is:

            HAL_GPIO_WritePin(GPIOA,UART1_DE_Pin,GPIO_PIN_SET);

            HAL_UART_Transmit_DMA(&huart1,Test_DMA,23);

            HAL_GPIO_WritePin(GPIOA,UART1_DE_Pin,GPIO_PIN_RESET);

And I catch the scope shown below:

CH1: Yellow, DE signal

CH2: Green, UART_Tx

0690X00000607ndQAA.png0690X00000607nnQAA.png

From this figure, I think MCU execute the HAL_UART_Transmit_DMA function then do the next code,

do not wait the HAL_UART_Transmit_DMA

.

And the DE pulse width is the DMA code execution time. Cause the DE pin status change too soon, so I cannot receive anything on PC.

But when I use DMA transmit for SPI, I would not meet this issue.

My code in SPI transmit:

HAL_SPI_Transmit_DMA(&hspi1,dataS,3);

 HAL_GPIO_WritePin(GPIOA,SPI1_NSS_Pin, GPIO_PIN_SET);

 HAL_GPIO_WritePin(GPIOA,SPI1_NSS_Pin, GPIO_PIN_RESET);

And the scope is shown below:

0690X00000607o2QAA.png

From this figure,

write pin code is executed after DMA transmit

.

Why is SPI DMA transmit different from UART DMA transmit execute time sequence?

Amel NASRI
ST Employee
Posted on August 01, 2017 at 12:35

Hi

‌,

Even if DMA is used, it is required to add the USART interrupt handler into your stm32f0xx_it.c:

void USARTx_IRQHandler(void){ HAL_UART_IRQHandler(&UartHandle);}�?�?�?�?

It is related to this sequence to handle 'Transmission using DMA' (see RM0091, paragraph 'USART continuous communication in DMA mode') :'Clear the TC flag in the USART_ISR register by setting the TCCF bit in the USART_ICR register'.

-Amel

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.

Posted on August 01, 2017 at 13:53

Yes, the code is already there in

stm32f0xx_it.c 

:0690X00000607nJQAQ.png

In my last reply, I compare the SPI DMA transmit and UART DMA transmit. 

And my  question is about the code execution time sequence.

In SPI DMA transmit code, after DMA transmit, the GPIO status is changed.

But in the UART tranmit code, the GPIO status is changed before DMA transmit complete.

Posted on August 01, 2017 at 14:02

Looks like the DMA command returns immediately, rather than blocking, you'd need to wait for it the actually complete before pulling the GPIO low.

Generally the purpose of DMA is to allow the CPU to do some productive work rather than sit in a loop blocking. If your architecture is unable to run other tasks you could use a loop polling and pumping other processing.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..