5
\$\begingroup\$

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.

\$\endgroup\$
5
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ +1, I'm not familiar enough with that platform to be sure but sounds like the FPU operations are not atomic leaving it in an undefined state. Another (not good long term) thing would be to disable interrupts while doing all FPU code in your main code just to see if that solves it. \$\endgroup\$ – PeterJ Feb 7 '13 at 3:53
  • \$\begingroup\$ I agree that the ISR is not the ideal location for FP calculations, so if all else fails, I guess I'll have to do that. However, I'd rather just have the library work instead of having to wade through all the code and cripple it just for the sake of getting it to work. \$\endgroup\$ – Darhuuk Feb 7 '13 at 10:21
  • \$\begingroup\$ As for the FPU operations not being atomic: the existence of the FPUStackingEnable() function would suggest otherwise. Also, I can break the code by executing 1 single FP operation even before initializing the IRMP library. After that my main() is just an empty busy loop. \$\endgroup\$ – Darhuuk Feb 7 '13 at 10:23
  • \$\begingroup\$ @Michael Karas: I went through the code, there's not FP arithmetic in there anyway. See my update nr 2 in the original question. \$\endgroup\$ – Darhuuk Feb 8 '13 at 1:20
  • \$\begingroup\$ @Darhuuk - Sorry if I answered wrong for your specific situation. My comment still stands for doing Interrupt time code in that it is generally a bad practice to do things like floating point inside it an ISR. For most programming like this it is wisest to keep code executed at each interrupt to a minimum. Simply enabling the option to supposedly enable the floating point inside ISRs places a big burden on each interrupt routine to in terms of having to push a lot of big registers to the stack. Look at the disassembly code....ouch. \$\endgroup\$ – Michael Karas Feb 8 '13 at 5:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.