/* * File : rtc.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://openlab.rt-thread.com/license/LICENSE * * Change Logs: * Date Author Notes * 2009-04-26 yi.qiu first version */ #include #include #include #include "rtc.h" /** * This function get rtc time */ void rt_hw_rtc_get(struct rtc_time *ti) { rt_uint8_t sec, min, hour, mday, wday, mon, year; /* enable access to RTC registers */ RTC_ENABLE(); /* read RTC registers */ do { sec = BCDSEC; min = BCDMIN; hour = BCDHOUR; mday = BCDDATE; wday = BCDDAY; mon = BCDMON; year = BCDYEAR; } while (sec != BCDSEC); /* disable access to RTC registers */ RTC_DISABLE(); ti->tm_sec = BCD2BIN(sec & 0x7F); ti->tm_min = BCD2BIN(min & 0x7F); ti->tm_hour = BCD2BIN(hour & 0x3F); ti->tm_mday = BCD2BIN(mday & 0x3F); ti->tm_mon = BCD2BIN(mon & 0x1F); ti->tm_year = BCD2BIN(year); ti->tm_wday = BCD2BIN(wday & 0x07); ti->tm_yday = 0; ti->tm_isdst = 0; } /** * This function set rtc time */ void rt_hw_rtc_set(struct rtc_time *ti) { rt_uint8_t sec, min, hour, mday, wday, mon, year; year = BIN2BCD(ti->tm_year); mon = BIN2BCD(ti->tm_mon); wday = BIN2BCD(ti->tm_wday); mday = BIN2BCD(ti->tm_mday); hour = BIN2BCD(ti->tm_hour); min = BIN2BCD(ti->tm_min); sec = BIN2BCD(ti->tm_sec); /* enable access to RTC registers */ RTC_ENABLE(); /* write RTC registers */ BCDSEC = sec; BCDMIN = min; BCDHOUR = hour; BCDDATE = mday; BCDDAY = wday; BCDMON = mon; BCDYEAR = year; /* disable access to RTC registers */ RTC_DISABLE(); } /** * This function reset rtc */ void rt_hw_rtc_reset (void) { RTCCON = (RTCCON & ~0x06) | 0x08; RTCCON &= ~(0x08|0x01); } static struct rt_device rtc; static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag) { RTC_ENABLE(); return RT_EOK; } static rt_err_t rt_rtc_close(rt_device_t dev) { RTC_DISABLE(); return RT_EOK; } static rt_size_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size) { return RT_EOK; } static rt_err_t rt_rtc_control(rt_device_t dev, rt_uint8_t cmd, void *args) { struct rtc_time* time; RT_ASSERT(dev != RT_NULL); time = (struct rtc_time*)args; switch (cmd) { case RT_DEVICE_CTRL_RTC_GET_TIME: /* read device */ rt_hw_rtc_get(time); break; case RT_DEVICE_CTRL_RTC_SET_TIME: /* write device */ rt_hw_rtc_set(time); break; } return RT_EOK; } void rt_hw_rtc_init(void) { rtc.type = RT_Device_Class_RTC; /* register rtc device */ rtc.init = RT_NULL; rtc.open = rt_rtc_open; rtc.close = rt_rtc_close; rtc.read = rt_rtc_read; rtc.write = RT_NULL; rtc.control = rt_rtc_control; /* no private */ rtc.private = RT_NULL; rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR); } time_t time(time_t* t) { rt_device_t device; struct tm ti; time_t time; device = rt_device_find("rtc"); if (device != RT_NULL) { rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &ti); if (t != RT_NULL) { time = mktime(&ti); *t = time; } } return time; } #ifdef RT_USING_FINSH #include void set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) { struct rtc_time ti; rt_device_t device; device = rt_device_find("rtc"); if (device != RT_NULL) { rt_rtc_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &ti); ti.tm_year = year - 1900; ti.tm_mon = month - 1; ti.tm_mday = day; rt_rtc_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &ti); } } FINSH_FUNCTION_EXPORT(set_date, set date(year, month, day)) void set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) { struct rtc_time ti; rt_device_t device; device = rt_device_find("rtc"); if (device != RT_NULL) { rt_rtc_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &ti); ti.tm_hour = hour; ti.tm_min = minute; ti.tm_sec = second; rt_rtc_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &ti); } } FINSH_FUNCTION_EXPORT(set_time, set time(hour, minute, second)) void list_date(void) { time_t now; time(&now); rt_kprintf("%s\n", ctime(&now)); } FINSH_FUNCTION_EXPORT(list_date, list date) #endif