drv_rtc.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. * 2021-04-13 armink the first version
  9. */
  10. #include <sys/time.h>
  11. #include <string.h>
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #ifdef RT_USING_RTC
  15. static struct rt_device rtc_dev;
  16. #ifdef RT_USING_ALARM
  17. static struct rt_rtc_wkalarm wkalarm;
  18. static struct rt_timer alarm_time;
  19. static void alarm_timeout(void *param)
  20. {
  21. rt_alarm_update(param, 1);
  22. }
  23. static void soft_rtc_alarm_update(struct rt_rtc_wkalarm *palarm)
  24. {
  25. rt_tick_t next_tick;
  26. if (palarm->enable)
  27. {
  28. next_tick = RT_TICK_PER_SECOND;
  29. rt_timer_control(&alarm_time, RT_TIMER_CTRL_SET_TIME, &next_tick);
  30. rt_timer_start(&alarm_time);
  31. }
  32. else
  33. {
  34. rt_timer_stop(&alarm_time);
  35. }
  36. }
  37. #endif
  38. static void get_rtc_timeval(struct timeval *tv)
  39. {
  40. struct tm newtime = { 0 };
  41. SYSTEMTIME sys_time;
  42. GetSystemTime(&sys_time);
  43. newtime.tm_year = sys_time.wYear - 1900;
  44. newtime.tm_mon = sys_time.wMonth - 1;
  45. newtime.tm_mday = sys_time.wDay;
  46. newtime.tm_hour = sys_time.wHour;
  47. newtime.tm_min = sys_time.wMinute;
  48. newtime.tm_sec = sys_time.wSecond;
  49. tv->tv_sec = timegm(&newtime);
  50. tv->tv_usec = sys_time.wMilliseconds * 1000UL;
  51. }
  52. static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
  53. {
  54. __time32_t *t;
  55. struct tm newtime;
  56. RT_ASSERT(dev != RT_NULL);
  57. switch (cmd)
  58. {
  59. case RT_DEVICE_CTRL_RTC_GET_TIME:
  60. {
  61. struct timeval tv;
  62. get_rtc_timeval(&tv);
  63. *(rt_uint32_t *) args = tv.tv_sec;
  64. break;
  65. }
  66. case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
  67. {
  68. get_rtc_timeval((struct timeval *) args);
  69. break;
  70. }
  71. case RT_DEVICE_CTRL_RTC_SET_TIME:
  72. {
  73. #ifdef RT_USING_ALARM
  74. soft_rtc_alarm_update(&wkalarm);
  75. #endif
  76. break;
  77. }
  78. #ifdef RT_USING_ALARM
  79. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  80. *((struct rt_rtc_wkalarm *)args) = wkalarm;
  81. break;
  82. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  83. wkalarm = *((struct rt_rtc_wkalarm *)args);
  84. soft_rtc_alarm_update(&wkalarm);
  85. break;
  86. #endif
  87. default:
  88. return -RT_ERROR;
  89. }
  90. return RT_EOK;
  91. }
  92. #ifdef RT_USING_DEVICE_OPS
  93. const static struct rt_device_ops soft_rtc_ops =
  94. {
  95. RT_NULL,
  96. RT_NULL,
  97. RT_NULL,
  98. RT_NULL,
  99. RT_NULL,
  100. soft_rtc_control
  101. };
  102. #endif
  103. int rt_win_rtc_init(void)
  104. {
  105. static rt_bool_t init_ok = RT_FALSE;
  106. if (init_ok)
  107. {
  108. return 0;
  109. }
  110. /* make sure only one 'rtc' device */
  111. RT_ASSERT(!rt_device_find("rtc"));
  112. #ifdef RT_USING_ALARM
  113. rt_timer_init(&alarm_time,
  114. "alarm",
  115. alarm_timeout,
  116. &rtc_dev,
  117. 0,
  118. RT_TIMER_FLAG_SOFT_TIMER | RT_TIMER_FLAG_ONE_SHOT);
  119. #endif
  120. rtc_dev.type = RT_Device_Class_RTC;
  121. /* register rtc device */
  122. #ifdef RT_USING_DEVICE_OPS
  123. rtc_dev.ops = &soft_rtc_ops;
  124. #else
  125. rtc_dev.init = RT_NULL;
  126. rtc_dev.open = RT_NULL;
  127. rtc_dev.close = RT_NULL;
  128. rtc_dev.read = RT_NULL;
  129. rtc_dev.write = RT_NULL;
  130. rtc_dev.control = soft_rtc_control;
  131. #endif
  132. /* no private */
  133. rtc_dev.user_data = RT_NULL;
  134. rt_device_register(&rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR);
  135. init_ok = RT_TRUE;
  136. return 0;
  137. }
  138. INIT_BOARD_EXPORT(rt_win_rtc_init);
  139. #endif /* RT_USING_RTC */