1 /*!
2     \file    gd32f403_rtc.c
3     \brief   RTC driver
4 
5     \version 2017-02-10, V1.0.0, firmware for GD32F403
6     \version 2018-12-25, V2.0.0, firmware for GD32F403
7     \version 2020-09-30, V2.1.0, firmware for GD32F403
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 "gd32f403_rtc.h"
38 
39 /*!
40     \brief      enable RTC interrupt
41     \param[in]  interrupt: specify which interrupt to enbale
42           \arg    RTC_INT_SECOND: second interrupt
43           \arg    RTC_INT_ALARM: alarm interrupt
44           \arg    RTC_INT_OVERFLOW: overflow interrupt
45     \param[out] none
46     \retval     none
47 */
rtc_interrupt_enable(uint32_t interrupt)48 void rtc_interrupt_enable(uint32_t interrupt)
49 {
50     RTC_INTEN |= interrupt;
51 }
52 
53 /*!
54     \brief      disable RTC interrupt
55     \param[in]  interrupt: specify which interrupt to disbale
56           \arg    RTC_INT_SECOND: second interrupt
57           \arg    RTC_INT_ALARM: alarm interrupt
58           \arg    RTC_INT_OVERFLOW: overflow interrupt
59     \param[out] none
60     \retval     none
61 */
rtc_interrupt_disable(uint32_t interrupt)62 void rtc_interrupt_disable(uint32_t interrupt)
63 {
64     RTC_INTEN &= ~interrupt;
65 }
66 
67 /*!
68     \brief      enter RTC configuration mode
69     \param[in]  none
70     \param[out] none
71     \retval     none
72 */
rtc_configuration_mode_enter(void)73 void rtc_configuration_mode_enter(void)
74 {
75     RTC_CTL |= RTC_CTL_CMF;
76 }
77 
78 /*!
79     \brief      exit RTC configuration mode
80     \param[in]  none
81     \param[out] none
82     \retval     none
83 */
rtc_configuration_mode_exit(void)84 void rtc_configuration_mode_exit(void)
85 {
86     RTC_CTL &= ~RTC_CTL_CMF;
87 }
88 
89 /*!
90     \brief      wait RTC last write operation finished flag set
91     \param[in]  none
92     \param[out] none
93     \retval     none
94 */
rtc_lwoff_wait(void)95 void rtc_lwoff_wait(void)
96 {
97      /* loop until LWOFF flag is set */
98     while (RESET == (RTC_CTL & RTC_CTL_LWOFF)){
99     }
100 }
101 
102 /*!
103     \brief      wait RTC registers synchronized flag set
104     \param[in]  none
105     \param[out] none
106     \retval     none
107 */
rtc_register_sync_wait(void)108 void rtc_register_sync_wait(void)
109 {
110      /* clear RSYNF flag */
111     RTC_CTL &= ~RTC_CTL_RSYNF;
112     /* loop until RSYNF flag is set */
113     while (RESET == (RTC_CTL & RTC_CTL_RSYNF)){
114     }
115 }
116 
117 /*!
118     \brief      get RTC counter value
119     \param[in]  none
120     \param[out] none
121     \retval     RTC counter value
122 */
rtc_counter_get(void)123 uint32_t rtc_counter_get(void)
124 {
125     uint32_t temp = 0x0U;
126     temp = RTC_CNTL;
127     temp |= (RTC_CNTH << 16);
128     return temp;
129 }
130 
131 /*!
132     \brief      set RTC counter value
133     \param[in]  cnt: RTC counter value
134     \param[out] none
135     \retval     none
136 */
rtc_counter_set(uint32_t cnt)137 void rtc_counter_set(uint32_t cnt)
138 {
139     rtc_configuration_mode_enter();
140     /* set the RTC counter high bits */
141     RTC_CNTH = cnt >> 16;
142     /* set the RTC counter low bits */
143     RTC_CNTL = (cnt & RTC_LOW_VALUE);
144     rtc_configuration_mode_exit();
145 }
146 
147 /*!
148     \brief      set RTC prescaler value
149     \param[in]  psc: RTC prescaler value
150     \param[out] none
151     \retval     none
152 */
rtc_prescaler_set(uint32_t psc)153 void rtc_prescaler_set(uint32_t psc)
154 {
155     rtc_configuration_mode_enter();
156     /* set the RTC prescaler high bits */
157     RTC_PSCH = (psc & RTC_HIGH_VALUE) >> 16;
158     /* set the RTC prescaler low bits */
159     RTC_PSCL = (psc & RTC_LOW_VALUE);
160     rtc_configuration_mode_exit();
161 }
162 
163 /*!
164     \brief      set RTC alarm value
165     \param[in]  alarm: RTC alarm value
166     \param[out] none
167     \retval     none
168 */
rtc_alarm_config(uint32_t alarm)169 void rtc_alarm_config(uint32_t alarm)
170 {
171     rtc_configuration_mode_enter();
172     /* set the alarm high bits */
173     RTC_ALRMH = alarm >> 16;
174     /* set the alarm low bits */
175     RTC_ALRML = (alarm & RTC_LOW_VALUE);
176     rtc_configuration_mode_exit();
177 }
178 
179 /*!
180     \brief      get RTC divider value
181     \param[in]  none
182     \param[out] none
183     \retval     RTC divider value
184 */
rtc_divider_get(void)185 uint32_t rtc_divider_get(void)
186 {
187     uint32_t temp = 0x00U;
188     temp = (RTC_DIVH & RTC_DIVH_DIV) << 16;
189     temp |= RTC_DIVL;
190     return temp;
191 }
192 
193 /*!
194     \brief      get RTC flag status
195     \param[in]  flag: specify which flag status to get
196           \arg    RTC_FLAG_SECOND: second interrupt flag
197           \arg    RTC_FLAG_ALARM: alarm interrupt flag
198           \arg    RTC_FLAG_OVERFLOW: overflow interrupt flag
199           \arg    RTC_FLAG_RSYN: registers synchronized flag
200           \arg    RTC_FLAG_LWOF: last write operation finished flag
201     \param[out] none
202     \retval     SET or RESET
203 */
rtc_flag_get(uint32_t flag)204 FlagStatus rtc_flag_get(uint32_t flag)
205 {
206     if(RESET != (RTC_CTL & flag)){
207         return SET;
208     }else{
209         return RESET;
210     }
211 }
212 
213 /*!
214     \brief      clear RTC flag status
215     \param[in]  flag: specify which flag status to clear
216           \arg    RTC_FLAG_SECOND: second interrupt flag
217           \arg    RTC_FLAG_ALARM: alarm interrupt flag
218           \arg    RTC_FLAG_OVERFLOW: overflow interrupt flag
219           \arg    RTC_FLAG_RSYN: registers synchronized flag
220     \param[out] none
221     \retval     none
222 */
rtc_flag_clear(uint32_t flag)223 void rtc_flag_clear(uint32_t flag)
224 {
225     /* clear RTC flag */
226     RTC_CTL &= ~flag;
227 }
228 
229