S32 SDK
rtc_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 - 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
19 #include "rtc_hw_access.h"
20 
55 
60 
61 /* Table of month length (in days) for the Un-leap-year*/
62 static const uint8_t ULY[] = {0U, 31U, 28U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
63 
64 /* Table of month length (in days) for the Leap-year*/
65 static const uint8_t LY[] = {0U, 31U, 29U, 31U, 30U, 31U, 30U, 31U, 31U, 30U, 31U, 30U, 31U};
66 
67 /* Number of days from begin of the non Leap-year*/
68 static const uint16_t MONTH_DAYS[] = {0U, 0U, 31U, 59U, 90U, 120U, 151U, 181U, 212U, 243U, 273U, 304U, 334U};
69 
74 static struct
75 {
82 
83 
84 /*******************************************************************************
85  * Code
86  ******************************************************************************/
87 
88 /*FUNCTION**********************************************************************
89  *
90  * Function Name : RTC_DRV_Init
91  * Description : This function initializes the RTC instance with the settings
92  * provided by the user via the rtcUserCfg parameter. The user must ensure
93  * that clock is enabled for the RTC instance used. If the Control register
94  * is locked then this method returns STATUS_ERROR.
95  * In order to clear the CR Lock the user must perform a power-on reset.
96  * Return : STATUS_SUCCESS if the operation was successful, STATUS_ERROR
97  * if Control Register is locked.
98  * Implements : RTC_DRV_Init_Activity
99  *END**************************************************************************/
100 status_t RTC_DRV_Init(uint32_t instance, const rtc_init_config_t * const rtcUserCfg)
101 {
102  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
103  DEV_ASSERT(rtcUserCfg != NULL);
104 
105  status_t statusCode = STATUS_SUCCESS;
106  RTC_Type * basePtr = g_rtcBase[instance];
107 
108  /* Initialize runtime structure */
109  g_rtcRuntimeConfig[instance].alarmConfig = NULL;
110  g_rtcRuntimeConfig[instance].intConfig = NULL;
111  g_rtcRuntimeConfig[instance].secondsIntConfig = NULL;
112  g_rtcRuntimeConfig[instance].isAlarmTimeNew = false;
113 
114  /* Check if the control register is locked. If true, the method cannot
115  * continue.
116  */
117  if (RTC_IsRegisterLocked(basePtr, RTC_CTRL_REG_LOCK) == true)
118  {
119  /* Return status code */
120  statusCode = STATUS_ERROR;
121  }
122  else
123  {
124  /* Disable the RTC instance IRQ to perform a software reset */
126  /* Perform a software reset */
127  RTC_SoftwareReset(basePtr);
128  /* Clear the pending interrupt generated by the software reset */
129  INT_SYS_ClearPending(g_rtcIrqNumbers[instance]);
130  /* Setup the RTC instance as configured in the structure */
131  (void)RTC_ConfigureClockOut(basePtr, rtcUserCfg->clockOutConfig);
132  RTC_SetLPOSelect(basePtr, rtcUserCfg->clockSelect);
133  RTC_SetUpdateMode(basePtr, rtcUserCfg->updateEnable);
134  RTC_SetNonSupervisorAccess(basePtr, rtcUserCfg->nonSupervisorAccessEnable);
135  /* Check if compensation needs to be updated */
136  if (rtcUserCfg->compensation != 0)
137  {
138  RTC_SetTimeCompensation(basePtr,
139  rtcUserCfg->compensation,
140  rtcUserCfg->compensationInterval);
141  }
142  }
143 
144  /* Return the exit code */
145  return statusCode;
146 }
147 
148 /*FUNCTION**********************************************************************
149  *
150  * Function Name : RTC_DRV_Deinit
151  * Description : This function deinitializes the RTC instance.
152  * If the Control register is locked then this method returns
153  * STATUS_ERROR.
154  * In order to clear the CR Lock the user must perform a power-on reset.
155  * Return : STATUS_SUCCESS if the operation was successful or
156  * STATUS_ERROR if Control register is locked.
157  * Implements : RTC_DRV_Deinit_Activity
158  *END**************************************************************************/
159 status_t RTC_DRV_Deinit(uint32_t instance)
160 {
161  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
162 
163  status_t statusCode = STATUS_SUCCESS;
164 
165  /* Check if the control register is locked. If true, the method cannot
166  * continue.
167  */
168  if (RTC_IsRegisterLocked(g_rtcBase[instance], RTC_CTRL_REG_LOCK) == true)
169  {
170  statusCode = STATUS_ERROR;
171  }
172  else
173  {
174  /* Disable RTC instance's interrupts */
177  /* Perform a software reset */
178  RTC_SoftwareReset(g_rtcBase[instance]);
179  /* Clear the pending interrupt generated by the software reset */
180  INT_SYS_ClearPending(g_rtcIrqNumbers[instance]);
181  }
182 
183  /* Return the exit code */
184  return statusCode;
185 }
186 
187 /*FUNCTION**********************************************************************
188  *
189  * Function Name : RTC_DRV_GetDefaultConfig
190  * Description : This function will set the default configuration
191  * values into the structure passed as a parameter
192  * Return : None
193  * Implements : RTC_DRV_GetDefaultConfig_Activity
194  *END**************************************************************************/
196 {
197  DEV_ASSERT(config != NULL);
198 
201  config->updateEnable = true;
202  config->nonSupervisorAccessEnable = true;
203  config->compensation = 0;
204  config->compensationInterval = 0U;
205 }
206 
207 /*FUNCTION**********************************************************************
208  *
209  * Function Name : RTC_DRV_CanWriteTCE
210  * Description : This function checks the following conditions to find if the
211  * Time Counter Enable bit is writable.
212  * - if Update Mode bitfield if 1 and:
213  * - Time is invalid or
214  * - Time Seconds Register has overflowed or
215  * - Time Counter is disabled,
216  * then the TCE bit can be set even if Status Register is locked.
217  *
218  * This method is a private one, it is used only by the API internally.
219  * Return : True if the TCE can be set, otherwise false
220  *END**************************************************************************/
221 static bool RTC_DRV_CanWriteTCE(uint32_t instance)
222 {
223  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
224 
225  bool result = false;
226  bool tifFlagSet;
227  bool tofFlagSet;
228  bool tceFlagSet;
229 
230  /* Check if the status register is locked */
231  if (RTC_IsRegisterLocked(g_rtcBase[instance], RTC_STATUS_REG_LOCK) == false)
232  {
233  result = true;
234  }
235  /* Get the Update Mode bit */
236  else if (RTC_GetUpdateMode(g_rtcBase[instance]))
237  {
238  tifFlagSet = RTC_GetTimeInvalidFlag(g_rtcBase[instance]);
239  tofFlagSet = RTC_GetTimeOverflowFlag(g_rtcBase[instance]);
240  tceFlagSet = RTC_GetTimeCounterEnable(g_rtcBase[instance]);
241 
242  /* Check for the specified conditions */
243  if ((tifFlagSet == true) || (tofFlagSet == true) || (tceFlagSet == false))
244  {
245  result = true;
246  }
247  }
248  else
249  {
250  result = false;
251  }
252 
253  /* Return the exit code */
254  return result;
255 }
256 
257 /*FUNCTION**********************************************************************
258  *
259  * Function Name : RTC_DRV_StartCounter
260  * Description : Start RTC instance counter. Before calling this function the user
261  * should use RTC_DRV_SetTimeDate to configure the start time
262  * Return : STATUS_SUCCESS if the operation was successful, STATUS_ERROR
263  * if the counter cannot be enabled or is already enabled.
264  * Implements : RTC_DRV_StartCounter_Activity
265  *END**************************************************************************/
266 status_t RTC_DRV_StartCounter(uint32_t instance)
267 {
268  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
269 
270  status_t statusCode = STATUS_SUCCESS;
271 
272  /* Check if the TCE is writable and return corresponding status
273  * if it is not
274  */
275  if (RTC_DRV_CanWriteTCE(instance) == false)
276  {
277  statusCode = STATUS_ERROR;
278  }
279  else
280  {
281  /* Enable the counter */
282  statusCode = RTC_Enable(g_rtcBase[instance]);
283  }
284 
285  /* Return the exit code */
286  return statusCode;
287 }
288 
289 /*FUNCTION**********************************************************************
290  *
291  * Function Name : RTC_DRV_StopCounter
292  * Description : This function disables the RTC instance counter.
293  * Return : STATUS_SUCCESS if the operation was successful, STATUS_ERROR
294  * if the counter could not be stopped.
295  * Implements : RTC_DRV_StopCounter_Activity
296  *END**************************************************************************/
297 status_t RTC_DRV_StopCounter(uint32_t instance)
298 {
299  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
300 
301  status_t statusCode = STATUS_SUCCESS;
302 
303  /* Check if the TCE is writable */
304  if (RTC_DRV_CanWriteTCE(instance) == false)
305  {
306  statusCode = STATUS_ERROR;
307  }
308  else
309  {
310  /* Disable the RTC instance */
311  statusCode = RTC_Disable(g_rtcBase[instance]);
312  }
313 
314  /* Return the exit code */
315  return statusCode;
316 }
317 
318 /*FUNCTION**********************************************************************
319  *
320  * Function Name : RTC_DRV_GetCurrentTimeDate
321  * Description : This retrieves the current time and date from the RTC instance.
322  * Data is saved into currentTime, which is a pointer of the rtc_timedate_t
323  * type.
324  * Return : STATUS_SUCCESS if the operation was successful, STATUS_ERROR
325  * if there was a problem.
326  * Implements : RTC_DRV_GetCurrentTimeDate_Activity
327  *END**************************************************************************/
328 status_t RTC_DRV_GetCurrentTimeDate(uint32_t instance, rtc_timedate_t * const currentTime)
329 {
330  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
331  DEV_ASSERT(currentTime != NULL);
332 
333  /* Declare local variables */
334  status_t statusCode = STATUS_SUCCESS;
335  uint32_t seconds;
336  uint32_t tempSeconds;
337 
338  /* Make two consecutive reads to ensure that the read was not
339  * done when the counter is incrementing.
340  * This is recommended in the reference manual.
341  */
342  tempSeconds = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
343  seconds = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
344  /* If the read was done when the counter was incrementing,
345  * try and read again.
346  */
347  if (tempSeconds != seconds)
348  {
349  /* Reinitialize the temporary variable */
350  tempSeconds = 0UL;
351  /* Get the current time again */
352  tempSeconds = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
353  if (tempSeconds != seconds)
354  {
355  /* If the last two reads are not equal, there is an error */
356  statusCode = STATUS_ERROR;
357  }
358  else
359  {
360  /* Convert the current time from seconds to time date structure */
361  RTC_DRV_ConvertSecondsToTimeDate(&seconds, currentTime);
362  }
363  }
364  else
365  {
366  /* Convert the current time from seconds to time date structure */
367  RTC_DRV_ConvertSecondsToTimeDate(&seconds, currentTime);
368  }
369 
370  /* Return the exit code */
371  return statusCode;
372 }
373 
374 /*FUNCTION**********************************************************************
375  *
376  * Function Name : RTC_DRV_SetTimeDate
377  * Description : This modifies the time and date of the RTC instance.
378  * Return : STATUS_SUCCESS if the operation was successful, STATUS_ERROR
379  * if the time provided was invalid or if the counter was not
380  * stopped.
381  * Implements : RTC_DRV_SetTimeDate_Activity
382  *END**************************************************************************/
383 status_t RTC_DRV_SetTimeDate(uint32_t instance, const rtc_timedate_t * const time)
384 {
385  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
386 
387  /* Declare local variables */
388  status_t statusCode = STATUS_SUCCESS;
389  uint32_t seconds = 0;
390 
391  /* Check if the time is in the correct format */
392  if (RTC_DRV_IsTimeDateCorrectFormat(time) == false)
393  {
394  /* Set the exit code to error */
395  statusCode = STATUS_ERROR;
396  }
397  /* Check if the TCE bit is writable */
398  else if (RTC_DRV_CanWriteTCE(instance) == false)
399  {
400  /* Set the exit code to locked */
401  statusCode = STATUS_ERROR;
402  }
403  else
404  {
405  /* Convert the desired time to seconds */
406  RTC_DRV_ConvertTimeDateToSeconds(time, &seconds);
407  /* Set the time */
408  (void)RTC_SetTimeSecondsRegister(g_rtcBase[instance], seconds);
409  }
410 
411  /* Return the exit code */
412  return statusCode;
413 }
414 
415 /*FUNCTION**********************************************************************
416  *
417  * Function Name : RTC_DRV_ConfigureRegisterLock
418  * Description : This method configures register lock for the corresponding
419  * RTC instance. Remember that all the registers are unlocked
420  * only by software reset or power on reset.
421  * (Except for CR that is unlocked only by POR).
422  * Return : STATUS_SUCCESS if the operation was successful,
423  * STATUS_ERROR if the Lock Register is locked.
424  * Implements : RTC_DRV_ConfigureRegisterLock_Activity
425  *END**************************************************************************/
426 status_t RTC_DRV_ConfigureRegisterLock(uint32_t instance, const rtc_register_lock_config_t * const lockConfig)
427 {
428  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
429  DEV_ASSERT(lockConfig != NULL);
430 
431  /* Declare local variables */
432  status_t statusCode = STATUS_SUCCESS;
433 
434  /* Lock the requested registers, but always the Lock register last,
435  * otherwise other registers can not be locked.
436  */
437 
438  /* Configure Control register lock */
439  if (lockConfig->controlRegisterLock)
440  {
441  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_CTRL_REG_LOCK);
442  }
443  /* Configure Status register lock */
444  if (lockConfig->statusRegisterLock)
445  {
446  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_STATUS_REG_LOCK);
447  }
448  /* Configure Time Compensation register lock */
449  if (lockConfig->timeCompensationRegisterLock)
450  {
451  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_TCL_REG_LOCK);
452  }
453  /* Configure Lock register lock */
454  if (lockConfig->lockRegisterLock)
455  {
456  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_LOCK_REG_LOCK);
457  }
458 
459  /* Return the exit code */
460  return statusCode;
461 }
462 
463 /*FUNCTION**********************************************************************
464  *
465  * Function Name : RTC_DRV_GetRegisterLock
466  * Description : This retrieves the register lock configuration from the RTC
467  * instance.
468  * Data is stored in the structure referenced by the lockConfig
469  * pointer.
470  * Return : None
471  * Implements : RTC_DRV_GetRegisterLock_Activity
472  *END**************************************************************************/
473 void RTC_DRV_GetRegisterLock(uint32_t instance, rtc_register_lock_config_t * const lockConfig)
474 {
475  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
476  DEV_ASSERT(lockConfig != NULL);
477 
478  /* Get the configuration of the register lock */
479 
480  /* For the Lock Register */
481  lockConfig->lockRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_LOCK_REG_LOCK);
482  /* For the Control Register */
483  lockConfig->controlRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_CTRL_REG_LOCK);
484  /* For the Status Register */
485  lockConfig->statusRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_STATUS_REG_LOCK);
486  /* For the Time Compensation Register */
487  lockConfig->timeCompensationRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_TCL_REG_LOCK);
488 }
489 
490 /*FUNCTION**********************************************************************
491  *
492  * Function Name : RTC_DRV_ConfigureTimeCompensation
493  * Description : This method configures time compensation. Data is passed by
494  * the compInterval and compensation parameters.
495  * For more details regarding coefficient calculation see the
496  * Reference Manual.
497  * Return : STATUS_SUCCESS if the operation was successful,
498  * STATUS_ERROR if the TC Register is locked.
499  * Implements : RTC_DRV_ConfigureTimeCompensation_Activity
500  *END**************************************************************************/
501 status_t RTC_DRV_ConfigureTimeCompensation(uint32_t instance, uint8_t compInterval, int8_t compensation)
502 {
503  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
504 
505  /* Declare local variables */
506  status_t statusCode = STATUS_SUCCESS;
507 
508  /* Check if the TCR is locked */
509  if (RTC_IsRegisterLocked(g_rtcBase[instance], RTC_TCL_REG_LOCK) == true)
510  {
511  /* Set the exit code to locked */
512  statusCode = STATUS_ERROR;
513  }
514  else
515  {
516  /* Set the corresponding values for compensation and compensation
517  * interval.
518  */
519  RTC_SetTimeCompensation(g_rtcBase[instance], compensation, compInterval);
520  }
521 
522  /* Return the exit code */
523  return statusCode;
524 }
525 
526 /*FUNCTION**********************************************************************
527  *
528  * Function Name : RTC_DRV_GetTimeCompensation
529  * Description : This retrieves the time compensation coefficients and saves
530  * them on the variables referenced by the parameters.
531  * Return : None
532  * Implements : RTC_DRV_GetTimeCompensation_Activity
533  *END**************************************************************************/
534 void RTC_DRV_GetTimeCompensation(uint32_t instance, uint8_t * compInterval, int8_t * compensation)
535 {
536  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
537  DEV_ASSERT(compInterval != NULL);
538  DEV_ASSERT(compensation != NULL);
539 
540  /* Get the compensation interval */
541  RTC_GetCurrentTimeCompensation(g_rtcBase[instance], compensation, compInterval);
542 }
543 
544 /*FUNCTION**********************************************************************
545  *
546  * Function Name : RTC_DRV_ConvertSecondsToTimeDate
547  * Description : This method converts seconds into time-date format.
548  * Return : None
549  * Implements : RTC_DRV_ConvertSecondsToTimeDate_Activity
550  *END**************************************************************************/
551 void RTC_DRV_ConvertSecondsToTimeDate(const uint32_t * const seconds, rtc_timedate_t * const timeDate)
552 {
553  DEV_ASSERT(seconds != NULL);
554  DEV_ASSERT(timeDate != NULL);
555 
556  /* Declare the variables needed */
557  uint8_t i;
558  bool yearLeap = false;
559  uint32_t numberOfDays = 0U;
560  uint32_t tempSeconds;
561  uint16_t daysInYear;
562 
563  /* Because the starting year(1970) is not leap, set the daysInYear
564  * variable with the number of the days in a normal year
565  */
566  daysInYear = DAYS_IN_A_YEAR;
567 
568  /* Set the year to the beginning of the range */
569  timeDate->year = YEAR_RANGE_START;
570 
571  /* Get the number of days */
572  numberOfDays = (*seconds) / SECONDS_IN_A_DAY;
573  /* Get the number of seconds remaining */
574  tempSeconds = (*seconds) % SECONDS_IN_A_DAY;
575 
576  /* Get the current hour */
577  timeDate->hour = (uint16_t)(tempSeconds / SECONDS_IN_A_HOUR);
578  /* Get the remaining seconds */
579  tempSeconds = tempSeconds % SECONDS_IN_A_HOUR;
580  /* Get the minutes */
581  timeDate->minutes = (uint16_t)(tempSeconds / SECONDS_IN_A_MIN);
582  /* Get seconds */
583  timeDate->seconds = (uint8_t)(tempSeconds % SECONDS_IN_A_MIN);
584 
585  /* Get the current year */
586  while (numberOfDays >= daysInYear)
587  {
588  /* Increment year if the number of days is greater than the ones in
589  * one year
590  */
591  timeDate->year++;
592  /* Subtract the number of the days */
593  numberOfDays -= daysInYear;
594 
595  /* Check if the year is leap or unleap */
596  if (!RTC_DRV_IsYearLeap(timeDate->year))
597  {
598  /* Set the number of non leap year to the current year number
599  * of days.
600  */
601  daysInYear = DAYS_IN_A_YEAR;
602  }
603  else
604  {
605  /* Set the number of leap year to the current year number
606  * of days.
607  */
608  daysInYear = DAYS_IN_A_LEAP_YEAR;
609  }
610  }
611 
612  /* Add the current day */
613  numberOfDays += 1U;
614 
615  /* Check if the current year is leap */
616  yearLeap = RTC_DRV_IsYearLeap(timeDate->year);
617 
618  /* Get the month */
619  for (i = 1U; i <= 12U; i++)
620  {
621  uint32_t daysInCurrentMonth = ((yearLeap == true) ? (uint32_t)LY[i] : (uint32_t)ULY[i]);
622  if (numberOfDays <= daysInCurrentMonth)
623  {
624  timeDate->month = (uint16_t)i;
625  break;
626  }
627  else
628  {
629  numberOfDays -= daysInCurrentMonth;
630  }
631 
632  }
633 
634  /* Set the current day */
635  timeDate->day = (uint16_t)numberOfDays;
636 }
637 
638 /*FUNCTION**********************************************************************
639  *
640  * Function Name : RTC_DRV_ConvertTimeDateToSeconds
641  * Description : This method converts time-date into seconds.
642  * Return : None
643  * Implements : RTC_DRV_ConvertTimeDateToSeconds_Activity
644  *END**************************************************************************/
645 void RTC_DRV_ConvertTimeDateToSeconds(const rtc_timedate_t * const timeDate, uint32_t * const seconds)
646 {
647  DEV_ASSERT(seconds != NULL);
648  DEV_ASSERT(timeDate != NULL);
649 
650  /* Declare local variables */
651  uint16_t year;
652 
653  /* Convert years to seconds */
654  (*seconds) = (uint32_t)(DAYS_IN_A_YEAR * (uint32_t)(SECONDS_IN_A_DAY));
655  (*seconds) *= ((uint32_t)timeDate->year - YEAR_RANGE_START);
656 
657  /* Add the seconds from the leap years */
658  for (year = YEAR_RANGE_START; year < timeDate->year; year++)
659  {
660  if (RTC_DRV_IsYearLeap(year))
661  {
662  (*seconds) += SECONDS_IN_A_DAY;
663  }
664  }
665 
666  /* If the current year is leap and 29th of February has passed, add
667  * another day to seconds passed.
668  */
669  if ((RTC_DRV_IsYearLeap(year)) && (timeDate->month > 2U))
670  {
671  (*seconds) += SECONDS_IN_A_DAY;
672  }
673 
674  /* Add the rest of the seconds from the current month */
675  (*seconds) += MONTH_DAYS[timeDate->month] * SECONDS_IN_A_DAY;
676  /* Add the rest of the seconds from the current day */
677  (*seconds) += (uint32_t)(((uint32_t)timeDate->day - 1U) * (uint32_t)SECONDS_IN_A_DAY);
678  /* Add the rest of the seconds from the current time */
679  (*seconds) += (uint32_t)(((uint32_t)timeDate->hour * SECONDS_IN_A_HOUR) + \
680  ((uint32_t)timeDate->minutes * SECONDS_IN_A_MIN) + \
681  (uint32_t)timeDate->seconds);
682 }
683 
684 /*FUNCTION**********************************************************************
685  *
686  * Function Name : RTC_DRV_IsTimeDateCorrectFormat
687  * Description : This method checks if date-time structure is in a correct
688  * format
689  * Return : True if the following conditions are met:
690  * - is a valid year, month and date
691  * - is a valid time format
692  * False otherwise
693  * Implements : RTC_DRV_IsTimeDateCorrectFormat_Activity
694  *END**************************************************************************/
696 {
697  DEV_ASSERT(timeDate != NULL);
698 
699  /* Declare local variables */
700  bool returnCode = true;
701  const uint8_t * pDays;
702 
703  /* Set the days-in-month table for the corresponding year */
704  pDays = RTC_DRV_IsYearLeap(timeDate->year) ? (LY) : (ULY);
705 
706  /* Check if the time and date are in the correct ranges */
707  if ((timeDate->year < YEAR_RANGE_START) || (timeDate->year > YEAR_RANGE_END)
708  || (timeDate->month < 1U) || (timeDate->month > 12U)
709  || (timeDate->day < 1U) || (timeDate->day > 31U)
710  || (timeDate->hour > HOURS_IN_A_DAY)
711  || (timeDate->minutes > MINS_IN_A_HOUR) || (timeDate->seconds > SECONDS_IN_A_MIN))
712  {
713  returnCode = false;
714  }
715  /* Check if the day is a valid day from the corresponding month */
716  else if (timeDate->day > pDays[timeDate->month])
717  {
718  returnCode = false;
719  }
720  else
721  {
722  returnCode = true;
723  }
724 
725  /* Return the exit code */
726  return returnCode;
727 }
728 
729 /*FUNCTION**********************************************************************
730  *
731  * Function Name : RTC_DRV_IsYearLeap
732  * Description : This method checks if the year passed as a parameter is a leap
733  * one.
734  * Return : True if the year is leap, false if otherwise.
735  * Implements : RTC_DRV_IsYearLeap_Activity
736  *END**************************************************************************/
737 bool RTC_DRV_IsYearLeap(uint16_t year)
738 {
739  bool isYearLeap = false;
740 
741  if ((year % 4U) > 0U)
742  {
743  isYearLeap = false;
744  }
745  else if ((year % 100U) > 0U)
746  {
747  isYearLeap = true;
748  }
749  else if ((year % 400U) > 0U)
750  {
751  isYearLeap = false;
752  }
753  else
754  {
755  isYearLeap = true;
756  }
757 
758  /* Return the exit code */
759  return isYearLeap;
760 }
761 
762 
763 /*FUNCTION**********************************************************************
764  *
765  * Function Name : RTC_DRV_IRQHandler
766  * Description : This method is the API's Interrupt handler for generic and
767  * alarm IRQ. It will handle the alarm repetition and calls the
768  * user callbacks if they are not NULL.
769  * Return : None
770  *
771  * Implements : RTC_DRV_IRQHandler_Activity
772  *END**************************************************************************/
773 void RTC_DRV_IRQHandler(uint32_t instance)
774 {
775  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
776 
777  uint32_t tempSeconds;
778  /* Get the alarm configuration */
779  rtc_alarm_config_t * alarmConfig = g_rtcRuntimeConfig[instance].alarmConfig;
780  /* Get the fault interrupt configuration */
781  const rtc_interrupt_config_t * const intConfig = g_rtcRuntimeConfig[instance].intConfig;
782 
783  /* Check if an alarm has occurred */
784  if (RTC_GetTimeAlarmFlag(g_rtcBase[instance]) == true)
785  {
786  /* If the alarm interrupt configuration has been defined process the
787  * alarm IRQ
788  */
789  if ((alarmConfig != NULL))
790  {
791  /* If recurrence is enabled modify the alarm register to the next
792  * alarm.
793  */
794  if ((alarmConfig->numberOfRepeats > 0UL) || (alarmConfig->repeatForever == true))
795  {
796  tempSeconds = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
797  tempSeconds += alarmConfig->repetitionInterval - 1UL;
798 
799  RTC_SetTimeAlarmRegister(g_rtcBase[instance], tempSeconds);
800 
801  g_rtcRuntimeConfig[instance].isAlarmTimeNew = true;
802  /* If the alarm repeats forever, set number of repeats to 0
803  * to avoid an accidental trigger of the core overflow flag
804  */
805  alarmConfig->numberOfRepeats = (alarmConfig->repeatForever == false) ? (alarmConfig->numberOfRepeats - 1UL) : 0UL;
806  }
807  else
808  {
809  /* If the alarm does not repeat, write 0 to TAR to clear the
810  * alarm flag.
811  */
812  RTC_SetTimeAlarmRegister(g_rtcBase[instance], 0UL);
813  /* Set the internal variabile which indicates that a new alarm is enabled to false */
814  g_rtcRuntimeConfig[instance].isAlarmTimeNew = false;
815  }
816  /* If the user has defined a callback, call it */
817  if (alarmConfig->alarmCallback != NULL)
818  {
819  alarmConfig->alarmCallback(alarmConfig->callbackParams);
820  }
821  }
822  }
823  /* If the IRQ is not caused by the alarm then call the user callback if
824  * defined.
825  */
826  else if ((intConfig->rtcCallback != NULL) && (intConfig != NULL))
827  {
828  intConfig->rtcCallback(intConfig->callbackParams);
829  }
830  else
831  {
832  /* Do nothing*/
833  ;
834  }
835 }
836 
837 /*FUNCTION**********************************************************************
838  *
839  * Function Name : RTC_DRV_SecondsIRQHandler
840  * Description : This method is the API's Interrupt handler for RTC Second
841  * interrupt. This ISR will call the user callback if defined.
842  * Return : None
843  * Implements : RTC_DRV_SecondsIRQHandler_Activity
844  *END**************************************************************************/
845 void RTC_DRV_SecondsIRQHandler(uint32_t instance)
846 {
847  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
848 
849  const rtc_seconds_int_config_t * const intCfg = g_rtcRuntimeConfig[instance].secondsIntConfig;
850 
851  /* If the interrupt is configured by the driver API and the user callback
852  * is not NULL, then call it.
853  */
854  if ((intCfg != NULL) && (intCfg->rtcSecondsCallback != NULL))
855  {
856  intCfg->rtcSecondsCallback(intCfg->secondsCallbackParams);
857  }
858 }
859 
860 /*FUNCTION**********************************************************************
861  *
862  * Function Name : RTC_DRV_ConfigureFaultInt
863  * Description : This method configures fault interrupts such as:
864  * - Time Overflow Interrupt
865  * - Time Invalid Interrupt
866  * with the user provided configuration struct intConfig.
867  * Return : None
868  * Implements : RTC_DRV_ConfigureFaultInt_Activity
869  *END**************************************************************************/
871 {
872  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
873  DEV_ASSERT(intConfig != NULL);
874 
875  /* Disable the IRQ to avoid accidental interrupt requests */
877  /* Save the configuration into the instance's runtime structure */
878  g_rtcRuntimeConfig[instance].intConfig = intConfig;
879 
880  /* Enable or disable selected interrupts */
881  RTC_SetTimeOverflowIntEnable(g_rtcBase[instance], intConfig->overflowIntEnable);
882 
883  RTC_SetTimeInvalidIntEnable(g_rtcBase[instance], intConfig->timeInvalidIntEnable);
884 
885  /* After the configuration is done, re-enable the interrupt in NVIC */
887 }
888 
889 /*FUNCTION**********************************************************************
890  *
891  * Function Name : RTC_DRV_ConfigureSecondsInt
892  * Description : This method configures the Time Seconds Interrupt with the
893  * configuration from the intConfig parameter.
894  * Return : None
895  * Implements : RTC_DRV_ConfigureSecondsInt_Activity
896  *END**************************************************************************/
898 {
899  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
900  DEV_ASSERT(intConfig != NULL);
901 
902  /* Disable the IRQ to avoid accidental interrupt requests */
904  /* Disable the IRQ to avoid accidental interrupt requests */
905  g_rtcRuntimeConfig[instance].secondsIntConfig = intConfig;
906 
907  /* Configure the interrupt frequency */
908  RTC_SetTimeSecondsIntConf(g_rtcBase[instance], intConfig->secondIntConfig);
909 
910  /* Enable or disable Time Seconds interrupt */
911  RTC_SetTimeSecondsIntEnable(g_rtcBase[instance], intConfig->secondIntEnable);
912 
913  /* After the configuration is done, re-enable the interrupt in NVIC */
915 }
916 
917 /*FUNCTION**********************************************************************
918  *
919  * Function Name : RTC_DRV_ConfigureAlarm
920  * Description : This method configures the alarm with the
921  * configuration from the alarmConfig parameter.
922  *
923  * Return : STATUS_SUCCESS if the configuration is successful or
924  * STATUS_ERROR if the alarm time is invalid.
925  * Implements : RTC_DRV_ConfigureAlarm_Activity
926  *END**************************************************************************/
928 {
929  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
930  DEV_ASSERT(alarmConfig != NULL);
931 
932  status_t statusCode = STATUS_SUCCESS;
933  uint32_t alarmTime;
934  uint32_t currentTime;
935 
936  /* Check if the alarm time is in a correct format */
937  if (RTC_DRV_IsTimeDateCorrectFormat(&(alarmConfig->alarmTime)) == true)
938  {
939  /* Convert the time date to seconds */
940  RTC_DRV_ConvertTimeDateToSeconds(&(alarmConfig->alarmTime), &alarmTime);
941  /* Get current time in seconds */
942  currentTime = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
943 
944  /* Check if the alarm time is greater than current time */
945  if(alarmTime > currentTime)
946  {
947  /* Disable the IRQ to avoid accidental interrupt requests */
949  g_rtcRuntimeConfig[instance].alarmConfig = alarmConfig;
950 
951  /* Write alarm time into Time Alarm Register */
952  RTC_SetTimeAlarmRegister(g_rtcBase[instance], alarmTime);
953  /* Enable/disable interrupt source based on the configuration */
954  RTC_SetTimeAlarmIntEnable(g_rtcBase[instance], alarmConfig->alarmIntEnable);
955  /* After the configuration is done, re-enable the interrupt in
956  * NVIC.
957  */
959  }
960  else
961  {
962  statusCode = STATUS_ERROR;
963  }
964  }
965  else
966  {
967  statusCode = STATUS_ERROR;
968  }
969 
970  /* Return the exit code */
971  return statusCode;
972 }
973 
974 /*FUNCTION**********************************************************************
975  *
976  * Function Name : RTC_DRV_GetAlarmConfig
977  * Description : This method retrieves the alarm configuration.
978  * Return : None
979  * Implements : RTC_DRV_GetAlarmConfig_Activity
980  *END**************************************************************************/
982 {
983  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
984  DEV_ASSERT(alarmConfig != NULL);
985 
986  *alarmConfig = *(g_rtcRuntimeConfig[instance].alarmConfig);
987 }
988 
989 /*FUNCTION**********************************************************************
990  *
991  * Function Name : RTC_DRV_IsAlarmPending
992  * Description : This method specifies if an alarm has occurred.
993  * Return : True if an alarm has occurred, false if not.
994  * Implements : RTC_DRV_IsAlarmPending_Activity
995  *END**************************************************************************/
996 bool RTC_DRV_IsAlarmPending(uint32_t instance)
997 {
998  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
999 
1000  /* Return the exit code */
1001  return RTC_GetTimeAlarmFlag(g_rtcBase[instance]);
1002 }
1003 
1004 /*FUNCTION**********************************************************************
1005  *
1006  * Function Name : RTC_DRV_GetNextAlarmTime
1007  * Description : This method retrieves the next alarm time;
1008  * Return : STATUS_SUCCESS if the next alarm time is valid
1009  * STATUS_ERROR if there is no new alarm
1010  *
1011  * Implements : RTC_DRV_GetNextAlarmTime_Activity
1012  *END**************************************************************************/
1013 status_t RTC_DRV_GetNextAlarmTime(uint32_t instance, rtc_timedate_t * const alarmTime)
1014 {
1015  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
1016  DEV_ASSERT(alarmTime != NULL);
1017 
1018  status_t statusCode = STATUS_SUCCESS;
1019  uint32_t alarmInSec;
1020 
1021  if (g_rtcRuntimeConfig[instance].isAlarmTimeNew == true)
1022  {
1023  alarmInSec = RTC_GetTimeAlarmRegister(g_rtcBase[instance]);
1024  RTC_DRV_ConvertSecondsToTimeDate(&alarmInSec, alarmTime);
1025  }
1026  else
1027  {
1028  statusCode = STATUS_ERROR;
1029  }
1030  /* Return the exit code */
1031 
1032  return statusCode;
1033 }
1034 /*******************************************************************************
1035  * EOF
1036  ******************************************************************************/
rtc_interrupt_config_t * intConfig
Definition: rtc_driver.c:78
#define RTC_SECONDS_IRQS_CH_COUNT
Definition: S32K142.h:8936
uint16_t day
Definition: rtc_driver.h:103
uint16_t month
Definition: rtc_driver.h:102
bool nonSupervisorAccessEnable
Definition: rtc_driver.h:120
RTC Initialization structure Implements : rtc_init_config_t_Class.
Definition: rtc_driver.h:113
#define SECONDS_IN_A_DAY
Definition: rtc_driver.h:36
uint16_t year
Definition: rtc_driver.h:101
#define DAYS_IN_A_YEAR
Definition: rtc_driver.h:41
status_t RTC_DRV_StartCounter(uint32_t instance)
Start RTC instance counter. Before calling this function the user should use RTC_DRV_SetTimeDate to c...
Definition: rtc_driver.c:266
status_t RTC_DRV_StopCounter(uint32_t instance)
Disable RTC instance counter.
Definition: rtc_driver.c:297
RTC interrupt configuration. It is used to configure interrupt other than Time Alarm and Time Seconds...
Definition: rtc_driver.h:143
status_t RTC_DRV_ConfigureRegisterLock(uint32_t instance, const rtc_register_lock_config_t *const lockConfig)
This method configures register lock for the corresponding RTC instance. Remember that all the regist...
Definition: rtc_driver.c:426
uint32_t numberOfRepeats
Definition: rtc_driver.h:131
void RTC_DRV_GetTimeCompensation(uint32_t instance, uint8_t *compInterval, int8_t *compensation)
This retrieves the time compensation coefficients and saves them on the variables referenced by the p...
Definition: rtc_driver.c:534
status_t RTC_DRV_GetCurrentTimeDate(uint32_t instance, rtc_timedate_t *const currentTime)
Get current time and date from RTC instance.
Definition: rtc_driver.c:328
#define RTC_INSTANCE_COUNT
Definition: S32K142.h:8919
void RTC_DRV_GetAlarmConfig(uint32_t instance, rtc_alarm_config_t *alarmConfig)
Get alarm configuration for RTC instance.
Definition: rtc_driver.c:981
status_t RTC_DRV_Init(uint32_t instance, const rtc_init_config_t *const rtcUserCfg)
This function initializes the RTC instance with the settings provided by the user via the rtcUserCfg ...
Definition: rtc_driver.c:100
void RTC_DRV_ConvertSecondsToTimeDate(const uint32_t *const seconds, rtc_timedate_t *const timeDate)
Convert seconds to rtc_timedate_t structure.
Definition: rtc_driver.c:551
#define RTC_BASE_PTRS
Definition: S32K142.h:8930
RTC alarm configuration Implements : rtc_alarm_config_t_Class.
Definition: rtc_driver.h:127
void INT_SYS_DisableIRQ(IRQn_Type irqNumber)
Disables an interrupt for a given IRQ number.
rtc_alarm_config_t * alarmConfig
Definition: rtc_driver.c:76
#define DEV_ASSERT(x)
Definition: devassert.h:77
static bool RTC_DRV_CanWriteTCE(uint32_t instance)
Definition: rtc_driver.c:221
bool RTC_DRV_IsTimeDateCorrectFormat(const rtc_timedate_t *const timeDate)
Check if the date time struct is configured properly.
Definition: rtc_driver.c:695
status_t RTC_DRV_ConfigureTimeCompensation(uint32_t instance, uint8_t compInterval, int8_t compensation)
This method configures time compensation. Data is passed by the compInterval and compensation paramet...
Definition: rtc_driver.c:501
RTC Seconds Interrupt Configuration Implements : rtc_seconds_int_config_t_Class.
Definition: rtc_driver.h:155
rtc_clk_out_config_t clockOutConfig
Definition: rtc_driver.h:118
RTC Register Lock Configuration Implements : rtc_register_lock_config_t_Class.
Definition: rtc_driver.h:167
static RTC_Type *const g_rtcBase[RTC_INSTANCE_COUNT]
Definition: rtc_driver.c:54
void RTC_DRV_SecondsIRQHandler(uint32_t instance)
This method is the API's Interrupt handler for RTC Second interrupt. This ISR will call the user call...
Definition: rtc_driver.c:845
status_t RTC_DRV_GetNextAlarmTime(uint32_t instance, rtc_timedate_t *const alarmTime)
Gets the next alarm time.
Definition: rtc_driver.c:1013
static const uint8_t LY[]
Definition: rtc_driver.c:65
void(* alarmCallback)(void *callbackParam)
Definition: rtc_driver.h:134
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
#define YEAR_RANGE_START
Definition: rtc_driver.h:43
uint8_t compensationInterval
Definition: rtc_driver.h:115
uint32_t repetitionInterval
Definition: rtc_driver.h:130
#define SECONDS_IN_A_MIN
Definition: rtc_driver.h:38
void RTC_DRV_ConfigureFaultInt(uint32_t instance, rtc_interrupt_config_t *const intConfig)
This method configures fault interrupts such as:
Definition: rtc_driver.c:870
void RTC_DRV_ConfigureSecondsInt(uint32_t instance, rtc_seconds_int_config_t *const intConfig)
This method configures the Time Seconds Interrupt with the configuration from the intConfig parameter...
Definition: rtc_driver.c:897
bool RTC_DRV_IsYearLeap(uint16_t year)
Check if the current year is leap.
Definition: rtc_driver.c:737
rtc_second_int_cfg_t secondIntConfig
Definition: rtc_driver.h:157
const IRQn_Type g_rtcIrqNumbers[RTC_IRQS_CH_COUNT]
Table used to store the RTC IRQ names.
Definition: rtc_irq.c:35
void RTC_DRV_GetRegisterLock(uint32_t instance, rtc_register_lock_config_t *const lockConfig)
Get which registers are locked for RTC instance.
Definition: rtc_driver.c:473
void(* rtcSecondsCallback)(void *callbackParam)
Definition: rtc_driver.h:159
#define MINS_IN_A_HOUR
Definition: rtc_driver.h:39
bool RTC_DRV_IsAlarmPending(uint32_t instance)
Check if alarm is pending.
Definition: rtc_driver.c:996
void RTC_DRV_IRQHandler(uint32_t instance)
This method is the API's Interrupt handler for generic and alarm IRQ. It will handle the alarm repeti...
Definition: rtc_driver.c:773
rtc_timedate_t alarmTime
Definition: rtc_driver.h:129
uint16_t hour
Definition: rtc_driver.h:104
#define HOURS_IN_A_DAY
Definition: rtc_driver.h:40
RTC Time Date structure Implements : rtc_timedate_t_Class.
Definition: rtc_driver.h:99
rtc_clk_select_t clockSelect
Definition: rtc_driver.h:117
void RTC_DRV_GetDefaultConfig(rtc_init_config_t *const config)
This function will set the default configuration values into the structure passed as a parameter...
Definition: rtc_driver.c:195
static const uint8_t ULY[]
Definition: rtc_driver.c:62
uint16_t minutes
Definition: rtc_driver.h:105
uint8_t seconds
Definition: rtc_driver.h:106
void INT_SYS_EnableIRQ(IRQn_Type irqNumber)
Enables an interrupt for a given IRQ number.
bool isAlarmTimeNew
Definition: rtc_driver.c:77
status_t RTC_DRV_Deinit(uint32_t instance)
This function deinitializes the RTC instance. If the Control register is locked then this method retu...
Definition: rtc_driver.c:159
status_t RTC_DRV_ConfigureAlarm(uint32_t instance, rtc_alarm_config_t *const alarmConfig)
This method configures the alarm with the configuration from the alarmConfig parameter.
Definition: rtc_driver.c:927
#define SECONDS_IN_A_HOUR
Definition: rtc_driver.h:37
void(* rtcCallback)(void *callbackParam)
Definition: rtc_driver.h:147
const IRQn_Type g_rtcSecondsIrqNb[RTC_SECONDS_IRQS_CH_COUNT]
Definition: rtc_irq.c:37
static const uint16_t MONTH_DAYS[]
Definition: rtc_driver.c:68
static struct @19 g_rtcRuntimeConfig[RTC_INSTANCE_COUNT]
static RTC runtime structure, it is designed only for internal purposes such as storing interrupt con...
status_t RTC_DRV_SetTimeDate(uint32_t instance, const rtc_timedate_t *const time)
Set time and date for RTC instance. The user must stop the counter before using this function...
Definition: rtc_driver.c:383
void RTC_DRV_ConvertTimeDateToSeconds(const rtc_timedate_t *const timeDate, uint32_t *const seconds)
Convert seconds to rtc_timedate_t structure.
Definition: rtc_driver.c:645
#define RTC_IRQS_CH_COUNT
Definition: S32K142.h:8934
#define YEAR_RANGE_END
Definition: rtc_driver.h:44
#define DAYS_IN_A_LEAP_YEAR
Definition: rtc_driver.h:42
rtc_seconds_int_config_t * secondsIntConfig
Definition: rtc_driver.c:79
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K142.h:192