1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2020 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_wdog32.h"
10
11 /* Component ID definition, used by tools. */
12 #ifndef FSL_COMPONENT_ID
13 #define FSL_COMPONENT_ID "platform.drivers.wdog32"
14 #endif
15
16 #if defined(WDOG_RSTS)
17 #define WDOG_RESETS_ARRAY WDOG_RSTS
18 #endif
19
20 /*
21 * $Coverage Justification Reference$
22 *
23 * $Justification wdog32_c_ref_1$
24 * Function not covered. Test unfeasible, the reset state is too short to catch.
25 *
26 */
27
28 /*******************************************************************************
29 * Prototypes
30 ******************************************************************************/
31 #if defined(WDOG_RESETS_ARRAY)
32 /*!
33 * @brief Get instance number for WDOG32_ module.
34 *
35 * @param base WDOG32_ peripheral base address.
36 */
37 static uint32_t WDOG32_GetInstance(WDOG_Type *base);
38 #endif
39
40 /*******************************************************************************
41 * Variables
42 ******************************************************************************/
43 #if defined(WDOG_RESETS_ARRAY)
44 static WDOG_Type *const s_wdogBases[] = WDOG_BASE_PTRS;
45
46 /* Reset array */
47 static const reset_ip_name_t s_wdogResets[] = WDOG_RESETS_ARRAY;
48 #endif
49 /*******************************************************************************
50 * Code
51 ******************************************************************************/
52 #if defined(WDOG_RESETS_ARRAY)
WDOG32_GetInstance(WDOG_Type * base)53 static uint32_t WDOG32_GetInstance(WDOG_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_wdogBases); instance++)
59 {
60 if (s_wdogBases[instance] == base)
61 {
62 break;
63 }
64 }
65
66 assert(instance < ARRAY_SIZE(s_wdogBases));
67
68 return instance;
69 }
70 #endif
71
WDOG32_ClearStatusFlags(WDOG_Type * base,uint32_t mask)72 void WDOG32_ClearStatusFlags(WDOG_Type *base, uint32_t mask)
73 {
74
75 /* $Line Coverage Justification$ $ref wdog32_c_ref_1$. */
76 /* $Branch Coverage Justification$ $ref wdog32_c_ref_1$. */
77 if (0U != (mask & (uint32_t)kWDOG32_InterruptFlag))
78 {
79 base->CS |= WDOG_CS_FLG_MASK;
80 }
81 }
82
83 /*!
84 * brief Initializes the WDOG32 configuration structure.
85 *
86 * This function initializes the WDOG32 configuration structure to default values. The default
87 * values are:
88 * code
89 * wdog32Config->enableWdog32 = true;
90 * wdog32Config->clockSource = kWDOG32_ClockSource1;
91 * wdog32Config->prescaler = kWDOG32_ClockPrescalerDivide1;
92 * wdog32Config->workMode.enableWait = true;
93 * wdog32Config->workMode.enableStop = false;
94 * wdog32Config->workMode.enableDebug = false;
95 * wdog32Config->testMode = kWDOG32_TestModeDisabled;
96 * wdog32Config->enableUpdate = true;
97 * wdog32Config->enableInterrupt = false;
98 * wdog32Config->enableWindowMode = false;
99 * wdog32Config->windowValue = 0U;
100 * wdog32Config->timeoutValue = 0xFFFFU;
101 * endcode
102 *
103 * param config Pointer to the WDOG32 configuration structure.
104 * see wdog32_config_t
105 */
WDOG32_GetDefaultConfig(wdog32_config_t * config)106 void WDOG32_GetDefaultConfig(wdog32_config_t *config)
107 {
108 assert(NULL != config);
109
110 /* Initializes the configure structure to zero. */
111 (void)memset(config, 0, sizeof(*config));
112
113 config->enableWdog32 = true;
114 config->clockSource = kWDOG32_ClockSource1;
115 config->prescaler = kWDOG32_ClockPrescalerDivide1;
116 config->workMode.enableWait = true;
117 config->workMode.enableStop = false;
118 config->workMode.enableDebug = false;
119 config->testMode = kWDOG32_TestModeDisabled;
120 config->enableUpdate = true;
121 config->enableInterrupt = false;
122 config->enableWindowMode = false;
123 config->windowValue = 0U;
124 config->timeoutValue = 0xFFFFU;
125 }
126
WDOG32_Init(WDOG_Type * base,const wdog32_config_t * config)127 void WDOG32_Init(WDOG_Type *base, const wdog32_config_t *config)
128 {
129 assert(NULL != config);
130
131 register uint32_t value = 0U;
132 uint32_t primaskValue = 0U;
133 register WDOG_Type *regBase = base;
134 register const wdog32_config_t *regConfig = config;
135 uint32_t tempPrescaler = (uint32_t)regConfig->prescaler;
136
137 #if defined(WDOG_RESETS_ARRAY)
138 RESET_ReleasePeripheralReset(s_wdogResets[WDOG32_GetInstance(base)]);
139 #endif
140
141 value = WDOG_CS_EN((uint32_t)regConfig->enableWdog32) | WDOG_CS_CLK((uint32_t)regConfig->clockSource) |
142 WDOG_CS_INT((uint32_t)regConfig->enableInterrupt) | WDOG_CS_WIN((uint32_t)regConfig->enableWindowMode) |
143 WDOG_CS_UPDATE((uint32_t)regConfig->enableUpdate) | WDOG_CS_DBG((uint32_t)regConfig->workMode.enableDebug) |
144 WDOG_CS_STOP((uint32_t)regConfig->workMode.enableStop) |
145 WDOG_CS_WAIT((uint32_t)regConfig->workMode.enableWait) | WDOG_CS_PRES(tempPrescaler) |
146 WDOG_CS_CMD32EN(1UL) | WDOG_CS_TST((uint32_t)regConfig->testMode);
147
148 /* Disable the global interrupts. Otherwise, an interrupt could effectively invalidate the unlock sequence
149 * and the WCT may expire. After the configuration finishes, re-enable the global interrupts. */
150 primaskValue = DisableGlobalIRQ();
151 WDOG32_Unlock(base);
152 regBase->WIN = regConfig->windowValue;
153 regBase->TOVAL = regConfig->timeoutValue;
154 regBase->CS = value;
155 #ifdef WDOG_CS_RCS_MASK
156 /* Waits until for new configuration to take effect. */
157 while (0U == ((base->CS) & WDOG_CS_RCS_MASK))
158 {
159 ;
160 }
161 #else
162 /* When switches clock sources during reconfiguration, the watchdog hardware holds the counter at
163 zero for 2.5 periods of the previous clock source and 2.5 periods of the new clock source
164 after the configuration time period (128 bus clocks) ends.
165 This delay ensures a smooth transition before restarting the counter with the new configuration. */
166 for (uint8_t timeDelay = 0U; timeDelay < 128U; timeDelay++)
167 {
168 (void)base->CNT;
169 }
170 #endif /* WDOG_CS_RCS_MASK */
171
172 EnableGlobalIRQ(primaskValue);
173 }
174
175 /*!
176 * brief De-initializes the WDOG32 module.
177 *
178 * This function shuts down the WDOG32.
179 * Ensure that the WDOG_CS.UPDATE is 1, which means that the register update is enabled.
180 *
181 * param base WDOG32 peripheral base address.
182 */
WDOG32_Deinit(WDOG_Type * base)183 void WDOG32_Deinit(WDOG_Type *base)
184 {
185 uint32_t primaskValue = 0U;
186
187 /* Disable the global interrupts */
188 primaskValue = DisableGlobalIRQ();
189 WDOG32_Unlock(base);
190 WDOG32_Disable(base);
191 EnableGlobalIRQ(primaskValue);
192 }
193
194 /*!
195 * brief Unlocks the WDOG32 register written.
196 *
197 * This function unlocks the WDOG32 register written.
198 *
199 * Before starting the unlock sequence and following the configuration, disable the global interrupts.
200 * Otherwise, an interrupt could effectively invalidate the unlock sequence and the WCT may expire.
201 * After the configuration finishes, re-enable the global interrupts.
202 *
203 * param base WDOG32 peripheral base address
204 */
WDOG32_Unlock(WDOG_Type * base)205 void WDOG32_Unlock(WDOG_Type *base)
206 {
207 if (0U != ((base->CS) & WDOG_CS_CMD32EN_MASK))
208 {
209 base->CNT = WDOG_UPDATE_KEY;
210 }
211 else
212 {
213 base->CNT = WDOG_FIRST_WORD_OF_UNLOCK;
214 base->CNT = WDOG_SECOND_WORD_OF_UNLOCK;
215 }
216 #ifdef WDOG_CS_ULK_MASK
217 /* Waited until for registers to be unlocked. */
218 while (0U == ((base->CS) & WDOG_CS_ULK_MASK))
219 {
220 ;
221 }
222 #endif /* WDOG_CS_ULK_MASK */
223 }
224
225 /*!
226 * brief Enables the WDOG32 module.
227 *
228 * This function writes a value into the WDOG_CS register to enable the WDOG32.
229 * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
230 * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
231 * this register has not been written in this WCT while the function is called.
232 *
233 * param base WDOG32 peripheral base address.
234 */
WDOG32_Enable(WDOG_Type * base)235 void WDOG32_Enable(WDOG_Type *base)
236 {
237 base->CS |= WDOG_CS_EN_MASK;
238 }
239
240 /*!
241 * brief Disables the WDOG32 module.
242 *
243 * This function writes a value into the WDOG_CS register to disable the WDOG32.
244 * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
245 * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
246 * this register has not been written in this WCT while the function is called.
247 *
248 * param base WDOG32 peripheral base address
249 */
WDOG32_Disable(WDOG_Type * base)250 void WDOG32_Disable(WDOG_Type *base)
251 {
252 base->CS &= ~WDOG_CS_EN_MASK;
253 }
254
255 /*!
256 * brief Enables the WDOG32 interrupt.
257 *
258 * This function writes a value into the WDOG_CS register to enable the WDOG32 interrupt.
259 * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
260 * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
261 * this register has not been written in this WCT while the function is called.
262 *
263 * param base WDOG32 peripheral base address.
264 * param mask The interrupts to enable.
265 * The parameter can be a combination of the following source if defined:
266 * arg kWDOG32_InterruptEnable
267 */
WDOG32_EnableInterrupts(WDOG_Type * base,uint32_t mask)268 void WDOG32_EnableInterrupts(WDOG_Type *base, uint32_t mask)
269 {
270 base->CS |= mask;
271 }
272
273 /*!
274 * brief Disables the WDOG32 interrupt.
275 *
276 * This function writes a value into the WDOG_CS register to disable the WDOG32 interrupt.
277 * The WDOG_CS register is a write-once register. Please check the enableUpdate is set to true for calling WDOG32_Init
278 * to do wdog initialize, before call the re-configuration APIs, ensure that the WCT window is still open and
279 * this register has not been written in this WCT while the function is called.
280 *
281 * param base WDOG32 peripheral base address.
282 * param mask The interrupts to disabled.
283 * The parameter can be a combination of the following source if defined:
284 * arg kWDOG32_InterruptEnable
285 */
WDOG32_DisableInterrupts(WDOG_Type * base,uint32_t mask)286 void WDOG32_DisableInterrupts(WDOG_Type *base, uint32_t mask)
287 {
288 base->CS &= ~mask;
289 }
290
291 /*!
292 * brief Sets the WDOG32 timeout value.
293 *
294 * This function writes a timeout value into the WDOG_TOVAL register.
295 * The WDOG_TOVAL register is a write-once register. To ensure the reconfiguration fits the timing of WCT, unlock
296 * function will be called in the function.
297 *
298 * param base WDOG32 peripheral base address
299 * param timeoutCount WDOG32 timeout value, count of WDOG32 clock ticks.
300 */
WDOG32_SetTimeoutValue(WDOG_Type * base,uint16_t timeoutCount)301 void WDOG32_SetTimeoutValue(WDOG_Type *base, uint16_t timeoutCount)
302 {
303 base->TOVAL = timeoutCount;
304 }
305
306 /*!
307 * brief Sets the WDOG32 window value.
308 *
309 * This function writes a window value into the WDOG_WIN register.
310 * The WDOG_WIN register is a write-once register. Ensure that the WCT window is still open and
311 * this register has not been written in this WCT while the function is called.
312 *
313 * param base WDOG32 peripheral base address.
314 * param windowValue WDOG32 window value.
315 */
WDOG32_SetWindowValue(WDOG_Type * base,uint16_t windowValue)316 void WDOG32_SetWindowValue(WDOG_Type *base, uint16_t windowValue)
317 {
318 base->WIN = windowValue;
319 }
320