AnsweredAssumed Answered

Reasons for TIM CCx ISR not firing on STM32L433

Question asked by pschn on May 25, 2018
Latest reply on May 28, 2018 by pschn

Hi there,

I have a rather odd problem and am trying to find a solution or reason for it:

I am using 3 different timers on STM32L433 with 4 capture compare registers each to generate a total of 12 completely independant software PWM signals. Hardware layout is fixed, so no option to use hardware PWM.

I also tried only one of the timers with one capture compare register (with same behaviour), so for the sake of simplicity let's assume we are using TIM2 with CC1.

The initialization is:

CR1 = 0

CR2 = 0

SMCR = 0

DIER = DIER_CC1IE

EGR = EGR_UG

CCMR1 = 0

CCMR2 = 0

CCR1 = initial value

CCR2 = 0

CCR3 = 0

CCR4 = 0

CCER = 0

ARR = 0xFFFF

PSC = (Systemcoreclock / 1000000) - 1 //with ARR a base of 1µs  - this is validated and works

DCR = 0

DMAR = 0

 

After that I enable the timer and work in the interrupt.

 

The algorithm for the interrupt handler I am using to generate the PWM signal is as follows (pseudocode), registers are all TIM2 and CC1:

 

 

HandleIrq()

{

   if(isflgset(TIMTable[_TimNo]->SR, TIM_SR_UIF))
   {
      clrflg(TIMTable[_TimNo]->SR, TIM_SR_UIF);
   }

   if(isflgset(TIMTable[_TimNo]->SR, TIM_SR_CC1IF) &&
      isflgset(TIMTable[_TimNo]->DIER, TIM_DIER_CC1IE))
   {
      if(Toggle)

      {

          Toggle = 1 - Toggle;

          *(u16*)TIMCCRegTable[_TimIdx] = (u16)(TIM2->CNT + onTime);

          PINSET;

      }

      else

      {

          Toggle = 1 - Toggle;         

          *(u16*)TIMCCRegTable[_TimIdx] = (u16)(TIM2->CNT + offTime);

          PINRESET;

      }
      clrflg(TIMTable[_TimNo]->SR, TIM_SR_CC1IF);
   }

}

 

This has different implications:

I have a lot of Capture Compare interrupts between one timer overflow. 

The routine itself takes less time than onTime/offTime. (ISR takes 8µs, minimum onoffTime is 400µs)

Both are true (mostly)

 

My problem is, this all works MOST of the time perfectly with all timings, but once in a while ONE interrupt is not getting fired in the current timer overflow but in the next. Example:

CC1 ISR at Counter-Value: 0x5000

Next desired Value: 0x6000 (4096µs time)

CC1 ISR is triggered at 0x6000 but one COMPLETE timer overflow later (4096µs + 0xFFFFµs = 69631µs have passed)

This is perfectly accurate and measurable, so it's clear that it's exact one timer "round".

Question is why am I losing this interrupt, and just "sometimes". It just looks like sometimes someone would clear the interrupt before it gets fired OR the timer would just update the CCx register to its shadow register after the overflow event.

The effects are desastrous, I am using this to regulate output currents and when this is happening the output current clamps to Maximum or Zero for this period of time (65ms).

Could anybody think of anything causing my problem?

Thanks in advance for your help,

Pat

Outcomes