unexpected register change TIM1->DIER / interrupt enable flag
Controller: STM32G431VBT6
Compiler: arm-none-eabi-gcc version 12.2.1
Libraries: CMSIS
I use STM32G431VBT6 for a sensorless BLDC motor control with zero-cross detection.
TIM1 is used for PWM outputs. See below part of the code.
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable clock
TIM1->PSC = 0; // no prescaling
TIM1->ARR = SYSTEM_CLK / MOTOR_PWM_FREQ / 2; // auto reload register
TIM1->CR1 |= TIM_CR1_CMS_0; // center aligned mode 1, int. at rising edge
TIM1->CR1 |= TIM_CR1_ARPE; // ARR register is buffered
TIM1->CCR1 = TIM1->ARR; // trigger in the mid of PWM off
// channel 2, phase W
TIM1->CCMR1 |= TIM_CCMR1_OC2M_1 | TIM_CCMR1_OC2M_2; // PWM mode 1
TIM1->CCMR1 |= TIM_CCMR1_OC2PE; // output compare preload enable
// channel 3, phase V
TIM1->CCMR2 |= TIM_CCMR2_OC3M_1 | TIM_CCMR2_OC3M_2; // PWM mode 1
TIM1->CCMR2 |= TIM_CCMR2_OC3PE; // output compare preload enable
// channel 4, phase U
TIM1->CCMR2 |= TIM_CCMR2_OC4M_1 | TIM_CCMR2_OC4M_2; // PWM mode 1
TIM1->CCMR2 |= TIM_CCMR2_OC4PE; // output compare preload enable
// 1 µs dead time for both edges -- 22R, CSD18510KTT
TIM1->BDTR |= (MOTOR_DT << TIM_BDTR_DTG_Pos) | TIM_BDTR_OSSI | TIM_BDTR_OSSR;
TIM1->CR2 |= TIM_CR2_CCPC; // CCxE, CCxNE and OCxM bits are preloaded
TIM1->EGR |= TIM_EGR_UG;
NVIC_EnableIRQ(TIM1_CC_IRQn);
NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
TIM1->CR1 |= TIM_CR1_CEN; // enable timer
Zero-Cross is sampled using internal comparators every PWM cycle within CCR1 interrupt routine. The corresponding interrupt enable flag is set like: TIM1->DIER |= TIM_DIER_CC1IE
The problem:
Sometimes TIM1_DIER_CC1IE gets reset unexpectedly. I checked all the code. There is no software action that does reset TIM1_DIER_CC1IE.
How is it possible that TIM_DIER_CC1IE of TIM1->DIER gets reset without any software action?
Is there any hardware condition (except device reset) that can change TIM1->DIER register?
How to debug?
I've been struggling for days now. Can anybody help? I appreciate every helping comment.
