Skip to main content
matteo239955
Associate II
February 26, 2014
Question

STM32F103 USART DMA issue

  • February 26, 2014
  • 10 replies
  • 2183 views
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);

}
    This topic has been closed for replies.

    10 replies

    Tesla DeLorean
    Guru
    February 26, 2014
    Posted on February 26, 2014 at 15:58

    The code is incomplete, lack defines, and won't compile

    No DMA interrupt implemented

    The USART RXNE interrupt is not enabled

    DMA_ITConfig(DMA1_Channel2, DMA1_IT_TC2 | DMA1_IT_TE2, ENABLE); // No I don't think so!

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    matteo239955
    Associate II
    February 26, 2014
    Posted on February 26, 2014 at 16:05

    Yes I know Clive1 that many parts of the code are missing because it's quite distributed... I've just posted the USART/DMA configurations...

    What do you mean with your comment '' // No I don't think so!'' ? 

    I've missed any flag or used something inappropriate?

    anhhuy0701
    Associate III
    February 26, 2014
    Posted on February 26, 2014 at 16:12

    waclawek.jan
    Super User
    February 26, 2014
    Posted on February 26, 2014 at 16:15

    > Yes I know Clive1 that many parts of the code are missing because it's quite distributed... I've just posted the USART/DMA configurations...

    Prepare and post a minimal, but complete and compilable example, exhibiting your problem.

    JW

    waclawek.jan
    Super User
    February 26, 2014
    Posted on February 26, 2014 at 16:24

    > hello admin, how can I post a question on this forum?

    0690X000006051FQAQ.png

    Tesla DeLorean
    Guru
    February 26, 2014
    Posted on February 26, 2014 at 16:33

    What do you mean with your comment '' // No I don't think so!'' ?  I've missed any flag or used something inappropriate?

     

    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC | DMA_IT_TE, ENABLE)

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    matteo239955
    Associate II
    February 26, 2014
    Posted on February 26, 2014 at 16:38

    Thank you very mutch clive1... it was just that mistake... now works!

    I'm sorry for the confusion I've created.... next time I will try to better describe the problem with a more complete code

    Thanks again!

    Mat

    stm322399
    Senior
    February 26, 2014
    Posted on February 26, 2014 at 16:40

    DMA_TX_InitStructure is obviously global, are you sure it is not modified anywhere else ?

    waclawek.jan
    Super User
    February 26, 2014
    Posted on February 26, 2014 at 17:03

    > DMA_ITConfig(DMA1_Channel2, DMA1_IT_TC2 | DMA1_IT_TE2, ENABLE); // No I don't think so!

    > DMA_ITConfig(DMA1_Channel2, DMA_IT_TC | DMA_IT_TE, ENABLE)

    I say, you deserved it, for using the ''library''... ;)

    JW

    matteo239955
    Associate II
    February 27, 2014
    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