添加rtthread相关代码
This commit is contained in:
		
							
								
								
									
										375
									
								
								riscv/rtthread/components/drivers/rtc/rtc.c
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										375
									
								
								riscv/rtthread/components/drivers/rtc/rtc.c
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,375 @@ | ||||
| /* | ||||
|  * Copyright (c) 2006-2023, RT-Thread Development Team | ||||
|  * | ||||
|  * SPDX-License-Identifier: Apache-2.0 | ||||
|  * | ||||
|  * Change Logs: | ||||
|  * Date           Author       Notes | ||||
|  * 2012-01-29     aozima       first version. | ||||
|  * 2012-04-12     aozima       optimization: find rtc device only first. | ||||
|  * 2012-04-16     aozima       add scheduler lock for set_date and set_time. | ||||
|  * 2018-02-16     armink       add auto sync time by NTP | ||||
|  * 2021-05-09     Meco Man     remove NTP | ||||
|  * 2021-06-11     iysheng      implement RTC framework V2.0 | ||||
|  * 2021-07-30     Meco Man     move rtc_core.c to rtc.c | ||||
|  */ | ||||
|  | ||||
| #include <string.h> | ||||
| #include <stdlib.h> | ||||
| #include <rtthread.h> | ||||
| #include <drivers/rtc.h> | ||||
|  | ||||
| #ifdef RT_USING_RTC | ||||
|  | ||||
| static rt_device_t _rtc_device; | ||||
| /* | ||||
|  * This function initializes rtc_core | ||||
|  */ | ||||
| static rt_err_t rt_rtc_init(struct rt_device *dev) | ||||
| { | ||||
|     rt_rtc_dev_t *rtc_core; | ||||
|  | ||||
|     RT_ASSERT(dev != RT_NULL); | ||||
|     rtc_core = (rt_rtc_dev_t *)dev; | ||||
|     if (rtc_core->ops->init) | ||||
|     { | ||||
|         return (rtc_core->ops->init()); | ||||
|     } | ||||
|  | ||||
|     return -RT_ENOSYS; | ||||
| } | ||||
|  | ||||
| static rt_err_t rt_rtc_open(struct rt_device *dev, rt_uint16_t oflag) | ||||
| { | ||||
|     return RT_EOK; | ||||
| } | ||||
|  | ||||
| static rt_err_t rt_rtc_close(struct rt_device *dev) | ||||
| { | ||||
|     /* Add close member function in rt_rtc_ops when need, | ||||
|      * then call that function here. | ||||
|      * */ | ||||
|     return RT_EOK; | ||||
| } | ||||
|  | ||||
| static rt_err_t rt_rtc_control(struct rt_device *dev, int cmd, void *args) | ||||
| { | ||||
| #define TRY_DO_RTC_FUNC(rt_rtc_dev, func_name, args) \ | ||||
|     rt_rtc_dev->ops->func_name ?  rt_rtc_dev->ops->func_name(args) : -RT_EINVAL; | ||||
|  | ||||
|     rt_rtc_dev_t *rtc_device; | ||||
|     rt_err_t ret = -RT_EINVAL; | ||||
|  | ||||
|     RT_ASSERT(dev != RT_NULL); | ||||
|     rtc_device = (rt_rtc_dev_t *)dev; | ||||
|  | ||||
|     switch (cmd) | ||||
|     { | ||||
|         case RT_DEVICE_CTRL_RTC_GET_TIME: | ||||
|             ret = TRY_DO_RTC_FUNC(rtc_device, get_secs, args); | ||||
|             break; | ||||
|         case RT_DEVICE_CTRL_RTC_SET_TIME: | ||||
|             ret = TRY_DO_RTC_FUNC(rtc_device, set_secs, args); | ||||
|             break; | ||||
|         case RT_DEVICE_CTRL_RTC_GET_TIMEVAL: | ||||
|             ret = TRY_DO_RTC_FUNC(rtc_device, get_timeval, args); | ||||
|             break; | ||||
|         case RT_DEVICE_CTRL_RTC_SET_TIMEVAL: | ||||
|             ret = TRY_DO_RTC_FUNC(rtc_device, set_timeval, args); | ||||
|             break; | ||||
|         case RT_DEVICE_CTRL_RTC_GET_ALARM: | ||||
|             ret = TRY_DO_RTC_FUNC(rtc_device, get_alarm, args); | ||||
|             break; | ||||
|         case RT_DEVICE_CTRL_RTC_SET_ALARM: | ||||
|             ret = TRY_DO_RTC_FUNC(rtc_device, set_alarm, args); | ||||
|             break; | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     return ret; | ||||
|  | ||||
| #undef TRY_DO_RTC_FUNC | ||||
| } | ||||
|  | ||||
| #ifdef RT_USING_DEVICE_OPS | ||||
| const static struct rt_device_ops rtc_core_ops = | ||||
| { | ||||
|     rt_rtc_init, | ||||
|     rt_rtc_open, | ||||
|     rt_rtc_close, | ||||
|     RT_NULL, | ||||
|     RT_NULL, | ||||
|     rt_rtc_control, | ||||
| }; | ||||
| #endif /* RT_USING_DEVICE_OPS */ | ||||
|  | ||||
| rt_err_t rt_hw_rtc_register(rt_rtc_dev_t  *rtc, | ||||
|                             const char    *name, | ||||
|                             rt_uint32_t    flag, | ||||
|                             void          *data) | ||||
| { | ||||
|     struct rt_device *device; | ||||
|     RT_ASSERT(rtc != RT_NULL); | ||||
|  | ||||
|     device = &(rtc->parent); | ||||
|  | ||||
|     device->type        = RT_Device_Class_RTC; | ||||
|     device->rx_indicate = RT_NULL; | ||||
|     device->tx_complete = RT_NULL; | ||||
|  | ||||
| #ifdef RT_USING_DEVICE_OPS | ||||
|     device->ops         = &rtc_core_ops; | ||||
| #else | ||||
|     device->init        = rt_rtc_init; | ||||
|     device->open        = rt_rtc_open; | ||||
|     device->close       = rt_rtc_close; | ||||
|     device->read        = RT_NULL; | ||||
|     device->write       = RT_NULL; | ||||
|     device->control     = rt_rtc_control; | ||||
| #endif /* RT_USING_DEVICE_OPS */ | ||||
|     device->user_data   = data; | ||||
|  | ||||
|     /* register a character device */ | ||||
|     return rt_device_register(device, name, flag); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set system date(time not modify, local timezone). | ||||
|  * | ||||
|  * @param rt_uint32_t year  e.g: 2012. | ||||
|  * @param rt_uint32_t month e.g: 12 (1~12). | ||||
|  * @param rt_uint32_t day   e.g: 31. | ||||
|  * | ||||
|  * @return rt_err_t if set success, return RT_EOK. | ||||
|  */ | ||||
| rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day) | ||||
| { | ||||
|     time_t now, old_timestamp = 0; | ||||
|     struct tm tm_new = {0}; | ||||
|     rt_err_t ret = -RT_ERROR; | ||||
|  | ||||
|     if (_rtc_device == RT_NULL) | ||||
|     { | ||||
|         _rtc_device = rt_device_find("rtc"); | ||||
|         if (_rtc_device == RT_NULL) | ||||
|         { | ||||
|             return -RT_ERROR; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* get current time */ | ||||
|     ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp); | ||||
|     if (ret != RT_EOK) | ||||
|     { | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     /* converts calendar time into local time. */ | ||||
|     localtime_r(&old_timestamp, &tm_new); | ||||
|  | ||||
|     /* update date. */ | ||||
|     tm_new.tm_year = year - 1900; | ||||
|     tm_new.tm_mon  = month - 1; /* tm_mon: 0~11 */ | ||||
|     tm_new.tm_mday = day; | ||||
|  | ||||
|     /* converts the local time into the calendar time. */ | ||||
|     now = mktime(&tm_new); | ||||
|  | ||||
|     /* update to RTC device. */ | ||||
|     ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set system time(date not modify, local timezone). | ||||
|  * | ||||
|  * @param rt_uint32_t hour   e.g: 0~23. | ||||
|  * @param rt_uint32_t minute e.g: 0~59. | ||||
|  * @param rt_uint32_t second e.g: 0~59. | ||||
|  * | ||||
|  * @return rt_err_t if set success, return RT_EOK. | ||||
|  */ | ||||
| rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second) | ||||
| { | ||||
|     time_t now, old_timestamp = 0; | ||||
|     struct tm tm_new = {0}; | ||||
|     rt_err_t ret = -RT_ERROR; | ||||
|  | ||||
|     if (_rtc_device == RT_NULL) | ||||
|     { | ||||
|         _rtc_device = rt_device_find("rtc"); | ||||
|         if (_rtc_device == RT_NULL) | ||||
|         { | ||||
|             return -RT_ERROR; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* get current time */ | ||||
|     ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp); | ||||
|     if (ret != RT_EOK) | ||||
|     { | ||||
|         return ret; | ||||
|     } | ||||
|  | ||||
|     /* converts calendar time into local time. */ | ||||
|     localtime_r(&old_timestamp, &tm_new); | ||||
|  | ||||
|     /* update time. */ | ||||
|     tm_new.tm_hour = hour; | ||||
|     tm_new.tm_min  = minute; | ||||
|     tm_new.tm_sec  = second; | ||||
|  | ||||
|     /* converts the local time into the calendar time. */ | ||||
|     now = mktime(&tm_new); | ||||
|  | ||||
|     /* update to RTC device. */ | ||||
|     ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now); | ||||
|     return ret; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Set timestamp(UTC). | ||||
|  * | ||||
|  * @param time_t timestamp | ||||
|  * | ||||
|  * @return rt_err_t if set success, return RT_EOK. | ||||
|  */ | ||||
| rt_err_t set_timestamp(time_t timestamp) | ||||
| { | ||||
|     if (_rtc_device == RT_NULL) | ||||
|     { | ||||
|         _rtc_device = rt_device_find("rtc"); | ||||
|         if (_rtc_device == RT_NULL) | ||||
|         { | ||||
|             return -RT_ERROR; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* update to RTC device. */ | ||||
|     return rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, ×tamp); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get timestamp(UTC). | ||||
|  * | ||||
|  * @param time_t* timestamp | ||||
|  * | ||||
|  * @return rt_err_t if set success, return RT_EOK. | ||||
|  */ | ||||
| rt_err_t get_timestamp(time_t *timestamp) | ||||
| { | ||||
|     if (_rtc_device == RT_NULL) | ||||
|     { | ||||
|         _rtc_device = rt_device_find("rtc"); | ||||
|         if (_rtc_device == RT_NULL) | ||||
|         { | ||||
|             return -RT_ERROR; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* Get timestamp from RTC device. */ | ||||
|     return rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, timestamp); | ||||
| } | ||||
|  | ||||
| #ifdef RT_USING_FINSH | ||||
| #include <finsh.h> | ||||
| /** | ||||
|  * get date and time or set (local timezone) [year month day hour min sec] | ||||
|  */ | ||||
| static void date(int argc, char **argv) | ||||
| { | ||||
|     time_t now = (time_t)0; | ||||
|  | ||||
|     if (argc == 1) | ||||
|     { | ||||
|         struct timeval tv = { 0 }; | ||||
|         int32_t tz_offset_sec = 0; | ||||
|         uint32_t abs_tz_offset_sec = 0U; | ||||
|  | ||||
| #if defined(RT_LIBC_USING_LIGHT_TZ_DST) | ||||
|         tz_offset_sec = rt_tz_get(); | ||||
| #endif /* RT_LIBC_USING_LIGHT_TZ_DST */ | ||||
|  | ||||
|         gettimeofday(&tv, RT_NULL); | ||||
|         now = tv.tv_sec; | ||||
|  | ||||
|         abs_tz_offset_sec = tz_offset_sec > 0 ? tz_offset_sec : -tz_offset_sec; | ||||
|         /* output current time */ | ||||
|         rt_kprintf("local time: %.*s", 25U, ctime(&now)); | ||||
|         rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec); | ||||
|         rt_kprintf("timezone: UTC%c%02d:%02d:%02d\n", | ||||
|             tz_offset_sec > 0 ? '+' : '-', abs_tz_offset_sec / 3600U, abs_tz_offset_sec % 3600U / 60U, abs_tz_offset_sec % 3600U % 60U); | ||||
|     } | ||||
|     else if (argc >= 7) | ||||
|     { | ||||
|         /* set time and date */ | ||||
|         struct tm tm_new = {0}; | ||||
|         time_t old = (time_t)0; | ||||
|         rt_err_t err; | ||||
|  | ||||
|         tm_new.tm_year = atoi(argv[1]) - 1900; | ||||
|         tm_new.tm_mon = atoi(argv[2]) - 1; /* .tm_min's range is [0-11] */ | ||||
|         tm_new.tm_mday = atoi(argv[3]); | ||||
|         tm_new.tm_hour = atoi(argv[4]); | ||||
|         tm_new.tm_min = atoi(argv[5]); | ||||
|         tm_new.tm_sec = atoi(argv[6]); | ||||
|         if (tm_new.tm_year <= 0) | ||||
|         { | ||||
|             rt_kprintf("year is out of range [1900-]\n"); | ||||
|             return; | ||||
|         } | ||||
|         if (tm_new.tm_mon > 11) /* .tm_min's range is [0-11] */ | ||||
|         { | ||||
|             rt_kprintf("month is out of range [1-12]\n"); | ||||
|             return; | ||||
|         } | ||||
|         if (tm_new.tm_mday == 0 || tm_new.tm_mday > 31) | ||||
|         { | ||||
|             rt_kprintf("day is out of range [1-31]\n"); | ||||
|             return; | ||||
|         } | ||||
|         if (tm_new.tm_hour > 23) | ||||
|         { | ||||
|             rt_kprintf("hour is out of range [0-23]\n"); | ||||
|             return; | ||||
|         } | ||||
|         if (tm_new.tm_min > 59) | ||||
|         { | ||||
|             rt_kprintf("minute is out of range [0-59]\n"); | ||||
|             return; | ||||
|         } | ||||
|         if (tm_new.tm_sec > 60) | ||||
|         { | ||||
|             rt_kprintf("second is out of range [0-60]\n"); | ||||
|             return; | ||||
|         } | ||||
|         /* save old timestamp */ | ||||
|         err = get_timestamp(&old); | ||||
|         if (err != RT_EOK) | ||||
|         { | ||||
|             rt_kprintf("Get current timestamp failed. %d\n", err); | ||||
|             return; | ||||
|         } | ||||
|         /* converts the local time into the calendar time. */ | ||||
|         now = mktime(&tm_new); | ||||
|         err = set_timestamp(now); | ||||
|         if (err != RT_EOK) | ||||
|         { | ||||
|             rt_kprintf("set date failed. %d\n", err); | ||||
|             return; | ||||
|         } | ||||
|         get_timestamp(&now); /* get new timestamp */ | ||||
|         rt_kprintf("old: %.*s", 25, ctime(&old)); | ||||
|         rt_kprintf("now: %.*s", 25, ctime(&now)); | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         rt_kprintf("please input: date [year month day hour min sec] or date\n"); | ||||
|         rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n"); | ||||
|     } | ||||
| } | ||||
| MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec]) | ||||
| #endif /* RT_USING_FINSH */ | ||||
|  | ||||
| #endif /* RT_USING_RTC */ | ||||
		Reference in New Issue
	
	Block a user