cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4xx DMA IRQ problem

llombardini
Associate II
Posted on June 04, 2012 at 11:15

Hi all,

I'm using the STM Discovery EVM to make some sample program.

I'm using IAR as compiler and CMSIS 2.1

In this example I simple set a timer with 50ms period and start DMA transfert on USART 3

The transfer is correctly done on the serial port (I see the transmitted sting using Hyperterminal on PC), but I have a problem on the DMA IRQ Handler routine,

Infact when I check the TCIF flag I found that the DMA transfert is not complete (while the transfert is already done on serial port). Furthermore I check for any DMA tranfert error and I found that there are no error. Where I wrong?

Here The revelant part of the code:

First the define for DMA

/* Definition for DMAx resources **********************************************/

#define USARTx_DR_ADDRESS                ((uint32_t)USART3 + 0x04)

#define USARTx_DMA                       DMA1

#define USARTx_DMAx_CLK                  RCC_AHB1Periph_DMA1

   

#define USARTx_TX_DMA_CHANNEL            DMA_Channel_4

#define USARTx_TX_DMA_STREAM             DMA1_Stream3

#define USARTx_TX_DMA_FLAG_FEIF          DMA_FLAG_FEIF3

#define USARTx_TX_DMA_FLAG_DMEIF         DMA_FLAG_DMEIF3

#define USARTx_TX_DMA_FLAG_TEIF          DMA_FLAG_TEIF3

#define USARTx_TX_DMA_FLAG_HTIF          DMA_FLAG_HTIF3

#define USARTx_TX_DMA_FLAG_TCIF          DMA_FLAG_TCIF3

            

#define USARTx_RX_DMA_CHANNEL            DMA_Channel_4

#define USARTx_RX_DMA_STREAM             DMA1_Stream1

#define USARTx_RX_DMA_FLAG_FEIF          DMA_FLAG_FEIF1

#define USARTx_RX_DMA_FLAG_DMEIF         DMA_FLAG_DMEIF1

#define USARTx_RX_DMA_FLAG_TEIF          DMA_FLAG_TEIF1

#define USARTx_RX_DMA_FLAG_HTIF          DMA_FLAG_HTIF1

#define USARTx_RX_DMA_FLAG_TCIF          DMA_FLAG_TCIF1

#define USARTx_DMA_TX_IRQn               DMA1_Stream3_IRQn

#define USARTx_DMA_RX_IRQn               DMA1_Stream1_IRQn

#define USARTx_DMA_TX_IRQHandler         DMA1_Stream3_IRQHandler

#define USARTx_DMA_RX_IRQHandler         DMA1_Stream1_IRQHandler   

here the TX Buffer String

uint8_t TxBuffer[]= ''^**********************************************************************\r\n\

Prova di invio di caratteri alla seriale per vedere se ne perde qualcuno\r\n\

Cosi vediamo come si comporta il uP e il PC sperando che entrambi ce la facciano\r\n\

**********************************************************************@'';

Then the Timer IRQ Handler routine:

void TIM3_IRQHandler(void)

{

  if (TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET)

  {

    TIM_ClearITPendingBit(TIM3, TIM_IT_CC1);

    /* LED4 toggling with frequency = 4.57 Hz */

    STM_EVAL_LEDToggle(LED4);

    capture = TIM_GetCapture1(TIM3);

    TIM_SetCompare1(TIM3, capture + CCR1_Val);

    if (!DMASet)

       SetDMA();

    STM_EVAL_LEDToggle(LED4);

  }

}

Here MY routine for DMA settings

void SetDMA(void)

{

    DMASet = 1;

    DMA_DeInit(USARTx_TX_DMA_STREAM);

    DMA_InitStructureTX.DMA_PeripheralBaseAddr = USARTx_DR_ADDRESS;

    DMA_InitStructureTX.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

    DMA_InitStructureTX.DMA_MemoryInc = DMA_MemoryInc_Enable;

    DMA_InitStructureTX.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;

    DMA_InitStructureTX.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;

    DMA_InitStructureTX.DMA_Mode = DMA_Mode_Normal;

    DMA_InitStructureTX.DMA_Priority = DMA_Priority_VeryHigh;

    DMA_InitStructureTX.DMA_FIFOMode = DMA_FIFOMode_Enable;

    DMA_InitStructureTX.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

    DMA_InitStructureTX.DMA_MemoryBurst = DMA_MemoryBurst_Single;

    DMA_InitStructureTX.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

    DMA_InitStructureTX.DMA_Channel = USARTx_TX_DMA_CHANNEL;

    DMA_InitStructureTX.DMA_DIR = DMA_DIR_MemoryToPeripheral;  

    DMA_InitStructureTX.DMA_Memory0BaseAddr = (uint32_t)TxBuffer;

//    DMA_InitStructureTX.DMA_BufferSize = 300;

    DMA_InitStructureTX.DMA_BufferSize = 300;

//    DMA_InitStructureTX.DMA_BufferSize = (uint16_t)BUFFERSIZE;

    DMA_Init(USARTx_TX_DMA_STREAM, &DMA_InitStructureTX);

    /* Enable DMA1_Stream3 Transfer complete interrupt */

    DMA_ITConfig(USARTx_TX_DMA_STREAM, DMA_IT_TC, ENABLE);

    

//    /* Enable DMA1_Stream3 */

//    DMA_Cmd(USARTx_TX_DMA_STREAM, ENABLE);

//      

      

      /* Enable DMA USART Tx Stream */

      DMA_Cmd(USARTx_TX_DMA_STREAM, ENABLE);

}

