2017-07-31 07:08 PM
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.
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 #stm32f02017-07-31 07:49 PM
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.
2017-07-31 09:05 PM
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);
2017-08-01 02:29 AM
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.
2017-08-01 02:51 AM
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
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:
From this figure,
write pin code is executed after DMA transmit
.Why is SPI DMA transmit different from UART DMA transmit execute time sequence?
2017-08-01 03:35 AM
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.
2017-08-01 06:53 AM
Yes, the code is already there in
stm32f0xx_it.c
: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.
2017-08-01 07:02 AM
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.