fsl_qtmr.c 15 KB

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