STM32 DMA transfer error

15,154

I just finished my SDIO+DMA this days, some notes maybe useful for you:

  1. Clear Flags before enabling the stream

    DMA_ClearFlag(DMA2_Stream2, DMA_FLAG_FEIF2|DMA_FLAG_DMEIF2|DMA_FLAG_TEIF2|DMA_FLAG_HTIF2|DMA_FLAG_TCIF2);
    
  2. Clear EN bit in the DMA_SxCR Register, Wait Until the EN bit is read as 0 before DMA_Init()

    DMA_Cmd(DMA2_Stream2, DISABLE);
    while (DMA2_Stream2->CR & DMA_SxCR_EN);
    
  3. When use DMA_FIFOMode_Disable (Direct Mode), data width is determined by DMA_PeripheralDataSize (PSIZE), DMA_MemoryDataSize (MSIZE) is ignored

  4. Memory address must be aligned to your selected data width (HalfWord)

Reference:

  1. STM32F407XX Reference Manual - Chapter 10 DMA Controller
  2. STM32F4XX Standard Peripheral Library
Share:
15,154
Goshik
Author by

Goshik

Updated on June 08, 2022

Comments

  • Goshik
    Goshik about 2 years

    I use STM32F407VTG6 controller and try to receive data from SPI using DMA. Then I want to process data on DMA Complete Transfer Interrupt. But when Complete Transfer Interrupt is occurred I see that TEIF (transfer error interrupt flag) is set. After this DMA can't be started. This is part of my code:

    static void DmaInit()
    {
     DMA_InitTypeDef dma;
    
     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
    
     // DMA for Rx
     dma.DMA_Channel = DMA_Channel_3;
     dma.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
     dma.DMA_Memory0BaseAddr = 0; // will be set later
     dma.DMA_DIR = DMA_DIR_PeripheralToMemory;
     dma.DMA_BufferSize = 1; // will be set later
     dma.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
     dma.DMA_MemoryInc = DMA_MemoryInc_Enable;
     dma.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
     dma.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
     dma.DMA_Mode = DMA_Mode_Normal;
     dma.DMA_Priority = DMA_Priority_High;
     dma.DMA_FIFOMode = DMA_FIFOMode_Disable;
     dma.DMA_FIFOThreshold = DMA_FIFOThreshold_HalfFull;
     dma.DMA_MemoryBurst = DMA_MemoryBurst_Single;
     dma.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
     DMA_DeInit(DMA2_Stream2);
     DMA_Init(DMA2_Stream2, &dma);
    
     // Enable DMA Interrupt on complete transfer
     NVIC_EnableIRQ(DMA2_Stream2_IRQn);
     DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);
    }
    
    // It run on external interrupt
    static void DmaStart(uint32_t bufferSize, uint32_t* rxBuffer)
    { 
     // Start DMA for reading
     DMA2_Stream2->NDTR = bufferSize;
     DMA2_Stream2->M0AR = (uint32_t)rxBuffer;
     DMA_Cmd(DMA2_Stream2, ENABLE);
    }
    
    static void SpiInit()
    {
      SPI_InitTypeDef spi;
    
      // Enable clock for SPI
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
    
      // SPI settings
      SPI_StructInit(&spi);
      spi.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
      spi.SPI_Mode = SPI_Mode_Master;
      spi.SPI_DataSize = SPI_DataSize_8b;
      spi.SPI_CPOL = SPI_CPOL_Low;
      spi.SPI_CPHA = SPI_CPHA_2Edge;
      spi.SPI_NSS = SPI_NSS_Soft;
      spi.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
      spi.SPI_FirstBit = SPI_FirstBit_MSB;
      SPI_Init(SPI1, &spi);
      SPI_Cmd(SPI1, ENABLE);
    
      SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
    }