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