1 /*
2 * Copyright (c) 2015, Freescale Semiconductor, Inc.
3 * Copyright 2016-2019, 2023 NXP
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
9 #include "fsl_irtc.h"
10
11 /*******************************************************************************
12 * Definitions
13 ******************************************************************************/
14
15 /* Component ID definition, used by tools. */
16 #ifndef FSL_COMPONENT_ID
17 #define FSL_COMPONENT_ID "platform.drivers.irtc"
18 #endif
19
20 #define IRTC_BASE_YEAR (2112U)
21 #define YEAR_RANGE_START (1984U) /* Valid values for year range from -128 to 127; 2112 - 128 */
22 #define YEAR_RANGE_END (2239U) /* Valid values for year range from -128 to 127; 2112 + 127 */
23
24 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
25 (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
26 /*! @brief Array to map IRTC instance number to base pointer. */
27 static RTC_Type *const kIrtcBases[] = RTC_BASE_PTRS;
28 #endif
29
30 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
31 /*! @brief Array to map IRTC instance number to clock gate enum. */
32 static clock_ip_name_t const kIrtcClocks[] = RTC_CLOCKS;
33 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
34
35 #if defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET
36 /*! @brief Pointers to IRTC resets for each instance. */
37 static const reset_ip_name_t kIrtcResets[] = RTC_RSTS;
38 #endif
39
40 /*******************************************************************************
41 * Prototypes
42 ******************************************************************************/
43 /*!
44 * @brief Checks whether the date and time passed in is valid
45 *
46 * @param datetime Pointer to structure where the date and time details are stored
47 *
48 * @return Returns false if the date & time details are out of range; true if in range
49 */
50 static bool IRTC_CheckDatetimeFormat(const irtc_datetime_t *datetime);
51
52 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
53 (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
54 /*!
55 * @brief Returns an instance number given a base address.
56 *
57 * @param base The IRTC peripheral base address.
58 * @return IRTC instance number starting from 0. If cannot the base address is
59 * not a valid address, this function returns -1.
60 */
61 static int32_t IRTC_GetInstance(RTC_Type *base);
62 #endif
63
64 /*******************************************************************************
65 * Code
66 ******************************************************************************/
IRTC_CheckDatetimeFormat(const irtc_datetime_t * datetime)67 static bool IRTC_CheckDatetimeFormat(const irtc_datetime_t *datetime)
68 {
69 assert(NULL != datetime);
70
71 bool fgRet = true;
72
73 /* Table of days in a month for a non leap year */
74 uint8_t daysPerMonth[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
75
76 /* Check year, month, hour, minute, seconds */
77 if ((datetime->year < YEAR_RANGE_START) || (datetime->year > YEAR_RANGE_END) || (datetime->month > 12U) ||
78 (datetime->month < 1U) || (datetime->weekDay >= 7U) || (datetime->hour >= 24U) || (datetime->minute >= 60U) ||
79 (datetime->second >= 60U))
80 {
81 /* If not correct then error*/
82 fgRet = false;
83 }
84 else
85 {
86 /* Adjust the days in February for a leap year */
87 if (((0U == (datetime->year & 3U)) && (0U != (datetime->year % 100U))) || (0U == (datetime->year % 400U)))
88 {
89 daysPerMonth[2] = 29U;
90 }
91
92 /* Check the validity of the day */
93 if ((datetime->day > daysPerMonth[datetime->month]) || (datetime->day < 1U))
94 {
95 fgRet = false;
96 }
97 }
98 return fgRet;
99 }
100
101 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
102 (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
IRTC_GetInstance(RTC_Type * base)103 static int32_t IRTC_GetInstance(RTC_Type *base)
104 {
105 int32_t instance;
106
107 for (instance = 0; instance < (int32_t)ARRAY_SIZE(kIrtcBases); ++instance)
108 {
109 if (MSDK_REG_SECURE_ADDR(kIrtcBases[instance]) == MSDK_REG_SECURE_ADDR(base))
110 {
111 break;
112 }
113 }
114
115 if (instance >= (int32_t)ARRAY_SIZE(kIrtcBases))
116 {
117 instance = -1;
118 }
119
120 return instance;
121 }
122 #endif
123
124 /*!
125 * brief Ungates the IRTC clock and configures the peripheral for basic operation.
126 *
127 * This function initiates a soft-reset of the IRTC module, this has not effect on DST,
128 * calendaring, standby time and tamper detect registers.
129 *
130 * note This API should be called at the beginning of the application using the IRTC driver.
131 *
132 * param base IRTC peripheral base address
133 * param config Pointer to user's IRTC config structure.
134 *
135 * return kStatus_Fail if we cannot disable register write protection
136 */
IRTC_Init(RTC_Type * base,const irtc_config_t * config)137 status_t IRTC_Init(RTC_Type *base, const irtc_config_t *config)
138 {
139 assert(NULL != config);
140
141 uint16_t reg;
142 status_t status = kStatus_Success;
143
144 #if (!(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)) || \
145 (defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET)
146 int32_t instance = IRTC_GetInstance(base);
147 if (instance < 0)
148 {
149 return kStatus_InvalidArgument;
150 }
151 #endif
152
153 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
154 CLOCK_EnableClock(kIrtcClocks[instance]);
155 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
156
157 #if defined(FSL_FEATURE_RTC_HAS_RESET) && FSL_FEATURE_RTC_HAS_RESET
158 RESET_ReleasePeripheralReset(kIrtcResets[instance]);
159 #endif
160
161 /* Unlock to allow register write operation */
162 if (kStatus_Success == IRTC_SetWriteProtection(base, false))
163 {
164 /* Issue a software reset */
165 IRTC_Reset(base);
166
167 #if !defined(FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE) || (!FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE)
168 /* Setup the wakeup pin select */
169 if (config->wakeupSelect)
170 {
171 base->CTRL2 |= RTC_CTRL2_WAKEUP_MODE_MASK;
172 }
173 else
174 {
175 base->CTRL2 &= ~(uint16_t)RTC_CTRL2_WAKEUP_MODE_MASK;
176 }
177 #endif
178 /* Setup alarm match operation, sampling clock operation in standby mode, 16.384kHz RTC clock and selected clock outout to other peripherals */
179 reg = base->CTRL;
180 reg &= ~(
181 #if !defined(FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK) || (!FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK)
182 (uint16_t)RTC_CTRL_TIMER_STB_MASK_MASK |
183 #endif
184 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
185 (uint16_t)RTC_CTRL_CLK_SEL_MASK |
186 #endif
187 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE) && FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE
188 (uint16_t)RTC_CTRL_CLKO_DIS_MASK |
189 #endif
190 (uint16_t)RTC_CTRL_ALM_MATCH_MASK);
191 reg |= (
192 #if !defined(FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK) || (!FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK)
193 RTC_CTRL_TIMER_STB_MASK(config->timerStdMask) |
194 #endif
195 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
196 RTC_CTRL_CLK_SEL(config->clockSelect) |
197 #endif
198 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE) && FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE
199 RTC_CTRL_CLKO_DIS(config->disableClockOutput) |
200 #endif
201 RTC_CTRL_ALM_MATCH(config->alrmMatch));
202 base->CTRL = reg;
203 }
204 else
205 {
206 status = kStatus_Fail;
207 }
208
209 return status;
210 }
211
212 /*
213 * brief Gate the IRTC clock
214 *
215 * param base IRTC peripheral base address
216 */
IRTC_Deinit(RTC_Type * base)217 status_t IRTC_Deinit(RTC_Type *base)
218 {
219 #if !(defined(FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL) && FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL)
220 int32_t instance = IRTC_GetInstance(base);
221 if (instance < 0)
222 {
223 return kStatus_InvalidArgument;
224 }
225
226 CLOCK_DisableClock(kIrtcClocks[instance]);
227 #endif /* FSL_SDK_DISABLE_DRIVER_CLOCK_CONTROL */
228
229 return kStatus_Success;
230 }
231
232 /*!
233 * brief Fill in the IRTC config struct with the default settings
234 *
235 * The default values are:
236 * code
237 * config->wakeupSelect = true;
238 * config->timerStdMask = false;
239 * config->alrmMatch = kRTC_MatchSecMinHr;
240 * endcode
241 * param config Pointer to user's IRTC config structure.
242 */
IRTC_GetDefaultConfig(irtc_config_t * config)243 void IRTC_GetDefaultConfig(irtc_config_t *config)
244 {
245 assert(NULL != config);
246
247 /* Initializes the configure structure to zero. */
248 (void)memset(config, 0, sizeof(*config));
249
250 #if !defined(FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE) || (!FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE)
251 /* Tamper pin 0 is used as a wakeup/hibernation pin */
252 config->wakeupSelect = true;
253 #endif
254
255 #if !defined(FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK) || (!FSL_FEATURE_RTC_HAS_NO_TIMER_STB_MASK)
256 /* Sampling clock are not gated when in standby mode */
257 config->timerStdMask = false;
258 #endif
259
260 /* Only seconds, minutes and hours are matched when generating an alarm */
261 config->alrmMatch = kRTC_MatchSecMinHr;
262
263 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
264 /* 16.384kHz clock is selected */
265 config->clockSelect = kIRTC_Clk16K;
266 #endif
267
268 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE) && FSL_FEATURE_RTC_HAS_CLOCK_OUTPUT_DISABLE
269 /* The selected clock is not output to other peripherals */
270 config->disableClockOutput = true;
271 #endif
272 }
273
274 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
275 /*!
276 * brief Sets the IRTC date and time according to the given time structure.
277 *
278 * The IRTC counter is started after the time is set.
279 *
280 * param base IRTC peripheral base address
281 * param datetime Pointer to structure where the date and time details to set are stored
282 *
283 * return kStatus_Success: success in setting the time and starting the IRTC
284 * kStatus_InvalidArgument: failure. An error occurs because the datetime format is incorrect.
285 */
IRTC_SetDatetime(RTC_Type * base,const irtc_datetime_t * datetime)286 status_t IRTC_SetDatetime(RTC_Type *base, const irtc_datetime_t *datetime)
287 {
288 assert(NULL != datetime);
289
290 status_t status = kStatus_Success;
291
292 /* Return error if the time provided is not valid */
293 if (IRTC_CheckDatetimeFormat(datetime))
294 {
295 /* The register stores the offset in years from the base year of 2112 */
296 if (datetime->year < IRTC_BASE_YEAR)
297 {
298 /* Values for years less than the base year range from -128 to 1 */
299 base->YEARMON =
300 RTC_YEARMON_YROFST(0x100U + datetime->year - IRTC_BASE_YEAR) | RTC_YEARMON_MON_CNT(datetime->month);
301 }
302 else
303 {
304 /* Values for years greater or equal to the base year range from 0 to 127 */
305 base->YEARMON = RTC_YEARMON_YROFST(datetime->year - IRTC_BASE_YEAR) | RTC_YEARMON_MON_CNT(datetime->month);
306 }
307 /* Update the Day Count and Day of the week field */
308 base->DAYS = RTC_DAYS_DOW(datetime->weekDay) | RTC_DAYS_DAY_CNT(datetime->day);
309
310 /* Update hour and minute field */
311 base->HOURMIN = RTC_HOURMIN_HOUR_CNT(datetime->hour) | RTC_HOURMIN_MIN_CNT(datetime->minute);
312
313 /* Update the seconds register */
314 base->SECONDS = RTC_SECONDS_SEC_CNT(datetime->second);
315 }
316 else
317 {
318 status = kStatus_InvalidArgument;
319 }
320
321 return status;
322 }
323 #endif /* FSL_FEATURE_RTC_IS_SLAVE */
324
325 /*!
326 * brief Gets the IRTC time and stores it in the given time structure.
327 *
328 * param base IRTC peripheral base address
329 * param datetime Pointer to structure where the date and time details are stored.
330 */
IRTC_GetDatetime(RTC_Type * base,irtc_datetime_t * datetime)331 void IRTC_GetDatetime(RTC_Type *base, irtc_datetime_t *datetime)
332 {
333 assert(NULL != datetime);
334
335 uint16_t temp = base->YEARMON;
336
337 datetime->year =
338 (uint16_t)IRTC_BASE_YEAR + (uint16_t)((int8_t)(uint8_t)((temp >> RTC_YEARMON_YROFST_SHIFT) & 0xFFU));
339 datetime->month = (uint8_t)temp & RTC_YEARMON_MON_CNT_MASK;
340
341 temp = base->DAYS;
342 datetime->weekDay = (uint8_t)((temp & RTC_DAYS_DOW_MASK) >> RTC_DAYS_DOW_SHIFT);
343 datetime->day = (uint8_t)temp & RTC_DAYS_DAY_CNT_MASK;
344
345 temp = base->HOURMIN;
346 datetime->hour = (uint8_t)((temp & RTC_HOURMIN_HOUR_CNT_MASK) >> RTC_HOURMIN_HOUR_CNT_SHIFT);
347 datetime->minute = (uint8_t)temp & RTC_HOURMIN_MIN_CNT_MASK;
348
349 datetime->second = (uint8_t)(base->SECONDS) & RTC_SECONDS_SEC_CNT_MASK;
350 }
351
352 /*!
353 * brief Sets the IRTC alarm time
354 *
355 * param base RTC peripheral base address
356 * param alarmTime Pointer to structure where the alarm time is stored.
357 *
358 * note weekDay field of alarmTime is not used during alarm match and should be set to 0
359 *
360 * return kStatus_Success: success in setting the alarm
361 * kStatus_InvalidArgument: error in setting the alarm. Error occurs because the alarm
362 * datetime format is incorrect.
363 */
IRTC_SetAlarm(RTC_Type * base,const irtc_datetime_t * alarmTime)364 status_t IRTC_SetAlarm(RTC_Type *base, const irtc_datetime_t *alarmTime)
365 {
366 assert(NULL != alarmTime);
367
368 status_t status = kStatus_Success;
369
370 /* Return error if the alarm time provided is not valid */
371 if (IRTC_CheckDatetimeFormat(alarmTime))
372 {
373 /* Set the alarm year */
374 if (alarmTime->year < IRTC_BASE_YEAR)
375 {
376 base->ALM_YEARMON = RTC_ALM_YEARMON_ALM_YEAR(0x100U + alarmTime->year - IRTC_BASE_YEAR) |
377 RTC_ALM_YEARMON_ALM_MON(alarmTime->month);
378 }
379 else
380 {
381 base->ALM_YEARMON =
382 RTC_ALM_YEARMON_ALM_YEAR(alarmTime->year - IRTC_BASE_YEAR) | RTC_ALM_YEARMON_ALM_MON(alarmTime->month);
383 }
384
385 /* Set the alarm day */
386 base->ALM_DAYS = RTC_ALM_DAYS_ALM_DAY(alarmTime->day);
387
388 /* Set the alarm hour and minute */
389 base->ALM_HOURMIN = RTC_ALM_HOURMIN_ALM_HOUR(alarmTime->hour) | RTC_ALM_HOURMIN_ALM_MIN(alarmTime->minute);
390
391 /* Set the alarm seconds */
392 base->ALM_SECONDS = RTC_ALM_SECONDS_ALM_SEC(alarmTime->second);
393 }
394 else
395 {
396 status = kStatus_InvalidArgument;
397 }
398
399 return status;
400 }
401
402 /*!
403 * brief Returns the IRTC alarm time.
404 *
405 * param base RTC peripheral base address
406 * param datetime Pointer to structure where the alarm date and time details are stored.
407 */
IRTC_GetAlarm(RTC_Type * base,irtc_datetime_t * datetime)408 void IRTC_GetAlarm(RTC_Type *base, irtc_datetime_t *datetime)
409 {
410 assert(NULL != datetime);
411
412 uint16_t temp = base->ALM_YEARMON;
413
414 datetime->year =
415 (uint16_t)IRTC_BASE_YEAR + (uint16_t)((int8_t)(uint8_t)((temp >> RTC_ALM_YEARMON_ALM_YEAR_SHIFT) & 0xFFU));
416 datetime->month = (uint8_t)temp & RTC_ALM_YEARMON_ALM_MON_MASK;
417
418 datetime->day = (uint8_t)(base->ALM_DAYS) & RTC_ALM_DAYS_ALM_DAY_MASK;
419
420 temp = base->ALM_HOURMIN;
421 datetime->hour = (uint8_t)((temp & RTC_ALM_HOURMIN_ALM_HOUR_MASK) >> RTC_ALM_HOURMIN_ALM_HOUR_SHIFT);
422 datetime->minute = (uint8_t)temp & RTC_ALM_HOURMIN_ALM_MIN_MASK;
423
424 datetime->second = (uint8_t)(base->ALM_SECONDS) & RTC_ALM_SECONDS_ALM_SEC_MASK;
425 }
426
427 /*!
428 * brief Locks or unlocks IRTC registers for write access.
429 *
430 * note When the registers are unlocked, they remain in unlocked state for
431 * 2 seconds, after which they are locked automatically. After
432 * power-on-reset, the registers come out unlocked and they are locked
433 * automatically 15 seconds after power on.
434 *
435 * param base IRTC peripheral base address
436 * param lock true: Lock IRTC registers; false: Unlock IRTC registers.
437 *
438 * return kStatus_Success: if lock or unlock operation is successful
439 * kStatus_Fail: if lock or unlock operation fails even after multiple retry attempts
440 */
IRTC_SetWriteProtection(RTC_Type * base,bool lock)441 status_t IRTC_SetWriteProtection(RTC_Type *base, bool lock)
442 {
443 /* Retry before giving up */
444 uint8_t repeatProtectSequence = 0xFFU;
445 status_t status = kStatus_Success;
446
447 if (!lock)
448 {
449 /* Unlock IRTC registers */
450 while ((0U != (base->STATUS & (uint16_t)RTC_STATUS_WRITE_PROT_EN_MASK)) && (0U != repeatProtectSequence))
451 {
452 /* Access in 8-bit mode while storing the value */
453 *(__IO uint8_t *)(&base->STATUS) = 0U;
454 *(__IO uint8_t *)(&base->STATUS) = 0x40U;
455 *(__IO uint8_t *)(&base->STATUS) = 0xC0U;
456 *(__IO uint8_t *)(&base->STATUS) = 0x80U;
457 repeatProtectSequence--;
458 }
459 }
460 else
461 {
462 /* Lock IRTC registers */
463 while ((0U == ((base->STATUS & (uint16_t)RTC_STATUS_WRITE_PROT_EN_MASK) >> RTC_STATUS_WRITE_PROT_EN_SHIFT)) &&
464 (0U != repeatProtectSequence))
465 {
466 *(__IO uint8_t *)(&base->STATUS) = 0x80U;
467 repeatProtectSequence--;
468 }
469 }
470
471 /* Lock/unlock was not successful even after trying 256 times */
472 if (0U == repeatProtectSequence)
473 {
474 status = kStatus_Fail;
475 }
476
477 return status;
478 }
479
480 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
481 /*!
482 * brief Sets the IRTC daylight savings start and stop date and time.
483 *
484 * It also enables the daylight saving bit in the IRTC control register
485 *
486 * param base IRTC peripheral base address
487 * param datetime Pointer to a structure where the date and time details are stored.
488 */
IRTC_SetDaylightTime(RTC_Type * base,const irtc_daylight_time_t * datetime)489 void IRTC_SetDaylightTime(RTC_Type *base, const irtc_daylight_time_t *datetime)
490 {
491 assert(NULL != datetime);
492
493 /* Disable daylight saving time */
494 base->CTRL &= ~(uint16_t)RTC_CTRL_DST_EN_MASK;
495
496 /* Set the daylight saving time start month and end month value */
497 base->DST_MONTH =
498 RTC_DST_MONTH_DST_START_MONTH(datetime->startMonth) | RTC_DST_MONTH_DST_END_MONTH(datetime->endMonth);
499
500 /* Set the daylight saving time start day and end day value */
501 base->DST_DAY = RTC_DST_DAY_DST_START_DAY(datetime->startDay) | RTC_DST_DAY_DST_END_DAY(datetime->endDay);
502
503 /* Set the daylight saving time start hour and end hour value */
504 base->DST_HOUR = RTC_DST_HOUR_DST_START_HOUR(datetime->startHour) | RTC_DST_HOUR_DST_END_HOUR(datetime->endHour);
505
506 /* Enable daylight saving time */
507 base->CTRL |= RTC_CTRL_DST_EN_MASK;
508 }
509 #endif /* FSL_FEATURE_RTC_IS_SLAVE */
510
511 /*!
512 * brief Gets the IRTC daylight savings time and stores it in the given time structure.
513 *
514 * param base IRTC peripheral base address
515 * param datetime Pointer to a structure where the date and time details are stored.
516 */
IRTC_GetDaylightTime(RTC_Type * base,irtc_daylight_time_t * datetime)517 void IRTC_GetDaylightTime(RTC_Type *base, irtc_daylight_time_t *datetime)
518 {
519 assert(NULL != datetime);
520
521 uint16_t temp = base->DST_MONTH;
522
523 /* Get the daylight savings time start and end month value */
524 datetime->startMonth =
525 (uint8_t)((temp & RTC_DST_MONTH_DST_START_MONTH_MASK) >> RTC_DST_MONTH_DST_START_MONTH_SHIFT);
526 datetime->endMonth = (uint8_t)((temp & RTC_DST_MONTH_DST_END_MONTH_MASK) >> RTC_DST_MONTH_DST_END_MONTH_SHIFT);
527
528 /* Get the daylight savings time start and end day value */
529 temp = base->DST_DAY;
530 datetime->startDay = (uint8_t)((temp & RTC_DST_DAY_DST_START_DAY_MASK) >> RTC_DST_DAY_DST_START_DAY_SHIFT);
531 datetime->endDay = (uint8_t)((temp & RTC_DST_DAY_DST_END_DAY_MASK) >> RTC_DST_DAY_DST_END_DAY_SHIFT);
532
533 /* Get the daylight savings time start and end hour value */
534 temp = base->DST_HOUR;
535 datetime->startHour = (uint8_t)((temp & RTC_DST_HOUR_DST_START_HOUR_MASK) >> RTC_DST_HOUR_DST_START_HOUR_SHIFT);
536 datetime->endHour = (uint8_t)((temp & RTC_DST_HOUR_DST_END_HOUR_MASK) >> RTC_DST_HOUR_DST_END_HOUR_SHIFT);
537 }
538
539 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
540 /*!
541 * brief Enables the coarse compensation and sets the value in the IRTC compensation register.
542 *
543 * param base IRTC peripheral base address
544 * param compensationValue Compensation value is a 2's complement value.
545 * param compensationInterval Compensation interval.
546 */
IRTC_SetCoarseCompensation(RTC_Type * base,uint8_t compensationValue,uint8_t compensationInterval)547 void IRTC_SetCoarseCompensation(RTC_Type *base, uint8_t compensationValue, uint8_t compensationInterval)
548 {
549 uint16_t reg;
550
551 /* Set the compensation value and interval */
552 base->COMPEN = (uint16_t)compensationValue | ((uint16_t)compensationInterval << 8U);
553
554 /* Disable fine and enable coarse compensation */
555 reg = base->CTRL;
556 reg &= ~(uint16_t)RTC_CTRL_FINEEN_MASK;
557 reg |= RTC_CTRL_COMP_EN_MASK;
558 base->CTRL = reg;
559 }
560
561 /*!
562 * brief Enables the fine compensation and sets the value in the IRTC compensation register.
563 *
564 * param base The IRTC peripheral base address
565 * param integralValue Compensation integral value; twos complement value of the integer part
566 * param fractionValue Compensation fraction value expressed as number of clock cycles of a
567 * fixed 4.194304Mhz clock that have to be added.
568 * param accumulateFractional Flag indicating if we want to add to previous fractional part;
569 * true: Add to previously accumulated fractional part,
570 * false: Start afresh and overwrite current value
571 */
IRTC_SetFineCompensation(RTC_Type * base,uint8_t integralValue,uint8_t fractionValue,bool accumulateFractional)572 void IRTC_SetFineCompensation(RTC_Type *base, uint8_t integralValue, uint8_t fractionValue, bool accumulateFractional)
573 {
574 if (!accumulateFractional)
575 {
576 /* Disable compensation to clear previous accumulated fractional part */
577 base->CTRL &= ~(((uint16_t)1U << RTC_CTRL_COMP_EN_SHIFT) | ((uint16_t)1U << RTC_CTRL_FINEEN_SHIFT));
578 }
579
580 /* Set the compensation fractional and integral parts */
581 base->COMPEN = ((uint16_t)fractionValue & 0x7FU) | (((uint16_t)integralValue & 0xFU) << 12U);
582 /* Enable fine compensation */
583 base->CTRL |= (RTC_CTRL_COMP_EN_MASK | RTC_CTRL_FINEEN_MASK);
584 }
585 #endif /* FSL_FEATURE_RTC_IS_SLAVE */
586
587 #if !defined(FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE) || (!FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE)
588
589 /*!
590 * brief This function allows configuring the four tamper inputs.
591 *
592 * The function configures the filter properties for the three external tampers.
593 * It also sets up active/passive and direction of the tamper bits, which are not available
594 * on all platforms.
595 * note This function programs the tamper filter parameters. The user must gate the 32K clock to
596 * the RTC before calling this function. It is assumed that the time and date are set after this
597 * and the tamper parameters do not require to be changed again later.
598 *
599 * param base The IRTC peripheral base address
600 * param tamperNumber The IRTC tamper input to configure
601 * param tamperConfig The IRTC tamper properties
602 */
IRTC_SetTamperParams(RTC_Type * base,irtc_tamper_pins_t tamperNumber,const irtc_tamper_config_t * tamperConfig)603 void IRTC_SetTamperParams(RTC_Type *base, irtc_tamper_pins_t tamperNumber, const irtc_tamper_config_t *tamperConfig)
604 {
605 assert(NULL != tamperConfig);
606
607 uint16_t reg = 0;
608
609 #if defined(FSL_FEATURE_RTC_HAS_TAMPER_DIRECTION) && (FSL_FEATURE_RTC_HAS_TAMPER_DIRECTION)
610 reg = base->TAMPER_DIRECTION;
611 /* Set whether tamper pin is active or passive */
612 if (tamperConfig->activePassive)
613 {
614 /* In case of active tamper, set the direction */
615 reg |= (1U << tamperNumber);
616 if (tamperConfig->direction)
617 {
618 /* Tamper direction is output */
619 reg |= (1U << (RTC_TAMPER_DIRECTION_I_O_TAMP_SHIFT + tamperNumber));
620 }
621 else
622 {
623 /* Tamper direction is input */
624 reg &= ~(1U << (RTC_TAMPER_DIRECTION_I_O_TAMP_SHIFT + tamperNumber));
625 }
626 }
627 else
628 {
629 /* Passive tampers are input only and the direction bit is read only in this case */
630 reg &= ~(1U << tamperNumber);
631 }
632 base->TAMPER_DIRECTION = reg;
633 #endif /* FSL_FEATURE_RTC_HAS_TAMPER_DIRECTION */
634
635 /* Set the filter properties for the external tamper pins */
636 switch (tamperNumber)
637 {
638 case kIRTC_Tamper_0:
639 /* Set the pin for Tamper 0 */
640 #if !defined(FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE) || (!FSL_FEATURE_RTC_HAS_NO_CTRL2_WAKEUP_MODE)
641 base->CTRL2 &= ~(uint16_t)RTC_CTRL2_WAKEUP_MODE_MASK;
642 #endif
643 reg = base->FILTER01_CFG;
644 reg &= ~((uint16_t)RTC_FILTER01_CFG_POL0_MASK | (uint16_t)RTC_FILTER01_CFG_FIL_DUR0_MASK |
645 (uint16_t)RTC_FILTER01_CFG_CLK_SEL0_MASK);
646 reg |= (RTC_FILTER01_CFG_POL0(tamperConfig->pinPolarity) |
647 RTC_FILTER01_CFG_FIL_DUR0(tamperConfig->filterDuration) |
648 RTC_FILTER01_CFG_CLK_SEL0(tamperConfig->filterClk));
649 base->FILTER01_CFG = reg;
650 break;
651 case kIRTC_Tamper_1:
652 reg = base->FILTER01_CFG;
653 reg &= ~((uint16_t)RTC_FILTER01_CFG_POL1_MASK | (uint16_t)RTC_FILTER01_CFG_FIL_DUR1_MASK |
654 (uint16_t)RTC_FILTER01_CFG_CLK_SEL1_MASK);
655 reg |= (RTC_FILTER01_CFG_POL1(tamperConfig->pinPolarity) |
656 RTC_FILTER01_CFG_FIL_DUR1(tamperConfig->filterDuration) |
657 RTC_FILTER01_CFG_CLK_SEL1(tamperConfig->filterClk));
658 base->FILTER01_CFG = reg;
659 break;
660 #if defined(FSL_FEATURE_RTC_HAS_FILTER23_CFG) && FSL_FEATURE_RTC_HAS_FILTER23_CFG
661 case kIRTC_Tamper_2:
662 reg = base->FILTER23_CFG;
663 reg &= ~((uint16_t)RTC_FILTER23_CFG_POL2_MASK | (uint16_t)RTC_FILTER23_CFG_FIL_DUR2_MASK |
664 (uint16_t)RTC_FILTER23_CFG_CLK_SEL2_MASK);
665 reg |= (RTC_FILTER23_CFG_POL2(tamperConfig->pinPolarity) |
666 RTC_FILTER23_CFG_FIL_DUR2(tamperConfig->filterDuration) |
667 RTC_FILTER23_CFG_CLK_SEL2(tamperConfig->filterClk));
668 base->FILTER23_CFG = reg;
669 break;
670 case kIRTC_Tamper_3:
671 reg = base->FILTER23_CFG;
672 reg &= ~((uint16_t)RTC_FILTER23_CFG_POL3_MASK | (uint16_t)RTC_FILTER23_CFG_FIL_DUR3_MASK |
673 (uint16_t)RTC_FILTER23_CFG_CLK_SEL3_MASK);
674 reg |= (RTC_FILTER23_CFG_POL3(tamperConfig->pinPolarity) |
675 RTC_FILTER23_CFG_FIL_DUR3(tamperConfig->filterDuration) |
676 RTC_FILTER23_CFG_CLK_SEL3(tamperConfig->filterClk));
677 base->FILTER23_CFG = reg;
678 break;
679 #else
680 case kIRTC_Tamper_2:
681 reg = base->FILTER2_CFG;
682 reg &= ~((uint16_t)RTC_FILTER2_CFG_POL2_MASK | (uint16_t)RTC_FILTER2_CFG_FIL_DUR2_MASK |
683 (uint16_t)RTC_FILTER2_CFG_CLK_SEL2_MASK);
684 reg |= (RTC_FILTER2_CFG_POL2(tamperConfig->pinPolarity) |
685 RTC_FILTER2_CFG_FIL_DUR2(tamperConfig->filterDuration) |
686 RTC_FILTER2_CFG_CLK_SEL2(tamperConfig->filterClk));
687 base->FILTER2_CFG = reg;
688 break;
689 #endif
690
691 default:
692 /* Internal tamper, does not have filter configuration. */
693 break;
694 }
695 }
696
697 #endif
698
699 #if !defined(FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE) || (!FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE)
700 #if defined(FSL_FEATURE_RTC_HAS_TAMPER_QUEUE) && (FSL_FEATURE_RTC_HAS_TAMPER_QUEUE)
701
702 /*!
703 * brief This function reads the tamper timestamp and returns the associated tamper pin.
704 *
705 * The tamper timestamp has month, day, hour, minutes, and seconds. Ignore the year field as this
706 * information is not available in the tamper queue. The user should look at the RTC_YEARMON register
707 * for this because the expectation is that the queue is read at least once a year.
708 * Return the tamper pin number associated with the timestamp.
709 *
710 * param base The IRTC peripheral base address
711 * param tamperTimestamp The tamper timestamp
712 *
713 * return The tamper pin number
714 */
IRTC_ReadTamperQueue(RTC_Type * base,irtc_datetime_t * tamperTimestamp)715 uint8_t IRTC_ReadTamperQueue(RTC_Type *base, irtc_datetime_t *tamperTimestamp)
716 {
717 assert(NULL != tamperTimestamp);
718
719 /* Read the register 2 times to get a entry*/
720 uint16_t temp1 = base->TAMPER_QUEUE;
721 uint16_t temp2 = base->TAMPER_QUEUE;
722 uint8_t tamperNum;
723
724 /*
725 * Tamper queue does not store the year field as this value can be read from RTC_YEARMON.
726 * It is expected that the queue will be read at least once in a year.
727 */
728 tamperTimestamp->year = 0;
729 /* From the first read; TAMPER_DATA[4:0] is the hour field */
730 tamperTimestamp->hour = (uint8_t)temp1 & 0x1FU;
731 /* From the first read; TAMPER_DATA[9:5] is the day field */
732 tamperTimestamp->day = (uint8_t)(temp1 >> 5U) & 0x1FU;
733 /* From the first read; TAMPER_DATA[13:10] is the month field */
734 tamperTimestamp->month = (uint8_t)(temp1 >> 10U) & 0xFU;
735
736 /* From the second read; TAMPER_DATA[5:0] is the seconds field */
737 tamperTimestamp->second = (uint8_t)temp2 & 0x3FU;
738 /* From the second read; TAMPER_DATA[11:6] is the minutes field */
739 tamperTimestamp->minute = (uint8_t)(temp2 >> 6U) & 0x3FU;
740 /* From the second read; TAMPER_DATA[14:12] is the tamper index */
741 tamperNum = (uint8_t)(temp2 >> 12U) & 0x7U;
742
743 return tamperNum;
744 }
745
746 #endif /* FSL_FEATURE_RTC_HAS_TAMPER_QUEUE */
747 #endif /* FSL_FEATURE_RTC_HAS_NO_TAMPER_FEATURE */
748
749 /*!
750 * brief Select which clock to output from RTC.
751 *
752 * Select which clock to output from RTC for other modules to use inside SoC, for example,
753 * RTC subsystem needs RTC to output 1HZ clock for sub-second counter.
754 *
755 * param base IRTC peripheral base address
756 * param cloOut select clock to use for output
757 */
IRTC_ConfigClockOut(RTC_Type * base,irtc_clockout_sel_t clkOut)758 void IRTC_ConfigClockOut(RTC_Type *base, irtc_clockout_sel_t clkOut)
759 {
760 uint16_t ctrlVal = base->CTRL;
761
762 ctrlVal &= (uint16_t)(~RTC_CTRL_CLKOUT_MASK);
763
764 ctrlVal |= RTC_CTRL_CLKOUT((uint16_t)clkOut);
765
766 #if !(defined(FSL_FEATURE_RTC_IS_SLAVE) && (FSL_FEATURE_RTC_IS_SLAVE != 0U))
767 if (clkOut == kIRTC_ClkoutCoarse1Hz)
768 {
769 ctrlVal |= RTC_CTRL_COMP_EN_MASK;
770 }
771 else if (clkOut == kIRTC_ClkoutFine1Hz)
772 {
773 ctrlVal |= RTC_CTRL_FINEEN_MASK;
774 }
775 else
776 {
777 /* empty else */
778 }
779 #endif /* FSL_FEATURE_RTC_IS_SLAVE */
780
781 base->CTRL = ctrlVal;
782 }
783
784 #if defined(FSL_FEATURE_RTC_HAS_CLOCK_SELECT) && FSL_FEATURE_RTC_HAS_CLOCK_SELECT
785
786 /*!
787 * brief Select which clock is used by RTC.
788 *
789 * Select which clock is used by RTC to output to the peripheral
790 * and divided to generate a 512 Hz clock and a 1 Hz clock.
791 *
792 * param base IRTC peripheral base address
793 * param clkSelect select clock used by RTC
794 */
IRTC_ConfigClockSelect(RTC_Type * base,irtc_clock_select_t clkSelect)795 void IRTC_ConfigClockSelect(RTC_Type *base, irtc_clock_select_t clkSelect)
796 {
797 uint16_t ctrlVal = base->CTRL;
798
799 ctrlVal &= (uint16_t)(~RTC_CTRL_CLK_SEL_MASK);
800
801 ctrlVal |= RTC_CTRL_CLK_SEL((uint16_t)clkSelect);
802
803 base->CTRL = ctrlVal;
804 }
805
806 #endif /* FSL_FEATURE_RTC_HAS_CLOCK_SELECT */
807