cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 USART DMA issue

matteo239955
Associate III
Posted on February 26, 2014 at 15:29

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);

}
10 REPLIES 10
matteo239955
Associate III
Posted on February 27, 2014 at 18:18

Hi All again...

Thank to your suggestion, I've completed the UART/DMA and it works perfectly.

My actual problem is the following:

I'm using the uart with dma to receive a fixed length (10 bytes) packet and it works correctly... I receive hundreds of correct packet with no problem but there is a condition where I need to reset the MCU...

well, after the reset the usart gets only the first byte and then nothing else... it seems like that something disables the DMA (but nothing really does it).

If instead I wait for about 2 seconds after the reset and then start to send packets, everything works correctly.

I've checked insisde the reference manual and seeked in the forum but didn't find something similar... 

Does somebody know if there is any flag time to wait before start using the usart/dma after the core startup?

Thanks and regards

Mat