em_timer.c 11 KB

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