//***************************************************************************** // // fpu.c - Routines for manipulating the floating-point unit in the Cortex-M // processor. // // Copyright (c) 2011 Texas Instruments Incorporated. All rights reserved. // Software License Agreement // // Texas Instruments (TI) is supplying this software for use solely and // exclusively on TI's microcontroller products. The software is owned by // TI and/or its suppliers, and is protected under applicable copyright // laws. You may not combine this software with "viral" open-source // software in order to form a larger program. // // THIS SOFTWARE IS PROVIDED "AS IS" AND WITH ALL FAULTS. // NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING, BUT // NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR // A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE. TI SHALL NOT, UNDER ANY // CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR CONSEQUENTIAL // DAMAGES, FOR ANY REASON WHATSOEVER. // // This is part of revision 8264 of the Stellaris Peripheral Driver Library. // //***************************************************************************** //***************************************************************************** // //! \addtogroup fpu_api //! @{ // //***************************************************************************** #include "inc/hw_nvic.h" #include "inc/hw_types.h" #include "fpu.h" //***************************************************************************** // //! 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. //! //! \return None. // //***************************************************************************** void FPUEnable(void) { // // Enable the coprocessors used by the floating-point unit. // HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) & ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) | NVIC_CPAC_CP10_FULL | NVIC_CPAC_CP11_FULL); } //***************************************************************************** // //! Disables the floating-point unit. //! //! This function disables the floating-point unit, preventing floating-point //! instructions from executing (generating a NOCP usage fault instead). //! //! \return None. // //***************************************************************************** void FPUDisable(void) { // // Disable the coprocessors used by the floating-point unit. // HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) & ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) | NVIC_CPAC_CP10_DIS | NVIC_CPAC_CP11_DIS); } //***************************************************************************** // //! 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. //! //! \return None. // //***************************************************************************** void FPUStackingEnable(void) { // // Enable automatic state preservation for the floating-point unit, and // disable lazy state preservation (meaning that the floating-point state // is always stacked when floating-point instructions are used). // HWREG(NVIC_FPCC) = (HWREG(NVIC_FPCC) & ~NVIC_FPCC_LSPEN) | NVIC_FPCC_ASPEN; } //***************************************************************************** // //! 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). //! //! \return None. // //***************************************************************************** void FPULazyStackingEnable(void) { // // Enable automatic and lazy state preservation for the floating-point // unit. // HWREG(NVIC_FPCC) |= NVIC_FPCC_ASPEN | NVIC_FPCC_LSPEN; } //***************************************************************************** // //! 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. //! //! \return None. // //***************************************************************************** void FPUStackingDisable(void) { // // Disable automatic and lazy state preservation for the floating-point // unit. // HWREG(NVIC_FPCC) &= ~(NVIC_FPCC_ASPEN | NVIC_FPCC_LSPEN); } //***************************************************************************** // //! Selects the format of half-precision floating-point values. //! //! \param ulMode is the format for half-precision floating-point value, which //! is either \b FPU_HALF_IEEE or \b 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 signaling). The //! default setting is the IEEE format. //! //! \note Unless this function is called prior to executing any floating-point //! instructions, the default mode is used. //! //! \return None. // //***************************************************************************** void FPUHalfPrecisionModeSet(unsigned long ulMode) { // // Set the half-precision floating-point format. // HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_AHP)) | ulMode; } //***************************************************************************** // //! Selects the NaN mode. //! //! \param ulMode is the mode for NaN results; which is either //! \b FPU_NAN_PROPAGATE or \b 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. //! //! \note Unless this function is called prior to executing any floating-point //! instructions, the default mode is used. //! //! \return None. // //***************************************************************************** void FPUNaNModeSet(unsigned long ulMode) { // // Set the NaN mode. // HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_DN)) | ulMode; } //***************************************************************************** // //! Selects the flush-to-zero mode. //! //! \param ulMode is the flush-to-zero mode; which is either //! \b FPU_FLUSH_TO_ZERO_DIS or \b 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). //! //! \note Unless this function is called prior to executing any floating-point //! instructions, the default mode is used. //! //! \return None. // //***************************************************************************** void FPUFlushToZeroModeSet(unsigned long ulMode) { // // Set the flush-to-zero mode. // HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_FZ)) | ulMode; } //***************************************************************************** // //! Selects the rounding mode for floating-point results. //! //! \param ulMode 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 \b FPU_ROUND_NEAREST. //! //! The following rounding modes are available (as specified by \e ulMode): //! //! - \b FPU_ROUND_NEAREST - round toward the nearest value //! - \b FPU_ROUND_POS_INF - round toward positive infinity //! - \b FPU_ROUND_NEG_INF - round toward negative infinity //! - \b FPU_ROUND_ZERO - round toward zero //! //! \note Unless this function is called prior to executing any floating-point //! instructions, the default mode is used. //! //! \return None. // //***************************************************************************** void FPURoundingModeSet(unsigned long ulMode) { // // Set the rounding mode. // HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_RMODE_M)) | ulMode; } //***************************************************************************** // // Close the Doxygen group. //! @} // //*****************************************************************************