cancel
Showing results for 
Search instead for 
Did you mean: 

TIM4 Missing Update Interrupt

fabrizio23
Associate II
Posted on December 06, 2011 at 10:12

The follow ISR capture an event incoming on TIM4_CCP2, and

each 8 of this events the register oldCCP is subtracted from

CCR2, this value is strored in loop_buf[cyc][lb_index], the

value of CCR2 updates oldCCP, and also cyc and lb_index are

updated.

Each update event the counter cntr0 increase of 0x00010000,

in order to manage time intervals greater than 16bits.

Sometimes a missed rollover event occur, so losing the MSB

of the captured value.

I' ve tried to swap the ISR each other, without fixing the

problem.

brief hardware and settings description:

microcontroller: STM32F103V8Tb

compiler: IAR 5.4_2 (maximum balanced compression)

Incoming signal: square wawe at 30KHz and dutycycle 23%

interrupts enabled:

  - Systick every 50 microseconds preemption pr. 1,

    subpriority 0

  - Adconv1 watchdog preemption pr. 1,

    subpriority 0

  - TIM4 preemption pr. 0,

    subpriority 0

TIM4 settings:

  TIM_TimeBaseInitStruct.TIM_Prescaler = 0;

  TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInitStruct.TIM_Period = 0xFFFF;

  TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;

 

  TIM_TimeBaseInit(TIM4, &TIM_TimeBaseInitStruct);  

  TIM_SetClockDivision(TIM4,TIM_CKD_DIV1);

  TIM_UpdateDisableConfig(TIM4, DISABLE);

 

  TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;

  TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;

  TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;

  TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV8;

  TIM_ICInitStruct.TIM_ICFilter = 5;  

  TIM_ICInit(TIM4, &TIM_ICInitStruct);

/*******************************************************************

unsigned int  loop_buf[2][8]; //2-dimensions filtering vector

unsigned int  lb_index[2];    //pointer index on loop_buf

unsigned int  oldCCP[2];      //previous CCP value

char s_frq[2] = {2, 1};       //frequency selection (don't care)

int  cyc =0;                  //allowed values: 0 and 1

void TIM4_IRQHandler(void)

{

  static int contaeventi=, cntRO[2]={0,0};

  short pinO;

  //ISR for capture event

  if(TIM_GetFlagStatus(TIM4, TIM_FLAG_CC2))

  {   

    TIM4->SR = 0xFFFB;

    if(--contaeventi<N_meas[cyc])

    {

      if(contaeventi==0)

      {

        cntRO[cyc]=cntRO[cyc+TIM4->CCR2;

        if(TIM4->CCR2==0)

          cntRO[cyc]=cntRO[cyc]+0x00010000;

       

        loop_buf[cyc][lb_index[cyc]]=(cntRO[cyc]-oldCCP[cyc]);

        cntRO[cyc]=0;

        lb_index[cyc]=(lb_index[cyc]+1)&7;

        cyc = (~cyc)&1;

        pinO = ((short)((~s_frq[cyc])&3)<<11)|((short)((2-cyc)&3)<<9);

        GPIOD->BRR = pinO;

        GPIOD->BSRR = (~pinO)&0x1E00;

        contaeventi=((3*N_meas[cyc])>>1)+2;

      }

    }

    else

     oldCCP[cyc]=TIM4->CCR2;

  }

  //ISR for TIM4_CNT rollover event

  if(TIM_GetFlagStatus(TIM4, TIM_FLAG_Update))

  {

   TIM4->SR=0xFFFE);

   cntRO[cyc]=cntRO[cyc]+0x00010000;

    if(cntRO[cyc]==0)

      cntRO[cyc]=0xFFFF0000;

  }

}

#tim4-missing-update-interrupt
9 REPLIES 9
rosarium
Associate II
Posted on December 08, 2011 at 10:47

I hope you are providing proper clock to TIM4?

Posted on December 08, 2011 at 16:01

Wow, that's some fugly code, and badly pasted.

Yeah, you're going to have some serious problems with that as CCR approaches within a few dozen cycles of the update point, with a particularity nasty race condition.

Does it really make sense to ping-pong between two variables holding state information?

How are you determining if the CCR event occurs before/after the Update? You don't seem to be accounting for any window for that to be occurring.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 08, 2011 at 16:02

Double post, forum choked!

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabrizio23
Associate II
Posted on December 09, 2011 at 08:33

what does it means?

fabrizio23
Associate II
Posted on December 09, 2011 at 09:37

This is the system clock settings:

/*******************************************************************************

* Function Name  : InitRCC

* Description    : Configures the different system clocks.

* Input          : None

* Output         : None

* Return         : None

*******************************************************************************/

