]> git.donarmstrong.com Git - qmk_firmware.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/rtc/fsl_rtc_hal.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[qmk_firmware.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_Freescale / TARGET_KPSDK_MCUS / TARGET_KPSDK_CODE / hal / rtc / fsl_rtc_hal.c
1 /*
2  * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification,
6  * are permitted provided that the following conditions are met:
7  *
8  * o Redistributions of source code must retain the above copyright notice, this list
9  *   of conditions and the following disclaimer.
10  *
11  * o Redistributions in binary form must reproduce the above copyright notice, this
12  *   list of conditions and the following disclaimer in the documentation and/or
13  *   other materials provided with the distribution.
14  *
15  * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
16  *   contributors may be used to endorse or promote products derived from this
17  *   software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
23  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include "fsl_rtc_hal.h"
32 #include "fsl_device_registers.h"
33
34 /*******************************************************************************
35  * Definitions
36  ******************************************************************************/
37
38 #define SECONDS_IN_A_DAY     (86400U)
39 #define SECONDS_IN_A_HOUR    (3600U)
40 #define SECONDS_IN_A_MIN     (60U)
41 #define MINS_IN_A_HOUR       (60U)
42 #define HOURS_IN_A_DAY       (24U)
43 #define DAYS_IN_A_YEAR       (365U)
44 #define DAYS_IN_A_LEAP_YEAR  (366U)
45 #define YEAR_RANGE_START     (1970U)
46 #define YEAR_RANGE_END       (2099U)
47
48 /*******************************************************************************
49  * Variables
50  ******************************************************************************/
51
52 /* Table of month length (in days) for the Un-leap-year*/
53 static const uint8_t ULY[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U,
54     31U,30U,31U};
55
56 /* Table of month length (in days) for the Leap-year*/
57 static const uint8_t LY[] = {0U, 31U, 29U, 31U, 30U, 31U, 30U, 31U, 31U, 30U,
58     31U,30U,31U};
59
60 /* Number of days from begin of the non Leap-year*/
61 static const uint16_t MONTH_DAYS[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U,
62     212U, 243U, 273U, 304U, 334U};
63
64 /*******************************************************************************
65  * Code
66  ******************************************************************************/
67
68 /*FUNCTION**********************************************************************
69  *
70  * Function Name : RTC_HAL_ConvertSecsToDatetime
71  * Description   : converts time data from seconds to a datetime structure.
72  * This function will convert time data from seconds to a datetime structure.
73  *
74  *END**************************************************************************/
75 void RTC_HAL_ConvertSecsToDatetime(const uint32_t * seconds, rtc_datetime_t * datetime)
76 {
77     uint32_t x;
78     uint32_t Seconds, Days, Days_in_year;
79     const uint8_t *Days_in_month;
80
81     /* Start from 1970-01-01*/
82     Seconds = *seconds;
83     /* days*/
84     Days = Seconds / SECONDS_IN_A_DAY;
85     /* seconds left*/
86     Seconds = Seconds % SECONDS_IN_A_DAY;
87     /* hours*/
88     datetime->hour = Seconds / SECONDS_IN_A_HOUR;
89     /* seconds left*/
90     Seconds = Seconds % SECONDS_IN_A_HOUR;
91     /* minutes*/
92     datetime->minute = Seconds / SECONDS_IN_A_MIN;
93     /* seconds*/
94     datetime->second = Seconds % SECONDS_IN_A_MIN;
95     /* year*/
96     datetime->year = YEAR_RANGE_START;
97     Days_in_year = DAYS_IN_A_YEAR;
98
99     while (Days > Days_in_year)
100     {
101         Days -= Days_in_year;
102         datetime->year++;
103         if  (datetime->year & 3U)
104         {
105             Days_in_year = DAYS_IN_A_YEAR;
106         }
107         else
108         {
109             Days_in_year = DAYS_IN_A_LEAP_YEAR;
110         }
111     }
112
113     if  (datetime->year & 3U)
114     {
115         Days_in_month = ULY;
116     }
117     else
118     {
119         Days_in_month = LY;
120     }
121
122     for (x=1U; x <= 12U; x++)
123     {
124         if (Days <= (*(Days_in_month + x)))
125         {
126             datetime->month = x;
127             break;
128         }
129         else
130         {
131             Days -= (*(Days_in_month + x));
132         }
133     }
134
135     datetime->day = Days;
136 }
137
138 /*FUNCTION**********************************************************************
139  *
140  * Function Name : RTC_HAL_IsDatetimeCorrectFormat
141  * Description   : checks if the datetime is in correct format.
142  * This function will check if the given datetime is in the correct format.
143  *
144  *END**************************************************************************/
145 bool RTC_HAL_IsDatetimeCorrectFormat(const rtc_datetime_t * datetime)
146 {
147     bool result = false;
148
149     /* Test correctness of given parameters*/
150     if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) ||
151         (datetime->month > 12U) || (datetime->month < 1U) ||
152         (datetime->day > 31U) || (datetime->day < 1U) ||
153         (datetime->hour >= HOURS_IN_A_DAY) || (datetime->minute >= MINS_IN_A_HOUR) ||
154         (datetime->second >= SECONDS_IN_A_MIN))
155     {
156         /* If not correct then error*/
157         result = false;
158     }
159     else
160     {
161         result = true;
162     }
163
164     /* Is given year un-leap-one?*/
165     /* Leap year calculation only looks for years divisible by 4 as acceptable years is limited */
166     if ( result && (datetime->year & 3U))
167     {
168         /* Does the obtained number of days exceed number of days in the appropriate month & year?*/
169         if (ULY[datetime->month] < datetime->day)
170         {
171             /* If yes (incorrect datetime inserted) then error*/
172             result = false;
173         }
174     }
175     else /* Is given year leap-one?*/
176     {
177         /* Does the obtained number of days exceed number of days in the appropriate month & year?*/
178         if (result && (LY[datetime->month] < datetime->day))
179         {
180             /* if yes (incorrect date inserted) then error*/
181             result = false;
182         }
183     }
184
185     return result;
186 }
187
188 /*FUNCTION**********************************************************************
189  *
190  * Function Name : RTC_HAL_ConvertDatetimeToSecs
191  * Description   : converts time data from datetime to seconds.
192  * This function will convert time data from datetime to seconds.
193  *
194  *END**************************************************************************/
195 void RTC_HAL_ConvertDatetimeToSecs(const rtc_datetime_t * datetime, uint32_t * seconds)
196 {
197     /* Compute number of days from 1970 till given year*/
198     *seconds = (datetime->year - 1970U) * DAYS_IN_A_YEAR;
199     /* Add leap year days */
200     *seconds += ((datetime->year / 4) - (1970U / 4));
201     /* Add number of days till given month*/
202     *seconds += MONTH_DAYS[datetime->month];
203     /* Add days in given month*/
204     *seconds += datetime->day;
205     /* For leap year if month less than or equal to Febraury, decrement day counter*/
206     if ((!(datetime->year & 3U)) && (datetime->month <= 2U))
207     {
208         (*seconds)--;
209     }
210
211     *seconds = ((*seconds) * SECONDS_IN_A_DAY) + (datetime->hour * SECONDS_IN_A_HOUR) +
212                (datetime->minute * SECONDS_IN_A_MIN) + datetime->second;
213 }
214
215 /*FUNCTION**********************************************************************
216  *
217  * Function Name : RTC_HAL_Enable
218  * Description   : initializes the RTC module.
219  * This function will initiate a soft-reset of the RTC module to reset
220  * all the RTC registers. It also enables the RTC oscillator.
221  *
222  *END**************************************************************************/
223 void RTC_HAL_Enable(uint32_t rtcBaseAddr)
224 {
225     /* Enable RTC oscillator since it is required to start the counter*/
226     RTC_HAL_SetOscillatorCmd(rtcBaseAddr, true);
227 }
228
229 void RTC_HAL_Disable(uint32_t rtcBaseAddr)
230 {
231     /* Disable counter*/
232     RTC_HAL_EnableCounter(rtcBaseAddr, false);
233
234     /* Disable RTC oscillator */
235     RTC_HAL_SetOscillatorCmd(rtcBaseAddr, false);
236 }
237
238 void RTC_HAL_Init(uint32_t rtcBaseAddr)
239 {
240     uint32_t seconds = 0x1;
241
242     /* Resets the RTC registers except for the SWR bit */
243     RTC_HAL_SoftwareReset(rtcBaseAddr);
244     RTC_HAL_SoftwareResetFlagClear(rtcBaseAddr);
245
246     /* Set TSR register to 0x1 to avoid the TIF bit being set in the SR register */
247     RTC_HAL_SetSecsReg(rtcBaseAddr, seconds);
248
249     /* Clear the interrupt enable register */
250     RTC_HAL_SetSecsIntCmd(rtcBaseAddr, false);
251     RTC_HAL_SetAlarmIntCmd(rtcBaseAddr, false);
252     RTC_HAL_SetTimeOverflowIntCmd(rtcBaseAddr, false);
253     RTC_HAL_SetTimeInvalidIntCmd(rtcBaseAddr, false);
254 }
255
256 void RTC_HAL_SetDatetime(uint32_t rtcBaseAddr, const rtc_datetime_t * datetime)
257 {
258     uint32_t seconds;
259
260     /* Protect against null pointers*/
261     assert(datetime);
262
263     RTC_HAL_ConvertDatetimeToSecs(datetime, &seconds);
264     /* Set time in seconds */
265     RTC_HAL_SetDatetimeInsecs(rtcBaseAddr, seconds);
266 }
267
268 void RTC_HAL_SetDatetimeInsecs(uint32_t rtcBaseAddr, const uint32_t seconds)
269 {
270     /* Disable counter*/
271     RTC_HAL_EnableCounter(rtcBaseAddr, false);
272     /* Set seconds counter*/
273     RTC_HAL_SetSecsReg(rtcBaseAddr, seconds);
274     /* Enable the counter*/
275     RTC_HAL_EnableCounter(rtcBaseAddr, true);
276 }
277
278 void RTC_HAL_GetDatetime(uint32_t rtcBaseAddr, rtc_datetime_t * datetime)
279 {
280     uint32_t seconds = 0;
281
282     /* Protect against null pointers*/
283     assert(datetime);
284
285     RTC_HAL_GetDatetimeInSecs(rtcBaseAddr, &seconds);
286
287     RTC_HAL_ConvertSecsToDatetime(&seconds, datetime);
288 }
289
290 void RTC_HAL_GetDatetimeInSecs(uint32_t rtcBaseAddr, uint32_t * seconds)
291 {
292     /* Protect against null pointers*/
293     assert(seconds);
294     *seconds = RTC_HAL_GetSecsReg(rtcBaseAddr);
295 }
296
297 bool RTC_HAL_SetAlarm(uint32_t rtcBaseAddr, const rtc_datetime_t * date)
298 {
299     uint32_t alrm_seconds, curr_seconds;
300
301     /* Protect against null pointers*/
302     assert(date);
303
304     RTC_HAL_ConvertDatetimeToSecs(date, &alrm_seconds);
305
306     /* Get the current time */
307     curr_seconds = RTC_HAL_GetSecsReg(rtcBaseAddr);
308
309     /* Make sure the alarm is for a future time */
310     if (alrm_seconds <= curr_seconds)
311     {
312         return false;
313     }
314
315     /* set alarm in seconds*/
316     RTC_HAL_SetAlarmReg(rtcBaseAddr, alrm_seconds);
317
318     return true;
319 }
320
321 void RTC_HAL_GetAlarm(uint32_t rtcBaseAddr, rtc_datetime_t * date)
322 {
323     uint32_t seconds = 0;
324
325     /* Protect against null pointers*/
326     assert(date);
327
328     /* Get alarm in seconds  */
329     seconds = RTC_HAL_GetAlarmReg(rtcBaseAddr);
330
331     RTC_HAL_ConvertSecsToDatetime(&seconds, date);
332 }
333
334 #if FSL_FEATURE_RTC_HAS_MONOTONIC
335
336 void RTC_HAL_GetMonotonicCounter(uint32_t rtcBaseAddr, uint64_t * counter)
337 {
338     uint32_t tmpCountHigh = 0;
339     uint32_t tmpCountLow = 0;
340
341     tmpCountHigh = RTC_HAL_GetMonotonicCounterHigh(rtcBaseAddr);
342     tmpCountLow = RTC_HAL_GetMonotonicCounterLow(rtcBaseAddr);
343
344     *counter = (((uint64_t)(tmpCountHigh) << 32) | ((uint64_t)tmpCountLow));
345 }
346
347 void RTC_HAL_SetMonotonicCounter(uint32_t rtcBaseAddr, const uint64_t * counter)
348 {
349     uint32_t tmpCountHigh = 0;
350     uint32_t tmpCountLow = 0;
351
352     tmpCountHigh = (uint32_t)((*counter) >> 32);
353     RTC_HAL_SetMonotonicCounterHigh(rtcBaseAddr, tmpCountHigh);
354     tmpCountLow = (uint32_t)(*counter);
355     RTC_HAL_SetMonotonicCounterLow(rtcBaseAddr, tmpCountLow);
356 }
357
358 bool RTC_HAL_IncrementMonotonicCounter(uint32_t rtcBaseAddr)
359 {
360     bool result = false;
361
362     if((!(RTC_HAL_IsMonotonicCounterOverflow(rtcBaseAddr))) && (!(RTC_HAL_IsTimeInvalid(rtcBaseAddr))))
363     {
364         /* prepare for incrementing after write*/
365         RTC_HAL_SetMonotonicEnableCmd(rtcBaseAddr, true);
366
367         /* write anything so the counter increments*/
368         BW_RTC_MCLR_MCL(rtcBaseAddr, 1U);
369
370         result = true;
371     }
372
373     return result;
374 }
375
376 #endif
377
378 /*******************************************************************************
379  * EOF
380  ******************************************************************************/
381