Skip to main content
markgilson9
Associate III
December 14, 2011
Question

DMA Double Buffer IRQ

  • December 14, 2011
  • 15 replies
  • 2915 views
Posted on December 14, 2011 at 20:35

I currently have code which runs on the STM32F4-Discovery board and DMA's data from the ADC to a buffer.  I am using double buffering, so I can operate on one buffer while the other is being filled.  In short, my code works; both buffers are correctly filled with data.  The problem I'm having is that I'm interrupted at the end of filling both, when I really want to be interrupted when the first has been filled and the other one just starts getting filled by the DMA.  Some of my code is below:

DMA_InitStructure.DMA_Channel = DMA_Channel_2;  

  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)ADC3_DR_ADDRESS;

  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)&ADCBuf[0];

  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;

  DMA_InitStructure.DMA_BufferSize = 800;

  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;

  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;

  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;

  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;

  DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;

  DMA_InitStructure.DMA_Priority = DMA_Priority_High;

  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;         

  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;

  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;

  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

  DMA_DoubleBufferModeConfig(DMA2_Stream0, (uint32_t)&ADCBuf[1], DMA_Memory_0);

  DMA_DoubleBufferModeCmd(DMA2_Stream0, ENABLE);

  

  DMA_ITConfig(DMA2_Stream0, DMA_IT_HT | DMA_IT_TC | DMA_IT_TE, ENABLE);

  DMA_Cmd(DMA2_Stream0, ENABLE);

I then enable the interrupt:

void NVIC_Configuration(void)

{

  NVIC_InitTypeDef NVIC_InitStructure;

  /* Configure and enable DMA interrupt */

  NVIC_InitStructure.NVIC_IRQChannel = DMA2_Stream0_IRQn;

  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);

}

And then finally I have the IRQHandler reset the interrupt flags:

void DMA2_Stream0_IRQHandler()

{

DMA_ClearFlag(DMA2_Stream0, DMA_IT_HT | DMA_IT_TC | DMA_IT_TE);

}

Any ideas as to how to be able to interrupt immediately following the filling of the first buffer?  I'm wondering if I have to use 2 separate streams?  Thanks in advance.
    This topic has been closed for replies.

    15 replies

    markgilson9
    Associate III
    January 24, 2012
    Posted on January 24, 2012 at 22:16

    It looks like within the IRQ_Handler I see the LISR register value as either 0x00000030, or 0x00000020, which tells me that I'm interrupting due to Half-Transfer and Transfer Complete (correct?).  

    What's wierd is that I'm only enabling TC and TE:

    DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE, ENABLE);

    Why would Half-Transfer trigger interrupts?  I also notice that even though I clear the interrupts twice within the IRQHandler, only the half transfer bit clears:

    DMA_ClearFlag(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE);

    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE);

    I must be missing something.

    Tesla DeLorean
    Guru
    January 24, 2012
    Posted on January 24, 2012 at 23:10

    I must be missing something.

    Yes, that

    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE);

    should be

    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0 | DMA_IT_TEIF0);

    and you don't need the ClearFlag code

    #define DMA_IT_TC                         ((uint32_t)0x00000010)

    #define DMA_IT_TE                         ((uint32_t)0x00000004)

    #define DMA_IT_TEIF0                      ((uint32_t)0x10002008)

    #define DMA_IT_HTIF0                      ((uint32_t)0x10004010)

    #define DMA_IT_TCIF0                      ((uint32_t)0x10008020)

    /**

      * @brief  Clears the DMAy Streamx's interrupt pending bits.

      * @param  DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0

      *          to 7 to select the DMA Stream.

      * @param  DMA_IT: specifies the DMA interrupt pending bit to clear.

      *          This parameter can be any combination of the following values:

      *            @arg DMA_IT_TCIFx:  Streamx transfer complete interrupt

      *            @arg DMA_IT_HTIFx:  Streamx half transfer complete interrupt

      *            @arg DMA_IT_TEIFx:  Streamx transfer error interrupt

      *            @arg DMA_IT_DMEIFx: Streamx direct mode error interrupt

      *            @arg DMA_IT_FEIFx:  Streamx FIFO error interrupt

      *         Where x can be 0 to 7 to select the DMA Stream.

      * @retval None

      */

    void DMA_ClearITPendingBit(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT)

    /**

      * @brief  Enables or disables the specified DMAy Streamx interrupts.

      * @param  DMAy_Streamx: where y can be 1 or 2 to select the DMA and x can be 0

      *          to 7 to select the DMA Stream.

      * @param DMA_IT: specifies the DMA interrupt sources to be enabled or disabled.

      *          This parameter can be any combination of the following values:

      *            @arg DMA_IT_TC:  Transfer complete interrupt mask

      *            @arg DMA_IT_HT:  Half transfer complete interrupt mask

      *            @arg DMA_IT_TE:  Transfer error interrupt mask

      *            @arg DMA_IT_FE:  FIFO error interrupt mask

      * @param  NewState: new state of the specified DMA interrupts.

      *          This parameter can be: ENABLE or DISABLE.

      * @retval None

      */

    void DMA_ITConfig(DMA_Stream_TypeDef* DMAy_Streamx, uint32_t DMA_IT, FunctionalState NewState)

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    markgilson9
    Associate III
    January 25, 2012
    Posted on January 25, 2012 at 17:08

    Excellent catch, thanks clive1!

    Tesla DeLorean
    Guru
    January 25, 2012
    Posted on January 25, 2012 at 17:27

    Excellent catch, thanks clive1!

    Bit of bastard isn't it? Who thought that was a good idea?

    There aren't that many examples to be found either, I just thought to look because you said it wasn't clearing, and the bit values didn't jive.

    I think you'll find HT signals, but isn't gated to the NVIC based on you not enabling it.

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    raffael
    Associate II
    January 26, 2012
    Posted on January 26, 2012 at 09:36

    Thanks for your posts.

    As you mentioned there aren't many examples...

    Thanks to this posts I could implement dual simultaneous ADC to double buffer very fast.