Skip to main content
Ilya Suvorov
Associate
Jan 15, 2021 3:16 AM UTC
Solved

TIM2 freeze on ARR register value changed STM32H743ZI2

Hi. I'm working on project where I need short pulses with precise periods generated in audio ranges (10 - 20kHz). So I decided to choose TIM2 and using it in PWM mode. I'm using HAL library and configuration code generated by CubeMX:

void MX_TIM2_Init(void)
{
 TIM_ClockConfigTypeDef sClockSourceConfig = {0};
 TIM_MasterConfigTypeDef sMasterConfig = {0};
 TIM_OC_InitTypeDef sConfigOC = {0};
 
 htim2.Instance = TIM2;
 htim2.Init.Prescaler = 2;
 htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
 htim2.Init.Period = 24000;
 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_PWM_Init(&htim2) != 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_PWM1;
 sConfigOC.Pulse = 150;
 sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
 sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
 if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
 {
 Error_Handler();
 }
 HAL_TIM_MspPostInit(&htim2);
 
}

The ARR is changing by TIM4 interrupt which is configured in encoder mode

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {
	if (htim->Instance == TIM4) {
	 long value = 24000 + TIM4->CNT * 8;
		TIM2->ARR = value;
	}
}

So. The freeze occurs when I quickly decreasing TIM4->CNT it takes about 50 seconds after that it starts operating. And it never happened on increasing. For quick test I used this code:

int click = 0;
 
int main(void) {
 HAL_Init();
 
 SystemClock_Config();
 
 MX_GPIO_Init();
 MX_TIM2_Init();
 MX_TIM4_Init();
 
 HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
 HAL_TIM_Encoder_Start_IT(&htim4, htim4.Channel);
 
 while (1) {
	HAL_Delay(2000);
	click++;
	if (click % 2 == 0) {
		TIM2->ARR = 548280;
	} else {
		TIM2->ARR = 24000;
	}
 }
}

Could you explain me why is it happens and maybe could point me out to some solution.

This topic has been closed for replies.
waclawek.jan
waclawek.janBest answer
Super User
Jan 15, 2021 10:22 AM UTC

> htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

If you change ARR below current CNT, CNT keeps incrementing until it overflows over its maximum value to 0, which in case of TIM2 - a 32-bit timer - is cca 4e9 counts (cca 40 seconds if timer's clock is around 100MHz).

The most straighforward solution is to enable ARR preload - this problem is exactly why ARR preload is for.

JW

2 replies

waclawek.jan
waclawek.janBest answer
Super User
Jan 15, 2021 10:22 AM UTC

> htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;

If you change ARR below current CNT, CNT keeps incrementing until it overflows over its maximum value to 0, which in case of TIM2 - a 32-bit timer - is cca 4e9 counts (cca 40 seconds if timer's clock is around 100MHz).

The most straighforward solution is to enable ARR preload - this problem is exactly why ARR preload is for.

JW

Ilya Suvorov
Associate
Jan 15, 2021 11:13 AM UTC

Thank you for clear answer!