title: STM32 DMA transfer error both FIFO and transfer error flags set
body: <p>I have an STM32F769I-EVAL configured to receive 8 bit parallel data based on code from ST's <a href="http://www.st.com/en/embedded-software/x-cube-paral-com.html" rel="nofollow noreferrer">AN4666</a>. What I expect to happen is: the clock from my input device triggers the input capture DMA and writes data to SDRAM until my OC timer interrupt disables the transfer. At that point I can manipulate the data in SDRAM and transfer it elsewhere. However, after the hardware is configured and the input capture enabled I get a DMA transfer error. The value for errorcode (6) in the HAL_DMA_IRQHandler function shows that both FIFO and transfer error flags are set. According to my understanding of the <a href="http://www.st.com/content/ccc/resource/technical/document/reference_manual/group0/96/8b/0d/ec/16/22/43/71/DM00224583/files/DM00224583.pdf/jcr:content/translations/en.DM00224583.pdf" rel="nofollow noreferrer">datasheet</a> (see pg 261) this should not be possible, I assume I have mis-configured a setting somewhere but I am at a loss as far as how to proceed. What steps can I take to solve this?</p>
  
  <p>DMA configuration:</p>
  
  <pre><code>void HAL_TIM_Base_MspInit(TIM_HandleTypeDef *htim)
  {
      GPIO_InitTypeDef   GPIO_InitStruct;
      static DMA_HandleTypeDef  hdma_tim;
  
      /* TIMx clock enable */
      TIMx_CLK_ENABLE();
  
      /* Enable DMA clock */
      DMAx_CLK_ENABLE();
  
      /* Enable TIM input GPIO clock */
      TIMx_CHy_GPIOCLK_ENABLE();
  
      /* Configure input of TIMx_CHy on AF */
      GPIO_InitStruct.Pin = TIMx_CHy_PIN;
      GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
      GPIO_InitStruct.Pull = GPIO_NOPULL;
      GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
      GPIO_InitStruct.Alternate = GPIO_AF_TIMx;
      HAL_GPIO_Init(TIMx_CHy_PORT, &amp;GPIO_InitStruct);
  
      /* Set the parameters to be configured */
      hdma_tim.Init.Channel  = DMA_CHANNEL;
      hdma_tim.Init.Direction = DMA_PERIPH_TO_MEMORY;
      hdma_tim.Init.PeriphInc = DMA_PINC_DISABLE;
      hdma_tim.Init.MemInc = DMA_MINC_ENABLE;
      hdma_tim.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE ; /* Reading in GPIO PC[7:0]*/
      hdma_tim.Init.MemDataAlignment = DMA_MDATAALIGN_WORD ;
      hdma_tim.Init.Mode = DMA_NORMAL;  /* double memory buffer used */
      hdma_tim.Init.Priority = DMA_PRIORITY_HIGH;
      hdma_tim.Init.FIFOMode = DMA_FIFOMODE_ENABLE; /* using FIFO mode since memory datasize=32bit and GPIO=8bits in our case */
      hdma_tim.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_1QUARTERFULL; /* flushing FIFO at each 32bit reception (4 data) */
      hdma_tim.Init.MemBurst = DMA_MBURST_SINGLE;
      hdma_tim.Init.PeriphBurst = DMA_PBURST_SINGLE;
  
      /* Set hdma_tim instance */
      hdma_tim.Instance = DMA_STREAM;
  
      /* Link hdma_tim to hdma[CC1] */
      __HAL_LINKDMA(htim, hdma[TIMx_DMA_ID], hdma_tim);
  
      /* Initialize TIMx DMA handle */
      HAL_DMA_Init(htim-&gt;hdma[TIMx_DMA_ID]);
  
      /* NVIC configuration for TIMx output compare interrupt */
      HAL_NVIC_SetPriority(TIMx_IRQn, 0, 2);
      HAL_NVIC_EnableIRQ(TIMx_IRQn);
  
      /* Configure the NVIC for DMA                             */
      /* NVIC configuration for DMA transfer complete interrupt */
      HAL_NVIC_SetPriority(TIMx_DMA_IRQn, 0, 0);
      HAL_NVIC_EnableIRQ(TIMx_DMA_IRQn);
  
  }
  </code></pre>
  
  <p>Code from main:</p>
  
  <pre><code>/* Initialize SDRAM */
  BSP_SDRAM_Init();
  
  /* Configure the Data GPIO in input mode  */
  Data_GPIO_Config();
  
  /* Set Timers instance */
  TimHandle.Instance = TIMx;
  
  /* Initialize global Timer parameters */
  TimHandle.Init.Period            = MAX_COUNTER;
  TimHandle.Init.Prescaler         = TIMx_PRESCALER - 1;
  TimHandle.Init.ClockDivision     = TIM_CLOCKDIVISION_DIV1;
  TimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
  TimHandle.Init.RepetitionCounter = 0;
  if (HAL_TIM_Base_Init(&amp;TimHandle) != HAL_OK)
  {
      /* Initialization Error */
      Error_Handler();
  }
  
  //Initialize Timer "OC" channel for OC mode
  sOConfig.OCMode       = TIM_OCMODE_TIMING/*TIM_OCMODE_TOGGLE*/;
  sOConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
  sOConfig.Pulse        = NB_COUNTER_CYCLE;
  sOConfig.OCNPolarity  = TIM_OCPOLARITY_HIGH;
  sOConfig.OCFastMode   = TIM_OCFAST_DISABLE;
  sOConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  sOConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;
  if (HAL_TIM_OC_ConfigChannel(&amp;TimHandle, &amp;sOConfig, TIMx_CHANNEL_OC) != HAL_OK)
  {
      //Configuration Error
  Error_Handler();
  }
  
  /* Initialize Timer "IC" channel for IC mode     */
  sICConfig.ICPolarity  = CLK_LATCHING_DATA_EDGE;
  sICConfig.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sICConfig.ICPrescaler = TIM_ICPSC_DIV1;
  sICConfig.ICFilter    = TIM_IC_FILTER;  /* filter the clock signal over/undershoot */
  if (HAL_TIM_IC_ConfigChannel(&amp;TimHandle, &amp;sICConfig, TIMx_CHANNEL_IC) != HAL_OK)
  {
      /* Configuration Error */
      Error_Handler();
  }
  
  /* Set the DMA memory0 conversion complete callback */
  TimHandle.hdma[TIMx_DMA_ID]-&gt;XferCpltCallback = TransferComplete;
  /* Set the DMA memory1 conversion complete callback */
  TimHandle.hdma[TIMx_DMA_ID]-&gt;XferM1CpltCallback = TransferComplete;
  /* Set the DMA error callback */
  TimHandle.hdma[TIMx_DMA_ID]-&gt;XferErrorCallback = TransferError ;
  
  /* Update second memory address */
  second_mem_address = (uint32_t)((SDRAM_BANK_ADDR + WRITE_READ_ADDR) + (DMA_MEM_BUFF_SIZE));
  
  /* Start DMA multi buffer transfer */
  if (HAL_DMAEx_MultiBufferStart_IT(TimHandle.hdma[TIMx_DMA_ID], GPIOx_IDR, (SDRAM_BANK_ADDR + WRITE_READ_ADDR), second_mem_address, DMA_MEM_BUFF_SIZE) != HAL_OK)
  {
      /* Transfer Error */
      Error_Handler();
  }
  
  __HAL_TIM_ENABLE_DMA(&amp;TimHandle, TIMx_DMA_CC);
  
  /* Enable the TIMx OC channel interrupt */
  __HAL_TIM_ENABLE_IT(&amp;TimHandle, TIMx_IT_OC);
  /* Enable the TIMX OC channel */
  TIM_CCxChannelCmd(TimHandle.Instance, TIMx_CHANNEL_OC, TIM_CCx_ENABLE);
  
  /* Enable the TIMx IC channel */
  TIM_CCxChannelCmd(TimHandle.Instance, TIMx_CHANNEL_IC, TIM_CCx_ENABLE);
  
  HAL_TIM_OC_Start(&amp;TimHandle, TIMx_CHANNEL_OC); // enable counter
  
  /* processing while Timeout not reached */
  while (timeout_flag == 0);
  </code></pre>