AnsweredAssumed Answered

STM32F4 DMA large block transfer

Question asked by Gregorsanec.Toni on Jan 21, 2014
Latest reply on Jan 22, 2014 by Gregorsanec.Toni
Hello to all,

I am writing application which uses peripheral to memory DMA transfer. When transfers are
smaller than 65535 items written in NDTR register everything is working fine.To be able to support large piece of data transfer I have modified DMA interrupt handler like this:

void DMA2_Stream1_IRQHandler(void)
{   
    /* DMA Transfer Complete Interrupt */
    if(DMA_GetITStatus(DMA2_Stream1, DMA_IT_TCIF1)) 
    {
        DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TCIF1);
        if(pic_frame_size > 0)
        {
          DMA_Cmd(DMA2_Stream1, DISABLE);
          while((DMA_GetCmdStatus(DMA2_Stream1)) != DISABLE);

          if(pic_frame_size <= 65532)
            DMA_InitStructure.DMA_BufferSize = pic_frame_size;
          else
            DMA_InitStructure.DMA_BufferSize = 65532;
  
          pic_frame_size_proc = DMA_InitStructure.DMA_BufferSize;
          pic_frame_size -= pic_frame_size_proc; 
          g_dma_cycle++;
          
          DMA_InitStructure.DMA_Memory0BaseAddr = (buffer + (SDRAM_DMA_ADDR_BLOCK * g_dma_cycle));


          DMA_Init(DMA2_Stream1, &DMA_InitStructure);


          DMA_Cmd(DMA2_Stream1, ENABLE);         
          while((DMA_GetCmdStatus(DMA2_Stream1)) != ENABLE);
        }else
          tx_ready = 1;
    }else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_HTIF1)) 
    {
         DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_HTIF1);
    }else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_TEIF1)) 
    {
         DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_TEIF1);
    }else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_DMEIF1)) 
    {
      DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_DMEIF1);
    }else if (DMA_GetITStatus(DMA2_Stream1, DMA_IT_FEIF1)) 
    {
         DMA_ClearITPendingBit(DMA2_Stream1, DMA_IT_FEIF1);
    }
}

Data are transferred to the external 16 bit wide SDRAM, while peripheral is 32 bit wide.
The problem I am experiencing is, that DMA_IT_TCIF1 is set even NDTR register is not 0,
what is stated in data sheets and also observed when number of items are less then 65535. 
The second interrupt which happens is  DMA_IT_HTIF1, which should not happen. 
I done DMA setup like this:

    DMA_InitStructure.DMA_Channel = DMA_Channel_1; 
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;


    pic_frame_size = FRAME_BUFFER_SIZE/4;
    if(pic_frame_size <= 65532)
      DMA_InitStructure.DMA_BufferSize = pic_frame_size;
    else
      DMA_InitStructure.DMA_BufferSize = 65532;
  
    pic_frame_size_proc = DMA_InitStructure.DMA_BufferSize;
    pic_frame_size -= pic_frame_size_proc;

    DMA_InitStructure.DMA_Memory0BaseAddr = buffer;
    DMA_InitStructure.DMA_PeripheralBaseAddr = DCMI_DR_ADDR;     
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word;
    DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
    DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;
    DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
    DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_INC4;
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;

    DMA_Init(DMA2_Stream1, &DMA_InitStructure);

Could be something wrong with DMA setup?

I will appreciate any help.

Outcomes