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