1
0

rtc.c 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. /*
  2. * Copyright (c) 2006-2021, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2012-01-29 aozima first version.
  9. * 2012-04-12 aozima optimization: find rtc device only first.
  10. * 2012-04-16 aozima add scheduler lock for set_date and set_time.
  11. * 2018-02-16 armink add auto sync time by NTP
  12. * 2021-05-09 Meco Man remove NTP
  13. * 2021-06-11 iysheng implement RTC framework V2.0
  14. * 2021-07-30 Meco Man move rtc_core.c to rtc.c
  15. */
  16. #include <time.h>
  17. #include <string.h>
  18. #include <stdlib.h>
  19. #include <rtthread.h>
  20. #include <drivers/rtc.h>
  21. #ifdef RT_USING_RTC
  22. /*
  23. * This function initializes rtc_core
  24. */
  25. static rt_err_t rt_rtc_init(struct rt_device *dev)
  26. {
  27. rt_rtc_dev_t *rtc_core;
  28. RT_ASSERT(dev != RT_NULL);
  29. rtc_core = (rt_rtc_dev_t *)dev;
  30. if (rtc_core->ops->init)
  31. {
  32. return (rtc_core->ops->init());
  33. }
  34. return -RT_ENOSYS;
  35. }
  36. static rt_err_t rt_rtc_open(struct rt_device *dev, rt_uint16_t oflag)
  37. {
  38. return RT_EOK;
  39. }
  40. static rt_err_t rt_rtc_close(struct rt_device *dev)
  41. {
  42. /* Add close member function in rt_rtc_ops when need,
  43. * then call that function here.
  44. * */
  45. return RT_EOK;
  46. }
  47. static rt_err_t rt_rtc_control(struct rt_device *dev, int cmd, void *args)
  48. {
  49. #define TRY_DO_RTC_FUNC(rt_rtc_dev, func_name, args) \
  50. rt_rtc_dev->ops->func_name ? rt_rtc_dev->ops->func_name(args) : -RT_EINVAL;
  51. rt_rtc_dev_t *rtc_device;
  52. rt_err_t ret = -RT_EINVAL;
  53. RT_ASSERT(dev != RT_NULL);
  54. rtc_device = (rt_rtc_dev_t *)dev;
  55. switch (cmd)
  56. {
  57. case RT_DEVICE_CTRL_RTC_GET_TIME:
  58. ret = TRY_DO_RTC_FUNC(rtc_device, get_secs, args);
  59. break;
  60. case RT_DEVICE_CTRL_RTC_SET_TIME:
  61. ret = TRY_DO_RTC_FUNC(rtc_device, set_secs, args);
  62. break;
  63. case RT_DEVICE_CTRL_RTC_GET_TIME_US:
  64. ret = TRY_DO_RTC_FUNC(rtc_device, get_usecs, args);
  65. break;
  66. case RT_DEVICE_CTRL_RTC_SET_TIME_US:
  67. ret = TRY_DO_RTC_FUNC(rtc_device, set_usecs, args);
  68. break;
  69. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  70. ret = TRY_DO_RTC_FUNC(rtc_device, get_alarm, args);
  71. break;
  72. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  73. ret = TRY_DO_RTC_FUNC(rtc_device, set_alarm, args);
  74. break;
  75. default:
  76. break;
  77. }
  78. return ret;
  79. #undef TRY_DO_RTC_FUNC
  80. }
  81. #ifdef RT_USING_DEVICE_OPS
  82. const static struct rt_device_ops rtc_core_ops =
  83. {
  84. rt_rtc_init,
  85. rt_rtc_open,
  86. rt_rtc_close,
  87. RT_NULL,
  88. RT_NULL,
  89. rt_rtc_control,
  90. };
  91. #endif /* RT_USING_DEVICE_OPS */
  92. rt_err_t rt_hw_rtc_register(rt_rtc_dev_t *rtc,
  93. const char *name,
  94. rt_uint32_t flag,
  95. void *data)
  96. {
  97. struct rt_device *device;
  98. RT_ASSERT(rtc != RT_NULL);
  99. device = &(rtc->parent);
  100. device->type = RT_Device_Class_RTC;
  101. device->rx_indicate = RT_NULL;
  102. device->tx_complete = RT_NULL;
  103. #ifdef RT_USING_DEVICE_OPS
  104. device->ops = &rtc_core_ops;
  105. #else
  106. device->init = rt_rtc_init;
  107. device->open = rt_rtc_open;
  108. device->close = rt_rtc_close;
  109. device->read = RT_NULL;
  110. device->write = RT_NULL;
  111. device->control = rt_rtc_control;
  112. #endif /* RT_USING_DEVICE_OPS */
  113. device->user_data = data;
  114. /* register a character device */
  115. return rt_device_register(device, name, flag);
  116. }
  117. /**
  118. * Set system date(time not modify, local timezone).
  119. *
  120. * @param rt_uint32_t year e.g: 2012.
  121. * @param rt_uint32_t month e.g: 12 (1~12).
  122. * @param rt_uint32_t day e.g: 31.
  123. *
  124. * @return rt_err_t if set success, return RT_EOK.
  125. */
  126. rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)
  127. {
  128. time_t now;
  129. struct tm tm_new;
  130. rt_device_t device;
  131. rt_err_t ret = -RT_ERROR;
  132. /* get current time */
  133. now = time(RT_NULL);
  134. /* converts calendar time into local time. */
  135. localtime_r(&now, &tm_new);
  136. /* update date. */
  137. tm_new.tm_year = year - 1900;
  138. tm_new.tm_mon = month - 1; /* tm_mon: 0~11 */
  139. tm_new.tm_mday = day;
  140. /* converts the local time into the calendar time. */
  141. now = mktime(&tm_new);
  142. device = rt_device_find("rtc");
  143. if (device == RT_NULL)
  144. {
  145. return -RT_ERROR;
  146. }
  147. /* update to RTC device. */
  148. ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
  149. return ret;
  150. }
  151. /**
  152. * Set system time(date not modify, local timezone).
  153. *
  154. * @param rt_uint32_t hour e.g: 0~23.
  155. * @param rt_uint32_t minute e.g: 0~59.
  156. * @param rt_uint32_t second e.g: 0~59.
  157. *
  158. * @return rt_err_t if set success, return RT_EOK.
  159. */
  160. rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
  161. {
  162. time_t now;
  163. struct tm tm_new;
  164. rt_device_t device;
  165. rt_err_t ret = -RT_ERROR;
  166. /* get current time */
  167. now = time(RT_NULL);
  168. /* converts calendar time into local time. */
  169. localtime_r(&now, &tm_new);
  170. /* update time. */
  171. tm_new.tm_hour = hour;
  172. tm_new.tm_min = minute;
  173. tm_new.tm_sec = second;
  174. /* converts the local time into the calendar time. */
  175. now = mktime(&tm_new);
  176. device = rt_device_find("rtc");
  177. if (device == RT_NULL)
  178. {
  179. return -RT_ERROR;
  180. }
  181. /* update to RTC device. */
  182. ret = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
  183. return ret;
  184. }
  185. #ifdef RT_USING_FINSH
  186. #include <finsh.h>
  187. /**
  188. * get date and time or set (local timezone) [year month day hour min sec]
  189. */
  190. static void date(uint8_t argc, char **argv)
  191. {
  192. if (argc == 1)
  193. {
  194. time_t now;
  195. /* output current time */
  196. now = time(RT_NULL);
  197. rt_kprintf("%.*s", 25, ctime(&now));
  198. }
  199. else if (argc >= 7)
  200. {
  201. /* set time and date */
  202. uint16_t year;
  203. uint8_t month, day, hour, min, sec;
  204. year = atoi(argv[1]);
  205. month = atoi(argv[2]);
  206. day = atoi(argv[3]);
  207. hour = atoi(argv[4]);
  208. min = atoi(argv[5]);
  209. sec = atoi(argv[6]);
  210. if (year > 2099 || year < 2000)
  211. {
  212. rt_kprintf("year is out of range [2000-2099]\n");
  213. return;
  214. }
  215. if (month == 0 || month > 12)
  216. {
  217. rt_kprintf("month is out of range [1-12]\n");
  218. return;
  219. }
  220. if (day == 0 || day > 31)
  221. {
  222. rt_kprintf("day is out of range [1-31]\n");
  223. return;
  224. }
  225. if (hour > 23)
  226. {
  227. rt_kprintf("hour is out of range [0-23]\n");
  228. return;
  229. }
  230. if (min > 59)
  231. {
  232. rt_kprintf("minute is out of range [0-59]\n");
  233. return;
  234. }
  235. if (sec > 59)
  236. {
  237. rt_kprintf("second is out of range [0-59]\n");
  238. return;
  239. }
  240. set_time(hour, min, sec);
  241. set_date(year, month, day);
  242. }
  243. else
  244. {
  245. rt_kprintf("please input: date [year month day hour min sec] or date\n");
  246. rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n");
  247. }
  248. }
  249. MSH_CMD_EXPORT(date, get date and time or set (local timezone) [year month day hour min sec])
  250. #endif /* RT_USING_FINSH */
  251. #endif /* RT_USING_RTC */