cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 Timer Compare missed the first time

ADunc.1
Senior

I have an odd issue.  I am setting up a timer compare channel for a 5ms delay in the future.  I set the counter to 0, set the compare value to 5ms in the future.  The compare interrupt does not occur, until the timer wraps all the way around and passes the compare value for a second time.  It passes the compare value the first time with no interrupt.

Setup is:  STM32H753 (on custom HW), TIM2, Ch1/Ch2 used for PWM input capture. Ch3 used for timeout if IC does not occur.  All setup is using STM32Cube MX.  See code below.  The timers are started with the following code:

The idea is that the PWM input rising edge on Ch1 will reset the counter every cycle (1kHz), but if the counter does not get reset due to no PWM input signal for 5ms, Ch3 compare happens.  Everything works as expected except if there is no input signal from the start, the timeout takes a full timer roller over, instead of 5ms, then is always 5ms after that! 

It is like the timer needs to do a rollover first before output compare works.  I tried setting UG bit and CC3G bit in EGR, but did not help.  I even tried setting the counter to near rollover so it could roll over, but still didn't work!  I also tried removing all Ch1/2 functionality and disabling slave mode.  Just simple single channel as output compare.  Still same behavior!

Any help would be greatly appreciated.

 

My code to start the timers:

static TIM_HandleTypeDef* const cPWMMeasTimer = &htim2;
#define cPWMMeasRisingChannel TIM_CHANNEL_1
#define cPWMMeasFallingChannel TIM_CHANNEL_2
#define cPWMMeasTimeoutChannel TIM_CHANNEL_3
#define PWM_MEAS_TIMER_CLK_FREQ  240000000UL
#define NO_PWM_MEAS_TIMEOUT_MS 5u

...

// Start PWM measurement
__HAL_TIM_SET_COUNTER(cPWMMeasTimer, 0x0);
__HAL_TIM_SET_COMPARE(cPWMMeasTimer, cPWMMeasTimeoutChannel, (NO_PWM_MEAS_TIMEOUT_MS * PWM_MEAS_TIMER_CLK_FREQ) / 1000u);
HAL_TIM_OC_Start_IT(cPWMMeasTimer,  cPWMMeasTimeoutChannel);
HAL_TIM_IC_Start_IT(cPWMMeasTimer, cPWMMeasRisingChannel);
HAL_TIM_IC_Start(cPWMMeasTimer, cPWMMeasFallingChannel);

STM32Cube MX generated code:

void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 0;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 4294967295;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_OC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_TI1FP1;
  sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sSlaveConfig.TriggerPrescaler = TIM_ICPSC_DIV1;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;
  sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;
  sConfigIC.ICFilter = 0;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_FALLING;
  sConfigIC.ICSelection = TIM_ICSELECTION_INDIRECTTI;
  if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 0;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}

Timer registers after all initialization and starting channels:

ADunc1_0-1747616054370.png

 

 

 

0 REPLIES 0