1 /***************************************************************************//**
2 * \file cy_rtc.c
3 * \version 2.70
4 *
5 * This file provides constants and parameter values for the APIs for the
6 * Real-Time Clock (RTC).
7 *
8 ********************************************************************************
9 * \copyright
10 * Copyright (c) (2016-2022), Cypress Semiconductor Corporation (an Infineon company) or
11 * an affiliate of Cypress Semiconductor Corporation.
12 * SPDX-License-Identifier: Apache-2.0
13 *
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
17 *
18 * http://www.apache.org/licenses/LICENSE-2.0
19 *
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
25 *******************************************************************************/
26
27 #include "cy_device.h"
28
29 #if defined (CY_IP_MXS40SRSS_RTC) || defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS) || defined (CY_IP_MXS22SRSS)
30
31 #include "cy_rtc.h"
32
33 CY_MISRA_DEVIATE_BLOCK_START('MISRA C-2012 Rule 2.2', 3, \
34 'The unused code due to weak implementation can be overwritten further and then interrupt handler can call it.')
35 #if defined(__cplusplus)
36 extern "C" {
37 #endif
38
39 #if defined (CY_IP_MXS28SRSS) || defined (CY_IP_MXS40SSRSS) || (defined (CY_IP_MXS40SRSS_RTC_VERSION) && (CY_IP_MXS40SRSS_RTC_VERSION >= 3))
40 #define CONVERT_BCD_TO_DEC(bcdNum) (bcdNum)
41 #define CONVERT_DEC_TO_BCD(decNum) (decNum)
42 #else
43 #define CONVERT_BCD_TO_DEC(bcdNum) Cy_RTC_ConvertBcdToDec(bcdNum)
44 #define CONVERT_DEC_TO_BCD(decNum) Cy_RTC_ConvertDecToBcd(decNum)
45 #endif /* CY_IP_MXS40SRSS_RTC, CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS */
46
47 /** RTC days in months table */
48 uint8_t const cy_RTC_daysInMonthTbl[CY_RTC_MONTHS_PER_YEAR] = {CY_RTC_DAYS_IN_JANUARY,
49 CY_RTC_DAYS_IN_FEBRUARY,
50 CY_RTC_DAYS_IN_MARCH,
51 CY_RTC_DAYS_IN_APRIL,
52 CY_RTC_DAYS_IN_MAY,
53 CY_RTC_DAYS_IN_JUNE,
54 CY_RTC_DAYS_IN_JULY,
55 CY_RTC_DAYS_IN_AUGUST,
56 CY_RTC_DAYS_IN_SEPTEMBER,
57 CY_RTC_DAYS_IN_OCTOBER,
58 CY_RTC_DAYS_IN_NOVEMBER,
59 CY_RTC_DAYS_IN_DECEMBER};
60
61 /* Static functions */
62 static void ConstructTimeDate(cy_stc_rtc_config_t const *timeDate, uint32_t *timeBcd, uint32_t *dateBcd);
63 static void ConstructAlarmTimeDate(cy_stc_rtc_alarm_t const *alarmDateTime, uint32_t *alarmTimeBcd,
64 uint32_t *alarmDateBcd);
65 static uint32_t RelativeToFixed(cy_stc_rtc_dst_format_t const *convertDst);
66
67
68 /*******************************************************************************
69 * Function Name: Cy_RTC_Init
70 ****************************************************************************//**
71 *
72 * Initializes the RTC driver.
73 *
74 * \param *config
75 * The pointer to the RTC configuration structure, see \ref cy_stc_rtc_config_t.
76 *
77 * \return
78 * Checking result. If the pointer is NULL, returns an error.
79 * See \ref cy_en_rtc_status_t.
80 *
81 *******************************************************************************/
Cy_RTC_Init(cy_stc_rtc_config_t const * config)82 cy_en_rtc_status_t Cy_RTC_Init(cy_stc_rtc_config_t const *config)
83 {
84 return(Cy_RTC_SetDateAndTime(config));
85 }
86
87
88 /*******************************************************************************
89 * Function Name: Cy_RTC_SetDateAndTime
90 ****************************************************************************//**
91 *
92 * Sets the time and date values into the RTC_TIME and RTC_DATE registers.
93 *
94 * \param dateTime
95 * The pointer to the RTC configuration structure, see \ref cy_stc_rtc_config_t.
96 *
97 * \return
98 * A validation check result of date and month. Returns an
99 * error, if the date range is invalid. See \ref cy_en_rtc_status_t.
100 *
101 * \note
102 * The function may return CY_RTC_INVALID_STATE if the RTC is
103 * busy with previous update. In such situation, user should
104 * call this function repetitively with appropriate parameters
105 * to ensure that RTC is updated with provided arguments.
106 *
107 * \note
108 * Refresh ALARM using \ref Cy_RTC_SetAlarmDateAndTime if it is already enabled
109 * before calling this API.
110 *
111 *******************************************************************************/
Cy_RTC_SetDateAndTime(cy_stc_rtc_config_t const * dateTime)112 cy_en_rtc_status_t Cy_RTC_SetDateAndTime(cy_stc_rtc_config_t const *dateTime)
113 {
114 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
115 uint32_t interruptState;
116 uint32_t tmpTime;
117 uint32_t tmpDate;
118
119 if (NULL != dateTime)
120 {
121 /* Check dateTime->date input */
122 uint32_t tmpDaysInMonth = Cy_RTC_DaysInMonth(dateTime->month, (dateTime->year + CY_RTC_TWO_THOUSAND_YEARS));
123
124 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(dateTime->sec));
125 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(dateTime->min));
126 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(dateTime->hour));
127 CY_ASSERT_L3(CY_RTC_IS_DOW_VALID(dateTime->dayOfWeek));
128 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(dateTime->month));
129 CY_ASSERT_L3(CY_RTC_IS_YEAR_SHORT_VALID(dateTime->year));
130 CY_ASSERT_L3(CY_RTC_IS_DATE_VALID(dateTime->date, tmpDaysInMonth));
131 CY_ASSERT_L3(CY_RTC_IS_WEEK_DAY_VALID(dateTime->dayOfWeek, Cy_RTC_ConvertDayOfWeek(dateTime->date, dateTime->month, (dateTime->year + CY_RTC_TWO_THOUSAND_YEARS))));
132
133 if ((dateTime->date > 0U) && (dateTime->date <= tmpDaysInMonth))
134 {
135
136 ConstructTimeDate(dateTime, &tmpTime, &tmpDate);
137
138 /* The RTC AHB registers can be updated only under condition that the
139 * Write bit is set and the RTC busy bit is cleared (CY_RTC_BUSY = 0).
140 */
141 interruptState = Cy_SysLib_EnterCriticalSection();
142 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
143 if (retVal == CY_RTC_SUCCESS)
144 {
145 BACKUP_RTC_TIME = tmpTime;
146 BACKUP_RTC_DATE = tmpDate;
147
148 /* Clear the RTC Write bit to finish RTC register update */
149 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
150 }
151 Cy_SysLib_ExitCriticalSection(interruptState);
152 }
153 }
154 return(retVal);
155 }
156
157
158 /*******************************************************************************
159 * Function Name: Cy_RTC_GetDateAndTime
160 ****************************************************************************//**
161 *
162 * Gets the current RTC time and date. The AHB RTC Time and Date register values
163 * are stored into the *dateTime structure.
164 *
165 * \param dateTime
166 * The RTC time and date structure. See \ref group_rtc_data_structures.
167 *
168 *******************************************************************************/
Cy_RTC_GetDateAndTime(cy_stc_rtc_config_t * dateTime)169 void Cy_RTC_GetDateAndTime(cy_stc_rtc_config_t* dateTime)
170 {
171 uint32_t tmpTime;
172 uint32_t tmpDate;
173
174 CY_ASSERT_L1(NULL != dateTime);
175
176 /* Read the current RTC time and date to validate the input parameters */
177 Cy_RTC_SyncFromRtc();
178
179 /* Write the AHB RTC registers date and time into the local variables and
180 * updating the dateTime structure elements
181 */
182 tmpTime = BACKUP_RTC_TIME;
183 tmpDate = BACKUP_RTC_DATE;
184 dateTime->sec = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_SEC, tmpTime));
185 dateTime->min = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_MIN, tmpTime));
186 dateTime->hrFormat = ((_FLD2BOOL(BACKUP_RTC_TIME_CTRL_12HR, tmpTime)) ? CY_RTC_12_HOURS : CY_RTC_24_HOURS);
187
188 /* Read the current hour mode to know how many hour bits should be converted
189 * In the 24-hour mode, the hour value is presented in [21:16] bits in the
190 * BCD format.
191 * In the 12-hour mode the hour value is presented in [20:16] bits in the BCD
192 * format and bit [21] is present: 0 - AM; 1 - PM.
193 */
194 if (dateTime->hrFormat != CY_RTC_24_HOURS)
195 {
196 dateTime->hour =
197 CONVERT_BCD_TO_DEC((tmpTime & CY_RTC_BACKUP_RTC_TIME_RTC_12HOUR) >> BACKUP_RTC_TIME_RTC_HOUR_Pos);
198 dateTime->amPm = ((0U != (tmpTime & CY_RTC_BACKUP_RTC_TIME_RTC_PM)) ? CY_RTC_PM : CY_RTC_AM);
199 }
200 else
201 {
202 dateTime->hour = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_HOUR, tmpTime));
203 dateTime->amPm = CY_RTC_AM;
204 }
205 dateTime->dayOfWeek = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_DAY, tmpTime));
206
207 dateTime->date = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_DATE, tmpDate));
208 dateTime->month = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_MON, tmpDate));
209 dateTime->year = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, tmpDate));
210 }
211
212
213 /*******************************************************************************
214 * Function Name: Cy_RTC_SetAlarmDateAndTime
215 ****************************************************************************//**
216 *
217 * Sets alarm time and date values into the ALMx_TIME and ALMx_DATE registers.
218 *
219 * \param alarmDateTime
220 * The alarm configuration structure, see \ref cy_stc_rtc_alarm_t.
221 *
222 * \param alarmIndex
223 * The alarm index to be configured, see \ref cy_en_rtc_alarm_t.
224 *
225 * \return
226 * A validation check result of date and month. Returns an
227 * error, if the date range is invalid. See \ref cy_en_rtc_status_t.
228 *
229 * \note
230 * The function may return CY_RTC_INVALID_STATE if the RTC is
231 * busy with previous update. In such situation, user should
232 * call this function repetitively with appropriate parameters
233 * to ensure that RTC is updated with provided arguments.
234 *
235 *******************************************************************************/
Cy_RTC_SetAlarmDateAndTime(cy_stc_rtc_alarm_t const * alarmDateTime,cy_en_rtc_alarm_t alarmIndex)236 cy_en_rtc_status_t Cy_RTC_SetAlarmDateAndTime(cy_stc_rtc_alarm_t const *alarmDateTime, cy_en_rtc_alarm_t alarmIndex)
237 {
238 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
239
240 if (NULL != alarmDateTime)
241 {
242 uint32_t tmpYear;
243 uint32_t interruptState;
244 uint32_t tmpAlarmTime;
245 uint32_t tmpAlarmDate;
246
247 tmpYear = CY_RTC_TWO_THOUSAND_YEARS + CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, BACKUP_RTC_DATE));
248
249 CY_UNUSED_PARAMETER(tmpYear);
250
251 CY_ASSERT_L3(CY_RTC_IS_ALARM_IDX_VALID(alarmIndex));
252
253 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(alarmDateTime->sec));
254 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->secEn));
255
256 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(alarmDateTime->min));
257 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->minEn));
258
259 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(alarmDateTime->hour));
260 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->hourEn));
261
262 CY_ASSERT_L3(CY_RTC_IS_DOW_VALID(alarmDateTime->dayOfWeek));
263 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->dayOfWeekEn));
264
265 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(alarmDateTime->month));
266 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->monthEn));
267
268 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->dateEn));
269
270 CY_ASSERT_L3(CY_RTC_IS_ALARM_EN_VALID(alarmDateTime->almEn));
271
272 CY_ASSERT_L3(CY_RTC_IS_DATE_VALID(alarmDateTime->date, Cy_RTC_DaysInMonth(alarmDateTime->month, tmpYear)));
273
274 /* Read the current RTC year to validate alarmDateTime->date */
275 Cy_RTC_SyncFromRtc();
276
277 ConstructAlarmTimeDate(alarmDateTime, &tmpAlarmTime, &tmpAlarmDate);
278
279 /* The RTC AHB registers can be updated only under condition that the
280 * Write bit is set and the RTC busy bit is cleared (RTC_BUSY = 0).
281 */
282 interruptState = Cy_SysLib_EnterCriticalSection();
283 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
284 if (CY_RTC_SUCCESS == retVal)
285 {
286 /* Update the AHB RTC registers with formed values */
287 if (alarmIndex != CY_RTC_ALARM_2)
288 {
289 BACKUP_ALM1_TIME = tmpAlarmTime;
290 BACKUP_ALM1_DATE = tmpAlarmDate;
291 }
292 else
293 {
294 BACKUP_ALM2_TIME = tmpAlarmTime;
295 BACKUP_ALM2_DATE = tmpAlarmDate;
296 }
297
298 /* Clear the RTC Write bit to finish RTC update */
299 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
300 }
301 Cy_SysLib_ExitCriticalSection(interruptState);
302 }
303
304 return(retVal);
305 }
306
307
308 /*******************************************************************************
309 * Function Name: Cy_RTC_GetAlarmDateAndTime
310 ****************************************************************************//**
311 *
312 * Returns the current alarm time and date values from the ALMx_TIME and
313 * ALMx_DATE registers.
314 *
315 * \param alarmDateTime
316 * The alarm configuration structure, see \ref cy_stc_rtc_alarm_t.
317 *
318 * \param alarmIndex
319 * The alarm index to be configured, see \ref cy_en_rtc_alarm_t.
320 *
321 *******************************************************************************/
Cy_RTC_GetAlarmDateAndTime(cy_stc_rtc_alarm_t * alarmDateTime,cy_en_rtc_alarm_t alarmIndex)322 void Cy_RTC_GetAlarmDateAndTime(cy_stc_rtc_alarm_t *alarmDateTime, cy_en_rtc_alarm_t alarmIndex)
323 {
324 uint32_t tmpAlarmTime;
325 uint32_t tmpAlarmDate;
326 cy_en_rtc_hours_format_t curHoursFormat;
327
328 CY_ASSERT_L1(NULL != alarmDateTime);
329 CY_ASSERT_L3(CY_RTC_IS_ALARM_IDX_VALID(alarmIndex));
330
331 /* Read the current RTC time and date to validate the input parameters */
332 Cy_RTC_SyncFromRtc();
333
334 curHoursFormat = Cy_RTC_GetHoursFormat();
335
336 /* Write the AHB RTC registers into the local variables and update the
337 * alarmDateTime structure elements
338 */
339 if (alarmIndex != CY_RTC_ALARM_2)
340 {
341 tmpAlarmTime = BACKUP_ALM1_TIME;
342 tmpAlarmDate = BACKUP_ALM1_DATE;
343
344 alarmDateTime->sec = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_SEC, tmpAlarmTime));
345 alarmDateTime->secEn =
346 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_SEC_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
347 alarmDateTime->min = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_MIN, tmpAlarmTime));
348 alarmDateTime->minEn =
349 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_MIN_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
350
351 /* Read the current hour mode to know how many hour bits to convert.
352 * In the 24-hour mode, the hour value is presented in [21:16] bits in
353 * the BCD format.
354 * In the 12-hour mode, the hour value is presented in [20:16] bits in
355 * the BCD format and bit [21] is present: 0 - AM; 1 - PM.
356 */
357 if (curHoursFormat != CY_RTC_24_HOURS)
358 {
359 alarmDateTime->hour =
360 CONVERT_BCD_TO_DEC((tmpAlarmTime & CY_RTC_BACKUP_RTC_TIME_RTC_12HOUR)
361 >> BACKUP_ALM1_TIME_ALM_HOUR_Pos);
362
363 /* In the structure, the hour value should be presented in the 24-hour mode. In
364 * that condition the firmware checks the AM/PM status and adds 12 hours to
365 * the converted hour value if the PM bit is set.
366 */
367 if ((alarmDateTime->hour < CY_RTC_HOURS_PER_HALF_DAY) &&
368 (0U != (BACKUP_ALM1_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
369 {
370 alarmDateTime->hour += CY_RTC_HOURS_PER_HALF_DAY;
371 }
372
373 /* Set zero hour, as the 12 A hour is zero hour in 24-hour format */
374 if ((alarmDateTime->hour == CY_RTC_HOURS_PER_HALF_DAY) &&
375 (0U == (BACKUP_ALM1_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
376 {
377 alarmDateTime->hour = 0U;
378 }
379
380 }
381 else
382 {
383 alarmDateTime->hour = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_HOUR, tmpAlarmTime));
384 }
385 alarmDateTime->hourEn =
386 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_HOUR_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
387
388 alarmDateTime->dayOfWeek = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_TIME_ALM_DAY, tmpAlarmTime));
389 alarmDateTime->dayOfWeekEn =
390 ((_FLD2BOOL(BACKUP_ALM1_TIME_ALM_DAY_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
391
392 alarmDateTime->date = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_DATE_ALM_DATE, tmpAlarmDate));
393 alarmDateTime->dateEn =
394 ((_FLD2BOOL(BACKUP_ALM1_DATE_ALM_DATE_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
395
396 alarmDateTime->month = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM1_DATE_ALM_MON, tmpAlarmDate));
397 alarmDateTime->monthEn =
398 ((_FLD2BOOL(BACKUP_ALM1_DATE_ALM_MON_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
399
400 alarmDateTime->almEn =
401 ((_FLD2BOOL(BACKUP_ALM1_DATE_ALM_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
402 }
403 else
404 {
405 tmpAlarmTime = BACKUP_ALM2_TIME;
406 tmpAlarmDate = BACKUP_ALM2_DATE;
407
408 alarmDateTime->sec = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_SEC, tmpAlarmTime));
409 alarmDateTime->secEn =
410 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_SEC_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
411
412 alarmDateTime->min = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_MIN, tmpAlarmTime));
413 alarmDateTime->minEn =
414 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_MIN_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
415
416 /* Read the current hour mode to know how many hour bits to convert.
417 * In the 24-hour mode, the hour value is presented in [21:16] bits in
418 * the BCD format.
419 * In the 12-hour mode the hour value is presented in [20:16] bits in
420 * the BCD format and bit [21] is present: 0 - AM; 1 - PM.
421 */
422 if (curHoursFormat != CY_RTC_24_HOURS)
423 {
424 alarmDateTime->hour = CONVERT_BCD_TO_DEC((tmpAlarmTime & CY_RTC_BACKUP_RTC_TIME_RTC_12HOUR) >>
425 BACKUP_ALM2_TIME_ALM_HOUR_Pos);
426 /* In the structure, the hour value should be presented in the 24-hour mode. In
427 * that condition the firmware checks the AM/PM status and adds 12 hours to
428 * the converted hour value if the PM bit is set.
429 */
430 if ((alarmDateTime->hour < CY_RTC_HOURS_PER_HALF_DAY) &&
431 (0U != (BACKUP_ALM2_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
432 {
433 alarmDateTime->hour += CY_RTC_HOURS_PER_HALF_DAY;
434 }
435 /* Set zero hour, as the 12 am hour is zero hour in 24-hour format */
436 else if ((alarmDateTime->hour == CY_RTC_HOURS_PER_HALF_DAY) &&
437 (0U == (BACKUP_ALM2_TIME & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
438 {
439 alarmDateTime->hour = 0U;
440 }
441 else
442 {
443 /* No corrections are required */
444 }
445 }
446 else
447 {
448 alarmDateTime->hour = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_HOUR, tmpAlarmTime));
449 }
450 alarmDateTime->hourEn =
451 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_HOUR_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
452
453 alarmDateTime->dayOfWeek = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_TIME_ALM_DAY, tmpAlarmTime));
454 alarmDateTime->dayOfWeekEn =
455 ((_FLD2BOOL(BACKUP_ALM2_TIME_ALM_DAY_EN, tmpAlarmTime)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
456
457 alarmDateTime->date = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_DATE_ALM_DATE, tmpAlarmDate));
458 alarmDateTime->dateEn =
459 ((_FLD2BOOL(BACKUP_ALM2_DATE_ALM_DATE_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
460
461 alarmDateTime->month = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_ALM2_DATE_ALM_MON, tmpAlarmDate));
462 alarmDateTime->monthEn =
463 ((_FLD2BOOL(BACKUP_ALM2_DATE_ALM_MON_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
464
465 alarmDateTime->almEn =
466 ((_FLD2BOOL(BACKUP_ALM2_DATE_ALM_EN, tmpAlarmDate)) ? CY_RTC_ALARM_ENABLE : CY_RTC_ALARM_DISABLE);
467 }
468 }
469
470
471 /*******************************************************************************
472 * Function Name: Cy_RTC_SetDateAndTimeDirect
473 ****************************************************************************//**
474 *
475 * Sets the time and date values into the RTC_TIME and RTC_DATE registers using
476 * direct time parameters.
477 *
478 * \param sec The second valid range is [0-59].
479 *
480 * \param min The minute valid range is [0-59].
481 *
482 * \param hour
483 * The hour valid range is [0-23]. This parameter should be presented in the
484 * 24-hour format.
485 *
486 * The function reads the current 12/24-hour mode, then converts the hour value
487 * properly as the mode.
488 *
489 * \param date
490 * The date valid range is [1-31], if the month of February is
491 * selected as the Month parameter, then the valid range is [0-29].
492 *
493 * \param month The month valid range is [1-12].
494 *
495 * \param year The year valid range is [0-99].
496 *
497 * \return
498 * A validation check result of date and month. Returns an
499 * error, if the date range is invalid or the RTC time and date set was
500 * cancelled: the RTC Write bit was not set, the RTC was synchronizing.
501 * See \ref cy_en_rtc_status_t.
502 *
503 *******************************************************************************/
Cy_RTC_SetDateAndTimeDirect(uint32_t sec,uint32_t min,uint32_t hour,uint32_t date,uint32_t month,uint32_t year)504 cy_en_rtc_status_t Cy_RTC_SetDateAndTimeDirect(uint32_t sec, uint32_t min, uint32_t hour,
505 uint32_t date, uint32_t month, uint32_t year)
506 {
507 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
508 cy_stc_rtc_config_t curTimeAndDate;
509 uint32_t tmpTime;
510 uint32_t tmpDate;
511 uint32_t interruptState;
512
513 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(sec));
514 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(min));
515 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(hour));
516 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(month));
517 CY_ASSERT_L3(CY_RTC_IS_YEAR_SHORT_VALID(year));
518 CY_ASSERT_L3(CY_RTC_IS_DATE_VALID(date, Cy_RTC_DaysInMonth(month, year + CY_RTC_TWO_THOUSAND_YEARS)));
519
520 /* Fill the date and time structure */
521 curTimeAndDate.sec = sec;
522 curTimeAndDate.min = min;
523
524 /* Read the current hour mode */
525 Cy_RTC_SyncFromRtc();
526
527 if (CY_RTC_12_HOURS != Cy_RTC_GetHoursFormat())
528 {
529 curTimeAndDate.hrFormat = CY_RTC_24_HOURS;
530 curTimeAndDate.hour = hour;
531 }
532 else
533 {
534 curTimeAndDate.hrFormat = CY_RTC_12_HOURS;
535
536 /* Convert the 24-hour format input value into the 12-hour format */
537 if (hour >= CY_RTC_HOURS_PER_HALF_DAY)
538 {
539 /* The current hour is more than 12 or equal 12, in the 24-hour
540 * format. Set the PM bit and convert the hour: hour = hour - 12,
541 * except that the hour is 12.
542 */
543 curTimeAndDate.hour =
544 (hour > CY_RTC_HOURS_PER_HALF_DAY) ? ((uint32_t) hour - CY_RTC_HOURS_PER_HALF_DAY) : hour;
545
546 curTimeAndDate.amPm = CY_RTC_PM;
547 }
548 else
549 {
550 /* The current hour is less than 12 AM. The zero hour is equal
551 * to 12:00 AM
552 */
553 curTimeAndDate.hour = ((hour == 0U) ? CY_RTC_HOURS_PER_HALF_DAY : hour);
554 curTimeAndDate.amPm = CY_RTC_AM;
555 }
556 }
557 curTimeAndDate.dayOfWeek = Cy_RTC_ConvertDayOfWeek(date, month, (year + CY_RTC_TWO_THOUSAND_YEARS));
558 curTimeAndDate.date = date;
559 curTimeAndDate.month = month;
560 curTimeAndDate.year = year;
561
562 ConstructTimeDate(&curTimeAndDate, &tmpTime, &tmpDate);
563
564 /* The RTC AHB register can be updated only under condition that the
565 * Write bit is set and the RTC busy bit is cleared (CY_RTC_BUSY = 0).
566 */
567 interruptState = Cy_SysLib_EnterCriticalSection();
568 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
569 if (retVal == CY_RTC_SUCCESS)
570 {
571 BACKUP_RTC_TIME = tmpTime;
572 BACKUP_RTC_DATE = tmpDate;
573
574 /* Clear the RTC Write bit to finish RTC register update */
575 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
576 }
577 Cy_SysLib_ExitCriticalSection(interruptState);
578
579 return(retVal);
580 }
581
582
583 /*******************************************************************************
584 * Function Name: Cy_RTC_SetAlarmDateAndTimeDirect
585 ****************************************************************************//**
586 *
587 * Sets alarm time and date values into the ALMx_TIME and ALMx_DATE
588 * registers using direct time parameters. ALM_DAY_EN is default 0 (=ignore) for
589 * this function.
590 *
591 * \param sec The alarm second valid range is [0-59].
592 *
593 * \param min The alarm minute valid range is [0-59].
594 *
595 * \param hour
596 * The valid range is [0-23].
597 * This parameter type is always in the 24-hour type. This function reads the
598 * current 12/24-hour mode, then converts the hour value properly as the mode.
599 *
600 * \param date
601 * The valid range is [1-31], if the month of February is selected as
602 * the Month parameter, then the valid range is [0-29].
603 *
604 * \param month The alarm month valid range is [1-12].
605 *
606 * \param alarmIndex
607 * The alarm index to be configured, see \ref cy_en_rtc_alarm_t.
608 *
609 * \return
610 * A validation check result of date and month. Returns an
611 * error, if the date range is invalid. See \ref cy_en_rtc_status_t.
612 *
613 *******************************************************************************/
Cy_RTC_SetAlarmDateAndTimeDirect(uint32_t sec,uint32_t min,uint32_t hour,uint32_t date,uint32_t month,cy_en_rtc_alarm_t alarmIndex)614 cy_en_rtc_status_t Cy_RTC_SetAlarmDateAndTimeDirect(uint32_t sec, uint32_t min, uint32_t hour,
615 uint32_t date, uint32_t month, cy_en_rtc_alarm_t alarmIndex)
616 {
617 uint32_t tmpCurrentYear;
618 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
619 uint32_t tmpAlarmTime;
620 uint32_t tmpAlarmDate;
621 uint32_t interruptState;
622 cy_stc_rtc_alarm_t alarmDateTime;
623
624 /* Get the current year value to calculate */
625 tmpCurrentYear = CY_RTC_TWO_THOUSAND_YEARS + CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, BACKUP_RTC_DATE));
626
627 CY_UNUSED_PARAMETER(tmpCurrentYear);
628
629 CY_ASSERT_L3(CY_RTC_IS_SEC_VALID(sec));
630 CY_ASSERT_L3(CY_RTC_IS_MIN_VALID(min));
631 CY_ASSERT_L3(CY_RTC_IS_HOUR_VALID(hour));
632 CY_ASSERT_L3(CY_RTC_IS_MONTH_VALID(month));
633 CY_ASSERT_L3(CY_RTC_IS_ALARM_IDX_VALID(alarmIndex));
634 CY_ASSERT_L3(CY_RTC_IS_DATE_VALID(date, Cy_RTC_DaysInMonth(month, tmpCurrentYear)));
635
636
637 /* Read the current time to validate the input parameters */
638 Cy_RTC_SyncFromRtc();
639
640 /* Fill the alarm structure */
641 alarmDateTime.sec = sec;
642 alarmDateTime.secEn = CY_RTC_ALARM_ENABLE;
643 alarmDateTime.min = min;
644 alarmDateTime.minEn = CY_RTC_ALARM_ENABLE;
645 alarmDateTime.hour = hour;
646 alarmDateTime.hourEn = CY_RTC_ALARM_ENABLE;
647 alarmDateTime.dayOfWeek = CY_RTC_SUNDAY;
648 alarmDateTime.dayOfWeekEn = CY_RTC_ALARM_DISABLE;
649
650 alarmDateTime.date = date;
651 alarmDateTime.dateEn = CY_RTC_ALARM_ENABLE;
652 alarmDateTime.month = month;
653 alarmDateTime.monthEn = CY_RTC_ALARM_ENABLE;
654 alarmDateTime.almEn = CY_RTC_ALARM_ENABLE;
655
656 ConstructAlarmTimeDate(&alarmDateTime, &tmpAlarmTime, &tmpAlarmDate);
657
658 /* The RTC AHB register can be updated only under condition that the
659 * Write bit is set and the RTC busy bit is cleared (CY_RTC_BUSY = 0).
660 */
661 interruptState = Cy_SysLib_EnterCriticalSection();
662 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
663 if (retVal == CY_RTC_SUCCESS)
664 {
665 if (alarmIndex != CY_RTC_ALARM_2)
666 {
667 BACKUP_ALM1_TIME = tmpAlarmTime;
668 BACKUP_ALM1_DATE = tmpAlarmDate;
669 }
670 else
671 {
672 BACKUP_ALM2_TIME = tmpAlarmTime;
673 BACKUP_ALM2_DATE = tmpAlarmDate;
674 }
675
676 /* Clear the RTC Write bit to finish RTC register update */
677 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
678 }
679 Cy_SysLib_ExitCriticalSection(interruptState);
680
681 return(retVal);
682 }
683
684
685 /*******************************************************************************
686 * Function Name: Cy_RTC_SetHoursFormat
687 ****************************************************************************//**
688 *
689 * Sets the 12/24-hour mode.
690 *
691 * \param hoursFormat
692 * The current hour format, see \ref cy_en_rtc_hours_format_t.
693 *
694 * \return
695 * A validation check result of RTC register update. See \ref cy_en_rtc_status_t.
696 *
697 * \note
698 * Refresh ALARM using \ref Cy_RTC_SetAlarmDateAndTime if it is already enabled
699 * before calling this API.
700 *
701 *******************************************************************************/
Cy_RTC_SetHoursFormat(cy_en_rtc_hours_format_t hoursFormat)702 cy_en_rtc_status_t Cy_RTC_SetHoursFormat(cy_en_rtc_hours_format_t hoursFormat)
703 {
704 uint32_t curTime;
705 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
706
707 CY_ASSERT_L3(CY_RTC_IS_HRS_FORMAT_VALID(hoursFormat));
708
709 /* Read the current time to validate the input parameters */
710 Cy_RTC_SyncFromRtc();
711 curTime = BACKUP_RTC_TIME;
712
713 /* Hour format can be changed in condition that current hour format is not
714 * the same as requested in function argument
715 */
716 if (hoursFormat != Cy_RTC_GetHoursFormat())
717 {
718 uint32_t hourValue;
719
720 /* Convert the current hour value from 24H into the 12H format */
721 if (hoursFormat == CY_RTC_12_HOURS)
722 {
723 hourValue = CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_HOUR, curTime));
724 if (hourValue >= CY_RTC_HOURS_PER_HALF_DAY)
725 {
726 /* The current hour is more than 12 or equal 12 in the 24-hour
727 * mode. Set the PM bit and convert the hour: hour = hour - 12.
728 */
729 hourValue = (uint32_t) (hourValue - CY_RTC_HOURS_PER_HALF_DAY);
730 hourValue = ((0U != hourValue) ? hourValue : CY_RTC_HOURS_PER_HALF_DAY);
731
732 curTime = (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
733 curTime |= CY_RTC_BACKUP_RTC_TIME_RTC_PM;
734 }
735 else if (hourValue < 1U)
736 {
737 /* The current hour in the 24-hour mode is 0 which is equal
738 * to 12:00 AM
739 */
740 curTime =
741 (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR,
742 CONVERT_DEC_TO_BCD(CY_RTC_HOURS_PER_HALF_DAY)));
743 /* Set the AM bit */
744 curTime &= ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM);
745 }
746 else
747 {
748 /* The current hour is less than 12 */
749 curTime = (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
750 curTime &= ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM);
751 }
752
753 curTime |= BACKUP_RTC_TIME_CTRL_12HR_Msk;
754 }
755 /* Convert the hour value into 24H format value */
756 else
757 {
758 /* Mask the AM/PM bit as the hour value is in [20:16] bits */
759 hourValue =
760 CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_TIME_RTC_HOUR,
761 (curTime & (uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM)));
762 /* Add 12 hours in condition that current time is in PM period */
763 if ((hourValue < CY_RTC_HOURS_PER_HALF_DAY) && (0U != (curTime & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
764 {
765 hourValue += CY_RTC_HOURS_PER_HALF_DAY;
766 }
767
768 /* Current hour is 12 AM which is equal to zero hour in 24-hour format */
769 if ((hourValue == CY_RTC_HOURS_PER_HALF_DAY) && (0U == (curTime & CY_RTC_BACKUP_RTC_TIME_RTC_PM)))
770 {
771 hourValue = 0U;
772 }
773
774 curTime = (_CLR_SET_FLD32U(curTime, BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
775 curTime &= (uint32_t) ~BACKUP_RTC_TIME_CTRL_12HR_Msk;
776 }
777
778 /* Writing corrected hour value and hour format bit into the RTC AHB
779 * register. The RTC AHB register can be updated only under condition
780 * that the Write bit is set and the RTC busy bit is cleared
781 * (CY_RTC_BUSY = 0).
782 */
783 uint32_t interruptState;
784
785 interruptState = Cy_SysLib_EnterCriticalSection();
786 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
787 if (retVal == CY_RTC_SUCCESS)
788 {
789 BACKUP_RTC_TIME = curTime;
790 /* Clear the RTC Write bit to finish RTC register update */
791 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
792 }
793 Cy_SysLib_ExitCriticalSection(interruptState);
794 }
795 else
796 {
797 retVal = CY_RTC_SUCCESS;
798 }
799 return(retVal);
800 }
801
802 #if defined (CY_IP_MXS40SRSS_RTC) || defined (CY_IP_MXS40SSRSS) || defined (CY_IP_MXS22SRSS)
803 /*******************************************************************************
804 * Function Name: Cy_RTC_SelectFrequencyPrescaler()
805 ****************************************************************************//**
806 *
807 * Selects the RTC pre-scaler value and changes its clock frequency.
808 * If the external 32.768 kHz WCO is absent on the board, the RTC can
809 * be driven by a 32.768kHz square clock source or an external 50-Hz or 60-Hz
810 * sine-wave clock source, for example the wall AC frequency.
811 *
812 * \param clkSel clock frequency, see \ref cy_en_rtc_clock_freq_t.
813 *
814 * In addition to generating the 32.768 kHz clock from external crystals, the WCO
815 * can be sourced by an external clock source (50 Hz or 60Hz), even the wall AC
816 * frequency as a timebase. The API helps select between the RTC sources:
817 * * A 32.768 kHz digital clock source.
818 * * An external 50-Hz or 60-Hz sine-wave clock source.
819 *
820 * If you want to use an external 50-Hz or 60-Hz sine-wave clock source to
821 * drive the RTC, the next procedure is required:
822 * -# Disable the WCO <br>
823 * -# Bypass the WCO using the Cy_SysClk_WcoBypass() function.
824 * -# Configure both wco_out and wco_in pins. Note that only one of the wco pins
825 * should be driven and the other wco pin should be floating, which depends on
826 * the source that drives the RTC (*1).
827 * -# Call Cy_RTC_SelectFrequencyPrescaler(CY_RTC_FREQ_60_HZ), if you want to
828 * drive the WCO, for example, with a 60 Hz source.
829 * -# Enable the WCO.
830 *
831 * If you want to use the WCO after using an external 50-Hz or 60-Hz sine-wave
832 * clock source:
833 * -# Disable the WCO.
834 * -# Switch-off the WCO bypass using the Cy_SysClk_WcoBypass() function.
835 * -# Drive off the wco pin with an external signal source.
836 * -# Call Cy_RTC_SelectFrequencyPrescaler(CY_RTC_FREQ_WCO_32768_HZ).
837 * -# Enable the WCO.
838 *
839 * (1) - Refer to the device TRM to know how to configure the wco pins properly
840 * and which wco pin should be driven/floating.
841 *
842 * \warning
843 * There is a limitation to the external clock source frequencies. Only two
844 * frequencies are allowed - 50 Hz or 60 Hz. Note that this limitation is related
845 * to the RTC pre-scaling feature presented in this function. This
846 * limitation is not related to WCO external clock sources which can drive the
847 * WCO in Bypass mode.
848 *
849 * \note
850 * This API is available for CAT1B, CAT1C and CAT1D devices.
851 *
852 *******************************************************************************/
Cy_RTC_SelectFrequencyPrescaler(cy_en_rtc_clock_freq_t clkSel)853 void Cy_RTC_SelectFrequencyPrescaler(cy_en_rtc_clock_freq_t clkSel)
854 {
855 CY_ASSERT_L3(CY_RTC_IS_CLK_VALID(clkSel));
856
857 #if defined (CY_IP_MXS22SRSS)
858 BACKUP_CTL = (_CLR_SET_FLD32U(BACKUP_CTL, SRSS_CLK_WCO_CONFIG_PRESCALER, (uint32_t) clkSel));
859 #else
860 BACKUP_CTL = (_CLR_SET_FLD32U(BACKUP_CTL, BACKUP_CTL_PRESCALER, (uint32_t) clkSel));
861 #endif
862 }
863 #endif /* CY_IP_MXS40SRSS_RTC, CY_IP_MXS40SSRSS, CY_IP_MXS22SRSS*/
864 /*******************************************************************************
865 * Function Name: Cy_RTC_SelectClockSource()
866 ****************************************************************************//**
867 * \param clkSel Source clock, see \ref cy_en_rtc_clk_select_sources_t
868 * Selects the source clock for RTC.
869 *
870 * \note
871 * This API is available for CAT1B devices.
872 *
873 *******************************************************************************/
Cy_RTC_SelectClockSource(cy_en_rtc_clk_select_sources_t clkSel)874 void Cy_RTC_SelectClockSource(cy_en_rtc_clk_select_sources_t clkSel)
875 {
876 CY_ASSERT_L3(CY_RTC_IS_SRC_CLK_SELECT_VALID(clkSel));
877
878 #if defined (CY_IP_MXS22SRSS)
879 BACKUP_CTL = (_CLR_SET_FLD32U(BACKUP_CTL, SRSS_CLK_WCO_CONFIG_CLK_RTC_SEL, (uint32_t) clkSel));
880 #else
881 BACKUP_CTL = (_CLR_SET_FLD32U(BACKUP_CTL, BACKUP_CTL_CLK_SEL, (uint32_t) clkSel));
882 #endif
883 }
884
885 /*******************************************************************************
886 * Function Name: Cy_RTC_EnableDstTime
887 ****************************************************************************//**
888 *
889 * The function sets the DST time, configures the DST start time when the specified time is outside DST period and configures the ALARM2 interrupt register
890 * with the appropriate DST time. This function sets the DST stop time if the
891 * specified time is already in the DST period. The DST period is a period of time
892 * between the DST start time and DST stop time. The DST start time and DST stop
893 * time is presented in the DST configuration structure,
894 * see \ref cy_stc_rtc_dst_t.
895 *
896 * \param dstTime
897 * The DST configuration structure, see \ref cy_stc_rtc_dst_t.
898 *
899 * \param timeDate
900 * The time and date structure. The appropriate DST time is
901 * set based on this time and date, see \ref cy_stc_rtc_config_t.
902 *
903 * \return
904 * A validation check result of RTC register update. See \ref cy_en_rtc_status_t.
905 *
906 *******************************************************************************/
Cy_RTC_EnableDstTime(cy_stc_rtc_dst_t const * dstTime,cy_stc_rtc_config_t const * timeDate)907 cy_en_rtc_status_t Cy_RTC_EnableDstTime(cy_stc_rtc_dst_t const *dstTime, cy_stc_rtc_config_t const *timeDate)
908 {
909 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
910
911 if ((NULL != dstTime) && (NULL != timeDate))
912 {
913 if (Cy_RTC_GetDstStatus(dstTime, timeDate))
914 {
915 retVal = Cy_RTC_SetNextDstTime(&dstTime->stopDst);
916 }
917 else
918 {
919 retVal = Cy_RTC_SetNextDstTime(&dstTime->startDst);
920 }
921
922 Cy_RTC_SetInterruptMask(Cy_RTC_GetInterruptMask() | CY_RTC_INTR_ALARM2);
923 }
924
925 return (retVal);
926 }
927
928
929 /*******************************************************************************
930 * Function Name: Cy_RTC_SetNextDstTime
931 ****************************************************************************//**
932 *
933 * A low-level DST function sets ALARM2 for a next DST event.
934 * If Cy_RTC_GetDSTStatus() is true(=1), the next DST event should be
935 * the DST stop, then this function should be called with the DST stop time.
936 * Used by the \ref Cy_RTC_EnableDstTime and \ref Cy_RTC_DstInterrupt functions.
937 *
938 * If the time format(.format) is relative option(=0), the
939 * RelativeToFixed() is called to convert to a fixed date.
940 *
941 * \param nextDst
942 * The structure with time at which a next DST event should occur
943 * (ALARM2 interrupt should occur). See \ref cy_stc_rtc_config_t.
944 *
945 * \return
946 * A validation check result of RTC register update. See \ref cy_en_rtc_status_t.
947 *
948 *******************************************************************************/
Cy_RTC_SetNextDstTime(cy_stc_rtc_dst_format_t const * nextDst)949 cy_en_rtc_status_t Cy_RTC_SetNextDstTime(cy_stc_rtc_dst_format_t const *nextDst)
950 {
951 cy_en_rtc_status_t retVal = CY_RTC_BAD_PARAM;
952
953 if (NULL != nextDst)
954 {
955 CY_ASSERT_L3(CY_RTC_IS_DST_FORMAT_VALID(nextDst->format));
956 uint32_t tryesToSetup = CY_RTC_TRYES_TO_SETUP_DST;
957 cy_stc_rtc_alarm_t dstAlarmTimeAndDate;
958
959 /* Configure an alarm structure based on the DST structure */
960 dstAlarmTimeAndDate.sec = 0U;
961 dstAlarmTimeAndDate.secEn = CY_RTC_ALARM_ENABLE;
962 dstAlarmTimeAndDate.min = 0U;
963 dstAlarmTimeAndDate.minEn = CY_RTC_ALARM_ENABLE;
964 dstAlarmTimeAndDate.hour = nextDst->hour;
965 dstAlarmTimeAndDate.hourEn = CY_RTC_ALARM_ENABLE;
966 dstAlarmTimeAndDate.dayOfWeek = nextDst->dayOfWeek;
967 dstAlarmTimeAndDate.dayOfWeekEn = CY_RTC_ALARM_DISABLE;
968
969 /* Calculate a day-of-month value for the relative DST start structure */
970 if (CY_RTC_DST_FIXED != nextDst->format)
971 {
972 dstAlarmTimeAndDate.date = RelativeToFixed(nextDst);
973 }
974 else
975 {
976 dstAlarmTimeAndDate.date = nextDst->dayOfMonth;
977 }
978 dstAlarmTimeAndDate.dateEn = CY_RTC_ALARM_ENABLE;
979 dstAlarmTimeAndDate.month = nextDst->month;
980 dstAlarmTimeAndDate.monthEn = CY_RTC_ALARM_ENABLE;
981 dstAlarmTimeAndDate.almEn = CY_RTC_ALARM_ENABLE;
982
983 while((retVal != CY_RTC_SUCCESS) && (0U != tryesToSetup))
984 {
985 retVal = Cy_RTC_SetAlarmDateAndTime(&dstAlarmTimeAndDate, CY_RTC_ALARM_2);
986 --tryesToSetup;
987 }
988
989 if (tryesToSetup == 0U)
990 {
991 retVal = CY_RTC_TIMEOUT;
992 }
993 }
994
995 return (retVal);
996 }
997
998
999 /*******************************************************************************
1000 * Function Name: Cy_RTC_GetDstStatus
1001 ****************************************************************************//**
1002 *
1003 * A low-level DST function returns the current DST status using given time
1004 * information. This function is used in the initial state of a system.
1005 * If the DST is enabled, the system sets the DST start or stop as a result of
1006 * this function.
1007 * Used by the \ref Cy_RTC_EnableDstTime and \ref Cy_RTC_DstInterrupt functions.
1008 *
1009 * \param dstTime The DST configuration structure, see \ref cy_stc_rtc_dst_t.
1010 *
1011 * \param timeDate
1012 * The time and date structure. The appropriate DST time is
1013 * set based on this time and date, see \ref cy_stc_rtc_config_t.
1014 *
1015 * \return
1016 * False - The current date and time is out of the DST period.
1017 * True - The current date and time is in the DST period.
1018 *
1019 *******************************************************************************/
Cy_RTC_GetDstStatus(cy_stc_rtc_dst_t const * dstTime,cy_stc_rtc_config_t const * timeDate)1020 bool Cy_RTC_GetDstStatus(cy_stc_rtc_dst_t const *dstTime, cy_stc_rtc_config_t const *timeDate)
1021 {
1022 uint32_t dstStartTime;
1023 uint32_t currentTime;
1024 uint32_t dstStopTime;
1025 uint32_t dstStartDayOfMonth;
1026 uint32_t dstStopDayOfMonth;
1027 bool status = false;
1028
1029 CY_ASSERT_L1(NULL != dstTime);
1030 CY_ASSERT_L1(NULL != timeDate);
1031
1032 /* Calculate a day-of-month value for the relative DST start structure */
1033 if (CY_RTC_DST_RELATIVE != dstTime->startDst.format)
1034 {
1035 dstStartDayOfMonth = dstTime->startDst.dayOfMonth;
1036 }
1037 else
1038 {
1039 dstStartDayOfMonth = RelativeToFixed(&dstTime->startDst);
1040 }
1041
1042 /* Calculate the day of a month value for the relative DST stop structure */
1043 if (CY_RTC_DST_RELATIVE != dstTime->stopDst.format)
1044 {
1045 dstStopDayOfMonth = dstTime->stopDst.dayOfMonth;
1046 }
1047 else
1048 {
1049 dstStopDayOfMonth = RelativeToFixed(&dstTime->stopDst);
1050 }
1051
1052 /* The function forms the date and time values for the DST start time,
1053 * the DST Stop Time and for the Current Time. The function that compares
1054 * the three formed values returns "true" under condition that:
1055 * dstStartTime < currentTime < dstStopTime.
1056 * The date and time value are formed this way:
1057 * [13-10] - Month
1058 * [9-5] - Day of Month
1059 * [0-4] - Hour
1060 */
1061 dstStartTime = ((uint32_t) (dstTime->startDst.month << CY_RTC_DST_MONTH_POSITION) |
1062 (dstStartDayOfMonth << CY_RTC_DST_DAY_OF_MONTH_POSITION) | (dstTime->startDst.hour));
1063
1064 currentTime = ((uint32_t) (timeDate->month << CY_RTC_DST_MONTH_POSITION) |
1065 (timeDate->date << CY_RTC_DST_DAY_OF_MONTH_POSITION) | (timeDate->hour));
1066
1067 dstStopTime = ((uint32_t) (dstTime->stopDst.month << CY_RTC_DST_MONTH_POSITION) |
1068 (dstStopDayOfMonth << CY_RTC_DST_DAY_OF_MONTH_POSITION) | (dstTime->stopDst.hour));
1069
1070 if ((dstStartTime <= currentTime) && (dstStopTime > currentTime))
1071 {
1072 status = true;
1073
1074 if (1UL == (dstStopTime - currentTime)) /* Check for the 'an hour before/after stop DST event' period */
1075 {
1076 cy_stc_rtc_alarm_t alarm;
1077 uint32_t locDate = (CY_RTC_DST_FIXED != dstTime->startDst.format) ? RelativeToFixed(&dstTime->startDst) : dstTime->startDst.dayOfMonth;
1078 Cy_RTC_GetAlarmDateAndTime(&alarm, CY_RTC_ALARM_2);
1079
1080 /* If Alarm2 is set for the "Start DST" event - the "Stop DST" event is already passed: */
1081 if ((alarm.almEn == CY_RTC_ALARM_ENABLE ) &&
1082 (alarm.monthEn == CY_RTC_ALARM_ENABLE ) &&
1083 (alarm.month == dstTime->startDst.month) &&
1084 (alarm.dateEn == CY_RTC_ALARM_ENABLE ) &&
1085 (alarm.date == locDate ) &&
1086 (alarm.dayOfWeekEn == CY_RTC_ALARM_DISABLE ) &&
1087 (alarm.hourEn == CY_RTC_ALARM_ENABLE ) &&
1088 (alarm.hour == dstTime->startDst.hour ) &&
1089 (alarm.minEn == CY_RTC_ALARM_ENABLE ) &&
1090 (alarm.min == 0UL ) &&
1091 (alarm.secEn == CY_RTC_ALARM_ENABLE ) &&
1092 (alarm.sec == 0UL ))
1093 {
1094 status = false;
1095 }
1096 /* Otherwise, including the case when Alarm2 is not set at all (DST is not enabled yet) - return true. */
1097 }
1098 }
1099
1100 return (status);
1101 }
1102
1103
1104 /*******************************************************************************
1105 * Function Name: Cy_RTC_Alarm1Interrupt
1106 ****************************************************************************//**
1107 *
1108 * A blank weak interrupt handler function which indicates assert of the RTC
1109 * alarm 1 interrupt.
1110 *
1111 * Function implementation should be defined in user source code in condition
1112 * that such event handler is required. If such event is not required user
1113 * should not do any actions.
1114 *
1115 * This function is called in the general RTC interrupt handler
1116 * Cy_RTC_Interrupt() function.
1117 *
1118 *******************************************************************************/
Cy_RTC_Alarm1Interrupt(void)1119 __WEAK void Cy_RTC_Alarm1Interrupt(void)
1120 {
1121 /* weak blank function */
1122 }
1123
1124
1125 /*******************************************************************************
1126 * Function Name: Cy_RTC_Alarm2Interrupt
1127 ****************************************************************************//**
1128 *
1129 * A blank weak interrupt handler function which indicates assert of the RTC
1130 * alarm 2 interrupt.
1131 *
1132 * Function implementation should be defined in user source code in condition
1133 * that such event handler is required. If such event is not required user
1134 * should not do any actions.
1135 *
1136 * This function is called in the general RTC interrupt handler
1137 * Cy_RTC_Interrupt() function. Cy_RTC_Alarm2Interrupt() function is
1138 * ignored in Cy_RTC_Interrupt() function if DST is enabled. Refer to
1139 * Cy_RTC_Interrupt() description.
1140 *
1141 *******************************************************************************/
Cy_RTC_Alarm2Interrupt(void)1142 __WEAK void Cy_RTC_Alarm2Interrupt(void)
1143 {
1144 /* weak blank function */
1145 }
1146
1147
1148 /*******************************************************************************
1149 * Function Name: Cy_RTC_DstInterrupt
1150 ****************************************************************************//**
1151 *
1152 * This is a processing handler against the DST event. It adjusts the current
1153 * time using the DST start/stop parameters and registers the next DST event time
1154 * into the ALARM2 interrupt. This function is already called by \ref Cy_RTC_Interrupt().
1155 *
1156 * \param dstTime The DST configuration structure, see \ref cy_stc_rtc_dst_t.
1157 *
1158 *******************************************************************************/
Cy_RTC_DstInterrupt(cy_stc_rtc_dst_t const * dstTime)1159 void Cy_RTC_DstInterrupt(cy_stc_rtc_dst_t const *dstTime)
1160 {
1161 cy_stc_rtc_config_t curDateTime;
1162
1163 Cy_RTC_GetDateAndTime(&curDateTime);
1164
1165 if (Cy_RTC_GetDstStatus(dstTime, &curDateTime))
1166 {
1167 /* Under condition that the DST start time was selected as 23:00, and
1168 * the time adjusting occurs, the other time and date values should be
1169 * corrected (day of the week, date, month and year).
1170 */
1171 if (curDateTime.hour == CY_RTC_MAX_HOURS_24H)
1172 {
1173 /* Incrementing day of the week value as hour adjusted next day of
1174 * the week and date. Correcting hour value as its incrementation
1175 * adjusted it out of valid range [0-23].
1176 */
1177 curDateTime.dayOfWeek++;
1178 curDateTime.hour = 0U;
1179
1180 /* Correct a day of the week if its incrementation adjusted it out
1181 * of valid range [1-7].
1182 */
1183 if (curDateTime.dayOfWeek > CY_RTC_SATURDAY)
1184 {
1185 curDateTime.dayOfWeek = CY_RTC_SUNDAY;
1186 }
1187
1188 curDateTime.date++;
1189
1190 /* Correct a day of a month if its incrementation adjusted it out of
1191 * the valid range [1-31]. Increment month value.
1192 */
1193 if (curDateTime.date > Cy_RTC_DaysInMonth(curDateTime.month,
1194 (curDateTime.year + CY_RTC_TWO_THOUSAND_YEARS)))
1195 {
1196 curDateTime.date = CY_RTC_FIRST_DAY_OF_MONTH;
1197 curDateTime.month++;
1198 }
1199
1200 /* Correct a month if its incrementation adjusted it out of the
1201 * valid range [1-12]. Increment year value.
1202 */
1203 if (curDateTime.month > CY_RTC_MONTHS_PER_YEAR)
1204 {
1205 curDateTime.month = CY_RTC_JANUARY;
1206 curDateTime.year++;
1207 }
1208 }
1209 else
1210 {
1211 curDateTime.hour++;
1212 }
1213
1214 (void) Cy_RTC_SetDateAndTime(&curDateTime);
1215 (void) Cy_RTC_SetNextDstTime(&dstTime->stopDst);
1216 }
1217 else
1218 {
1219 if (curDateTime.hour < 1U)
1220 {
1221 /* Decrementing day of the week time and date values as hour
1222 * adjusted next day of the week and date. Correct hour value as
1223 * its incrementation adjusted it out of valid range [0-23].
1224 */
1225 curDateTime.hour = CY_RTC_MAX_HOURS_24H;
1226 curDateTime.dayOfWeek--;
1227
1228 /* Correct a day of the week if its incrementation adjusted it out
1229 * of the valid range [1-7].
1230 */
1231 if (curDateTime.dayOfWeek < CY_RTC_SUNDAY)
1232 {
1233 curDateTime.dayOfWeek = CY_RTC_SUNDAY;
1234 }
1235
1236 curDateTime.date--;
1237
1238 /* Correct a day of a month value if its incrementation adjusted it
1239 * out of the valid range [1-31]. Decrement month value.
1240 */
1241 if (curDateTime.date < CY_RTC_FIRST_DAY_OF_MONTH)
1242 {
1243 curDateTime.month--;
1244 curDateTime.date =
1245 Cy_RTC_DaysInMonth(curDateTime.month, (curDateTime.year + CY_RTC_TWO_THOUSAND_YEARS));
1246 }
1247
1248 /* Correct a month if its increment pushed it out of the valid
1249 * range [1-12]. Decrement year value.
1250 */
1251 if (curDateTime.month < CY_RTC_JANUARY)
1252 {
1253 curDateTime.month = CY_RTC_DECEMBER;
1254 curDateTime.year--;
1255 }
1256 }
1257 else
1258 {
1259 curDateTime.hour--;
1260 }
1261
1262 (void) Cy_RTC_SetDateAndTime(&curDateTime);
1263 (void) Cy_RTC_SetNextDstTime(&dstTime->startDst);
1264 }
1265 }
1266
1267
1268 /*******************************************************************************
1269 * Function Name: Cy_RTC_CenturyInterrupt
1270 ****************************************************************************//**
1271 *
1272 * This is a weak function and it should be redefined in user source code
1273 * in condition that such event handler is required.
1274 * By calling this function, it indicates the year reached 2100.
1275 *
1276 * Function implementation should be defined in user source code in condition
1277 * that such event handler is required. If such event is not required user
1278 * should not do any actions.
1279 *
1280 *******************************************************************************/
Cy_RTC_CenturyInterrupt(void)1281 __WEAK void Cy_RTC_CenturyInterrupt(void)
1282 {
1283 /* weak blank function */
1284 }
1285
1286
1287 /*******************************************************************************
1288 * Function Name: Cy_RTC_GetInterruptStatus
1289 ****************************************************************************//**
1290 *
1291 * Returns a status of RTC interrupt requests.
1292 *
1293 * \return
1294 * Bit mapping information, see \ref group_rtc_macros_interrupts.
1295 *
1296 *******************************************************************************/
Cy_RTC_GetInterruptStatus(void)1297 uint32_t Cy_RTC_GetInterruptStatus(void)
1298 {
1299 return(BACKUP_INTR);
1300 }
1301
1302
1303 /*******************************************************************************
1304 * Function Name: Cy_RTC_GetInterruptStatusMasked
1305 ****************************************************************************//**
1306 *
1307 * Returns an interrupt request register masked by the interrupt mask. Returns a
1308 * result of the bitwise AND operation between the corresponding interrupt
1309 * request and mask bits.
1310 *
1311 * \return
1312 * Bit mapping information, see \ref group_rtc_macros_interrupts.
1313 *
1314 *******************************************************************************/
Cy_RTC_GetInterruptStatusMasked(void)1315 uint32_t Cy_RTC_GetInterruptStatusMasked(void)
1316 {
1317 return(BACKUP_INTR_MASKED);
1318 }
1319
1320
1321 /*******************************************************************************
1322 * Function Name: Cy_RTC_GetInterruptMask
1323 ****************************************************************************//**
1324 *
1325 * Returns an interrupt mask.
1326 *
1327 * \return
1328 * Bit mapping information, see \ref group_rtc_macros_interrupts.
1329 *
1330 *******************************************************************************/
Cy_RTC_GetInterruptMask(void)1331 uint32_t Cy_RTC_GetInterruptMask(void)
1332 {
1333 return (BACKUP_INTR_MASK);
1334 }
1335
1336
1337 /*******************************************************************************
1338 * Function Name: Cy_RTC_SetInterrupt
1339 ****************************************************************************//**
1340 *
1341 * Sets a software interrupt request
1342 *
1343 * \param interruptMask
1344 * Bit mask, see \ref group_rtc_macros_interrupts.
1345 *
1346 *******************************************************************************/
Cy_RTC_SetInterrupt(uint32_t interruptMask)1347 void Cy_RTC_SetInterrupt(uint32_t interruptMask)
1348 {
1349 CY_ASSERT_L3(CY_RTC_INTR_VALID(interruptMask));
1350
1351 BACKUP_INTR_SET = interruptMask;
1352 }
1353
1354
1355 /*******************************************************************************
1356 * Function Name: Cy_RTC_ClearInterrupt
1357 ****************************************************************************//**
1358 *
1359 * Clears RTC interrupts by setting each bit.
1360 *
1361 * \param
1362 * interruptMask The bit mask of interrupts to set,
1363 * see \ref group_rtc_macros_interrupts.
1364 *
1365 *******************************************************************************/
Cy_RTC_ClearInterrupt(uint32_t interruptMask)1366 void Cy_RTC_ClearInterrupt(uint32_t interruptMask)
1367 {
1368 CY_ASSERT_L3(CY_RTC_INTR_VALID(interruptMask));
1369
1370 (void) BACKUP_INTR;
1371
1372 BACKUP_INTR = interruptMask;
1373 }
1374
1375
1376 /*******************************************************************************
1377 * Function Name: Cy_RTC_SetInterruptMask
1378 ****************************************************************************//**
1379 *
1380 * Configures which bits of the interrupt request register that triggers an
1381 * interrupt event.
1382 *
1383 * \param interruptMask
1384 * The bit mask of interrupts to set, see \ref group_rtc_macros_interrupts.
1385 *
1386 *******************************************************************************/
Cy_RTC_SetInterruptMask(uint32_t interruptMask)1387 void Cy_RTC_SetInterruptMask(uint32_t interruptMask)
1388 {
1389 CY_ASSERT_L3(CY_RTC_INTR_VALID(interruptMask));
1390
1391 BACKUP_INTR_MASK = interruptMask;
1392 }
1393
1394
1395 /*******************************************************************************
1396 * Function Name: Cy_RTC_Interrupt
1397 ****************************************************************************//**
1398 *
1399 * The interrupt handler function which should be called in user provided
1400 * RTC interrupt function.
1401 *
1402 * This is the handler of the RTC interrupt in CPU NVIC. The handler checks
1403 * which RTC interrupt was asserted and calls the respective RTC interrupt
1404 * handler functions: Cy_RTC_Alarm1Interrupt(), Cy_RTC_Alarm2Interrupt() or
1405 * Cy_RTC_DstInterrupt(), and Cy_RTC_CenturyInterrupt().
1406 *
1407 * The order of the RTC handler functions execution is incremental.
1408 * Cy_RTC_Alarm1Interrupt() is run as the first one and Cy_RTC_CenturyInterrupt()
1409 * is called as the last one.
1410 *
1411 * This function clears the RTC interrupt every time when it is called.
1412 *
1413 * Cy_RTC_DstInterrupt() function is called instead of Cy_RTC_Alarm2Interrupt()
1414 * in condition that the mode parameter is true.
1415 *
1416 * \param dstTime
1417 * The daylight saving time configuration structure, see \ref cy_stc_rtc_dst_t.
1418 *
1419 * \param mode
1420 * False - if the DST is disabled.
1421 * True - if DST is enabled.
1422 *
1423 * \note This function is required to be called in user interrupt handler.
1424 *
1425 *******************************************************************************/
Cy_RTC_Interrupt(cy_stc_rtc_dst_t const * dstTime,bool mode)1426 void Cy_RTC_Interrupt(cy_stc_rtc_dst_t const *dstTime, bool mode)
1427 {
1428 uint32_t interruptStatus;
1429 interruptStatus = Cy_RTC_GetInterruptStatusMasked();
1430
1431 Cy_RTC_ClearInterrupt(interruptStatus);
1432
1433 if (0U != (CY_RTC_INTR_ALARM1 & interruptStatus))
1434 {
1435 Cy_RTC_Alarm1Interrupt();
1436 }
1437
1438 if (0U != (CY_RTC_INTR_ALARM2 & interruptStatus))
1439 {
1440 if (mode)
1441 {
1442 Cy_RTC_DstInterrupt(dstTime);
1443 }
1444 else
1445 {
1446 Cy_RTC_Alarm2Interrupt();
1447 }
1448 }
1449
1450 if (0U != (CY_RTC_INTR_CENTURY & interruptStatus))
1451 {
1452 Cy_RTC_CenturyInterrupt();
1453 }
1454 }
1455
1456
1457 /*******************************************************************************
1458 * Function Name: Cy_RTC_DeepSleepCallback
1459 ****************************************************************************//**
1460 *
1461 * This function checks the RTC_BUSY bit to avoid data corruption before
1462 * enters the Deep Sleep mode.
1463 *
1464 * \param callbackParams
1465 * The structure with the SysPm callback parameters,
1466 * see \ref cy_stc_syspm_callback_params_t
1467 *
1468 * \param mode
1469 * Callback mode, see \ref cy_en_syspm_callback_mode_t.
1470 *
1471 * \return
1472 * The SysPm return status, see \ref cy_en_syspm_status_t.
1473 *
1474 * \note The *base and *context elements are required to be present in
1475 * the parameter structure because this function uses the SysPm driver
1476 * callback type.
1477 * The SysPm driver callback function type requires implementing the function
1478 * with next parameters and return value:
1479 *
1480 * cy_en_syspm_status_t (*Cy_SysPmCallback)
1481 * (cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
1482 *
1483 *******************************************************************************/
Cy_RTC_DeepSleepCallback(const cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)1484 cy_en_syspm_status_t Cy_RTC_DeepSleepCallback(const cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
1485 {
1486 cy_en_syspm_status_t retVal = CY_SYSPM_FAIL;
1487
1488 if (callbackParams != NULL)
1489 {
1490 switch(mode)
1491 {
1492 case CY_SYSPM_CHECK_READY:
1493 {
1494 if (CY_RTC_AVAILABLE == Cy_RTC_GetSyncStatus())
1495 {
1496 retVal = CY_SYSPM_SUCCESS;
1497 }
1498 }
1499 break;
1500
1501 case CY_SYSPM_CHECK_FAIL:
1502 {
1503 retVal = CY_SYSPM_SUCCESS;
1504 }
1505 break;
1506
1507 case CY_SYSPM_BEFORE_TRANSITION:
1508 {
1509 retVal = CY_SYSPM_SUCCESS;
1510 }
1511 break;
1512
1513 case CY_SYSPM_AFTER_TRANSITION:
1514 {
1515 retVal = CY_SYSPM_SUCCESS;
1516 }
1517 break;
1518
1519 default:
1520 /* Unknown state */
1521 break;
1522 }
1523 }
1524 return (retVal);
1525 }
1526
1527
1528 /*******************************************************************************
1529 * Function Name: Cy_RTC_HibernateCallback
1530 ****************************************************************************//**
1531 *
1532 * This function checks the RTC_BUSY bit to avoid data corruption before
1533 * enters the Hibernate mode.
1534 *
1535 * \param callbackParams
1536 * structure with the syspm callback parameters,
1537 * see \ref cy_stc_syspm_callback_params_t.
1538 *
1539 * \param mode
1540 * Callback mode, see \ref cy_en_syspm_callback_mode_t
1541 *
1542 * \return
1543 * The syspm return status, see \ref cy_en_syspm_status_t
1544 *
1545 * \note The *base and *context elements are required to be present in
1546 * the parameter structure because this function uses the SysPm driver
1547 * callback type.
1548 * The SysPm driver callback function type requires implementing the function
1549 * with next parameters and return value:
1550 *
1551 * cy_en_syspm_status_t (*Cy_SysPmCallback)
1552 * (cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode);
1553 *
1554 *******************************************************************************/
Cy_RTC_HibernateCallback(const cy_stc_syspm_callback_params_t * callbackParams,cy_en_syspm_callback_mode_t mode)1555 cy_en_syspm_status_t Cy_RTC_HibernateCallback(const cy_stc_syspm_callback_params_t *callbackParams, cy_en_syspm_callback_mode_t mode)
1556 {
1557 return (Cy_RTC_DeepSleepCallback(callbackParams, mode));
1558 }
1559
1560
1561 /*******************************************************************************
1562 * Function Name: Cy_RTC_CalibrationControlEnable
1563 ****************************************************************************//**
1564 *
1565 * This function writes calibration control register.
1566 *
1567 * \param calib_val
1568 * Calibration value for absolute frequency (at a fixed temperature).
1569 * Each step causes 128 ticks to be added or removed each hour.
1570 *
1571 * \param calib_sign
1572 * Remove or Add ticks, see \ref cy_en_rtc_calib_sign_t
1573 *
1574 * \param calib_sel
1575 * Select calibration wave output signal, see \ref cy_en_rtc_calib_sel_t
1576 *
1577 * \return
1578 * The RTC return status, see \ref cy_en_rtc_status_t
1579 *
1580 *******************************************************************************/
Cy_RTC_CalibrationControlEnable(uint8_t calib_val,cy_en_rtc_calib_sign_t calib_sign,cy_en_rtc_calib_sel_t calib_sel)1581 cy_en_rtc_status_t Cy_RTC_CalibrationControlEnable(uint8_t calib_val, cy_en_rtc_calib_sign_t calib_sign, cy_en_rtc_calib_sel_t calib_sel)
1582 {
1583 cy_en_rtc_status_t retVal = CY_RTC_INVALID_STATE;
1584 uint32_t interruptState;
1585
1586 CY_UNUSED_PARAMETER(calib_sel);
1587
1588 /* The RTC AHB registers can be updated only under condition that the
1589 * Write bit is set and the RTC busy bit is cleared (RTC_BUSY = 0).
1590 */
1591 interruptState = Cy_SysLib_EnterCriticalSection();
1592 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
1593 if (CY_RTC_SUCCESS == retVal)
1594 {
1595 BACKUP_CAL_CTL =
1596 _VAL2FLD(BACKUP_CAL_CTL_CALIB_VAL, calib_val) |
1597 _VAL2FLD(BACKUP_CAL_CTL_CALIB_SIGN, (uint32_t)calib_sign) |
1598 #if defined (CY_IP_MXS40SSRSS) || (defined (CY_IP_MXS40SRSS_RTC_VERSION) && (CY_IP_MXS40SRSS_RTC_VERSION >= 2))
1599 _VAL2FLD(BACKUP_CAL_CTL_CAL_SEL, (uint32_t)calib_sel) |
1600 #endif
1601 _VAL2FLD(BACKUP_CAL_CTL_CAL_OUT, 1U);
1602
1603 /* Clear the RTC Write bit to finish RTC update */
1604 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
1605 }
1606 Cy_SysLib_ExitCriticalSection(interruptState);
1607
1608 return(retVal);
1609 }
1610
1611 /*******************************************************************************
1612 * Function Name: Cy_RTC_CalibrationControlDisable
1613 ****************************************************************************//**
1614 *
1615 * This function disables the calibration control.
1616 *
1617 * \return
1618 * The RTC return status, see \ref cy_en_rtc_status_t
1619 *
1620 *******************************************************************************/
Cy_RTC_CalibrationControlDisable(void)1621 cy_en_rtc_status_t Cy_RTC_CalibrationControlDisable(void)
1622 {
1623 cy_en_rtc_status_t retVal = CY_RTC_INVALID_STATE;
1624 uint32_t interruptState;
1625
1626 /* The RTC AHB registers can be updated only under condition that the
1627 * Write bit is set and the RTC busy bit is cleared (RTC_BUSY = 0).
1628 */
1629 interruptState = Cy_SysLib_EnterCriticalSection();
1630 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_ENABLED);
1631 if (CY_RTC_SUCCESS == retVal)
1632 {
1633 BACKUP_CAL_CTL =
1634 _VAL2FLD(BACKUP_CAL_CTL_CAL_OUT, 0U);
1635
1636 /* Clear the RTC Write bit to finish RTC update */
1637 retVal = Cy_RTC_WriteEnable(CY_RTC_WRITE_DISABLED);
1638 }
1639 Cy_SysLib_ExitCriticalSection(interruptState);
1640
1641 return(retVal);
1642 }
1643
1644
1645 /*******************************************************************************
1646 * Function Name: ConstructTimeDate
1647 ****************************************************************************//**
1648 *
1649 * Returns BCD time and BCD date in the format used in APIs from individual
1650 * elements passed.
1651 * Converted BCD time(*timeBcd) and BCD date(*dateBcd) are matched with RTC_TIME
1652 * and RTC_DATE bit fields format.
1653 *
1654 * \param timeDate
1655 * The structure of time and date, see \ref cy_stc_rtc_config_t.
1656 *
1657 * \param timeBcd
1658 * The BCD-formatted time variable which has the same bit masks as the
1659 * RTC_TIME register:
1660 *
1661 * [0:6] - Calendar seconds in BCD, the range 0-59. \n
1662 * [14:8] - Calendar minutes in BCD, the range 0-59. \n
1663 * [21:16] - Calendar hours in BCD, value depends on the 12/24-hour mode. \n
1664 * 12HR: [21]:0 = AM, 1 = PM, [20:16] = 1 - 12; \n
1665 * 24HR: [21:16] = 0-23. \n
1666 * [22] - Selects the 12/24-hour mode: 1 - 12-hour, 0 - 24-hour. \n
1667 * [26:24] - A calendar day of the week, the range 1 - 7, where 1 - Sunday. \n
1668 *
1669 * \param dateBcd
1670 * The BCD-formatted time variable which has the same bit masks as the
1671 * RTC_DATE register:
1672 *
1673 * [5:0] - A calendar day of a month in BCD, the range 1-31. \n
1674 * [12:8] - A calendar month in BCD, the range 1-12. \n
1675 * [23:16] - A calendar year in BCD, the range 0-99. \n
1676 *
1677 *******************************************************************************/
ConstructTimeDate(cy_stc_rtc_config_t const * timeDate,uint32_t * timeBcd,uint32_t * dateBcd)1678 static void ConstructTimeDate(cy_stc_rtc_config_t const *timeDate, uint32_t *timeBcd, uint32_t *dateBcd)
1679 {
1680 uint32_t tmpTime;
1681 uint32_t tmpDate;
1682
1683 /* Prepare the RTC TIME value based on the structure obtained */
1684 tmpTime = (_VAL2FLD(BACKUP_RTC_TIME_RTC_SEC, CONVERT_DEC_TO_BCD(timeDate->sec)));
1685 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_MIN, CONVERT_DEC_TO_BCD(timeDate->min)));
1686
1687 /* Read the current hour mode to know how many hour bits to convert.
1688 * In the 24-hour mode, the hour value is presented in [21:16] bits in the
1689 * BCD format.
1690 * In the 12-hour mode, the hour value is presented in [20:16] bits in the
1691 * BCD format and bit [21] is present: 0 - AM; 1 - PM.
1692 */
1693 if (timeDate->hrFormat != CY_RTC_24_HOURS)
1694 {
1695 if (CY_RTC_AM != timeDate->amPm)
1696 {
1697 /* Set the PM bit */
1698 tmpTime |= CY_RTC_BACKUP_RTC_TIME_RTC_PM;
1699 }
1700 else
1701 {
1702 /* Set the AM bit */
1703 tmpTime &= ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM);
1704 }
1705 tmpTime |= BACKUP_RTC_TIME_CTRL_12HR_Msk;
1706 tmpTime |=
1707 (_VAL2FLD(BACKUP_RTC_TIME_RTC_HOUR,
1708 (CONVERT_DEC_TO_BCD(timeDate->hour) & ((uint32_t) ~CY_RTC_12HRS_PM_BIT))));
1709 }
1710 else
1711 {
1712 tmpTime &= ((uint32_t) ~BACKUP_RTC_TIME_CTRL_12HR_Msk);
1713 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_HOUR, CONVERT_DEC_TO_BCD(timeDate->hour)));
1714 }
1715
1716 if (timeDate->dayOfWeek == CY_RTC_DAY_AUTO)
1717 {
1718 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_DAY, CONVERT_DEC_TO_BCD(Cy_RTC_ConvertDayOfWeek(timeDate->date, timeDate->month, (timeDate->year + CY_RTC_TWO_THOUSAND_YEARS)))));
1719 }
1720 else
1721 {
1722 tmpTime |= (_VAL2FLD(BACKUP_RTC_TIME_RTC_DAY, CONVERT_DEC_TO_BCD(timeDate->dayOfWeek)));
1723 }
1724
1725 /* Prepare the RTC Date value based on the structure obtained */
1726 tmpDate = (_VAL2FLD(BACKUP_RTC_DATE_RTC_DATE, CONVERT_DEC_TO_BCD(timeDate->date)));
1727 tmpDate |= (_VAL2FLD(BACKUP_RTC_DATE_RTC_MON, CONVERT_DEC_TO_BCD(timeDate->month)));
1728 tmpDate |= (_VAL2FLD(BACKUP_RTC_DATE_RTC_YEAR, CONVERT_DEC_TO_BCD(timeDate->year)));
1729 /* Update the parameter values with prepared values */
1730 *timeBcd = tmpTime;
1731 *dateBcd = tmpDate;
1732 }
1733
1734
1735 /*******************************************************************************
1736 * Function Name: ConstructAlarmTimeDate
1737 ****************************************************************************//**
1738 *
1739 * Returns the BCD time and BCD date in the format used in APIs from individual
1740 * elements passed for alarm.
1741 * Converted BCD time(*alarmTimeBcd) and BCD date(*alarmDateBcd) should be
1742 * matched with the ALMx_TIME and ALMx_DATE bit fields format.
1743 *
1744 * \param alarmDateTime
1745 * The structure of time and date, see \ref cy_stc_rtc_alarm_t.
1746 *
1747 * \param alarmTimeBcd
1748 * The BCD-formatted time variable which has the same bit masks as the
1749 * ALMx_TIME register time fields:
1750 *
1751 * [0:6] - Alarm seconds in BCD, the range 0-59. \n
1752 * [7] - Alarm seconds Enable: 0 - ignore, 1 - match. \n
1753 * [14:8] - Alarm minutes in BCD, the range 0-59. \n
1754 * [15] - Alarm minutes Enable: 0 - ignore, 1 - match. \n
1755 * [21:16] - Alarm hours in BCD, value depending on the 12/24-hour mode
1756 * (RTC_CTRL_12HR) \n
1757 * 12HR: [21]:0 = AM, 1 = PM, [20:16] = 1 - 12; \n
1758 * 24HR: [21:16] = the range 0-23. \n
1759 * [23] - Alarm hours Enable: 0 - ignore, 1 - match. \n
1760 * [26:24] - An alarm day of the week, the range 1 - 7, where 1 - Monday. \n
1761 * [31] - An alarm day of the week Enable: 0 - ignore, 1 - match. \n
1762 *
1763 * \param alarmDateBcd
1764 * The BCD-formatted date variable which has the same bit masks as the
1765 * ALMx_DATE register date fields:
1766 *
1767 * [5:0] - An alarm day of a month in BCD, the range 1-31. \n
1768 * [7] - An alarm day of a month Enable: 0 - ignore, 1 - match. \n
1769 * [12:8] - An alarm month in BCD, the range 1-12. \n
1770 * [15] - An alarm month Enable: 0 - ignore, 1 - match. \n
1771 * [31] - The Enable alarm: 0 - Alarm is disabled, 1 - Alarm is enabled. \n
1772 *
1773 * This function reads current AHB register RTC_TIME value to know hour mode.
1774 * It is recommended to call Cy_RTC_SyncFromRtc() function before calling the
1775 * ConstructAlarmTimeDate() functions.
1776 *
1777 * Construction is based on RTC_ALARM1 register bit fields.
1778 *
1779 *******************************************************************************/
ConstructAlarmTimeDate(cy_stc_rtc_alarm_t const * alarmDateTime,uint32_t * alarmTimeBcd,uint32_t * alarmDateBcd)1780 static void ConstructAlarmTimeDate(cy_stc_rtc_alarm_t const *alarmDateTime, uint32_t *alarmTimeBcd,
1781 uint32_t *alarmDateBcd)
1782 {
1783 uint32_t tmpAlarmTime;
1784 uint32_t tmpAlarmDate;
1785 uint32_t hourValue;
1786
1787 /* Prepare the RTC ALARM value based on the structure obtained */
1788 tmpAlarmTime = (_VAL2FLD(BACKUP_ALM1_TIME_ALM_SEC, CONVERT_DEC_TO_BCD(alarmDateTime->sec)));
1789 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_SEC_EN, alarmDateTime->secEn));
1790 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_MIN, CONVERT_DEC_TO_BCD(alarmDateTime->min)));
1791 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_MIN_EN, alarmDateTime->minEn));
1792
1793 /* Read the current hour mode to know how many hour bits to convert.
1794 * In the 24-hour mode, the hour value is presented in [21:16] bits in the
1795 * BCD format.
1796 * In the 12-hour mode, the hour value is presented in [20:16] bits in the
1797 * BCD format and bit [21] is present: 0 - AM; 1 - PM
1798 */
1799 Cy_RTC_SyncFromRtc();
1800 if (CY_RTC_24_HOURS != Cy_RTC_GetHoursFormat())
1801 {
1802 /* Convert the hour from the 24-hour mode into the 12-hour mode */
1803 if (alarmDateTime->hour >= CY_RTC_HOURS_PER_HALF_DAY)
1804 {
1805 /* The current hour is more than 12 in the 24-hour mode. Set the PM
1806 * bit and converting hour: hour = hour - 12
1807 */
1808 hourValue = (uint32_t) alarmDateTime->hour - CY_RTC_HOURS_PER_HALF_DAY;
1809 hourValue = ((0U != hourValue) ? hourValue : CY_RTC_HOURS_PER_HALF_DAY);
1810 tmpAlarmTime |=
1811 CY_RTC_BACKUP_RTC_TIME_RTC_PM | (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CONVERT_DEC_TO_BCD(hourValue)));
1812 }
1813 else if (alarmDateTime->hour < 1U)
1814 {
1815 /* The current hour in the 24-hour mode is 0 which is equal to 12:00 AM */
1816 tmpAlarmTime = (tmpAlarmTime & ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM)) |
1817 (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CY_RTC_HOURS_PER_HALF_DAY));
1818 }
1819 else
1820 {
1821 /* The current hour is less than 12. Set the AM bit */
1822 tmpAlarmTime = (tmpAlarmTime & ((uint32_t) ~CY_RTC_BACKUP_RTC_TIME_RTC_PM)) |
1823 (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CONVERT_DEC_TO_BCD(alarmDateTime->hour)));
1824 }
1825 tmpAlarmTime |= BACKUP_RTC_TIME_CTRL_12HR_Msk;
1826 }
1827 else
1828 {
1829 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR, CONVERT_DEC_TO_BCD(alarmDateTime->hour)));
1830 tmpAlarmTime &= ((uint32_t) ~BACKUP_RTC_TIME_CTRL_12HR_Msk);
1831 }
1832 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_HOUR_EN, alarmDateTime->hourEn));
1833 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_DAY, CONVERT_DEC_TO_BCD(alarmDateTime->dayOfWeek)));
1834 tmpAlarmTime |= (_VAL2FLD(BACKUP_ALM1_TIME_ALM_DAY_EN, alarmDateTime->dayOfWeekEn));
1835
1836 /* Prepare the RTC ALARM DATE value based on the obtained structure */
1837 tmpAlarmDate = (_VAL2FLD(BACKUP_ALM1_DATE_ALM_DATE, CONVERT_DEC_TO_BCD(alarmDateTime->date)));
1838 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_DATE_EN, alarmDateTime->dateEn));
1839 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_MON, CONVERT_DEC_TO_BCD(alarmDateTime->month)));
1840 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_MON_EN, alarmDateTime->monthEn));
1841 tmpAlarmDate |= (_VAL2FLD(BACKUP_ALM1_DATE_ALM_EN, alarmDateTime->almEn));
1842
1843 /* Update the parameter values with prepared values */
1844 *alarmTimeBcd = tmpAlarmTime;
1845 *alarmDateBcd = tmpAlarmDate;
1846 }
1847
1848
1849 /*******************************************************************************
1850 * Function Name: RelativeToFixed
1851 ****************************************************************************//**
1852 *
1853 * Converts time from a relative format to a fixed format to set the ALARM2.
1854 *
1855 * \param convertDst
1856 * The DST structure, its appropriate elements should be converted.
1857 *
1858 * \return
1859 * The current date of a month.
1860 *
1861 *******************************************************************************/
RelativeToFixed(cy_stc_rtc_dst_format_t const * convertDst)1862 static uint32_t RelativeToFixed(cy_stc_rtc_dst_format_t const *convertDst)
1863 {
1864 uint32_t currentYear;
1865 uint32_t currentDay;
1866 uint32_t currentWeek;
1867 uint32_t daysInMonth;
1868 uint32_t tmpDayOfMonth;
1869
1870 /* Read the current year */
1871 Cy_RTC_SyncFromRtc();
1872
1873 currentYear =
1874 CY_RTC_TWO_THOUSAND_YEARS + CONVERT_BCD_TO_DEC(_FLD2VAL(BACKUP_RTC_DATE_RTC_YEAR, BACKUP_RTC_DATE));
1875 currentDay = CY_RTC_FIRST_DAY_OF_MONTH;
1876 currentWeek = CY_RTC_FIRST_WEEK_OF_MONTH;
1877 daysInMonth = Cy_RTC_DaysInMonth(convertDst->month, currentYear);
1878 tmpDayOfMonth = currentDay;
1879
1880 while((currentWeek <= convertDst->weekOfMonth) && (currentDay <= daysInMonth))
1881 {
1882 if (convertDst->dayOfWeek == Cy_RTC_ConvertDayOfWeek(currentDay, convertDst->month, currentYear))
1883 {
1884 tmpDayOfMonth = currentDay;
1885 currentWeek++;
1886 }
1887 currentDay++;
1888 }
1889 return(tmpDayOfMonth);
1890 }
1891
1892 #if defined(__cplusplus)
1893 }
1894 #endif
1895
1896 CY_MISRA_BLOCK_END('MISRA C-2012 Rule 2.2')
1897 #endif /* CY_IP_MXS40SRSS_RTC, CY_IP_MXS28SRSS, CY_IP_MXS40SSRSS */
1898
1899 /* [] END OF FILE */
1900