efm32_timer.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. /***************************************************************************//**
  2. * @file
  3. * @brief Timer/counter (TIMER) Peripheral API for EFM32
  4. * @author Energy Micro AS
  5. * @version 2.3.2
  6. *******************************************************************************
  7. * @section License
  8. * <b>(C) Copyright 2010 Energy Micro AS, http://www.energymicro.com</b>
  9. *******************************************************************************
  10. *
  11. * This source code is the property of Energy Micro AS. The source and compiled
  12. * code may only be used on Energy Micro "EFM32" microcontrollers.
  13. *
  14. * This copyright notice may not be removed from the source code nor changed.
  15. *
  16. * DISCLAIMER OF WARRANTY/LIMITATION OF REMEDIES: Energy Micro AS has no
  17. * obligation to support this Software. Energy Micro AS is providing the
  18. * Software "AS IS", with no express or implied warranties of any kind,
  19. * including, but not limited to, any implied warranties of merchantability
  20. * or fitness for any particular purpose or warranties against infringement
  21. * of any proprietary rights of a third party.
  22. *
  23. * Energy Micro AS will not be liable for any consequential, incidental, or
  24. * special damages, or any other relief, or for any claim by any third party,
  25. * arising from your use of this Software.
  26. *
  27. ******************************************************************************/
  28. #include "efm32_timer.h"
  29. #include "efm32_cmu.h"
  30. #include "efm32_assert.h"
  31. /***************************************************************************//**
  32. * @addtogroup EFM32_Library
  33. * @{
  34. ******************************************************************************/
  35. /***************************************************************************//**
  36. * @addtogroup TIMER
  37. * @brief Timer/Counter (TIMER) Peripheral API for EFM32
  38. * @details
  39. * The timer module consists of three main parts:
  40. * @li General timer config and enable control.
  41. * @li Compare/capture control.
  42. * @li Dead time insertion control (may not be available for all timers).
  43. * @{
  44. ******************************************************************************/
  45. /*******************************************************************************
  46. ******************************* DEFINES ***********************************
  47. ******************************************************************************/
  48. /** @cond DO_NOT_INCLUDE_WITH_DOXYGEN */
  49. /** Validation of TIMER register block pointer reference for assert statements. */
  50. #if (TIMER_COUNT == 1)
  51. #define TIMER_REF_VALID(ref) ((ref) == TIMER0)
  52. #elif (TIMER_COUNT == 2)
  53. #define TIMER_REF_VALID(ref) (((ref) == TIMER0) || ((ref) == TIMER1))
  54. #elif (TIMER_COUNT == 3)
  55. #define TIMER_REF_VALID(ref) (((ref) == TIMER0) || \
  56. ((ref) == TIMER1) || \
  57. ((ref) == TIMER2))
  58. #elif (TIMER_COUNT == 4)
  59. #define TIMER_REF_VALID(ref) (((ref) == TIMER0) || \
  60. ((ref) == TIMER1) || \
  61. ((ref) == TIMER2) || \
  62. ((ref) == TIMER3))
  63. #else
  64. #error Undefined number of timers.
  65. #endif
  66. /** Validation of TIMER compare/capture channel number */
  67. #define TIMER_CH_VALID(ch) ((ch) < 3)
  68. /** @endcond */
  69. /*******************************************************************************
  70. ************************** GLOBAL FUNCTIONS *******************************
  71. ******************************************************************************/
  72. /***************************************************************************//**
  73. * @brief
  74. * Start/stop TIMER.
  75. *
  76. * @param[in] timer
  77. * Pointer to TIMER peripheral register block.
  78. *
  79. * @param[in] enable
  80. * true to enable counting, false to disable.
  81. ******************************************************************************/
  82. void TIMER_Enable(TIMER_TypeDef *timer, bool enable)
  83. {
  84. EFM_ASSERT(TIMER_REF_VALID(timer));
  85. if (enable)
  86. {
  87. timer->CMD = TIMER_CMD_START;
  88. }
  89. else
  90. {
  91. timer->CMD = TIMER_CMD_STOP;
  92. }
  93. }
  94. /***************************************************************************//**
  95. * @brief
  96. * Initialize TIMER.
  97. *
  98. * @details
  99. * Notice that counter top must be configured separately with for instance
  100. * TIMER_TopSet(). In addition, compare/capture and dead-time insertion
  101. * init must be initialized separately if used. That should probably
  102. * be done prior to the use of this function if configuring the TIMER to
  103. * start when initialization is completed.
  104. *
  105. * @param[in] timer
  106. * Pointer to TIMER peripheral register block.
  107. *
  108. * @param[in] init
  109. * Pointer to TIMER initialization structure.
  110. ******************************************************************************/
  111. void TIMER_Init(TIMER_TypeDef *timer, const TIMER_Init_TypeDef *init)
  112. {
  113. EFM_ASSERT(TIMER_REF_VALID(timer));
  114. /* Stop timer if specified to be disabled (dosn't hurt if already stopped) */
  115. if (!(init->enable))
  116. {
  117. timer->CMD = TIMER_CMD_STOP;
  118. }
  119. /* Reset counter */
  120. timer->CNT = _TIMER_CNT_RESETVALUE;
  121. timer->CTRL =
  122. ((uint32_t)(init->prescale) << _TIMER_CTRL_PRESC_SHIFT) |
  123. ((uint32_t)(init->clkSel) << _TIMER_CTRL_CLKSEL_SHIFT) |
  124. ((uint32_t)(init->fallAction) << _TIMER_CTRL_FALLA_SHIFT) |
  125. ((uint32_t)(init->riseAction) << _TIMER_CTRL_RISEA_SHIFT) |
  126. ((uint32_t)(init->mode) << _TIMER_CTRL_MODE_SHIFT) |
  127. (init->debugRun ? TIMER_CTRL_DEBUGRUN : 0) |
  128. (init->dmaClrAct ? TIMER_CTRL_DMACLRACT : 0) |
  129. (init->quadModeX4 ? TIMER_CTRL_QDM_X4 : 0) |
  130. (init->oneShot ? TIMER_CTRL_OSMEN : 0) |
  131. #if defined(_EFM32_GIANT_FAMILY) || defined(_EFM32_TINY_FAMILY)
  132. (init->count2x ? TIMER_CTRL_X2CNT : 0) |
  133. (init->ati ? TIMER_CTRL_ATI : 0) |
  134. #endif
  135. (init->sync ? TIMER_CTRL_SYNC : 0);
  136. /* Start timer if specified to be enabled (dosn't hurt if already started) */
  137. if (init->enable)
  138. {
  139. timer->CMD = TIMER_CMD_START;
  140. }
  141. }
  142. /***************************************************************************//**
  143. * @brief
  144. * Initialize TIMER compare/capture channel.
  145. *
  146. * @details
  147. * Notice that if operating channel in compare mode, the CCV and CCVB register
  148. * must be set separately as required.
  149. *
  150. * @param[in] timer
  151. * Pointer to TIMER peripheral register block.
  152. *
  153. * @param[in] ch
  154. * Compare/capture channel to init for.
  155. *
  156. * @param[in] init
  157. * Pointer to TIMER initialization structure.
  158. ******************************************************************************/
  159. void TIMER_InitCC(TIMER_TypeDef *timer,
  160. unsigned int ch,
  161. const TIMER_InitCC_TypeDef *init)
  162. {
  163. EFM_ASSERT(TIMER_REF_VALID(timer));
  164. EFM_ASSERT(TIMER_CH_VALID(ch));
  165. timer->CC[ch].CTRL =
  166. ((uint32_t)(init->eventCtrl) << _TIMER_CC_CTRL_ICEVCTRL_SHIFT) |
  167. ((uint32_t)(init->edge) << _TIMER_CC_CTRL_ICEDGE_SHIFT) |
  168. ((uint32_t)(init->prsSel) << _TIMER_CC_CTRL_PRSSEL_SHIFT) |
  169. ((uint32_t)(init->cufoa) << _TIMER_CC_CTRL_CUFOA_SHIFT) |
  170. ((uint32_t)(init->cofoa) << _TIMER_CC_CTRL_COFOA_SHIFT) |
  171. ((uint32_t)(init->cmoa) << _TIMER_CC_CTRL_CMOA_SHIFT) |
  172. ((uint32_t)(init->mode) << _TIMER_CC_CTRL_MODE_SHIFT) |
  173. (init->filter ? TIMER_CC_CTRL_FILT_ENABLE : 0) |
  174. (init->prsInput ? TIMER_CC_CTRL_INSEL_PRS : 0) |
  175. (init->coist ? TIMER_CC_CTRL_COIST : 0) |
  176. (init->outInvert ? TIMER_CC_CTRL_OUTINV : 0);
  177. }
  178. #ifdef TIMER_DTLOCK_LOCKKEY_LOCK
  179. /***************************************************************************//**
  180. * @brief
  181. * Lock the TIMER in order to protect some of its registers against unintended
  182. * modification.
  183. *
  184. * @details
  185. * Please refer to the reference manual for TIMER registers that will be
  186. * locked.
  187. *
  188. * @note
  189. * If locking the TIMER registers, they must be unlocked prior to using any
  190. * TIMER API functions modifying TIMER registers protected by the lock.
  191. *
  192. * @param[in] timer
  193. * Pointer to TIMER peripheral register block.
  194. ******************************************************************************/
  195. void TIMER_Lock(TIMER_TypeDef *timer)
  196. {
  197. EFM_ASSERT(TIMER_REF_VALID(timer));
  198. timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_LOCK;
  199. }
  200. #endif
  201. /***************************************************************************//**
  202. * @brief
  203. * Reset TIMER to same state as after a HW reset.
  204. *
  205. * @note
  206. * The ROUTE register is NOT reset by this function, in order to allow for
  207. * centralized setup of this feature.
  208. *
  209. * @param[in] timer
  210. * Pointer to TIMER peripheral register block.
  211. ******************************************************************************/
  212. void TIMER_Reset(TIMER_TypeDef *timer)
  213. {
  214. int i;
  215. EFM_ASSERT(TIMER_REF_VALID(timer));
  216. /* Make sure disabled first, before resetting other registers */
  217. timer->CMD = TIMER_CMD_STOP;
  218. timer->CTRL = _TIMER_CTRL_RESETVALUE;
  219. timer->IEN = _TIMER_IEN_RESETVALUE;
  220. timer->IFC = _TIMER_IFC_MASK;
  221. timer->TOP = _TIMER_TOP_RESETVALUE;
  222. timer->TOPB = _TIMER_TOPB_RESETVALUE;
  223. timer->CNT = _TIMER_CNT_RESETVALUE;
  224. /* Do not reset route register, setting should be done independently */
  225. /* (Note: ROUTE register may be locked by DTLOCK register.) */
  226. for (i = 0; TIMER_CH_VALID(i); i++)
  227. {
  228. timer->CC[i].CTRL = _TIMER_CC_CTRL_RESETVALUE;
  229. timer->CC[i].CCV = _TIMER_CC_CCV_RESETVALUE;
  230. timer->CC[i].CCVB = _TIMER_CC_CCVB_RESETVALUE;
  231. }
  232. /* Reset dead time insertion module, no effect on timers without DTI */
  233. #ifdef TIMER_DTLOCK_LOCKKEY_UNLOCK
  234. /* Unlock DTI registers first in case locked */
  235. timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK;
  236. timer->DTCTRL = _TIMER_DTCTRL_RESETVALUE;
  237. timer->DTTIME = _TIMER_DTTIME_RESETVALUE;
  238. timer->DTFC = _TIMER_DTFC_RESETVALUE;
  239. timer->DTOGEN = _TIMER_DTOGEN_RESETVALUE;
  240. timer->DTFAULTC = _TIMER_DTFAULTC_MASK;
  241. #endif
  242. }
  243. #ifdef TIMER_DTLOCK_LOCKKEY_UNLOCK
  244. /***************************************************************************//**
  245. * @brief
  246. * Unlock the TIMER so that writing to locked registers again is possible.
  247. *
  248. * @param[in] timer
  249. * Pointer to TIMER peripheral register block.
  250. ******************************************************************************/
  251. void TIMER_Unlock(TIMER_TypeDef *timer)
  252. {
  253. EFM_ASSERT(TIMER_REF_VALID(timer));
  254. timer->DTLOCK = TIMER_DTLOCK_LOCKKEY_UNLOCK;
  255. }
  256. #endif
  257. /** @} (end addtogroup TIMER) */
  258. /** @} (end addtogroup EFM32_Library) */