AnsweredAssumed Answered

STM32F030 UART TX via DMA only works once

Question asked by Conover.John on Oct 31, 2016
Latest reply on Nov 3, 2016 by Conover.John
Hi,

    I've seen similar questions to this but none seem to have helped. I'm transmitting on UART1 via DMA
channel 2 and the first transmission works fine. I am unable to get anything out after receiving a DMA
TC. None of the standard peripheral libraries examples show getting the DMA transmission to restart
after a completion. Here are the basics(code is shown below.)

1) After pin/uart/dma initialization I wait for a send_string call.
2) Send_string() sets up DMA1 channel 2 descriptor and size, then enables DMA1_Channel2.
3) Upon DMA TC, clear DMA1_IT_TC2 flag.

     I have tried going to using the UART TC interrupt(as suggested in other threads) but it never
seem to fire the interrupt. I'm sure it is something simple I need to clear/reset but I am unable to find
it.

Thanks,
     John C.

#ifdef SERIAL
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_0);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_0);
 
    // Configure the serial port on PB6(TX) and PB7(RX)
    GPIO_InitStructure.GPIO_Pin     = TX | RX;
    GPIO_InitStructure.GPIO_Mode    = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_OType   = GPIO_OType_PP;
    GPIO_InitStructure.GPIO_Speed   = GPIO_Speed_10MHz;
    GPIO_InitStructure.GPIO_PuPd    = GPIO_PuPd_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
#endif
#ifdef SERIAL
    USART_InitTypeDef USART_InitStructure;
 
    // USART configuration
    // BaudRate = 115200 baud, Word Length = 8 Bits
    // One Stop Bit, No parity,
    // Hardware flow control disabled (RTS and CTS signals)
    //Receive and transmit enabled
    USART_InitStructure.USART_BaudRate      = 115200;
    USART_InitStructure.USART_WordLength    = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits      = USART_StopBits_1;
    USART_InitStructure.USART_Parity        = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode          = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);
 
    /* Enable USART */
    USART_Cmd(USART1, ENABLE);
 
    /* Enable the USART1 Tx DMA1 requests */
    USART_DMACmd(USART1, USART_DMAReq_Tx, ENABLE);
 
    // USe DMA to transmit the serial data
    DMA_InitTypeDef   DMA_InitStructure;
 
    /* DMA1 Channel1 Config */
    DMA_DeInit(DMA1_Channel2);
    DMA_InitStructure.DMA_BufferSize            = SERIAL_TX_SIZE;
    DMA_InitStructure.DMA_PeripheralDataSize    = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize        = DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_PeripheralInc         = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryInc             = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_Mode                  = DMA_Mode_Normal;
    DMA_InitStructure.DMA_M2M                   = DMA_M2M_Disable;
    DMA_InitStructure.DMA_MemoryBaseAddr        = (uint32_t)infoString;
    DMA_InitStructure.DMA_DIR                   = DMA_DIR_PeripheralDST;
    DMA_InitStructure.DMA_PeripheralBaseAddr    = (uint32_t)&(USART1->TDR);
 
    DMA_InitStructure.DMA_Priority              = DMA_Priority_High;
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);
 
    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
#endif
 
#ifdef SERIAL
    /* Enable the USART Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel          = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority  = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd       = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
 
        NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
    NVIC_SetPriority(DMA1_Channel2_3_IRQn,0);
#endif
 
void DMA1_Channel2_3_IRQHandler(void)
{
    if ((DMA1->ISR & DMA_ISR_TCIF2) != 0) /* Test if transfer completed on DMA channel 2 */
    {
        txTail++;
        txTail &= (MAX_SERIAL_TX_BUFFS-1);
 
        // Clear the interrupt pending flag
        DMA_ClearFlag(DMA1_FLAG_TC2);
        DMA_ClearITPendingBit(DMA_ISR_TCIF2);
 
        //DMA_ClearITPendingBit(DMA1_IT_GL2);
        //USART_ClearFlag(USART1, USART_FLAG_IDLE);
        //USART_ClearFlag(USART1, USART_ISR_TXE);
 
 
    }
}
 
void uart1_send(const char *string_p)
{
size_t  size;
 
    size = strlen(string_p);
    if (size)
    {
        uart1TX[txHead].txCount = 0;
 
        strcpy(uart1TX[txHead].txBuffer, string_p);
        DMA1_Channel2->CMAR     = (uint32_t)uart1TX[txHead].txBuffer;
        DMA1_Channel2->CNDTR    = size;
 
        uart1TX[txHead].txSize  = size;
        txHead++;
        txHead &= (MAX_SERIAL_TX_BUFFS-1);
 
        DMA_Cmd(DMA1_Channel2, ENABLE);
    }
}

 

 

Outcomes