STMicroelectronics / STM32CubeG0

STM32Cube MCU Full Package for the STM32G0 series - (HAL + LL Drivers, CMSIS Core, CMSIS Device, MW libraries plus a set of Projects running on all boards provided by ST (Nucleo, Evaluation and Discovery Kits))
Other
164 stars 75 forks source link

HAL_TIM_IC_START_IT does not enable CC2E for duty&freq capture #23

Closed embcla closed 2 years ago

embcla commented 2 years ago

Caution The Issues are strictly limited for the reporting of problem encountered with the software provided in this project. For any other problem related to the STM32 product, the performance, the hardware characteristics and boards, the tools the environment in general, please post a topic in the ST Community/STM32 MCUs forum.

Describe the set-up

Describe the bug When TIM2 is configured as pwm input capture to capture both duty and frequency, and capturing is enabled, CC2E is not set resulting in failure to acquire the second register value.

How To Reproduce

  1. Configure TIM2 with CubeMX on a STM32G071 like in the picture, pay attention to the fact that Channel1 is on rising edge, while Channel2 is on falling edge image

  2. in the code, call everything necessary to start the capture

    MX_TIM2_Init();
    if (HAL_TIM_Base_Start(&htim2) != HAL_OK) {
        Error_Handler();
    }
    
    HAL_TIM_IC_Init(&htim2);
    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
  3. CC2E won't be set, so only the rising edge interrupt will be generated

  4. Solution is to add bit set operation after starting the capture

    /* Enable also the capture on the falling edge for Duty Cycle */
    TIM2->CCER |= TIM_CCER_CC2E;

Timer2 setup code as generated by CubeMX

void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_IC_InitTypeDef sConfigIC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 100 - 1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 0xFFFFFFFF;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != 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.TriggerFilter = 0;
  if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != 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();
  }
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */

}
ASELSTM commented 2 years ago

Hi @embcla,

An instruction is missing in your code so that you can activate the CC2E. The code should then be:

    MX_TIM2_Init();
    if (HAL_TIM_Base_Start(&htim2) != HAL_OK) {
        Error_Handler();
    }

    HAL_TIM_IC_Init(&htim2);
    HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_1);
+   HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2);

The HAL_TIM_IC_Start_IT(&htim2, TIM_CHANNEL_2) function will starts the TIM Input Capture measurement in interrupt mode on the channel 2 and enables the TIM Capture Compare on the specified channel.

I hope this would help you.

With regards,

embcla commented 2 years ago

Hello @ASELSTM and thank you for taking a look at this.

The confusion comes from the fact that I couldn't find this mentioned anywhere. The STM32G0x1 RM0444 manual only mentions specific bits and registers, while the HAL has no example usage of groups of functions. Bridging that gap proved hard for me.

ASELSTM commented 2 years ago

Hi @embcla,

It is mentioned in the HAL_TIM_IC_Start_IT() function description in the stm32g0xx_hal_tim.c driver.

https://github.com/STMicroelectronics/STM32CubeG0/blob/03cb8e9ec0cbefad623caebe47359df0bab1d05e/Drivers/STM32G0xx_HAL_Driver/Src/stm32g0xx_hal_tim.c#L2160-L2165

Hence, as there is no issue please allow me then to close these thread. Thank you for your comprehension and thank you for your contribution.

With regards,