2024-08-21 12:49 AM
Hi!
I am performing a calculation in an interrupt as this:
L1L2_filteredTimeNegFlank = ((TIM_GetCounter(TIM16)*50) + 206*L1L2_filteredTimeNegFlank)>>8;
But it seems like that it sporadically computes the wrong value and it disappears when I reformulate the calculation like this:
L1L2_filteredTimeNegFlank = TIM_GetCounter(TIM16)*50;
L1L2_filteredTimeNegFlank = L1L2_filteredTimeNegFlank + 206*L1L2_filteredTimeNegFlank;
L1L2_filteredTimeNegFlank = L1L2_filteredTimeNegFlank>>8;
Does anyone know why this happen?
Thanks
/Tomas
Solved! Go to Solution.
2024-08-21 01:05 AM
few general ideas for finding the root cause:
- forgotten volatile declaration when using a global variable in an interrupt?
- cache issues (what core?)
- do you see a pattern in when & what wrong value(s) occur?
- timing glitches by other interfering interrupts like SysTick
- check / change interrupt priorities
- make your handler uninterruptable by using __disable_irq()
- change optimization level
- compare assembler code of both verions
hth
KnarfB
2024-08-21 01:05 AM
few general ideas for finding the root cause:
- forgotten volatile declaration when using a global variable in an interrupt?
- cache issues (what core?)
- do you see a pattern in when & what wrong value(s) occur?
- timing glitches by other interfering interrupts like SysTick
- check / change interrupt priorities
- make your handler uninterruptable by using __disable_irq()
- change optimization level
- compare assembler code of both verions
hth
KnarfB
2024-08-21 01:49 AM
Hi KnarfB,
Thank you so much for your effort!
Seems like you are really experienced, as Im not 🙂
The mcu used is named STM32F030C8T6TR.
The variables are volatile.
How do I recognize if there is a cache issue?
Unfortunately I cannot see any pattern in the occurances.
The optimization level is set o none.
Interrupt priority is set to highest using nvic.
Interesting, when I disable/enable irqs as you suggest the problem occurs more often! This may be something!
Best regards,
Tomas
2024-08-21 04:08 AM
Hello @TBerg
The issue you're encountering is likely due to the way the compiler optimizes and handles the complex expression in the first version of your code. When you break down the calculation into multiple steps, it becomes easier for the compiler to manage unexpected behavior.
Example of code with the steps broken down:
int tempCounter = TIM_GetCounter(TIM16) * 50;
int tempFilteredTime = 206 * L1L2_filteredTimeNegFlank;
int combinedResult = tempCounter + tempFilteredTime;
L1L2_filteredTimeNegFlank = combinedResult >> 8;
By breaking down the calculation into simpler steps, you make the code more readable and reduce the risk of compiler optimization issues or data type overflows. This approach also makes it easier to debug and verify each part of the calculation.
2024-08-21 05:39 AM
So I found the issue that was not what I thought.
The issue came from that there were oscillations on the input signal that generated an interrupt. By separating the computation to several stages, as I did show, I made it slower and probably this lead to that I did read the value later and then the input value was getting time to stabilize. And that changed the result.
My solution was more like this:
stab_IO_Register = 0;
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
while( (stab_IO_Register != 0x7f) && (stab_IO_Register != 0x00) ){
stab_IO_Register = (stab_IO_Register<<1) | (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_7));
stab_IO_Register &= 0x7f;
}
Thank you very much for your effort,
Best regards,
Tomas Bergh