void InitRCC(void)

{

  // RCC system reset

  RCC_DeInit();

  // 1: clocking the controller from internal HSI RC (8 MHz)

  RCC_HSICmd(ENABLE);

 

  // wait until the HSI is ready

  while(RCC_GetFlagStatus(RCC_FLAG_HSIRDY) == RESET);

  // selezione del clock come clock di sistema

  RCC_SYSCLKConfig(RCC_SYSCLKSource_HSI);

 

  // 2: enable ext. high frequency OSC

  RCC_HSEConfig(RCC_HSE_ON);

 

  // wait until the HSE is ready

  while(RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);

 

  // 3: init Embedded Flash

  // ENABLE Prefetch buffer

  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

 

  // SET FLASH latency

  // Flash wait state

  // Zero wait state, if 0 < HCLK 24 MHz

  // --> One wait state, if 24 MHz < HCLK 56 MHz

  // Two wait states, if 56 MHz < HCLK 72 MHz

  FLASH_SetLatency(FLASH_Latency_2);

 

  // Half cycle access disabled

  FLASH_HalfCycleAccessCmd(FLASH_HalfCycleAccess_Disable);

 

  // 4: init PLL

  RCC_PLLConfig(RCC_PLLSource_HSE_Div1,RCC_PLLMul_9); // 72MHz

  RCC_PLLCmd(ENABLE);  // PLL enable

 

  // wait until the PLL is ready

  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

 

  // 5: Set system clock dividers

  RCC_HCLKConfig(RCC_SYSCLK_Div1);//AHB clock-->72MHz

  RCC_PCLK1Config(RCC_HCLK_Div2); //APB1 clock(36MHz)-->TIM4:36*2=72MHz

  RCC_PCLK2Config(RCC_HCLK_Div1); //APB2 clock(72MHz)-->TIM1

  RCC_ADCCLKConfig(RCC_PCLK2_Div6); //clock ADC(72MHz/6)=12MHz

  RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); //clock USB-->48MHz

 

  // 6: Clock system from PLL

  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

  while(RCC_GetSYSCLKSource() != 0x08);  

}

Posted on December 09, 2011 at 16:17

what does it means?

It means the forum is flaky, and crashed/accepted the same post twice, the second of which was edited to indicate that occurred.

OR

It means you have failed to understand that your interrupt handler can/will enter under 3 conditions :

CC

UPDATE

CC+UPDATE

For example consider this subset for CCR values

FFFC

FFFF

0000

0004

In all these cases *BOTH* CC and UPDATE will be signalled on entry, what do you do now?

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabrizio23
Associate II
Posted on December 09, 2011 at 17:03

OK,

how I should do

to

detect

clearly

the two

interrupts

?

Posted on December 09, 2011 at 17:39

Well, I'd start be reading the timer's complete interrupt flag register, and time stamp the entry.

I would deal with the unambiguous conditions first. And I'd read the CCR and CNT registers for the ambiguous case and determine which side of the update the compare occurred. I would also look to use the free running 32-bit counter to count the overflows.

And I'd significantly simplify the logic of the code, but I'm not sure what characteristics/aspects of the signal you are actually trying to measure.

Also, remember you are clocking the counter at 72 MHz, from what I can see,  so you're likely to encounter a window of a hundred or so cycles. The current code structure compounds this problem.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
fabrizio23
Associate II
Posted on December 12, 2011 at 11:46

to explain as well the task:

I want to measure a time interval;

this time interval could be longer of a rollover period of

the cnt register, so I need to count also the rollover events

in order to manage time measures greater of 16 bits.

the rollover ISR will only increment a register

representing the most significant part of the measured

interval,

while the ccr ISR measure the time duration between

n (n will be variable) events by subtracting the old ccr

value from the actual ccr value; then, the obtained value

will be stored into a 8-wide circular buffer.

I agree with the need to correctly manage all the possible

event sequence, and maybe the present code don't do

the job properly, but my actual problem is simpler:

sometimes the update event ISR don't execute, even though

there is no ccr ISR executing.

I tried to disable the ccr interrupt and the update event

work properly; also enabling ccr interrupt but executing

a very short ISR dummy routine the update event work

properly; only trying to execute the whole ccr ISR result

in missing rollover event.