UART DMA Memory Corruption during Buffer Wrap-Around
I'm using HAL UART Receive with DMA (configured using CubeMX). I'm encountering a problem where data via UART, send in chunks, is corrupted if a chunk doesn't fit at the end of buffer perfectly. By chunks I mean a set of byte-sized data that is transmitted one following another in immediate manner.
I'm using a simple circular buffer struct where DMA is writing to. I check the CNDTR DMA Channel register to update "head" index of this software buffer. The only process that writes to this buffer is the DMA channel assigned to UART RX.
The following code shows how DMA and UART is configured from CubeMX:
/**
* @brief USART1 Initialization Function
* @PAram None
* @retval None
*/
static void MX_USART1_UART_Init(void)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/**
* Enable DMA controller clock
*/
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel1_IRQn);
/* DMA1_Channel5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
The following code shows how DMA UART channel is used:
HAL_UART_Receive_DMA(monHuart, (uint8_t *)rxCirBuff.buff, MONRX_CIRBUFF_SIZE);
while (1) {
rxCirBuff.head = MONRX_CIRBUFF_SIZE - __HAL_DMA_GET_COUNTER(monHuart->hdmarx);
}
The following two images show buffer state as it is loaded with F1 key codes delivered continuously by external keyboard. The valid chunk of bytes is as follows (decimal values): 27 -> 91 -> 49 -> 49 -> 126. The first image shows the buffer state before the last chunk arrives:
The second image shows the buffer state after the last chunk arrives, when buffer wrap-around happens. Note that now 30th byte is overwritten (probably) with the byte 91, however it should be 27 as for all other chunks. Note that DMA channel properly updates its counter index and the rest of the bytes are written properly without being corrupted.

Additionally note that this happens spontaneously, meaning sometimes the last chunk, being split into two parts, comes out valid. What could be the issue?
