1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2009-04-26 yi.qiu first version
9 * 2010-03-18 Gary Lee add functions such as GregorianDay
10 * and rtc_time_to_tm
11 * 2009-03-20 yi.qiu clean up
12 */
13
14 #include <rtthread.h>
15 #include <time.h>
16 #include <s3c24x0.h>
17
18 // #define RTC_DEBUG
19
20 #define RTC_ENABLE RTCCON |= 0x01; /*RTC read and write enable */
21 #define RTC_DISABLE RTCCON &= ~0x01; /* RTC read and write disable */
22 #define BCD2BIN(n) (((((n) >> 4) & 0x0F) * 10) + ((n) & 0x0F))
23 #define BIN2BCD(n) ((((n) / 10) << 4) | ((n) % 10))
24
25 /**
26 * This function get rtc time
27 */
rt_hw_rtc_get(struct tm * ti)28 void rt_hw_rtc_get(struct tm *ti)
29 {
30 rt_uint8_t sec, min, hour, mday, wday, mon, year;
31
32 /* enable access to RTC registers */
33 RTCCON |= RTC_ENABLE;
34
35 /* read RTC registers */
36 do
37 {
38 sec = BCDSEC;
39 min = BCDMIN;
40 hour = BCDHOUR;
41 mday = BCDDATE;
42 wday = BCDDAY;
43 mon = BCDMON;
44 year = BCDYEAR;
45 } while (sec != BCDSEC);
46
47 #ifdef RTC_DEBUG
48 rt_kprintf("sec:%x min:%x hour:%x mday:%x wday:%x mon:%x year:%x\n",
49 sec, min, hour, mday, wday, mon, year);
50 #endif
51
52 /* disable access to RTC registers */
53 RTC_DISABLE
54
55 ti->tm_sec = BCD2BIN(sec & 0x7F);
56 ti->tm_min = BCD2BIN(min & 0x7F);
57 ti->tm_hour = BCD2BIN(hour & 0x3F);
58 ti->tm_mday = BCD2BIN(mday & 0x3F);
59 ti->tm_mon = BCD2BIN(mon & 0x1F);
60 ti->tm_year = BCD2BIN(year);
61 ti->tm_wday = BCD2BIN(wday & 0x07);
62 ti->tm_yday = 0;
63 ti->tm_isdst = 0;
64 }
65
66 /**
67 * This function set rtc time
68 */
rt_hw_rtc_set(struct tm * ti)69 void rt_hw_rtc_set(struct tm *ti)
70 {
71 rt_uint8_t sec, min, hour, mday, wday, mon, year;
72
73 year = BIN2BCD(ti->tm_year);
74 mon = BIN2BCD(ti->tm_mon);
75 wday = BIN2BCD(ti->tm_wday);
76 mday = BIN2BCD(ti->tm_mday);
77 hour = BIN2BCD(ti->tm_hour);
78 min = BIN2BCD(ti->tm_min);
79 sec = BIN2BCD(ti->tm_sec);
80
81 /* enable access to RTC registers */
82 RTC_ENABLE
83
84 do{
85 /* write RTC registers */
86 BCDSEC = sec;
87 BCDMIN = min;
88 BCDHOUR = hour;
89 BCDDATE = mday;
90 BCDDAY = wday;
91 BCDMON = mon;
92 BCDYEAR = year;
93 }while (sec != BCDSEC);
94
95 /* disable access to RTC registers */
96 RTC_DISABLE
97 }
98
99 /**
100 * This function reset rtc
101 */
rt_hw_rtc_reset(void)102 void rt_hw_rtc_reset (void)
103 {
104 RTCCON = (RTCCON & ~0x06) | 0x08;
105 RTCCON &= ~(0x08|0x01);
106 }
107
108 static struct rt_device rtc;
rtc_open(rt_device_t dev,rt_uint16_t oflag)109 static rt_err_t rtc_open(rt_device_t dev, rt_uint16_t oflag)
110 {
111 RTC_ENABLE
112 return RT_EOK;
113 }
114
rtc_close(rt_device_t dev)115 static rt_err_t rtc_close(rt_device_t dev)
116 {
117 RTC_DISABLE
118 return RT_EOK;
119 }
120
rtc_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)121 static rt_size_t rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
122 {
123 return RT_EOK;
124 }
125
rtc_control(rt_device_t dev,int cmd,void * args)126 static rt_err_t rtc_control(rt_device_t dev, int cmd, void *args)
127 {
128 struct tm tm, *tm_ptr;
129 time_t *time;
130 RT_ASSERT(dev != RT_NULL);
131
132 time = (time_t *)args;
133 switch (cmd)
134 {
135 case RT_DEVICE_CTRL_RTC_GET_TIME:
136 /* read device */
137 rt_hw_rtc_get(&tm);
138 *((rt_time_t *)args) = mktime(&tm);
139 break;
140
141 case RT_DEVICE_CTRL_RTC_SET_TIME:
142 tm_ptr = localtime(time);
143 /* write device */
144 rt_hw_rtc_set(tm_ptr);
145 break;
146 }
147
148 return RT_EOK;
149 }
150
rt_hw_rtc_init(void)151 void rt_hw_rtc_init(void)
152 {
153 rtc.type = RT_Device_Class_RTC;
154
155 /* register rtc device */
156 rtc.init = RT_NULL;
157 rtc.open = rtc_open;
158 rtc.close = rtc_close;
159 rtc.read = rtc_read;
160 rtc.write = RT_NULL;
161 rtc.control = rtc_control;
162
163 /* no private */
164 rtc.user_data = RT_NULL;
165
166 rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
167 }
168
169 #ifdef RT_USING_FINSH
170 #include <finsh.h>
list_date()171 void list_date()
172 {
173 time_t time;
174 rt_device_t device;
175
176 device = rt_device_find("rtc");
177 if (device != RT_NULL)
178 {
179 rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time);
180
181 rt_kprintf("%d, %s\n", time, ctime(&time));
182 }
183 }
184 FINSH_FUNCTION_EXPORT(list_date, list date);
185 #endif
186