cancel
Showing results for 
Search instead for 
Did you mean: 

PWM on STM32l4 stops working randomly

rickard2
Associate III

I have a problem that the PWM timer stops working randomly, maybe once every 2 weeks on 4 prototoypes. The PWM signal is just high instead of the frequency it should do. I have added reset and recover but nothing seems to fix. Since I am not able to reproduce it can any one see something I do wrong? The STM32 is in sleep mode and when it goes active sometimes the PWM will not be there until processor is reset.

The PWM is started at some moments, 3 times at 200 ms with 800 ms in bewteen and then disabled.

The input parametes to PWM is same when it works/don't work. There are no errors on the UART when this happens.

TIM_HandleTypeDef    PWMTimHandle;
TIM_OC_InitTypeDef sConfig;
 
void HW_TIM_PWM_Set(uint32_t freq, uint16_t duty)
{
	uint32_t period, temp, prescaler = 1 ;
	if(freq < 10)
	{
		return;
	}
	__HAL_RCC_TIM1_FORCE_RESET();
	__HAL_RCC_TIM1_RELEASE_RESET();
	__HAL_RCC_TIM1_CLK_ENABLE();
	uint32_t period_ns = 100000000 / (freq/10);
	uint32_t tickresolution = 0;
	uint16_t pulse;
	do
	{
		tickresolution = 1000000 / ((SystemCoreClock /(10*1000))/ prescaler);	// 0.1 ns upplösning
		period = (period_ns * 10)/ tickresolution;
		if(period > 0xFFFF)
		{
			prescaler++;
		}
	}while(period > 0xFFFF);
	temp = (period * duty)/100;
	pulse = (uint16_t)temp;
	prescaler = prescaler - 1;	//prescaler 0 ger system clock
 
	printf("PWM: f %d => period %d prescaler %d puls %d \n\r", (unsigned int)freq, (unsigned int)period, (unsigned int)prescaler, (unsigned int)pulse);
 
	PWMTimHandle.Instance = TIM1;
 
	PWMTimHandle.Init.Prescaler         = prescaler;
	PWMTimHandle.Init.Period            = period;
	PWMTimHandle.Init.ClockDivision     = 0;
	PWMTimHandle.Init.CounterMode       = TIM_COUNTERMODE_UP;
	PWMTimHandle.Init.RepetitionCounter = 0;
	if (HAL_TIM_PWM_Init(&PWMTimHandle) != HAL_OK)
	{
		printf("Error TIM!\r\n");
		return;
	}
 
	sConfig.OCMode       = TIM_OCMODE_PWM1;
	sConfig.OCPolarity   = TIM_OCPOLARITY_HIGH;
	sConfig.OCFastMode   = TIM_OCFAST_DISABLE;
	sConfig.OCNPolarity  = TIM_OCNPOLARITY_HIGH;
	sConfig.OCNIdleState = TIM_OCNIDLESTATE_RESET;
	sConfig.OCIdleState  = TIM_OCIDLESTATE_RESET;
 
	sConfig.Pulse = pulse;
	if (HAL_TIM_PWM_ConfigChannel(&PWMTimHandle, &sConfig, TIM_CHANNEL_1) != HAL_OK)
	{
		printf("Error PWM!\r\n");
	}
}
 
void HW_TIM_PWM_Enable()
{
	GPIO_InitTypeDef   GPIO_InitStruct;
	__HAL_RCC_GPIOA_CLK_ENABLE();
	GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
	GPIO_InitStruct.Pull = GPIO_PULLUP;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
	GPIO_InitStruct.Alternate = GPIO_AF1_TIM1;
	GPIO_InitStruct.Pin = GPIO_PIN_8;
	/*if(PWMTimHandle.Instance == TIM2)
	{
		GPIO_InitStruct.Pin = GPIO_PIN_0;
	}*/
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
 
	if (HAL_TIM_PWM_Start(&PWMTimHandle, TIM_CHANNEL_1) != HAL_OK)
	{
		printf("PWM start error\r\n");
	}
 
	/*if (HAL_TIM_Base_Start_IT(&PWMTimHandle) != HAL_OK)
	{
		return;
	}*/
}
 
void HW_TIM_PWM_Disable()
{
	GPIO_InitTypeDef   GPIO_InitStruct;
	HAL_TIM_PWM_Stop(&PWMTimHandle, TIM_CHANNEL_1);
	__HAL_RCC_TIM1_CLK_DISABLE();
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
	GPIO_InitStruct.Pin = GPIO_PIN_8;
	/*if(PWMTimHandle.Instance == TIM2)
	{
		GPIO_InitStruct.Pin = GPIO_PIN_0;
	}*/
	HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
	HAL_GPIO_WritePin(GPIOA,  GPIO_PIN_8, GPIO_PIN_RESET);
}

7 REPLIES 7
TDK
Guru

Since your PWM starts correctly, I doubt the issue is in the PWM initialization/start code.

Can you attach a debugger to a device showing the issue? You could examine register to see what the issue is, and see if the code is stuck somewhere.

If you feel a post has answered your question, please click "Accept as Solution".
rickard2
Associate III

Yeah that is a good proposal. I cannot connect debugger on field units, but I can write a code which peeks registers over UART.

Okay so where is the content of registers? TIM and relevant GPIO.

You want to accelerate the failure rate first, e.g. by increasing rate of any external stimulus by orders of magnitude, shortening or randomizing any fixed sleep time, etc.

For anything non-trivial, i.e. not something what can be directly clicked in CubeMX, you should really consider dropping Cube/HAL, it's just an unnecessary burden.

JW

MM..1
Chief II

You realy use sleep not stop mode anywhere?

rickard2
Associate III

I cannot get it to appear at will, I have tried....all inputs are welcome

Can you point out more specific which register addresses are suitable to printout? I will post them next time it appears.

I do not use CubeMX, but I do use HAL ( as seen above).

> I cannot get it to appear at will, I have tried....all inputs are welcome

I did not say, at will, but try to increase it's frequency of ocurrence. I've given ideas above.

JW

rickard2
Associate III

I think I solved the problem, at least it has not appeared in a couple of weeks. I added a check of CR1 and if it was not 0x00000001 after HAL_configuration I set it to 0x00000001.

I really do not understand why HAL not always set CEN bit....