2017-08-09 06:50 PM
Hi!
On both STM32F405 and STM32F745:
We use circular mode DMA RX. It works fine until the first frame or hight noise error occurs (which rarely but happen).
After the error DMA stops working. Naive calling HAL_UART_Receive_DMA doesn't help.
How to re-enable circular DMA receive again using STM32 HAL drivers? Or how to make DMA ignore framing and noising errors?
Details:
1. When error occurs, UART_DMAAbortOnError is called from DMA IRQ and it triggers HAL_UART_ErrorCallback where we see frame or high noise error HAL_UART_GetError.
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
if (huart == &huart6)
{
// How to restore dma work here????
// Last try witch is definately an overkill but it doesn't work
__HAL_UART_CLEAR_PEFLAG(&huart6);
HAL_UART_DMAStop(&huart6);
HAL_UART_MspDeInit(&huart6);
HAL_UART_MspInit(&huart6);
HAL_UART_Receive_DMA(&huart6, rxBuffer, DUD_RX_BUFFER_LEN);
// Also tried like but didn't work
// HAL_UART_DMAStop(&huart6);
// HAL_UART_Receive_DMA(&huart6, rxBuffer, DUD_RX_BUFFER_LEN);
// And tried some other combinations
// Shows FRAMING or HIGH noise ERROR
//sprintf(dbgSndBuff, 'UART6 error %i DMA error %i \r\n', HAL_UART_GetError(&huart6), HAL_DMA_GetError(&hdma_usart6_rx));
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
2. We have 'standard' CubeMX initialization code:
/* USART6 init function */
void MX_USART6_UART_Init(void)
{
huart6.Instance = USART6;
huart6.Init.BaudRate = 1000000;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart6) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
/* USART6_RX Init */
hdma_usart6_rx.Instance = DMA2_Stream1;
hdma_usart6_rx.Init.Channel = DMA_CHANNEL_5;
hdma_usart6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart6_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart6_rx.Init.Mode = DMA_CIRCULAR;
hdma_usart6_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_usart6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart6_rx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(uartHandle,hdmarx,hdma_usart6_rx);
/* USART6_TX Init */
hdma_usart6_tx.Instance = DMA2_Stream6;
hdma_usart6_tx.Init.Channel = DMA_CHANNEL_5;
hdma_usart6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart6_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart6_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart6_tx.Init.Mode = DMA_NORMAL;
hdma_usart6_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_usart6_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart6_tx) != HAL_OK)
{
_Error_Handler(__FILE__, __LINE__);
}
__HAL_LINKDMA(uartHandle,hdmatx,hdma_usart6_tx);
�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
3. CubeMX version 4.22,
STM32CubeF7 Firmware Package V1.7.0, STM32CubeF4 Firmware Package V1.0
P.S. Our protocol has data consistency check, so in general we don't care about single UART errors, so if DMA would ignore errors should work for us fine too.
#error #stm32 #hal #dma #uart2017-08-10 04:36 PM
Hello!
Calling HAL functions(not all functions) inside a HAL callback in handler mode, is an known issue that causes HAL Lock !!
Find another way, at least , not to call theese functions from inside callback.
check theese functions if fits to your needs.
UART_DMARxAbortCallback(...
UART_DMAAbortOnError(...
HAL_UART_AbortReceive_IT(
Inside relevant .c files you will find a lot of explanation about the use of functions.
Regards.
2017-09-18 04:05 AM
We have the same problem on a STM32F051 device. At the moment the only solution that seems working for us is to comment (into the original HAL_UART_IRQHandler routine) these lines :
huart->ErrorCode |= HAL_UART_ERROR_FE; //-> framing error is not longer visible
huart->ErrorCode |= HAL_UART_ERROR_NE;
// -> noise error is not longer visible
huart->ErrorCode |= HAL_UART_ERROR_ORE;
// ->
overrun
error is longer not visible
[Also in our case the protocol has data consisency check, so we can trap in a higher level bad frames]
2018-06-01 02:04 AM
We also have a 'standard' CubeMX circular DMA UART setup, which stops on error. Caused us some headaches, but ultimately able to resolve it thusly:
In DMA mode, a comms error actually triggers a DMA end of transfer interrupt (not a UART error). The DMA HAL picks this up, aborts the DMA and then calls the registered
XferAbortCallback
(seestm32f4xx_hal_dma.c:883
) which is actuallyUART_DMAAbortOnError
. That then callsHAL_UART_ErrorCallback
, so once that callback runs the DMA is already aborted. Further, it turns out only a deliberate call toHAL_UART_Abort_IT
ends up callingHAL_UART_AbortCpltCallback
, so in DMA mode UART DMA restoration needs to happen inHAL_UART_ErrorCallback
.In the end, all we did is call
HAL_UART_Receive_DMA()
fromHAL_UART_ErrorCallback
(once the error is logged/otherwise dealt with). No init/de-init, flag clearing or error suppressing necessary.To the OP: is it possible you missed the simplest one-statement option in your efforts?
Anyone else solved it otherwise?