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