This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Float casting in IRQ (RM46)

Hi!

I encountered a weird problem with float calculation/casting in irq on rm46.
I read some ADC values, do averaging and calculate the millivolts out of the increments.
When I call the handler in FIQ, everything works fine.
Now I wanted to call the handler from IRQ and sometimes the voltage-variable calculates to 0xFFFFFFFF,
although the variable "f" has the right value (verified with debugger).
I think something can go wrong with typecasting while FIQ interrupts the IRQ !?

my code is as follows:

IRQ
void irqHandler(void)
{
	float f;
	uint32_t voltage;
	uint32_t sum = 0;

	// averaging
	for(i=0;i<8;i++)
	{
		sum += adcValues[i];
	}

	f = (float)(sum/8) * 8.13f; // calculation of millivolts with some factor

	voltage = (uint32_t) f;
}

What could produce the problem?

Best regards

Falk

  • Falk,

    As you reported, the issue only occurs sometimes, I would think that there might be some kind of timing issue in your application. To further debug the problem, I would suggest you adding diagnostic check at the end of your ISR as follows.

    if(voltage == 0xffffffff)
    {
    while(1);
    }

    Place a breakpoint at while(1) function so that you can check all the variables in the ISR. Then you will have a clear picture about what is wrong. I would also suggest disabling FIQ so that this ISR is not interrupted.

    Thanks and regards,

    Zhaohong
  • That is exactly what I did before I opened this topic.
    What I saw is, that the error occurs in the conversion from float to u32. (voltage = (uint32_t) f;)
    In assembler I saw that the s0 register is used in every float calculation.
    Are the FPU registers saved before the FIQ interrupts the IRQ?

    Thank you!
    Falk
  • Falk,

    TI compiler does not save FPU registers in interrupt service routines (FIQ and IRQ). The user has to save them manually with assembly instructions such as VSTM and VLDM.

    Thanks and regards,

    Zhaohong

  • Zhaohong,


    I am using the ARM Toolchain.
    Do you have an example for saving and restoring the FPU registers?

    Is there a way to disable FPU usage for specific functions. (Like an attribute)
    I only need to use it in the motor controller task.
    In other functions it could be disabled.

    Thanks!

    Falk

  • Falk,

    Would you please try the following instructions in your c-code?

    asm(" vstm sp!,{d0-d15}"); //save all VFP registers to stack
    asm(" vldm sp!,{d0-d15}"); //restore all VFP registers from stack

    I did not see anyway to disable the use of FPU at the function level. I would suggest not to use float point operation in interrupt service routines.

    Thanks and regards,

    Zhaohong
  • Falk,

    I don't think disabling the FPU as mentioned above is what you want.

    You can control whether the FPU registers are used or not based on compiler switches. So I think you should be able to compile your ISRs so that they do not use the FPU and link w. a control program that does use the FPU. The trick will be to find the right compiler switches. A couple years ago I remember finding the various ABI variants in the ARM compiler manuals for this but I just skimmed their site and can't find it now. If memory serves me they had a way (combination of switches) that you would tell the compiler to compile a particular function to be linkable with another function that does use the FPU -- but also that this particular function does not use the FPU.

    You probably need to go to ARM or Keil for support on this question if you are using their compiler.

    The TI compiler has something similar I believe -- so if you're actually using the TI compiler we can get you help on this.