fpu.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300
  1. //*****************************************************************************
  2. //
  3. // fpu.c - Routines for manipulating the floating-point unit in the Cortex-M
  4. // processor.
  5. //
  6. // Copyright (c) 2011-2014 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.1.0.12573 of the Tiva Peripheral Driver Library.
  38. //
  39. //*****************************************************************************
  40. //*****************************************************************************
  41. //
  42. //! \addtogroup fpu_api
  43. //! @{
  44. //
  45. //*****************************************************************************
  46. #include <stdint.h>
  47. #include "inc/hw_nvic.h"
  48. #include "inc/hw_types.h"
  49. #include "driverlib/fpu.h"
  50. //*****************************************************************************
  51. //
  52. //! Enables the floating-point unit.
  53. //!
  54. //! This function enables the floating-point unit, allowing the floating-point
  55. //! instructions to be executed. This function must be called prior to
  56. //! performing any hardware floating-point operations; failure to do so results
  57. //! in a NOCP usage fault.
  58. //!
  59. //! \return None.
  60. //
  61. //*****************************************************************************
  62. void
  63. FPUEnable(void)
  64. {
  65. //
  66. // Enable the coprocessors used by the floating-point unit.
  67. //
  68. HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) &
  69. ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) |
  70. NVIC_CPAC_CP10_FULL | NVIC_CPAC_CP11_FULL);
  71. }
  72. //*****************************************************************************
  73. //
  74. //! Disables the floating-point unit.
  75. //!
  76. //! This function disables the floating-point unit, preventing floating-point
  77. //! instructions from executing (generating a NOCP usage fault instead).
  78. //!
  79. //! \return None.
  80. //
  81. //*****************************************************************************
  82. void
  83. FPUDisable(void)
  84. {
  85. //
  86. // Disable the coprocessors used by the floating-point unit.
  87. //
  88. HWREG(NVIC_CPAC) = ((HWREG(NVIC_CPAC) &
  89. ~(NVIC_CPAC_CP10_M | NVIC_CPAC_CP11_M)) |
  90. NVIC_CPAC_CP10_DIS | NVIC_CPAC_CP11_DIS);
  91. }
  92. //*****************************************************************************
  93. //
  94. //! Enables the stacking of floating-point registers.
  95. //!
  96. //! This function enables the stacking of floating-point registers s0-s15 when
  97. //! an interrupt is handled. When enabled, space is reserved on the stack for
  98. //! the floating-point context and the floating-point state is saved into this
  99. //! stack space. Upon return from the interrupt, the floating-point context is
  100. //! restored.
  101. //!
  102. //! If the floating-point registers are not stacked, floating-point
  103. //! instructions cannot be safely executed in an interrupt handler because the
  104. //! values of s0-s15 are not likely to be preserved for the interrupted code.
  105. //! On the other hand, stacking the floating-point registers increases the
  106. //! stacking operation from 8 words to 26 words, also increasing the interrupt
  107. //! response latency.
  108. //!
  109. //! \return None.
  110. //
  111. //*****************************************************************************
  112. void
  113. FPUStackingEnable(void)
  114. {
  115. //
  116. // Enable automatic state preservation for the floating-point unit, and
  117. // disable lazy state preservation (meaning that the floating-point state
  118. // is always stacked when floating-point instructions are used).
  119. //
  120. HWREG(NVIC_FPCC) = (HWREG(NVIC_FPCC) & ~NVIC_FPCC_LSPEN) | NVIC_FPCC_ASPEN;
  121. }
  122. //*****************************************************************************
  123. //
  124. //! Enables the lazy stacking of floating-point registers.
  125. //!
  126. //! This function enables the lazy stacking of floating-point registers s0-s15
  127. //! when an interrupt is handled. When lazy stacking is enabled, space is
  128. //! reserved on the stack for the floating-point context, but the
  129. //! floating-point state is not saved. If a floating-point instruction is
  130. //! executed from within the interrupt context, the floating-point context is
  131. //! first saved into the space reserved on the stack. On completion of the
  132. //! interrupt handler, the floating-point context is only restored if it was
  133. //! saved (as the result of executing a floating-point instruction).
  134. //!
  135. //! This method provides a compromise between fast interrupt response (because
  136. //! the floating-point state is not saved on interrupt entry) and the ability
  137. //! to use floating-point in interrupt handlers (because the floating-point
  138. //! state is saved if floating-point instructions are used).
  139. //!
  140. //! \return None.
  141. //
  142. //*****************************************************************************
  143. void
  144. FPULazyStackingEnable(void)
  145. {
  146. //
  147. // Enable automatic and lazy state preservation for the floating-point
  148. // unit.
  149. //
  150. HWREG(NVIC_FPCC) |= NVIC_FPCC_ASPEN | NVIC_FPCC_LSPEN;
  151. }
  152. //*****************************************************************************
  153. //
  154. //! Disables the stacking of floating-point registers.
  155. //!
  156. //! This function disables the stacking of floating-point registers s0-s15 when
  157. //! an interrupt is handled. When floating-point context stacking is disabled,
  158. //! floating-point operations performed in an interrupt handler destroy the
  159. //! floating-point context of the main thread of execution.
  160. //!
  161. //! \return None.
  162. //
  163. //*****************************************************************************
  164. void
  165. FPUStackingDisable(void)
  166. {
  167. //
  168. // Disable automatic and lazy state preservation for the floating-point
  169. // unit.
  170. //
  171. HWREG(NVIC_FPCC) &= ~(NVIC_FPCC_ASPEN | NVIC_FPCC_LSPEN);
  172. }
  173. //*****************************************************************************
  174. //
  175. //! Selects the format of half-precision floating-point values.
  176. //!
  177. //! \param ui32Mode is the format for half-precision floating-point value,
  178. //! which is either \b FPU_HALF_IEEE or \b FPU_HALF_ALTERNATE.
  179. //!
  180. //! This function selects between the IEEE half-precision floating-point
  181. //! representation and the Cortex-M processor alternative representation. The
  182. //! alternative representation has a larger range but does not have a way to
  183. //! encode infinity (positive or negative) or NaN (quiet or signaling). The
  184. //! default setting is the IEEE format.
  185. //!
  186. //! \note Unless this function is called prior to executing any floating-point
  187. //! instructions, the default mode is used.
  188. //!
  189. //! \return None.
  190. //
  191. //*****************************************************************************
  192. void
  193. FPUHalfPrecisionModeSet(uint32_t ui32Mode)
  194. {
  195. //
  196. // Set the half-precision floating-point format.
  197. //
  198. HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_AHP)) | ui32Mode;
  199. }
  200. //*****************************************************************************
  201. //
  202. //! Selects the NaN mode.
  203. //!
  204. //! \param ui32Mode is the mode for NaN results; which is either
  205. //! \b FPU_NAN_PROPAGATE or \b FPU_NAN_DEFAULT.
  206. //!
  207. //! This function selects the handling of NaN results during floating-point
  208. //! computations. NaNs can either propagate (the default), or they can return
  209. //! the default NaN.
  210. //!
  211. //! \note Unless this function is called prior to executing any floating-point
  212. //! instructions, the default mode is used.
  213. //!
  214. //! \return None.
  215. //
  216. //*****************************************************************************
  217. void
  218. FPUNaNModeSet(uint32_t ui32Mode)
  219. {
  220. //
  221. // Set the NaN mode.
  222. //
  223. HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_DN)) | ui32Mode;
  224. }
  225. //*****************************************************************************
  226. //
  227. //! Selects the flush-to-zero mode.
  228. //!
  229. //! \param ui32Mode is the flush-to-zero mode; which is either
  230. //! \b FPU_FLUSH_TO_ZERO_DIS or \b FPU_FLUSH_TO_ZERO_EN.
  231. //!
  232. //! This function enables or disables the flush-to-zero mode of the
  233. //! floating-point unit. When disabled (the default), the floating-point unit
  234. //! is fully IEEE compliant. When enabled, values close to zero are treated as
  235. //! zero, greatly improving the execution speed at the expense of some accuracy
  236. //! (as well as IEEE compliance).
  237. //!
  238. //! \note Unless this function is called prior to executing any floating-point
  239. //! instructions, the default mode is used.
  240. //!
  241. //! \return None.
  242. //
  243. //*****************************************************************************
  244. void
  245. FPUFlushToZeroModeSet(uint32_t ui32Mode)
  246. {
  247. //
  248. // Set the flush-to-zero mode.
  249. //
  250. HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_FZ)) | ui32Mode;
  251. }
  252. //*****************************************************************************
  253. //
  254. //! Selects the rounding mode for floating-point results.
  255. //!
  256. //! \param ui32Mode is the rounding mode.
  257. //!
  258. //! This function selects the rounding mode for floating-point results. After
  259. //! a floating-point operation, the result is rounded toward the specified
  260. //! value. The default mode is \b FPU_ROUND_NEAREST.
  261. //!
  262. //! The following rounding modes are available (as specified by \e ui32Mode):
  263. //!
  264. //! - \b FPU_ROUND_NEAREST - round toward the nearest value
  265. //! - \b FPU_ROUND_POS_INF - round toward positive infinity
  266. //! - \b FPU_ROUND_NEG_INF - round toward negative infinity
  267. //! - \b FPU_ROUND_ZERO - round toward zero
  268. //!
  269. //! \note Unless this function is called prior to executing any floating-point
  270. //! instructions, the default mode is used.
  271. //!
  272. //! \return None.
  273. //
  274. //*****************************************************************************
  275. void
  276. FPURoundingModeSet(uint32_t ui32Mode)
  277. {
  278. //
  279. // Set the rounding mode.
  280. //
  281. HWREG(NVIC_FPDSC) = (HWREG(NVIC_FPDSC) & ~(NVIC_FPDSC_RMODE_M)) | ui32Mode;
  282. }
  283. //*****************************************************************************
  284. //
  285. // Close the Doxygen group.
  286. //! @}
  287. //
  288. //*****************************************************************************