fpu.c 10 KB

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