Skip to main content
patrickschneider9
Associate III
May 25, 2018
Question

Reasons for TIM CCx ISR not firing on STM32L433

  • May 25, 2018
  • 9 replies
  • 1321 views
Posted on May 25, 2018 at 15:57

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

    This topic has been closed for replies.

    9 replies

    Jan Waclawek
    Visitor II
    May 25, 2018
    Posted on May 25, 2018 at 17:24

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

    My guess is that this is RMW (i.e. SR &= UIF). If so, that's the culprit, SR flags are to be cleared by direct write, read the description of SR in RM.

    JW

    patrickschneider9
    Associate III
    May 25, 2018
    Posted on May 25, 2018 at 19:50

    Hello Jan,

    thank you for your answer! What exactly do you mean by RMW? I'm sorry I don't know that term. 

    My clrflg makro is:

    #define clrflg(x,y) ((x) &= ~(y))

    Pat

    Tesla DeLorean
    Guru
    May 25, 2018
    Posted on May 25, 2018 at 20:05

    RMW  Read Modify Write

    For the SR register use SR= not SR&=,  the logic on the register does the clearing in a single cycle atomically, you don't need to read it, that creates a hazard as the TIM can out run the load/store you are attempting.

    TIM->SR = ~TIM_SR_UIF;

    Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
    patrickschneider9
    Associate III
    May 25, 2018
    Posted on May 25, 2018 at 20:43

    Thanks for the clarification Clive.

    I think I'm not understanding the SR register right. So basically with 

    TIM->SR = ~TIM_SR_UIF I'm writing 1's to all other SR Flags, which can only be set by hardware. So this is not a problem?

    So having more than one Capture Compare flag CC1IF, CC2IF at the same time is also no problem then? Can you clarify: if CC1 and CC2 for example happen to have the same Counter value and trigger 'simultaneous', will there be one ISR trigger with both flags rising or two consecutive ISRs?

    Thanks to you two for pointing that out and I will definetly try that monday at the lab - but I can't possibly imagine that this has something todo with my problem: the minimum time I'm 'forwarding' the ISR is 400µs, the time between a read and write of the register should be way less, shouldn't it (running at 24MHz)?

    Thanks again for alle the fast answers so far.

    patrickschneider9
    Associate III
    May 28, 2018
    Posted on May 28, 2018 at 08:20

    Thank you Jan and Clive,

    this seemed to do the trick. Output current is stable now!

    Thank you so much for your help and fast answers!  Probably wouldn't have found it without you guys.

    Cheers,

    Pat