nu_etimer.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341
  1. /**************************************************************************//**
  2. * @file etimer.c
  3. * @brief N9H30 series ETIMER driver source file
  4. *
  5. * @note
  6. * SPDX-License-Identifier: Apache-2.0
  7. * Copyright (C) 2018 Nuvoton Technology Corp. All rights reserved.
  8. *****************************************************************************/
  9. #include "N9H30.h"
  10. #include "nu_sys.h"
  11. /// @cond HIDDEN_SYMBOLS
  12. /**
  13. * @brief This API is used to get the clock frequency of Timer
  14. * @param[in] timer ETIMER number. Range from 0 ~ 3
  15. * @return Timer clock frequency
  16. * @note This API cannot return correct clock rate if timer source is external clock input.
  17. */
  18. UINT ETIMER_GetModuleClock(UINT timer)
  19. {
  20. UINT src;
  21. src = (inpw(REG_CLK_DIVCTL8) >> (16 + timer * 4)) & 0x3;
  22. if (src == 0)
  23. return 12000000;
  24. else if (src == 1)
  25. return (sysGetClock(SYS_PCLK) * 1000000);
  26. else if (src == 2)
  27. return (sysGetClock(SYS_PCLK) * 1000000 / 4096);
  28. else
  29. return 32768;
  30. }
  31. /// @endcond /* HIDDEN_SYMBOLS */
  32. /** @addtogroup N9H30_Device_Driver N9H30 Device Driver
  33. @{
  34. */
  35. /** @addtogroup N9H30_ETIMER_Driver ETIMER Driver
  36. @{
  37. */
  38. /** @addtogroup N9H30_ETIMER_EXPORTED_FUNCTIONS ETIMER Exported Functions
  39. @{
  40. */
  41. /**
  42. * @brief This API is used to configure timer to operate in specified mode
  43. * and frequency. If timer cannot work in target frequency, a closest
  44. * frequency will be chose and returned.
  45. * @param[in] timer ETIMER number. Range from 0 ~ 3
  46. * @param[in] u32Mode Operation mode. Possible options are
  47. * - \ref ETIMER_ONESHOT_MODE
  48. * - \ref ETIMER_PERIODIC_MODE
  49. * - \ref ETIMER_TOGGLE_MODE
  50. * - \ref ETIMER_CONTINUOUS_MODE
  51. * @param[in] u32Freq Target working frequency
  52. * @return Real Timer working frequency
  53. * @note After calling this API, Timer is \b NOT running yet. But could start timer running be calling
  54. * \ref ETIMER_Start macro or program registers directly
  55. */
  56. UINT ETIMER_Open(UINT timer, UINT u32Mode, UINT u32Freq)
  57. {
  58. UINT u32Clk = ETIMER_GetModuleClock(timer);
  59. UINT u32Cmpr = 0, u32Prescale = 0;
  60. // Fastest possible timer working freq is u32Clk / 2. While cmpr = 2, pre-scale = 0
  61. if (u32Freq > (u32Clk / 2))
  62. {
  63. u32Cmpr = 2;
  64. }
  65. else
  66. {
  67. if (u32Clk >= 0x4000000)
  68. {
  69. u32Prescale = 7; // real prescaler value is 8
  70. u32Clk >>= 3;
  71. }
  72. else if (u32Clk >= 0x2000000)
  73. {
  74. u32Prescale = 3; // real prescaler value is 4
  75. u32Clk >>= 2;
  76. }
  77. else if (u32Clk >= 0x1000000)
  78. {
  79. u32Prescale = 1; // real prescaler value is 2
  80. u32Clk >>= 1;
  81. }
  82. u32Cmpr = u32Clk / u32Freq;
  83. }
  84. if (timer == 0)
  85. {
  86. outpw(REG_ETMR0_CMPR, u32Cmpr);
  87. outpw(REG_ETMR0_PRECNT, u32Prescale);
  88. outpw(REG_ETMR0_CTL, 1 | u32Mode);
  89. }
  90. else if (timer == 1)
  91. {
  92. outpw(REG_ETMR1_CMPR, u32Cmpr);
  93. outpw(REG_ETMR1_PRECNT, u32Prescale);
  94. outpw(REG_ETMR1_CTL, 1 | u32Mode);
  95. }
  96. else if (timer == 2)
  97. {
  98. outpw(REG_ETMR2_CMPR, u32Cmpr);
  99. outpw(REG_ETMR2_PRECNT, u32Prescale);
  100. outpw(REG_ETMR2_CTL, 1 | u32Mode);
  101. }
  102. else
  103. {
  104. outpw(REG_ETMR3_CMPR, u32Cmpr);
  105. outpw(REG_ETMR3_PRECNT, u32Prescale);
  106. outpw(REG_ETMR3_CTL, 1 | u32Mode);
  107. }
  108. return (u32Clk / (u32Cmpr * (u32Prescale + 1)));
  109. }
  110. /**
  111. * @brief This API stops Timer counting and disable the Timer interrupt function
  112. * @param[in] timer ETIMER number. Range from 0 ~ 3
  113. * @return None
  114. */
  115. void ETIMER_Close(UINT timer)
  116. {
  117. if (timer == 0)
  118. {
  119. outpw(REG_ETMR0_CTL, 0);
  120. outpw(REG_ETMR0_IER, 0);
  121. }
  122. else if (timer == 1)
  123. {
  124. outpw(REG_ETMR1_CTL, 0);
  125. outpw(REG_ETMR1_IER, 0);
  126. }
  127. else if (timer == 2)
  128. {
  129. outpw(REG_ETMR2_CTL, 0);
  130. outpw(REG_ETMR2_IER, 0);
  131. }
  132. else
  133. {
  134. outpw(REG_ETMR3_CTL, 0);
  135. outpw(REG_ETMR3_IER, 0);
  136. }
  137. }
  138. /**
  139. * @brief This API is used to create a delay loop for u32usec micro seconds
  140. * @param[in] timer ETIMER number. Range from 0 ~ 3
  141. * @param[in] u32Usec Delay period in micro seconds with 10 usec every step. Valid values are between 10~1000000 (10 micro second ~ 1 second)
  142. * @return None
  143. * @note This API overwrites the register setting of the timer used to count the delay time.
  144. * @note This API use polling mode. So there is no need to enable interrupt for the timer module used to generate delay
  145. */
  146. void ETIMER_Delay(UINT timer, UINT u32Usec)
  147. {
  148. UINT u32Clk = ETIMER_GetModuleClock(timer);
  149. UINT u32Prescale = 0, delay = 300000000 / u32Clk;
  150. float fCmpr;
  151. // Clear current timer configuration
  152. if (timer == 0)
  153. {
  154. outpw(REG_ETMR0_CTL, 0);
  155. }
  156. else if (timer == 1)
  157. {
  158. outpw(REG_ETMR1_CTL, 0);
  159. }
  160. else if (timer == 2)
  161. {
  162. outpw(REG_ETMR2_CTL, 0);
  163. }
  164. else
  165. {
  166. outpw(REG_ETMR3_CTL, 0);
  167. }
  168. if (u32Clk == 10000) // min delay is 100us if timer clock source is LIRC 10k
  169. {
  170. u32Usec = ((u32Usec + 99) / 100) * 100;
  171. }
  172. else // 10 usec every step
  173. {
  174. u32Usec = ((u32Usec + 9) / 10) * 10;
  175. }
  176. if (u32Clk >= 0x4000000)
  177. {
  178. u32Prescale = 7; // real prescaler value is 8
  179. u32Clk >>= 3;
  180. }
  181. else if (u32Clk >= 0x2000000)
  182. {
  183. u32Prescale = 3; // real prescaler value is 4
  184. u32Clk >>= 2;
  185. }
  186. else if (u32Clk >= 0x1000000)
  187. {
  188. u32Prescale = 1; // real prescaler value is 2
  189. u32Clk >>= 1;
  190. }
  191. // u32Usec * u32Clk might overflow if using UINT
  192. fCmpr = ((float)u32Usec * (float)u32Clk) / 1000000.0;
  193. if (timer == 0)
  194. {
  195. outpw(REG_ETMR0_CMPR, (UINT)fCmpr);
  196. outpw(REG_ETMR0_PRECNT, u32Prescale);
  197. outpw(REG_ETMR0_CTL, 1);
  198. }
  199. else if (timer == 1)
  200. {
  201. outpw(REG_ETMR1_CMPR, (UINT)fCmpr);
  202. outpw(REG_ETMR1_PRECNT, u32Prescale);
  203. outpw(REG_ETMR1_CTL, 1);
  204. }
  205. else if (timer == 2)
  206. {
  207. outpw(REG_ETMR2_CMPR, (UINT)fCmpr);
  208. outpw(REG_ETMR2_PRECNT, u32Prescale);
  209. outpw(REG_ETMR2_CTL, 1);
  210. }
  211. else
  212. {
  213. outpw(REG_ETMR3_CMPR, (UINT)fCmpr);
  214. outpw(REG_ETMR3_PRECNT, u32Prescale);
  215. outpw(REG_ETMR3_CTL, 1);
  216. }
  217. // When system clock is faster than timer clock, it is possible timer active bit cannot set in time while we check it.
  218. // And the while loop below return immediately, so put a tiny delay here allowing timer start counting and raise active flag.
  219. for (; delay > 0; delay--)
  220. {
  221. #if defined (__GNUC__) && !(__CC_ARM)
  222. __asm__ __volatile__
  223. (
  224. "nop \n"
  225. );
  226. #else
  227. __asm
  228. {
  229. NOP
  230. }
  231. #endif
  232. }
  233. if (timer == 0)
  234. {
  235. while (inpw(REG_ETMR0_CTL) & 0x80);
  236. }
  237. else if (timer == 1)
  238. {
  239. while (inpw(REG_ETMR1_CTL) & 0x80);
  240. }
  241. else if (timer == 2)
  242. {
  243. while (inpw(REG_ETMR2_CTL) & 0x80);
  244. }
  245. else
  246. {
  247. while (inpw(REG_ETMR3_CTL) & 0x80);
  248. }
  249. }
  250. /**
  251. * @brief This API is used to enable timer capture function with specified mode and capture edge
  252. * @param[in] timer ETIMER number. Range from 0 ~ 3
  253. * @param[in] u32CapMode Timer capture mode. Could be
  254. * - \ref ETIMER_CAPTURE_FREE_COUNTING_MODE
  255. * - \ref ETIMER_CAPTURE_TRIGGER_COUNTING_MODE
  256. * - \ref ETIMER_CAPTURE_COUNTER_RESET_MODE
  257. * @param[in] u32Edge Timer capture edge. Possible values are
  258. * - \ref ETIMER_CAPTURE_FALLING_EDGE
  259. * - \ref ETIMER_CAPTURE_RISING_EDGE
  260. * - \ref ETIMER_CAPTURE_FALLING_THEN_RISING_EDGE
  261. * - \ref ETIMER_CAPTURE_RISING_THEN_FALLING_EDGE
  262. * @return None
  263. * @note Timer frequency should be configured separately by using \ref ETIMER_Open API, or program registers directly
  264. */
  265. void ETIMER_EnableCapture(UINT timer, UINT u32CapMode, UINT u32Edge)
  266. {
  267. if (timer == 0)
  268. {
  269. outpw(REG_ETMR0_CTL, (inpw(REG_ETMR0_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000);
  270. }
  271. else if (timer == 1)
  272. {
  273. outpw(REG_ETMR1_CTL, (inpw(REG_ETMR1_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000);
  274. }
  275. else if (timer == 2)
  276. {
  277. outpw(REG_ETMR2_CTL, (inpw(REG_ETMR2_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000);
  278. }
  279. else
  280. {
  281. outpw(REG_ETMR3_CTL, (inpw(REG_ETMR3_CTL) & ~0x1E0000) | u32CapMode | u32Edge | 0x10000);
  282. }
  283. }
  284. /**
  285. * @brief This API is used to disable the Timer capture function
  286. * @param[in] timer ETIMER number. Range from 0 ~ 3
  287. * @return None
  288. */
  289. void ETIMER_DisableCapture(UINT timer)
  290. {
  291. if (timer == 0)
  292. {
  293. outpw(REG_ETMR0_CTL, inpw(REG_ETMR0_CTL) & ~0x10000);
  294. }
  295. else if (timer == 1)
  296. {
  297. outpw(REG_ETMR1_CTL, inpw(REG_ETMR1_CTL) & ~0x10000);
  298. }
  299. else if (timer == 2)
  300. {
  301. outpw(REG_ETMR2_CTL, inpw(REG_ETMR2_CTL) & ~0x10000);
  302. }
  303. else
  304. {
  305. outpw(REG_ETMR3_CTL, inpw(REG_ETMR3_CTL) & ~0x10000);
  306. }
  307. }
  308. /*@}*/ /* end of group N9H30_ETIMER_EXPORTED_FUNCTIONS */
  309. /*@}*/ /* end of group N9H30_ETIMER_Driver */
  310. /*@}*/ /* end of group N9H30_Device_Driver */
  311. /*** (C) COPYRIGHT 2018 Nuvoton Technology Corp. ***/