1 /*
2 * Copyright 2023 NXP
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #include "fsl_waketimer.h"
9
10 /*******************************************************************************
11 * Definitions
12 ******************************************************************************/
13
14 /* Component ID definition, used by tools. */
15 #ifndef FSL_COMPONENT_ID
16 #define FSL_COMPONENT_ID "platform.drivers.waketimer"
17 #endif
18
19 /*******************************************************************************
20 * Prototypes
21 ******************************************************************************/
22 /*!
23 * brief Gets the instance from the base address
24 *
25 * param base WAKETIMER peripheral base address
26 *
27 * return The WAKETIMER instance
28 */
29 static uint32_t WAKETIMER_GetInstance(WAKETIMER_Type *base);
30
31 /*!
32 * brief WAKETIMER generic IRQ handle function.
33 *
34 * param index WAKETIMER peripheral instance index.
35 */
36 static void WAKETIMER_GenericIRQHandler(WAKETIMER_Type *base, waketimer_callback_t callback);
37
38 /*******************************************************************************
39 * Variables
40 ******************************************************************************/
41 /* Array of WAKETIMER peripheral base address. */
42 static WAKETIMER_Type *const s_waketimerBases[] = WAKETIMER_BASE_PTRS;
43 /* Array of WAKETIMER ISR. */
44 static waketimer_callback_t s_waketimerCallback[sizeof(s_waketimerBases) / sizeof(s_waketimerBases[0])];
45 /* Array of WAKETIMER IRQ number. */
46 static const IRQn_Type s_waketimerIRQ[] = WAKETIMER_IRQS;
47
48 /*******************************************************************************
49 * Code
50 ******************************************************************************/
51
52 /* brief Function for getting the instance number of Waketimer. */
WAKETIMER_GetInstance(WAKETIMER_Type * base)53 static uint32_t WAKETIMER_GetInstance(WAKETIMER_Type *base)
54 {
55 uint32_t instance;
56
57 /* Find the instance index from base address mappings. */
58 for (instance = 0; instance < ARRAY_SIZE(s_waketimerBases); instance++)
59 {
60 if (s_waketimerBases[instance] == base)
61 {
62 break;
63 }
64 }
65
66 assert(instance < ARRAY_SIZE(s_waketimerBases));
67
68 return instance;
69 }
70
71 /*!
72 * brief Initializes an WAKETIMER.
73 * param base WAKETIMER peripheral base address.
74 */
WAKETIMER_Init(WAKETIMER_Type * base,const waketimer_config_t * config)75 void WAKETIMER_Init(WAKETIMER_Type *base, const waketimer_config_t *config)
76 {
77 assert(NULL != base);
78
79 uint32_t index = WAKETIMER_GetInstance(base);
80
81 /* Halt timer */
82 base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_CLR_WAKE_TIMER_MASK;
83
84 /* Set OSC divide */
85 if (config->enableOSCDivide)
86 {
87 base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_OSC_DIV_ENA_MASK;
88 }
89 else
90 {
91 base->WAKE_TIMER_CTRL &= ~WAKETIMER_WAKE_TIMER_CTRL_OSC_DIV_ENA_MASK;
92 }
93
94 /* Set callback */
95 s_waketimerCallback[index] = config->callback;
96
97 /* Set interrupt */
98 if (config->enableInterrupt)
99 {
100 base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
101 (void)EnableIRQ(s_waketimerIRQ[index]);
102 }
103 else
104 {
105 base->WAKE_TIMER_CTRL &= ~WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
106 (void)DisableIRQ(s_waketimerIRQ[index]);
107 }
108 }
109
110 /*!
111 * brief Deinitializes a WAKETIMER instance.
112 *
113 * This function deinitializes the WAKETIMER.
114 *
115 * param base WAKETIMER peripheral base address.
116 */
WAKETIMER_Deinit(WAKETIMER_Type * base)117 void WAKETIMER_Deinit(WAKETIMER_Type *base)
118 {
119 assert(NULL != base);
120
121 uint32_t index = WAKETIMER_GetInstance(base);
122
123 /* Disable IRQ at NVIC Level */
124 (void)DisableIRQ(s_waketimerIRQ[index]);
125 }
126
127 /*!
128 * brief Fills in the WAKETIMER configuration structure with the default settings.
129 *
130 * The default values are:
131 * code
132 * config->enableInterrupt = true;
133 * config->enableOSCDivide = true;
134 * config->callback = NULL;
135 * endcode
136 * param config Pointer to the user configuration structure.
137 */
WAKETIMER_GetDefaultConfig(waketimer_config_t * config)138 void WAKETIMER_GetDefaultConfig(waketimer_config_t *config)
139 {
140 config->enableInterrupt = true;
141 config->enableOSCDivide = true;
142 config->callback = NULL;
143 }
144
145 /*!
146 * brief Enables the selected WAKETIMER interrupts.
147 *
148 * param base WAKETIMER peripheral base address
149 * param mask Mask value for interrupt events. See to #_waketimer_interrupt_enable
150 */
WAKETIMER_EnableInterrupts(WAKETIMER_Type * base,uint32_t mask)151 void WAKETIMER_EnableInterrupts(WAKETIMER_Type *base, uint32_t mask)
152 {
153 assert(NULL != base);
154
155 if (0U != (mask & (uint32_t)kWAKETIMER_WakeInterruptEnable))
156 {
157 base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
158 }
159 }
160
161 /*!
162 * brief Disable the selected WAKETIMER interrupts.
163 *
164 * param base WAKETIMER peripheral base address
165 * param mask Mask value for interrupt events. See to #_waketimer_interrupt_enable
166 */
WAKETIMER_DisableInterrupts(WAKETIMER_Type * base,uint32_t mask)167 void WAKETIMER_DisableInterrupts(WAKETIMER_Type *base, uint32_t mask)
168 {
169 assert(NULL != base);
170
171 if (0U != (mask & (uint32_t)kWAKETIMER_WakeInterruptEnable))
172 {
173 base->WAKE_TIMER_CTRL &= ~WAKETIMER_WAKE_TIMER_CTRL_INTR_EN_MASK;
174 }
175 }
176
177 /*!
178 * brief Clear Status Interrupt Flag.
179 *
180 * This clears intrrupt status flag.
181 * Currently, only match interrupt flag can be cleared.
182 *
183 * param base WAKETIMER peripheral base address.
184 * param mask Mask value for flags to be cleared. See to #_waketimer_status_flags.
185 * return none
186 */
WAKETIMER_ClearStatusFlags(WAKETIMER_Type * base,uint32_t mask)187 void WAKETIMER_ClearStatusFlags(WAKETIMER_Type *base, uint32_t mask)
188 {
189 if (0U != (mask & (uint32_t)kWAKETIMER_WakeFlag))
190 {
191 base->WAKE_TIMER_CTRL |= WAKETIMER_WAKE_TIMER_CTRL_WAKE_FLAG_MASK;
192 }
193 }
194
195 /*!
196 * brief Receive noticification when waketime countdown.
197 *
198 * If the interrupt for the waketime countdown is enabled, then a callback can be registered
199 * which will be invoked when the event is triggered
200 *
201 * param base WAKETIMER peripheral base address
202 * param callback Function to invoke when the event is triggered
203 */
WAKETIMER_SetCallback(WAKETIMER_Type * base,waketimer_callback_t callback)204 void WAKETIMER_SetCallback(WAKETIMER_Type *base, waketimer_callback_t callback)
205 {
206 assert(NULL != base);
207
208 uint32_t index = WAKETIMER_GetInstance(base);
209 s_waketimerCallback[index] = callback;
210 }
211
212 /*!
213 * brief Get current timer count value from WAKETIMER.
214 *
215 * This function will get a decimal timer count value.
216 * The RAW value of timer count is gray code format, will be translated to decimal data internally.
217 *
218 * param base WAKETIMER peripheral base address.
219 * return Value of WAKETIMER which will formated to decimal value.
220 */
WAKETIMER_GetCurrentTimerValue(WAKETIMER_Type * base)221 uint32_t WAKETIMER_GetCurrentTimerValue(WAKETIMER_Type *base)
222 {
223 uint32_t value1 = 0;
224 uint32_t value2 = 0;
225
226 do
227 {
228 value1 = base->WAKE_TIMER_CNT;
229 value2 = base->WAKE_TIMER_CNT;
230 } while (value1 != value2);
231
232 return value1;
233 }
234
WAKETIMER_GenericIRQHandler(WAKETIMER_Type * base,waketimer_callback_t callback)235 static void WAKETIMER_GenericIRQHandler(WAKETIMER_Type *base, waketimer_callback_t callback)
236 {
237 /* Clear interrupt flag. */
238 WAKETIMER_ClearStatusFlags(base, (uint32_t)kWAKETIMER_WakeFlag);
239
240 if (callback != NULL)
241 {
242 callback();
243 }
244 }
245
246 #if defined(WAKETIMER0)
247 void WAKETIMER0_DriverIRQHandler(void);
WAKETIMER0_DriverIRQHandler(void)248 void WAKETIMER0_DriverIRQHandler(void)
249 {
250 WAKETIMER_GenericIRQHandler(WAKETIMER0, s_waketimerCallback[0]);
251 SDK_ISR_EXIT_BARRIER;
252 }
253 #endif
254