1 /*!
2 \file gd32f4xx_rtc.c
3 \brief RTC driver
4
5 \version 2016-08-15, V1.0.0, firmware for GD32F4xx
6 \version 2018-12-12, V2.0.0, firmware for GD32F4xx
7 \version 2020-09-30, V2.1.0, firmware for GD32F4xx
8 \version 2022-03-09, V3.0.0, firmware for GD32F4xx
9 */
10
11 /*
12 Copyright (c) 2022, GigaDevice Semiconductor Inc.
13
14 Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16
17 1. Redistributions of source code must retain the above copyright notice, this
18 list of conditions and the following disclaimer.
19 2. Redistributions in binary form must reproduce the above copyright notice,
20 this list of conditions and the following disclaimer in the documentation
21 and/or other materials provided with the distribution.
22 3. Neither the name of the copyright holder nor the names of its contributors
23 may be used to endorse or promote products derived from this software without
24 specific prior written permission.
25
26 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37
38
39 #include "gd32f4xx_rtc.h"
40
41 /* RTC timeout value */
42 #define RTC_WTWF_TIMEOUT ((uint32_t)0x00004000U) /*!< wakeup timer can be write flag timeout */
43 #define RTC_INITM_TIMEOUT ((uint32_t)0x00004000U) /*!< initialization state flag timeout */
44 #define RTC_RSYNF_TIMEOUT ((uint32_t)0x00008000U) /*!< register synchronization flag timeout */
45 #define RTC_HRFC_TIMEOUT ((uint32_t)0x20000000U) /*!< recalibration pending flag timeout */
46 #define RTC_SHIFTCTL_TIMEOUT ((uint32_t)0x00001000U) /*!< shift function operation pending flag timeout */
47 #define RTC_ALRMXWF_TIMEOUT ((uint32_t)0x00008000U) /*!< alarm configuration can be write flag timeout */
48
49 /*!
50 \brief reset most of the RTC registers
51 \param[in] none
52 \param[out] none
53 \retval ErrStatus: ERROR or SUCCESS
54 */
rtc_deinit(void)55 ErrStatus rtc_deinit(void)
56 {
57 ErrStatus error_status = ERROR;
58 volatile uint32_t time_index = RTC_WTWF_TIMEOUT;
59 uint32_t flag_status = RESET;
60 /* RTC_TAMP register is not under write protection */
61 RTC_TAMP = RTC_REGISTER_RESET;
62
63 /* disable the write protection */
64 RTC_WPK = RTC_UNLOCK_KEY1;
65 RTC_WPK = RTC_UNLOCK_KEY2;
66
67 /* enter init mode */
68 error_status = rtc_init_mode_enter();
69
70 if(ERROR != error_status) {
71 /* reset RTC_CTL register, but RTC_CTL[2��0] */
72 RTC_CTL &= (RTC_REGISTER_RESET | RTC_CTL_WTCS);
73 /* before reset RTC_TIME and RTC_DATE, BPSHAD bit in RTC_CTL should be reset as the condition.
74 in order to read calendar from shadow register, not the real registers being reset */
75 RTC_TIME = RTC_REGISTER_RESET;
76 RTC_DATE = RTC_DATE_RESET;
77
78 RTC_PSC = RTC_PSC_RESET;
79 /* only when RTC_CTL_WTEN=0 and RTC_STAT_WTWF=1 can write RTC_CTL[2��0] */
80 /* wait until the WTWF flag to be set */
81 do {
82 flag_status = RTC_STAT & RTC_STAT_WTWF;
83 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
84
85 if((uint32_t)RESET == flag_status) {
86 error_status = ERROR;
87 } else {
88 RTC_CTL &= RTC_REGISTER_RESET;
89 RTC_WUT = RTC_WUT_RESET;
90 RTC_COSC = RTC_REGISTER_RESET;
91 /* to write RTC_ALRMxSS register, ALRMxEN bit in RTC_CTL register should be reset as the condition */
92 RTC_ALRM0TD = RTC_REGISTER_RESET;
93 RTC_ALRM1TD = RTC_REGISTER_RESET;
94 RTC_ALRM0SS = RTC_REGISTER_RESET;
95 RTC_ALRM1SS = RTC_REGISTER_RESET;
96 /* reset RTC_STAT register, also exit init mode.
97 at the same time, RTC_STAT_SOPF bit is reset, as the condition to reset RTC_SHIFTCTL register later */
98 RTC_STAT = RTC_STAT_RESET;
99 /* reset RTC_SHIFTCTL and RTC_HRFC register, this can be done without the init mode */
100 RTC_SHIFTCTL = RTC_REGISTER_RESET;
101 RTC_HRFC = RTC_REGISTER_RESET;
102 error_status = rtc_register_sync_wait();
103 }
104 }
105
106 /* enable the write protection */
107 RTC_WPK = RTC_LOCK_KEY;
108
109 return error_status;
110 }
111
112 /*!
113 \brief initialize RTC registers
114 \param[in] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains
115 parameters for initialization of the rtc peripheral
116 members of the structure and the member values are shown as below:
117 year: 0x0 - 0x99(BCD format)
118 month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN,
119 RTC_JUL, RTC_AUG, RTC_SEP, RTC_OCT, RTC_NOV, RTC_DEC
120 date: 0x1 - 0x31(BCD format)
121 day_of_week: RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY
122 RTC_FRIDAY, RTC_SATURDAY, RTC_SUNDAY
123 hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format chose
124 minute: 0x0 - 0x59(BCD format)
125 second: 0x0 - 0x59(BCD format)
126 factor_asyn: 0x0 - 0x7F
127 factor_syn: 0x0 - 0x7FFF
128 am_pm: RTC_AM, RTC_PM
129 display_format: RTC_24HOUR, RTC_12HOUR
130 \param[out] none
131 \retval ErrStatus: ERROR or SUCCESS
132 */
rtc_init(rtc_parameter_struct * rtc_initpara_struct)133 ErrStatus rtc_init(rtc_parameter_struct *rtc_initpara_struct)
134 {
135 ErrStatus error_status = ERROR;
136 uint32_t reg_time = 0U, reg_date = 0U;
137
138 reg_date = (DATE_YR(rtc_initpara_struct->year) | \
139 DATE_DOW(rtc_initpara_struct->day_of_week) | \
140 DATE_MON(rtc_initpara_struct->month) | \
141 DATE_DAY(rtc_initpara_struct->date));
142
143 reg_time = (rtc_initpara_struct->am_pm | \
144 TIME_HR(rtc_initpara_struct->hour) | \
145 TIME_MN(rtc_initpara_struct->minute) | \
146 TIME_SC(rtc_initpara_struct->second));
147
148 /* 1st: disable the write protection */
149 RTC_WPK = RTC_UNLOCK_KEY1;
150 RTC_WPK = RTC_UNLOCK_KEY2;
151
152 /* 2nd: enter init mode */
153 error_status = rtc_init_mode_enter();
154
155 if(ERROR != error_status) {
156 RTC_PSC = (uint32_t)(PSC_FACTOR_A(rtc_initpara_struct->factor_asyn) | \
157 PSC_FACTOR_S(rtc_initpara_struct->factor_syn));
158
159 RTC_TIME = (uint32_t)reg_time;
160 RTC_DATE = (uint32_t)reg_date;
161
162 RTC_CTL &= (uint32_t)(~RTC_CTL_CS);
163 RTC_CTL |= rtc_initpara_struct->display_format;
164
165 /* 3rd: exit init mode */
166 rtc_init_mode_exit();
167
168 /* 4th: wait the RSYNF flag to set */
169 error_status = rtc_register_sync_wait();
170 }
171
172 /* 5th: enable the write protection */
173 RTC_WPK = RTC_LOCK_KEY;
174
175 return error_status;
176 }
177
178 /*!
179 \brief enter RTC init mode
180 \param[in] none
181 \param[out] none
182 \retval ErrStatus: ERROR or SUCCESS
183 */
rtc_init_mode_enter(void)184 ErrStatus rtc_init_mode_enter(void)
185 {
186 volatile uint32_t time_index = RTC_INITM_TIMEOUT;
187 uint32_t flag_status = RESET;
188 ErrStatus error_status = ERROR;
189
190 /* check whether it has been in init mode */
191 if((uint32_t)RESET == (RTC_STAT & RTC_STAT_INITF)) {
192 RTC_STAT |= RTC_STAT_INITM;
193
194 /* wait until the INITF flag to be set */
195 do {
196 flag_status = RTC_STAT & RTC_STAT_INITF;
197 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
198
199 if((uint32_t)RESET != flag_status) {
200 error_status = SUCCESS;
201 }
202 } else {
203 error_status = SUCCESS;
204 }
205 return error_status;
206 }
207
208 /*!
209 \brief exit RTC init mode
210 \param[in] none
211 \param[out] none
212 \retval none
213 */
rtc_init_mode_exit(void)214 void rtc_init_mode_exit(void)
215 {
216 RTC_STAT &= (uint32_t)(~RTC_STAT_INITM);
217 }
218
219 /*!
220 \brief wait until RTC_TIME and RTC_DATE registers are synchronized with APB clock, and the shadow
221 registers are updated
222 \param[in] none
223 \param[out] none
224 \retval ErrStatus: ERROR or SUCCESS
225 */
rtc_register_sync_wait(void)226 ErrStatus rtc_register_sync_wait(void)
227 {
228 volatile uint32_t time_index = RTC_RSYNF_TIMEOUT;
229 uint32_t flag_status = RESET;
230 ErrStatus error_status = ERROR;
231
232 if((uint32_t)RESET == (RTC_CTL & RTC_CTL_BPSHAD)) {
233 /* disable the write protection */
234 RTC_WPK = RTC_UNLOCK_KEY1;
235 RTC_WPK = RTC_UNLOCK_KEY2;
236
237 /* firstly clear RSYNF flag */
238 RTC_STAT &= (uint32_t)(~RTC_STAT_RSYNF);
239
240 /* wait until RSYNF flag to be set */
241 do {
242 flag_status = RTC_STAT & RTC_STAT_RSYNF;
243 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
244
245 if((uint32_t)RESET != flag_status) {
246 error_status = SUCCESS;
247 }
248
249 /* enable the write protection */
250 RTC_WPK = RTC_LOCK_KEY;
251 } else {
252 error_status = SUCCESS;
253 }
254
255 return error_status;
256 }
257
258 /*!
259 \brief get current time and date
260 \param[in] none
261 \param[out] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains
262 parameters for initialization of the rtc peripheral
263 members of the structure and the member values are shown as below:
264 year: 0x0 - 0x99(BCD format)
265 month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN,
266 RTC_JUL, RTC_AUG, RTC_SEP, RTC_OCT, RTC_NOV, RTC_DEC
267 date: 0x1 - 0x31(BCD format)
268 day_of_week: RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY
269 RTC_FRIDAY, RTC_SATURDAY, RTC_SUNDAY
270 hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format chose
271 minute: 0x0 - 0x59(BCD format)
272 second: 0x0 - 0x59(BCD format)
273 factor_asyn: 0x0 - 0x7F
274 factor_syn: 0x0 - 0x7FFF
275 am_pm: RTC_AM, RTC_PM
276 display_format: RTC_24HOUR, RTC_12HOUR
277 \retval none
278 */
rtc_current_time_get(rtc_parameter_struct * rtc_initpara_struct)279 void rtc_current_time_get(rtc_parameter_struct *rtc_initpara_struct)
280 {
281 uint32_t temp_tr = 0U, temp_dr = 0U, temp_pscr = 0U, temp_ctlr = 0U;
282
283 temp_tr = (uint32_t)RTC_TIME;
284 temp_dr = (uint32_t)RTC_DATE;
285 temp_pscr = (uint32_t)RTC_PSC;
286 temp_ctlr = (uint32_t)RTC_CTL;
287
288 /* get current time and construct rtc_parameter_struct structure */
289 rtc_initpara_struct->year = (uint8_t)GET_DATE_YR(temp_dr);
290 rtc_initpara_struct->month = (uint8_t)GET_DATE_MON(temp_dr);
291 rtc_initpara_struct->date = (uint8_t)GET_DATE_DAY(temp_dr);
292 rtc_initpara_struct->day_of_week = (uint8_t)GET_DATE_DOW(temp_dr);
293 rtc_initpara_struct->hour = (uint8_t)GET_TIME_HR(temp_tr);
294 rtc_initpara_struct->minute = (uint8_t)GET_TIME_MN(temp_tr);
295 rtc_initpara_struct->second = (uint8_t)GET_TIME_SC(temp_tr);
296 rtc_initpara_struct->factor_asyn = (uint16_t)GET_PSC_FACTOR_A(temp_pscr);
297 rtc_initpara_struct->factor_syn = (uint16_t)GET_PSC_FACTOR_S(temp_pscr);
298 rtc_initpara_struct->am_pm = (uint32_t)(temp_pscr & RTC_TIME_PM);
299 rtc_initpara_struct->display_format = (uint32_t)(temp_ctlr & RTC_CTL_CS);
300 }
301
302 /*!
303 \brief get current subsecond value
304 \param[in] none
305 \param[out] none
306 \retval current subsecond value
307 */
rtc_subsecond_get(void)308 uint32_t rtc_subsecond_get(void)
309 {
310 uint32_t reg = 0U;
311 /* if BPSHAD bit is reset, reading RTC_SS will lock RTC_TIME and RTC_DATE automatically */
312 reg = (uint32_t)RTC_SS;
313 /* read RTC_DATE to unlock the 3 shadow registers */
314 (void)(RTC_DATE);
315
316 return reg;
317 }
318
319 /*!
320 \brief configure RTC alarm
321 \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1
322 \param[in] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains
323 parameters for RTC alarm configuration
324 members of the structure and the member values are shown as below:
325 alarm_mask: RTC_ALARM_NONE_MASK, RTC_ALARM_DATE_MASK, RTC_ALARM_HOUR_MASK
326 RTC_ALARM_MINUTE_MASK, RTC_ALARM_SECOND_MASK, RTC_ALARM_ALL_MASK
327 weekday_or_date: RTC_ALARM_DATE_SELECTED, RTC_ALARM_WEEKDAY_SELECTED
328 alarm_day: 1) 0x1 - 0x31(BCD format) if RTC_ALARM_DATE_SELECTED is set
329 2) RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY, RTC_FRIDAY,
330 RTC_SATURDAY, RTC_SUNDAY if RTC_ALARM_WEEKDAY_SELECTED is set
331 alarm_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format
332 alarm_minute: 0x0 - 0x59(BCD format)
333 alarm_second: 0x0 - 0x59(BCD format)
334 am_pm: RTC_AM, RTC_PM
335 \param[out] none
336 \retval none
337 */
rtc_alarm_config(uint8_t rtc_alarm,rtc_alarm_struct * rtc_alarm_time)338 void rtc_alarm_config(uint8_t rtc_alarm, rtc_alarm_struct *rtc_alarm_time)
339 {
340 uint32_t reg_alrmtd = 0U;
341
342 reg_alrmtd = (rtc_alarm_time->alarm_mask | \
343 rtc_alarm_time->weekday_or_date | \
344 rtc_alarm_time->am_pm | \
345 ALRMTD_DAY(rtc_alarm_time->alarm_day) | \
346 ALRMTD_HR(rtc_alarm_time->alarm_hour) | \
347 ALRMTD_MN(rtc_alarm_time->alarm_minute) | \
348 ALRMTD_SC(rtc_alarm_time->alarm_second));
349
350 /* disable the write protection */
351 RTC_WPK = RTC_UNLOCK_KEY1;
352 RTC_WPK = RTC_UNLOCK_KEY2;
353
354 if(RTC_ALARM0 == rtc_alarm) {
355 RTC_ALRM0TD = (uint32_t)reg_alrmtd;
356
357 } else {
358 RTC_ALRM1TD = (uint32_t)reg_alrmtd;
359 }
360 /* enable the write protection */
361 RTC_WPK = RTC_LOCK_KEY;
362 }
363
364 /*!
365 \brief configure subsecond of RTC alarm
366 \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1
367 \param[in] mask_subsecond: alarm subsecond mask
368 \arg RTC_MASKSSC_0_14: mask alarm subsecond configuration
369 \arg RTC_MASKSSC_1_14: mask RTC_ALRMXSS_SSC[14:1], and RTC_ALRMXSS_SSC[0] is to be compared
370 \arg RTC_MASKSSC_2_14: mask RTC_ALRMXSS_SSC[14:2], and RTC_ALRMXSS_SSC[1:0] is to be compared
371 \arg RTC_MASKSSC_3_14: mask RTC_ALRMXSS_SSC[14:3], and RTC_ALRMXSS_SSC[2:0] is to be compared
372 \arg RTC_MASKSSC_4_14: mask RTC_ALRMXSS_SSC[14:4]], and RTC_ALRMXSS_SSC[3:0] is to be compared
373 \arg RTC_MASKSSC_5_14: mask RTC_ALRMXSS_SSC[14:5], and RTC_ALRMXSS_SSC[4:0] is to be compared
374 \arg RTC_MASKSSC_6_14: mask RTC_ALRMXSS_SSC[14:6], and RTC_ALRMXSS_SSC[5:0] is to be compared
375 \arg RTC_MASKSSC_7_14: mask RTC_ALRMXSS_SSC[14:7], and RTC_ALRMXSS_SSC[6:0] is to be compared
376 \arg RTC_MASKSSC_8_14: mask RTC_ALRMXSS_SSC[14:8], and RTC_ALRMXSS_SSC[7:0] is to be compared
377 \arg RTC_MASKSSC_9_14: mask RTC_ALRMXSS_SSC[14:9], and RTC_ALRMXSS_SSC[8:0] is to be compared
378 \arg RTC_MASKSSC_10_14: mask RTC_ALRMXSS_SSC[14:10], and RTC_ALRMXSS_SSC[9:0] is to be compared
379 \arg RTC_MASKSSC_11_14: mask RTC_ALRMXSS_SSC[14:11], and RTC_ALRMXSS_SSC[10:0] is to be compared
380 \arg RTC_MASKSSC_12_14: mask RTC_ALRMXSS_SSC[14:12], and RTC_ALRMXSS_SSC[11:0] is to be compared
381 \arg RTC_MASKSSC_13_14: mask RTC_ALRMXSS_SSC[14:13], and RTC_ALRMXSS_SSC[12:0] is to be compared
382 \arg RTC_MASKSSC_14: mask RTC_ALRMXSS_SSC[14], and RTC_ALRMXSS_SSC[13:0] is to be compared
383 \arg RTC_MASKSSC_NONE: mask none, and RTC_ALRMXSS_SSC[14:0] is to be compared
384 \param[in] subsecond: alarm subsecond value(0x000 - 0x7FFF)
385 \param[out] none
386 \retval none
387 */
rtc_alarm_subsecond_config(uint8_t rtc_alarm,uint32_t mask_subsecond,uint32_t subsecond)388 void rtc_alarm_subsecond_config(uint8_t rtc_alarm, uint32_t mask_subsecond, uint32_t subsecond)
389 {
390 /* disable the write protection */
391 RTC_WPK = RTC_UNLOCK_KEY1;
392 RTC_WPK = RTC_UNLOCK_KEY2;
393
394 if(RTC_ALARM0 == rtc_alarm) {
395 RTC_ALRM0SS = mask_subsecond | subsecond;
396 } else {
397 RTC_ALRM1SS = mask_subsecond | subsecond;
398 }
399 /* enable the write protection */
400 RTC_WPK = RTC_LOCK_KEY;
401 }
402
403 /*!
404 \brief get RTC alarm
405 \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1
406 \param[out] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains
407 parameters for RTC alarm configuration
408 members of the structure and the member values are shown as below:
409 alarm_mask: RTC_ALARM_NONE_MASK, RTC_ALARM_DATE_MASK, RTC_ALARM_HOUR_MASK
410 RTC_ALARM_MINUTE_MASK, RTC_ALARM_SECOND_MASK, RTC_ALARM_ALL_MASK
411 weekday_or_date: RTC_ALARM_DATE_SELECTED, RTC_ALARM_WEEKDAY_SELECTED
412 alarm_day: 1) 0x1 - 0x31(BCD format) if RTC_ALARM_DATE_SELECTED is set
413 2) RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY, RTC_FRIDAY,
414 RTC_SATURDAY, RTC_SUNDAY if RTC_ALARM_WEEKDAY_SELECTED is set
415 alarm_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format
416 alarm_minute: 0x0 - 0x59(BCD format)
417 alarm_second: 0x0 - 0x59(BCD format)
418 am_pm: RTC_AM, RTC_PM
419 \retval none
420 */
rtc_alarm_get(uint8_t rtc_alarm,rtc_alarm_struct * rtc_alarm_time)421 void rtc_alarm_get(uint8_t rtc_alarm, rtc_alarm_struct *rtc_alarm_time)
422 {
423 uint32_t reg_alrmtd = 0U;
424
425 /* get the value of RTC_ALRM0TD register */
426 if(RTC_ALARM0 == rtc_alarm) {
427 reg_alrmtd = RTC_ALRM0TD;
428 } else {
429 reg_alrmtd = RTC_ALRM1TD;
430 }
431 /* get alarm parameters and construct the rtc_alarm_struct structure */
432 rtc_alarm_time->alarm_mask = reg_alrmtd & RTC_ALARM_ALL_MASK;
433 rtc_alarm_time->am_pm = (uint32_t)(reg_alrmtd & RTC_ALRMXTD_PM);
434 rtc_alarm_time->weekday_or_date = (uint32_t)(reg_alrmtd & RTC_ALRMXTD_DOWS);
435 rtc_alarm_time->alarm_day = (uint8_t)GET_ALRMTD_DAY(reg_alrmtd);
436 rtc_alarm_time->alarm_hour = (uint8_t)GET_ALRMTD_HR(reg_alrmtd);
437 rtc_alarm_time->alarm_minute = (uint8_t)GET_ALRMTD_MN(reg_alrmtd);
438 rtc_alarm_time->alarm_second = (uint8_t)GET_ALRMTD_SC(reg_alrmtd);
439 }
440
441 /*!
442 \brief get RTC alarm subsecond
443 \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1
444 \param[out] none
445 \retval RTC alarm subsecond value
446 */
rtc_alarm_subsecond_get(uint8_t rtc_alarm)447 uint32_t rtc_alarm_subsecond_get(uint8_t rtc_alarm)
448 {
449 if(RTC_ALARM0 == rtc_alarm) {
450 return ((uint32_t)(RTC_ALRM0SS & RTC_ALRM0SS_SSC));
451 } else {
452 return ((uint32_t)(RTC_ALRM1SS & RTC_ALRM1SS_SSC));
453 }
454 }
455
456 /*!
457 \brief enable RTC alarm
458 \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1
459 \param[out] none
460 \retval none
461 */
rtc_alarm_enable(uint8_t rtc_alarm)462 void rtc_alarm_enable(uint8_t rtc_alarm)
463 {
464 /* disable the write protection */
465 RTC_WPK = RTC_UNLOCK_KEY1;
466 RTC_WPK = RTC_UNLOCK_KEY2;
467
468 if(RTC_ALARM0 == rtc_alarm) {
469 RTC_CTL |= RTC_CTL_ALRM0EN;
470 } else {
471 RTC_CTL |= RTC_CTL_ALRM1EN;
472 }
473 /* enable the write protection */
474 RTC_WPK = RTC_LOCK_KEY;
475 }
476
477 /*!
478 \brief disable RTC alarm
479 \param[in] rtc_alarm: RTC_ALARM0 or RTC_ALARM1
480 \param[out] none
481 \retval ErrStatus: ERROR or SUCCESS
482 */
rtc_alarm_disable(uint8_t rtc_alarm)483 ErrStatus rtc_alarm_disable(uint8_t rtc_alarm)
484 {
485 volatile uint32_t time_index = RTC_ALRMXWF_TIMEOUT;
486 ErrStatus error_status = ERROR;
487 uint32_t flag_status = RESET;
488
489 /* disable the write protection */
490 RTC_WPK = RTC_UNLOCK_KEY1;
491 RTC_WPK = RTC_UNLOCK_KEY2;
492
493 /* clear the state of alarm */
494 if(RTC_ALARM0 == rtc_alarm) {
495 RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM0EN);
496 /* wait until ALRM0WF flag to be set after the alarm is disabled */
497 do {
498 flag_status = RTC_STAT & RTC_STAT_ALRM0WF;
499 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
500 } else {
501 RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM1EN);
502 /* wait until ALRM1WF flag to be set after the alarm is disabled */
503 do {
504 flag_status = RTC_STAT & RTC_STAT_ALRM1WF;
505 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
506 }
507
508 if((uint32_t)RESET != flag_status) {
509 error_status = SUCCESS;
510 }
511
512 /* enable the write protection */
513 RTC_WPK = RTC_LOCK_KEY;
514
515 return error_status;
516 }
517
518 /*!
519 \brief enable RTC time-stamp
520 \param[in] edge: specify which edge to detect of time-stamp
521 \arg RTC_TIMESTAMP_RISING_EDGE: rising edge is valid event edge for timestamp event
522 \arg RTC_TIMESTAMP_FALLING_EDGE: falling edge is valid event edge for timestamp event
523 \param[out] none
524 \retval none
525 */
rtc_timestamp_enable(uint32_t edge)526 void rtc_timestamp_enable(uint32_t edge)
527 {
528 uint32_t reg_ctl = 0U;
529
530 /* clear the bits to be configured in RTC_CTL */
531 reg_ctl = (uint32_t)(RTC_CTL & (uint32_t)(~(RTC_CTL_TSEG | RTC_CTL_TSEN)));
532
533 /* new configuration */
534 reg_ctl |= (uint32_t)(edge | RTC_CTL_TSEN);
535
536 /* disable the write protection */
537 RTC_WPK = RTC_UNLOCK_KEY1;
538 RTC_WPK = RTC_UNLOCK_KEY2;
539
540 RTC_CTL = (uint32_t)reg_ctl;
541
542 /* enable the write protection */
543 RTC_WPK = RTC_LOCK_KEY;
544 }
545
546 /*!
547 \brief disable RTC time-stamp
548 \param[in] none
549 \param[out] none
550 \retval none
551 */
rtc_timestamp_disable(void)552 void rtc_timestamp_disable(void)
553 {
554 /* disable the write protection */
555 RTC_WPK = RTC_UNLOCK_KEY1;
556 RTC_WPK = RTC_UNLOCK_KEY2;
557
558 /* clear the TSEN bit */
559 RTC_CTL &= (uint32_t)(~ RTC_CTL_TSEN);
560
561 /* enable the write protection */
562 RTC_WPK = RTC_LOCK_KEY;
563 }
564
565 /*!
566 \brief get RTC timestamp time and date
567 \param[in] none
568 \param[out] rtc_timestamp: pointer to a rtc_timestamp_struct structure which contains
569 parameters for RTC time-stamp configuration
570 members of the structure and the member values are shown as below:
571 timestamp_month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN,
572 RTC_JUL, RTC_AUG, RTC_SEP, RTC_OCT, RTC_NOV, RTC_DEC
573 timestamp_date: 0x1 - 0x31(BCD format)
574 timestamp_day: RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY, RTC_FRIDAY,
575 RTC_SATURDAY, RTC_SUNDAY if RTC_ALARM_WEEKDAY_SELECTED is set
576 timestamp_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format
577 timestamp_minute: 0x0 - 0x59(BCD format)
578 timestamp_second: 0x0 - 0x59(BCD format)
579 am_pm: RTC_AM, RTC_PM
580 \retval none
581 */
rtc_timestamp_get(rtc_timestamp_struct * rtc_timestamp)582 void rtc_timestamp_get(rtc_timestamp_struct *rtc_timestamp)
583 {
584 uint32_t temp_tts = 0U, temp_dts = 0U;
585
586 /* get the value of time_stamp registers */
587 temp_tts = (uint32_t)RTC_TTS;
588 temp_dts = (uint32_t)RTC_DTS;
589
590 /* get timestamp time and construct the rtc_timestamp_struct structure */
591 rtc_timestamp->am_pm = (uint32_t)(temp_tts & RTC_TTS_PM);
592 rtc_timestamp->timestamp_month = (uint8_t)GET_DTS_MON(temp_dts);
593 rtc_timestamp->timestamp_date = (uint8_t)GET_DTS_DAY(temp_dts);
594 rtc_timestamp->timestamp_day = (uint8_t)GET_DTS_DOW(temp_dts);
595 rtc_timestamp->timestamp_hour = (uint8_t)GET_TTS_HR(temp_tts);
596 rtc_timestamp->timestamp_minute = (uint8_t)GET_TTS_MN(temp_tts);
597 rtc_timestamp->timestamp_second = (uint8_t)GET_TTS_SC(temp_tts);
598 }
599
600 /*!
601 \brief get RTC time-stamp subsecond
602 \param[in] none
603 \param[out] none
604 \retval RTC time-stamp subsecond value
605 */
rtc_timestamp_subsecond_get(void)606 uint32_t rtc_timestamp_subsecond_get(void)
607 {
608 return ((uint32_t)RTC_SSTS);
609 }
610
611 /*!
612 \brief RTC time-stamp mapping
613 \param[in] rtc_af:
614 \arg RTC_AF0_TIMESTAMP: RTC_AF0 use for timestamp
615 \arg RTC_AF1_TIMESTAMP: RTC_AF1 use for timestamp
616 \param[out] none
617 \retval none
618 */
rtc_timestamp_pin_map(uint32_t rtc_af)619 void rtc_timestamp_pin_map(uint32_t rtc_af)
620 {
621 RTC_TAMP &= ~RTC_TAMP_TSSEL;
622 RTC_TAMP |= rtc_af;
623 }
624
625 /*!
626 \brief enable RTC tamper
627 \param[in] rtc_tamper: pointer to a rtc_tamper_struct structure which contains
628 parameters for RTC tamper configuration
629 members of the structure and the member values are shown as below:
630 detecting tamper event can using edge mode or level mode
631 (1) using edge mode configuration:
632 tamper_source: RTC_TAMPER0, RTC_TAMPER1
633 tamper_trigger: RTC_TAMPER_TRIGGER_EDGE_RISING, RTC_TAMPER_TRIGGER_EDGE_FALLING
634 tamper_filter: RTC_FLT_EDGE
635 tamper_with_timestamp: DISABLE, ENABLE
636 (2) using level mode configuration:
637 tamper_source: RTC_TAMPER0, RTC_TAMPER1
638 tamper_trigger:RTC_TAMPER_TRIGGER_LEVEL_LOW, RTC_TAMPER_TRIGGER_LEVEL_HIGH
639 tamper_filter: RTC_FLT_2S, RTC_FLT_4S, RTC_FLT_8S
640 tamper_sample_frequency: RTC_FREQ_DIV32768, RTC_FREQ_DIV16384, RTC_FREQ_DIV8192,
641 RTC_FREQ_DIV4096, RTC_FREQ_DIV2048, RTC_FREQ_DIV1024,
642 RTC_FREQ_DIV512, RTC_FREQ_DIV256
643 tamper_precharge_enable: DISABLE, ENABLE
644 tamper_precharge_time: RTC_PRCH_1C, RTC_PRCH_2C, RTC_PRCH_4C, RTC_PRCH_8C
645 tamper_with_timestamp: DISABLE, ENABLE
646 \param[out] none
647 \retval none
648 */
rtc_tamper_enable(rtc_tamper_struct * rtc_tamper)649 void rtc_tamper_enable(rtc_tamper_struct *rtc_tamper)
650 {
651 /* disable tamper */
652 RTC_TAMP &= (uint32_t)~(rtc_tamper->tamper_source);
653
654 /* tamper filter must be used when the tamper source is voltage level detection */
655 RTC_TAMP &= (uint32_t)~RTC_TAMP_FLT;
656
657 /* the tamper source is voltage level detection */
658 if((uint32_t)(rtc_tamper->tamper_filter) != RTC_FLT_EDGE) {
659 RTC_TAMP &= (uint32_t)~(RTC_TAMP_DISPU | RTC_TAMP_PRCH | RTC_TAMP_FREQ | RTC_TAMP_FLT);
660
661 /* check if the tamper pin need precharge, if need, then configure the precharge time */
662 if(DISABLE == rtc_tamper->tamper_precharge_enable) {
663 RTC_TAMP |= (uint32_t)RTC_TAMP_DISPU;
664 } else {
665 RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_precharge_time);
666 }
667
668 RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_sample_frequency);
669 RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_filter);
670
671 /* configure the tamper trigger */
672 RTC_TAMP &= ((uint32_t)~((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS));
673 if(RTC_TAMPER_TRIGGER_LEVEL_LOW != rtc_tamper->tamper_trigger) {
674 RTC_TAMP |= (uint32_t)((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS);
675 }
676 } else {
677
678 /* configure the tamper trigger */
679 RTC_TAMP &= ((uint32_t)~((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS));
680 if(RTC_TAMPER_TRIGGER_EDGE_RISING != rtc_tamper->tamper_trigger) {
681 RTC_TAMP |= (uint32_t)((rtc_tamper->tamper_source) << RTC_TAMPER_TRIGGER_POS);
682 }
683 }
684
685 RTC_TAMP &= (uint32_t)~RTC_TAMP_TPTS;
686 if(DISABLE != rtc_tamper->tamper_with_timestamp) {
687 /* the tamper event also cause a time-stamp event */
688 RTC_TAMP |= (uint32_t)RTC_TAMP_TPTS;
689 }
690 /* enable tamper */
691 RTC_TAMP |= (uint32_t)(rtc_tamper->tamper_source);
692 }
693
694 /*!
695 \brief disable RTC tamper
696 \param[in] source: specify which tamper source to be disabled
697 \arg RTC_TAMPER0
698 \arg RTC_TAMPER1
699 \param[out] none
700 \retval none
701 */
rtc_tamper_disable(uint32_t source)702 void rtc_tamper_disable(uint32_t source)
703 {
704 /* disable tamper */
705 RTC_TAMP &= (uint32_t)~source;
706
707 }
708
709 /*!
710 \brief RTC tamper0 mapping
711 \param[in] rtc_af:
712 \arg RTC_AF0_TAMPER0: RTC_AF0 use for tamper0
713 \arg RTC_AF1_TAMPER0: RTC_AF1 use for tamper0
714 \param[out] none
715 \retval none
716 */
rtc_tamper0_pin_map(uint32_t rtc_af)717 void rtc_tamper0_pin_map(uint32_t rtc_af)
718 {
719 RTC_TAMP &= ~(RTC_TAMP_TP0EN | RTC_TAMP_TP0SEL);
720 RTC_TAMP |= rtc_af;
721 }
722
723 /*!
724 \brief enable specified RTC interrupt
725 \param[in] interrupt: specify which interrupt source to be enabled
726 \arg RTC_INT_TIMESTAMP: timestamp interrupt
727 \arg RTC_INT_ALARM0: alarm0 interrupt
728 \arg RTC_INT_ALARM1: alarm1 interrupt
729 \arg RTC_INT_TAMP: tamper detection interrupt
730 \arg RTC_INT_WAKEUP: wakeup timer interrupt
731 \param[out] none
732 \retval none
733 */
rtc_interrupt_enable(uint32_t interrupt)734 void rtc_interrupt_enable(uint32_t interrupt)
735 {
736 /* disable the write protection */
737 RTC_WPK = RTC_UNLOCK_KEY1;
738 RTC_WPK = RTC_UNLOCK_KEY2;
739
740 /* enable the interrupts in RTC_CTL register */
741 RTC_CTL |= (uint32_t)(interrupt & (uint32_t)~RTC_TAMP_TPIE);
742 /* enable the interrupts in RTC_TAMP register */
743 RTC_TAMP |= (uint32_t)(interrupt & RTC_TAMP_TPIE);
744
745 /* enable the write protection */
746 RTC_WPK = RTC_LOCK_KEY;
747 }
748
749 /*!
750 \brief disble specified RTC interrupt
751 \param[in] interrupt: specify which interrupt source to be disabled
752 \arg RTC_INT_TIMESTAMP: timestamp interrupt
753 \arg RTC_INT_ALARM0: alarm interrupt
754 \arg RTC_INT_ALARM1: alarm interrupt
755 \arg RTC_INT_TAMP: tamper detection interrupt
756 \arg RTC_INT_WAKEUP: wakeup timer interrupt
757 \param[out] none
758 \retval none
759 */
rtc_interrupt_disable(uint32_t interrupt)760 void rtc_interrupt_disable(uint32_t interrupt)
761 {
762 /* disable the write protection */
763 RTC_WPK = RTC_UNLOCK_KEY1;
764 RTC_WPK = RTC_UNLOCK_KEY2;
765
766 /* disable the interrupts in RTC_CTL register */
767 RTC_CTL &= (uint32_t)~(interrupt & (uint32_t)~RTC_TAMP_TPIE);
768 /* disable the interrupts in RTC_TAMP register */
769 RTC_TAMP &= (uint32_t)~(interrupt & RTC_TAMP_TPIE);
770
771 /* enable the write protection */
772 RTC_WPK = RTC_LOCK_KEY;
773 }
774
775 /*!
776 \brief check specified flag
777 \param[in] flag: specify which flag to check
778 \arg RTC_STAT_SCP: smooth calibration pending flag
779 \arg RTC_FLAG_TP1: RTC tamper 1 detected flag
780 \arg RTC_FLAG_TP0: RTC tamper 0 detected flag
781 \arg RTC_FLAG_TSOVR: time-stamp overflow flag
782 \arg RTC_FLAG_TS: time-stamp flag
783 \arg RTC_FLAG_ALRM0: alarm0 occurs flag
784 \arg RTC_FLAG_ALRM1: alarm1 occurs flag
785 \arg RTC_FLAG_WT: wakeup timer occurs flag
786 \arg RTC_FLAG_INIT: initialization state flag
787 \arg RTC_FLAG_RSYN: register synchronization flag
788 \arg RTC_FLAG_YCM: year configuration mark status flag
789 \arg RTC_FLAG_SOP: shift function operation pending flag
790 \arg RTC_FLAG_ALRM0W: alarm0 configuration can be write flag
791 \arg RTC_FLAG_ALRM1W: alarm1 configuration can be write flag
792 \arg RTC_FLAG_WTW: wakeup timer can be write flag
793 \param[out] none
794 \retval FlagStatus: SET or RESET
795 */
rtc_flag_get(uint32_t flag)796 FlagStatus rtc_flag_get(uint32_t flag)
797 {
798 FlagStatus flag_state = RESET;
799
800 if((uint32_t)RESET != (RTC_STAT & flag)) {
801 flag_state = SET;
802 }
803 return flag_state;
804 }
805
806 /*!
807 \brief clear specified flag
808 \arg RTC_FLAG_TP1: RTC tamper 1 detected flag
809 \arg RTC_FLAG_TP0: RTC tamper 0 detected flag
810 \arg RTC_FLAG_TSOVR: time-stamp overflow flag
811 \arg RTC_FLAG_TS: time-stamp flag
812 \arg RTC_FLAG_WT: wakeup timer occurs flag
813 \arg RTC_FLAG_ALARM0: alarm0 occurs flag
814 \arg RTC_FLAG_ALARM1: alarm1 occurs flag
815 \arg RTC_FLAG_RSYN: register synchronization flag
816 \param[out] none
817 \retval none
818 */
rtc_flag_clear(uint32_t flag)819 void rtc_flag_clear(uint32_t flag)
820 {
821 RTC_STAT &= (uint32_t)(~flag);
822 }
823
824 /*!
825 \brief configure rtc alarm output source
826 \param[in] source: specify signal to output
827 \arg RTC_ALARM0_HIGH: when the alarm0 flag is set, the output pin is high
828 \arg RTC_ALARM0_LOW: when the alarm0 flag is set, the output pin is low
829 \arg RTC_ALARM1_HIGH: when the alarm1 flag is set, the output pin is high
830 \arg RTC_ALARM1_LOW: when the alarm1 flag is set, the output pin is low
831 \arg RTC_WAKEUP_HIGH: when the wakeup flag is set, the output pin is high
832 \arg RTC_WAKEUP_LOW: when the wakeup flag is set, the output pin is low
833 \param[in] mode: specify the output pin mode when output alarm signal
834 \arg RTC_ALARM_OUTPUT_OD: open drain mode
835 \arg RTC_ALARM_OUTPUT_PP: push pull mode
836 \param[out] none
837 \retval none
838 */
rtc_alarm_output_config(uint32_t source,uint32_t mode)839 void rtc_alarm_output_config(uint32_t source, uint32_t mode)
840 {
841 /* disable the write protection */
842 RTC_WPK = RTC_UNLOCK_KEY1;
843 RTC_WPK = RTC_UNLOCK_KEY2;
844
845 RTC_CTL &= ~(RTC_CTL_OS | RTC_CTL_OPOL);
846 RTC_TAMP &= ~RTC_TAMP_AOT;
847
848 RTC_CTL |= (uint32_t)(source);
849 /* alarm output */
850 RTC_TAMP |= (uint32_t)(mode);
851
852 /* enable the write protection */
853 RTC_WPK = RTC_LOCK_KEY;
854 }
855
856 /*!
857 \brief configure rtc calibration output source
858 \param[in] source: specify signal to output
859 \arg RTC_CALIBRATION_512HZ: when the LSE freqency is 32768Hz and the RTC_PSC
860 is the default value, output 512Hz signal
861 \arg RTC_CALIBRATION_1HZ: when the LSE freqency is 32768Hz and the RTC_PSC
862 is the default value, output 1Hz signal
863 \param[out] none
864 \retval none
865 */
rtc_calibration_output_config(uint32_t source)866 void rtc_calibration_output_config(uint32_t source)
867 {
868 /* disable the write protection */
869 RTC_WPK = RTC_UNLOCK_KEY1;
870 RTC_WPK = RTC_UNLOCK_KEY2;
871
872 RTC_CTL &= (uint32_t)~(RTC_CTL_COEN | RTC_CTL_COS);
873
874 RTC_CTL |= (uint32_t)(source);
875 /* enable the write protection */
876 RTC_WPK = RTC_LOCK_KEY;
877 }
878
879 /*!
880 \brief adjust the daylight saving time by adding or substracting one hour from the current time
881 \param[in] operation: hour adjustment operation
882 \arg RTC_CTL_A1H: add one hour
883 \arg RTC_CTL_S1H: substract one hour
884 \param[out] none
885 \retval none
886 */
rtc_hour_adjust(uint32_t operation)887 void rtc_hour_adjust(uint32_t operation)
888 {
889 /* disable the write protection */
890 RTC_WPK = RTC_UNLOCK_KEY1;
891 RTC_WPK = RTC_UNLOCK_KEY2;
892
893 RTC_CTL |= (uint32_t)(operation);
894
895 /* enable the write protection */
896 RTC_WPK = RTC_LOCK_KEY;
897 }
898
899 /*!
900 \brief adjust RTC second or subsecond value of current time
901 \param[in] add: add 1s to current time or not
902 \arg RTC_SHIFT_ADD1S_RESET: no effect
903 \arg RTC_SHIFT_ADD1S_SET: add 1s to current time
904 \param[in] minus: number of subsecond to minus from current time(0x0 - 0x7FFF)
905 \param[out] none
906 \retval ErrStatus: ERROR or SUCCESS
907 */
rtc_second_adjust(uint32_t add,uint32_t minus)908 ErrStatus rtc_second_adjust(uint32_t add, uint32_t minus)
909 {
910 volatile uint32_t time_index = RTC_SHIFTCTL_TIMEOUT;
911 ErrStatus error_status = ERROR;
912 uint32_t flag_status = RESET;
913 uint32_t temp = 0U;
914 /* disable the write protection */
915 RTC_WPK = RTC_UNLOCK_KEY1;
916 RTC_WPK = RTC_UNLOCK_KEY2;
917
918 /* check if a shift operation is ongoing */
919 do {
920 flag_status = RTC_STAT & RTC_STAT_SOPF;
921 } while((--time_index > 0U) && ((uint32_t)RESET != flag_status));
922
923 /* check if the function of reference clock detection is disabled */
924 temp = RTC_CTL & RTC_CTL_REFEN;
925 if((RESET == flag_status) && (RESET == temp)) {
926 RTC_SHIFTCTL = (uint32_t)(add | SHIFTCTL_SFS(minus));
927 error_status = rtc_register_sync_wait();
928 }
929
930 /* enable the write protection */
931 RTC_WPK = RTC_LOCK_KEY;
932
933 return error_status;
934 }
935
936 /*!
937 \brief enable RTC bypass shadow registers function
938 \param[in] none
939 \param[out] none
940 \retval none
941 */
rtc_bypass_shadow_enable(void)942 void rtc_bypass_shadow_enable(void)
943 {
944 /* disable the write protection */
945 RTC_WPK = RTC_UNLOCK_KEY1;
946 RTC_WPK = RTC_UNLOCK_KEY2;
947
948 RTC_CTL |= RTC_CTL_BPSHAD;
949
950 /* enable the write protection */
951 RTC_WPK = RTC_LOCK_KEY;
952 }
953
954 /*!
955 \brief disable RTC bypass shadow registers function
956 \param[in] none
957 \param[out] none
958 \retval none
959 */
rtc_bypass_shadow_disable(void)960 void rtc_bypass_shadow_disable(void)
961 {
962 /* disable the write protection */
963 RTC_WPK = RTC_UNLOCK_KEY1;
964 RTC_WPK = RTC_UNLOCK_KEY2;
965
966 RTC_CTL &= ~RTC_CTL_BPSHAD;
967
968 /* enable the write protection */
969 RTC_WPK = RTC_LOCK_KEY;
970 }
971
972 /*!
973 \brief enable RTC reference clock detection function
974 \param[in] none
975 \param[out] none
976 \retval ErrStatus: ERROR or SUCCESS
977 */
rtc_refclock_detection_enable(void)978 ErrStatus rtc_refclock_detection_enable(void)
979 {
980 ErrStatus error_status = ERROR;
981
982 /* disable the write protection */
983 RTC_WPK = RTC_UNLOCK_KEY1;
984 RTC_WPK = RTC_UNLOCK_KEY2;
985
986 /* enter init mode */
987 error_status = rtc_init_mode_enter();
988
989 if(ERROR != error_status) {
990 RTC_CTL |= (uint32_t)RTC_CTL_REFEN;
991 /* exit init mode */
992 rtc_init_mode_exit();
993 }
994
995 /* enable the write protection */
996 RTC_WPK = RTC_LOCK_KEY;
997
998 return error_status;
999 }
1000
1001 /*!
1002 \brief disable RTC reference clock detection function
1003 \param[in] none
1004 \param[out] none
1005 \retval ErrStatus: ERROR or SUCCESS
1006 */
rtc_refclock_detection_disable(void)1007 ErrStatus rtc_refclock_detection_disable(void)
1008 {
1009 ErrStatus error_status = ERROR;
1010
1011 /* disable the write protection */
1012 RTC_WPK = RTC_UNLOCK_KEY1;
1013 RTC_WPK = RTC_UNLOCK_KEY2;
1014
1015 /* enter init mode */
1016 error_status = rtc_init_mode_enter();
1017
1018 if(ERROR != error_status) {
1019 RTC_CTL &= (uint32_t)~RTC_CTL_REFEN;
1020 /* exit init mode */
1021 rtc_init_mode_exit();
1022 }
1023
1024 /* enable the write protection */
1025 RTC_WPK = RTC_LOCK_KEY;
1026
1027 return error_status;
1028 }
1029
1030 /*!
1031 \brief enable RTC auto wakeup function
1032 \param[in] none
1033 \param[out] none
1034 \retval none
1035 */
rtc_wakeup_enable(void)1036 void rtc_wakeup_enable(void)
1037 {
1038 /* disable the write protection */
1039 RTC_WPK = RTC_UNLOCK_KEY1;
1040 RTC_WPK = RTC_UNLOCK_KEY2;
1041
1042 RTC_CTL |= RTC_CTL_WTEN;
1043
1044 /* enable the write protection */
1045 RTC_WPK = RTC_LOCK_KEY;
1046 }
1047
1048 /*!
1049 \brief disable RTC auto wakeup function
1050 \param[in] none
1051 \param[out] none
1052 \retval ErrStatus: ERROR or SUCCESS
1053 */
rtc_wakeup_disable(void)1054 ErrStatus rtc_wakeup_disable(void)
1055 {
1056 ErrStatus error_status = ERROR;
1057 volatile uint32_t time_index = RTC_WTWF_TIMEOUT;
1058 uint32_t flag_status = RESET;
1059 /* disable the write protection */
1060 RTC_WPK = RTC_UNLOCK_KEY1;
1061 RTC_WPK = RTC_UNLOCK_KEY2;
1062 RTC_CTL &= ~RTC_CTL_WTEN;
1063 /* wait until the WTWF flag to be set */
1064 do {
1065 flag_status = RTC_STAT & RTC_STAT_WTWF;
1066 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
1067
1068 if((uint32_t)RESET == flag_status) {
1069 error_status = ERROR;
1070 } else {
1071 error_status = SUCCESS;
1072 }
1073 /* enable the write protection */
1074 RTC_WPK = RTC_LOCK_KEY;
1075 return error_status;
1076 }
1077
1078 /*!
1079 \brief set RTC auto wakeup timer clock
1080 \param[in] wakeup_clock:
1081 \arg WAKEUP_RTCCK_DIV16: RTC auto wakeup timer clock is RTC clock divided by 16
1082 \arg WAKEUP_RTCCK_DIV8: RTC auto wakeup timer clock is RTC clock divided by 8
1083 \arg WAKEUP_RTCCK_DIV4: RTC auto wakeup timer clock is RTC clock divided by 4
1084 \arg WAKEUP_RTCCK_DIV2: RTC auto wakeup timer clock is RTC clock divided by 2
1085 \arg WAKEUP_CKSPRE: RTC auto wakeup timer clock is ckspre
1086 \arg WAKEUP_CKSPRE_2EXP16: RTC auto wakeup timer clock is ckspre and wakeup timer add 2exp16
1087 \param[out] none
1088 \retval ErrStatus: ERROR or SUCCESS
1089 */
rtc_wakeup_clock_set(uint8_t wakeup_clock)1090 ErrStatus rtc_wakeup_clock_set(uint8_t wakeup_clock)
1091 {
1092 ErrStatus error_status = ERROR;
1093 volatile uint32_t time_index = RTC_WTWF_TIMEOUT;
1094 uint32_t flag_status = RESET;
1095 /* disable the write protection */
1096 RTC_WPK = RTC_UNLOCK_KEY1;
1097 RTC_WPK = RTC_UNLOCK_KEY2;
1098 /* only when RTC_CTL_WTEN=0 and RTC_STAT_WTWF=1 can write RTC_CTL[2��0] */
1099 /* wait until the WTWF flag to be set */
1100 do {
1101 flag_status = RTC_STAT & RTC_STAT_WTWF;
1102 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
1103
1104 if((uint32_t)RESET == flag_status) {
1105 error_status = ERROR;
1106 } else {
1107 RTC_CTL &= (uint32_t)~ RTC_CTL_WTCS;
1108 RTC_CTL |= (uint32_t)wakeup_clock;
1109 error_status = SUCCESS;
1110 }
1111 /* enable the write protection */
1112 RTC_WPK = RTC_LOCK_KEY;
1113
1114 return error_status;
1115 }
1116
1117 /*!
1118 \brief set wakeup timer value
1119 \param[in] wakeup_timer: 0x0000-0xffff
1120 \param[out] none
1121 \retval ErrStatus: ERROR or SUCCESS
1122 */
rtc_wakeup_timer_set(uint16_t wakeup_timer)1123 ErrStatus rtc_wakeup_timer_set(uint16_t wakeup_timer)
1124 {
1125 ErrStatus error_status = ERROR;
1126 volatile uint32_t time_index = RTC_WTWF_TIMEOUT;
1127 uint32_t flag_status = RESET;
1128 /* disable the write protection */
1129 RTC_WPK = RTC_UNLOCK_KEY1;
1130 RTC_WPK = RTC_UNLOCK_KEY2;
1131 /* wait until the WTWF flag to be set */
1132 do {
1133 flag_status = RTC_STAT & RTC_STAT_WTWF;
1134 } while((--time_index > 0U) && ((uint32_t)RESET == flag_status));
1135
1136 if((uint32_t)RESET == flag_status) {
1137 error_status = ERROR;
1138 } else {
1139 RTC_WUT = (uint32_t)wakeup_timer;
1140 error_status = SUCCESS;
1141 }
1142 /* enable the write protection */
1143 RTC_WPK = RTC_LOCK_KEY;
1144 return error_status;
1145 }
1146
1147 /*!
1148 \brief get wakeup timer value
1149 \param[in] none
1150 \param[out] none
1151 \retval wakeup timer value
1152 */
rtc_wakeup_timer_get(void)1153 uint16_t rtc_wakeup_timer_get(void)
1154 {
1155 return (uint16_t)RTC_WUT;
1156 }
1157
1158 /*!
1159 \brief configure RTC smooth calibration
1160 \param[in] window: select calibration window
1161 \arg RTC_CALIBRATION_WINDOW_32S: 2exp20 RTCCLK cycles, 32s if RTCCLK = 32768 Hz
1162 \arg RTC_CALIBRATION_WINDOW_16S: 2exp19 RTCCLK cycles, 16s if RTCCLK = 32768 Hz
1163 \arg RTC_CALIBRATION_WINDOW_8S: 2exp18 RTCCLK cycles, 8s if RTCCLK = 32768 Hz
1164 \param[in] plus: add RTC clock or not
1165 \arg RTC_CALIBRATION_PLUS_SET: add one RTC clock every 2048 rtc clock
1166 \arg RTC_CALIBRATION_PLUS_RESET: no effect
1167 \param[in] minus: the RTC clock to minus during the calibration window(0x0 - 0x1FF)
1168 \param[out] none
1169 \retval ErrStatus: ERROR or SUCCESS
1170 */
rtc_smooth_calibration_config(uint32_t window,uint32_t plus,uint32_t minus)1171 ErrStatus rtc_smooth_calibration_config(uint32_t window, uint32_t plus, uint32_t minus)
1172 {
1173 volatile uint32_t time_index = RTC_HRFC_TIMEOUT;
1174 ErrStatus error_status = ERROR;
1175 uint32_t flag_status = RESET;
1176
1177 /* disable the write protection */
1178 RTC_WPK = RTC_UNLOCK_KEY1;
1179 RTC_WPK = RTC_UNLOCK_KEY2;
1180
1181 /* check if a smooth calibration operation is ongoing */
1182 do {
1183 flag_status = RTC_STAT & RTC_STAT_SCPF;
1184 } while((--time_index > 0U) && ((uint32_t)RESET != flag_status));
1185
1186 if((uint32_t)RESET == flag_status) {
1187 RTC_HRFC = (uint32_t)(window | plus | HRFC_CMSK(minus));
1188 error_status = SUCCESS;
1189 }
1190
1191 /* enable the write protection */
1192 RTC_WPK = RTC_LOCK_KEY;
1193
1194 return error_status;
1195 }
1196
1197 /*!
1198 \brief enable RTC coarse calibration
1199 \param[in] none
1200 \param[out] none
1201 \retval ErrStatus: ERROR or SUCCESS
1202 */
rtc_coarse_calibration_enable(void)1203 ErrStatus rtc_coarse_calibration_enable(void)
1204 {
1205 ErrStatus error_status = ERROR;
1206 /* disable the write protection */
1207 RTC_WPK = RTC_UNLOCK_KEY1;
1208 RTC_WPK = RTC_UNLOCK_KEY2;
1209 /* enter init mode */
1210 error_status = rtc_init_mode_enter();
1211
1212 if(ERROR != error_status) {
1213 RTC_CTL |= (uint32_t)RTC_CTL_CCEN;
1214 /* exit init mode */
1215 rtc_init_mode_exit();
1216 }
1217
1218 /* enable the write protection */
1219 RTC_WPK = RTC_LOCK_KEY;
1220 return error_status;
1221 }
1222
1223 /*!
1224 \brief disable RTC coarse calibration
1225 \param[in] none
1226 \param[out] none
1227 \retval ErrStatus: ERROR or SUCCESS
1228 */
rtc_coarse_calibration_disable(void)1229 ErrStatus rtc_coarse_calibration_disable(void)
1230 {
1231 ErrStatus error_status = ERROR;
1232 /* disable the write protection */
1233 RTC_WPK = RTC_UNLOCK_KEY1;
1234 RTC_WPK = RTC_UNLOCK_KEY2;
1235 /* enter init mode */
1236 error_status = rtc_init_mode_enter();
1237
1238 if(ERROR != error_status) {
1239 RTC_CTL &= (uint32_t)~RTC_CTL_CCEN;
1240 /* exit init mode */
1241 rtc_init_mode_exit();
1242 }
1243
1244 /* enable the write protection */
1245 RTC_WPK = RTC_LOCK_KEY;
1246 return error_status;
1247 }
1248
1249 /*!
1250 \brief config coarse calibration direction and step
1251 \param[in] direction: CALIB_INCREASE or CALIB_DECREASE
1252 \param[in] step: 0x00-0x1F
1253 COSD=0:
1254 0x00:+0 PPM
1255 0x01:+4 PPM
1256 0x02:+8 PPM
1257 ....
1258 0x1F:+126 PPM
1259 COSD=1:
1260 0x00:-0 PPM
1261 0x01:-2 PPM
1262 0x02:-4 PPM
1263 ....
1264 0x1F:-63 PPM
1265 \param[out] none
1266 \retval ErrStatus: ERROR or SUCCESS
1267 */
rtc_coarse_calibration_config(uint8_t direction,uint8_t step)1268 ErrStatus rtc_coarse_calibration_config(uint8_t direction, uint8_t step)
1269 {
1270 ErrStatus error_status = ERROR;
1271 /* disable the write protection */
1272 RTC_WPK = RTC_UNLOCK_KEY1;
1273 RTC_WPK = RTC_UNLOCK_KEY2;
1274
1275 /* enter init mode */
1276 error_status = rtc_init_mode_enter();
1277
1278 if(ERROR != error_status) {
1279 if(CALIB_DECREASE == direction) {
1280 RTC_COSC |= (uint32_t)RTC_COSC_COSD;
1281 } else {
1282 RTC_COSC &= (uint32_t)~RTC_COSC_COSD;
1283 }
1284 RTC_COSC &= ~RTC_COSC_COSS;
1285 RTC_COSC |= (uint32_t)((uint32_t)step & 0x1FU);
1286 /* exit init mode */
1287 rtc_init_mode_exit();
1288 }
1289
1290 /* enable the write protection */
1291 RTC_WPK = RTC_LOCK_KEY;
1292
1293 return error_status;
1294 }
1295