cancel
Showing results for 
Search instead for 
Did you mean: 

TIM3 periodElapsedCallback never called

JustSomeGuy
Associate III

In my code, after setting an on-board LED, the timer is started like this.

 __HAL_TIM_SET_COUNTER(&htim3, 0);
while(HAL_TIM_Base_Start_IT(&htim3) != HAL_BUSY);

In debugging mode, I saw that the CNT register was in fact incrementing, however in would always rollover and would never trigger this callback function:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM3)
	{
		while(HAL_TIM_Base_Stop_IT(htim) != HAL_BUSY);
		HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, RESET);
	}
}

 I saw on another forum post that someone suggested to put that code in stm32l0xx.c in the function TIM3_IRQHandler(). However when I did that, I found that the function was called instantly after HAL_TIM_Base_Start_IT(&htim3). 

What is going on here? I opened a new project with the EXACT same settings for timer 3, and it worked perfectly. This project has become far too massive to move everything over to a new project without a lot of headache. I would prefer to find out how to solve this in the project I am currently working on. Here is the cubeMX configuration:

static void MX_TIM3_Init(void)
{
  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};

  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 2047;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 7811;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
}
1 ACCEPTED SOLUTION

Accepted Solutions
JustSomeGuy
Associate III

Some more information: I removed the function HAL_TIM_BASE_Stop_IT(), moved HAL_TIM_BASE_Start_IT() to the top of main(), and set a boolean value to indicate that the LED is set when I cleared the CNT register. in the interrupt callback, I check the timer instance and that boolean value to check whether the LED has been set. Now it's working flawlessly.

View solution in original post

14 REPLIES 14
Bob S
Principal

Do you have the TIM3 interrupt enabled in the NVIC?  In CubeMX open the timer config window and click on the "NVIC Settings" tab.

Yes, those have been enabled since the start.

Here is some more information: I looked at the vector tables for both the original non-functioning program and the new functioning one. I found that TIM3_IRQHandler is mentioned in the non-functional project, but not the functional project.

attach your IOC file.

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.
 
Karl Yamashita
Lead III

One thing i've noticed is that you're checking for HAL_BUSY when you call HAL_TIM_Base_Start_IT but the function only returns HAL_OK or HAL_ERROR. Not sure how you're getting past this or are you? You should be stuck here forever. 

while(HAL_TIM_Base_Start_IT(&htim3) != HAL_BUSY);

 

You also check for HAL_BUSY in the callback. This will be a stuck forever loop as well

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if(htim->Instance == TIM3)
	{
		while(HAL_TIM_Base_Stop_IT(htim) != HAL_BUSY);
		HAL_GPIO_WritePin(GREEN_LED_GPIO_Port, GREEN_LED_Pin, RESET);
	}
}

 

Change HAL_BUSY to HAL_OK which should fix your issue.

 

 

 

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.

I tried that method, and the interrupt worked once, but after that my B-L072Z-LRWAN1 board wouldn't receive LoRa data (this LED is an indicator for when data is received through LoRa). I switched the method to polling the CNT register and that worked with no issues. However, polling is not ideal. I would really like to know why this timer is malfunctioning like this in interrupt mode.

Another thing to consider, if the HAL_TIM_BASE_Start_IT() only returns HAL_ERROR or HAL_OK, it should always exit the while loop after 1 pass, since I am checking to make sure that the function does not return a value that it will never return. I still changed it to != HAL_OK though, just so it actually does something.

JustSomeGuy
Associate III

Some more information: I removed the function HAL_TIM_BASE_Stop_IT(), moved HAL_TIM_BASE_Start_IT() to the top of main(), and set a boolean value to indicate that the LED is set when I cleared the CNT register. in the interrupt callback, I check the timer instance and that boolean value to check whether the LED has been set. Now it's working flawlessly.


Another thing to consider, if the HAL_TIM_BASE_Start_IT() only returns HAL_ERROR or HAL_OK, it should always exit the while loop after 1 pass, since I am checking to make sure that the function does not return a value that it will never return. I still changed it to != HAL_OK though, just so it actually does something.


If you don't receive HAL_BUSY, then there is no way to exit the while loop.

 

Instead you've should have tested for the return status to be not HAL_OK

	if(HAL_TIM_Base_Start_IT(&htim1) != HAL_OK)
	{
		// handle error
	}

 

 

If smoke escapes your device, put the smoke back in. It'll still work as a conversation piece. If you find my answers useful, click the Accept as Solution button so that way others can see the solution.