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 * 2018-01-30 armink the first version 9 */ 10 11 #include <time.h> 12 #include <string.h> 13 #include <rtthread.h> 14 15 #include <drivers/rtc.h> 16 17 #ifdef RT_USING_SOFT_RTC 18 19 /* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50) */ 20 #define RTC_TIME_INIT(year, month, day, hour, minute, second) \ 21 {.tm_year = year - 1900, .tm_mon = month - 1, .tm_mday = day, .tm_hour = hour, .tm_min = minute, .tm_sec = second} 22 23 #ifndef SOFT_RTC_TIME_DEFAULT 24 #define SOFT_RTC_TIME_DEFAULT RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0) 25 #endif 26 27 static struct rt_device soft_rtc_dev; 28 static rt_tick_t init_tick; 29 static time_t init_time; 30 31 static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args) 32 { 33 time_t *time; 34 struct tm time_temp; 35 36 RT_ASSERT(dev != RT_NULL); 37 memset(&time_temp, 0, sizeof(struct tm)); 38 39 switch (cmd) 40 { 41 case RT_DEVICE_CTRL_RTC_GET_TIME: 42 time = (time_t *) args; 43 *time = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; 44 break; 45 46 case RT_DEVICE_CTRL_RTC_SET_TIME: 47 { 48 time = (time_t *) args; 49 init_time = *time - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND; 50 break; 51 } 52 } 53 54 return RT_EOK; 55 } 56 57 #ifdef RT_USING_DEVICE_OPS 58 const static struct rt_device_ops soft_rtc_ops = 59 { 60 RT_NULL, 61 RT_NULL, 62 RT_NULL, 63 RT_NULL, 64 RT_NULL, 65 soft_rtc_control 66 }; 67 #endif 68 69 int rt_soft_rtc_init(void) 70 { 71 static rt_bool_t init_ok = RT_FALSE; 72 struct tm time_new = SOFT_RTC_TIME_DEFAULT; 73 74 if (init_ok) 75 { 76 return 0; 77 } 78 /* make sure only one 'rtc' device */ 79 RT_ASSERT(!rt_device_find("rtc")); 80 81 init_tick = rt_tick_get(); 82 init_time = mktime(&time_new); 83 84 soft_rtc_dev.type = RT_Device_Class_RTC; 85 86 /* register rtc device */ 87 #ifdef RT_USING_DEVICE_OPS 88 soft_rtc_dev.ops = &soft_rtc_ops; 89 #else 90 soft_rtc_dev.init = RT_NULL; 91 soft_rtc_dev.open = RT_NULL; 92 soft_rtc_dev.close = RT_NULL; 93 soft_rtc_dev.read = RT_NULL; 94 soft_rtc_dev.write = RT_NULL; 95 soft_rtc_dev.control = soft_rtc_control; 96 #endif 97 98 /* no private */ 99 soft_rtc_dev.user_data = RT_NULL; 100 101 rt_device_register(&soft_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR); 102 103 init_ok = RT_TRUE; 104 105 return 0; 106 } 107 INIT_DEVICE_EXPORT(rt_soft_rtc_init); 108 109 #endif /* RT_USING_SOFT_RTC */ 110