1 /*!
2     \file    gd32e10x_rtc.c
3     \brief   RTC driver
4 
5     \version 2017-12-26, V1.0.0, firmware for GD32E10x
6     \version 2020-09-30, V1.1.0, firmware for GD32E10x
7     \version 2020-12-31, V1.2.0, firmware for GD32E10x
8     \version 2022-06-30, V1.3.0, firmware for GD32E10x
9 */
10 
11 /*
12     Copyright (c) 2022, GigaDevice Semiconductor Inc.
13 
14     Redistribution and use in source and binary forms, with or without modification,
15 are permitted provided that the following conditions are met:
16 
17     1. Redistributions of source code must retain the above copyright notice, this
18        list of conditions and the following disclaimer.
19     2. Redistributions in binary form must reproduce the above copyright notice,
20        this list of conditions and the following disclaimer in the documentation
21        and/or other materials provided with the distribution.
22     3. Neither the name of the copyright holder nor the names of its contributors
23        may be used to endorse or promote products derived from this software without
24        specific prior written permission.
25 
26     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
28 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
30 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
32 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
33 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
35 OF SUCH DAMAGE.
36 */
37 
38 #include "gd32e10x_rtc.h"
39 
40 /* RTC register high / low bits mask */
41 #define RTC_HIGH_BITS_MASK         ((uint32_t)0x000F0000U)  /* RTC high bits mask */
42 #define RTC_LOW_BITS_MASK          ((uint32_t)0x0000FFFFU)  /* RTC low bits mask */
43 
44 /* RTC register high bits offset */
45 #define RTC_HIGH_BITS_OFFSET       ((uint32_t)16U)
46 
47 /*!
48     \brief      enter RTC configuration mode
49     \param[in]  none
50     \param[out] none
51     \retval     none
52 */
rtc_configuration_mode_enter(void)53 void rtc_configuration_mode_enter(void)
54 {
55     RTC_CTL |= RTC_CTL_CMF;
56 }
57 
58 /*!
59     \brief      exit RTC configuration mode
60     \param[in]  none
61     \param[out] none
62     \retval     none
63 */
rtc_configuration_mode_exit(void)64 void rtc_configuration_mode_exit(void)
65 {
66     RTC_CTL &= ~RTC_CTL_CMF;
67 }
68 
69 /*!
70     \brief      set RTC counter value
71     \param[in]  cnt: RTC counter value
72     \param[out] none
73     \retval     none
74 */
rtc_counter_set(uint32_t cnt)75 void rtc_counter_set(uint32_t cnt)
76 {
77     rtc_configuration_mode_enter();
78     /* set the RTC counter high bits */
79     RTC_CNTH = (cnt >> RTC_HIGH_BITS_OFFSET);
80     /* set the RTC counter low bits */
81     RTC_CNTL = (cnt & RTC_LOW_BITS_MASK);
82     rtc_configuration_mode_exit();
83 }
84 
85 /*!
86     \brief      set RTC prescaler value
87     \param[in]  psc: RTC prescaler value
88     \param[out] none
89     \retval     none
90 */
rtc_prescaler_set(uint32_t psc)91 void rtc_prescaler_set(uint32_t psc)
92 {
93     rtc_configuration_mode_enter();
94     /* set the RTC prescaler high bits */
95     RTC_PSCH = ((psc & RTC_HIGH_BITS_MASK) >> RTC_HIGH_BITS_OFFSET);
96     /* set the RTC prescaler low bits */
97     RTC_PSCL = (psc & RTC_LOW_BITS_MASK);
98     rtc_configuration_mode_exit();
99 }
100 
101 /*!
102     \brief      wait RTC last write operation finished flag set
103     \param[in]  none
104     \param[out] none
105     \retval     none
106 */
rtc_lwoff_wait(void)107 void rtc_lwoff_wait(void)
108 {
109     /* loop until LWOFF flag is set */
110     while(RESET == (RTC_CTL & RTC_CTL_LWOFF)){
111     }
112 }
113 
114 /*!
115     \brief      wait RTC registers synchronized flag set
116     \param[in]  none
117     \param[out] none
118     \retval     none
119 */
rtc_register_sync_wait(void)120 void rtc_register_sync_wait(void)
121 {
122     /* clear RSYNF flag */
123     RTC_CTL &= ~RTC_CTL_RSYNF;
124     /* loop until RSYNF flag is set */
125     while(RESET == (RTC_CTL & RTC_CTL_RSYNF)){
126     }
127 }
128 
129 /*!
130     \brief      set RTC alarm value
131     \param[in]  alarm: RTC alarm value
132     \param[out] none
133     \retval     none
134 */
rtc_alarm_config(uint32_t alarm)135 void rtc_alarm_config(uint32_t alarm)
136 {
137     rtc_configuration_mode_enter();
138     /* set the alarm high bits */
139     RTC_ALRMH = (alarm >> RTC_HIGH_BITS_OFFSET);
140     /* set the alarm low bits */
141     RTC_ALRML = (alarm & RTC_LOW_BITS_MASK);
142     rtc_configuration_mode_exit();
143 }
144 
145 /*!
146     \brief      get RTC counter value
147     \param[in]  none
148     \param[out] none
149     \retval     RTC counter value
150 */
rtc_counter_get(void)151 uint32_t rtc_counter_get(void)
152 {
153     uint32_t temp = 0x0U, high_old, high_new;
154 
155     high_old = RTC_CNTH;
156     temp = RTC_CNTL;
157     high_new = RTC_CNTH;
158 
159     if(high_old != high_new){
160         temp = (high_new << RTC_HIGH_BITS_OFFSET) | RTC_CNTL;
161     }else{
162         temp |= (high_new << RTC_HIGH_BITS_OFFSET);
163     }
164 
165     return temp;
166 }
167 
168 /*!
169     \brief      get RTC divider value
170     \param[in]  none
171     \param[out] none
172     \retval     RTC divider value
173 */
rtc_divider_get(void)174 uint32_t rtc_divider_get(void)
175 {
176     uint32_t temp = 0x00U;
177 
178     temp = ((RTC_DIVH & RTC_DIVH_DIV) << RTC_HIGH_BITS_OFFSET);
179     temp |= RTC_DIVL;
180     return temp;
181 }
182 
183 /*!
184     \brief      get RTC flag status
185     \param[in]  flag: specify which flag status to get
186                 only one parameter can be selected which is shown as below:
187       \arg        RTC_FLAG_SECOND: second interrupt flag
188       \arg        RTC_FLAG_ALARM: alarm interrupt flag
189       \arg        RTC_FLAG_OVERFLOW: overflow interrupt flag
190       \arg        RTC_FLAG_RSYN: registers synchronized flag
191       \arg        RTC_FLAG_LWOF: last write operation finished flag
192     \param[out] none
193     \retval     SET or RESET
194 */
rtc_flag_get(uint32_t flag)195 FlagStatus rtc_flag_get(uint32_t flag)
196 {
197     if(RESET != (RTC_CTL & flag)){
198         return SET;
199     }else{
200         return RESET;
201     }
202 }
203 
204 /*!
205     \brief      clear RTC flag status
206     \param[in]  flag: specify which flag status to clear
207                 one or more parameters can be selected which are shown as below:
208       \arg        RTC_FLAG_SECOND: second interrupt flag
209       \arg        RTC_FLAG_ALARM: alarm interrupt flag
210       \arg        RTC_FLAG_OVERFLOW: overflow interrupt flag
211       \arg        RTC_FLAG_RSYN: registers synchronized flag
212     \param[out] none
213     \retval     none
214 */
rtc_flag_clear(uint32_t flag)215 void rtc_flag_clear(uint32_t flag)
216 {
217     /* clear RTC flag */
218     RTC_CTL &= ~flag;
219 }
220 
221 /*!
222     \brief      get RTC interrupt flag status
223     \param[in]  flag: specify which flag status to get
224                 only one parameter can be selected which is shown as below:
225       \arg        RTC_INT_FLAG_SECOND: second interrupt flag
226       \arg        RTC_INT_FLAG_ALARM: alarm interrupt flag
227       \arg        RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
228     \param[out] none
229     \retval     SET or RESET
230 */
rtc_interrupt_flag_get(uint32_t flag)231 FlagStatus rtc_interrupt_flag_get(uint32_t flag)
232 {
233     if(RESET != (RTC_CTL & flag)){
234         return SET;
235     }else{
236         return RESET;
237     }
238 }
239 
240 /*!
241     \brief      clear RTC interrupt flag status
242     \param[in]  flag: specify which flag status to clear
243                 one or more parameters can be selected which are shown as below:
244       \arg        RTC_INT_FLAG_SECOND: second interrupt flag
245       \arg        RTC_INT_FLAG_ALARM: alarm interrupt flag
246       \arg        RTC_INT_FLAG_OVERFLOW: overflow interrupt flag
247     \param[out] none
248     \retval     none
249 */
rtc_interrupt_flag_clear(uint32_t flag)250 void rtc_interrupt_flag_clear(uint32_t flag)
251 {
252     /* clear RTC interrupt flag */
253     RTC_CTL &= ~flag;
254 }
255 
256 /*!
257     \brief      enable RTC interrupt
258     \param[in]  interrupt: specify which interrupt to enable
259                 one or more parameters can be selected which are shown as below:
260       \arg        RTC_INT_SECOND: second interrupt
261       \arg        RTC_INT_ALARM: alarm interrupt
262       \arg        RTC_INT_OVERFLOW: overflow interrupt
263     \param[out] none
264     \retval     none
265 */
rtc_interrupt_enable(uint32_t interrupt)266 void rtc_interrupt_enable(uint32_t interrupt)
267 {
268     RTC_INTEN |= interrupt;
269 }
270 
271 /*!
272     \brief      disable RTC interrupt
273     \param[in]  interrupt: specify which interrupt to disable
274                 one or more parameters can be selected which are shown as below:
275       \arg        RTC_INT_SECOND: second interrupt
276       \arg        RTC_INT_ALARM: alarm interrupt
277       \arg        RTC_INT_OVERFLOW: overflow interrupt
278     \param[out] none
279     \retval     none
280 */
rtc_interrupt_disable(uint32_t interrupt)281 void rtc_interrupt_disable(uint32_t interrupt)
282 {
283     RTC_INTEN &= ~interrupt;
284 }
285