1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2022-10-19 Nations first version
9 */
10
11 #include "board.h"
12 #include <sys/time.h>
13 #include <rtdevice.h>
14
15 #ifdef BSP_USING_RTC
16
17 #define USER_WRITE_BKP_DAT1_DATA 0xA5A5
18
19 uint32_t SynchPrediv, AsynchPrediv;
20
n32_rtc_get_timeval(struct timeval * tv)21 static rt_err_t n32_rtc_get_timeval(struct timeval *tv)
22 {
23 struct tm tm_new = {0};
24 RTC_DateType RTC_DateStructure;
25 RTC_TimeType RTC_TimeStructure;
26
27 RTC_GetTime(RTC_FORMAT_BIN, &RTC_TimeStructure);
28 RTC_GetDate(RTC_FORMAT_BIN, &RTC_DateStructure);
29
30 tm_new.tm_sec = RTC_TimeStructure.Seconds;
31 tm_new.tm_min = RTC_TimeStructure.Minutes;
32 tm_new.tm_hour = RTC_TimeStructure.Hours;
33 tm_new.tm_wday = RTC_DateStructure.WeekDay;
34 tm_new.tm_mday = RTC_DateStructure.Date;
35 tm_new.tm_mon = RTC_DateStructure.Month - 1;
36 tm_new.tm_year = RTC_DateStructure.Year + 100;
37
38 tv->tv_sec = timegm(&tm_new);
39
40 return RT_EOK;
41 }
42
set_rtc_time_stamp(time_t time_stamp)43 static rt_err_t set_rtc_time_stamp(time_t time_stamp)
44 {
45 struct tm time = {0};
46 RTC_DateType RTC_DateStructure={0};
47 RTC_TimeType RTC_TimeStructure={0};
48
49 gmtime_r(&time_stamp, &time);
50 if (time.tm_year < 100)
51 {
52 return -RT_ERROR;
53 }
54
55 RTC_TimeStructure.Seconds = time.tm_sec ;
56 RTC_TimeStructure.Minutes = time.tm_min ;
57 RTC_TimeStructure.Hours = time.tm_hour;
58 RTC_DateStructure.Date = time.tm_mday;
59 RTC_DateStructure.Month = time.tm_mon + 1 ;
60 RTC_DateStructure.Year = time.tm_year - 100;
61 RTC_DateStructure.WeekDay = time.tm_wday + 1;
62
63 /* Configure the RTC date register */
64 if (RTC_SetDate(RTC_FORMAT_BIN, &RTC_DateStructure) != SUCCESS)
65 {
66 return -RT_ERROR;
67 }
68
69 /* Configure the RTC time register */
70 if (RTC_ConfigTime(RTC_FORMAT_BIN, &RTC_TimeStructure) != SUCCESS)
71 {
72 return -RT_ERROR;
73 }
74
75 rt_kprintf("set rtc time.\n");
76
77 return RT_EOK;
78 }
79
rt_rtc_config(void)80 static rt_err_t rt_rtc_config(void)
81 {
82 RTC_InitType RTC_InitStructure;
83
84 /* Configure the RTC data register and RTC prescaler */
85 RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
86 RTC_InitStructure.RTC_SynchPrediv = SynchPrediv;
87 RTC_InitStructure.RTC_HourFormat = RTC_24HOUR_FORMAT;
88
89 /* Check on RTC init */
90 if (RTC_Init(&RTC_InitStructure) != SUCCESS)
91 {
92 return -RT_ERROR;
93 }
94 return RT_EOK;
95 }
96
n32_rtc_init(void)97 static rt_err_t n32_rtc_init(void)
98 {
99 /* Enable the PWR clock */
100 #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
101 RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR | RCC_APB1_PERIPH_BKP, ENABLE);
102 RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
103 #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
104 RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE);
105 RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
106 #endif
107
108 /* Allow access to RTC */
109 PWR_BackupAccessEnable(ENABLE);
110 if (USER_WRITE_BKP_DAT1_DATA != BKP_ReadBkpData(BKP_DAT1) )
111 {
112
113 #if defined(SOC_N32G45X) || defined(SOC_N32WB452)
114 /* Reset Backup */
115 BKP_DeInit();
116 #endif
117
118 /* Disable RTC clock */
119 RCC_EnableRtcClk(DISABLE);
120
121 #ifdef BSP_RTC_USING_HSE
122 /* Enable the HSE OSC */
123 RCC_EnableLsi(DISABLE);
124 RCC_ConfigHse(RCC_HSE_ENABLE);
125 while (RCC_WaitHseStable() == ERROR)
126 {
127 }
128 #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
129 rt_kprintf("rtc clock source is set hse/128!\n");
130 RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV128);
131 #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
132 rt_kprintf("rtc clock source is set hse/32!\n");
133 RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV32);
134 #endif
135
136 #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
137 SynchPrediv = 0x1E8; // 8M/128 = 62.5KHz
138 AsynchPrediv = 0x7F; // value range: 0-7F
139 #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
140 SynchPrediv = 0x7A0; // 8M/32 = 250KHz
141 AsynchPrediv = 0x7F; // value range: 0-7F
142 #endif
143 #endif /* BSP_RTC_USING_HSE */
144
145 #ifdef BSP_RTC_USING_LSE
146 rt_kprintf("rtc clock source is set lse!\n");
147 /* Enable the LSE OSC32_IN PC14 */
148 RCC_EnableLsi(DISABLE); // LSI is turned off here to ensure that only one clock is turned on
149
150 #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
151 RCC_ConfigLse(RCC_LSE_ENABLE);
152 while (RCC_GetFlagStatus(RCC_FLAG_LSERD) == RESET)
153 {
154 }
155 #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
156 RCC_ConfigLse(RCC_LSE_ENABLE,0x28);
157 while (RCC_GetFlagStatus(RCC_LDCTRL_FLAG_LSERD) == RESET)
158 {
159 }
160 #endif
161 RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSE);
162
163 SynchPrediv = 0xFF; // 32.768KHz
164 AsynchPrediv = 0x7F; // value range: 0-7F
165 #endif /* BSP_RTC_USING_LSE */
166
167 #ifdef BSP_RTC_USING_LSI
168 rt_kprintf("rtc clock source is set lsi!\n");
169 /* Enable the LSI OSC */
170 RCC_EnableLsi(ENABLE);
171 #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
172 while (RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET)
173 {
174 }
175 #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
176 while (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_LSIRD) == RESET)
177 {
178 }
179 #endif
180 RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSI);
181
182 #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
183 SynchPrediv = 0x136; // 39.64928KHz
184 AsynchPrediv = 0x7F; // value range: 0-7F
185 #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
186 SynchPrediv = 0x14A; // 41828Hz
187 AsynchPrediv = 0x7F; // value range: 0-7F
188 #endif
189 #endif /* BSP_RTC_USING_LSI */
190
191 /* Enable the RTC Clock */
192 RCC_EnableRtcClk(ENABLE);
193 RTC_WaitForSynchro();
194
195 if (rt_rtc_config() != RT_EOK)
196 {
197 rt_kprintf("rtc init failed.\n");
198 return -RT_ERROR;
199 }
200
201 BKP_WriteBkpData(BKP_DAT1, USER_WRITE_BKP_DAT1_DATA);
202 }
203
204 return RT_EOK;
205 }
206
n32_rtc_get_secs(time_t * sec)207 static rt_err_t n32_rtc_get_secs(time_t *sec)
208 {
209 struct timeval tv;
210
211 n32_rtc_get_timeval(&tv);
212 *(time_t *) sec = tv.tv_sec;
213
214 rt_kprintf("RTC: get rtc_time %d.\n", *sec);
215
216 return RT_EOK;
217 }
218
n32_rtc_set_secs(time_t * sec)219 static rt_err_t n32_rtc_set_secs(time_t *sec)
220 {
221 rt_err_t result = RT_EOK;
222
223 if (set_rtc_time_stamp(*sec))
224 {
225 result = -RT_ERROR;
226 }
227
228 rt_kprintf("RTC: set rtc_time %d.\n", *sec);
229
230 return result;
231 }
232
233 static const struct rt_rtc_ops n32_rtc_ops =
234 {
235 n32_rtc_init,
236 n32_rtc_get_secs,
237 n32_rtc_set_secs,
238 RT_NULL,
239 RT_NULL,
240 n32_rtc_get_timeval,
241 RT_NULL,
242 };
243
244 static rt_rtc_dev_t n32_rtc_dev;
245
rt_hw_rtc_init(void)246 static int rt_hw_rtc_init(void)
247 {
248 rt_err_t result;
249
250 n32_rtc_dev.ops = &n32_rtc_ops;
251 result = rt_hw_rtc_register(&n32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
252 if (result != RT_EOK)
253 {
254 rt_kprintf("rtc register error code: %d.\n", result);
255 return result;
256 }
257 else
258 {
259 rt_kprintf("rtc initialize success.\n");
260 }
261
262 return RT_EOK;
263 }
264 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
265 #endif /* BSP_USING_RTC */
266
267