1
0

drv_rtc.c 6.4 KB

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