drv_rtc.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. /*
  2. * Copyright (c) 2006-2022, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2022-03-04 stevetong459 first version
  9. * 2022-07-15 Aligagago add apm32F4 serie MCU support
  10. */
  11. #include "board.h"
  12. #include <sys/time.h>
  13. #ifdef BSP_USING_ONCHIP_RTC
  14. #define LOG_TAG "drv.rtc"
  15. #define DBG_LVL DBG_INFO
  16. #include <rtdbg.h>
  17. #ifndef LSI_VALUE
  18. #define LSI_VALUE ((uint32_t)40000)
  19. #endif
  20. #ifndef LSE_VALUE
  21. #define LSE_VALUE ((uint32_t)32768)
  22. #endif
  23. #define DRV_RTC_TIME_OUT 0xFFF
  24. static rt_rtc_dev_t apm32_rtc_dev;
  25. static rt_uint8_t rtc_init_flag = RESET;
  26. /**
  27. * @brief This function will initialize the rtc on chip.
  28. *
  29. * @return RT_EOK indicates successful initialize, other value indicates failed;
  30. */
  31. static rt_err_t _rtc_init(void)
  32. {
  33. volatile rt_uint32_t counter = 0;
  34. /* Enable RTC Clock */
  35. #ifdef APM32F10X_HD
  36. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU | RCM_APB1_PERIPH_BAKR);
  37. #elif APM32F40X
  38. RCM_EnableAPB1PeriphClock(RCM_APB1_PERIPH_PMU);
  39. #endif
  40. PMU_EnableBackupAccess();
  41. /* Config RTC clock */
  42. #ifdef BSP_RTC_USING_LSI
  43. RCM_EnableLSI();
  44. while (!RCM_ReadStatusFlag(RCM_FLAG_LSIRDY))
  45. {
  46. if (++counter > DRV_RTC_TIME_OUT)
  47. {
  48. return RT_ETIMEOUT;
  49. }
  50. }
  51. RCM_ConfigRTCCLK(RCM_RTCCLK_LSI);
  52. #else
  53. RCM_ConfigLSE(RCM_LSE_OPEN);
  54. while (!RCM_ReadStatusFlag(RCM_FLAG_LSERDY))
  55. {
  56. if (++counter > DRV_RTC_TIME_OUT)
  57. {
  58. return RT_ETIMEOUT;
  59. }
  60. }
  61. RCM_ConfigRTCCLK(RCM_RTCCLK_LSE);
  62. #endif
  63. RCM_EnableRTCCLK();
  64. RTC_WaitForSynchro();
  65. #ifdef APM32F10X_HD
  66. counter = 0;
  67. while (!RTC_ReadStatusFlag(RTC_FLAG_OC))
  68. {
  69. if (++counter > DRV_RTC_TIME_OUT)
  70. {
  71. return RT_ETIMEOUT;
  72. }
  73. }
  74. RTC_EnableConfigMode();
  75. RTC_ClearStatusFlag(RTC_FLAG_OVR | RTC_FLAG_ALR | RTC_FLAG_SEC);
  76. #ifdef BSP_RTC_USING_LSI
  77. RTC_ConfigPrescaler(LSI_VALUE - 1);
  78. #else
  79. RTC_ConfigPrescaler(LSE_VALUE - 1);
  80. #endif
  81. #elif APM32F40X
  82. RTC_EnableInit();
  83. RTC_Config_T rtcConfig;
  84. RTC_ConfigStructInit(&rtcConfig);
  85. RTC_Config(&rtcConfig);
  86. #endif
  87. if (!rtc_init_flag)
  88. {
  89. rtc_init_flag = SET;
  90. }
  91. return RT_EOK;
  92. }
  93. #ifdef APM32F10X_HD
  94. /**
  95. * @brief This function will initialize the rtc on chip.
  96. *
  97. * @return RT_EOK indicates successful initialize, other value indicates failed;
  98. */
  99. static rt_err_t _rtc_get_secs(void *args)
  100. {
  101. volatile rt_uint32_t counter = 0;
  102. while (!RTC_ReadStatusFlag(RTC_FLAG_OC))
  103. {
  104. if (++counter > DRV_RTC_TIME_OUT)
  105. {
  106. return RT_ETIMEOUT;
  107. }
  108. }
  109. *(rt_uint32_t *) args = RTC_ReadCounter();
  110. return RT_EOK;
  111. }
  112. static rt_err_t _rtc_set_secs(void *args)
  113. {
  114. volatile rt_uint32_t counter = 0;
  115. if (!rtc_init_flag)
  116. {
  117. _rtc_init();
  118. }
  119. while (!RTC_ReadStatusFlag(RTC_FLAG_OC))
  120. {
  121. if (++counter > DRV_RTC_TIME_OUT)
  122. {
  123. return RT_ETIMEOUT;
  124. }
  125. }
  126. RTC_ConfigCounter(*(rt_uint32_t *)args);
  127. return RT_EOK;
  128. }
  129. #elif APM32F40X
  130. static void get_rtc_timeval(struct timeval *tv)
  131. {
  132. RTC_TimeConfig_T timeConfig;
  133. RTC_DateConfig_T dateConfig;
  134. struct tm tm_new = {0};
  135. RTC_ReadTime(RTC_FORMAT_BIN, &timeConfig);
  136. RTC_ReadDate(RTC_FORMAT_BIN, &dateConfig);
  137. tm_new.tm_sec = timeConfig.seconds;
  138. tm_new.tm_min = timeConfig.minutes;
  139. tm_new.tm_hour = timeConfig.hours;
  140. tm_new.tm_mday = dateConfig.date;
  141. tm_new.tm_mon = dateConfig.month - 1;
  142. tm_new.tm_year = dateConfig.year + 100;
  143. tv->tv_sec = timegm(&tm_new);
  144. }
  145. static rt_err_t set_rtc_timeval(time_t time_stamp)
  146. {
  147. RTC_TimeConfig_T timeConfig;
  148. RTC_DateConfig_T dateConfig;
  149. struct tm tm = {0};
  150. if (!rtc_init_flag)
  151. {
  152. _rtc_init();
  153. }
  154. gmtime_r(&time_stamp, &tm);
  155. if (tm.tm_year < 100)
  156. {
  157. return -RT_ERROR;
  158. }
  159. timeConfig.seconds = tm.tm_sec ;
  160. timeConfig.minutes = tm.tm_min ;
  161. timeConfig.hours = tm.tm_hour;
  162. dateConfig.date = tm.tm_mday;
  163. dateConfig.month = tm.tm_mon + 1 ;
  164. dateConfig.year = tm.tm_year - 100;
  165. dateConfig.weekday = tm.tm_wday + 1;
  166. RTC_ConfigTime(RTC_FORMAT_BIN, &timeConfig);
  167. RTC_ConfigDate(RTC_FORMAT_BIN, &dateConfig);
  168. return RT_EOK;
  169. }
  170. /**
  171. * @brief This function will initialize the rtc on chip.
  172. *
  173. * @return RT_EOK indicates successful initialize, other value indicates failed;
  174. */
  175. static rt_err_t _rtc_get_secs(void *args)
  176. {
  177. struct timeval tv;
  178. get_rtc_timeval(&tv);
  179. *(rt_uint32_t *) args = tv.tv_sec;
  180. return RT_EOK;
  181. }
  182. static rt_err_t _rtc_set_secs(void *args)
  183. {
  184. rt_err_t result = RT_EOK;
  185. if (set_rtc_timeval(*(rt_uint32_t *)args))
  186. {
  187. result = -RT_ERROR;
  188. }
  189. return result;
  190. }
  191. #endif
  192. static const struct rt_rtc_ops _rtc_ops =
  193. {
  194. _rtc_init,
  195. _rtc_get_secs,
  196. _rtc_set_secs,
  197. RT_NULL,
  198. RT_NULL,
  199. RT_NULL,
  200. RT_NULL,
  201. };
  202. /**
  203. * @brief RTC initialization function.
  204. *
  205. * @return RT_EOK indicates successful initialization, other value indicates failed;
  206. */
  207. static int rt_hw_rtc_init(void)
  208. {
  209. rt_err_t result = RT_EOK;
  210. apm32_rtc_dev.ops = &_rtc_ops;
  211. if (rt_hw_rtc_register(&apm32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL) != RT_EOK)
  212. {
  213. LOG_E("rtc init failed");
  214. result = RT_ERROR;
  215. }
  216. else
  217. {
  218. LOG_D("rtc init success");
  219. }
  220. return result;
  221. }
  222. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  223. #endif /* BSP_USING_ONCHIP_RTC */