At the end the DMA IRQ Handler routine

void DMA1_Stream3_IRQHandler(void)

{

//  STM_EVAL_LEDToggle(LED6);

  if(DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF))

  {

    DMA_ClearITPendingBit(DMA1_Stream3, DMA_IT_TCIF3);

//    /* Clear all DMA Streams flags */

////    DMA_ClearFlag(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_HTIF | USARTx_TX_DMA_FLAG_TCIF);

//    DMA_ClearFlag(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF);

//                                          

//    /* Disable the DMA Stream */

//    DMA_Cmd(USARTx_TX_DMA_STREAM, DISABLE);

//      

//    /* Disable the USART Tx DMA request */

//    USART_DMACmd(USARTx, USART_DMAReq_Tx, DISABLE);

      STM_EVAL_LEDToggle(LED6);

   }

  if (DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TEIF))

    STM_EVAL_LEDToggle(LED6);

  if (DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_HTIF))

    STM_EVAL_LEDToggle(LED6);

  if (DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_FEIF))

    STM_EVAL_LEDToggle(LED6);

 

}

4 REPLIES 4
Posted on June 04, 2012 at 17:22

Where I wrong?

USARTx_TX_DMA_FLAG_TCIF = DMA_FLAG_TCIF1

if(DMA_GetITStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF))

But DMA_GetITStatus expects DMA_IT_TCIF1

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
llombardini
Associate II
Posted on June 05, 2012 at 08:45

Hi Clive,

but I had define USART TX as Channel 4 stream 3

#define USARTx_TX_DMA_CHANNEL            DMA_Channel_4

#define USARTx_TX_DMA_STREAM             DMA1_Stream3

so I define the TCIF flag as ''stream 3''

#define USARTx_TX_DMA_FLAG_TCIF          DMA_FLAG_TCIF3

while the stream 1 of channel 4 is assigned to USART 3 RX channel (that is not used in this example)

This assignement is according to the ST reference manual pg 164.

Furthermore I enable (or I suppose that I do it) only the TX Tranfert complete IRQ

    /* Enable DMA1_Stream3 Transfer complete interrupt */

    DMA_ITConfig(USARTx_TX_DMA_STREAM, DMA_IT_TC, ENABLE);

So why you say that the DMA_GetITStatus expect TCIF1?

Thanks

Luca

llombardini
Associate II
Posted on June 05, 2012 at 09:26

Hi again Clive,

Maybe I understand what you meaning,

I used USARTxTX_DMA_FLAG_TCIF when I called DMA_GetITStatus, so I obtain wrong results.

If I want to use DMA_GetITStatus, I had to use DMA_IT_TCIFx.

  if(DMA_GetITStatus(USARTx_TX_DMA_STREAM, DMA_IT_TCIF3) != (uint32_t)RESET) 

while If I want to use USARTx_TX_DMA_FLAG_TCIF I have to use DMA_GetFlagStatus

//  if(DMA_GetFlagStatus(USARTx_TX_DMA_STREAM, USARTx_TX_DMA_FLAG_TCIF) != (uint32_t)RESET)

Now seems that the program working.

Thanks

Luca

Posted on November 16, 2016 at 09:32

Hi

I had a problem similar to the one you described here.

And now when i have solved it I thought it would be good to add a comment here to help others having similar problems.

I have a STM32F746 mcu running Free RTOS that should send audio to a audio codec using I2S and DMA. But I had some problems getting the interrupts signaling the DMA transfer complete and DMA transfer half complete to work.

It turned out that while following the examples from STM I had set the priority for the interrupts to 0, which was not permitted by Free RTOS (who permits a priority in the range of 5 down to 15.

HAL_NVIC_SetPriority(DMA1_Stream4_IRQn, 5, 0);

I had also a NULL-pointer exception which was hard to find. Since I had not found a good example where DMA and I2S was used together I had missed to link the DMA handler and the I2S handler.

__HAL_LINKDMA (i2sHandle, hdmatx, DmaHandle);

And of course I had to implement the interrupt function to handle the DMA stream interrupt.

void

DMA1_Stream4_IRQHandler (void)

{

  HAL_DMA_IRQHandler (i2sHandle.hdmatx);

}