ARM's Floating Point Unit module. More...
Macros | |
#define | FPU_HALF_IEEE 0x00000000 |
#define | FPU_HALF_ALTERNATE 0x04000000 |
#define | FPU_NAN_PROPAGATE 0x00000000 |
#define | FPU_NAN_DEFAULT 0x02000000 |
#define | FPU_FLUSH_TO_ZERO_DIS 0x00000000 |
#define | FPU_FLUSH_TO_ZERO_EN 0x01000000 |
#define | FPU_ROUND_NEAREST 0x00000000 |
#define | FPU_ROUND_POS_INF 0x00400000 |
#define | FPU_ROUND_NEG_INF 0x00800000 |
#define | FPU_ROUND_ZERO 0x00c00000 |
Functions | |
void | FPU_enableModule (void) |
void | FPU_disableModule (void) |
void | FPU_enableStacking (void) |
void | FPU_enableLazyStacking (void) |
void | FPU_disableStacking (void) |
void | FPU_setHalfPrecisionMode (uint32_t mode) |
void | FPU_setNaNMode (uint32_t mode) |
void | FPU_setFlushToZeroMode (uint32_t mode) |
void | FPU_setRoundingMode (uint32_t mode) |
ARM's Floating Point Unit module.
There are three methods of handling the floating-point context when the processor executes an interrupt handler: it can do nothing with the floating-point context, it can always save the floating-point context, or it can perform a lazy save/restore of the floating-point context. If nothing is done with the floating-point context, the interrupt stack frame is identical to a Cortex-M processor that does not have a floating-point unit, containing only the volatile registers of the integer unit. This method is useful for applications where the floating-point unit is used by the main thread of execution, but not in any of the interrupt handlers. By not saving the floating-point context, stack usage is reduced and interrupt latency is kept to a minimum.
Alternatively, the floating-point context can always be saved onto the stack. This method allows floating-point operations to be performed inside interrupt handlers without any special precautions, at the expense of increased stack usage (for the floating-point context) and increased interrupt latency (due to the additional writes to the stack). The advantage to this method is that the stack frame always contains the floating-point context when inside an interrupt handler.
The default handling of the floating-point context is to perform a lazy save/restore. When an interrupt is taken, space is reserved on the stack for the floating-point context but the context is not written. This method keeps the interrupt latency to a minimum because only the integer state is written to the stack. Then, if a floating-point instruction is executed from within the interrupt handler, the floating-point context is written to the stack prior to the execution of the floating-point instruction. Finally, upon return from the interrupt, the floating-point context is restored from the stack only if it was written. Using lazy save/restore provides a blend between fast interrupt response and the ability to use floating-point instructions in the interrupt handler.
The floating-point unit can generate an interrupt when one of several exceptions occur. The exceptions are underflow, overflow, divide by zero, invalid operation, input denormal, and inexact exception. The application can optionally choose to enable one or more of these interrupts and use the interrupt handler to decide upon a course of action to be taken in each case.
The behavior of the floating-point unit can also be adjusted, specifying the format of half-precision floating-point values, the handle of NaN values, the flush-to-zero mode (which sacrifices full IEEE compliance for execution speed), and the rounding mode for results.
Below is a very brief example of floating point operation. While the compiler will usually enable the floating point unit by default, when executing floating point operations it is important to make sure that the coprocessor is enabled (otherwise a system fault will occur).
#define FPU_HALF_IEEE 0x00000000 |
#define FPU_HALF_ALTERNATE 0x04000000 |
#define FPU_NAN_PROPAGATE 0x00000000 |
#define FPU_NAN_DEFAULT 0x02000000 |
#define FPU_FLUSH_TO_ZERO_DIS 0x00000000 |
#define FPU_FLUSH_TO_ZERO_EN 0x01000000 |
#define FPU_ROUND_NEAREST 0x00000000 |
#define FPU_ROUND_POS_INF 0x00400000 |
#define FPU_ROUND_NEG_INF 0x00800000 |
#define FPU_ROUND_ZERO 0x00c00000 |
void FPU_enableModule | ( | void | ) |
Enables the floating-point unit.
This function enables the floating-point unit, allowing the floating-point instructions to be executed. This function must be called prior to performing any hardware floating-point operations; failure to do so results in a NOCP usage fault.
void FPU_disableModule | ( | void | ) |
Disables the floating-point unit.
This function disables the floating-point unit, preventing floating-point instructions from executing (generating a NOCP usage fault instead).
void FPU_enableStacking | ( | void | ) |
Enables the stacking of floating-point registers.
This function enables the stacking of floating-point registers s0-s15 when an interrupt is handled. When enabled, space is reserved on the stack for the floating-point context and the floating-point state is saved into this stack space. Upon return from the interrupt, the floating-point context is restored.
If the floating-point registers are not stacked, floating-point instructions cannot be safely executed in an interrupt handler because the values of s0-s15 are not likely to be preserved for the interrupted code. On the other hand, stacking the floating-point registers increases the stacking operation from 8 words to 26 words, also increasing the interrupt response latency.
void FPU_enableLazyStacking | ( | void | ) |
Enables the lazy stacking of floating-point registers.
This function enables the lazy stacking of floating-point registers s0-s15 when an interrupt is handled. When lazy stacking is enabled, space is reserved on the stack for the floating-point context, but the floating-point state is not saved. If a floating-point instruction is executed from within the interrupt context, the floating-point context is first saved into the space reserved on the stack. On completion of the interrupt handler, the floating-point context is only restored if it was saved (as the result of executing a floating-point instruction).
This method provides a compromise between fast interrupt response (because the floating-point state is not saved on interrupt entry) and the ability to use floating-point in interrupt handlers (because the floating-point state is saved if floating-point instructions are used).
void FPU_disableStacking | ( | void | ) |
Disables the stacking of floating-point registers.
This function disables the stacking of floating-point registers s0-s15 when an interrupt is handled. When floating-point context stacking is disabled, floating-point operations performed in an interrupt handler destroy the floating-point context of the main thread of execution.
void FPU_setHalfPrecisionMode | ( | uint32_t | mode | ) |
Selects the format of half-precision floating-point values.
mode | is the format for half-precision floating-point value, which is either FPU_HALF_IEEE or FPU_HALF_ALTERNATE. |
This function selects between the IEEE half-precision floating-point representation and the Cortex-M processor alternative representation. The alternative representation has a larger range but does not have a way to encode infinity (positive or negative) or NaN (quiet or signalling). The default setting is the IEEE format.
void FPU_setNaNMode | ( | uint32_t | mode | ) |
Selects the NaN mode.
mode | is the mode for NaN results; which is either FPU_NAN_PROPAGATE or FPU_NAN_DEFAULT. |
This function selects the handling of NaN results during floating-point computations. NaNs can either propagate (the default), or they can return the default NaN.
void FPU_setFlushToZeroMode | ( | uint32_t | mode | ) |
Selects the flush-to-zero mode.
mode | is the flush-to-zero mode; which is either FPU_FLUSH_TO_ZERO_DIS or FPU_FLUSH_TO_ZERO_EN. |
This function enables or disables the flush-to-zero mode of the floating-point unit. When disabled (the default), the floating-point unit is fully IEEE compliant. When enabled, values close to zero are treated as zero, greatly improving the execution speed at the expense of some accuracy (as well as IEEE compliance).
void FPU_setRoundingMode | ( | uint32_t | mode | ) |
Selects the rounding mode for floating-point results.
mode | is the rounding mode. |
This function selects the rounding mode for floating-point results. After a floating-point operation, the result is rounded toward the specified value. The default mode is FPU_ROUND_NEAREST.
The following rounding modes are available (as specified by mode):