cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 DMA UART Transfer Issues

Churby
Visitor

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

 

 

 

 

 

 

 

0 REPLIES 0