cancel
Showing results for 
Search instead for 
Did you mean: 

Timer UEV event comes simultaneously with OC event, even though periods are different

maple
Associate II

Below is timer configuration generated by Cube for F103. The idea is to have it count all the way while input capture on CH2 will be resetting it to 0 using TI2FP2 and slave reset mode. The CH1 is configured for output compare to generate event when counter reaches 1/5 of the ARR.

TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
 
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 5493;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 65535;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_IC_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_RESET;
  sSlaveConfig.InputTrigger = TIM_TS_TI2FP2;
  sSlaveConfig.TriggerPolarity = TIM_INPUTCHANNELPOLARITY_RISING;
  sSlaveConfig.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim1, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_TIMING;
  sConfigOC.Pulse = 13107;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_LOW;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != 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(&htim1, &sConfigIC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  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.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }

These are initialization calls and event handlers:

HAL_TIM_OC_Start_IT(&htim1, TIM_CHANNEL_1);
HAL_TIM_Base_Start_IT(&htim1);
 
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
    printf("OC %lu\r\n", HAL_GetTick());
}
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    printf("UEV %lu\r\n", HAL_GetTick());
}

Observed behavior is that both events come almost simultaneously every 5 seconds, instead of OC coming after 1 sec and UEV 4 seconds later.

3 REPLIES 3

I don't Cube.

In 'F103, there are separate interrupt vectors for TIM1_UP and TIM1_CC. Are ISRs for both of them set up properly and inserted into the vector table (as confirmed by disasm)?

I personally would start with checking the registers' content, and then toggle output pins observed by a LA (or on attached LEDs) in the ISRs, rather than rely on Cube's tangles.

JW

maple
Associate II

Unfortunately this project is required to use HAL and is generated using Cube. Other team members often re-generate it as part of development process. But yes, I think I can check registers after HAL is done setting timer up.

I believe ISRs are set up properly, because when I uncheck any of them in Cube NVIC the corresponding callback is no longer called. The problem seems to be not in ISRs, but rather in some timer configuration parameter that I set up incorrectly.

https://github.com/STMicroelectronics/STM32CubeF1/blob/441b2cbdc25aa50437a59c4bffe22b88e78942c9/Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c#L73

(#) Configure the TIM in the desired functioning mode using one of the Initialization function of this driver

And the same with *_Start() functions... Nice example of the stupidity of HAL!

> Unfortunately this project is required to use HAL and is generated using Cube.

So it's required to be buggy, bloated, inflexible and eventually never working reliably? That's the strangest requirement I've seen!