2024-05-09 05:26 AM
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:
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.
Solved! Go to Solution.
2024-05-09 07:35 AM
I pref -O3
try place __DSB(); after =0
2024-05-09 08:26 AM
Result with IOs, because debugger might (and does) interfere.
So the ISR is called everytime, but MainCounter is not reset everytime. The behaviour is different with or without debugger connected, and also changes with different optimizations levels.
I'm starting to dislike this MCU, it's not like this is the only problem I have (1,2)
2024-05-09 08:37 AM
void TIM1_UP_IRQHandler(void)
{
LL_GPIO_SetOutputPin(dbg7b_GPIO_Port, dbg7b_Pin);
LL_TIM_ClearFlag_UPDATE(TIM1);
MainCounter = 0;
__DSB();
LL_GPIO_ResetOutputPin(dbg7b_GPIO_Port, dbg7b_Pin);
}
like so? does not help
2024-05-09 09:40 AM
Yes the debugger can frequently be invasive, it doesn't have magic access to the hardware, it must read the register/memory via normal access mechanics. It's will break peripheral status registers and FIFO's
There are DBGMCU settings related to how it deals with TIM clocks, etc.
But dead-stopping in the debugger for user interaction at a snails pace is going to break real-time behaviour. The cat's probably going to die if you peer into the box.. Better to instrument rather than use the debugger in these contexts.
The core's not built around the debug use-case, but the billions of situations where it's not used.
2024-05-09 10:26 AM
Likely because operation "MainCounter++" is not atomic. It consists of two instructions, the interrupt can hit between them.
2024-05-09 10:57 AM
This was my first thought, but my second thought was: this is a problem of the (8-bit microcontroller) past.
So if this is an actual problem, I’m a bit disappointed right now and it looks like I have to rethink a lot of code.
2024-05-09 05:59 PM
Don't rethink, just use the proper thing: atomics.
#include <stdatomic.h>
volatile atomic_int MainCounter;
void TIM1_UP_IRQHandler(void)
{
........
MainCounter = 0;
}
int main(void) {
MainCounter = 0;
.......
while (1) {
MainCounter++;
}
}
2024-05-09 11:27 PM
You explain problem , that exist for example on multitasking shared memory access etc. But your example isnt very clean, AI optimizer completely remove your maincounter because is only set and never get.
Not perfect , but good practice is on one side (irq task ...) only set value and on other only get. For reset then you require next bool flag.
2024-05-10 03:31 AM
interesting, but it takes about twices as long (130ns compared to 60ns, with -O3) as:
__disable_irq();
MainCounter++;
__enable_irq();
2024-05-10 08:32 AM
Using __disable_irq should work too on single core CPU, but then atomic_int is not needed. Choose one.