Electronic – Cortex-M4F FPU problems

armcortex-mfloating pointlaunchpadstellaris

I'm writing some code for a Texas Instruments Stellaris Launchpad board (a Cortex-M4F, the chip is a LM4F120H5QR). I'm using the IRMP library for infrared decoding, which works fine, as long as I don't use any floating point math outside of its ISR. Just a single operation such as in

MAP_SysCtlDelay((MAP_SysCtlClockGet())/ 30.0);

breaks the IRMP library. The chip still runs, IRMP calls all its required functions, UART transmissions work, but IRMP can't decode any infrared reception anymore.

At the very top of my main function I've got:

  // Enable FPU
  MAP_FPULazyStackingEnable();
  MAP_FPUEnable ();

In fact, if I comment out those lines, the software just hangs during intialization.

I've tried several flavours of those FPU enabling functions (ROM_, MAP_, FPUStackingEnable, FPULazyEnable), but nothing seems to fix the problem.

The past 4 hours of Googling have proven useless, so I was hoping to find an answer here.

Edit: More weirdness: if I compile with -O0, IRMP doesn't decode anything either. As soon as I set optimizations to O1 or higher, it starts working again (provided no floating point arithmetic takes place outside of the timer ISR routine and the functions it calls).

Oh, and in case it helps, arm-none-eabi-gcc --version gives:

arm-none-eabi-gcc (GNU Tools for ARM Embedded Processors) 4.7.3 20121207 (release) [ARM/embedded-4_7-branch revision 194305]

I'm compiling with the following options:

-DPART_LM4F120H5QR -DARM_MATH_CM4 -DTARGET_IS_BLIZZARD_RA1 -I$SOMEDIR/stellarisware 
-Os -Wall -std=gnu99 -c -fmessage-length=0 -fsingle-precision-constant -mcpu=cortex-m4 
-mfpu=fpv4-sp-d16 -mthumb -mfloat-abi=softfp -ffunction-sections -fdata-sections

Edit 2: I should add that no actual floating point calculations happen in the IRMP code. That is to say: all variables are integers. However, there are a lot of defines which are intermediate floats, e.g.:

#define IRMP_KEY_REPETITION_LEN (uint16_t)(F_INTERRUPTS * 150.0e-3 + 0.5)

These constants are compared with other uint16_t types in the actual code. I'm not quite sure why this requires FP arithmetic in the run-time code, it's all fixed values which can be folded into integers.

Best Answer

Why don't you try to remove all the floating point calculations from the interrupt service routines. Many folks would point out that it shouldn't be in there in the first place.

Pre-calculate floating point things in the mainline code flow so that it does not need to be in the ISR. This may require some rethinking of the algorithms used but will often lead to more robust and leaner code.