fpu.c 11 KB

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