dev_rtc.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368
  1. /**
  2. * RT-Thread RuiChing
  3. *
  4. * COPYRIGHT (C) 2024-2025 Shanghai Real-Thread Electronic Technology Co., Ltd.
  5. * All rights reserved.
  6. *
  7. * The license and distribution terms for this file may be
  8. * found in the file LICENSE in this distribution.
  9. */
  10. #include <rtthread.h>
  11. #include <drivers/dev_rtc.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. static rt_device_t _rtc_device;
  15. /*
  16. * This function initializes rtc_core
  17. */
  18. static rt_err_t rt_rtc_init(struct rt_device *dev)
  19. {
  20. rt_rtc_dev_t *rtc_core;
  21. RT_ASSERT(dev != RT_NULL);
  22. rtc_core = (rt_rtc_dev_t *)dev;
  23. if (rtc_core->ops->init)
  24. {
  25. return (rtc_core->ops->init());
  26. }
  27. return -RT_ENOSYS;
  28. }
  29. static rt_err_t rt_rtc_open(struct rt_device *dev, rt_uint16_t oflag)
  30. {
  31. return RT_EOK;
  32. }
  33. static rt_err_t rt_rtc_close(struct rt_device *dev)
  34. {
  35. /* Add close member function in rt_rtc_ops when need,
  36. * then call that function here.
  37. * */
  38. return RT_EOK;
  39. }
  40. static rt_err_t rt_rtc_control(struct rt_device *dev, int cmd, void *args)
  41. {
  42. #define TRY_DO_RTC_FUNC(rt_rtc_dev, func_name, args) \
  43. rt_rtc_dev->ops->func_name ? rt_rtc_dev->ops->func_name(args) : -RT_EINVAL;
  44. rt_rtc_dev_t *rtc_device;
  45. rt_err_t ret = -RT_EINVAL;
  46. RT_ASSERT(dev != RT_NULL);
  47. rtc_device = (rt_rtc_dev_t *)dev;
  48. switch (cmd)
  49. {
  50. case RT_DEVICE_CTRL_RTC_GET_TIME:
  51. ret = TRY_DO_RTC_FUNC(rtc_device, get_secs, args);
  52. break;
  53. case RT_DEVICE_CTRL_RTC_SET_TIME:
  54. ret = TRY_DO_RTC_FUNC(rtc_device, set_secs, args);
  55. break;
  56. case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
  57. ret = TRY_DO_RTC_FUNC(rtc_device, get_timeval, args);
  58. break;
  59. case RT_DEVICE_CTRL_RTC_SET_TIMEVAL:
  60. ret = TRY_DO_RTC_FUNC(rtc_device, set_timeval, args);
  61. break;
  62. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  63. ret = TRY_DO_RTC_FUNC(rtc_device, get_alarm, args);
  64. break;
  65. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  66. ret = TRY_DO_RTC_FUNC(rtc_device, set_alarm, args);
  67. break;
  68. default: break;
  69. }
  70. return ret;
  71. #undef TRY_DO_RTC_FUNC
  72. }
  73. #ifdef RT_USING_DEVICE_OPS
  74. const static struct rt_device_ops rtc_core_ops =
  75. {
  76. rt_rtc_init,
  77. rt_rtc_open,
  78. rt_rtc_close,
  79. RT_NULL,
  80. RT_NULL,
  81. rt_rtc_control,
  82. };
  83. #endif /* RT_USING_DEVICE_OPS */
  84. rt_err_t rt_hw_rtc_register(
  85. rt_rtc_dev_t *rtc, const char *name, rt_uint32_t flag, void *data)
  86. {
  87. struct rt_device *device;
  88. RT_ASSERT(rtc != RT_NULL);
  89. device = &(rtc->parent);
  90. device->type = RT_Device_Class_RTC;
  91. device->rx_indicate = RT_NULL;
  92. device->tx_complete = RT_NULL;
  93. #ifdef RT_USING_DEVICE_OPS
  94. device->ops = &rtc_core_ops;
  95. #else
  96. device->init = rt_rtc_init;
  97. device->open = rt_rtc_open;
  98. device->close = rt_rtc_close;
  99. device->read = RT_NULL;
  100. device->write = RT_NULL;
  101. device->control = rt_rtc_control;
  102. #endif /* RT_USING_DEVICE_OPS */
  103. device->user_data = data;
  104. /* register a character device */
  105. return rt_device_register(device, name, flag);
  106. }
  107. /**
  108. * Set system date(time not modify, local timezone).
  109. *
  110. * @param rt_uint32_t year e.g: 2012.
  111. * @param rt_uint32_t month e.g: 12 (1~12).
  112. * @param rt_uint32_t day e.g: 31.
  113. *
  114. * @return rt_err_t if set success, return RT_EOK.
  115. */
  116. rt_err_t set_date(rt_uint32_t year, rt_uint32_t month, rt_uint32_t day)
  117. {
  118. time_t now, old_timestamp = 0;
  119. struct tm tm_new = { 0 };
  120. rt_err_t ret = -RT_ERROR;
  121. if (_rtc_device == RT_NULL)
  122. {
  123. _rtc_device = rt_device_find("rtc");
  124. if (_rtc_device == RT_NULL)
  125. {
  126. return -RT_ERROR;
  127. }
  128. }
  129. /* get current time */
  130. ret = rt_device_control(
  131. _rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp);
  132. if (ret != RT_EOK)
  133. {
  134. return ret;
  135. }
  136. /* converts calendar time into local time. */
  137. localtime_r(&old_timestamp, &tm_new);
  138. /* update date. */
  139. tm_new.tm_year = year - 1900;
  140. tm_new.tm_mon = month - 1; /* tm_mon: 0~11 */
  141. tm_new.tm_mday = day;
  142. /* converts the local time into the calendar time. */
  143. now = mktime(&tm_new);
  144. /* update to RTC device. */
  145. ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
  146. return ret;
  147. }
  148. /**
  149. * Set system time(date not modify, local timezone).
  150. *
  151. * @param rt_uint32_t hour e.g: 0~23.
  152. * @param rt_uint32_t minute e.g: 0~59.
  153. * @param rt_uint32_t second e.g: 0~59.
  154. *
  155. * @return rt_err_t if set success, return RT_EOK.
  156. */
  157. rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second)
  158. {
  159. time_t now, old_timestamp = 0;
  160. struct tm tm_new = { 0 };
  161. rt_err_t ret = -RT_ERROR;
  162. if (_rtc_device == RT_NULL)
  163. {
  164. _rtc_device = rt_device_find("rtc");
  165. if (_rtc_device == RT_NULL)
  166. {
  167. return -RT_ERROR;
  168. }
  169. }
  170. /* get current time */
  171. ret = rt_device_control(
  172. _rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, &old_timestamp);
  173. if (ret != RT_EOK)
  174. {
  175. return ret;
  176. }
  177. /* converts calendar time into local time. */
  178. localtime_r(&old_timestamp, &tm_new);
  179. /* update time. */
  180. tm_new.tm_hour = hour;
  181. tm_new.tm_min = minute;
  182. tm_new.tm_sec = second;
  183. /* converts the local time into the calendar time. */
  184. now = mktime(&tm_new);
  185. /* update to RTC device. */
  186. ret = rt_device_control(_rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &now);
  187. return ret;
  188. }
  189. /**
  190. * Set timestamp(UTC).
  191. *
  192. * @param time_t timestamp
  193. *
  194. * @return rt_err_t if set success, return RT_EOK.
  195. */
  196. rt_err_t set_timestamp(time_t timestamp)
  197. {
  198. if (_rtc_device == RT_NULL)
  199. {
  200. _rtc_device = rt_device_find("rtc");
  201. if (_rtc_device == RT_NULL)
  202. {
  203. return -RT_ERROR;
  204. }
  205. }
  206. /* update to RTC device. */
  207. return rt_device_control(
  208. _rtc_device, RT_DEVICE_CTRL_RTC_SET_TIME, &timestamp);
  209. }
  210. /**
  211. * Get timestamp(UTC).
  212. *
  213. * @param time_t* timestamp
  214. *
  215. * @return rt_err_t if set success, return RT_EOK.
  216. */
  217. rt_err_t get_timestamp(time_t *timestamp)
  218. {
  219. if (_rtc_device == RT_NULL)
  220. {
  221. _rtc_device = rt_device_find("rtc");
  222. if (_rtc_device == RT_NULL)
  223. {
  224. return -RT_ERROR;
  225. }
  226. }
  227. /* Get timestamp from RTC device. */
  228. return rt_device_control(
  229. _rtc_device, RT_DEVICE_CTRL_RTC_GET_TIME, timestamp);
  230. }
  231. #ifdef RT_USING_FINSH
  232. #include <finsh.h>
  233. /**
  234. * get date and time or set (local timezone) [year month day hour min sec]
  235. */
  236. static void date(int argc, char **argv)
  237. {
  238. time_t now = (time_t)0;
  239. if (argc == 1)
  240. {
  241. struct timeval tv = { 0 };
  242. int32_t tz_offset_sec = 0;
  243. uint32_t abs_tz_offset_sec = 0U;
  244. #if defined(RT_LIBC_USING_LIGHT_TZ_DST)
  245. tz_offset_sec = rt_tz_get();
  246. #endif /* RT_LIBC_USING_LIGHT_TZ_DST */
  247. gettimeofday(&tv, RT_NULL);
  248. now = tv.tv_sec;
  249. abs_tz_offset_sec = tz_offset_sec > 0 ? tz_offset_sec : -tz_offset_sec;
  250. /* output current time */
  251. rt_kprintf("local time: %.*s", 25U, ctime(&now));
  252. rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec);
  253. rt_kprintf("timezone: UTC%c%02d:%02d:%02d\n",
  254. tz_offset_sec > 0 ? '+' : '-', abs_tz_offset_sec / 3600U,
  255. abs_tz_offset_sec % 3600U / 60U, abs_tz_offset_sec % 3600U % 60U);
  256. }
  257. else if (argc >= 7)
  258. {
  259. /* set time and date */
  260. struct tm tm_new = { 0 };
  261. time_t old = (time_t)0;
  262. rt_err_t err;
  263. tm_new.tm_year = atoi(argv[1]) - 1900;
  264. tm_new.tm_mon = atoi(argv[2]) - 1; /* .tm_min's range is [0-11] */
  265. tm_new.tm_mday = atoi(argv[3]);
  266. tm_new.tm_hour = atoi(argv[4]);
  267. tm_new.tm_min = atoi(argv[5]);
  268. tm_new.tm_sec = atoi(argv[6]);
  269. if (tm_new.tm_year <= 0)
  270. {
  271. rt_kprintf("year is out of range [1900-]\n");
  272. return;
  273. }
  274. if (tm_new.tm_mon > 11) /* .tm_min's range is [0-11] */
  275. {
  276. rt_kprintf("month is out of range [1-12]\n");
  277. return;
  278. }
  279. if (tm_new.tm_mday == 0 || tm_new.tm_mday > 31)
  280. {
  281. rt_kprintf("day is out of range [1-31]\n");
  282. return;
  283. }
  284. if (tm_new.tm_hour > 23)
  285. {
  286. rt_kprintf("hour is out of range [0-23]\n");
  287. return;
  288. }
  289. if (tm_new.tm_min > 59)
  290. {
  291. rt_kprintf("minute is out of range [0-59]\n");
  292. return;
  293. }
  294. if (tm_new.tm_sec > 60)
  295. {
  296. rt_kprintf("second is out of range [0-60]\n");
  297. return;
  298. }
  299. /* save old timestamp */
  300. err = get_timestamp(&old);
  301. if (err != RT_EOK)
  302. {
  303. rt_kprintf("Get current timestamp failed. %d\n", err);
  304. return;
  305. }
  306. /* converts the local time into the calendar time. */
  307. now = mktime(&tm_new);
  308. err = set_timestamp(now);
  309. if (err != RT_EOK)
  310. {
  311. rt_kprintf("set date failed. %d\n", err);
  312. return;
  313. }
  314. get_timestamp(&now); /* get new timestamp */
  315. rt_kprintf("old: %.*s", 25, ctime(&old));
  316. rt_kprintf("now: %.*s", 25, ctime(&now));
  317. }
  318. else
  319. {
  320. rt_kprintf(
  321. "please input: date [year month day hour min sec] or date\n");
  322. rt_kprintf("e.g: date 2018 01 01 23 59 59 or date\n");
  323. }
  324. }
  325. MSH_CMD_EXPORT(
  326. date, get date and time or set(local timezone)[year month day hour min sec])
  327. #endif /* RT_USING_FINSH */