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