1 //*****************************************************************************
2 //
3 // fpu.c - Routines for manipulating the floating-point unit in the Cortex-M
4 // processor.
5 //
6 // Copyright (c) 2011-2020 Texas Instruments Incorporated. All rights reserved.
7 // Software License Agreement
8 //
9 // Redistribution and use in source and binary forms, with or without
10 // modification, are permitted provided that the following conditions
11 // are met:
12 //
13 // Redistributions of source code must retain the above copyright
14 // notice, this list of conditions and the following disclaimer.
15 //
16 // Redistributions in binary form must reproduce the above copyright
17 // notice, this list of conditions and the following disclaimer in the
18 // documentation and/or other materials provided with the
19 // distribution.
20 //
21 // Neither the name of Texas Instruments Incorporated nor the names of
22 // its contributors may be used to endorse or promote products derived
23 // from this software without specific prior written permission.
24 //
25 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 //
37 // This is part of revision 2.2.0.295 of the Tiva Peripheral Driver Library.
38 //
39 //*****************************************************************************
40
41 //*****************************************************************************
42 //
43 //! \addtogroup fpu_api
44 //! @{
45 //
46 //*****************************************************************************
47
48 #include <stdint.h>
49 #include "inc/hw_nvic.h"
50 #include "inc/hw_types.h"
51 #include "driverlib/fpu.h"
52
53 //*****************************************************************************
54 //
55 //! Enables the floating-point unit.
56 //!
57 //! This function enables the floating-point unit, allowing the floating-point
58 //! instructions to be executed. This function must be called prior to
59 //! performing any hardware floating-point operations; failure to do so results
60 //! in a NOCP usage fault.
61 //!
62 //! \return None.
63 //
64 //*****************************************************************************
65 void
FPUEnable(void)66 FPUEnable(void)
67 {
68 //
69 // Enable the coprocessors used by the floating-point unit.
70 //
71 HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) &
72 ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) |
73 NVIC_CPAC_CP10_FULL | NVIC_CPAC_CP11_FULL);
74 }
75
76 //*****************************************************************************
77 //
78 //! Disables the floating-point unit.
79 //!
80 //! This function disables the floating-point unit, preventing floating-point
81 //! instructions from executing (generating a NOCP usage fault instead).
82 //!
83 //! \return None.
84 //
85 //*****************************************************************************
86 void
FPUDisable(void)87 FPUDisable(void)
88 {
89 //
90 // Disable the coprocessors used by the floating-point unit.
91 //
92 HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) &
93 ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) |
94 NVIC_CPAC_CP10_DIS | NVIC_CPAC_CP11_DIS);
95 }
96
97 //*****************************************************************************
98 //
99 //! Enables the stacking of floating-point registers.
100 //!
101 //! This function enables the stacking of floating-point registers s0-s15 when
102 //! an interrupt is handled. When enabled, space is reserved on the stack for
103 //! the floating-point context and the floating-point state is saved into this
104 //! stack space. Upon return from the interrupt, the floating-point context is
105 //! restored.
106 //!
107 //! If the floating-point registers are not stacked, floating-point
108 //! instructions cannot be safely executed in an interrupt handler because the
109 //! values of s0-s15 are not likely to be preserved for the interrupted code.
110 //! On the other hand, stacking the floating-point registers increases the
111 //! stacking operation from 8 words to 26 words, also increasing the interrupt
112 //! response latency.
113 //!
114 //! \return None.
115 //
116 //*****************************************************************************
117 void
FPUStackingEnable(void)118 FPUStackingEnable(void)
119 {
120 //
121 // Enable automatic state preservation for the floating-point unit, and
122 // disable lazy state preservation (meaning that the floating-point state
123 // is always stacked when floating-point instructions are used).
124 //
125 HWREG(NVIC_FPCC) = (HWREG(NVIC_FPCC) & ~NVIC_FPCC_LSPEN) | NVIC_FPCC_ASPEN;
126 }
127
128 //*****************************************************************************
129 //
130 //! Enables the lazy stacking of floating-point registers.
131 //!
132 //! This function enables the lazy stacking of floating-point registers s0-s15
133 //! when an interrupt is handled. When lazy stacking is enabled, space is
134 //! reserved on the stack for the floating-point context, but the
135 //! floating-point state is not saved. If a floating-point instruction is
136 //! executed from within the interrupt context, the floating-point context is
137 //! first saved into the space reserved on the stack. On completion of the
138 //! interrupt handler, the floating-point context is only restored if it was
139 //! saved (as the result of executing a floating-point instruction).
140 //!
141 //! This method provides a compromise between fast interrupt response (because
142 //! the floating-point state is not saved on interrupt entry) and the ability
143 //! to use floating-point in interrupt handlers (because the floating-point
144 //! state is saved if floating-point instructions are used).
145 //!
146 //! \return None.
147 //
148 //*****************************************************************************
149 void
FPULazyStackingEnable(void)150 FPULazyStackingEnable(void)
151 {
152 //
153 // Enable automatic and lazy state preservation for the floating-point
154 // unit.
155 //
156 HWREG(NVIC_FPCC) |= NVIC_FPCC_ASPEN | NVIC_FPCC_LSPEN;
157 }
158
159 //*****************************************************************************
160 //
161 //! Disables the stacking of floating-point registers.
162 //!
163 //! This function disables the stacking of floating-point registers s0-s15 when
164 //! an interrupt is handled. When floating-point context stacking is disabled,
165 //! floating-point operations performed in an interrupt handler destroy the
166 //! floating-point context of the main thread of execution.
167 //!
168 //! \return None.
169 //
170 //*****************************************************************************
171 void
FPUStackingDisable(void)172 FPUStackingDisable(void)
173 {
174 //
175 // Disable automatic and lazy state preservation for the floating-point
176 // unit.
177 //
178 HWREG(NVIC_FPCC) &= ~(NVIC_FPCC_ASPEN | NVIC_FPCC_LSPEN);
179 }
180
181 //*****************************************************************************
182 //
183 //! Selects the format of half-precision floating-point values.
184 //!
185 //! \param ui32Mode is the format for half-precision floating-point value,
186 //! which is either \b FPU_HALF_IEEE or \b FPU_HALF_ALTERNATE.
187 //!
188 //! This function selects between the IEEE half-precision floating-point
189 //! representation and the Cortex-M processor alternative representation. The
190 //! alternative representation has a larger range but does not have a way to
191 //! encode infinity (positive or negative) or NaN (quiet or signaling). The
192 //! default setting is the IEEE format.
193 //!
194 //! \note Unless this function is called prior to executing any floating-point
195 //! instructions, the default mode is used.
196 //!
197 //! \return None.
198 //
199 //*****************************************************************************
200 void
FPUHalfPrecisionModeSet(uint32_t ui32Mode)201 FPUHalfPrecisionModeSet(uint32_t ui32Mode)
202 {
203 //
204 // Set the half-precision floating-point format.
205 //
206 HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_AHP)) | ui32Mode;
207 }
208
209 //*****************************************************************************
210 //
211 //! Selects the NaN mode.
212 //!
213 //! \param ui32Mode is the mode for NaN results; which is either
214 //! \b FPU_NAN_PROPAGATE or \b FPU_NAN_DEFAULT.
215 //!
216 //! This function selects the handling of NaN results during floating-point
217 //! computations. NaNs can either propagate (the default), or they can return
218 //! the default NaN.
219 //!
220 //! \note Unless this function is called prior to executing any floating-point
221 //! instructions, the default mode is used.
222 //!
223 //! \return None.
224 //
225 //*****************************************************************************
226 void
FPUNaNModeSet(uint32_t ui32Mode)227 FPUNaNModeSet(uint32_t ui32Mode)
228 {
229 //
230 // Set the NaN mode.
231 //
232 HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_DN)) | ui32Mode;
233 }
234
235 //*****************************************************************************
236 //
237 //! Selects the flush-to-zero mode.
238 //!
239 //! \param ui32Mode is the flush-to-zero mode; which is either
240 //! \b FPU_FLUSH_TO_ZERO_DIS or \b FPU_FLUSH_TO_ZERO_EN.
241 //!
242 //! This function enables or disables the flush-to-zero mode of the
243 //! floating-point unit. When disabled (the default), the floating-point unit
244 //! is fully IEEE compliant. When enabled, values close to zero are treated as
245 //! zero, greatly improving the execution speed at the expense of some accuracy
246 //! (as well as IEEE compliance).
247 //!
248 //! \note Unless this function is called prior to executing any floating-point
249 //! instructions, the default mode is used.
250 //!
251 //! \return None.
252 //
253 //*****************************************************************************
254 void
FPUFlushToZeroModeSet(uint32_t ui32Mode)255 FPUFlushToZeroModeSet(uint32_t ui32Mode)
256 {
257 //
258 // Set the flush-to-zero mode.
259 //
260 HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_FZ)) | ui32Mode;
261 }
262
263 //*****************************************************************************
264 //
265 //! Selects the rounding mode for floating-point results.
266 //!
267 //! \param ui32Mode is the rounding mode.
268 //!
269 //! This function selects the rounding mode for floating-point results. After
270 //! a floating-point operation, the result is rounded toward the specified
271 //! value. The default mode is \b FPU_ROUND_NEAREST.
272 //!
273 //! The following rounding modes are available (as specified by \e ui32Mode):
274 //!
275 //! - \b FPU_ROUND_NEAREST - round toward the nearest value
276 //! - \b FPU_ROUND_POS_INF - round toward positive infinity
277 //! - \b FPU_ROUND_NEG_INF - round toward negative infinity
278 //! - \b FPU_ROUND_ZERO - round toward zero
279 //!
280 //! \note Unless this function is called prior to executing any floating-point
281 //! instructions, the default mode is used.
282 //!
283 //! \return None.
284 //
285 //*****************************************************************************
286 void
FPURoundingModeSet(uint32_t ui32Mode)287 FPURoundingModeSet(uint32_t ui32Mode)
288 {
289 //
290 // Set the rounding mode.
291 //
292 HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_RMODE_M)) | ui32Mode;
293 }
294
295 //*****************************************************************************
296 //
297 // Close the Doxygen group.
298 //! @}
299 //
300 //*****************************************************************************
301