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