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 static bool gRTCInitFlag = false;
19
20 static hal_rtc_callback_t rtcCallback;
21 static void *rtcCbparam;
22 /*
23 * \brief Holds time offset in microseconds, used to calculate the date
24 */
25 static volatile uint64_t gRTCTimeOffset;
26
27 /*
28 * \brief Holds time prescaler offset in ticks, used to calculate the date
29 */
30 static volatile uint32_t gRTCPrescalerOffset;
31
32 /************************************************************************************
33 *************************************************************************************
34 * Private memory declarations
35 *************************************************************************************
36 ************************************************************************************/
37 void RTC_IRQHandler(void);
RTC_IRQHandler(void)38 void RTC_IRQHandler(void)
39 {
40 uint32_t status = RTC_GetStatusFlags(RTC);
41
42 if (0U != (status & (uint32_t)kRTC_AlarmFlag))
43 {
44 /* Clear alarm flag */
45 RTC_ClearStatusFlags(RTC, (uint32_t)kRTC_AlarmInterruptEnable);
46 }
47 else if (0U != (status & (uint32_t)kRTC_TimeInvalidFlag))
48 {
49 /* Clear timer invalid flag */
50 RTC_ClearStatusFlags(RTC, (uint32_t)kRTC_TimeInvalidFlag);
51 }
52 else
53 {
54 /*MISRA rule 15.7*/
55 }
56
57 if (NULL != rtcCallback)
58 {
59 rtcCallback(rtcCbparam);
60 }
61 SDK_ISR_EXIT_BARRIER;
62 }
63
64 /************************************************************************************
65 *************************************************************************************
66 * Public functions
67 *************************************************************************************
68 ************************************************************************************/
HAL_RTCInit(void)69 void HAL_RTCInit(void)
70 {
71 rtc_config_t rtcConfig;
72 rtc_datetime_t date;
73 const rtc_config_t *rtcConfigure = (void *)&rtcConfig;
74 if (!gRTCInitFlag)
75 {
76 RTC_GetDefaultConfig(&rtcConfig);
77 RTC_Init(RTC, rtcConfigure);
78 /* Select RTC clock source */
79 RTC_SetClockSource(RTC);
80 date.year = 2018U;
81 date.month = 5U;
82 date.day = 30U;
83 date.hour = 19U;
84 date.minute = 0;
85 date.second = 0;
86
87 const rtc_datetime_t *rtcDate = (void *)&date;
88 /* RTC time counter has to be stopped before setting the date & time in the TSR register */
89 RTC_StopTimer(RTC);
90
91 /* Set RTC time to default */
92 (void)RTC_SetDatetime(RTC, rtcDate);
93 RTC_StartTimer(RTC);
94 gRTCInitFlag = true;
95 /* Enable RTC alarm interrupt */
96 RTC_EnableInterrupts(RTC, (uint32_t)kRTC_AlarmInterruptEnable);
97 /* Enable at the NVIC */
98 (void)EnableIRQ(RTC_IRQn);
99 }
100 }
101
102 /*! -------------------------------------------------------------------------
103 * \brief Returns the absolute time at the moment of the call.
104 * \return Absolute time at the moment of the call in microseconds.
105 *---------------------------------------------------------------------------*/
HAL_RTCGetTimestamp(void)106 uint64_t HAL_RTCGetTimestamp(void)
107 {
108 uint32_t seconds1, seconds2, prescaler0, prescaler1, prescaler2;
109 uint64_t useconds, offset, prescalerOffset;
110
111 if (!gRTCInitFlag)
112 {
113 useconds = 0;
114 offset = 0;
115 }
116 else
117 {
118 uint32_t regPrimask = DisableGlobalIRQ();
119 offset = gRTCTimeOffset;
120 prescalerOffset = gRTCPrescalerOffset;
121
122 prescaler0 = RTC->TPR;
123 seconds1 = RTC->TSR;
124 prescaler1 = RTC->TPR;
125 seconds2 = RTC->TSR;
126 prescaler2 = RTC->TPR;
127 EnableGlobalIRQ(regPrimask);
128
129 prescaler0 &= 0x7fffU;
130 seconds1 -= 1U;
131 prescaler1 &= 0x7fffU;
132 seconds2 -= 1U;
133 prescaler2 &= 0x7fffU;
134
135 if (seconds1 != seconds2)
136 {
137 seconds1 = seconds2;
138 prescaler1 = prescaler2;
139 }
140 else
141 {
142 if (prescaler1 != prescaler2)
143 {
144 prescaler1 = prescaler0;
145 }
146 }
147
148 useconds = ((prescaler1 + prescalerOffset + ((uint64_t)seconds1 << 15)) * 15625ULL) >> 9;
149 }
150
151 return useconds + offset;
152 }
153
154 #if (defined(RTC_FUNCTIONS_ENABLE) && (RTC_FUNCTIONS_ENABLE > 0))
155 /*! -------------------------------------------------------------------------
156 * \brief Sets the absolute time.
157 * \param[in] microseconds - Time in microseconds.
158 *---------------------------------------------------------------------------*/
HAL_RTCSetTime(uint64_t microseconds)159 void HAL_RTCSetTime(uint64_t microseconds)
160 {
161 uint32_t prescaler;
162 uint32_t seconds = (uint32_t)(microseconds / 1000000ULL);
163 uint32_t ms = (uint32_t)(microseconds % 1000000ULL);
164 /* microseconds = prescaler * 1_000_000 / 32768 = prescaler * 5^6 / 2^9 */
165 /* prescaler = microseconds *2^9 /5^6 */
166 prescaler = (ms << 9) / 15625UL;
167
168 RTC_StopTimer(RTC);
169 RTC->TSR = seconds;
170 RTC->TPR = prescaler;
171
172 RTC_StartTimer(RTC);
173 }
174
175 /*! -------------------------------------------------------------------------
176 * \brief Sets the alarm absolute time in seconds.
177 * \param[in] seconds - Time in seconds for the alarm.
178 * \param[in] callback - Callback function pointer.
179 * \param[in] param - Parameter for callback.
180 *---------------------------------------------------------------------------*/
HAL_RTCSetAlarm(uint64_t microseconds,hal_rtc_callback_t callback,void * param)181 void HAL_RTCSetAlarm(uint64_t microseconds, hal_rtc_callback_t callback, void *param)
182 {
183 /* Set alarm time in seconds */
184 RTC->TAR = (uint32_t)(microseconds / 1000000ULL);
185
186 rtcCallback = callback;
187 rtcCbparam = param;
188 }
189
190 /*! -------------------------------------------------------------------------
191 * \brief Sets the alarm relative time in seconds.
192 * \param[in] seconds - Time in seconds for the alarm.
193 * \param[in] callback - Callback function pointer.
194 * \param[in] param - Parameter for callback.
195 *---------------------------------------------------------------------------*/
HAL_RTCSetAlarmRelative(uint32_t seconds,hal_rtc_callback_t callback,void * param)196 void HAL_RTCSetAlarmRelative(uint32_t seconds, hal_rtc_callback_t callback, void *param)
197 {
198 uint32_t newSeconds;
199 newSeconds = RTC->TSR + seconds;
200 RTC->TAR = newSeconds;
201 rtcCallback = callback;
202 rtcCbparam = param;
203 }
204 #endif /* RTC_FUNCTIONS_ENABLE */
205