AnsweredAssumed Answered

STM32F103 USART DMA issue

Question asked by Mat on Feb 26, 2014
Latest reply on Feb 27, 2014 by Mat
Hi all,

I have a problem using the DMA with USART3 on an STM32F103 MCU:
I've configured the USART3 to transmit a buffer (fixed length) one shot using the DMA (just transmitting, not receiving) and then stop transmitting.

Once I've enabled the DMA and the uart starts to transmit bits, it never ends.... the behavior I see (using an oscilloscope) is the same I should get configuring the DMA in circular mode... but my DMA is in NormalMode...  so my code never gets into the DMA1_Channel2 TC interrupt.
Is there any other settings to do or any flag to clear in some interrupt handler?

I hope someone's able to help me... Tanks!


I've configured USART and DMA in the following way:

UartLayer_comLayerSetup(void) 
{
     // USART Init Structures
     GPIO_InitTypeDef GPIO_InitStructure;
     USART_InitTypeDef USART_InitStructure;
     NVIC_InitTypeDef NVIC_InitStructure;


     // Enabling bus clocks
     RCC_APB2PeriphClockCmd(HWCONF_USART_RCC_PORT | HWCONF_USART_BUS, ENABLE);
     RCC_APB1PeriphClockCmd(HWCONF_USART_APB_USART, ENABLE);


     // USART3 ---------------------------------------------------------------------------
     
     // COnfigure Pins
     GPIO_InitStructure.GPIO_Pin = HWCONF_USART_TX_PIN;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
     GPIO_Init(HWCONF_USART_PORT, &GPIO_InitStructure);     
     
     GPIO_InitStructure.GPIO_Pin = HWCONF_USART_RX_PIN;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     GPIO_Init(HWCONF_USART_PORT, &GPIO_InitStructure);


     // Set USART Parameters
     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_Mode = USART_Mode_Rx | USART_Mode_Tx;
     USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
     
  // USART 3 INTERRUPT CONFIGUTATION -> used in receiving mode on the RXNE flag
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
     NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
     
     //Write USART parameters
     USART_Init(HWCONF_USART_NUM, &USART_InitStructure);


     // DMA Tx interrupt configuration
     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
     NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
     NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
     NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
     NVIC_Init(&NVIC_InitStructure);
     
     DMA_DeInit(DMA1_Channel2);
     DMA_TX_InitStructure.DMA_PeripheralBaseAddr           = (uint32_t)&(USART3)->DR;               // Specifies the peripheral base address for DMAxChannely
  DMA_TX_InitStructure.DMA_DIR                                                   = DMA_DIR_PeripheralDST;                    // Specifies the DMA direction
  DMA_TX_InitStructure.DMA_PeripheralInc                          = DMA_PeripheralInc_Disable;          // Specifies whether the peripheral address register should be incremented or not
  DMA_TX_InitStructure.DMA_MemoryInc                                    = DMA_MemoryInc_Enable;                         // Specifies whether the memory address register should be incremented or not
  DMA_TX_InitStructure.DMA_PeripheralDataSize           = DMA_PeripheralDataSize_Byte;     // Specifies the peripheral data width
  DMA_TX_InitStructure.DMA_MemoryDataSize                     = DMA_MemoryDataSize_Byte;               // Specifies the memory data width
  DMA_TX_InitStructure.DMA_Mode                                              = DMA_Mode_Normal;                                   // Specifies the operation mode of the DMAxChannely
  DMA_TX_InitStructure.DMA_Priority                                    = DMA_Priority_High;                              // Specifies the software priority for the DMAxChannely
  DMA_TX_InitStructure.DMA_M2M                                                   = DMA_M2M_Disable;                                   // Disable MemoryToMemory feature

     USART_Cmd(HWCONF_USART_NUM, ENABLE);
}


void USART3_IRQHandler(void) 
{
     // If a byte has been received
     if (USART_GetITStatus(HWCONF_USART_NUM, USART_IT_RXNE) != RESET) 
     {
          //trace('c');
          uint8_t TmpRecByte = USART_ReceiveData(HWCONF_USART_NUM); // Reading byte
          
          USART_ClearITPendingBit(HWCONF_USART_NUM, USART_IT_RXNE); // Clearing Interrupt Flag
          
          _ComInterface_processByte(COM_UART, TmpRecByte);
     }
}

void _StartTxDMA(const uint8_t * dataBuffer, uint32_t dataSize)
{
     // Setting the TX Pin in Output Pull'up
     GPIO_InitTypeDef GPIO_InitStructure;
     GPIO_InitStructure.GPIO_Pin = HWCONF_USART_TX_PIN;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
     GPIO_Init(HWCONF_USART_PORT, &GPIO_InitStructure);
     
     
     // Preparing the DMA transaction from memory to USART
     DMA_DeInit(DMA1_Channel2);
     DMA_TX_InitStructure.DMA_MemoryBaseAddr = (uint32_t)dataBuffer;
     DMA_TX_InitStructure.DMA_BufferSize               = dataSize;
     DMA_Init(DMA1_Channel2, &DMA_TX_InitStructure);
     
     // Enable USART TX DMA request
     USART_DMACmd(USART3, USART_DMAReq_Tx, ENABLE);
     USART_ClearFlag(USART3, USART_FLAG_TC);
     
     // Enable DMA Interrupts
     DMA_ITConfig(DMA1_Channel2, DMA1_IT_TC2 | DMA1_IT_TE2, ENABLE);
     
     // Enable DMA stream -> start transfert
     DMA_Cmd(DMA1_Channel2, ENABLE);
}

Outcomes