drv_rtc.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2020-06-08 hqfang first implementation.
  9. */
  10. #include "drv_rtc.h"
  11. #ifdef BSP_USING_RTC
  12. static time_t get_timestamp(void)
  13. {
  14. return (time_t)rtc_counter_get();
  15. }
  16. static int set_timestamp(time_t timestamp)
  17. {
  18. /* wait until last write operation on RTC registers has finished */
  19. rtc_lwoff_wait();
  20. /* change the current time */
  21. rtc_counter_set((uint32_t)timestamp);
  22. /* wait until last write operation on RTC registers has finished */
  23. rtc_lwoff_wait();
  24. return RT_EOK;
  25. }
  26. static void rtc_configuration(void)
  27. {
  28. /* enable PMU and BKPI clocks */
  29. rcu_periph_clock_enable(RCU_BKPI);
  30. rcu_periph_clock_enable(RCU_PMU);
  31. /* allow access to BKP domain */
  32. pmu_backup_write_enable();
  33. /* reset backup domain */
  34. bkp_deinit();
  35. /* enable LXTAL */
  36. rcu_osci_on(RCU_LXTAL);
  37. /* wait till LXTAL is ready */
  38. rcu_osci_stab_wait(RCU_LXTAL);
  39. /* select RCU_LXTAL as RTC clock source */
  40. rcu_rtc_clock_config(RCU_RTCSRC_LXTAL);
  41. /* enable RTC Clock */
  42. rcu_periph_clock_enable(RCU_RTC);
  43. /* wait for RTC registers synchronization */
  44. rtc_register_sync_wait();
  45. /* wait until last write operation on RTC registers has finished */
  46. rtc_lwoff_wait();
  47. /* wait until last write operation on RTC registers has finished */
  48. rtc_lwoff_wait();
  49. /* set RTC prescaler: set RTC period to 1s */
  50. rtc_prescaler_set(32767);
  51. /* wait until last write operation on RTC registers has finished */
  52. rtc_lwoff_wait();
  53. }
  54. static rt_err_t gd32_rtc_init(rt_device_t dev)
  55. {
  56. if (bkp_data_read(BKP_DATA_0) != 0xA5A5)
  57. {
  58. rtc_configuration();
  59. bkp_data_write(BKP_DATA_0, 0xA5A5);
  60. }
  61. else
  62. {
  63. /* allow access to BKP domain */
  64. rcu_periph_clock_enable(RCU_PMU);
  65. pmu_backup_write_enable();
  66. /* wait for RTC registers synchronization */
  67. rtc_register_sync_wait();
  68. /* wait until last write operation on RTC registers has finished */
  69. rtc_lwoff_wait();
  70. }
  71. return RT_EOK;
  72. }
  73. static rt_err_t gd32_rtc_open(rt_device_t dev, rt_uint16_t oflag)
  74. {
  75. return RT_EOK;
  76. }
  77. static rt_err_t gd32_rtc_close(rt_device_t dev)
  78. {
  79. return RT_EOK;
  80. }
  81. static rt_size_t gd32_rtc_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size)
  82. {
  83. return RT_EOK;
  84. }
  85. static rt_size_t gd32_rtc_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size)
  86. {
  87. return RT_EOK;
  88. }
  89. static rt_err_t gd32_rtc_control(rt_device_t dev, int cmd, void *args)
  90. {
  91. RT_ASSERT(dev != RT_NULL);
  92. switch (cmd)
  93. {
  94. case RT_DEVICE_CTRL_RTC_GET_TIME:
  95. {
  96. *(uint32_t *)args = get_timestamp();
  97. }
  98. break;
  99. case RT_DEVICE_CTRL_RTC_SET_TIME:
  100. {
  101. set_timestamp(*(time_t *)args);
  102. }
  103. break;
  104. default:
  105. return RT_EINVAL;
  106. }
  107. return RT_EOK;
  108. }
  109. static struct rt_device rtc_device =
  110. {
  111. .type = RT_Device_Class_RTC,
  112. .init = gd32_rtc_init,
  113. .open = gd32_rtc_open,
  114. .close = gd32_rtc_close,
  115. .read = gd32_rtc_read,
  116. .write = gd32_rtc_write,
  117. .control = gd32_rtc_control,
  118. };
  119. int rt_hw_rtc_init(void)
  120. {
  121. rt_err_t ret = RT_EOK;
  122. ret = rt_device_register(&rtc_device, "rtc", RT_DEVICE_FLAG_RDWR);
  123. rt_device_open(&rtc_device, RT_DEVICE_OFLAG_RDWR);
  124. return RT_EOK;
  125. }
  126. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  127. #endif /* BSP_USING_RTC */