1 /*
2  * Copyright (c) 2006-2023, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date         Author        Notes
8  * 2024-01-13   ChuShicheng   first version
9  */
10 
11 #include "board.h"
12 #include <rtdevice.h>
13 #include "hardware/rtc.h"
14 #include "pico/util/datetime.h"
15 
16 #define DBG_LEVEL   DBG_LOG
17 #include <rtdbg.h>
18 #define LOG_TAG "DRV.RTC"
19 
20 struct rtc_device_object
21 {
22     rt_rtc_dev_t  rtc_dev;
23 };
24 
25 static struct rtc_device_object rtc_device;
26 
pico_rtc_get_timeval(struct timeval * tv)27 static rt_err_t pico_rtc_get_timeval(struct timeval *tv)
28 {
29     datetime_t t;
30     struct tm tm_new = {0};
31     rtc_get_datetime(&t);
32 
33     tm_new.tm_sec  = t.sec;
34     tm_new.tm_min  = t.min;
35     tm_new.tm_hour = t.hour;
36     tm_new.tm_wday = t.dotw;
37     tm_new.tm_mday = t.day;
38     tm_new.tm_mon  = t.month - 1;
39     tm_new.tm_year = t.year - 1900;
40 
41     tv->tv_sec = timegm(&tm_new);
42 
43     return RT_EOK;
44 }
45 
pico_rtc_init(void)46 static rt_err_t pico_rtc_init(void)
47 {
48     rtc_init();
49 
50     datetime_t t;
51     t.sec     = 0 ;
52     t.min     = 0;
53     t.hour    = 0;
54     t.day     = 01;
55     t.month   = 01;
56     t.year    = 1970;
57     t.dotw    = 4;
58     rtc_set_datetime(&t);
59 
60     return RT_EOK;
61 }
62 
pico_rtc_get_secs(time_t * sec)63 static rt_err_t pico_rtc_get_secs(time_t *sec)
64 {
65     struct timeval tv;
66 
67     pico_rtc_get_timeval(&tv);
68     *(time_t *) sec = tv.tv_sec;
69     LOG_D("RTC: get rtc_time %d", *sec);
70 
71     return RT_EOK;
72 }
73 
pico_rtc_set_secs(time_t * sec)74 static rt_err_t pico_rtc_set_secs(time_t *sec)
75 {
76     rt_err_t result = RT_EOK;
77     datetime_t t;
78     struct tm tm = {0};
79 
80     gmtime_r(sec, &tm);
81 
82     t.sec     = tm.tm_sec ;
83     t.min     = tm.tm_min ;
84     t.hour    = tm.tm_hour;
85     t.day     = tm.tm_mday;
86     t.month   = tm.tm_mon  + 1;
87     t.year    = tm.tm_year + 1900;
88     t.dotw    = tm.tm_wday;
89 
90     rtc_set_datetime(&t);
91     LOG_D("RTC: set rtc_time");
92 #ifdef RT_USING_ALARM
93     rt_alarm_update(&rtc_device.rtc_dev.parent, 1);
94 #endif
95     return result;
96 }
97 
98 static const struct rt_rtc_ops pico_rtc_ops =
99 {
100     pico_rtc_init,
101     pico_rtc_get_secs,
102     pico_rtc_set_secs,
103     RT_NULL,
104     RT_NULL,
105     pico_rtc_get_timeval,
106     RT_NULL,
107 };
108 
rt_hw_rtc_init(void)109 static int rt_hw_rtc_init(void)
110 {
111     rt_err_t result;
112 
113     rtc_device.rtc_dev.ops = &pico_rtc_ops;
114     result = rt_hw_rtc_register(&rtc_device.rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
115     if (result != RT_EOK)
116     {
117         LOG_E("rtc register err code: %d", result);
118         return result;
119     }
120     LOG_D("rtc init success");
121 
122     return RT_EOK;
123 }
124 INIT_DEVICE_EXPORT(rt_hw_rtc_init);
125