]>
git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KPSDK_MCUS/TARGET_KPSDK_CODE/hal/rtc/fsl_rtc_hal.c
2 * Copyright (c) 2013 - 2014, Freescale Semiconductor, Inc.
5 * Redistribution and use in source and binary forms, with or without modification,
6 * are permitted provided that the following conditions are met:
8 * o Redistributions of source code must retain the above copyright notice, this list
9 * of conditions and the following disclaimer.
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.
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.
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.
31 #include "fsl_rtc_hal.h"
32 #include "fsl_device_registers.h"
34 /*******************************************************************************
36 ******************************************************************************/
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)
48 /*******************************************************************************
50 ******************************************************************************/
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,
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,
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};
64 /*******************************************************************************
66 ******************************************************************************/
68 /*FUNCTION**********************************************************************
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.
74 *END**************************************************************************/
75 void RTC_HAL_ConvertSecsToDatetime(const uint32_t * seconds
, rtc_datetime_t
* datetime
)
78 uint32_t Seconds
, Days
, Days_in_year
;
79 const uint8_t *Days_in_month
;
81 /* Start from 1970-01-01*/
84 Days
= Seconds
/ SECONDS_IN_A_DAY
;
86 Seconds
= Seconds
% SECONDS_IN_A_DAY
;
88 datetime
->hour
= Seconds
/ SECONDS_IN_A_HOUR
;
90 Seconds
= Seconds
% SECONDS_IN_A_HOUR
;
92 datetime
->minute
= Seconds
/ SECONDS_IN_A_MIN
;
94 datetime
->second
= Seconds
% SECONDS_IN_A_MIN
;
96 datetime
->year
= YEAR_RANGE_START
;
97 Days_in_year
= DAYS_IN_A_YEAR
;
99 while (Days
> Days_in_year
)
101 Days
-= Days_in_year
;
103 if (datetime
->year
& 3U)
105 Days_in_year
= DAYS_IN_A_YEAR
;
109 Days_in_year
= DAYS_IN_A_LEAP_YEAR
;
113 if (datetime
->year
& 3U)
122 for (x
=1U; x
<= 12U; x
++)
124 if (Days
<= (*(Days_in_month
+ x
)))
131 Days
-= (*(Days_in_month
+ x
));
135 datetime
->day
= Days
;
138 /*FUNCTION**********************************************************************
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.
144 *END**************************************************************************/
145 bool RTC_HAL_IsDatetimeCorrectFormat(const rtc_datetime_t
* datetime
)
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
))
156 /* If not correct then error*/
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))
168 /* Does the obtained number of days exceed number of days in the appropriate month & year?*/
169 if (ULY
[datetime
->month
] < datetime
->day
)
171 /* If yes (incorrect datetime inserted) then error*/
175 else /* Is given year leap-one?*/
177 /* Does the obtained number of days exceed number of days in the appropriate month & year?*/
178 if (result
&& (LY
[datetime
->month
] < datetime
->day
))
180 /* if yes (incorrect date inserted) then error*/
188 /*FUNCTION**********************************************************************
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.
194 *END**************************************************************************/
195 void RTC_HAL_ConvertDatetimeToSecs(const rtc_datetime_t
* datetime
, uint32_t * seconds
)
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))
211 *seconds
= ((*seconds
) * SECONDS_IN_A_DAY
) + (datetime
->hour
* SECONDS_IN_A_HOUR
) +
212 (datetime
->minute
* SECONDS_IN_A_MIN
) + datetime
->second
;
215 /*FUNCTION**********************************************************************
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.
222 *END**************************************************************************/
223 void RTC_HAL_Enable(uint32_t rtcBaseAddr
)
225 /* Enable RTC oscillator since it is required to start the counter*/
226 RTC_HAL_SetOscillatorCmd(rtcBaseAddr
, true);
229 void RTC_HAL_Disable(uint32_t rtcBaseAddr
)
232 RTC_HAL_EnableCounter(rtcBaseAddr
, false);
234 /* Disable RTC oscillator */
235 RTC_HAL_SetOscillatorCmd(rtcBaseAddr
, false);
238 void RTC_HAL_Init(uint32_t rtcBaseAddr
)
240 uint32_t seconds
= 0x1;
242 /* Resets the RTC registers except for the SWR bit */
243 RTC_HAL_SoftwareReset(rtcBaseAddr
);
244 RTC_HAL_SoftwareResetFlagClear(rtcBaseAddr
);
246 /* Set TSR register to 0x1 to avoid the TIF bit being set in the SR register */
247 RTC_HAL_SetSecsReg(rtcBaseAddr
, seconds
);
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);
256 void RTC_HAL_SetDatetime(uint32_t rtcBaseAddr
, const rtc_datetime_t
* datetime
)
260 /* Protect against null pointers*/
263 RTC_HAL_ConvertDatetimeToSecs(datetime
, &seconds
);
264 /* Set time in seconds */
265 RTC_HAL_SetDatetimeInsecs(rtcBaseAddr
, seconds
);
268 void RTC_HAL_SetDatetimeInsecs(uint32_t rtcBaseAddr
, const uint32_t seconds
)
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);
278 void RTC_HAL_GetDatetime(uint32_t rtcBaseAddr
, rtc_datetime_t
* datetime
)
280 uint32_t seconds
= 0;
282 /* Protect against null pointers*/
285 RTC_HAL_GetDatetimeInSecs(rtcBaseAddr
, &seconds
);
287 RTC_HAL_ConvertSecsToDatetime(&seconds
, datetime
);
290 void RTC_HAL_GetDatetimeInSecs(uint32_t rtcBaseAddr
, uint32_t * seconds
)
292 /* Protect against null pointers*/
294 *seconds
= RTC_HAL_GetSecsReg(rtcBaseAddr
);
297 bool RTC_HAL_SetAlarm(uint32_t rtcBaseAddr
, const rtc_datetime_t
* date
)
299 uint32_t alrm_seconds
, curr_seconds
;
301 /* Protect against null pointers*/
304 RTC_HAL_ConvertDatetimeToSecs(date
, &alrm_seconds
);
306 /* Get the current time */
307 curr_seconds
= RTC_HAL_GetSecsReg(rtcBaseAddr
);
309 /* Make sure the alarm is for a future time */
310 if (alrm_seconds
<= curr_seconds
)
315 /* set alarm in seconds*/
316 RTC_HAL_SetAlarmReg(rtcBaseAddr
, alrm_seconds
);
321 void RTC_HAL_GetAlarm(uint32_t rtcBaseAddr
, rtc_datetime_t
* date
)
323 uint32_t seconds
= 0;
325 /* Protect against null pointers*/
328 /* Get alarm in seconds */
329 seconds
= RTC_HAL_GetAlarmReg(rtcBaseAddr
);
331 RTC_HAL_ConvertSecsToDatetime(&seconds
, date
);
334 #if FSL_FEATURE_RTC_HAS_MONOTONIC
336 void RTC_HAL_GetMonotonicCounter(uint32_t rtcBaseAddr
, uint64_t * counter
)
338 uint32_t tmpCountHigh
= 0;
339 uint32_t tmpCountLow
= 0;
341 tmpCountHigh
= RTC_HAL_GetMonotonicCounterHigh(rtcBaseAddr
);
342 tmpCountLow
= RTC_HAL_GetMonotonicCounterLow(rtcBaseAddr
);
344 *counter
= (((uint64_t)(tmpCountHigh
) << 32) | ((uint64_t)tmpCountLow
));
347 void RTC_HAL_SetMonotonicCounter(uint32_t rtcBaseAddr
, const uint64_t * counter
)
349 uint32_t tmpCountHigh
= 0;
350 uint32_t tmpCountLow
= 0;
352 tmpCountHigh
= (uint32_t)((*counter
) >> 32);
353 RTC_HAL_SetMonotonicCounterHigh(rtcBaseAddr
, tmpCountHigh
);
354 tmpCountLow
= (uint32_t)(*counter
);
355 RTC_HAL_SetMonotonicCounterLow(rtcBaseAddr
, tmpCountLow
);
358 bool RTC_HAL_IncrementMonotonicCounter(uint32_t rtcBaseAddr
)
362 if((!(RTC_HAL_IsMonotonicCounterOverflow(rtcBaseAddr
))) && (!(RTC_HAL_IsTimeInvalid(rtcBaseAddr
))))
364 /* prepare for incrementing after write*/
365 RTC_HAL_SetMonotonicEnableCmd(rtcBaseAddr
, true);
367 /* write anything so the counter increments*/
368 BW_RTC_MCLR_MCL(rtcBaseAddr
, 1U);
378 /*******************************************************************************
380 ******************************************************************************/