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 */
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 */
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  DEV_ASSERT(time != NULL);
387 
388  /* Declare local variables */
389  status_t statusCode = STATUS_SUCCESS;
390  uint32_t seconds = 0;
391 
392  /* Check if the time is in the correct format */
393  if (RTC_DRV_IsTimeDateCorrectFormat(time) == false)
394  {
395  /* Set the exit code to error */
396  statusCode = STATUS_ERROR;
397  }
398  /* Check if the TCE bit is writable */
399  else if (RTC_DRV_CanWriteTCE(instance) == false)
400  {
401  /* Set the exit code to locked */
402  statusCode = STATUS_ERROR;
403  }
404  else
405  {
406  /* Convert the desired time to seconds */
407  RTC_DRV_ConvertTimeDateToSeconds(time, &seconds);
408  /* Set the time */
409  statusCode = RTC_SetTimeSecondsRegister(g_rtcBase[instance], seconds);
410  }
411 
412  /* Return the exit code */
413  return statusCode;
414 }
415 
416 /*FUNCTION**********************************************************************
417  *
418  * Function Name : RTC_DRV_ConfigureRegisterLock
419  * Description : This method configures register lock for the corresponding
420  * RTC instance. Remember that all the registers are unlocked
421  * only by software reset or power on reset.
422  * (Except for CR that is unlocked only by POR).
423  * Return : STATUS_SUCCESS if the operation was successful,
424  * STATUS_ERROR if the Lock Register is locked.
425  * Implements : RTC_DRV_ConfigureRegisterLock_Activity
426  *END**************************************************************************/
427 status_t RTC_DRV_ConfigureRegisterLock(uint32_t instance, const rtc_register_lock_config_t * const lockConfig)
428 {
429  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
430  DEV_ASSERT(lockConfig != NULL);
431 
432  /* Declare local variables */
433  status_t statusCode = STATUS_SUCCESS;
434 
435  /* Lock the requested registers, but always the Lock register last,
436  * otherwise other registers can not be locked.
437  */
438 
439  /* Configure Control register lock */
440  if (lockConfig->controlRegisterLock)
441  {
442  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_CTRL_REG_LOCK);
443  }
444  /* Configure Status register lock */
445  if (lockConfig->statusRegisterLock)
446  {
447  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_STATUS_REG_LOCK);
448  }
449  /* Configure Time Compensation register lock */
450  if (lockConfig->timeCompensationRegisterLock)
451  {
452  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_TCL_REG_LOCK);
453  }
454  /* Configure Lock register lock */
455  if (lockConfig->lockRegisterLock)
456  {
457  statusCode = RTC_ConfigureRegisterLock(g_rtcBase[instance], RTC_LOCK_REG_LOCK);
458  }
459 
460  /* Return the exit code */
461  return statusCode;
462 }
463 
464 /*FUNCTION**********************************************************************
465  *
466  * Function Name : RTC_DRV_GetRegisterLock
467  * Description : This retrieves the register lock configuration from the RTC
468  * instance.
469  * Data is stored in the structure referenced by the lockConfig
470  * pointer.
471  * Return : None
472  * Implements : RTC_DRV_GetRegisterLock_Activity
473  *END**************************************************************************/
474 void RTC_DRV_GetRegisterLock(uint32_t instance, rtc_register_lock_config_t * const lockConfig)
475 {
476  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
477  DEV_ASSERT(lockConfig != NULL);
478 
479  /* Get the configuration of the register lock */
480 
481  /* For the Lock Register */
482  lockConfig->lockRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_LOCK_REG_LOCK);
483  /* For the Control Register */
484  lockConfig->controlRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_CTRL_REG_LOCK);
485  /* For the Status Register */
486  lockConfig->statusRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_STATUS_REG_LOCK);
487  /* For the Time Compensation Register */
488  lockConfig->timeCompensationRegisterLock = RTC_IsRegisterLocked(g_rtcBase[instance], RTC_TCL_REG_LOCK);
489 }
490 
491 /*FUNCTION**********************************************************************
492  *
493  * Function Name : RTC_DRV_ConfigureTimeCompensation
494  * Description : This method configures time compensation. Data is passed by
495  * the compInterval and compensation parameters.
496  * For more details regarding coefficient calculation see the
497  * Reference Manual.
498  * Return : STATUS_SUCCESS if the operation was successful,
499  * STATUS_ERROR if the TC Register is locked.
500  * Implements : RTC_DRV_ConfigureTimeCompensation_Activity
501  *END**************************************************************************/
502 status_t RTC_DRV_ConfigureTimeCompensation(uint32_t instance, uint8_t compInterval, int8_t compensation)
503 {
504  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
505 
506  /* Declare local variables */
507  status_t statusCode = STATUS_SUCCESS;
508 
509  /* Check if the TCR is locked */
510  if (RTC_IsRegisterLocked(g_rtcBase[instance], RTC_TCL_REG_LOCK) == true)
511  {
512  /* Set the exit code to locked */
513  statusCode = STATUS_ERROR;
514  }
515  else
516  {
517  /* Set the corresponding values for compensation and compensation
518  * interval.
519  */
520  RTC_SetTimeCompensation(g_rtcBase[instance], compensation, compInterval);
521  }
522 
523  /* Return the exit code */
524  return statusCode;
525 }
526 
527 /*FUNCTION**********************************************************************
528  *
529  * Function Name : RTC_DRV_GetTimeCompensation
530  * Description : This retrieves the time compensation coefficients and saves
531  * them on the variables referenced by the parameters.
532  * Return : None
533  * Implements : RTC_DRV_GetTimeCompensation_Activity
534  *END**************************************************************************/
535 void RTC_DRV_GetTimeCompensation(uint32_t instance, uint8_t * compInterval, int8_t * compensation)
536 {
537  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
538  DEV_ASSERT(compInterval != NULL);
539  DEV_ASSERT(compensation != NULL);
540 
541  /* Get the compensation interval */
542  RTC_GetCurrentTimeCompensation(g_rtcBase[instance], compensation, compInterval);
543 }
544 
545 /*FUNCTION**********************************************************************
546  *
547  * Function Name : RTC_DRV_ConvertSecondsToTimeDate
548  * Description : This method converts seconds into time-date format.
549  * Return : None
550  * Implements : RTC_DRV_ConvertSecondsToTimeDate_Activity
551  *END**************************************************************************/
552 void RTC_DRV_ConvertSecondsToTimeDate(const uint32_t * const seconds, rtc_timedate_t * const timeDate)
553 {
554  DEV_ASSERT(seconds != NULL);
555  DEV_ASSERT(timeDate != NULL);
556 
557  /* Declare the variables needed */
558  uint8_t i;
559  bool yearLeap = false;
560  uint32_t numberOfDays = 0U;
561  uint32_t tempSeconds;
562  uint16_t daysInYear;
563 
564  /* Because the starting year(1970) is not leap, set the daysInYear
565  * variable with the number of the days in a normal year
566  */
567  daysInYear = DAYS_IN_A_YEAR;
568 
569  /* Set the year to the beginning of the range */
570  timeDate->year = YEAR_RANGE_START;
571 
572  /* Get the number of days */
573  numberOfDays = (*seconds) / SECONDS_IN_A_DAY;
574  /* Get the number of seconds remaining */
575  tempSeconds = (*seconds) % SECONDS_IN_A_DAY;
576 
577  /* Get the current hour */
578  timeDate->hour = (uint16_t)(tempSeconds / SECONDS_IN_A_HOUR);
579  /* Get the remaining seconds */
580  tempSeconds = tempSeconds % SECONDS_IN_A_HOUR;
581  /* Get the minutes */
582  timeDate->minutes = (uint16_t)(tempSeconds / SECONDS_IN_A_MIN);
583  /* Get seconds */
584  timeDate->seconds = (uint8_t)(tempSeconds % SECONDS_IN_A_MIN);
585 
586  /* Get the current year */
587  while (numberOfDays >= daysInYear)
588  {
589  /* Increment year if the number of days is greater than the ones in
590  * one year
591  */
592  timeDate->year++;
593  /* Subtract the number of the days */
594  numberOfDays -= daysInYear;
595 
596  /* Check if the year is leap or unleap */
597  if (!RTC_DRV_IsYearLeap(timeDate->year))
598  {
599  /* Set the number of non leap year to the current year number
600  * of days.
601  */
602  daysInYear = DAYS_IN_A_YEAR;
603  }
604  else
605  {
606  /* Set the number of leap year to the current year number
607  * of days.
608  */
609  daysInYear = DAYS_IN_A_LEAP_YEAR;
610  }
611  }
612 
613  /* Add the current day */
614  numberOfDays += 1U;
615 
616  /* Check if the current year is leap */
617  yearLeap = RTC_DRV_IsYearLeap(timeDate->year);
618 
619  /* Get the month */
620  for (i = 1U; i <= 12U; i++)
621  {
622  uint32_t daysInCurrentMonth = ((yearLeap == true) ? (uint32_t)LY[i] : (uint32_t)ULY[i]);
623  if (numberOfDays <= daysInCurrentMonth)
624  {
625  timeDate->month = (uint16_t)i;
626  break;
627  }
628  else
629  {
630  numberOfDays -= daysInCurrentMonth;
631  }
632 
633  }
634 
635  /* Set the current day */
636  timeDate->day = (uint16_t)numberOfDays;
637 }
638 
639 /*FUNCTION**********************************************************************
640  *
641  * Function Name : RTC_DRV_ConvertTimeDateToSeconds
642  * Description : This method converts time-date into seconds.
643  * Return : None
644  * Implements : RTC_DRV_ConvertTimeDateToSeconds_Activity
645  *END**************************************************************************/
646 void RTC_DRV_ConvertTimeDateToSeconds(const rtc_timedate_t * const timeDate, uint32_t * const seconds)
647 {
648  DEV_ASSERT(seconds != NULL);
649  DEV_ASSERT(timeDate != NULL);
650 
651  /* Declare local variables */
652  uint16_t year;
653 
654  /* Convert years to seconds */
655  (*seconds) = (uint32_t)(DAYS_IN_A_YEAR * (uint32_t)(SECONDS_IN_A_DAY));
656  (*seconds) *= ((uint32_t)timeDate->year - YEAR_RANGE_START);
657 
658  /* Add the seconds from the leap years */
659  for (year = YEAR_RANGE_START; year < timeDate->year; year++)
660  {
661  if (RTC_DRV_IsYearLeap(year))
662  {
663  (*seconds) += SECONDS_IN_A_DAY;
664  }
665  }
666 
667  /* If the current year is leap and 29th of February has passed, add
668  * another day to seconds passed.
669  */
670  if ((RTC_DRV_IsYearLeap(year)) && (timeDate->month > 2U))
671  {
672  (*seconds) += SECONDS_IN_A_DAY;
673  }
674 
675  /* Add the rest of the seconds from the current month */
676  (*seconds) += MONTH_DAYS[timeDate->month] * SECONDS_IN_A_DAY;
677  /* Add the rest of the seconds from the current day */
678  (*seconds) += (uint32_t)(((uint32_t)timeDate->day - 1U) * (uint32_t)SECONDS_IN_A_DAY);
679  /* Add the rest of the seconds from the current time */
680  (*seconds) += (uint32_t)(((uint32_t)timeDate->hour * SECONDS_IN_A_HOUR) + \
681  ((uint32_t)timeDate->minutes * SECONDS_IN_A_MIN) + \
682  (uint32_t)timeDate->seconds);
683 }
684 
685 /*FUNCTION**********************************************************************
686  *
687  * Function Name : RTC_DRV_IsTimeDateCorrectFormat
688  * Description : This method checks if date-time structure is in a correct
689  * format
690  * Return : True if the following conditions are met:
691  * - is a valid year, month and date
692  * - is a valid time format
693  * False otherwise
694  * Implements : RTC_DRV_IsTimeDateCorrectFormat_Activity
695  *END**************************************************************************/
697 {
698  DEV_ASSERT(timeDate != NULL);
699 
700  /* Declare local variables */
701  bool returnCode = true;
702  const uint8_t * pDays;
703 
704  /* Set the days-in-month table for the corresponding year */
705  pDays = RTC_DRV_IsYearLeap(timeDate->year) ? (LY) : (ULY);
706 
707  /* Check if the time and date are in the correct ranges */
708  if ((timeDate->year < YEAR_RANGE_START) || (timeDate->year > YEAR_RANGE_END)
709  || (timeDate->month < 1U) || (timeDate->month > 12U)
710  || (timeDate->day < 1U) || (timeDate->day > 31U)
711  || (timeDate->hour >= HOURS_IN_A_DAY)
712  || (timeDate->minutes >= MINS_IN_A_HOUR) || (timeDate->seconds >= SECONDS_IN_A_MIN))
713  {
714  returnCode = false;
715  }
716  /* Check if the day is a valid day from the corresponding month */
717  else if (timeDate->day > pDays[timeDate->month])
718  {
719  returnCode = false;
720  }
721  else
722  {
723  returnCode = true;
724  }
725 
726  /* Return the exit code */
727  return returnCode;
728 }
729 
730 /*FUNCTION**********************************************************************
731  *
732  * Function Name : RTC_DRV_IsYearLeap
733  * Description : This method checks if the year passed as a parameter is a leap
734  * one.
735  * Return : True if the year is leap, false if otherwise.
736  * Implements : RTC_DRV_IsYearLeap_Activity
737  *END**************************************************************************/
738 bool RTC_DRV_IsYearLeap(uint16_t year)
739 {
740  bool isYearLeap = false;
741 
742  if ((year % 4U) > 0U)
743  {
744  isYearLeap = false;
745  }
746  else if ((year % 100U) > 0U)
747  {
748  isYearLeap = true;
749  }
750  else if ((year % 400U) > 0U)
751  {
752  isYearLeap = false;
753  }
754  else
755  {
756  isYearLeap = true;
757  }
758 
759  /* Return the exit code */
760  return isYearLeap;
761 }
762 
763 
764 /*FUNCTION**********************************************************************
765  *
766  * Function Name : RTC_DRV_IRQHandler
767  * Description : This method is the API's Interrupt handler for generic and
768  * alarm IRQ. It will handle the alarm repetition and calls the
769  * user callbacks if they are not NULL.
770  * Return : None
771  *
772  * Implements : RTC_DRV_IRQHandler_Activity
773  *END**************************************************************************/
774 void RTC_DRV_IRQHandler(uint32_t instance)
775 {
776  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
777 
778  uint32_t tempSeconds;
779  /* Get the alarm configuration */
780  rtc_alarm_config_t * alarmConfig = g_rtcRuntimeConfig[instance].alarmConfig;
781  /* Get the fault interrupt configuration */
782  const rtc_interrupt_config_t * const intConfig = g_rtcRuntimeConfig[instance].intConfig;
783 
784  /* Check if an alarm has occurred */
785  if (RTC_GetTimeAlarmFlag(g_rtcBase[instance]) == true)
786  {
787  /* If the alarm interrupt configuration has been defined process the
788  * alarm IRQ
789  */
790  if ((alarmConfig != NULL))
791  {
792  /* If recurrence is enabled modify the alarm register to the next
793  * alarm.
794  */
795  if ((alarmConfig->numberOfRepeats > 0UL) || (alarmConfig->repeatForever == true))
796  {
797  /* Get current time */
798  tempSeconds = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
799  /* Current time is incremented with the repetition value */
800  tempSeconds += alarmConfig->repetitionInterval - 1UL;
801  /* Set new value to trigger the alarm */
802  RTC_SetTimeAlarmRegister(g_rtcBase[instance], tempSeconds);
803 
804  g_rtcRuntimeConfig[instance].isAlarmTimeNew = true;
805  /* If the alarm repeats forever, set number of repeats to 0
806  * to avoid an accidental trigger of the core overflow flag
807  */
808  alarmConfig->numberOfRepeats = (alarmConfig->repeatForever == false) ? (alarmConfig->numberOfRepeats - 1UL) : 0UL;
809  }
810  else
811  {
812  /* If the alarm does not repeat, write 0 to TAR to clear the
813  * alarm flag.
814  */
815  RTC_SetTimeAlarmRegister(g_rtcBase[instance], 0UL);
816  /* Set the internal variable which indicates that a new alarm is enabled to false */
817  g_rtcRuntimeConfig[instance].isAlarmTimeNew = false;
818  }
819  /* If the user has defined a callback, call it */
820  if (alarmConfig->alarmCallback != NULL)
821  {
822  alarmConfig->alarmCallback(alarmConfig->callbackParams);
823  }
824  }
825  }
826  /* If the IRQ is not caused by the alarm then call the user callback if
827  * defined.
828  */
829  else if ( intConfig != NULL )
830  {
831  if ( intConfig->rtcCallback != NULL )
832  {
833  /* Call the RTC interrupt callback function with callback parameter */
834  intConfig->rtcCallback(intConfig->callbackParams);
835  }
836  }
837  else
838  {
839  /* Do nothing*/
840  }
841 }
842 
843 /*FUNCTION**********************************************************************
844  *
845  * Function Name : RTC_DRV_SecondsIRQHandler
846  * Description : This method is the API's Interrupt handler for RTC Second
847  * interrupt. This ISR will call the user callback if defined.
848  * Return : None
849  * Implements : RTC_DRV_SecondsIRQHandler_Activity
850  *END**************************************************************************/
851 void RTC_DRV_SecondsIRQHandler(uint32_t instance)
852 {
853  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
854 
855  const rtc_seconds_int_config_t * const intCfg = g_rtcRuntimeConfig[instance].secondsIntConfig;
856 
857  /* If the interrupt is configured by the driver API and the user callback
858  * is not NULL, then call it.
859  */
860  if ((intCfg != NULL) && (intCfg->rtcSecondsCallback != NULL))
861  {
862  /* Call the RTC Seconds interrupt callback function with callback parameter */
863  intCfg->rtcSecondsCallback(intCfg->secondsCallbackParams);
864  }
865 }
866 
867 /*FUNCTION**********************************************************************
868  *
869  * Function Name : RTC_DRV_ConfigureFaultInt
870  * Description : This method configures fault interrupts such as:
871  * - Time Overflow Interrupt
872  * - Time Invalid Interrupt
873  * with the user provided configuration struct intConfig.
874  * Return : None
875  * Implements : RTC_DRV_ConfigureFaultInt_Activity
876  *END**************************************************************************/
878 {
879  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
880  DEV_ASSERT(intConfig != NULL);
881 
882  /* Disable the IRQ to avoid accidental interrupt requests */
884  /* Save the configuration into the instance's runtime structure */
885  g_rtcRuntimeConfig[instance].intConfig = intConfig;
886 
887  /* Enable or disable selected interrupts */
888  RTC_SetTimeOverflowIntEnable(g_rtcBase[instance], intConfig->overflowIntEnable);
889 
890  RTC_SetTimeInvalidIntEnable(g_rtcBase[instance], intConfig->timeInvalidIntEnable);
891 
892  /* After the configuration is done, re-enable the interrupt in NVIC */
894 }
895 
896 /*FUNCTION**********************************************************************
897  *
898  * Function Name : RTC_DRV_ConfigureSecondsInt
899  * Description : This method configures the Time Seconds Interrupt with the
900  * configuration from the intConfig parameter.
901  * Return : None
902  * Implements : RTC_DRV_ConfigureSecondsInt_Activity
903  *END**************************************************************************/
905 {
906  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
907  DEV_ASSERT(intConfig != NULL);
908 
909  /* Disable the IRQ to avoid accidental interrupt requests */
911  /* Disable the IRQ to avoid accidental interrupt requests */
912  g_rtcRuntimeConfig[instance].secondsIntConfig = intConfig;
913 
914  /* Configure the interrupt frequency */
915  RTC_SetTimeSecondsIntConf(g_rtcBase[instance], intConfig->secondIntConfig);
916 
917  /* Enable or disable Time Seconds interrupt */
918  RTC_SetTimeSecondsIntEnable(g_rtcBase[instance], intConfig->secondIntEnable);
919 
920  /* After the configuration is done, re-enable the interrupt in NVIC */
922 }
923 
924 /*FUNCTION**********************************************************************
925  *
926  * Function Name : RTC_DRV_ConfigureAlarm
927  * Description : This method configures the alarm with the
928  * configuration from the alarmConfig parameter.
929  *
930  * Return : STATUS_SUCCESS if the configuration is successful or
931  * STATUS_ERROR if the alarm time is invalid.
932  * Implements : RTC_DRV_ConfigureAlarm_Activity
933  *END**************************************************************************/
935 {
936  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
937  DEV_ASSERT(alarmConfig != NULL);
938 
939  status_t statusCode = STATUS_SUCCESS;
940  uint32_t alarmTime;
941  uint32_t currentTime;
942 
943  /* Check if the alarm time is in a correct format */
944  if (RTC_DRV_IsTimeDateCorrectFormat(&(alarmConfig->alarmTime)) == true)
945  {
946  /* Convert the time date to seconds */
947  RTC_DRV_ConvertTimeDateToSeconds(&(alarmConfig->alarmTime), &alarmTime);
948  /* Get current time in seconds */
949  currentTime = RTC_GetTimeSecondsRegister(g_rtcBase[instance]);
950 
951  /* Check if the alarm time is greater than current time */
952  if(alarmTime > currentTime)
953  {
954  /* Disable the IRQ to avoid accidental interrupt requests */
956  g_rtcRuntimeConfig[instance].alarmConfig = alarmConfig;
957 
958  /* Write alarm time into Time Alarm Register */
959  RTC_SetTimeAlarmRegister(g_rtcBase[instance], alarmTime);
960  /* Enable/disable interrupt source based on the configuration */
961  RTC_SetTimeAlarmIntEnable(g_rtcBase[instance], alarmConfig->alarmIntEnable);
962  /* After the configuration is done, re-enable the interrupt in
963  * NVIC.
964  */
966  }
967  else
968  {
969  statusCode = STATUS_ERROR;
970  }
971  }
972  else
973  {
974  statusCode = STATUS_ERROR;
975  }
976 
977  /* Return the exit code */
978  return statusCode;
979 }
980 
981 /*FUNCTION**********************************************************************
982  *
983  * Function Name : RTC_DRV_GetAlarmConfig
984  * Description : This method retrieves the alarm configuration.
985  * Return : None
986  * Implements : RTC_DRV_GetAlarmConfig_Activity
987  *END**************************************************************************/
989 {
990  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
991  DEV_ASSERT(alarmConfig != NULL);
992 
993  *alarmConfig = *(g_rtcRuntimeConfig[instance].alarmConfig);
994 }
995 
996 /*FUNCTION**********************************************************************
997  *
998  * Function Name : RTC_DRV_IsAlarmPending
999  * Description : This method specifies if an alarm has occurred.
1000  * Return : True if an alarm has occurred, false if not.
1001  * Implements : RTC_DRV_IsAlarmPending_Activity
1002  *END**************************************************************************/
1003 bool RTC_DRV_IsAlarmPending(uint32_t instance)
1004 {
1005  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
1006 
1007  /* Return the exit code */
1008  return RTC_GetTimeAlarmFlag(g_rtcBase[instance]);
1009 }
1010 
1011 /*FUNCTION**********************************************************************
1012  *
1013  * Function Name : RTC_DRV_GetNextAlarmTime
1014  * Description : This method retrieves the next alarm time;
1015  * Return : STATUS_SUCCESS if the next alarm time is valid
1016  * STATUS_ERROR if there is no new alarm
1017  *
1018  * Implements : RTC_DRV_GetNextAlarmTime_Activity
1019  *END**************************************************************************/
1020 status_t RTC_DRV_GetNextAlarmTime(uint32_t instance, rtc_timedate_t * const alarmTime)
1021 {
1022  DEV_ASSERT(instance < RTC_INSTANCE_COUNT);
1023  DEV_ASSERT(alarmTime != NULL);
1024 
1025  status_t statusCode = STATUS_SUCCESS;
1026  uint32_t alarmInSec;
1027  /* Check if is a new alarm and if true update alarm time date format from time seconds */
1028  if (g_rtcRuntimeConfig[instance].isAlarmTimeNew == true)
1029  {
1030  alarmInSec = RTC_GetTimeAlarmRegister(g_rtcBase[instance]);
1031  RTC_DRV_ConvertSecondsToTimeDate(&alarmInSec, alarmTime);
1032  }
1033  else
1034  {
1035  statusCode = STATUS_ERROR;
1036  }
1037  /* Return the exit code */
1038 
1039  return statusCode;
1040 }
1041 /*******************************************************************************
1042  * EOF
1043  ******************************************************************************/
rtc_interrupt_config_t * intConfig
Definition: rtc_driver.c:78
#define RTC_SECONDS_IRQS_CH_COUNT
Definition: S32K118.h:8767
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:427
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:535
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: S32K118.h:8750
void RTC_DRV_GetAlarmConfig(uint32_t instance, rtc_alarm_config_t *alarmConfig)
Get alarm configuration for RTC instance.
Definition: rtc_driver.c:988
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:552
#define RTC_BASE_PTRS
Definition: S32K118.h:8761
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:696
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:502
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:851
status_t RTC_DRV_GetNextAlarmTime(uint32_t instance, rtc_timedate_t *const alarmTime)
Gets the next alarm time.
Definition: rtc_driver.c:1020
static struct @18 g_rtcRuntimeConfig[RTC_INSTANCE_COUNT]
static RTC runtime structure, it is designed only for internal purposes such as storing interrupt con...
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
IRQn_Type
Defines the Interrupt Numbers definitions.
Definition: S32K118.h:188
#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:877
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:904
bool RTC_DRV_IsYearLeap(uint16_t year)
Check if the current year is leap.
Definition: rtc_driver.c:738
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:474
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:1003
void INT_SYS_ClearPending(IRQn_Type irqNumber)
Clear Pending Interrupt.
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:774
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:934
#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
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:646
#define RTC_IRQS_CH_COUNT
Definition: S32K118.h:8765
#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