cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 DMA UART Transfer Issues

Churby
Associate II

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 {
    }

 

 

 

 

 

 

 

1 REPLY 1
Sarra.S
ST Employee

Hello @Churby

Could you also share UART2 configuration?

 

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.