cancel
Showing results for 
Search instead for 
Did you mean: 

Disabling interrupts and clearing flags (TIM8 CC4) - Only working when interrupts are enabled?

Tobe
Senior III

I have quite a complicated case, where a interrupt is beeing executed, allthough it has been disabled, and its flag beeing cleared. At the same time interrupts are disabled, and i put a few nops in between just to rule out any delay related issues. The disabling of the interrupt works, but there is just one afterwards that i cant get rid of.

For now i just would like to know, if anyone has any idea if the title can be answered with yes. (And if there is a explanation why that is)

I would have liked to try a minimal code, but its quite complicated and i am afraid the error can then not be reproduced. Timers are interconnected too.

6 REPLIES 6

If you disable the interrupt at the source (e.g. in TIMx_DIERx), it takes time until this gets propagated into NVIC.

There may be a strange effect with the interrupt "reappearing" in NVIC, if it was cleared too soon after disabling the interrupt source.

JW

This is how i clear it:

CLEAR_BIT(TIM8->DIER, TIM_DIER_CC4IE);

30 NOP´s

TIM8->SR = ~TIM_SR_CC4IF;

30 NOP´s

other code

SET_BIT(TIM8->EGR, TIM_EGR_COMG); //should not matter here

delayMicros(2);

When i enable interrupts before the delay, the interrupt does not get fired again, if i enable interrupts after, it does get fired again. See the picture for timing illusatration:

  • PC4 is the actual clearing (first 5 lines of code above).
  • PB11 is the problem interrupt
  • Pink lines show interrupt times
  • PA12 is the interrupt, that (should) disables the problem interrupt
  • Ignore the "IRQ Disabled" channel, as it has some issue and is not valid

There is no direct relationship between commutation event and CC4 event, so it can't be judged from this description without knowing your entire program.

JW

Any ideas what i could look into? What registers, or what tactic could be done?

What about the enabling of interruts, why does it make a difference of when the are enabled?

Allthough your link is not the exact problem i have (i think), it helped me (reading pending states) to get further: clearing the TIM_SR_CC4IF flag did not clear the pending interrupt, i had to clear the pending interrupt too.

 

Is this something that has to be done in general? I did not stumble upon this issue yet with my other interrupts.

 

I have now finished my investigation:

It is, as i expected, and wrote in the title of this topic:

In order for the pending status to be cleared with clearing the TIM_SR_CC4IF flag, interrupts have to be enabled at the same time. This also applies to reading the TIM_SR_CC4IF register.

That is NOT something i would expect. Usually i would disable interrupts, and then clear flags, to have a clean state of my program.

NOTE: It is necessary to have enabled interrupts in general, AND the CC interrupt itself, in order for the reading and clearing of the CC4IF flag to work properly!

I went down the rabbit hole, and i was there for quite a few days...

Huge thanks @waclawek.jan for pushing me into the right track, and using the array to debug the pending state!

Here the code as it was last used by me:

 

 

//__enable_irq();
	//while(READ_BIT(TIM8->SR, TIM_SR_CC4IF));	// Wait for flag to cause issue //TODO: Debug remove

	//IRQ_DISABLE_SAVE_PREV
	NVIC_EnableIRQ(TIM8_CC_IRQn);

	SEVEN_NOPS
	stateArray[2] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);

	TEST_CLEAR_TIM8_CC4_IRQ_DIS_ON
	CLEAR_BIT(TIM8->DIER, TIM_DIER_CC4IE);	// Disable interrupts (from ADC trigger) for kind of sine wave generation

	SEVEN_NOPS
	stateArray[3] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);

	TIM8->SR = ~TIM_SR_CC4IF;				// Clear any pending interrupts that were already pending.

	stateArray[4] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);
	SEVEN_NOPS
	stateArray[5] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);

//	NVIC_ClearPendingIRQ(TIM8_CC_IRQn);
//
//	stateArray[6] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);
//	SEVEN_NOPS				// Account for delay, that a signal could arrive after clearing the pending interrupt.


	stateArray[7] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);




	if(millis() > 100)
		stopNow = true;
	updateDuty();


	delayMicroseconds(6);	// delay and test if interrupt cleared
	TEST_CLEAR_TIM8_CC4_IRQ_DIS_OFF
	//__enable_irq();
	NVIC_EnableIRQ(TIM8_CC_IRQn);
	stateArray[8] =  NVIC_GetPendingIRQ(TIM8_CC_IRQn);