cancel
Showing results for 
Search instead for 
Did you mean: 

Timer triggering DMA

con3
Senior

Morning everyone,

I'm trying to reconfigure a timer configuration that generates dma requests.

The DMA request, moves data from the GPIO pins to memory, so peripheral to memory. Currently I have two timers cascaded, the one(being timer 8 is fed with an external clock) and produces a waveform when it is triggered. It outputs this waveform, which is then fed to timer 1 which is in input capture and generates the DMA requests.

This seems wasteful as the time it takes to toggle the pin and generate the DMA request from cascaded timers slows down the process.

To improve this, I'd like to only use timer 8 in output capture(no output mode) to trigger the dma whenever the counter overflows.

Here is the current timer 8 configuration:

 static void MX_TIM8_Init(void) {
 
 
   TIM_ClockConfigTypeDef sClockSourceConfig;
 
   TIM_SlaveConfigTypeDef sSlaveConfig;
 
   TIM_MasterConfigTypeDef sMasterConfig;
 
   TIM_OC_InitTypeDef sConfigOC;
 
   TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig;
 
 
   htim8.Instance = TIM8;
 
   htim8.Init.Prescaler = 0;
 
   htim8.Init.CounterMode = TIM_COUNTERMODE_UP;
 
   htim8.Init.Period = 15;
 
   htim8.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
 
   htim8.Init.RepetitionCounter = 17;
 
   htim8.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
 
   if (HAL_TIM_Base_Init(&htim8) != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
   sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_ETRMODE2;
 
   sClockSourceConfig.ClockPolarity = TIM_CLOCKPOLARITY_INVERTED;
 
   sClockSourceConfig.ClockPrescaler = TIM_CLOCKPRESCALER_DIV1;
 
   sClockSourceConfig.ClockFilter = 0;
 
   if (HAL_TIM_ConfigClockSource(&htim8, &sClockSourceConfig) != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
   if (HAL_TIM_OC_Init(&htim8) != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
   sSlaveConfig.SlaveMode = TIM_SLAVEMODE_COMBINED_RESETTRIGGER;
 
   sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
 
   sSlaveConfig.TriggerPolarity = TIM_TRIGGERPOLARITY_FALLING;
 
   sSlaveConfig.TriggerFilter = 0;
 
   if (HAL_TIM_SlaveConfigSynchronization(&htim8, &sSlaveConfig) != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
   sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
 
   sMasterConfig.MasterOutputTrigger2 = TIM_TRGO2_RESET;
 
   sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
 
   if (HAL_TIMEx_MasterConfigSynchronization(&htim8, &sMasterConfig)
 
         != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
   sConfigOC.OCMode = TIM_OCMODE_RETRIGERRABLE_OPM1;
 
   sConfigOC.Pulse = 8;
 
   sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
 
   sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
 
   sConfigOC.OCFastMode = TIM_OCFAST_ENABLE;
 
   sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
 
   sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
 
   if (HAL_TIM_OC_ConfigChannel(&htim8, &sConfigOC, TIM_CHANNEL_2) != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
   sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
 
   sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
 
   sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
 
   sBreakDeadTimeConfig.DeadTime = 0;
 
   sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
 
   sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
 
   sBreakDeadTimeConfig.BreakFilter = 0;
 
   sBreakDeadTimeConfig.Break2State = TIM_BREAK2_DISABLE;
 
   sBreakDeadTimeConfig.Break2Polarity = TIM_BREAK2POLARITY_HIGH;
 
   sBreakDeadTimeConfig.Break2Filter = 0;
 
   sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
 
   if (HAL_TIMEx_ConfigBreakDeadTime(&htim8, &sBreakDeadTimeConfig)
 
         != HAL_OK) {
 
      _Error_Handler(__FILE__, __LINE__);
 
   }
 
 
}
 
 

Here's the DMA configuration:

     else if(htim_base->Instance==TIM8)
  {
  /* USER CODE BEGIN TIM8_MspInit 0 */
 
  /* USER CODE END TIM8_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_TIM8_CLK_ENABLE();
  
    /**TIM8 GPIO Configuration    
    PA0-WKUP     ------> TIM8_ETR
    PC6     ------> TIM8_CH1 
    */
    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF3_TIM8;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
 
  /* USER CODE BEGIN TIM8_MspInit 1 */
     hdma_tim8_ch2.Instance = DMA2_Stream3;
     hdma_tim8_ch2.Init.Channel = DMA_CHANNEL_7;
     hdma_tim8_ch2.Init.Direction = DMA_PERIPH_TO_MEMORY;
     hdma_tim8_ch2.Init.PeriphInc = DMA_PINC_DISABLE;
     hdma_tim8_ch2.Init.MemInc = DMA_MINC_ENABLE;
     hdma_tim8_ch2.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
     hdma_tim8_ch2.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
     hdma_tim8_ch2.Init.Mode = DMA_CIRCULAR;
     hdma_tim8_ch2.Init.Priority = DMA_PRIORITY_VERY_HIGH;
     hdma_tim8_ch2.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
     hdma_tim8_ch2.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_HALFFULL;
     hdma_tim8_ch2.Init.MemBurst = DMA_MBURST_INC4;
     hdma_tim8_ch2.Init.PeriphBurst = DMA_PBURST_SINGLE;
     if (HAL_DMA_Init(&hdma_tim8_ch2) != HAL_OK)
     {
       _Error_Handler(__FILE__, __LINE__);
     }
 
     __HAL_LINKDMA(htim_base,hdma[TIM_DMA_ID_CC2],hdma_tim8_ch2);
 
  /* USER CODE END TIM8_MspInit 1 */
}

Here's how I'm starting the timer and DMA:

	hdma_tim8_ch2.XferM1CpltCallback = TransferComplete1;
	hdma_tim8_ch2.XferCpltCallback = TransferComplete;
	hdma_tim8_ch2.XferErrorCallback = TransferError;
	//Setup the DMA in Multibuffer mode with GPIOF as the input for the dataset
	if (HAL_DMAEx_MultiBufferStart_IT(htim8.hdma[TIM_DMA_ID_CC2], GPIOF_IDR,
			(uint32_t) &aDST_Buffer1, (uint32_t) &aDST_Buffer2, 32000)
			!= HAL_OK) {
		/* Transfer Error */
		Error_Handler();
	}
	//Enable the DMA and Timer interrupt
	__HAL_TIM_ENABLE_DMA(&htim8, TIM_DMA_CC2);
	__HAL_TIM_ENABLE_IT(&htim8, TIM_IT_CC2);
 
	HAL_TIM_OC_Start(&htim8, TIM_CHANNEL_2);
TIM_CCxChannelCmd(htim8.Instance, TIM_CHANNEL_2, TIM_CCx_ENABLE);

So This does seem to generate a DMA request, but not for both of these overflow cases:

htim8.Init.Period = 15;
sConfigOC.Pulse = 8;

As far as I can tell at this point, it seems to only generate the request when the counter surpasses the period value, but not for the pulse value.

How could I get the DMA generation to occur for both overflow at the pulse, period and to continue for the repetition counter period?

Any help will really be appreciated!

If any more information is required, please let me know

10 REPLIES 10

By "I don't use Cube" I mean "I don't use CubeMX (the configuration program), nor Cube (the library - i.e. neither its HAL nor LL part)".

IMO using "libraries" is a hindrance rather than help in programming microcontrollers. YMMV.

JW