1 /*
2 * Copyright 2018 NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_common.h"
10 #include "fsl_adapter_rtc.h"
11 #include "fsl_rtc.h"
12
13 /************************************************************************************
14 *************************************************************************************
15 * Private prototypes
16 *************************************************************************************
17 ************************************************************************************/
18
19 static hal_rtc_callback_t rtcCallback;
20 static void *rtcCbparam;
21
22 static uint8_t gRTCInitFlag = false;
23 /************************************************************************************
24 *************************************************************************************
25 * Private memory declarations
26 *************************************************************************************
27 ************************************************************************************/
RTC_IRQHandler(void)28 void RTC_IRQHandler(void)
29 {
30 if (RTC_GetStatusFlags(RTC) & kRTC_AlarmFlag)
31 {
32 /* Clear alarm flag */
33 RTC_ClearStatusFlags(RTC, kRTC_AlarmFlag);
34 }
35 rtcCallback(rtcCbparam);
36 SDK_ISR_EXIT_BARRIER;
37 }
38
39 /************************************************************************************
40 *************************************************************************************
41 * Public functions
42 *************************************************************************************
43 ************************************************************************************/
HAL_RTCInit(void)44 void HAL_RTCInit(void)
45 {
46 rtc_datetime_t date;
47 if (!gRTCInitFlag)
48 {
49 RTC_Init(RTC);
50 /* Select RTC clock source */
51 date.year = 2018U;
52 date.month = 5U;
53 date.day = 30U;
54 date.hour = 19U;
55 date.minute = 0;
56 date.second = 0;
57
58 /* RTC time counter has to be stopped before setting the date & time in the TSR register */
59 RTC_StopTimer(RTC);
60
61 /* Set RTC time to default */
62 RTC_SetDatetime(RTC, &date);
63
64 /* Enable RTC alarm interrupt */
65 RTC_EnableInterrupts(RTC, kRTC_AlarmInterruptEnable);
66
67 /* Enable at the NVIC */
68 EnableIRQ(RTC_IRQn);
69
70 /* Start the RTC time counter */
71 RTC_StartTimer(RTC);
72 gRTCInitFlag = true;
73 }
74 }
75
76 /*! -------------------------------------------------------------------------
77 * \brief Returns the absolute time at the moment of the call.
78 * \return Absolute time at the moment of the call in microseconds.
79 *---------------------------------------------------------------------------*/
HAL_RTCGetTimestamp(void)80 uint64_t HAL_RTCGetTimestamp(void)
81 {
82 uint32_t seconds1, seconds2, prescaler0, prescaler1, prescaler2;
83 uint64_t useconds;
84
85 if (!gRTCInitFlag)
86 {
87 useconds = 0;
88 }
89 else
90 {
91 uint32_t regPrimask = DisableGlobalIRQ();
92 prescaler0 = RTC->WAKE;
93 seconds1 = RTC->COUNT;
94 prescaler1 = RTC->WAKE;
95 seconds2 = RTC->COUNT;
96 prescaler2 = RTC->WAKE;
97 EnableGlobalIRQ(regPrimask);
98
99 prescaler0 &= 0x7fff;
100 prescaler1 &= 0x7fff;
101 prescaler2 &= 0x7fff;
102
103 if (seconds1 != seconds2)
104 {
105 seconds1 = seconds2;
106 prescaler1 = prescaler2;
107 }
108 else
109 {
110 if (prescaler1 != prescaler2)
111 {
112 prescaler1 = prescaler0;
113 }
114 }
115 useconds = ((prescaler1 + ((uint64_t)seconds1 << 15)) * 15625) >> 9;
116 }
117
118 return useconds;
119 }
120
121 /*! -------------------------------------------------------------------------
122 * \brief Sets the absolute time.
123 * \param[in] microseconds - Time in microseconds.
124 *---------------------------------------------------------------------------*/
HAL_RTCSetTime(uint64_t microseconds)125 void HAL_RTCSetTime(uint64_t microseconds)
126 {
127 uint32_t prescaler;
128 uint32_t seconds = microseconds / 1000000;
129 uint32_t ms = microseconds % 1000000;
130 /* microseconds = prescaler * 1_000_000 / 32768 = prescaler * 5^6 / 2^9 */
131 /* prescaler = microseconds *2^9 /5^6 */
132 prescaler = (ms << 9) / 15625;
133
134 RTC_StopTimer(RTC);
135 RTC->COUNT = seconds;
136
137 RTC->WAKE = prescaler;
138 RTC_StartTimer(RTC);
139 }
140
141 /*! -------------------------------------------------------------------------
142 * \brief Sets the alarm absolute time in seconds.
143 * \param[in] microseconds - Time in seconds for the alarm.
144 * \param[in] callback - Callback function pointer.
145 * \param[in] param - Parameter for callback.
146 *---------------------------------------------------------------------------*/
HAL_RTCSetAlarm(uint64_t microseconds,hal_rtc_callback_t callback,void * param)147 void HAL_RTCSetAlarm(uint64_t microseconds, hal_rtc_callback_t callback, void *param)
148 {
149 /* Set alarm time in seconds */
150 RTC->MATCH = microseconds / 1000000;
151
152 rtcCallback = callback;
153 rtcCbparam = param;
154 }
155
156 /*! -------------------------------------------------------------------------
157 * \brief Sets the alarm relative time in seconds.
158 * \param[in] seconds - Time in seconds for the alarm.
159 * \param[in] callback - Callback function pointer.
160 * \param[in] param - Parameter for callback.
161 *---------------------------------------------------------------------------*/
HAL_RTCSetAlarmRelative(uint32_t seconds,hal_rtc_callback_t callback,void * param)162 void HAL_RTCSetAlarmRelative(uint32_t seconds, hal_rtc_callback_t callback, void *param)
163 {
164 uint32_t newSeconds;
165 newSeconds = RTC->COUNT + seconds;
166 RTC->MATCH = newSeconds;
167 rtcCallback = callback;
168 rtcCbparam = param;
169 }
170