1 #include "ameba_soc.h"
2 #include "k_api.h"
3 #include "board.h"
4 #include "device.h"
5 #include "aos/hal/rtc.h"
6 #include <time.h>
7 #include "rtc_api.h"
8
9 static struct tm rtc_timeinfo;
10 static int rtc_en = 0;
11
12 const static u8 dim[12] = {
13 31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
14
15 /**
16 * @brief This function is used to tell a year is a leap year or not.
17 * @param year: The year need to be told.
18 * @retval value:
19 * - 1: This year is leap year.
20 * - 0: This year is not leap year.
21 */
is_leap_year(unsigned int year)22 static inline bool is_leap_year(unsigned int year)
23 {
24 u32 full_year = year + 1900;
25 return (!(full_year % 4) && (full_year % 100)) || !(full_year % 400);
26 }
27
28
29 /**
30 * @brief This function tells how many days in a month of a year.
31 * @param year: Specified year
32 * @param month: Specified month
33 * @retval value: Number of days in the month.
34 */
days_in_month(u8 month,u8 year)35 static u8 days_in_month (u8 month, u8 year)
36 {
37 u8 ret = dim[month];
38 if (ret == 0)
39 ret = is_leap_year (year) ? 29 : 28;
40 return ret;
41 }
42
43 /**
44 * @brief This function is used to calculate month and day of month according to year and day of the year.
45 * @param year: years since 1900.
46 * @param yday: day of the year.
47 * @param mon: pointer to the variable which stores month, the value can be 0-11
48 * @param mday: pointer to the variable which stores day of month, the value can be 1-31
49 * @retval value: none
50 */
rtc_calculate_mday(int year,int yday,int * mon,int * mday)51 static void rtc_calculate_mday(int year, int yday, int* mon, int* mday)
52 {
53 int t_mon = -1, t_yday = yday + 1;
54
55 while(t_yday > 0){
56 t_mon ++;
57 t_yday -= days_in_month(t_mon, year);
58 }
59
60 *mon = t_mon;
61 *mday = t_yday + days_in_month(t_mon, year);
62 }
63
64 /**
65 * @brief This function is used to calculate day of week according to date.
66 * @param year: years since 1900.
67 * @param mon: which month of the year
68 * @param mday: pointer to the variable which store day of month
69 * @param wday: pointer to the variable which store day of week, the value can be 0-6, and 0 means Sunday
70 * @retval value: none
71 */
rtc_calculate_wday(int year,int mon,int mday,int * wday)72 static void rtc_calculate_wday(int year, int mon, int mday, int* wday)
73 {
74 int t_year = year + 1900, t_mon = mon + 1;
75
76 if(t_mon == 1 || t_mon == 2){
77 t_year --;
78 t_mon += 12;
79 }
80
81 int c = t_year / 100;
82 int y = t_year % 100;
83 int week = (c / 4) - 2 * c + (y + y / 4) + (26 * (t_mon + 1) / 10) + mday -1;
84
85 while(week < 0){
86 week += 7;
87 }
88 week %= 7;
89
90 *wday = week;
91 }
92
get_yday(rtc_time_t * time)93 static u32 get_yday(rtc_time_t *time)
94 {
95 int days = time->date;
96
97 for(int i = 0; i < time->month-1; i++){
98 days += dim[i];
99 }
100 }
101
102 /**
103 * @brief This function is used to restore rtc_timeinfo global variable whose value is lost after system reset.
104 * @param none
105 * @retval value: none
106 */
rtc_restore_timeinfo(rtc_dev_t * rtc)107 static void rtc_restore_timeinfo(rtc_dev_t *rtc)
108 {
109 u32 value, days_in_year, format;
110
111 if(rtc->config.format == HAL_RTC_FORMAT_DEC)
112 format = RTC_Format_BIN;
113 else if(rtc->config.format == HAL_RTC_FORMAT_BCD)
114 format = RTC_Format_BCD;
115
116
117 RTC_TimeTypeDef RTC_TimeStruct;
118 RTC_GetTime(format, &RTC_TimeStruct);
119 rtc_timeinfo.tm_sec = RTC_TimeStruct.RTC_Seconds;
120 rtc_timeinfo.tm_min = RTC_TimeStruct.RTC_Minutes;
121 rtc_timeinfo.tm_hour = RTC_TimeStruct.RTC_Hours;
122 rtc_timeinfo.tm_yday = RTC_TimeStruct.RTC_Days;
123
124 value = BKUP_Read(0);
125
126 rtc_timeinfo.tm_year = (value & BIT_RTC_BACKUP) >> 8;
127
128 days_in_year = (is_leap_year(rtc_timeinfo.tm_year) ? 366 : 365);
129 if(rtc_timeinfo.tm_yday > days_in_year - 1){
130 rtc_timeinfo.tm_year ++;
131 rtc_timeinfo.tm_yday -= days_in_year;
132
133 /* over one year, update days in RTC_TR */
134 RTC_TimeStruct.RTC_Days = rtc_timeinfo.tm_yday;
135 RTC_SetTime(format, &RTC_TimeStruct);
136 }
137
138 rtc_calculate_mday(rtc_timeinfo.tm_year, rtc_timeinfo.tm_yday, &rtc_timeinfo.tm_mon, &rtc_timeinfo.tm_mday);
139 rtc_calculate_wday(rtc_timeinfo.tm_year, rtc_timeinfo.tm_mon, rtc_timeinfo.tm_mday, &rtc_timeinfo.tm_wday);
140 }
141
142
143 /**
144 * @brief Initializes the RTC device, include clock, RTC registers and function.
145 * @param none
146 * @retval none
147 */
148
149 /**
150 * This function will initialize the on board CPU real time clock
151 *
152 *
153 * @param[in] rtc rtc device
154 *
155 * @return 0 : on success, EIO : if an error occurred with any step
156 */
hal_rtc_init(rtc_dev_t * rtc)157 int32_t hal_rtc_init(rtc_dev_t *rtc)
158 {
159 RTC_InitTypeDef RTC_InitStruct;
160
161 RCC_PeriphClockSource_RTC(0);
162
163 RTC_StructInit(&RTC_InitStruct);
164 RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
165
166 RTC_Init(&RTC_InitStruct);
167
168 /* 32760 need add need add 15 cycles (256Hz) every 4 min*/
169 //RTC_SmoothCalibConfig(RTC_CalibSign_Positive, 15,
170 // RTC_CalibPeriod_4MIN, RTC_Calib_Enable);
171
172 rtc_en = 1;
173
174 return 0;
175 }
176
177 /**
178 * This function will return the value of time read from the on board CPU real time clock.
179 *
180 * @param[in] rtc rtc device
181 * @param[out] time pointer to a time structure
182 *
183 * @return 0 : on success, EIO : if an error occurred with any step
184 */
hal_rtc_get_time(rtc_dev_t * rtc,rtc_time_t * time)185 int32_t hal_rtc_get_time(rtc_dev_t *rtc, rtc_time_t *time)
186 {
187 int format;
188 struct tm tm_temp;
189 RTC_TimeTypeDef RTC_TimeStruct;
190 u32 delta_days = 0;
191
192 if(BKUP_Read(0) & BIT_RTC_RESTORE){
193 rtc_restore_timeinfo(rtc);
194 BKUP_Clear(0, BIT_RTC_RESTORE);
195 }
196
197 _memcpy((void*)&tm_temp, (void*)&rtc_timeinfo, sizeof(struct tm));
198
199 if(rtc->config.format == HAL_RTC_FORMAT_DEC)
200 format = RTC_Format_BIN;
201 else if(rtc->config.format == HAL_RTC_FORMAT_BCD)
202 format = RTC_Format_BCD;
203 /*hour, min, sec get from RTC*/
204 RTC_GetTime(format, &RTC_TimeStruct);
205 tm_temp.tm_sec = RTC_TimeStruct.RTC_Seconds;
206 tm_temp.tm_min = RTC_TimeStruct.RTC_Minutes;
207 tm_temp.tm_hour = RTC_TimeStruct.RTC_Hours;
208
209 /* calculate how many days later from last time update rtc_timeinfo */
210 delta_days = RTC_TimeStruct.RTC_Days - tm_temp.tm_yday;
211
212 /* calculate wday, mday, yday, mon, year*/
213 tm_temp.tm_wday += delta_days;
214 if(tm_temp.tm_wday >= 7){
215 tm_temp.tm_wday = tm_temp.tm_wday % 7;
216 }
217
218 tm_temp.tm_yday += delta_days;
219 tm_temp.tm_mday += delta_days;
220
221 while(tm_temp.tm_mday > days_in_month(tm_temp.tm_mon, tm_temp.tm_year)){
222 tm_temp.tm_mday -= days_in_month(tm_temp.tm_mon, tm_temp.tm_year);
223 tm_temp.tm_mon++;
224
225 if(tm_temp.tm_mon >= 12){
226 tm_temp.tm_mon -= 12;
227 tm_temp.tm_yday -= is_leap_year(tm_temp.tm_year) ? 366 : 365;
228 tm_temp.tm_year ++;
229
230 /* over one year, update days in RTC_TR */
231 RTC_TimeStruct.RTC_Days = tm_temp.tm_yday;
232 RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
233
234 /* update rtc_timeinfo */
235 _memcpy((void*)&rtc_timeinfo, (void*)&tm_temp, sizeof(struct tm));
236 }
237 }
238
239 time->sec = tm_temp.tm_sec;
240 time->min = tm_temp.tm_min;
241 time->hr = tm_temp.tm_hour;
242 time->weekday = tm_temp.tm_wday;
243 time->date = tm_temp.tm_mday;
244 time->month = tm_temp.tm_mon;
245 time->year = tm_temp.tm_year;
246
247 return 0;
248 }
249
250 /**
251 * This function will set MCU RTC time to a new value.
252 *
253 * @param[in] rtc rtc device
254 * @param[out] time pointer to a time structure
255 *
256 * @return 0 : on success, EIO : if an error occurred with any step
257 */
hal_rtc_set_time(rtc_dev_t * rtc,const rtc_time_t * time)258 int32_t hal_rtc_set_time(rtc_dev_t *rtc, const rtc_time_t *time)
259 {
260 struct tm timeinfo;
261 int format;
262
263 timeinfo.tm_sec = time->sec;
264 timeinfo.tm_min = time->min ;
265 timeinfo.tm_hour= time->hr;
266 timeinfo.tm_wday= time->weekday;
267 timeinfo.tm_mday= time->date;
268 timeinfo.tm_mon =time->month;
269 timeinfo.tm_year= time->year;
270
271 timeinfo.tm_yday = get_yday((rtc_time_t *)time);
272
273 RTC_TimeTypeDef RTC_TimeStruct;
274
275 /*set time in RTC */
276 RTC_TimeStruct.RTC_H12_PMAM = RTC_H12_AM;
277 RTC_TimeStruct.RTC_Days = timeinfo.tm_yday;
278 RTC_TimeStruct.RTC_Hours = timeinfo.tm_hour;
279 RTC_TimeStruct.RTC_Minutes = timeinfo.tm_min;
280 RTC_TimeStruct.RTC_Seconds = timeinfo.tm_sec;
281
282
283 if(rtc->config.format == HAL_RTC_FORMAT_DEC)
284 format = RTC_Format_BIN;
285 else if(rtc->config.format == HAL_RTC_FORMAT_BCD)
286 format = RTC_Format_BCD;
287
288 RTC_SetTime(format, &RTC_TimeStruct);
289
290 /* Set rtc_timeinfo*/
291 _memcpy((void*)&rtc_timeinfo, (void*)&timeinfo, sizeof(struct tm));
292
293 return 0;
294 }
295 /**
296 * De-initialises an RTC interface, Turns off an RTC hardware interface
297 *
298 * @param[in] RTC the interface which should be de-initialised
299 *
300 * @return 0 : on success, EIO : if an error occurred with any step
301 */
hal_rtc_finalize(rtc_dev_t * rtc)302 int32_t hal_rtc_finalize(rtc_dev_t *rtc)
303 {
304 rtc_en = 0;
305
306 return 0;
307 }
308
309