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