/* * 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 * 2010-03-18 Gary Lee add functions such as GregorianDay * and rt_rtc_time_to_tm * 2009-03-20 yi.qiu clean up */ #include #include #include #define RTC_DEBUG #define RTC_ENABLE (RTCCON |= 0x01); /*RTC read and write enable */ #define RTC_DISABLE (RTCCON &= ~0x01); /* RTC read and write disable */ #define BCD2BIN(n) (((((n) >> 4) & 0x0F) * 10) + ((n) & 0x0F)) #define BIN2BCD(n) ((((n) / 10) << 4) | ((n) % 10)) /** * This function get rtc time */ void rt_hw_rtc_get(struct tm *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 tm *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 tm* time; RT_ASSERT(dev != RT_NULL); time = (struct tm*)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 tm 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 tm 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