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 */ 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 */ 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 */ 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; 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 115 static rt_err_t rtc_close(rt_device_t dev) 116 { 117 RTC_DISABLE 118 return RT_EOK; 119 } 120 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 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 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> 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