cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F205,UART DMA transfer stuck after a while

BSELL.11
Associate

Hello to everyone,

Thank's to the people who will take time to read my problem.

To be short, I'm working on a system which embed a STM32F205 MCU. This system can communicate with other similar systems by exchanging UART messages over an RS485 physical layer.

A ring topology is used between the systems, which induces that each system has 2 UARTs, one for the messages from the previous system, one for the messages for the next system.

DMA in circular mode is used to send and receive the packets. Currently the system is working well during hours/days/weeks, but at one moment, when it tries to transmit a packet to the UART peripheral using DMA, it stays stuck at the following condition :

while(DMA_GetCmdStatus(DMA2_Stream6) != DISABLE){;}     

Below is the part of the code where the DMA transfer is done :

//REDE activation for RS485 transfer
GPIO_SetBits(OUT_DIG_REDE_1_GPIO_PORT,OUT_DIG_REDE_1_PIN);
 
//Number of data to be transferred
DMA_SetCurrDataCounter(DMA2_Stream6,ModbusStructure->MessageEnvoyeStructure->taille);
 
//Enable the DMA Tx stream
DMA_Cmd(DMA2_Stream6, ENABLE);
 
//wait until DMA stream disable meaning transfert complete
while(DMA_GetCmdStatus(DMA2_Stream6) != DISABLE){;}          

Here is the DMA initialisation for the corresponding UART

DMA_InitTypeDef DMA_InitStructure;
    
/* Enable DMAy's AHB1 interface clock */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMAy, ENABLE);
 
/* Configure DMAy Streamx channel_x from USARTx to the RxBuffer table */
DMA_StructInit(&DMA_InitStructure);
 
DMA_InitStructure.DMA_Channel = DMA_Channel_x;
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t) &((USARTx)->DR);
DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t) &buffer[0];
DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
DMA_InitStructure.DMA_BufferSize = 256;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; 
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
 
/* Attendre la désactivation du DMA avant de le configurer */
while(DMA_GetCmdStatus(DMAy_Streamx)!=DISABLE)  
{
    DMA_Cmd(DMAy_Streamx, DISABLE);
}
  
DMA_Init(DMAy_Streamx, &DMA_InitStructure);
 
USART_DMACmd(USARTx, USART_DMAReq_Tx, ENABLE);

And here is the DMA configuration :

USART_Cmd(EVAL_COM1, DISABLE);
USART_InitStructure.USART_BaudRate = 115200;
USART_InitStructure.USART_WordLength = USART_WordLength_9b;
USART_InitStructure.USART_StopBits = USART_StopBits_1;
USART_InitStructure.USART_Parity = USART_Parity_Even;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(EVAL_COM1,&USART_InitStructure);
                                        
NVIC_InitStructure.NVIC_IRQChannel = USART6_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
                                        
USART_ITConfig(EVAL_COM1, USART_IT_TC, ENABLE);
USART_ITConfig(EVAL_COM1, USART_IT_IDLE, ENABLE);
                                        
USART_SetAddress(EVAL_COM1, 1);
USART_WakeUpConfig(EVAL_COM1, USART_WakeUp_IdleLine);
                                        
USART_Cmd(EVAL_COM1, ENABLE);
                                        
/*active DMA */
DMA_ConfigUsartReception(RCC_AHB1Periph_DMA2 ,DMA2_Stream1, DMA_Channel_5, USART6, (uint32_t*) DMARxBuffer1);
DMA_ConfigUsartEmission(RCC_AHB1Periph_DMA2 ,DMA2_Stream6, DMA_Channel_5, USART6, (uint32_t*) DMATxBuffer1);

Also, when the transfer stucked, here are the different values of the parameters of the DMA stream struct. I noticed that the NDTR value is always the number of data to be transmitted minus 1, like only one data have been transmitted.

I already tried when stucked to deInit and Init the UART and DMA but with no luck.

Thanks by advance for anyone who can help me with my problem.

Best regards.

3 REPLIES 3

What do you use, SPL?

> //wait until DMA stream disable meaning transfert complete

>while(DMA_GetCmdStatus(DMA2_Stream6) != DISABLE){;}

I don't understand. Where is the stream disabled? You've said, it's in Circular mode - in that mode, only user can disable the stream.

When the problem happens, read out and post the DMA registers content, including the status register.

JW

BSELL.11
Associate

Thank you JW for your reply.

Yes, I'm using the standard peripheral librairies.

Sorry I made a mistake, in transfert mode the DMA is defined on normal. It's in receive mode that the DMA stream is defined in circular.

> DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

And as indicated in the reference manual, the enable bit in the DMA_SxCR register is cleared by software once the NDTR reach 0 .

I indeed checked the DMA stream register which I failed to join to my post. On the picture we can see NDTR stuck on 3 while it was trying to transfert a message of 4 packets. 0693W00000BaapLQAR.pngMissed to check the DMA status register, I will post that the next time I can catch a crash.

This looks quite normal.

If you catch the crash, besides DMA registers, read out and post also content of USART registers. Please make all registers display in hexadecimal.

JW