cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F072CBU6 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!

 

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 {
    }
2 REPLIES 2
Karl Yamashita
Lead II

Use the </> to post your code so it's formatted.

If you find my answers useful, click the accept button so that way others can see the solution.
BarryWhit
Senior III

You say you use DMA to transfer data "from" the UARTs, but your DMA is tied to tx handle and uses DMA_MEMORY_TO_PERIPH. Which is it?

 

I normally use Cube generated code but, doesn't the initializing of values under hdma_usart1_tx.Init in preperation for calling some kind of HAL init function? without one, where are these values actually used?

 

How is DmaRingBuffer actually used as a ring buffer? is SerialUsartX.RingBufferIn a uint8_t?

 

When you say the data "seen" on uart2 is corrupted, where are you looking? are you talking about the data received by the other end?

 

 

- If someone's post helped resolve your issue, thank them by clicking "Accept as Solution".
- Once you've solved your issue, please post an update with any further details.