fsl_qtmr.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467
  1. /*
  2. * Copyright 2017 NXP
  3. *
  4. * Redistribution and use in source and binary forms, with or without modification,
  5. * are permitted provided that the following conditions are met:
  6. *
  7. * o Redistributions of source code must retain the above copyright notice, this list
  8. * of conditions and the following disclaimer.
  9. *
  10. * o Redistributions in binary form must reproduce the above copyright notice, this
  11. * list of conditions and the following disclaimer in the documentation and/or
  12. * other materials provided with the distribution.
  13. *
  14. * o Neither the name of the copyright holder nor the names of its
  15. * contributors may be used to endorse or promote products derived from this
  16. * software without specific prior written permission.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  19. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  22. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  23. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  24. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  25. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  26. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  27. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  28. */
  29. #include "fsl_qtmr.h"
  30. /*******************************************************************************
  31. * Prototypes
  32. ******************************************************************************/
  33. /*!
  34. * @brief Gets the instance from the base address to be used to gate or ungate the module clock
  35. *
  36. * @param base Quad Timer peripheral base address
  37. *
  38. * @return The Quad Timer instance
  39. */
  40. static uint32_t QTMR_GetInstance(TMR_Type *base);
  41. /*******************************************************************************
  42. * Variables
  43. ******************************************************************************/
  44. /*! @brief Pointers to Quad Timer bases for each instance. */
  45. static TMR_Type *const s_qtmrBases[] = TMR_BASE_PTRS;
  46. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  47. /*! @brief Pointers to Quad Timer clocks for each instance. */
  48. static const clock_ip_name_t s_qtmrClocks[] = TMR_CLOCKS;
  49. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  50. /*******************************************************************************
  51. * Code
  52. ******************************************************************************/
  53. static uint32_t QTMR_GetInstance(TMR_Type *base)
  54. {
  55. uint32_t instance;
  56. /* Find the instance index from base address mappings. */
  57. for (instance = 0; instance < ARRAY_SIZE(s_qtmrBases); instance++)
  58. {
  59. if (s_qtmrBases[instance] == base)
  60. {
  61. break;
  62. }
  63. }
  64. assert(instance < ARRAY_SIZE(s_qtmrBases));
  65. return instance;
  66. }
  67. void QTMR_Init(TMR_Type *base, qtmr_channel_selection_t channel, const qtmr_config_t *config)
  68. {
  69. assert(config);
  70. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  71. /* Enable the module clock */
  72. CLOCK_EnableClock(s_qtmrClocks[QTMR_GetInstance(base)]);
  73. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  74. /* Setup the counter sources */
  75. base->CHANNEL[channel].CTRL = (TMR_CTRL_PCS(config->primarySource) | TMR_CTRL_SCS(config->secondarySource));
  76. /* Setup the master mode operation */
  77. base->CHANNEL[channel].SCTRL = (TMR_SCTRL_EEOF(config->enableExternalForce) | TMR_SCTRL_MSTR(config->enableMasterMode));
  78. /* Setup debug mode */
  79. base->CHANNEL[channel].CSCTRL = TMR_CSCTRL_DBG_EN(config->debugMode);
  80. base->CHANNEL[channel].FILT &= ~( TMR_FILT_FILT_CNT_MASK | TMR_FILT_FILT_PER_MASK);
  81. /* Setup input filter */
  82. base->CHANNEL[channel].FILT = (TMR_FILT_FILT_CNT(config->faultFilterCount) | TMR_FILT_FILT_PER(config->faultFilterPeriod));
  83. }
  84. void QTMR_Deinit(TMR_Type *base, qtmr_channel_selection_t channel)
  85. {
  86. /* Stop the counter */
  87. base->CHANNEL[channel].CTRL &= ~TMR_CTRL_CM_MASK;
  88. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  89. /* Disable the module clock */
  90. CLOCK_DisableClock(s_qtmrClocks[QTMR_GetInstance(base)]);
  91. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  92. }
  93. void QTMR_GetDefaultConfig(qtmr_config_t *config)
  94. {
  95. assert(config);
  96. /* Halt counter during debug mode */
  97. config->debugMode = kQTMR_RunNormalInDebug;
  98. /* Another counter cannot force state of OFLAG signal */
  99. config->enableExternalForce = false;
  100. /* Compare function's output from this counter is not broadcast to other counters */
  101. config->enableMasterMode = false;
  102. /* Fault filter count is set to 0 */
  103. config->faultFilterCount = 0;
  104. /* Fault filter period is set to 0 which disables the fault filter */
  105. config->faultFilterPeriod = 0;
  106. /* Primary count source is IP bus clock divide by 2 */
  107. config->primarySource = kQTMR_ClockDivide_2;
  108. /* Secondary count source is counter 0 input pin */
  109. config->secondarySource = kQTMR_Counter0InputPin;
  110. }
  111. status_t QTMR_SetupPwm(
  112. TMR_Type *base, qtmr_channel_selection_t channel, uint32_t pwmFreqHz, uint8_t dutyCyclePercent, bool outputPolarity, uint32_t srcClock_Hz)
  113. {
  114. uint32_t periodCount, highCount, lowCount, reg;
  115. if (dutyCyclePercent > 100)
  116. {
  117. /* Invalid dutycycle */
  118. return kStatus_Fail;
  119. }
  120. /* Set OFLAG pin for output mode and force out a low on the pin */
  121. base->CHANNEL[channel].SCTRL |= (TMR_SCTRL_FORCE_MASK | TMR_SCTRL_OEN_MASK);
  122. /* Counter values to generate a PWM signal */
  123. periodCount = (srcClock_Hz / pwmFreqHz);
  124. highCount = (periodCount * dutyCyclePercent) / 100;
  125. lowCount = periodCount - highCount;
  126. /* Setup the compare registers for PWM output */
  127. base->CHANNEL[channel].COMP1 = lowCount;
  128. base->CHANNEL[channel].COMP2 = highCount;
  129. /* Setup the pre-load registers for PWM output */
  130. base->CHANNEL[channel].CMPLD1 = lowCount;
  131. base->CHANNEL[channel].CMPLD2 = highCount;
  132. reg = base->CHANNEL[channel].CSCTRL;
  133. /* Setup the compare load control for COMP1 and COMP2.
  134. * Load COMP1 when CSCTRL[TCF2] is asserted, load COMP2 when CSCTRL[TCF1] is asserted
  135. */
  136. reg &= ~(TMR_CSCTRL_CL1_MASK | TMR_CSCTRL_CL2_MASK);
  137. reg |= (TMR_CSCTRL_CL1(kQTMR_LoadOnComp2) | TMR_CSCTRL_CL2(kQTMR_LoadOnComp1));
  138. base->CHANNEL[channel].CSCTRL = reg;
  139. if (outputPolarity)
  140. {
  141. /* Invert the polarity */
  142. base->CHANNEL[channel].SCTRL |= TMR_SCTRL_OPS_MASK;
  143. }
  144. else
  145. {
  146. /* True polarity, no inversion */
  147. base->CHANNEL[channel].SCTRL &= ~TMR_SCTRL_OPS_MASK;
  148. }
  149. reg = base->CHANNEL[channel].CTRL;
  150. reg &= ~(TMR_CTRL_OUTMODE_MASK);
  151. /* Count until compare value is reached and re-initialize the counter, toggle OFLAG output
  152. * using alternating compare register
  153. */
  154. reg |= (TMR_CTRL_LENGTH_MASK | TMR_CTRL_OUTMODE(kQTMR_ToggleOnAltCompareReg));
  155. base->CHANNEL[channel].CTRL = reg;
  156. return kStatus_Success;
  157. }
  158. void QTMR_SetupInputCapture(TMR_Type *base,
  159. qtmr_channel_selection_t channel,
  160. qtmr_input_source_t capturePin,
  161. bool inputPolarity,
  162. bool reloadOnCapture,
  163. qtmr_input_capture_edge_t captureMode)
  164. {
  165. uint16_t reg;
  166. /* Clear the prior value for the input source for capture */
  167. reg = base->CHANNEL[channel].CTRL & (~TMR_CTRL_SCS_MASK);
  168. /* Set the new input source */
  169. reg |= TMR_CTRL_SCS(capturePin);
  170. base->CHANNEL[channel].CTRL = reg;
  171. /* Clear the prior values for input polarity, capture mode. Set the external pin as input */
  172. reg = base->CHANNEL[channel].SCTRL & (~(TMR_SCTRL_IPS_MASK | TMR_SCTRL_CAPTURE_MODE_MASK | TMR_SCTRL_OEN_MASK));
  173. /* Set the new values */
  174. reg |= (TMR_SCTRL_IPS(inputPolarity) | TMR_SCTRL_CAPTURE_MODE(captureMode));
  175. base->CHANNEL[channel].SCTRL = reg;
  176. /* Setup if counter should reload when a capture occurs */
  177. if (reloadOnCapture)
  178. {
  179. base->CHANNEL[channel].CSCTRL |= TMR_CSCTRL_ROC_MASK;
  180. }
  181. else
  182. {
  183. base->CHANNEL[channel].CSCTRL &= ~TMR_CSCTRL_ROC_MASK;
  184. }
  185. }
  186. void QTMR_EnableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
  187. {
  188. uint16_t reg;
  189. reg = base->CHANNEL[channel].SCTRL;
  190. /* Compare interrupt */
  191. if (mask & kQTMR_CompareInterruptEnable)
  192. {
  193. reg |= TMR_SCTRL_TCFIE_MASK;
  194. }
  195. /* Overflow interrupt */
  196. if (mask & kQTMR_OverflowInterruptEnable)
  197. {
  198. reg |= TMR_SCTRL_TOFIE_MASK;
  199. }
  200. /* Input edge interrupt */
  201. if (mask & kQTMR_EdgeInterruptEnable)
  202. {
  203. /* Restriction: Do not set both SCTRL[IEFIE] and DMA[IEFDE] */
  204. base->CHANNEL[channel].DMA &= ~TMR_DMA_IEFDE_MASK;
  205. reg |= TMR_SCTRL_IEFIE_MASK;
  206. }
  207. base->CHANNEL[channel].SCTRL = reg;
  208. reg = base->CHANNEL[channel].CSCTRL;
  209. /* Compare 1 interrupt */
  210. if (mask & kQTMR_Compare1InterruptEnable)
  211. {
  212. reg |= TMR_CSCTRL_TCF1EN_MASK;
  213. }
  214. /* Compare 2 interrupt */
  215. if (mask & kQTMR_Compare2InterruptEnable)
  216. {
  217. reg |= TMR_CSCTRL_TCF2EN_MASK;
  218. }
  219. base->CHANNEL[channel].CSCTRL = reg;
  220. }
  221. void QTMR_DisableInterrupts(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
  222. {
  223. uint16_t reg;
  224. reg = base->CHANNEL[channel].SCTRL;
  225. /* Compare interrupt */
  226. if (mask & kQTMR_CompareInterruptEnable)
  227. {
  228. reg &= ~TMR_SCTRL_TCFIE_MASK;
  229. }
  230. /* Overflow interrupt */
  231. if (mask & kQTMR_OverflowInterruptEnable)
  232. {
  233. reg &= ~TMR_SCTRL_TOFIE_MASK;
  234. }
  235. /* Input edge interrupt */
  236. if (mask & kQTMR_EdgeInterruptEnable)
  237. {
  238. reg &= ~TMR_SCTRL_IEFIE_MASK;
  239. }
  240. base->CHANNEL[channel].SCTRL = reg;
  241. reg = base->CHANNEL[channel].CSCTRL;
  242. /* Compare 1 interrupt */
  243. if (mask & kQTMR_Compare1InterruptEnable)
  244. {
  245. reg &= ~TMR_CSCTRL_TCF1EN_MASK;
  246. }
  247. /* Compare 2 interrupt */
  248. if (mask & kQTMR_Compare2InterruptEnable)
  249. {
  250. reg &= ~TMR_CSCTRL_TCF2EN_MASK;
  251. }
  252. base->CHANNEL[channel].CSCTRL = reg;
  253. }
  254. uint32_t QTMR_GetEnabledInterrupts(TMR_Type *base, qtmr_channel_selection_t channel)
  255. {
  256. uint32_t enabledInterrupts = 0;
  257. uint16_t reg;
  258. reg = base->CHANNEL[channel].SCTRL;
  259. /* Compare interrupt */
  260. if (reg & TMR_SCTRL_TCFIE_MASK)
  261. {
  262. enabledInterrupts |= kQTMR_CompareFlag;
  263. }
  264. /* Overflow interrupt */
  265. if (reg & TMR_SCTRL_TOFIE_MASK)
  266. {
  267. enabledInterrupts |= kQTMR_OverflowInterruptEnable;
  268. }
  269. /* Input edge interrupt */
  270. if (reg & TMR_SCTRL_IEFIE_MASK)
  271. {
  272. enabledInterrupts |= kQTMR_EdgeInterruptEnable;
  273. }
  274. reg = base->CHANNEL[channel].CSCTRL;
  275. /* Compare 1 interrupt */
  276. if (reg & TMR_CSCTRL_TCF1EN_MASK)
  277. {
  278. enabledInterrupts |= kQTMR_Compare1InterruptEnable;
  279. }
  280. /* Compare 2 interrupt */
  281. if (reg & TMR_CSCTRL_TCF2EN_MASK)
  282. {
  283. enabledInterrupts |= kQTMR_Compare2InterruptEnable;
  284. }
  285. return enabledInterrupts;
  286. }
  287. uint32_t QTMR_GetStatus(TMR_Type *base, qtmr_channel_selection_t channel)
  288. {
  289. uint32_t statusFlags = 0;
  290. uint16_t reg;
  291. reg = base->CHANNEL[channel].SCTRL;
  292. /* Timer compare flag */
  293. if (reg & TMR_SCTRL_TCF_MASK)
  294. {
  295. statusFlags |= kQTMR_CompareFlag;
  296. }
  297. /* Timer overflow flag */
  298. if (reg & TMR_SCTRL_TOF_MASK)
  299. {
  300. statusFlags |= kQTMR_OverflowFlag;
  301. }
  302. /* Input edge flag */
  303. if (reg & TMR_SCTRL_IEF_MASK)
  304. {
  305. statusFlags |= kQTMR_EdgeFlag;
  306. }
  307. reg = base->CHANNEL[channel].CSCTRL;
  308. /* Compare 1 flag */
  309. if (reg & TMR_CSCTRL_TCF1_MASK)
  310. {
  311. statusFlags |= kQTMR_Compare1Flag;
  312. }
  313. /* Compare 2 flag */
  314. if (reg & TMR_CSCTRL_TCF2_MASK)
  315. {
  316. statusFlags |= kQTMR_Compare2Flag;
  317. }
  318. return statusFlags;
  319. }
  320. void QTMR_ClearStatusFlags(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
  321. {
  322. uint16_t reg;
  323. reg = base->CHANNEL[channel].SCTRL;
  324. /* Timer compare flag */
  325. if (mask & kQTMR_CompareFlag)
  326. {
  327. reg &= ~TMR_SCTRL_TCF_MASK;
  328. }
  329. /* Timer overflow flag */
  330. if (mask & kQTMR_OverflowFlag)
  331. {
  332. reg &= ~TMR_SCTRL_TOF_MASK;
  333. }
  334. /* Input edge flag */
  335. if (mask & kQTMR_EdgeFlag)
  336. {
  337. reg &= ~TMR_SCTRL_IEF_MASK;
  338. }
  339. base->CHANNEL[channel].SCTRL = reg;
  340. reg = base->CHANNEL[channel].CSCTRL;
  341. /* Compare 1 flag */
  342. if (mask & kQTMR_Compare1Flag)
  343. {
  344. reg &= ~TMR_CSCTRL_TCF1_MASK;
  345. }
  346. /* Compare 2 flag */
  347. if (mask & kQTMR_Compare2Flag)
  348. {
  349. reg &= ~TMR_CSCTRL_TCF2_MASK;
  350. }
  351. base->CHANNEL[channel].CSCTRL = reg;
  352. }
  353. void QTMR_SetTimerPeriod(TMR_Type *base, qtmr_channel_selection_t channel, uint16_t ticks)
  354. {
  355. /* Set the length bit to reinitialize the counters on a match */
  356. base->CHANNEL[channel].CTRL |= TMR_CTRL_LENGTH_MASK;
  357. if (base->CHANNEL[channel].CTRL & TMR_CTRL_DIR_MASK)
  358. {
  359. /* Counting down */
  360. base->CHANNEL[channel].COMP2 = ticks;
  361. }
  362. else
  363. {
  364. /* Counting up */
  365. base->CHANNEL[channel].COMP1 = ticks;
  366. }
  367. }
  368. void QTMR_EnableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
  369. {
  370. uint16_t reg;
  371. reg = base->CHANNEL[channel].DMA;
  372. /* Input Edge Flag DMA Enable */
  373. if (mask & kQTMR_InputEdgeFlagDmaEnable)
  374. {
  375. /* Restriction: Do not set both DMA[IEFDE] and SCTRL[IEFIE] */
  376. base->CHANNEL[channel].SCTRL &= ~TMR_SCTRL_IEFIE_MASK;
  377. reg |= TMR_DMA_IEFDE_MASK;
  378. }
  379. /* Comparator Preload Register 1 DMA Enable */
  380. if (mask & kQTMR_ComparatorPreload1DmaEnable)
  381. {
  382. reg |= TMR_DMA_CMPLD1DE_MASK;
  383. }
  384. /* Comparator Preload Register 2 DMA Enable */
  385. if (mask & kQTMR_ComparatorPreload2DmaEnable)
  386. {
  387. reg |= TMR_DMA_CMPLD2DE_MASK;
  388. }
  389. base->CHANNEL[channel].DMA = reg;
  390. }
  391. void QTMR_DisableDma(TMR_Type *base, qtmr_channel_selection_t channel, uint32_t mask)
  392. {
  393. uint16_t reg;
  394. reg = base->CHANNEL[channel].DMA;
  395. /* Input Edge Flag DMA Enable */
  396. if (mask & kQTMR_InputEdgeFlagDmaEnable)
  397. {
  398. reg &= ~TMR_DMA_IEFDE_MASK;
  399. }
  400. /* Comparator Preload Register 1 DMA Enable */
  401. if (mask & kQTMR_ComparatorPreload1DmaEnable)
  402. {
  403. reg &= ~TMR_DMA_CMPLD1DE_MASK;
  404. }
  405. /* Comparator Preload Register 2 DMA Enable */
  406. if (mask & kQTMR_ComparatorPreload2DmaEnable)
  407. {
  408. reg &= ~TMR_DMA_CMPLD2DE_MASK;
  409. }
  410. base->CHANNEL[channel].DMA = reg;
  411. }