Reputation: 2101
Relevant Specs:
Question: How might I programmatically turn the FPU on prior to FP computations, and turn it off again when finished?
In SystemInit()
, which is called prior to main
, the following code is executed:
#if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2)); /* set CP10 and CP11 Full Access */
#endif
Note that this sets CPACR bits [23:20] to 1. This is required, or else a HardFault IRQ will be called upon the next FPU assembler instruction. But does disabling this have any additional implications, such as lower power-consumption, etc, or does this register just police the coprocessor (FPU)?
If there is no further implication, then perhaps "turning it off", via CPACR, doesn't accomplish anything, indicating that FPU only draws additional power while executing FPU Instruction Set commands.
Thanks,
Upvotes: 2
Views: 4950
Reputation: 1820
You will get a Usage Fault (or promoted Hard Fault if Usage Faults are disabled) if an instruction attempts to access a coprocessor (like the FPU) and it is disabled. You can inspect the NOCP bit in the Usage Fault Status Register to see if that is the source of the fault. You can then use the Usage Fault as a trap to enable the FPU and resume execution.
My approach would be as follows:
If you use an RTOS, you will need to look at their implementation of context switching, as it may also attempt to hook into the Usage Fault/Hard Fault if it uses lazy stacking (see reference) rather than active stacking.
One thing to consider if power is a concern would be whether floating point is needed. If you can represent your number space as fixed point in a 32-bit value, using fixed point math instead of floating point may result in overall lower power consumption, as there would be no overhead to enabling/disabling the FPU or stacking FPU registers on context switch. The trade-off is that the fixed point math may be a few instructions longer per operation
Reference: ARM AppNote 298
Upvotes: 2