drv_rtc.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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. * 2020-05-19 shelton first version
  9. * 2021-08-125 Dozingfiretruck implement RTC framework V2.0
  10. */
  11. #include "board.h"
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #include <sys/time.h>
  15. #ifdef BSP_USING_RTC
  16. #ifndef BKP_DR1
  17. #define BKP_DR1 RT_NULL
  18. #endif
  19. //#define DRV_DEBUG
  20. #define LOG_TAG "drv.rtc"
  21. #include <drv_log.h>
  22. #define BKUP_REG_DATA 0xA5A5
  23. static time_t get_rtc_timestamp(void)
  24. {
  25. #ifdef SOC_SERIES_AT32F415
  26. struct tm tm_new;
  27. ERTC_TimeType ERTC_TimeStruct;
  28. ERTC_DateType ERTC_DateStruct;
  29. ERTC_GetTimeValue(ERTC_Format_BIN, &ERTC_TimeStruct);
  30. ERTC_GetDateValue(ERTC_Format_BIN, &ERTC_DateStruct);
  31. tm_new.tm_sec = ERTC_TimeStruct.ERTC_Seconds;
  32. tm_new.tm_min = ERTC_TimeStruct.ERTC_Minutes;
  33. tm_new.tm_hour = ERTC_TimeStruct.ERTC_Hours;
  34. tm_new.tm_mday = ERTC_DateStruct.ERTC_Date;
  35. tm_new.tm_mon = ERTC_DateStruct.ERTC_Month - 1;
  36. tm_new.tm_year = ERTC_DateStruct.ERTC_Year + 100;
  37. LOG_D("get rtc time.");
  38. return timegm(&tm_new);
  39. #else
  40. return RTC_GetCounter();
  41. #endif
  42. }
  43. static rt_err_t set_rtc_time_stamp(time_t time_stamp)
  44. {
  45. #ifdef SOC_SERIES_AT32F415
  46. ERTC_TimeType ERTC_TimeStructure;
  47. ERTC_DateType ERTC_DateStructure;
  48. struct tm *p_tm;
  49. p_tm = gmtime(&time_stamp);
  50. if (p_tm->tm_year < 100)
  51. {
  52. return -RT_ERROR;
  53. }
  54. ERTC_TimeStructure.ERTC_Seconds = p_tm->tm_sec ;
  55. ERTC_TimeStructure.ERTC_Minutes = p_tm->tm_min ;
  56. ERTC_TimeStructure.ERTC_Hours = p_tm->tm_hour;
  57. ERTC_DateStructure.ERTC_Date = p_tm->tm_mday;
  58. ERTC_DateStructure.ERTC_Month = p_tm->tm_mon + 1 ;
  59. ERTC_DateStructure.ERTC_Year = p_tm->tm_year - 100;
  60. ERTC_DateStructure.ERTC_WeekDay = p_tm->tm_wday + 1;
  61. if (ERTC_SetTimeValue(ERTC_Format_BIN, &ERTC_TimeStructure) != SUCCESS)
  62. {
  63. return -RT_ERROR;
  64. }
  65. if (ERTC_SetDateValue(ERTC_Format_BIN, &ERTC_DateStructure) != SUCCESS)
  66. {
  67. return -RT_ERROR;
  68. }
  69. #else
  70. /* Set the RTC counter value */
  71. RTC_SetCounter(time_stamp);
  72. /* Wait until last write operation on RTC registers has finished */
  73. RTC_WaitForLastTask();
  74. #endif /* SOC_SERIES_AT32F415 */
  75. LOG_D("set rtc time.");
  76. #ifdef SOC_SERIES_AT32F415
  77. ERTC_WriteBackupRegister(ERTC_BKP_DT0, BKUP_REG_DATA);
  78. #else
  79. BKP_WriteBackupReg(BKP_DT1, BKUP_REG_DATA);
  80. #endif
  81. return RT_EOK;
  82. }
  83. static rt_err_t rt_rtc_config(void)
  84. {
  85. #if defined (SOC_SERIES_AT32F415)
  86. ERTC_InitType ERTC_InitStructure;
  87. #endif
  88. /* Allow access to BKP Domain */
  89. PWR_BackupAccessCtrl(ENABLE);
  90. #ifdef SOC_SERIES_AT32F415
  91. #ifdef BSP_RTC_USING_LSI
  92. RCC_ERTCCLKConfig(RCC_ERTCCLKSelection_LSI);
  93. RCC_ERTCCLKCmd(ENABLE);
  94. #else
  95. RCC_ERTCCLKConfig(RCC_ERTCCLKSelection_LSE);
  96. RCC_ERTCCLKCmd(ENABLE);
  97. #endif /* BSP_RTC_USING_LSI */
  98. /* Wait for ERTC APB registers synchronisation */
  99. ERTC_WaitForSynchro();
  100. #else
  101. #ifdef BSP_RTC_USING_LSI
  102. RCC_RTCCLKConfig(RCC_RTCCLKSelection_LSI);
  103. RCC_RTCCLKCmd(ENABLE);
  104. #else
  105. RCC_RTCCLKConfig(RCC_RTCCLKSelection_LSE);
  106. RCC_RTCCLKCmd(ENABLE);
  107. #endif /* BSP_RTC_USING_LSI */
  108. /* Wait for RTC registers synchronization */
  109. RTC_WaitForSynchro();
  110. /* Wait until last write operation on RTC registers has finished */
  111. RTC_WaitForLastTask();
  112. #endif /* SOC_SERIES_AT32F415 */
  113. #ifdef SOC_SERIES_AT32F415
  114. if (ERTC_ReadBackupRegister(BKP_DT1)!= BKUP_REG_DATA)
  115. #else
  116. if (BKP_ReadBackupReg(BKP_DT1) != BKUP_REG_DATA)
  117. #endif
  118. {
  119. LOG_I("RTC hasn't been configured, please use <date> command to config.");
  120. #ifdef SOC_SERIES_AT32F415
  121. /* Configure the ERTC data register and ERTC prescaler */
  122. ERTC_InitStructure.ERTC_AsynchPrediv = 0x7F;
  123. ERTC_InitStructure.ERTC_SynchPrediv = 0xFF;
  124. ERTC_InitStructure.ERTC_HourFormat = ERTC_HourFormat_24;
  125. ERTC_Init(&ERTC_InitStructure);
  126. #else
  127. /* Set RTC prescaler: set RTC period to 1sec */
  128. RTC_SetDIV(32767);
  129. /* Wait until last write operation on RTC registers has finished */
  130. RTC_WaitForLastTask();
  131. #endif
  132. }
  133. return RT_EOK;
  134. }
  135. static rt_err_t _rtc_init(void)
  136. {
  137. #if defined (SOC_SERIES_AT32F415)
  138. RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR, ENABLE);
  139. #else
  140. RCC_APB1PeriphClockCmd(RCC_APB1PERIPH_PWR | RCC_APB1PERIPH_BKP, ENABLE);
  141. #endif
  142. #ifdef BSP_RTC_USING_LSI
  143. RCC_LSICmd(ENABLE);
  144. while(RCC_GetFlagStatus(RCC_FLAG_LSISTBL) == RESET);
  145. #else
  146. PWR_BackupAccessCtrl(ENABLE);
  147. RCC_LSEConfig(RCC_LSE_ENABLE);
  148. while(RCC_GetFlagStatus(RCC_FLAG_LSESTBL) == RESET);
  149. #endif /* BSP_RTC_USING_LSI */
  150. if (rt_rtc_config() != RT_EOK)
  151. {
  152. LOG_E("rtc init failed.");
  153. return -RT_ERROR;
  154. }
  155. return RT_EOK;
  156. }
  157. static rt_err_t _rtc_get_secs(void *args)
  158. {
  159. *(rt_uint32_t *)args = get_rtc_timestamp();
  160. LOG_D("RTC: get rtc_time %x\n", *(rt_uint32_t *)args);
  161. return RT_EOK;
  162. }
  163. static rt_err_t _rtc_set_secs(void *args)
  164. {
  165. rt_err_t result = RT_EOK;
  166. if (set_rtc_time_stamp(*(rt_uint32_t *)args))
  167. {
  168. result = -RT_ERROR;
  169. }
  170. LOG_D("RTC: set rtc_time %x\n", *(rt_uint32_t *)args);
  171. return result;
  172. }
  173. static const struct rt_rtc_ops _rtc_ops =
  174. {
  175. _rtc_init,
  176. _rtc_get_secs,
  177. _rtc_set_secs,
  178. RT_NULL,
  179. RT_NULL,
  180. RT_NULL,
  181. RT_NULL,
  182. };
  183. static rt_rtc_dev_t at32_rtc_dev;
  184. int rt_hw_rtc_init(void)
  185. {
  186. rt_err_t result;
  187. at32_rtc_dev.ops = &_rtc_ops;
  188. result = rt_hw_rtc_register(&at32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR,RT_NULL);
  189. if (result != RT_EOK)
  190. {
  191. LOG_E("rtc register err code: %d", result);
  192. return result;
  193. }
  194. LOG_D("rtc init success");
  195. return RT_EOK;
  196. }
  197. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  198. #endif /* BSP_USING_RTC */