drv_rtc.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  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. * 2022-05-16 shelton first version
  9. * 2023-04-08 shelton add support f423
  10. */
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <sys/time.h>
  14. #include "drv_common.h"
  15. #ifdef BSP_USING_RTC
  16. //#define DRV_DEBUG
  17. #define LOG_TAG "drv.rtc"
  18. #include <drv_log.h>
  19. #define BKUP_REG_DATA 0xA5A5
  20. static time_t get_rtc_timestamp(void)
  21. {
  22. #if defined (SOC_SERIES_AT32F435) || defined (SOC_SERIES_AT32F437) || \
  23. defined (SOC_SERIES_AT32F415) || defined (SOC_SERIES_AT32F421) || \
  24. defined (SOC_SERIES_AT32F425) || defined (SOC_SERIES_AT32F423)
  25. struct tm tm_new;
  26. ertc_time_type ertc_time_struct;
  27. ertc_calendar_get(&ertc_time_struct);
  28. tm_new.tm_sec = ertc_time_struct.sec;
  29. tm_new.tm_min = ertc_time_struct.min;
  30. tm_new.tm_hour = ertc_time_struct.hour;
  31. tm_new.tm_mday = ertc_time_struct.day;
  32. tm_new.tm_mon = ertc_time_struct.month - 1;
  33. tm_new.tm_year = ertc_time_struct.year + 100;
  34. LOG_D("get rtc time.");
  35. return timegm(&tm_new);
  36. #else
  37. return rtc_counter_get();
  38. #endif
  39. }
  40. static rt_err_t set_rtc_time_stamp(time_t time_stamp)
  41. {
  42. #if defined (SOC_SERIES_AT32F435) || defined (SOC_SERIES_AT32F437) || \
  43. defined (SOC_SERIES_AT32F415) || defined (SOC_SERIES_AT32F421) || \
  44. defined (SOC_SERIES_AT32F425) || defined (SOC_SERIES_AT32F423)
  45. struct tm now;
  46. gmtime_r(&time_stamp, &now);
  47. if (now.tm_year < 100)
  48. {
  49. return -RT_ERROR;
  50. }
  51. /* set time */
  52. if(ertc_time_set(now.tm_hour, now.tm_min, now.tm_sec, ERTC_AM) != SUCCESS)
  53. {
  54. return -RT_ERROR;
  55. }
  56. /* set date */
  57. if(ertc_date_set(now.tm_year - 100, now.tm_mon + 1, now.tm_mday, now.tm_wday + 1) != SUCCESS)
  58. {
  59. return -RT_ERROR;
  60. }
  61. LOG_D("set rtc time.");
  62. /* indicator for the ertc configuration */
  63. ertc_bpr_data_write(ERTC_DT1, BKUP_REG_DATA);
  64. #else
  65. /* set the rtc counter value */
  66. rtc_counter_set(time_stamp);
  67. /* wait until last write operation on rtc registers has finished */
  68. rtc_wait_config_finish();
  69. LOG_D("set rtc time.");
  70. bpr_data_write(BPR_DATA1, BKUP_REG_DATA);
  71. #endif
  72. return RT_EOK;
  73. }
  74. static rt_err_t rt_rtc_config(void)
  75. {
  76. /* allow access to pattery powered domain */
  77. pwc_battery_powered_domain_access(TRUE);
  78. #if defined (SOC_SERIES_AT32F435) || defined (SOC_SERIES_AT32F437) || \
  79. defined (SOC_SERIES_AT32F415) || defined (SOC_SERIES_AT32F421) || \
  80. defined (SOC_SERIES_AT32F425) || defined (SOC_SERIES_AT32F423)
  81. /* select rtc clock source */
  82. #ifdef BSP_RTC_USING_LICK
  83. crm_ertc_clock_select(CRM_ERTC_CLOCK_LICK);
  84. #else
  85. crm_ertc_clock_select(CRM_ERTC_CLOCK_LEXT);
  86. #endif /* BSP_RTC_USING_LICK */
  87. /* enable rtc */
  88. crm_ertc_clock_enable(TRUE);
  89. /* wait for ertc registers update */
  90. ertc_wait_update();
  91. if (ertc_bpr_data_read(ERTC_DT1)!= BKUP_REG_DATA)
  92. {
  93. LOG_I("RTC hasn't been configured, please use <date> command to config.");
  94. /* configure the ertc divider */
  95. ertc_divider_set(0x7F, 0xFF);
  96. /* configure the ertc hour mode */
  97. ertc_hour_mode_set(ERTC_HOUR_MODE_24);
  98. }
  99. #else
  100. #ifdef BSP_RTC_USING_LICK
  101. crm_rtc_clock_select(CRM_RTC_CLOCK_LICK);
  102. #else
  103. crm_rtc_clock_select(CRM_RTC_CLOCK_LEXT);
  104. #endif /* BSP_RTC_USING_LICK */
  105. /* enable rtc */
  106. crm_rtc_clock_enable(TRUE);
  107. /* wait for rtc registers update finish */
  108. rtc_wait_update_finish();
  109. /* wait until last write operation on rtc registers has finished */
  110. rtc_wait_config_finish();
  111. if (bpr_data_read(BPR_DATA1) != BKUP_REG_DATA)
  112. {
  113. LOG_I("RTC hasn't been configured, please use <date> command to config.");
  114. /* set rtc divider: set rtc period to 1sec */
  115. rtc_divider_set(32767);
  116. /* wait until last write operation on rtc registers has finished */
  117. rtc_wait_config_finish();
  118. }
  119. #endif
  120. return RT_EOK;
  121. }
  122. static rt_err_t _rtc_init(void)
  123. {
  124. crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
  125. #if defined (SOC_SERIES_AT32F403A) || defined (SOC_SERIES_AT32F407) || \
  126. defined (SOC_SERIES_AT32F413)
  127. crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
  128. #endif
  129. #ifdef BSP_RTC_USING_LICK
  130. crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);
  131. while(crm_flag_get(CRM_LICK_STABLE_FLAG) == RESET);
  132. #else
  133. pwc_battery_powered_domain_access(TRUE);
  134. crm_clock_source_enable(CRM_CLOCK_SOURCE_LEXT, TRUE);
  135. while(crm_flag_get(CRM_LEXT_STABLE_FLAG) == RESET);
  136. #endif /* BSP_RTC_USING_LICK */
  137. if (rt_rtc_config() != RT_EOK)
  138. {
  139. LOG_E("rtc init failed.");
  140. return -RT_ERROR;
  141. }
  142. return RT_EOK;
  143. }
  144. static rt_err_t _rtc_get_secs(time_t *args)
  145. {
  146. *(rt_uint32_t *)args = get_rtc_timestamp();
  147. LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)args);
  148. return RT_EOK;
  149. }
  150. static rt_err_t _rtc_set_secs(time_t *args)
  151. {
  152. rt_err_t result = RT_EOK;
  153. if (set_rtc_time_stamp(*(rt_uint32_t *)args))
  154. {
  155. result = -RT_ERROR;
  156. }
  157. LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args);
  158. return result;
  159. }
  160. static const struct rt_rtc_ops _rtc_ops =
  161. {
  162. _rtc_init,
  163. _rtc_get_secs,
  164. _rtc_set_secs,
  165. RT_NULL,
  166. RT_NULL,
  167. RT_NULL,
  168. RT_NULL,
  169. };
  170. static rt_rtc_dev_t at32_rtc_dev;
  171. int rt_hw_rtc_init(void)
  172. {
  173. rt_err_t result;
  174. at32_rtc_dev.ops = &_rtc_ops;
  175. result = rt_hw_rtc_register(&at32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR,RT_NULL);
  176. if (result != RT_EOK)
  177. {
  178. LOG_E("rtc register err code: %d", result);
  179. return result;
  180. }
  181. LOG_D("rtc init success");
  182. return RT_EOK;
  183. }
  184. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  185. #endif /* BSP_USING_RTC */