1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  */
8 
9 #include "fsl_rtc.h"
10 
11 /*******************************************************************************
12  * Definitions
13  ******************************************************************************/
14 #define SECONDS_IN_A_DAY (86400U)
15 #define SECONDS_IN_A_HOUR (3600U)
16 #define SECONDS_IN_A_MINUTE (60U)
17 #define DAYS_IN_A_YEAR (365U)
18 #define YEAR_RANGE_START (1970U)
19 #define YEAR_RANGE_END (2099U)
20 
21 /*******************************************************************************
22  * Prototypes
23  ******************************************************************************/
24 /*!
25  * @brief Checks whether the date and time passed in is valid
26  *
27  * @param datetime Pointer to structure where the date and time details are stored
28  *
29  * @return Returns false if the date & time details are out of range; true if in range
30  */
31 static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime);
32 
33 /*!
34  * @brief Converts time data from datetime to seconds
35  *
36  * @param datetime Pointer to datetime structure where the date and time details are stored
37  *
38  * @return The result of the conversion in seconds
39  */
40 static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime);
41 
42 /*!
43  * @brief Converts time data from seconds to a datetime structure
44  *
45  * @param seconds  Seconds value that needs to be converted to datetime format
46  * @param datetime Pointer to the datetime structure where the result of the conversion is stored
47  */
48 static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime);
49 
50 /*******************************************************************************
51  * Code
52  ******************************************************************************/
RTC_CheckDatetimeFormat(const rtc_datetime_t * datetime)53 static bool RTC_CheckDatetimeFormat(const rtc_datetime_t *datetime)
54 {
55     assert(datetime);
56 
57     /* Table of days in a month for a non leap year. First entry in the table is not used,
58      * valid months start from 1
59      */
60     uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
61 
62     /* Check year, month, hour, minute, seconds */
63     if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
64         (datetime->month < 1U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) || (datetime->second >= 60U))
65     {
66         /* If not correct then error*/
67         return false;
68     }
69 
70     /* Adjust the days in February for a leap year */
71     if ((((datetime->year & 3U) == 0) && (datetime->year % 100 != 0)) || (datetime->year % 400 == 0))
72     {
73         daysPerMonth[2] = 29U;
74     }
75 
76     /* Check the validity of the day */
77     if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
78     {
79         return false;
80     }
81 
82     return true;
83 }
84 
RTC_ConvertDatetimeToSeconds(const rtc_datetime_t * datetime)85 static uint32_t RTC_ConvertDatetimeToSeconds(const rtc_datetime_t *datetime)
86 {
87     assert(datetime);
88 
89     /* Number of days from begin of the non Leap-year*/
90     /* Number of days from begin of the non Leap-year*/
91     uint16_t monthDays[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
92     uint32_t seconds;
93 
94     /* Compute number of days from 1970 till given year*/
95     seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
96     /* Add leap year days */
97     seconds += ((datetime->year / 4) - (1970U / 4));
98     /* Add number of days till given month*/
99     seconds += monthDays[datetime->month];
100     /* Add days in given month. We subtract the current day as it is
101      * represented in the hours, minutes and seconds field*/
102     seconds += (datetime->day - 1);
103     /* For leap year if month less than or equal to Febraury, decrement day counter*/
104     if ((!(datetime->year & 3U)) && (datetime->month <= 2U))
105     {
106         seconds--;
107     }
108 
109     seconds = (seconds * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
110               (datetime->minute * SECONDS_IN_A_MINUTE) + datetime->second;
111 
112     return seconds;
113 }
114 
RTC_ConvertSecondsToDatetime(uint32_t seconds,rtc_datetime_t * datetime)115 static void RTC_ConvertSecondsToDatetime(uint32_t seconds, rtc_datetime_t *datetime)
116 {
117     assert(datetime);
118 
119     uint32_t x;
120     uint32_t secondsRemaining, days;
121     uint16_t daysInYear;
122     /* Table of days in a month for a non leap year. First entry in the table is not used,
123      * valid months start from 1
124      */
125     uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
126 
127     /* Start with the seconds value that is passed in to be converted to date time format */
128     secondsRemaining = seconds;
129 
130     /* Calcuate the number of days, we add 1 for the current day which is represented in the
131      * hours and seconds field
132      */
133     days = secondsRemaining / SECONDS_IN_A_DAY + 1;
134 
135     /* Update seconds left*/
136     secondsRemaining = secondsRemaining % SECONDS_IN_A_DAY;
137 
138     /* Calculate the datetime hour, minute and second fields */
139     datetime->hour = secondsRemaining / SECONDS_IN_A_HOUR;
140     secondsRemaining = secondsRemaining % SECONDS_IN_A_HOUR;
141     datetime->minute = secondsRemaining / 60U;
142     datetime->second = secondsRemaining % SECONDS_IN_A_MINUTE;
143 
144     /* Calculate year */
145     daysInYear = DAYS_IN_A_YEAR;
146     datetime->year = YEAR_RANGE_START;
147     while (days > daysInYear)
148     {
149         /* Decrease day count by a year and increment year by 1 */
150         days -= daysInYear;
151         datetime->year++;
152 
153         /* Adjust the number of days for a leap year */
154         if (datetime->year & 3U)
155         {
156             daysInYear = DAYS_IN_A_YEAR;
157         }
158         else
159         {
160             daysInYear = DAYS_IN_A_YEAR + 1;
161         }
162     }
163 
164     /* Adjust the days in February for a leap year */
165     if (!(datetime->year & 3U))
166     {
167         daysPerMonth[2] = 29U;
168     }
169 
170     for (x = 1U; x <= 12U; x++)
171     {
172         if (days <= daysPerMonth[x])
173         {
174             datetime->month = x;
175             break;
176         }
177         else
178         {
179             days -= daysPerMonth[x];
180         }
181     }
182 
183     datetime->day = days;
184 }
185 
RTC_Init(RTC_Type * base,const rtc_config_t * config)186 void RTC_Init(RTC_Type *base, const rtc_config_t *config)
187 {
188     assert(config);
189 
190     uint32_t reg;
191 
192 #if defined(RTC_CLOCKS)
193 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
194     CLOCK_EnableClock(kCLOCK_Rtc0);
195 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
196 #endif /* RTC_CLOCKS */
197 
198     /* Issue a software reset if timer is invalid */
199     if (RTC_GetStatusFlags(RTC) & kRTC_TimeInvalidFlag)
200     {
201         RTC_Reset(RTC);
202     }
203 
204     reg = base->CR;
205     /* Setup the update mode and supervisor access mode */
206     reg &= ~(RTC_CR_UM_MASK | RTC_CR_SUP_MASK);
207     reg |= RTC_CR_UM(config->updateMode) | RTC_CR_SUP(config->supervisorAccess);
208 #if defined(FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION) && FSL_FEATURE_RTC_HAS_WAKEUP_PIN_SELECTION
209     /* Setup the wakeup pin select */
210     reg &= ~(RTC_CR_WPS_MASK);
211     reg |= RTC_CR_WPS(config->wakeupSelect);
212 #endif /* FSL_FEATURE_RTC_HAS_WAKEUP_PIN */
213     base->CR = reg;
214 
215     /* Configure the RTC time compensation register */
216     base->TCR = (RTC_TCR_CIR(config->compensationInterval) | RTC_TCR_TCR(config->compensationTime));
217 
218 #if defined(FSL_FEATURE_RTC_HAS_TSIC) && FSL_FEATURE_RTC_HAS_TSIC
219 	/* Configure RTC timer seconds interrupt to be generated once per second */
220 	base->IER &= ~(RTC_IER_TSIC_MASK | RTC_IER_TSIE_MASK);
221 #endif
222 }
223 
RTC_GetDefaultConfig(rtc_config_t * config)224 void RTC_GetDefaultConfig(rtc_config_t *config)
225 {
226     assert(config);
227 
228     /* Wakeup pin will assert if the RTC interrupt asserts or if the wakeup pin is turned on */
229     config->wakeupSelect = false;
230     /* Registers cannot be written when locked */
231     config->updateMode = false;
232     /* Non-supervisor mode write accesses are not supported and will generate a bus error */
233     config->supervisorAccess = false;
234     /* Compensation interval used by the crystal compensation logic */
235     config->compensationInterval = 0;
236     /* Compensation time used by the crystal compensation logic */
237     config->compensationTime = 0;
238 }
239 
RTC_SetDatetime(RTC_Type * base,const rtc_datetime_t * datetime)240 status_t RTC_SetDatetime(RTC_Type *base, const rtc_datetime_t *datetime)
241 {
242     assert(datetime);
243 
244     /* Return error if the time provided is not valid */
245     if (!(RTC_CheckDatetimeFormat(datetime)))
246     {
247         return kStatus_InvalidArgument;
248     }
249 
250     /* Set time in seconds */
251     base->TSR = RTC_ConvertDatetimeToSeconds(datetime);
252 
253     return kStatus_Success;
254 }
255 
RTC_GetDatetime(RTC_Type * base,rtc_datetime_t * datetime)256 void RTC_GetDatetime(RTC_Type *base, rtc_datetime_t *datetime)
257 {
258     assert(datetime);
259 
260     uint32_t seconds = 0;
261 
262     seconds = base->TSR;
263     RTC_ConvertSecondsToDatetime(seconds, datetime);
264 }
265 
RTC_SetAlarm(RTC_Type * base,const rtc_datetime_t * alarmTime)266 status_t RTC_SetAlarm(RTC_Type *base, const rtc_datetime_t *alarmTime)
267 {
268     assert(alarmTime);
269 
270     uint32_t alarmSeconds = 0;
271     uint32_t currSeconds = 0;
272 
273     /* Return error if the alarm time provided is not valid */
274     if (!(RTC_CheckDatetimeFormat(alarmTime)))
275     {
276         return kStatus_InvalidArgument;
277     }
278 
279     alarmSeconds = RTC_ConvertDatetimeToSeconds(alarmTime);
280 
281     /* Get the current time */
282     currSeconds = base->TSR;
283 
284     /* Return error if the alarm time has passed */
285     if (alarmSeconds < currSeconds)
286     {
287         return kStatus_Fail;
288     }
289 
290     /* Set alarm in seconds*/
291     base->TAR = alarmSeconds;
292 
293     return kStatus_Success;
294 }
295 
RTC_GetAlarm(RTC_Type * base,rtc_datetime_t * datetime)296 void RTC_GetAlarm(RTC_Type *base, rtc_datetime_t *datetime)
297 {
298     assert(datetime);
299 
300     uint32_t alarmSeconds = 0;
301 
302     /* Get alarm in seconds  */
303     alarmSeconds = base->TAR;
304 
305     RTC_ConvertSecondsToDatetime(alarmSeconds, datetime);
306 }
307 
RTC_EnableInterrupts(RTC_Type * base,uint32_t mask)308 void RTC_EnableInterrupts(RTC_Type *base, uint32_t mask)
309 {
310     uint32_t tmp32 = 0U;
311 
312     /* RTC_IER */
313     if (kRTC_TimeInvalidInterruptEnable == (kRTC_TimeInvalidInterruptEnable & mask))
314     {
315         tmp32 |= RTC_IER_TIIE_MASK;
316     }
317     if (kRTC_TimeOverflowInterruptEnable == (kRTC_TimeOverflowInterruptEnable & mask))
318     {
319         tmp32 |= RTC_IER_TOIE_MASK;
320     }
321     if (kRTC_AlarmInterruptEnable == (kRTC_AlarmInterruptEnable & mask))
322     {
323         tmp32 |= RTC_IER_TAIE_MASK;
324     }
325     if (kRTC_SecondsInterruptEnable == (kRTC_SecondsInterruptEnable & mask))
326     {
327         tmp32 |= RTC_IER_TSIE_MASK;
328     }
329 #if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
330     if (kRTC_MonotonicOverflowInterruptEnable == (kRTC_MonotonicOverflowInterruptEnable & mask))
331     {
332         tmp32 |= RTC_IER_MOIE_MASK;
333     }
334 #endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
335     base->IER |= tmp32;
336 
337 #if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
338     tmp32 = 0U;
339 
340     /* RTC_TIR */
341     if (kRTC_TestModeInterruptEnable == (kRTC_TestModeInterruptEnable & mask))
342     {
343         tmp32 |= RTC_TIR_TMIE_MASK;
344     }
345     if (kRTC_FlashSecurityInterruptEnable == (kRTC_FlashSecurityInterruptEnable & mask))
346     {
347         tmp32 |= RTC_TIR_FSIE_MASK;
348     }
349 #if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
350     if (kRTC_TamperPinInterruptEnable == (kRTC_TamperPinInterruptEnable & mask))
351     {
352         tmp32 |= RTC_TIR_TPIE_MASK;
353     }
354 #endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
355 #if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
356     if (kRTC_SecurityModuleInterruptEnable == (kRTC_SecurityModuleInterruptEnable & mask))
357     {
358         tmp32 |= RTC_TIR_SIE_MASK;
359     }
360 #endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
361 #if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
362     if (kRTC_LossOfClockInterruptEnable == (kRTC_LossOfClockInterruptEnable & mask))
363     {
364         tmp32 |= RTC_TIR_LCIE_MASK;
365     }
366 #endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
367     base->TIR |= tmp32;
368 #endif /* FSL_FEATURE_RTC_HAS_TIR */
369 }
370 
RTC_DisableInterrupts(RTC_Type * base,uint32_t mask)371 void RTC_DisableInterrupts(RTC_Type *base, uint32_t mask)
372 {
373     uint32_t tmp32 = 0U;
374 
375     /* RTC_IER */
376     if (kRTC_TimeInvalidInterruptEnable == (kRTC_TimeInvalidInterruptEnable & mask))
377     {
378         tmp32 |= RTC_IER_TIIE_MASK;
379     }
380     if (kRTC_TimeOverflowInterruptEnable == (kRTC_TimeOverflowInterruptEnable & mask))
381     {
382         tmp32 |= RTC_IER_TOIE_MASK;
383     }
384     if (kRTC_AlarmInterruptEnable == (kRTC_AlarmInterruptEnable & mask))
385     {
386         tmp32 |= RTC_IER_TAIE_MASK;
387     }
388     if (kRTC_SecondsInterruptEnable == (kRTC_SecondsInterruptEnable & mask))
389     {
390         tmp32 |= RTC_IER_TSIE_MASK;
391     }
392 #if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
393     if (kRTC_MonotonicOverflowInterruptEnable == (kRTC_MonotonicOverflowInterruptEnable & mask))
394     {
395         tmp32 |= RTC_IER_MOIE_MASK;
396     }
397 #endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
398     base->IER &= (uint32_t)(~tmp32);
399 
400 #if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
401     tmp32 = 0U;
402 
403     /* RTC_TIR */
404     if (kRTC_TestModeInterruptEnable == (kRTC_TestModeInterruptEnable & mask))
405     {
406         tmp32 |= RTC_TIR_TMIE_MASK;
407     }
408     if (kRTC_FlashSecurityInterruptEnable == (kRTC_FlashSecurityInterruptEnable & mask))
409     {
410         tmp32 |= RTC_TIR_FSIE_MASK;
411     }
412 #if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
413     if (kRTC_TamperPinInterruptEnable == (kRTC_TamperPinInterruptEnable & mask))
414     {
415         tmp32 |= RTC_TIR_TPIE_MASK;
416     }
417 #endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
418 #if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
419     if (kRTC_SecurityModuleInterruptEnable == (kRTC_SecurityModuleInterruptEnable & mask))
420     {
421         tmp32 |= RTC_TIR_SIE_MASK;
422     }
423 #endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
424 #if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
425     if (kRTC_LossOfClockInterruptEnable == (kRTC_LossOfClockInterruptEnable & mask))
426     {
427         tmp32 |= RTC_TIR_LCIE_MASK;
428     }
429 #endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
430     base->TIR &= (uint32_t)(~tmp32);
431 #endif /* FSL_FEATURE_RTC_HAS_TIR */
432 }
433 
RTC_GetEnabledInterrupts(RTC_Type * base)434 uint32_t RTC_GetEnabledInterrupts(RTC_Type *base)
435 {
436     uint32_t tmp32 = 0U;
437 
438     /* RTC_IER */
439     if (RTC_IER_TIIE_MASK == (RTC_IER_TIIE_MASK & base->IER))
440     {
441         tmp32 |= kRTC_TimeInvalidInterruptEnable;
442     }
443     if (RTC_IER_TOIE_MASK == (RTC_IER_TOIE_MASK & base->IER))
444     {
445         tmp32 |= kRTC_TimeOverflowInterruptEnable;
446     }
447     if (RTC_IER_TAIE_MASK == (RTC_IER_TAIE_MASK & base->IER))
448     {
449         tmp32 |= kRTC_AlarmInterruptEnable;
450     }
451     if (RTC_IER_TSIE_MASK == (RTC_IER_TSIE_MASK & base->IER))
452     {
453         tmp32 |= kRTC_SecondsInterruptEnable;
454     }
455 #if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
456     if (RTC_IER_MOIE_MASK == (RTC_IER_MOIE_MASK & base->IER))
457     {
458         tmp32 |= kRTC_MonotonicOverflowInterruptEnable;
459     }
460 #endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
461 
462 #if (defined(FSL_FEATURE_RTC_HAS_TIR) && FSL_FEATURE_RTC_HAS_TIR)
463     /* RTC_TIR */
464     if (RTC_TIR_TMIE_MASK == (RTC_TIR_TMIE_MASK & base->TIR))
465     {
466         tmp32 |= kRTC_TestModeInterruptEnable;
467     }
468     if (RTC_TIR_FSIE_MASK == (RTC_TIR_FSIE_MASK & base->TIR))
469     {
470         tmp32 |= kRTC_FlashSecurityInterruptEnable;
471     }
472 #if (defined(FSL_FEATURE_RTC_HAS_TIR_TPIE) && FSL_FEATURE_RTC_HAS_TIR_TPIE)
473     if (RTC_TIR_TPIE_MASK == (RTC_TIR_TPIE_MASK & base->TIR))
474     {
475         tmp32 |= kRTC_TamperPinInterruptEnable;
476     }
477 #endif /* FSL_FEATURE_RTC_HAS_TIR_TPIE */
478 #if (defined(FSL_FEATURE_RTC_HAS_TIR_SIE) && FSL_FEATURE_RTC_HAS_TIR_SIE)
479     if (RTC_TIR_SIE_MASK == (RTC_TIR_SIE_MASK & base->TIR))
480     {
481         tmp32 |= kRTC_SecurityModuleInterruptEnable;
482     }
483 #endif /* FSL_FEATURE_RTC_HAS_TIR_SIE */
484 #if (defined(FSL_FEATURE_RTC_HAS_TIR_LCIE) && FSL_FEATURE_RTC_HAS_TIR_LCIE)
485     if (RTC_TIR_LCIE_MASK == (RTC_TIR_LCIE_MASK & base->TIR))
486     {
487         tmp32 |= kRTC_LossOfClockInterruptEnable;
488     }
489 #endif /* FSL_FEATURE_RTC_HAS_TIR_LCIE */
490 #endif /* FSL_FEATURE_RTC_HAS_TIR */
491 
492     return tmp32;
493 }
494 
RTC_GetStatusFlags(RTC_Type * base)495 uint32_t RTC_GetStatusFlags(RTC_Type *base)
496 {
497     uint32_t tmp32 = 0U;
498 
499     /* RTC_SR */
500     if (RTC_SR_TIF_MASK == (RTC_SR_TIF_MASK & base->SR))
501     {
502         tmp32 |= kRTC_TimeInvalidFlag;
503     }
504     if (RTC_SR_TOF_MASK == (RTC_SR_TOF_MASK & base->SR))
505     {
506         tmp32 |= kRTC_TimeOverflowFlag;
507     }
508     if (RTC_SR_TAF_MASK == (RTC_SR_TAF_MASK & base->SR))
509     {
510         tmp32 |= kRTC_AlarmFlag;
511     }
512 #if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
513     if (RTC_SR_MOF_MASK == (RTC_SR_MOF_MASK & base->SR))
514     {
515         tmp32 |= kRTC_MonotonicOverflowFlag;
516     }
517 #endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
518 #if (defined(FSL_FEATURE_RTC_HAS_SR_TIDF) && FSL_FEATURE_RTC_HAS_SR_TIDF)
519     if (RTC_SR_TIDF_MASK == (RTC_SR_TIDF_MASK & base->SR))
520     {
521         tmp32 |= kRTC_TamperInterruptDetectFlag;
522     }
523 #endif /* FSL_FEATURE_RTC_HAS_SR_TIDF */
524 
525 #if (defined(FSL_FEATURE_RTC_HAS_TDR) && FSL_FEATURE_RTC_HAS_TDR)
526     /* RTC_TDR */
527     if (RTC_TDR_TMF_MASK == (RTC_TDR_TMF_MASK & base->TDR))
528     {
529         tmp32 |= kRTC_TestModeFlag;
530     }
531     if (RTC_TDR_FSF_MASK == (RTC_TDR_FSF_MASK & base->TDR))
532     {
533         tmp32 |= kRTC_FlashSecurityFlag;
534     }
535 #if (defined(FSL_FEATURE_RTC_HAS_TDR_TPF) && FSL_FEATURE_RTC_HAS_TDR_TPF)
536     if (RTC_TDR_TPF_MASK == (RTC_TDR_TPF_MASK & base->TDR))
537     {
538         tmp32 |= kRTC_TamperPinFlag;
539     }
540 #endif /* FSL_FEATURE_RTC_HAS_TDR_TPF */
541 #if (defined(FSL_FEATURE_RTC_HAS_TDR_STF) && FSL_FEATURE_RTC_HAS_TDR_STF)
542     if (RTC_TDR_STF_MASK == (RTC_TDR_STF_MASK & base->TDR))
543     {
544         tmp32 |= kRTC_SecurityTamperFlag;
545     }
546 #endif /* FSL_FEATURE_RTC_HAS_TDR_STF */
547 #if (defined(FSL_FEATURE_RTC_HAS_TDR_LCTF) && FSL_FEATURE_RTC_HAS_TDR_LCTF)
548     if (RTC_TDR_LCTF_MASK == (RTC_TDR_LCTF_MASK & base->TDR))
549     {
550         tmp32 |= kRTC_LossOfClockTamperFlag;
551     }
552 #endif /* FSL_FEATURE_RTC_HAS_TDR_LCTF */
553 #endif /* FSL_FEATURE_RTC_HAS_TDR */
554 
555     return tmp32;
556 }
557 
RTC_ClearStatusFlags(RTC_Type * base,uint32_t mask)558 void RTC_ClearStatusFlags(RTC_Type *base, uint32_t mask)
559 {
560     /* The alarm flag is cleared by writing to the TAR register */
561     if (mask & kRTC_AlarmFlag)
562     {
563         base->TAR = 0U;
564     }
565 
566     /* The timer overflow flag is cleared by initializing the TSR register.
567      * The time counter should be disabled for this write to be successful
568      */
569     if (mask & kRTC_TimeOverflowFlag)
570     {
571         base->TSR = 1U;
572     }
573 
574     /* The timer overflow flag is cleared by initializing the TSR register.
575      * The time counter should be disabled for this write to be successful
576      */
577     if (mask & kRTC_TimeInvalidFlag)
578     {
579         base->TSR = 1U;
580     }
581 
582 #if (defined(FSL_FEATURE_RTC_HAS_TDR) && FSL_FEATURE_RTC_HAS_TDR)
583     /* To clear, write logic one to this flag after exiting from all test modes */
584     if (kRTC_TestModeFlag == (kRTC_TestModeFlag & mask))
585     {
586         base->TDR = RTC_TDR_TMF_MASK;
587     }
588     /* To clear, write logic one to this flag after flash security is enabled */
589     if (kRTC_FlashSecurityFlag == (kRTC_FlashSecurityFlag & mask))
590     {
591         base->TDR = RTC_TDR_FSF_MASK;
592     }
593 #if (defined(FSL_FEATURE_RTC_HAS_TDR_TPF) && FSL_FEATURE_RTC_HAS_TDR_TPF)
594     /* To clear, write logic one to the corresponding flag after that tamper pin negates */
595     if (kRTC_TamperPinFlag == (kRTC_TamperPinFlag & mask))
596     {
597         base->TDR = RTC_TDR_TPF_MASK;
598     }
599 #endif /* FSL_FEATURE_RTC_HAS_TDR_TPF */
600 #if (defined(FSL_FEATURE_RTC_HAS_TDR_STF) && FSL_FEATURE_RTC_HAS_TDR_STF)
601     /* To clear, write logic one to this flag after security module has negated its tamper detect */
602     if (kRTC_SecurityTamperFlag == (kRTC_SecurityTamperFlag & mask))
603     {
604         base->TDR = RTC_TDR_STF_MASK;
605     }
606 #endif /* FSL_FEATURE_RTC_HAS_TDR_STF */
607 #if (defined(FSL_FEATURE_RTC_HAS_TDR_LCTF) && FSL_FEATURE_RTC_HAS_TDR_LCTF)
608     /* To clear, write logic one to this flag after loss of clock negates */
609     if (kRTC_LossOfClockTamperFlag == (kRTC_LossOfClockTamperFlag & mask))
610     {
611         base->TDR = RTC_TDR_LCTF_MASK;
612     }
613 #endif /* FSL_FEATURE_RTC_HAS_TDR_LCTF */
614 #endif /* FSL_FEATURE_RTC_HAS_TDR */
615 }
616 
617 #if defined(FSL_FEATURE_RTC_HAS_MONOTONIC) && (FSL_FEATURE_RTC_HAS_MONOTONIC)
618 
RTC_GetMonotonicCounter(RTC_Type * base,uint64_t * counter)619 void RTC_GetMonotonicCounter(RTC_Type *base, uint64_t *counter)
620 {
621     assert(counter);
622 
623     *counter = (((uint64_t)base->MCHR << 32) | ((uint64_t)base->MCLR));
624 }
625 
RTC_SetMonotonicCounter(RTC_Type * base,uint64_t counter)626 void RTC_SetMonotonicCounter(RTC_Type *base, uint64_t counter)
627 {
628     /* Prepare to initialize the register with the new value written */
629     base->MER &= ~RTC_MER_MCE_MASK;
630 
631     base->MCHR = (uint32_t)((counter) >> 32);
632     base->MCLR = (uint32_t)(counter);
633 }
634 
RTC_IncrementMonotonicCounter(RTC_Type * base)635 status_t RTC_IncrementMonotonicCounter(RTC_Type *base)
636 {
637     if (base->SR & (RTC_SR_MOF_MASK | RTC_SR_TIF_MASK))
638     {
639         return kStatus_Fail;
640     }
641 
642     /* Prepare to switch to increment mode */
643     base->MER |= RTC_MER_MCE_MASK;
644     /* Write anything so the counter increments*/
645     base->MCLR = 1U;
646 
647     return kStatus_Success;
648 }
649 
650 #endif /* FSL_FEATURE_RTC_HAS_MONOTONIC */
651