drv_rtc.c 3.2 KB

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