fsl_sctimer.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559
  1. /*
  2. * The Clear BSD License
  3. * Copyright (c) 2016, Freescale Semiconductor, Inc.
  4. * Copyright 2016-2017 NXP
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without modification,
  8. * are permitted (subject to the limitations in the disclaimer below) provided
  9. * that the following conditions are met:
  10. *
  11. * o Redistributions of source code must retain the above copyright notice, this list
  12. * of conditions and the following disclaimer.
  13. *
  14. * o Redistributions in binary form must reproduce the above copyright notice, this
  15. * list of conditions and the following disclaimer in the documentation and/or
  16. * other materials provided with the distribution.
  17. *
  18. * o Neither the name of the copyright holder nor the names of its
  19. * contributors may be used to endorse or promote products derived from this
  20. * software without specific prior written permission.
  21. *
  22. * NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY THIS LICENSE.
  23. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
  24. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  25. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  26. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
  27. * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  28. * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  29. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
  30. * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  31. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  32. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  33. */
  34. #include "fsl_sctimer.h"
  35. /*******************************************************************************
  36. * Definitions
  37. ******************************************************************************/
  38. /* Component ID definition, used by tools. */
  39. #ifndef FSL_COMPONENT_ID
  40. #define FSL_COMPONENT_ID "platform.drivers.sctimer"
  41. #endif
  42. /*! @brief Typedef for interrupt handler. */
  43. typedef void (*sctimer_isr_t)(SCT_Type *base);
  44. /*******************************************************************************
  45. * Prototypes
  46. ******************************************************************************/
  47. /*!
  48. * @brief Gets the instance from the base address
  49. *
  50. * @param base SCTimer peripheral base address
  51. *
  52. * @return The SCTimer instance
  53. */
  54. static uint32_t SCTIMER_GetInstance(SCT_Type *base);
  55. /*******************************************************************************
  56. * Variables
  57. ******************************************************************************/
  58. /*! @brief Pointers to SCT bases for each instance. */
  59. static SCT_Type *const s_sctBases[] = SCT_BASE_PTRS;
  60. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  61. /*! @brief Pointers to SCT clocks for each instance. */
  62. static const clock_ip_name_t s_sctClocks[] = SCT_CLOCKS;
  63. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  64. #if defined(FSL_FEATURE_SCT_WRITE_ZERO_ASSERT_RESET) && FSL_FEATURE_SCT_WRITE_ZERO_ASSERT_RESET
  65. /*! @brief Pointers to SCT resets for each instance, writing a zero asserts the reset */
  66. static const reset_ip_name_t s_sctResets[] = SCT_RSTS_N;
  67. #else
  68. /*! @brief Pointers to SCT resets for each instance, writing a one asserts the reset */
  69. static const reset_ip_name_t s_sctResets[] = SCT_RSTS;
  70. #endif
  71. /*!< @brief SCTimer event Callback function. */
  72. static sctimer_event_callback_t s_eventCallback[FSL_FEATURE_SCT_NUMBER_OF_EVENTS];
  73. /*!< @brief Keep track of SCTimer event number */
  74. static uint32_t s_currentEvent;
  75. /*!< @brief Keep track of SCTimer state number */
  76. static uint32_t s_currentState;
  77. /*!< @brief Keep track of SCTimer match/capture register number */
  78. static uint32_t s_currentMatch;
  79. /*! @brief Pointer to SCTimer IRQ handler */
  80. static sctimer_isr_t s_sctimerIsr;
  81. /*******************************************************************************
  82. * Code
  83. ******************************************************************************/
  84. static uint32_t SCTIMER_GetInstance(SCT_Type *base)
  85. {
  86. uint32_t instance;
  87. uint32_t sctArrayCount = (sizeof(s_sctBases) / sizeof(s_sctBases[0]));
  88. /* Find the instance index from base address mappings. */
  89. for (instance = 0; instance < sctArrayCount; instance++)
  90. {
  91. if (s_sctBases[instance] == base)
  92. {
  93. break;
  94. }
  95. }
  96. assert(instance < sctArrayCount);
  97. return instance;
  98. }
  99. status_t SCTIMER_Init(SCT_Type *base, const sctimer_config_t *config)
  100. {
  101. assert(config);
  102. uint32_t i;
  103. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  104. /* Enable the SCTimer clock*/
  105. CLOCK_EnableClock(s_sctClocks[SCTIMER_GetInstance(base)]);
  106. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  107. /* Reset the module */
  108. RESET_PeripheralReset(s_sctResets[SCTIMER_GetInstance(base)]);
  109. /* Setup the counter operation */
  110. base->CONFIG = SCT_CONFIG_CKSEL(config->clockSelect) | SCT_CONFIG_CLKMODE(config->clockMode) |
  111. SCT_CONFIG_UNIFY(config->enableCounterUnify);
  112. /* Write to the control register, clear the counter and keep the counters halted */
  113. base->CTRL = SCT_CTRL_BIDIR_L(config->enableBidirection_l) | SCT_CTRL_PRE_L(config->prescale_l) |
  114. SCT_CTRL_CLRCTR_L_MASK | SCT_CTRL_HALT_L_MASK;
  115. if (!(config->enableCounterUnify))
  116. {
  117. base->CTRL |= SCT_CTRL_BIDIR_H(config->enableBidirection_h) | SCT_CTRL_PRE_H(config->prescale_h) |
  118. SCT_CTRL_CLRCTR_H_MASK | SCT_CTRL_HALT_H_MASK;
  119. }
  120. /* Initial state of channel output */
  121. base->OUTPUT = config->outInitState;
  122. /* Clear the global variables */
  123. s_currentEvent = 0;
  124. s_currentState = 0;
  125. s_currentMatch = 0;
  126. /* Clear the callback array */
  127. for (i = 0; i < FSL_FEATURE_SCT_NUMBER_OF_EVENTS; i++)
  128. {
  129. s_eventCallback[i] = NULL;
  130. }
  131. /* Save interrupt handler */
  132. s_sctimerIsr = SCTIMER_EventHandleIRQ;
  133. return kStatus_Success;
  134. }
  135. void SCTIMER_Deinit(SCT_Type *base)
  136. {
  137. /* Halt the counters */
  138. base->CTRL |= (SCT_CTRL_HALT_L_MASK | SCT_CTRL_HALT_H_MASK);
  139. #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
  140. /* Disable the SCTimer clock*/
  141. CLOCK_DisableClock(s_sctClocks[SCTIMER_GetInstance(base)]);
  142. #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
  143. }
  144. void SCTIMER_GetDefaultConfig(sctimer_config_t *config)
  145. {
  146. assert(config);
  147. /* SCT operates as a unified 32-bit counter */
  148. config->enableCounterUnify = true;
  149. /* System clock clocks the entire SCT module */
  150. config->clockMode = kSCTIMER_System_ClockMode;
  151. /* This is used only by certain clock modes */
  152. config->clockSelect = kSCTIMER_Clock_On_Rise_Input_0;
  153. /* Up count mode only for the unified counter */
  154. config->enableBidirection_l = false;
  155. /* Up count mode only for Counte_H */
  156. config->enableBidirection_h = false;
  157. /* Prescale factor of 1 */
  158. config->prescale_l = 0;
  159. /* Prescale factor of 1 for Counter_H*/
  160. config->prescale_h = 0;
  161. /* Clear outputs */
  162. config->outInitState = 0;
  163. }
  164. status_t SCTIMER_SetupPwm(SCT_Type *base,
  165. const sctimer_pwm_signal_param_t *pwmParams,
  166. sctimer_pwm_mode_t mode,
  167. uint32_t pwmFreq_Hz,
  168. uint32_t srcClock_Hz,
  169. uint32_t *event)
  170. {
  171. assert(pwmParams);
  172. assert(srcClock_Hz);
  173. assert(pwmFreq_Hz);
  174. assert(pwmParams->output < FSL_FEATURE_SCT_NUMBER_OF_OUTPUTS);
  175. uint32_t period, pulsePeriod = 0;
  176. uint32_t sctClock = srcClock_Hz / (((base->CTRL & SCT_CTRL_PRE_L_MASK) >> SCT_CTRL_PRE_L_SHIFT) + 1);
  177. uint32_t periodEvent = 0, pulseEvent = 0;
  178. uint32_t reg;
  179. /* This function will create 2 events, return an error if we do not have enough events available */
  180. if ((s_currentEvent + 2) > FSL_FEATURE_SCT_NUMBER_OF_EVENTS)
  181. {
  182. return kStatus_Fail;
  183. }
  184. if (pwmParams->dutyCyclePercent == 0)
  185. {
  186. return kStatus_Fail;
  187. }
  188. /* Set unify bit to operate in 32-bit counter mode */
  189. base->CONFIG |= SCT_CONFIG_UNIFY_MASK;
  190. /* Use bi-directional mode for center-aligned PWM */
  191. if (mode == kSCTIMER_CenterAlignedPwm)
  192. {
  193. base->CTRL |= SCT_CTRL_BIDIR_L_MASK;
  194. }
  195. /* Calculate PWM period match value */
  196. if (mode == kSCTIMER_EdgeAlignedPwm)
  197. {
  198. period = (sctClock / pwmFreq_Hz) - 1;
  199. }
  200. else
  201. {
  202. period = sctClock / (pwmFreq_Hz * 2);
  203. }
  204. /* Calculate pulse width match value */
  205. pulsePeriod = (period * pwmParams->dutyCyclePercent) / 100;
  206. /* For 100% dutycyle, make pulse period greater than period so the event will never occur */
  207. if (pwmParams->dutyCyclePercent >= 100)
  208. {
  209. pulsePeriod = period + 2;
  210. }
  211. /* Schedule an event when we reach the PWM period */
  212. SCTIMER_CreateAndScheduleEvent(base, kSCTIMER_MatchEventOnly, period, 0, kSCTIMER_Counter_L, &periodEvent);
  213. /* Schedule an event when we reach the pulse width */
  214. SCTIMER_CreateAndScheduleEvent(base, kSCTIMER_MatchEventOnly, pulsePeriod, 0, kSCTIMER_Counter_L, &pulseEvent);
  215. /* Reset the counter when we reach the PWM period */
  216. SCTIMER_SetupCounterLimitAction(base, kSCTIMER_Counter_L, periodEvent);
  217. /* Return the period event to the user */
  218. *event = periodEvent;
  219. /* For high-true level */
  220. if (pwmParams->level == kSCTIMER_HighTrue)
  221. {
  222. /* Set the initial output level to low which is the inactive state */
  223. base->OUTPUT &= ~(1U << pwmParams->output);
  224. if (mode == kSCTIMER_EdgeAlignedPwm)
  225. {
  226. /* Set the output when we reach the PWM period */
  227. SCTIMER_SetupOutputSetAction(base, pwmParams->output, periodEvent);
  228. /* Clear the output when we reach the PWM pulse value */
  229. SCTIMER_SetupOutputClearAction(base, pwmParams->output, pulseEvent);
  230. }
  231. else
  232. {
  233. /* Clear the output when we reach the PWM pulse event */
  234. SCTIMER_SetupOutputClearAction(base, pwmParams->output, pulseEvent);
  235. /* Reverse output when down counting */
  236. reg = base->OUTPUTDIRCTRL;
  237. reg &= ~(SCT_OUTPUTDIRCTRL_SETCLR0_MASK << (2 * pwmParams->output));
  238. reg |= (1U << (2 * pwmParams->output));
  239. base->OUTPUTDIRCTRL = reg;
  240. }
  241. }
  242. /* For low-true level */
  243. else
  244. {
  245. /* Set the initial output level to high which is the inactive state */
  246. base->OUTPUT |= (1U << pwmParams->output);
  247. if (mode == kSCTIMER_EdgeAlignedPwm)
  248. {
  249. /* Clear the output when we reach the PWM period */
  250. SCTIMER_SetupOutputClearAction(base, pwmParams->output, periodEvent);
  251. /* Set the output when we reach the PWM pulse value */
  252. SCTIMER_SetupOutputSetAction(base, pwmParams->output, pulseEvent);
  253. }
  254. else
  255. {
  256. /* Set the output when we reach the PWM pulse event */
  257. SCTIMER_SetupOutputSetAction(base, pwmParams->output, pulseEvent);
  258. /* Reverse output when down counting */
  259. reg = base->OUTPUTDIRCTRL;
  260. reg &= ~(SCT_OUTPUTDIRCTRL_SETCLR0_MASK << (2 * pwmParams->output));
  261. reg |= (1U << (2 * pwmParams->output));
  262. base->OUTPUTDIRCTRL = reg;
  263. }
  264. }
  265. return kStatus_Success;
  266. }
  267. void SCTIMER_UpdatePwmDutycycle(SCT_Type *base, sctimer_out_t output, uint8_t dutyCyclePercent, uint32_t event)
  268. {
  269. assert(dutyCyclePercent > 0);
  270. assert(output < FSL_FEATURE_SCT_NUMBER_OF_OUTPUTS);
  271. uint32_t periodMatchReg, pulseMatchReg;
  272. uint32_t pulsePeriod = 0, period;
  273. /* Retrieve the match register number for the PWM period */
  274. periodMatchReg = base->EVENT[event].CTRL & SCT_EVENT_CTRL_MATCHSEL_MASK;
  275. /* Retrieve the match register number for the PWM pulse period */
  276. pulseMatchReg = base->EVENT[event + 1].CTRL & SCT_EVENT_CTRL_MATCHSEL_MASK;
  277. period = base->SCTMATCH[periodMatchReg];
  278. /* Calculate pulse width match value */
  279. pulsePeriod = (period * dutyCyclePercent) / 100;
  280. /* For 100% dutycyle, make pulse period greater than period so the event will never occur */
  281. if (dutyCyclePercent >= 100)
  282. {
  283. pulsePeriod = period + 2;
  284. }
  285. /* Stop the counter before updating match register */
  286. SCTIMER_StopTimer(base, kSCTIMER_Counter_L);
  287. /* Update dutycycle */
  288. base->SCTMATCH[pulseMatchReg] = SCT_SCTMATCH_MATCHn_L(pulsePeriod);
  289. base->SCTMATCHREL[pulseMatchReg] = SCT_SCTMATCHREL_RELOADn_L(pulsePeriod);
  290. /* Restart the counter */
  291. SCTIMER_StartTimer(base, kSCTIMER_Counter_L);
  292. }
  293. status_t SCTIMER_CreateAndScheduleEvent(SCT_Type *base,
  294. sctimer_event_t howToMonitor,
  295. uint32_t matchValue,
  296. uint32_t whichIO,
  297. sctimer_counter_t whichCounter,
  298. uint32_t *event)
  299. {
  300. uint32_t combMode = (((uint32_t)howToMonitor & SCT_EVENT_CTRL_COMBMODE_MASK) >> SCT_EVENT_CTRL_COMBMODE_SHIFT);
  301. uint32_t currentCtrlVal = howToMonitor;
  302. /* Return an error if we have hit the limit in terms of number of events created */
  303. if (s_currentEvent >= FSL_FEATURE_SCT_NUMBER_OF_EVENTS)
  304. {
  305. return kStatus_Fail;
  306. }
  307. /* IO only mode */
  308. if (combMode == 0x2U)
  309. {
  310. base->EVENT[s_currentEvent].CTRL = currentCtrlVal | SCT_EVENT_CTRL_IOSEL(whichIO);
  311. }
  312. /* Match mode only */
  313. else if (combMode == 0x1U)
  314. {
  315. /* Return an error if we have hit the limit in terms of number of number of match registers */
  316. if (s_currentMatch >= FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE)
  317. {
  318. return kStatus_Fail;
  319. }
  320. currentCtrlVal |= SCT_EVENT_CTRL_MATCHSEL(s_currentMatch);
  321. /* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
  322. if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
  323. {
  324. base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_L(matchValue);
  325. base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_L(matchValue);
  326. }
  327. else
  328. {
  329. /* Select the counter, no need for this if operating in 32-bit mode */
  330. currentCtrlVal |= SCT_EVENT_CTRL_HEVENT(whichCounter);
  331. base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_H(matchValue);
  332. base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_H(matchValue);
  333. }
  334. base->EVENT[s_currentEvent].CTRL = currentCtrlVal;
  335. /* Increment the match register number */
  336. s_currentMatch++;
  337. }
  338. /* Use both Match & IO */
  339. else
  340. {
  341. /* Return an error if we have hit the limit in terms of number of number of match registers */
  342. if (s_currentMatch >= FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE)
  343. {
  344. return kStatus_Fail;
  345. }
  346. currentCtrlVal |= SCT_EVENT_CTRL_MATCHSEL(s_currentMatch) | SCT_EVENT_CTRL_IOSEL(whichIO);
  347. /* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
  348. if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
  349. {
  350. base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_L(matchValue);
  351. base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_L(matchValue);
  352. }
  353. else
  354. {
  355. /* Select the counter, no need for this if operating in 32-bit mode */
  356. currentCtrlVal |= SCT_EVENT_CTRL_HEVENT(whichCounter);
  357. base->SCTMATCH[s_currentMatch] = SCT_SCTMATCH_MATCHn_H(matchValue);
  358. base->SCTMATCHREL[s_currentMatch] = SCT_SCTMATCHREL_RELOADn_H(matchValue);
  359. }
  360. base->EVENT[s_currentEvent].CTRL = currentCtrlVal;
  361. /* Increment the match register number */
  362. s_currentMatch++;
  363. }
  364. /* Enable the event in the current state */
  365. base->EVENT[s_currentEvent].STATE = (1U << s_currentState);
  366. /* Return the event number */
  367. *event = s_currentEvent;
  368. /* Increment the event number */
  369. s_currentEvent++;
  370. return kStatus_Success;
  371. }
  372. void SCTIMER_ScheduleEvent(SCT_Type *base, uint32_t event)
  373. {
  374. /* Enable event in the current state */
  375. base->EVENT[event].STATE |= (1U << s_currentState);
  376. }
  377. status_t SCTIMER_IncreaseState(SCT_Type *base)
  378. {
  379. /* Return an error if we have hit the limit in terms of states used */
  380. if (s_currentState >= FSL_FEATURE_SCT_NUMBER_OF_STATES)
  381. {
  382. return kStatus_Fail;
  383. }
  384. s_currentState++;
  385. return kStatus_Success;
  386. }
  387. uint32_t SCTIMER_GetCurrentState(SCT_Type *base)
  388. {
  389. return s_currentState;
  390. }
  391. void SCTIMER_SetupOutputToggleAction(SCT_Type *base, uint32_t whichIO, uint32_t event)
  392. {
  393. assert(whichIO < FSL_FEATURE_SCT_NUMBER_OF_OUTPUTS);
  394. uint32_t reg;
  395. /* Set the same event to set and clear the output */
  396. base->OUT[whichIO].CLR |= (1U << event);
  397. base->OUT[whichIO].SET |= (1U << event);
  398. /* Set the conflict resolution to toggle output */
  399. reg = base->RES;
  400. reg &= ~(SCT_RES_O0RES_MASK << (2 * whichIO));
  401. reg |= (uint32_t)(kSCTIMER_ResolveToggle << (2 * whichIO));
  402. base->RES = reg;
  403. }
  404. status_t SCTIMER_SetupCaptureAction(SCT_Type *base,
  405. sctimer_counter_t whichCounter,
  406. uint32_t *captureRegister,
  407. uint32_t event)
  408. {
  409. /* Return an error if we have hit the limit in terms of number of capture/match registers used */
  410. if (s_currentMatch >= FSL_FEATURE_SCT_NUMBER_OF_MATCH_CAPTURE)
  411. {
  412. return kStatus_Fail;
  413. }
  414. /* Use Counter_L bits if counter is operating in 32-bit mode or user wants to setup the L counter */
  415. if ((base->CONFIG & SCT_CONFIG_UNIFY_MASK) || (whichCounter == kSCTIMER_Counter_L))
  416. {
  417. /* Set the bit to enable event */
  418. base->SCTCAPCTRL[s_currentMatch] |= SCT_SCTCAPCTRL_CAPCONn_L(1 << event);
  419. /* Set this resource to be a capture rather than match */
  420. base->REGMODE |= SCT_REGMODE_REGMOD_L(1 << s_currentMatch);
  421. }
  422. else
  423. {
  424. /* Set bit to enable event */
  425. base->SCTCAPCTRL[s_currentMatch] |= SCT_SCTCAPCTRL_CAPCONn_H(1 << event);
  426. /* Set this resource to be a capture rather than match */
  427. base->REGMODE |= SCT_REGMODE_REGMOD_H(1 << s_currentMatch);
  428. }
  429. /* Return the match register number */
  430. *captureRegister = s_currentMatch;
  431. /* Increase the match register number */
  432. s_currentMatch++;
  433. return kStatus_Success;
  434. }
  435. void SCTIMER_SetCallback(SCT_Type *base, sctimer_event_callback_t callback, uint32_t event)
  436. {
  437. s_eventCallback[event] = callback;
  438. }
  439. void SCTIMER_EventHandleIRQ(SCT_Type *base)
  440. {
  441. uint32_t eventFlag = SCT0->EVFLAG;
  442. /* Only clear the flags whose interrupt field is enabled */
  443. uint32_t clearFlag = (eventFlag & SCT0->EVEN);
  444. uint32_t mask = eventFlag;
  445. int i = 0;
  446. /* Invoke the callback for certain events */
  447. for (i = 0; (i < FSL_FEATURE_SCT_NUMBER_OF_EVENTS) && (mask != 0); i++)
  448. {
  449. if (mask & 0x1)
  450. {
  451. if (s_eventCallback[i] != NULL)
  452. {
  453. s_eventCallback[i]();
  454. }
  455. }
  456. mask >>= 1;
  457. }
  458. /* Clear event interrupt flag */
  459. SCT0->EVFLAG = clearFlag;
  460. }
  461. void SCT0_IRQHandler(void)
  462. {
  463. s_sctimerIsr(SCT0);
  464. /* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F Store immediate overlapping
  465. exception return operation might vector to incorrect interrupt */
  466. #if defined __CORTEX_M && (__CORTEX_M == 4U)
  467. __DSB();
  468. #endif
  469. }