AnsweredAssumed Answered

Usart TX with DMA : it doesn't send all buffer data

Question asked by Thomas Lotz on Sep 14, 2017
Latest reply on Sep 14, 2017 by waclawek.jan

Hello,

 

I try to use Usart Tx with DMA on a STM32L052K6, in order to send a string without needing to send each character independently. I don't use ISR. The Usart TX works well without DMA using HAL functions.

 

The problem : when I call my function UsartTxData, there is only 2 bytes that are transferred, whereas my string is 13 characters. I've checked with debugger that CNDTR is correctly loaded to the value 13.

As soon as TCIF = 1, there is only 2 bytes transferred instead of 13, I've check Tx signal with oscilloscope.

I can not find out the problem, can you please help me ?

 

Thanks !

Thomas

 

 

Main  :

char msg[20] = "page keybd   ";

#define BUFFER_SIZE        50

char TxBuffer[BUFFER_SIZE];

 

while(1)

{

    UsartTxData(msg);
    for(i=0;i<1000000;i++) RestartWdt();  // Delay

}

 

void UsartInit(void)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    // Peripheral clock enable
    __USART1_CLK_ENABLE();

    // USART1 GPIO Configuration
    // PB6     ------> USART1_TX
    // PB7     ------> USART1_RX
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF0_USART1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // DMA controller clock enable
    RCC->AHBENR |= RCC_AHBENR_DMA1EN;

    // Remap DMA channel2 on USART TX
    DMA1_CSELR->CSELR |= 0x011 << DMA_CSELR_C2S_Pos;

    // Configure the peripheral data register address
    DMA1_Channel2->CPAR = (uint32_t) (&(USART1->TDR));

    // Configure the memory address
    DMA1_Channel2->CMAR = (uint32_t)(TxBuffer);

    // Memory to memory transfer
    DMA1_Channel2->CCR |= DMA_CCR_MEM2MEM;

    // Memory increment mode enabled
    DMA1_Channel2->CCR |= DMA_CCR_MINC;

    // Data transfer direction, Read from memory
    DMA1_Channel2->CCR |= DMA_CCR_DIR;

    huart1.Instance = USART1;
    huart1.Init.BaudRate = 9600;
    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;
    huart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
    huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
    HAL_UART_Init(&huart1);

    // DMA USART TX Enable
    USART1->CR3 |= USART_CR3_DMAT;
}

 

 

void UsartTxData(char *data)
{

    // Check if Tx DMA is busy
    if(UsartTxBusy() == 1) return;

 

    // Clear status / interrupt flags
    DMA1->IFCR |= DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2;

 

    // Set transfer data size
    DMA1_Channel2->CNDTR = strlen(data);

 

    // Copy data to buffer
    strcpy(TxBuffer, data);

 

    // Set busy flag (used in UsartTxBusy())
    TxBusyFlag = 1;

 

    // Channel Enable - start transfer
    DMA1_Channel2->CCR |= DMA_CCR_EN;
}

 

 

uint8_t UsartTxBusy(void)
{
    if((DMA1->ISR & DMA_ISR_TCIF2) != 0)
    {
        TxBusyFlag = 0;
        DMA1_Channel2->CCR &= ~DMA_CCR_EN;

 

        // Clear status / interrupt flags
        DMA1->IFCR |= DMA_IFCR_CGIF2 | DMA_IFCR_CTCIF2 | DMA_IFCR_CHTIF2 | DMA_IFCR_CTEIF2;
    }
    return(TxBusyFlag);
}

Outcomes