drv_rtc.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Copyright (c) 2006-2023, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2021-08-10 charlown first version
  9. * 2022-09-22 hg0720 the first version which add from wch
  10. */
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <sys/time.h>
  14. #include "board.h"
  15. #ifdef BSP_USING_RTC
  16. #define LOG_TAG "drv.rtc"
  17. #include "drv_log.h"
  18. #ifndef BKP_DR1
  19. #define BKP_DR1 RT_NULL
  20. #endif
  21. #define BKUP_REG_DATA 0xA1A1
  22. static struct rt_rtc_device rtc;
  23. static void rt_rtc_config(void)
  24. {
  25. /* Allow access to BKP Domain */
  26. PWR_BackupAccessCmd(ENABLE);
  27. #if defined(BSP_USING_RTC_LSI) && defined(LSI_VALUE)
  28. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  29. #else /* BSP_USING_RTC_LSE */
  30. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  31. #endif
  32. RCC_RTCCLKCmd(ENABLE);
  33. RTC_WaitForLastTask();
  34. RTC_WaitForSynchro();
  35. if (BKP_ReadBackupRegister(BKP_DR1) != BKUP_REG_DATA)
  36. {
  37. LOG_I("RTC hasn't been configured, please use <date> command to config.");
  38. /* Set RTC prescaler: set RTC period to 1sec */
  39. RTC_SetPrescaler(32767);
  40. /* Wait until last write operation on RTC registers has finished */
  41. RTC_WaitForLastTask();
  42. }
  43. }
  44. static rt_err_t ch32_rtc_init(void)
  45. {
  46. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
  47. PWR_BackupAccessCmd(ENABLE);
  48. #if defined(BSP_USING_RTC_LSI) && defined(LSI_VALUE)
  49. RCC_LSICmd(ENABLE);
  50. while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
  51. #else /* BSP_USING_RTC_LSE */
  52. RCC_LSEConfig(RCC_LSE_ON);
  53. while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
  54. #endif
  55. rt_rtc_config();
  56. return RT_EOK;
  57. }
  58. static rt_err_t ch32_get_secs(time_t *sec)
  59. {
  60. *(rt_uint32_t *)sec = RTC_GetCounter();
  61. LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)sec);
  62. return RT_EOK;
  63. }
  64. static rt_err_t ch32_set_secs(time_t *sec)
  65. {
  66. /* Set the RTC counter value */
  67. RTC_SetCounter(*(rt_uint32_t *)sec);
  68. /* Wait until last write operation on RTC registers has finished */
  69. RTC_WaitForLastTask();
  70. LOG_D("set rtc time.");
  71. BKP_WriteBackupRegister(BKP_DR1, BKUP_REG_DATA);
  72. LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)sec);
  73. return RT_EOK;
  74. }
  75. const static struct rt_rtc_ops rtc_ops =
  76. {
  77. ch32_rtc_init,
  78. ch32_get_secs,
  79. ch32_set_secs,
  80. RT_NULL,
  81. RT_NULL,
  82. RT_NULL,
  83. RT_NULL
  84. };
  85. int rt_hw_rtc_init(void)
  86. {
  87. rt_err_t result;
  88. rtc.ops = &rtc_ops;
  89. result = rt_hw_rtc_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
  90. if (result != RT_EOK)
  91. {
  92. LOG_E("rtc register err code: %d", result);
  93. return result;
  94. }
  95. LOG_D("rtc init success");
  96. return RT_EOK;
  97. }
  98. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  99. #endif /* BSP_USING_RTC */