cancel
Showing results for 
Search instead for 
Did you mean: 

Computation error occurs sporadically

TBerg
Associate II

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

1 ACCEPTED SOLUTION

Accepted Solutions
KnarfB
Principal III

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

View solution in original post

4 REPLIES 4
KnarfB
Principal III

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

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

 

nouirakh
ST Employee

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.

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