1 /**
2  * @file xmc_rtc.c
3  * @date 2019-05-07
4  *
5  * @cond
6  *********************************************************************************************************************
7  * XMClib v2.1.24 - XMC Peripheral Driver Library
8  *
9  * Copyright (c) 2015-2019, Infineon Technologies AG
10  * All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without modification,are permitted provided that the
13  * following conditions are met:
14  *
15  * Redistributions of source code must retain the above copyright notice, this list of conditions and the following
16  * disclaimer.
17  *
18  * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided with the distribution.
20  *
21  * Neither the name of the copyright holders nor the names of its contributors may be used to endorse or promote
22  * products derived from this software without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
25  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE  FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
28  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
29  * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31  *
32  * To improve the quality of the software, users are encouraged to share modifications, enhancements or bug fixes with
33  * Infineon Technologies AG dave@infineon.com).
34  *********************************************************************************************************************
35  *
36  * Change History
37  * --------------
38  *
39  * 2015-02-20:
40  *     - Initial <br>
41  *
42  * 2015-06-20:
43  *     - Removed GetDriverVersion API
44  *
45  * 2016-05-19:
46  *     - Added XMC_RTC_SetTimeStdFormat() and XMC_RTC_SetAlarmStdFormat()
47  *
48  * 2018-06-21:
49  *     - Fixed value of XMC_RTC_MAXSECONDS, XMC_RTC_MAXMINUTES, XMC_RTC_MAXHOURS macros
50  *     - Fixed assertion on XMC_RTC_MAXDAYS
51  *
52  * 2019-05-07:
53  *     - Fixed compilation warnings
54  *
55  * @endcond
56  *
57  */
58 
59 /**
60  *
61  * @brief RTC driver for XMC microcontroller family.
62  *
63  */
64 
65 /*********************************************************************************************************************
66  * HEADER FILES
67  *********************************************************************************************************************/
68 
69 #include "xmc_scu.h"
70 #include "xmc_rtc.h"
71 
72 /*********************************************************************************************************************
73  * MACROS
74  *********************************************************************************************************************/
75 
76 #define XMC_RTC_MAXSECONDS  (60U)   /**< RTC time : Maximum seconds */
77 #define XMC_RTC_MAXMINUTES  (60U)   /**< RTC time : Maximum minutes */
78 #define XMC_RTC_MAXHOURS    (24U)   /**< RTC time : Maximum hours */
79 #define XMC_RTC_MAXDAYS     (31U)   /**< RTC time : Maximum days */
80 #define XMC_RTC_MAXDAYSOFWEEK  (7U) /**< RTC time : Maximum days of week */
81 #define XMC_RTC_MAXMONTH  (12U)     /**< RTC time : Maximum month */
82 #define XMC_RTC_MAXYEAR  (0xFFFFU)  /**< RTC time : Maximum year */
83 #define XMC_RTC_MAXPRESCALER  (0xFFFFU)  /**< RTC time : Maximum prescaler */
84 #define XMC_RTC_YEAR_OFFSET (1900U)      /**< RTC year offset : Year offset */
85 
86 #if (UC_FAMILY == XMC4)
87 #define XMC_RTC_INIT_SEQUENCE  (1U)
88 #endif
89 #if (UC_FAMILY == XMC1)
90 #define XMC_RTC_INIT_SEQUENCE  (0U)
91 #endif
92 
93 /*********************************************************************************************************************
94  * API IMPLEMENTATION
95  *********************************************************************************************************************/
96 
97 /*
98  * Enables RTC peripheral to start counting time
99  */
XMC_RTC_Start(void)100 void XMC_RTC_Start(void)
101 {
102   while((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_CTR_Msk) != 0U)
103   {
104     /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
105   }
106   RTC->CTR |= (uint32_t)RTC_CTR_ENB_Msk;
107 }
108 
109 /*
110  * Disables RTC peripheral to start counting time
111  */
XMC_RTC_Stop(void)112 void XMC_RTC_Stop(void)
113 {
114   while((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_CTR_Msk) != 0U)
115   {
116     /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
117   }
118   RTC->CTR &= ~(uint32_t)RTC_CTR_ENB_Msk;
119 }
120 
121 /*
122  * Sets the RTC module prescaler value
123  */
XMC_RTC_SetPrescaler(uint16_t prescaler)124 void XMC_RTC_SetPrescaler(uint16_t prescaler)
125 {
126   XMC_ASSERT("XMC_RTC_SetPrescaler:Wrong prescaler value", (prescaler < XMC_RTC_MAXPRESCALER));
127 
128   while((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_CTR_Msk) != 0U)
129   {
130     /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
131   }
132   RTC->CTR = (RTC->CTR & ~(uint32_t)RTC_CTR_DIV_Msk) |
133              ((uint32_t)prescaler << (uint32_t)RTC_CTR_DIV_Pos);
134 }
135 
136 /*
137  * Sets the RTC_TIM0, RTC_TIM1 registers with time values
138  */
XMC_RTC_SetTime(const XMC_RTC_TIME_t * const time)139 void XMC_RTC_SetTime(const XMC_RTC_TIME_t *const time)
140 {
141   XMC_ASSERT("XMC_RTC_SetTime:Wrong seconds value", ((uint32_t)time->seconds < XMC_RTC_MAXSECONDS));
142   XMC_ASSERT("XMC_RTC_SetTime:Wrong minutes value", ((uint32_t)time->minutes < XMC_RTC_MAXMINUTES));
143   XMC_ASSERT("XMC_RTC_SetTime:Wrong hours value", ((uint32_t)time->hours < XMC_RTC_MAXHOURS));
144   XMC_ASSERT("XMC_RTC_SetTime:Wrong week day value", ((uint32_t)time->daysofweek < XMC_RTC_MAXDAYSOFWEEK));
145   XMC_ASSERT("XMC_RTC_SetTime:Wrong month value", ((uint32_t)time->month < XMC_RTC_MAXMONTH));
146   XMC_ASSERT("XMC_RTC_SetTime:Wrong year value", ((uint32_t)time->year < XMC_RTC_MAXYEAR));
147 
148   #if (XMC_RTC_INIT_SEQUENCE == 1U)
149       while ((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_TIM0_Msk) != 0U)
150       {
151          /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
152       }
153       RTC->TIM0 = time->raw0;
154 
155       while ((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_TIM1_Msk) != 0U)
156       {
157         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
158       }
159       RTC->TIM1 = time->raw1;
160   #endif
161   #if (XMC_RTC_INIT_SEQUENCE == 0U)
162       while ((XMC_SCU_GetMirrorStatus() & (SCU_GENERAL_MIRRSTS_RTC_TIM0_Msk | SCU_GENERAL_MIRRSTS_RTC_TIM1_Msk)) != 0U)
163       {
164         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
165       }
166       RTC->TIM0 = time->raw0;
167       RTC->TIM1 = time->raw1;	;
168   #endif
169 }
170 
171 /*
172  * Gets the RTC module time value
173  */
XMC_RTC_GetTime(XMC_RTC_TIME_t * const time)174 void XMC_RTC_GetTime(XMC_RTC_TIME_t *const time)
175 {
176   time->raw0 = RTC->TIM0;
177   time->raw1 = RTC->TIM1;
178 }
179 
180 /*
181  * Sets the RTC module time values in standard format
182  */
XMC_RTC_SetTimeStdFormat(const struct tm * const stdtime)183 void XMC_RTC_SetTimeStdFormat(const struct tm *const stdtime)
184 {
185 
186   XMC_RTC_TIME_t time;
187 
188   time.seconds = stdtime->tm_sec;
189   time.minutes = stdtime->tm_min;
190   time.hours = stdtime->tm_hour;
191   time.days = stdtime->tm_mday - 1;
192   time.month = stdtime->tm_mon;
193   time.year = stdtime->tm_year + XMC_RTC_YEAR_OFFSET;
194   time.daysofweek = stdtime->tm_wday;
195 
196   XMC_RTC_SetTime(&time);
197 }
198 
199 /*
200  * Gets the RTC module time values in standard format
201  */
XMC_RTC_GetTimeStdFormat(struct tm * const stdtime)202 void XMC_RTC_GetTimeStdFormat(struct tm *const stdtime)
203 {
204   XMC_RTC_TIME_t time;
205   time.raw0 = RTC->TIM0;
206   time.raw1 = RTC->TIM1;
207 
208   stdtime->tm_sec = (int8_t)time.seconds;
209   stdtime->tm_min = (int8_t)time.minutes;
210   stdtime->tm_hour = (int8_t)time.hours;
211   stdtime->tm_mday = ((int8_t)time.days + (int8_t)1);
212   stdtime->tm_mon = (int8_t)time.month;
213   stdtime->tm_year = (int32_t)time.year - (int32_t)XMC_RTC_YEAR_OFFSET;
214   stdtime->tm_wday = (int8_t)time.daysofweek;
215 }
216 
217 /*
218  * Sets the RTC module alarm time value
219  */
XMC_RTC_SetAlarm(const XMC_RTC_ALARM_t * const alarm)220 void XMC_RTC_SetAlarm(const XMC_RTC_ALARM_t *const alarm)
221 {
222   XMC_ASSERT("XMC_RTC_SetAlarm:Wrong seconds value", ((uint32_t)alarm->seconds < XMC_RTC_MAXSECONDS));
223   XMC_ASSERT("XMC_RTC_SetAlarm:Wrong minutes value", ((uint32_t)alarm->minutes < XMC_RTC_MAXMINUTES));
224   XMC_ASSERT("XMC_RTC_SetAlarm:Wrong hours value", ((uint32_t)alarm->hours < XMC_RTC_MAXHOURS));
225   XMC_ASSERT("XMC_RTC_SetAlarm:Wrong month value", ((uint32_t)alarm->month < XMC_RTC_MAXMONTH));
226   XMC_ASSERT("XMC_RTC_SetAlarm:Wrong year value", ((uint32_t)alarm->year < XMC_RTC_MAXYEAR));
227 
228   #if (XMC_RTC_INIT_SEQUENCE == 1U)
229       while ((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_ATIM0_Msk) != 0U)
230       {
231         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
232       }
233       RTC->ATIM0 = alarm->raw0;
234 
235       while ((XMC_SCU_GetMirrorStatus() & SCU_GENERAL_MIRRSTS_RTC_ATIM1_Msk) != 0U)
236       {
237         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
238       }
239       RTC->ATIM1 = alarm->raw1;
240   #endif
241   #if (XMC_RTC_INIT_SEQUENCE == 0U)
242       while ((XMC_SCU_GetMirrorStatus() & (SCU_GENERAL_MIRRSTS_RTC_ATIM0_Msk | SCU_GENERAL_MIRRSTS_RTC_ATIM1_Msk)) != 0U)
243       {
244         /* check SCU_MIRRSTS to ensure that no transfer over serial interface is pending */
245       }
246       RTC->ATIM0 = alarm->raw0;
247       RTC->ATIM1 = alarm->raw1;
248   #endif
249 }
250 
251 /*
252  * Gets the RTC module alarm time value
253  */
XMC_RTC_GetAlarm(XMC_RTC_ALARM_t * const alarm)254 void XMC_RTC_GetAlarm(XMC_RTC_ALARM_t *const alarm)
255 {
256   alarm->raw0 = RTC->ATIM0;
257   alarm->raw1 = RTC->ATIM1;
258 }
259 
260 
261 /*
262  * Sets the RTC module alarm time value in standard format
263  */
XMC_RTC_SetAlarmStdFormat(const struct tm * const stdtime)264 void XMC_RTC_SetAlarmStdFormat(const struct tm *const stdtime)
265 {
266   XMC_RTC_ALARM_t alarm;
267 
268 
269   alarm.seconds = stdtime->tm_sec;
270   alarm.minutes = stdtime->tm_min;
271   alarm.hours = stdtime->tm_hour;
272   alarm.days = stdtime->tm_mday - 1;
273   alarm.month = stdtime->tm_mon;
274   alarm.year = stdtime->tm_year + XMC_RTC_YEAR_OFFSET;
275 
276   XMC_RTC_SetAlarm(&alarm);
277 }
278 
279 /*
280  * Gets the RTC module alarm time value in standard format
281  */
XMC_RTC_GetAlarmStdFormat(struct tm * const stdtime)282 void XMC_RTC_GetAlarmStdFormat(struct tm *const stdtime)
283 {
284   XMC_RTC_ALARM_t alarm;
285 
286   alarm.raw0 = RTC->ATIM0;
287   alarm.raw1 = RTC->ATIM1;
288 
289   stdtime->tm_sec = (int8_t)alarm.seconds;
290   stdtime->tm_min = (int8_t)alarm.minutes;
291   stdtime->tm_hour = (int8_t)alarm.hours;
292   stdtime->tm_mday = ((int8_t)alarm.days + (int8_t)1);
293   stdtime->tm_mon = (int8_t)alarm.month;
294   stdtime->tm_year = (int32_t)alarm.year - (int32_t)XMC_RTC_YEAR_OFFSET;
295 }
296 
297 /*
298  * Gets the RTC periodic and alarm event(s) status
299  */
XMC_RTC_GetEventStatus(void)300 uint32_t XMC_RTC_GetEventStatus(void)
301 {
302   return RTC->STSSR;
303 }
304