cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H745 - resetting of a variable in ISR does not work occasionally

Kurngop32
Associate III

I have a strange problem. I have a global uint32_t variable that counts up in the main loop and every 100 ms it gets reset in a timer-ISR. This works, but sometimes it does not.

Here is the value of the variable MainCounter read out by the debugger:

Kurngop32_1-1715256571202.png

The ISR is definitely called every time as the toggling variable test shows. Also inside the ISR MainCounter really is zero, I checked. But sometimes this zero does not "reach" the main loop.

Please help, I have absolutely no idea how this is even possible.

1 ACCEPTED SOLUTION

Accepted Solutions
Pavel A.
Evangelist III

Likely because operation "MainCounter++" is not atomic. It consists of two instructions, the interrupt can hit between them.

 

 

View solution in original post

20 REPLIES 20

>>I have absolutely no idea how this is even possible.

a) Optimization On, b) variables that should be flagged as volatile are not..

You'll need to show minimum code

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Kurngop32
Associate III
volatile uint32_t MainCounter = 0;

int main(void) {
	...
	while (1) {
		MainCounter++;
	}
}

void TimerISR(void) {
	extern volatile uint32_t MainCounter;
	static uint32_t reduction_counter = 0;

	if (++reduction_counter == 1000) {
		reduction_counter = 0;
		MainCounter = 0;
	}
}

No optimization, no cache

.data, .bss and stack are in DTCMRAM

It gets worse the shorter the main while loop is. With only the incrementation as in the example above, it is more like: it works sometimes.

If it doesn't reset, then likely because TimerISR() is NOT called. Look at how it's called and watch for RMW on SR, ie TIM->SR &= ~1 type usage

 

if (++reduction_counter >= 1000) { // might make this more defensive

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Kurngop32
Associate III

It is called, see first post. I also checked with toggling IO because I don't trust the debugger.

 

void TimerISR(void) {
	extern volatile uint32_t MainCounter;

 

this isnt good practice, right is 

 

extern volatile uint32_t MainCounter;
void TimerISR(void) {

too TimerISR isnt native ISR call. How you call it?

 


@MM..1 wrote:

too TimerISR isnt native ISR call. How you call it?


I didn't, this was just an example. Here is real, new, good practice code:

extern volatile uint32_t MainCounter;
void TIM1_UP_IRQHandler(void) {
	LL_TIM_ClearFlag_UPDATE(TIM1);
	MainCounter = 0;
}

The result is the same.

I also switched the test board and removed everything besides TIM1 from .ioc and all other unnecessary code, no difference.

And hope TIM and main is on same core. H745 is dual. Too isnt watchdog reset here ?

And LL sometimes require data risc management aka __DSB etc. try swap lines

I attached a freshy made minimal project, if you what to check.

No watchdog. It also happens on both cores.

both cores doing it (-O0)

Kurngop32_0-1715264916877.png

now compiled with -Ofast for both cores, CM7 looks better*
(* at least in this example, the first time I encounter this problem, code was compiled with -Ofast as well)

Kurngop32_1-1715265036719.png