Skip to main content
Explorer
August 26, 2024
Question

STM32 DMA UART Transfer Issues

  • August 26, 2024
  • 1 reply
  • 869 views

I am using the DMA to transfer data from UART 1 (Channel 2) and UART 2 (Channel 4). Every once and awhile the data seen on UART 2 which has a lower DMA priority will be "corrupted" by the UART 1 data. I know this because when I disable UART 1 routines, UART 2 receives perfectly everytime. This is never an issue with transmission on UART 2 even when UART 1 is enabled.

This is on the STM32F072CBU6 MCU. Both DMA protocols are initialized identically for UART 1 and UART 2.

I will post most of the code related to these functions.

Any ideas would be greatly appreciated!

NOTE: This is a repost because the last post was marked as spam...

UART Initializations:

 

uint32_t Tmp;

huart1.Instance = USART1;

STM32_GPIO_Init(RS485_TXD_GPIO_Port, RS485_TXD_Pin, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_HIGH, GPIO_AF1_USART1, 0);
STM32_GPIO_Init(RS485_RXD_GPIO_Port, RS485_RXD_Pin, GPIO_MODE_AF_PP, GPIO_PULLUP, GPIO_SPEED_FREQ_HIGH, GPIO_AF1_USART1, 0);

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;

Tmp = hdma_usart1_tx.Instance->CCR;
Tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | DMA_CCR_DIR));
Tmp |= DMA_MEMORY_TO_PERIPH | DMA_PINC_DISABLE | DMA_MINC_ENABLE |
DMA_PDATAALIGN_BYTE | DMA_MDATAALIGN_BYTE | DMA_NORMAL | DMA_PRIORITY_LOW;
hdma_usart1_tx.Instance->CCR = Tmp;
hdma_usart1_tx.ChannelIndex = (((uint32_t)hdma_usart1_tx.Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2u;
hdma_usart1_tx.DmaBaseAddress = DMA1;
hdma_usart1_tx.XferCpltCallback = NULL;

huart1.hdmatx = &hdma_usart1_tx;
hdma_usart1_tx.Parent = &huart1;

STM32_NVIC_SetPriority(USART1_IRQn, 0, 0);
STM32_NVIC_EnableIRQ(USART1_IRQn);

USART1->CR1 &= ~USART_CR1_UE;
USART1->CR1 = 0x0C;
USART1->CR2 = 0x00;
USART1->CR3 = 0x3000;
USART1->BRR = 417;
USART1->CR1 = 0x2D;

 

 

 

 

UART IRQ Handler:

 

 uint32_t ISRFlags;
 uint32_t ControlReg1its;

 ISRFlags = huart->Instance->ISR;
 ControlReg1its = huart->Instance->CR1;

 //
 // Clear Errors - even if there aren't any
 //
 huart->Instance->ICR = UART_CLEAR_PEF | UART_CLEAR_FEF | UART_CLEAR_NEF | UART_CLEAR_OREF;

 /* UART in mode Receiver */
 if (huart->Instance == USART1) {
 if (((ISRFlags & USART_ISR_RXNE) != 0) && ((ControlReg1its & USART_CR1_RXNEIE) != 0)) {
 SerialUsart1.DmaRingBuffer[SerialUsart1.RingBufferIn++] = (uint8_t)huart->Instance->RDR;
 return;
 }
 }
 else if (huart->Instance == USART2) {
 if (((ISRFlags & USART_ISR_RXNE) != 0) && ((ControlReg1its & USART_CR1_RXNEIE) != 0)) {
 SerialUsart2.DmaRingBuffer[SerialUsart2.RingBufferIn++] = (uint8_t)huart->Instance->RDR;
 return;
 }
 }

 /* UART in mode Transmitter (transmission end) -----------------------------*/
 if (((ISRFlags & USART_ISR_TC) != 0) && ((ControlReg1its & USART_CR1_TCIE) != 0)) {
 UART_EndTransmit_IT(huart);
 }

 

 

 

 

DMA Initialization:

 

 uint32_t Tmp;

 Tmp = hdma->Instance->CCR;
 Tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | DMA_CCR_DIR));
 Tmp |= hdma->Init.Direction |
 hdma->Init.PeriphInc | hdma->Init.MemInc |
 hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
 hdma->Init.Mode | hdma->Init.Priority;
 hdma->Instance->CCR = Tmp;
 hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2u;
 hdma->DmaBaseAddress = DMA1;
 hdma->XferCpltCallback = NULL;

 

 

 

 

DMA Interrupt Handler:

 

 uint32_t FlagIt = hdma->DmaBaseAddress->ISR;
 uint32_t SourceIt = hdma->Instance->CCR;

 /* Transfer Complete Interrupt management ***********************************/

 if ((RESET != (FlagIt & (DMA_FLAG_TC1 << hdma->ChannelIndex))) && (RESET != (SourceIt & DMA_IT_TC))) {
 if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0u) {
 /* Disable the transfer complete & transfer error interrupts */
 /* if the DMA mode is not CIRCULAR */
 hdma->Instance->CCR &= ~(DMA_IT_TC | DMA_IT_TE);
 }

 /* Clear the transfer complete flag */
 hdma->DmaBaseAddress->IFCR = DMA_FLAG_TC1 << hdma->ChannelIndex;

 if (hdma->XferCpltCallback != NULL) {
 /* Transfer complete callback */
 hdma->XferCpltCallback(hdma);
 }
 /* Transfer Error Interrupt management ***************************************/
 } else if ((RESET != (FlagIt & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (SourceIt & DMA_IT_TE))) {
 /* When a DMA transfer error occurs */
 /* reset the processor */
 Error_Handler(FILE_DMA, __LINE__);
 } else {
 }

 

 

 

 

 

 

 

    This topic has been closed for replies.

    1 reply

    ST Employee
    August 28, 2024

    Hello @Churby

    Could you also share UART2 configuration?