1 /*!
2 \file gd32f3x0_rtc.c
3 \brief RTC driver
4
5 \version 2017-06-06, V1.0.0, firmware for GD32F3x0
6 \version 2019-06-01, V2.0.0, firmware for GD32F3x0
7 \version 2020-09-30, V2.1.0, firmware for GD32F3x0
8 */
9
10 /*
11 Copyright (c) 2020, GigaDevice Semiconductor Inc.
12
13 Redistribution and use in source and binary forms, with or without modification,
14 are permitted provided that the following conditions are met:
15
16 1. Redistributions of source code must retain the above copyright notice, this
17 list of conditions and the following disclaimer.
18 2. Redistributions in binary form must reproduce the above copyright notice,
19 this list of conditions and the following disclaimer in the documentation
20 and/or other materials provided with the distribution.
21 3. Neither the name of the copyright holder nor the names of its contributors
22 may be used to endorse or promote products derived from this software without
23 specific prior written permission.
24
25 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
27 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
31 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
33 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
34 OF SUCH DAMAGE.
35 */
36
37 #include "gd32f3x0_rtc.h"
38
39 /*!
40 \brief reset most of the RTC registers
41 \param[in] none
42 \param[out] none
43 \retval ErrStatus: ERROR or SUCCESS
44 */
rtc_deinit(void)45 ErrStatus rtc_deinit(void)
46 {
47 ErrStatus error_status = ERROR;
48
49 /* RTC_TAMP register is not under write protection */
50 RTC_TAMP = RTC_REGISTER_RESET;
51
52 /* disable the write protection */
53 RTC_WPK = RTC_UNLOCK_KEY1;
54 RTC_WPK = RTC_UNLOCK_KEY2;
55
56 /* reset RTC_CTL register, this can be done without the init mode */
57 RTC_CTL &= RTC_REGISTER_RESET;
58
59 /* enter init mode */
60 error_status = rtc_init_mode_enter();
61
62 if(ERROR != error_status){
63 /* before reset RTC_TIME and RTC_DATE, BPSHAD bit in RTC_CTL should be reset as the condition.
64 in order to read calendar from shadow register, not the real registers being reset */
65 RTC_TIME = RTC_REGISTER_RESET;
66 RTC_DATE = RTC_DATE_RESET;
67
68 RTC_PSC = RTC_PSC_RESET;
69
70 /* reset RTC_STAT register, also exit init mode.
71 at the same time, RTC_STAT_SOPF bit is reset, as the condition to reset RTC_SHIFTCTL register later */
72 RTC_STAT = RTC_STAT_RESET;
73
74 /* to write RTC_ALRM0SS register, ALRM0EN bit in RTC_CTL register should be reset as the condition */
75 RTC_ALRM0TD = RTC_REGISTER_RESET;
76 RTC_ALRM0SS = RTC_REGISTER_RESET;
77
78 /* reset RTC_SHIFTCTL and RTC_HRFC register, this can be done without the init mode */
79 RTC_SHIFTCTL = RTC_REGISTER_RESET;
80 RTC_HRFC = RTC_REGISTER_RESET;
81
82 error_status = rtc_register_sync_wait();
83 }
84
85 /* enable the write protection */
86 RTC_WPK = RTC_LOCK_KEY;
87
88 return error_status;
89 }
90
91 /*!
92 \brief initialize RTC registers
93 \param[in] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains
94 parameters for initialization of the rtc peripheral
95 members of the structure and the member values are shown as below:
96 rtc_year: 0x0 - 0x99(BCD format)
97 rtc_month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN,
98 RTC_JUL, RTC_AUG, RTC_SEP, RTC_OCT, RTC_NOV, RTC_DEC
99 rtc_date: 0x1 - 0x31(BCD format)
100 rtc_day_of_week: RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY
101 RTC_FRIDAY, RTC_SATURDAY, RTC_SUNDAY
102 rtc_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format chose
103 rtc_minute: 0x0 - 0x59(BCD format)
104 rtc_second: 0x0 - 0x59(BCD format)
105 rtc_factor_asyn: 0x0 - 0x7F
106 rtc_factor_syn: 0x0 - 0x7FFF
107 rtc_am_pm: RTC_AM, RTC_PM
108 rtc_display_format: RTC_24HOUR, RTC_12HOUR
109 \param[out] none
110 \retval ErrStatus: ERROR or SUCCESS
111 */
rtc_init(rtc_parameter_struct * rtc_initpara_struct)112 ErrStatus rtc_init(rtc_parameter_struct* rtc_initpara_struct)
113 {
114 ErrStatus error_status = ERROR;
115 uint32_t reg_time = 0x00U, reg_date = 0x00U;
116
117 reg_date = (DATE_YR(rtc_initpara_struct->rtc_year) | \
118 DATE_DOW(rtc_initpara_struct->rtc_day_of_week) | \
119 DATE_MON(rtc_initpara_struct->rtc_month) | \
120 DATE_DAY(rtc_initpara_struct->rtc_date));
121
122 reg_time = (rtc_initpara_struct->rtc_am_pm| \
123 TIME_HR(rtc_initpara_struct->rtc_hour) | \
124 TIME_MN(rtc_initpara_struct->rtc_minute) | \
125 TIME_SC(rtc_initpara_struct->rtc_second));
126
127 /* 1st: disable the write protection */
128 RTC_WPK = RTC_UNLOCK_KEY1;
129 RTC_WPK = RTC_UNLOCK_KEY2;
130
131 /* 2nd: enter init mode */
132 error_status = rtc_init_mode_enter();
133
134 if(ERROR != error_status){
135 RTC_PSC = (uint32_t)(PSC_FACTOR_A(rtc_initpara_struct->rtc_factor_asyn)| \
136 PSC_FACTOR_S(rtc_initpara_struct->rtc_factor_syn));
137
138 RTC_TIME = (uint32_t)reg_time;
139 RTC_DATE = (uint32_t)reg_date;
140
141 RTC_CTL &= (uint32_t)(~RTC_CTL_CS);
142 RTC_CTL |= rtc_initpara_struct->rtc_display_format;
143
144 /* 3rd: exit init mode */
145 rtc_init_mode_exit();
146
147 /* 4th: wait the RSYNF flag to set */
148 error_status = rtc_register_sync_wait();
149 }
150
151 /* 5th: enable the write protection */
152 RTC_WPK = RTC_LOCK_KEY;
153
154 return error_status;
155 }
156
157 /*!
158 \brief enter RTC init mode
159 \param[in] none
160 \param[out] none
161 \retval ErrStatus: ERROR or SUCCESS
162 */
rtc_init_mode_enter(void)163 ErrStatus rtc_init_mode_enter(void)
164 {
165 uint32_t time_index = RTC_INITM_TIMEOUT;
166 uint32_t flag_status = RESET;
167 ErrStatus error_status = ERROR;
168
169 /* check whether it has been in init mode */
170 if(RESET == (RTC_STAT & RTC_STAT_INITF)){
171 RTC_STAT |= RTC_STAT_INITM;
172
173 /* wait until the INITF flag to be set */
174 do{
175 flag_status = RTC_STAT & RTC_STAT_INITF;
176 }while((--time_index > 0x00U) && (RESET == flag_status));
177
178 if(RESET != flag_status){
179 error_status = SUCCESS;
180 }
181 }else{
182 error_status = SUCCESS;
183 }
184 return error_status;
185 }
186
187 /*!
188 \brief exit RTC init mode
189 \param[in] none
190 \param[out] none
191 \retval none
192 */
rtc_init_mode_exit(void)193 void rtc_init_mode_exit(void)
194 {
195 RTC_STAT &= (uint32_t)(~RTC_STAT_INITM);
196 }
197
198 /*!
199 \brief wait until RTC_TIME and RTC_DATE registers are synchronized with APB clock, and the shadow
200 registers are updated
201 \param[in] none
202 \param[out] none
203 \retval ErrStatus: ERROR or SUCCESS
204 */
rtc_register_sync_wait(void)205 ErrStatus rtc_register_sync_wait(void)
206 {
207 volatile uint32_t time_index = RTC_RSYNF_TIMEOUT;
208 uint32_t flag_status = RESET;
209 ErrStatus error_status = ERROR;
210
211 if(RESET == (RTC_CTL & RTC_CTL_BPSHAD)){
212 /* disable the write protection */
213 RTC_WPK = RTC_UNLOCK_KEY1;
214 RTC_WPK = RTC_UNLOCK_KEY2;
215
216 /* firstly clear RSYNF flag */
217 RTC_STAT &= (uint32_t)(~RTC_STAT_RSYNF);
218
219 /* wait until RSYNF flag to be set */
220 do{
221 flag_status = RTC_STAT & RTC_STAT_RSYNF;
222 }while((--time_index > 0x00U) && (RESET == flag_status));
223
224 if(RESET != flag_status){
225 error_status = SUCCESS;
226 }
227
228 /* enable the write protection */
229 RTC_WPK = RTC_LOCK_KEY;
230 }else{
231 error_status = SUCCESS;
232 }
233
234 return error_status;
235 }
236
237 /*!
238 \brief get current time and date
239 \param[in] none
240 \param[out] rtc_initpara_struct: pointer to a rtc_parameter_struct structure which contains
241 parameters for initialization of the rtc peripheral
242 members of the structure and the member values are shown as below:
243 rtc_year: 0x0 - 0x99(BCD format)
244 rtc_month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN,
245 RTC_JUL, RTC_AUG, RTC_SEP, RTC_OCT, RTC_NOV, RTC_DEC
246 rtc_date: 0x1 - 0x31(BCD format)
247 rtc_day_of_week: RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY
248 RTC_FRIDAY, RTC_SATURDAY, RTC_SUNDAY
249 rtc_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format chose
250 rtc_minute: 0x0 - 0x59(BCD format)
251 rtc_second: 0x0 - 0x59(BCD format)
252 rtc_factor_asyn: 0x0 - 0x7F
253 rtc_factor_syn: 0x0 - 0x7FFF
254 rtc_am_pm: RTC_AM, RTC_PM
255 rtc_display_format: RTC_24HOUR, RTC_12HOUR
256 \retval none
257 */
rtc_current_time_get(rtc_parameter_struct * rtc_initpara_struct)258 void rtc_current_time_get(rtc_parameter_struct* rtc_initpara_struct)
259 {
260 uint32_t temp_tr = 0x00U, temp_dr = 0x00U, temp_pscr = 0x00U, temp_ctlr = 0x00U;
261
262 temp_tr = (uint32_t)RTC_TIME;
263 temp_dr = (uint32_t)RTC_DATE;
264 temp_pscr = (uint32_t)RTC_PSC;
265 temp_ctlr = (uint32_t)RTC_CTL;
266
267 /* get current time and construct rtc_parameter_struct structure */
268 rtc_initpara_struct->rtc_year = (uint8_t)GET_DATE_YR(temp_dr);
269 rtc_initpara_struct->rtc_month = (uint8_t)GET_DATE_MON(temp_dr);
270 rtc_initpara_struct->rtc_date = (uint8_t)GET_DATE_DAY(temp_dr);
271 rtc_initpara_struct->rtc_day_of_week = (uint8_t)GET_DATE_DOW(temp_dr);
272 rtc_initpara_struct->rtc_hour = (uint8_t)GET_TIME_HR(temp_tr);
273 rtc_initpara_struct->rtc_minute = (uint8_t)GET_TIME_MN(temp_tr);
274 rtc_initpara_struct->rtc_second = (uint8_t)GET_TIME_SC(temp_tr);
275 rtc_initpara_struct->rtc_factor_asyn = (uint16_t)GET_PSC_FACTOR_A(temp_pscr);
276 rtc_initpara_struct->rtc_factor_syn = (uint16_t)GET_PSC_FACTOR_S(temp_pscr);
277 rtc_initpara_struct->rtc_am_pm = (uint32_t)(temp_pscr & RTC_TIME_PM);
278 rtc_initpara_struct->rtc_display_format = (uint32_t)(temp_ctlr & RTC_CTL_CS);
279 }
280
281 /*!
282 \brief get current subsecond value
283 \param[in] none
284 \param[out] none
285 \retval current subsecond value
286 */
rtc_subsecond_get(void)287 uint32_t rtc_subsecond_get(void)
288 {
289 uint32_t reg = 0x00U;
290 /* if BPSHAD bit is reset, reading RTC_SS will lock RTC_TIME and RTC_DATE automatically */
291 reg = (uint32_t)RTC_SS;
292 /* read RTC_DATE to unlock the 3 shadow registers */
293 (void) (RTC_DATE);
294
295 return reg;
296 }
297
298 /*!
299 \brief configure RTC alarm
300 \param[in] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains
301 parameters for RTC alarm configuration
302 members of the structure and the member values are shown as below:
303 rtc_alarm_mask: RTC_ALARM_NONE_MASK, RTC_ALARM_DATE_MASK, RTC_ALARM_HOUR_MASK
304 RTC_ALARM_MINUTE_MASK, RTC_ALARM_SECOND_MASK, RTC_ALARM_ALL_MASK
305 rtc_weekday_or_date: RTC_ALARM_DATE_SELECTED, RTC_ALARM_WEEKDAY_SELECTED
306 rtc_alarm_day: 1) 0x1 - 0x31(BCD format) if RTC_ALARM_DATE_SELECTED is set
307 2) RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY, RTC_FRIDAY,
308 RTC_SATURDAY, RTC_SUNDAY if RTC_ALARM_WEEKDAY_SELECTED is set
309 rtc_alarm_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format
310 rtc_alarm_minute: 0x0 - 0x59(BCD format)
311 rtc_alarm_second: 0x0 - 0x59(BCD format)
312 rtc_am_pm: RTC_AM, RTC_PM
313 \param[out] none
314 \retval none
315 */
rtc_alarm_config(rtc_alarm_struct * rtc_alarm_time)316 void rtc_alarm_config(rtc_alarm_struct* rtc_alarm_time)
317 {
318 uint32_t reg_alrm0td = 0x00U;
319
320 reg_alrm0td = (rtc_alarm_time->rtc_alarm_mask | \
321 rtc_alarm_time->rtc_weekday_or_date | \
322 rtc_alarm_time->rtc_am_pm | \
323 ALRM0TD_DAY(rtc_alarm_time->rtc_alarm_day) | \
324 ALRM0TD_HR(rtc_alarm_time->rtc_alarm_hour) | \
325 ALRM0TD_MN(rtc_alarm_time->rtc_alarm_minute) | \
326 ALRM0TD_SC(rtc_alarm_time->rtc_alarm_second));
327
328 /* disable the write protection */
329 RTC_WPK = RTC_UNLOCK_KEY1;
330 RTC_WPK = RTC_UNLOCK_KEY2;
331
332 RTC_ALRM0TD = (uint32_t)reg_alrm0td;
333
334 /* enable the write protection */
335 RTC_WPK = RTC_LOCK_KEY;
336 }
337
338 /*!
339 \brief configure subsecond of RTC alarm
340 \param[in] mask_subsecond: alarm subsecond mask
341 only one parameter can be selected which is shown as below:
342 \arg RTC_MASKSSC_0_14: mask alarm subsecond configuration
343 \arg RTC_MASKSSC_1_14: mask RTC_ALRM0SS_SSC[14:1], and RTC_ALRM0SS_SSC[0] is to be compared
344 \arg RTC_MASKSSC_2_14: mask RTC_ALRM0SS_SSC[14:2], and RTC_ALRM0SS_SSC[1:0] is to be compared
345 \arg RTC_MASKSSC_3_14: mask RTC_ALRM0SS_SSC[14:3], and RTC_ALRM0SS_SSC[2:0] is to be compared
346 \arg RTC_MASKSSC_4_14: mask RTC_ALRM0SS_SSC[14:4], and RTC_ALRM0SS_SSC[3:0] is to be compared
347 \arg RTC_MASKSSC_5_14: mask RTC_ALRM0SS_SSC[14:5], and RTC_ALRM0SS_SSC[4:0] is to be compared
348 \arg RTC_MASKSSC_6_14: mask RTC_ALRM0SS_SSC[14:6], and RTC_ALRM0SS_SSC[5:0] is to be compared
349 \arg RTC_MASKSSC_7_14: mask RTC_ALRM0SS_SSC[14:7], and RTC_ALRM0SS_SSC[6:0] is to be compared
350 \arg RTC_MASKSSC_8_14: mask RTC_ALRM0SS_SSC[14:8], and RTC_ALRM0SS_SSC[7:0] is to be compared
351 \arg RTC_MASKSSC_9_14: mask RTC_ALRM0SS_SSC[14:9], and RTC_ALRM0SS_SSC[8:0] is to be compared
352 \arg RTC_MASKSSC_10_14: mask RTC_ALRM0SS_SSC[14:10], and RTC_ALRM0SS_SSC[9:0] is to be compared
353 \arg RTC_MASKSSC_11_14: mask RTC_ALRM0SS_SSC[14:11], and RTC_ALRM0SS_SSC[10:0] is to be compared
354 \arg RTC_MASKSSC_12_14: mask RTC_ALRM0SS_SSC[14:12], and RTC_ALRM0SS_SSC[11:0] is to be compared
355 \arg RTC_MASKSSC_13_14: mask RTC_ALRM0SS_SSC[14:13], and RTC_ALRM0SS_SSC[12:0] is to be compared
356 \arg RTC_MASKSSC_14: mask RTC_ALRM0SS_SSC[14], and RTC_ALRM0SS_SSC[13:0] is to be compared
357 \arg RTC_MASKSSC_NONE: mask none, and RTC_ALRM0SS_SSC[14:0] is to be compared
358 \param[in] subsecond: alarm subsecond value(0x000 - 0x7FFF)
359 \param[out] none
360 \retval none
361 */
rtc_alarm_subsecond_config(uint32_t mask_subsecond,uint32_t subsecond)362 void rtc_alarm_subsecond_config(uint32_t mask_subsecond, uint32_t subsecond)
363 {
364 /* disable the write protection */
365 RTC_WPK = RTC_UNLOCK_KEY1;
366 RTC_WPK = RTC_UNLOCK_KEY2;
367
368 RTC_ALRM0SS = mask_subsecond | subsecond;
369
370 /* enable the write protection */
371 RTC_WPK = RTC_LOCK_KEY;
372 }
373
374 /*!
375 \brief get RTC alarm
376 \param[in] none
377 \param[out] rtc_alarm_time: pointer to a rtc_alarm_struct structure which contains
378 parameters for RTC alarm configuration
379 members of the structure and the member values are shown as below:
380 rtc_alarm_mask: RTC_ALARM_NONE_MASK, RTC_ALARM_DATE_MASK, RTC_ALARM_HOUR_MASK
381 RTC_ALARM_MINUTE_MASK, RTC_ALARM_SECOND_MASK, RTC_ALARM_ALL_MASK
382 rtc_weekday_or_date: RTC_ALARM_DATE_SELECTED, RTC_ALARM_WEEKDAY_SELECTED
383 rtc_alarm_day: 1) 0x1 - 0x31(BCD format) if RTC_ALARM_DATE_SELECTED is set
384 2) RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY, RTC_FRIDAY,
385 RTC_SATURDAY, RTC_SUNDAY if RTC_ALARM_WEEKDAY_SELECTED is set
386 rtc_alarm_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format
387 rtc_alarm_minute: 0x0 - 0x59(BCD format)
388 rtc_alarm_second: 0x0 - 0x59(BCD format)
389 rtc_am_pm: RTC_AM, RTC_PM
390 \retval none
391 */
rtc_alarm_get(rtc_alarm_struct * rtc_alarm_time)392 void rtc_alarm_get(rtc_alarm_struct* rtc_alarm_time)
393 {
394 uint32_t reg_alrm0td = 0x00U;
395
396 /* get the value of RTC_ALRM0TD register */
397 reg_alrm0td = RTC_ALRM0TD;
398
399 /* get alarm parameters and construct the rtc_alarm_struct structure */
400 rtc_alarm_time->rtc_alarm_mask = reg_alrm0td & RTC_ALARM_ALL_MASK;
401 rtc_alarm_time->rtc_am_pm = (uint32_t)(reg_alrm0td & RTC_ALRM0TD_PM);
402 rtc_alarm_time->rtc_weekday_or_date = (uint32_t)(reg_alrm0td & RTC_ALRM0TD_DOWS);
403 rtc_alarm_time->rtc_alarm_day = (uint8_t)GET_ALRM0TD_DAY(reg_alrm0td);
404 rtc_alarm_time->rtc_alarm_hour = (uint8_t)GET_ALRM0TD_HR(reg_alrm0td);
405 rtc_alarm_time->rtc_alarm_minute = (uint8_t)GET_ALRM0TD_MN(reg_alrm0td);
406 rtc_alarm_time->rtc_alarm_second = (uint8_t)GET_ALRM0TD_SC(reg_alrm0td);
407 }
408
409 /*!
410 \brief get RTC alarm subsecond
411 \param[in] none
412 \param[out] none
413 \retval RTC alarm subsecond value
414 */
rtc_alarm_subsecond_get(void)415 uint32_t rtc_alarm_subsecond_get(void)
416 {
417 return ((uint32_t)(RTC_ALRM0SS & RTC_ALRM0SS_SSC));
418 }
419
420 /*!
421 \brief enable RTC alarm
422 \param[in] none
423 \param[out] none
424 \retval none
425 */
rtc_alarm_enable(void)426 void rtc_alarm_enable(void)
427 {
428 /* disable the write protection */
429 RTC_WPK = RTC_UNLOCK_KEY1;
430 RTC_WPK = RTC_UNLOCK_KEY2;
431
432 RTC_CTL |= RTC_CTL_ALRM0EN;
433
434 /* enable the write protection */
435 RTC_WPK = RTC_LOCK_KEY;
436 }
437
438 /*!
439 \brief disable RTC alarm
440 \param[in] none
441 \param[out] none
442 \retval ErrStatus: ERROR or SUCCESS
443 */
rtc_alarm_disable(void)444 ErrStatus rtc_alarm_disable(void)
445 {
446 volatile uint32_t time_index = RTC_ALRM0WF_TIMEOUT;
447 ErrStatus error_status = ERROR;
448 uint32_t flag_status = RESET;
449
450 /* disable the write protection */
451 RTC_WPK = RTC_UNLOCK_KEY1;
452 RTC_WPK = RTC_UNLOCK_KEY2;
453
454 /* clear the state of alarm */
455 RTC_CTL &= (uint32_t)(~RTC_CTL_ALRM0EN);
456
457 /* wait until ALRM0WF flag to be set after the alarm is disabled */
458 do{
459 flag_status = RTC_STAT & RTC_STAT_ALRM0WF;
460 }while((--time_index > 0x00U) && (RESET == flag_status));
461
462 if(RESET != flag_status){
463 error_status = SUCCESS;
464 }
465
466 /* enable the write protection */
467 RTC_WPK = RTC_LOCK_KEY;
468
469 return error_status;
470 }
471
472 /*!
473 \brief enable RTC time-stamp
474 \param[in] edge: specify which edge to detect of time-stamp
475 only one parameter can be selected which is shown as below:
476 \arg RTC_TIMESTAMP_RISING_EDGE: rising edge is valid event edge for timestamp event
477 \arg RTC_TIMESTAMP_FALLING_EDGE: falling edge is valid event edge for timestamp event
478 \param[out] none
479 \retval none
480 */
rtc_timestamp_enable(uint32_t edge)481 void rtc_timestamp_enable(uint32_t edge)
482 {
483 uint32_t reg_ctl = 0x00U;
484
485 /* clear the bits to be configured in RTC_CTL */
486 reg_ctl = (uint32_t)(RTC_CTL & (uint32_t)(~(RTC_CTL_TSEG | RTC_CTL_TSEN)));
487
488 /* new configuration */
489 reg_ctl |= (uint32_t)(edge | RTC_CTL_TSEN);
490
491 /* disable the write protection */
492 RTC_WPK = RTC_UNLOCK_KEY1;
493 RTC_WPK = RTC_UNLOCK_KEY2;
494
495 RTC_CTL = (uint32_t)reg_ctl;
496
497 /* enable the write protection */
498 RTC_WPK = RTC_LOCK_KEY;
499 }
500
501 /*!
502 \brief disable RTC time-stamp
503 \param[in] none
504 \param[out] none
505 \retval none
506 */
rtc_timestamp_disable(void)507 void rtc_timestamp_disable(void)
508 {
509 /* disable the write protection */
510 RTC_WPK = RTC_UNLOCK_KEY1;
511 RTC_WPK = RTC_UNLOCK_KEY2;
512
513 /* clear the TSEN bit */
514 RTC_CTL &= (uint32_t)(~ RTC_CTL_TSEN);
515
516 /* enable the write protection */
517 RTC_WPK = RTC_LOCK_KEY;
518 }
519
520 /*!
521 \brief get RTC timestamp time and date
522 \param[in] none
523 \param[out] rtc_timestamp: pointer to a rtc_timestamp_struct structure which contains
524 parameters for RTC time-stamp configuration
525 members of the structure and the member values are shown as below:
526 rtc_timestamp_month: RTC_JAN, RTC_FEB, RTC_MAR, RTC_APR, RTC_MAY, RTC_JUN,
527 RTC_JUL, RTC_AUG, RTC_SEP, RTC_OCT, RTC_NOV, RTC_DEC
528 rtc_timestamp_date: 0x1 - 0x31(BCD format)
529 rtc_timestamp_day: RTC_MONDAY, RTC_TUESDAY, RTC_WEDSDAY, RTC_THURSDAY, RTC_FRIDAY,
530 RTC_SATURDAY, RTC_SUNDAY if RTC_ALARM_WEEKDAY_SELECTED is set
531 rtc_timestamp_hour: 0x0 - 0x12(BCD format) or 0x0 - 0x23(BCD format) depending on the rtc_display_format
532 rtc_timestamp_minute: 0x0 - 0x59(BCD format)
533 rtc_timestamp_second: 0x0 - 0x59(BCD format)
534 rtc_am_pm: RTC_AM, RTC_PM
535 \retval none
536 */
rtc_timestamp_get(rtc_timestamp_struct * rtc_timestamp)537 void rtc_timestamp_get(rtc_timestamp_struct* rtc_timestamp)
538 {
539 uint32_t temp_tts = 0x00U, temp_dts = 0x00U;
540
541 /* get the value of time_stamp registers */
542 temp_tts = (uint32_t)RTC_TTS;
543 temp_dts = (uint32_t)RTC_DTS;
544
545 /* get timestamp time and construct the rtc_timestamp_struct structure */
546 rtc_timestamp->rtc_am_pm = (uint32_t)(temp_tts & RTC_TTS_PM);
547 rtc_timestamp->rtc_timestamp_month = (uint8_t)GET_DTS_MON(temp_dts);
548 rtc_timestamp->rtc_timestamp_date = (uint8_t)GET_DTS_DAY(temp_dts);
549 rtc_timestamp->rtc_timestamp_day = (uint8_t)GET_DTS_DOW(temp_dts);
550 rtc_timestamp->rtc_timestamp_hour = (uint8_t)GET_TTS_HR(temp_tts);
551 rtc_timestamp->rtc_timestamp_minute = (uint8_t)GET_TTS_MN(temp_tts);
552 rtc_timestamp->rtc_timestamp_second = (uint8_t)GET_TTS_SC(temp_tts);
553 }
554
555 /*!
556 \brief get RTC time-stamp subsecond
557 \param[in] none
558 \param[out] none
559 \retval RTC time-stamp subsecond value
560 */
rtc_timestamp_subsecond_get(void)561 uint32_t rtc_timestamp_subsecond_get(void)
562 {
563 return ((uint32_t)RTC_SSTS);
564 }
565
566 /*!
567 \brief enable RTC tamper
568 \param[in] rtc_tamper: pointer to a rtc_tamper_struct structure which contains
569 parameters for RTC tamper configuration
570 members of the structure and the member values are shown as below:
571 rtc_tamper_source: RTC_TAMPER0, RTC_TAMPER1
572 rtc_tamper_trigger: RTC_TAMPER_TRIGGER_EDGE_RISING, RTC_TAMPER_TRIGGER_EDGE_FALLING
573 RTC_TAMPER_TRIGGER_LEVEL_LOW, RTC_TAMPER_TRIGGER_LEVEL_HIGH
574 rtc_tamper_filter: RTC_FLT_EDGE, RTC_FLT_2S, RTC_FLT_4S, RTC_FLT_8S
575 rtc_tamper_sample_frequency: RTC_FREQ_DIV32768, RTC_FREQ_DIV16384, RTC_FREQ_DIV8192,
576 RTC_FREQ_DIV4096, RTC_FREQ_DIV2048, RTC_FREQ_DIV1024,
577 RTC_FREQ_DIV512, RTC_FREQ_DIV256
578 rtc_tamper_precharge_enable: DISABLE, ENABLE
579 rtc_tamper_precharge_time: RTC_PRCH_1C, RTC_PRCH_2C, RTC_PRCH_4C, RTC_PRCH_8C
580 rtc_tamper_with_timestamp: DISABLE, ENABLE
581 \param[out] none
582 \retval none
583 */
rtc_tamper_enable(rtc_tamper_struct * rtc_tamper)584 void rtc_tamper_enable(rtc_tamper_struct* rtc_tamper)
585 {
586 /* disable tamper */
587 RTC_TAMP &= (uint32_t)~(rtc_tamper->rtc_tamper_source);
588
589 /* tamper filter must be used when the tamper source is voltage level detection */
590 RTC_TAMP &= (uint32_t)~RTC_TAMP_FLT;
591
592 /* the tamper source is voltage level detection */
593 if(rtc_tamper->rtc_tamper_filter != RTC_FLT_EDGE ){
594 RTC_TAMP &= (uint32_t)~(RTC_TAMP_DISPU | RTC_TAMP_PRCH | RTC_TAMP_FREQ | RTC_TAMP_FLT);
595
596 /* check if the tamper pin need precharge, if need, then configure the precharge time */
597 if(DISABLE == rtc_tamper->rtc_tamper_precharge_enable){
598 RTC_TAMP |= (uint32_t)RTC_TAMP_DISPU;
599 }else{
600 RTC_TAMP |= (uint32_t)(rtc_tamper->rtc_tamper_precharge_time);
601 }
602
603 RTC_TAMP |= (uint32_t)(rtc_tamper->rtc_tamper_sample_frequency);
604 RTC_TAMP |= (uint32_t)(rtc_tamper->rtc_tamper_filter);
605 }
606
607 RTC_TAMP &= (uint32_t)~RTC_TAMP_TPTS;
608
609 if(DISABLE != rtc_tamper->rtc_tamper_with_timestamp){
610 /* the tamper event also cause a time-stamp event */
611 RTC_TAMP |= (uint32_t)RTC_TAMP_TPTS;
612 }
613
614 /* configure the tamper trigger */
615 RTC_TAMP &= ((uint32_t)~((rtc_tamper->rtc_tamper_source) << RTC_TAMPER_TRIGGER_POS));
616 if(RTC_TAMPER_TRIGGER_EDGE_RISING != rtc_tamper->rtc_tamper_trigger){
617 RTC_TAMP |= (uint32_t)((rtc_tamper->rtc_tamper_source)<< RTC_TAMPER_TRIGGER_POS);
618 }
619 /* enable tamper */
620 RTC_TAMP |= (uint32_t)(rtc_tamper->rtc_tamper_source);
621 }
622
623 /*!
624 \brief disable RTC tamper
625 \param[in] source: specify which tamper source to be disabled
626 only one parameter can be selected which is shown as below:
627 \arg RTC_TAMPER0
628 \arg RTC_TAMPER1
629 \param[out] none
630 \retval none
631 */
rtc_tamper_disable(uint32_t source)632 void rtc_tamper_disable(uint32_t source)
633 {
634 /* disable tamper */
635 RTC_TAMP &= (uint32_t)~source;
636
637 }
638
639 /*!
640 \brief enable specified RTC interrupt
641 \param[in] interrupt: specify which interrupt source to be enabled
642 only one parameter can be selected which is shown as below:
643 \arg RTC_INT_TIMESTAMP: timestamp interrupt
644 \arg RTC_INT_ALARM: alarm interrupt
645 \arg RTC_INT_TAMP: tamp interrupt
646 \param[out] none
647 \retval none
648 */
rtc_interrupt_enable(uint32_t interrupt)649 void rtc_interrupt_enable(uint32_t interrupt)
650 {
651 /* disable the write protection */
652 RTC_WPK = RTC_UNLOCK_KEY1;
653 RTC_WPK = RTC_UNLOCK_KEY2;
654
655 /* enable the interrupts in RTC_CTL register */
656 RTC_CTL |= (uint32_t)(interrupt & (uint32_t)~RTC_TAMP_TPIE);
657 /* enable the interrupts in RTC_TAMP register */
658 RTC_TAMP |= (uint32_t)(interrupt & RTC_TAMP_TPIE);
659
660 /* enable the write protection */
661 RTC_WPK = RTC_LOCK_KEY;
662 }
663
664 /*!
665 \brief disble specified RTC interrupt
666 \param[in] interrupt: specify which interrupt source to be disabled
667 only one parameter can be selected which is shown as below:
668 \arg RTC_INT_TIMESTAMP: timestamp interrupt
669 \arg RTC_INT_ALARM: alarm interrupt
670 \arg RTC_INT_TAMP: tamp interrupt
671 \param[out] none
672 \retval none
673 */
rtc_interrupt_disable(uint32_t interrupt)674 void rtc_interrupt_disable(uint32_t interrupt)
675 {
676 /* disable the write protection */
677 RTC_WPK = RTC_UNLOCK_KEY1;
678 RTC_WPK = RTC_UNLOCK_KEY2;
679
680 /* disable the interrupts in RTC_CTL register */
681 RTC_CTL &= (uint32_t)~(interrupt & (uint32_t)~RTC_TAMP_TPIE);
682 /* disable the interrupts in RTC_TAMP register */
683 RTC_TAMP &= (uint32_t)~(interrupt & RTC_TAMP_TPIE);
684
685 /* enable the write protection */
686 RTC_WPK = RTC_LOCK_KEY;
687 }
688
689 /*!
690 \brief check specified flag
691 \param[in] flag: specify which flag to check
692 only one parameter can be selected which is shown as below:
693 \arg RTC_FLAG_RECALIBRATION: recalibration pending flag
694 \arg RTC_FLAG_TAMP1: tamper 1 event flag
695 \arg RTC_FLAG_TAMP0: tamper 0 event flag
696 \arg RTC_FLAG_TIMESTAMP_OVERFLOW: time-stamp overflow event flag
697 \arg RTC_FLAG_TIMESTAMP: time-stamp event flag
698 \arg RTC_FLAG_ALARM0: alarm event flag
699 \arg RTC_FLAG_INIT: init mode event flag
700 \arg RTC_FLAG_RSYN: time and date registers synchronized event flag
701 \arg RTC_FLAG_YCM: year parameter configured event flag
702 \arg RTC_FLAG_SHIFT: shift operation pending flag
703 \arg RTC_FLAG_ALARM0_WRITTEN: alarm writen available flag
704 \param[out] none
705 \retval FlagStatus: SET or RESET
706 */
rtc_flag_get(uint32_t flag)707 FlagStatus rtc_flag_get(uint32_t flag)
708 {
709 FlagStatus flag_state = RESET;
710
711 if(RESET != (RTC_STAT & flag)){
712 flag_state = SET;
713 }
714 return flag_state;
715 }
716
717 /*!
718 \brief clear specified flag
719 \param[in] flag: specify which flag to clear
720 \arg RTC_FLAG_TAMP1: tamper 1 event flag
721 \arg RTC_FLAG_TAMP0: tamper 0 event flag
722 \arg RTC_FLAG_TIMESTAMP_OVERFLOW: time-stamp overflow event flag
723 \arg RTC_FLAG_TIMESTAMP: time-stamp event flag
724 \arg RTC_FLAG_ALARM0: alarm event flag
725 \arg RTC_FLAG_RSYN: time and date registers synchronized event flag
726 \param[out] none
727 \retval none
728 */
rtc_flag_clear(uint32_t flag)729 void rtc_flag_clear(uint32_t flag)
730 {
731 RTC_STAT &= (uint32_t)(~flag);
732 }
733
734 /*!
735 \brief configure rtc alternate output source
736 \param[in] source: specify signal to output
737 only one parameter can be selected which is shown as below:
738 \arg RTC_CALIBRATION_512HZ: when the LSE freqency is 32768Hz and the RTC_PSC
739 is the default value, output 512Hz signal
740 \arg RTC_CALIBRATION_1HZ: when the LSE freqency is 32768Hz and the RTC_PSC
741 is the default value, output 1Hz signal
742 \arg RTC_ALARM_HIGH: when the alarm flag is set, the output pin is high
743 \arg RTC_ALARM_LOW: when the Alarm flag is set, the output pin is low
744 \param[in] mode: specify the output pin (PC13) mode when output alarm signal
745 only one parameter can be selected which is shown as below:
746 \arg RTC_ALARM_OUTPUT_OD: open drain mode
747 \arg RTC_ALARM_OUTPUT_PP: push pull mode
748 \param[out] none
749 \retval none
750 */
rtc_alter_output_config(uint32_t source,uint32_t mode)751 void rtc_alter_output_config(uint32_t source, uint32_t mode)
752 {
753 /* disable the write protection */
754 RTC_WPK = RTC_UNLOCK_KEY1;
755 RTC_WPK = RTC_UNLOCK_KEY2;
756
757 RTC_CTL &= (uint32_t)~(RTC_CTL_COEN | RTC_CTL_OS | RTC_CTL_OPOL | RTC_CTL_COS);
758
759 RTC_CTL |= (uint32_t)(source);
760
761 /* alarm output */
762 if(RESET != (source & RTC_OS_ENABLE)){
763 RTC_TAMP &= (uint32_t)~(RTC_TAMP_PC13VAL);
764 RTC_TAMP |= (uint32_t)(mode);
765 }
766
767 /* enable the write protection */
768 RTC_WPK = RTC_LOCK_KEY;
769 }
770
771
772 /*!
773 \brief configure RTC calibration register
774 \param[in] window: select calibration window
775 only one parameter can be selected which is shown as below:
776 \arg RTC_CALIBRATION_WINDOW_32S: 2exp20 RTCCLK cycles, 32s if RTCCLK = 32768 Hz
777 \arg RTC_CALIBRATION_WINDOW_16S: 2exp19 RTCCLK cycles, 16s if RTCCLK = 32768 Hz
778 \arg RTC_CALIBRATION_WINDOW_8S: 2exp18 RTCCLK cycles, 8s if RTCCLK = 32768 Hz
779 \param[in] plus: add RTC clock or not
780 only one parameter can be selected which is shown as below:
781 \arg RTC_CALIBRATION_PLUS_SET: add one RTC clock every 2048 rtc clock
782 \arg RTC_CALIBRATION_PLUS_RESET: no effect
783 \param[in] minus: the RTC clock to minus during the calibration window(0x0 - 0x1FF)
784 \param[out] none
785 \retval ErrStatus: ERROR or SUCCESS
786 */
rtc_calibration_config(uint32_t window,uint32_t plus,uint32_t minus)787 ErrStatus rtc_calibration_config(uint32_t window, uint32_t plus, uint32_t minus)
788 {
789 uint32_t time_index = RTC_HRFC_TIMEOUT;
790 ErrStatus error_status = ERROR;
791 uint32_t flag_status = RESET;
792
793 /* disable the write protection */
794 RTC_WPK = RTC_UNLOCK_KEY1;
795 RTC_WPK = RTC_UNLOCK_KEY2;
796
797 /* check if a calibration operation is ongoing */
798 do{
799 flag_status = RTC_STAT & RTC_STAT_SCPF;
800 }while((--time_index > 0x00U) && (RESET != flag_status));
801
802 if(RESET == flag_status){
803 RTC_HRFC = (uint32_t)(window | plus | HRFC_CMSK(minus));
804 error_status = SUCCESS;
805 }
806
807 /* enable the write protection */
808 RTC_WPK = RTC_LOCK_KEY;
809
810 return error_status;
811 }
812
813 /*!
814 \brief ajust the daylight saving time by adding or substracting one hour from the current time
815 \param[in] operation: hour ajustment operation
816 only one parameter can be selected which is shown as below:
817 \arg RTC_CTL_A1H: add one hour
818 \arg RTC_CTL_S1H: substract one hour
819 \param[out] none
820 \retval none
821 */
rtc_hour_adjust(uint32_t operation)822 void rtc_hour_adjust(uint32_t operation)
823 {
824 /* disable the write protection */
825 RTC_WPK = RTC_UNLOCK_KEY1;
826 RTC_WPK = RTC_UNLOCK_KEY2;
827
828 RTC_CTL |= (uint32_t)(operation);
829
830 /* enable the write protection */
831 RTC_WPK = RTC_LOCK_KEY;
832 }
833
834 /*!
835 \brief ajust RTC second or subsecond value of current time
836 \param[in] add: add 1s to current time or not
837 only one parameter can be selected which is shown as below:
838 \arg RTC_SHIFT_ADD1S_RESET: no effect
839 \arg RTC_SHIFT_ADD1S_SET: add 1s to current time
840 \param[in] minus: number of subsecond to minus from current time(0x0 - 0x7FFF)
841 \param[out] none
842 \retval ErrStatus: ERROR or SUCCESS
843 */
rtc_second_adjust(uint32_t add,uint32_t minus)844 ErrStatus rtc_second_adjust(uint32_t add, uint32_t minus)
845 {
846 uint32_t time_index = RTC_SHIFTCTL_TIMEOUT;
847 ErrStatus error_status = ERROR;
848 uint32_t flag_status = RESET;
849 uint32_t temp=0U;
850
851 /* disable the write protection */
852 RTC_WPK = RTC_UNLOCK_KEY1;
853 RTC_WPK = RTC_UNLOCK_KEY2;
854
855 /* check if a shift operation is ongoing */
856 do{
857 flag_status = RTC_STAT & RTC_STAT_SOPF;
858 }while((--time_index > 0x00U) && (RESET != flag_status));
859
860 temp = RTC_CTL & RTC_CTL_REFEN;
861 /* check if the function of reference clock detection is disabled */
862 if((RESET == flag_status) && (RESET == temp)){
863 RTC_SHIFTCTL = (uint32_t)(add | SHIFTCTL_SFS(minus));
864 error_status = rtc_register_sync_wait();
865 }
866
867 /* enable the write protection */
868 RTC_WPK = RTC_LOCK_KEY;
869
870 return error_status;
871 }
872
873 /*!
874 \brief enable RTC bypass shadow registers function
875 \param[in] none
876 \param[out] none
877 \retval none
878 */
rtc_bypass_shadow_enable(void)879 void rtc_bypass_shadow_enable(void)
880 {
881 /* disable the write protection */
882 RTC_WPK = RTC_UNLOCK_KEY1;
883 RTC_WPK = RTC_UNLOCK_KEY2;
884
885 RTC_CTL |= (uint8_t)RTC_CTL_BPSHAD;
886
887 /* enable the write protection */
888 RTC_WPK = RTC_LOCK_KEY;
889 }
890
891 /*!
892 \brief disable RTC bypass shadow registers function
893 \param[in] none
894 \param[out] none
895 \retval none
896 */
rtc_bypass_shadow_disable(void)897 void rtc_bypass_shadow_disable(void)
898 {
899 /* disable the write protection */
900 RTC_WPK = RTC_UNLOCK_KEY1;
901 RTC_WPK = RTC_UNLOCK_KEY2;
902
903 RTC_CTL &= (uint8_t)~RTC_CTL_BPSHAD;
904
905 /* enable the write protection */
906 RTC_WPK = RTC_LOCK_KEY;
907 }
908
909 /*!
910 \brief enable RTC reference clock detection function
911 \param[in] none
912 \param[out] none
913 \retval ErrStatus: ERROR or SUCCESS
914 */
rtc_refclock_detection_enable(void)915 ErrStatus rtc_refclock_detection_enable(void)
916 {
917 ErrStatus error_status = ERROR;
918
919 /* disable the write protection */
920 RTC_WPK = RTC_UNLOCK_KEY1;
921 RTC_WPK = RTC_UNLOCK_KEY2;
922
923 /* enter init mode */
924 error_status = rtc_init_mode_enter();
925
926 if(ERROR != error_status){
927 RTC_CTL |= (uint32_t)RTC_CTL_REFEN;
928 /* exit init mode */
929 rtc_init_mode_exit();
930 }
931
932 /* enable the write protection */
933 RTC_WPK = RTC_LOCK_KEY;
934
935 return error_status;
936 }
937
938 /*!
939 \brief disable RTC reference clock detection function
940 \param[in] none
941 \param[out] none
942 \retval ErrStatus: ERROR or SUCCESS
943 */
rtc_refclock_detection_disable(void)944 ErrStatus rtc_refclock_detection_disable(void)
945 {
946 ErrStatus error_status = ERROR;
947
948 /* disable the write protection */
949 RTC_WPK = RTC_UNLOCK_KEY1;
950 RTC_WPK = RTC_UNLOCK_KEY2;
951
952 /* enter init mode */
953 error_status = rtc_init_mode_enter();
954
955 if(ERROR != error_status){
956 RTC_CTL &= (uint32_t)~RTC_CTL_REFEN;
957 /* exit init mode */
958 rtc_init_mode_exit();
959 }
960
961 /* enable the write protection */
962 RTC_WPK = RTC_LOCK_KEY;
963
964 return error_status;
965 }
966
967
968