AnsweredAssumed Answered

Error using UART and DMA

Question asked by Pablo Cottens on Feb 27, 2018
Latest reply on Feb 28, 2018 by T J



I am building an application in olimex e407. It's running FreeRTOS, lwIP, I'm running the ADC @10kHz triggered by timer and getting the data via DMA and I also want to communicate with an external uC via UART and DMA. 


For the solo UART implementation I did everything according to the reference manual and I also compared my code with some codes I found on the internet that were supposedly working. I can get to the point that I can send the UART transmission via DMA, then somewhere during the DMA reception an error occurred and it wouldn't work anymore. 


After a little bit of manually messing with the registers I noticed that I needed to clear the SR, more specifically, the idle flag and it started working. I could create a task that would send and receive data every second. 


When I tried putting everything together, the DMA would lock upt the entire system and FreeRTOS could no longer run anymore tasks. I can see, from what I've read on the internet that there is something wrong with the way I'm handling the error, but I have no idea how to proceed with this. 


PS: I also noticed that the uart handle has a rState of busy and a gState of ready, as well as the problem with the registers. I'm also communicating at 9600, nothing that should cause an overrun, at least in my opinion. 


huart.Instance = USART6;
huart.Init.BaudRate = 9600;
huart.Init.WordLength = UART_WORDLENGTH_8B;
huart.Init.StopBits = UART_STOPBITS_1;
huart.Init.Parity = UART_PARITY_NONE;
huart.Init.Mode = UART_MODE_TX_RX;
huart.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart.Init.OverSampling = UART_OVERSAMPLING_16;


hdma_usart_tx.Instance = DMA2_Stream6;
hdma_usart_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart_tx.Init.Mode = DMA_NORMAL;
hdma_usart_tx.Init.Priority = DMA_PRIORITY_LOW;
hdma_usart_tx.Init.Channel = DMA_CHANNEL_5;


hdma_usart_rx.Instance = DMA2_Stream1;
hdma_usart_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart_rx.Init.Mode = DMA_NORMAL;
hdma_usart_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_usart_rx.Init.Channel = DMA_CHANNEL_5;

This is my configuration, obviously I call the LINK macro, the proper init functions and finally HAL_UART_Receive_DMA and HAL_UART_Transmit_DMA. 


My error handling function basically consists on forcing a Ready state and clearing SR bits. I even clear bits in the USART6 IRQhandler. 


Can anyone point me in the right direction? Is it maybe a bug in the HAL library? Probably not, but I'd really like to make sure. Tomorrow I'll try new things and update the question, but if anyone is feeling generous and knows what's wrong, please let me know