drv_rtc.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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-10-19 Nations first version
  9. */
  10. #include "board.h"
  11. #include <sys/time.h>
  12. #include <rtdevice.h>
  13. #ifdef BSP_USING_RTC
  14. #define USER_WRITE_BKP_DAT1_DATA 0xA5A5
  15. uint32_t SynchPrediv, AsynchPrediv;
  16. static rt_err_t n32_rtc_get_timeval(struct timeval *tv)
  17. {
  18. struct tm tm_new = {0};
  19. RTC_DateType RTC_DateStructure;
  20. RTC_TimeType RTC_TimeStructure;
  21. RTC_GetTime(RTC_FORMAT_BIN, &RTC_TimeStructure);
  22. RTC_GetDate(RTC_FORMAT_BIN, &RTC_DateStructure);
  23. tm_new.tm_sec = RTC_TimeStructure.Seconds;
  24. tm_new.tm_min = RTC_TimeStructure.Minutes;
  25. tm_new.tm_hour = RTC_TimeStructure.Hours;
  26. tm_new.tm_wday = RTC_DateStructure.WeekDay;
  27. tm_new.tm_mday = RTC_DateStructure.Date;
  28. tm_new.tm_mon = RTC_DateStructure.Month - 1;
  29. tm_new.tm_year = RTC_DateStructure.Year + 100;
  30. tv->tv_sec = timegm(&tm_new);
  31. return RT_EOK;
  32. }
  33. static rt_err_t set_rtc_time_stamp(time_t time_stamp)
  34. {
  35. struct tm time = {0};
  36. RTC_DateType RTC_DateStructure={0};
  37. RTC_TimeType RTC_TimeStructure={0};
  38. gmtime_r(&time_stamp, &time);
  39. if (time.tm_year < 100)
  40. {
  41. return -RT_ERROR;
  42. }
  43. RTC_TimeStructure.Seconds = time.tm_sec ;
  44. RTC_TimeStructure.Minutes = time.tm_min ;
  45. RTC_TimeStructure.Hours = time.tm_hour;
  46. RTC_DateStructure.Date = time.tm_mday;
  47. RTC_DateStructure.Month = time.tm_mon + 1 ;
  48. RTC_DateStructure.Year = time.tm_year - 100;
  49. RTC_DateStructure.WeekDay = time.tm_wday + 1;
  50. /* Configure the RTC date register */
  51. if (RTC_SetDate(RTC_FORMAT_BIN, &RTC_DateStructure) != SUCCESS)
  52. {
  53. return -RT_ERROR;
  54. }
  55. /* Configure the RTC time register */
  56. if (RTC_ConfigTime(RTC_FORMAT_BIN, &RTC_TimeStructure) != SUCCESS)
  57. {
  58. return -RT_ERROR;
  59. }
  60. rt_kprintf("set rtc time.\n");
  61. return RT_EOK;
  62. }
  63. static rt_err_t rt_rtc_config(void)
  64. {
  65. RTC_InitType RTC_InitStructure;
  66. /* Configure the RTC data register and RTC prescaler */
  67. RTC_InitStructure.RTC_AsynchPrediv = AsynchPrediv;
  68. RTC_InitStructure.RTC_SynchPrediv = SynchPrediv;
  69. RTC_InitStructure.RTC_HourFormat = RTC_24HOUR_FORMAT;
  70. /* Check on RTC init */
  71. if (RTC_Init(&RTC_InitStructure) != SUCCESS)
  72. {
  73. return -RT_ERROR;
  74. }
  75. return RT_EOK;
  76. }
  77. static rt_err_t n32_rtc_init(void)
  78. {
  79. /* Enable the PWR clock */
  80. #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
  81. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR | RCC_APB1_PERIPH_BKP, ENABLE);
  82. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  83. #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
  84. RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_PWR, ENABLE);
  85. RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO, ENABLE);
  86. #endif
  87. /* Allow access to RTC */
  88. PWR_BackupAccessEnable(ENABLE);
  89. if (USER_WRITE_BKP_DAT1_DATA != BKP_ReadBkpData(BKP_DAT1) )
  90. {
  91. #if defined(SOC_N32G45X) || defined(SOC_N32WB452)
  92. /* Reset Backup */
  93. BKP_DeInit();
  94. #endif
  95. /* Disable RTC clock */
  96. RCC_EnableRtcClk(DISABLE);
  97. #ifdef BSP_RTC_USING_HSE
  98. /* Enable the HSE OSC */
  99. RCC_EnableLsi(DISABLE);
  100. RCC_ConfigHse(RCC_HSE_ENABLE);
  101. while (RCC_WaitHseStable() == ERROR)
  102. {
  103. }
  104. #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
  105. rt_kprintf("rtc clock source is set hse/128!\n");
  106. RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV128);
  107. #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
  108. rt_kprintf("rtc clock source is set hse/32!\n");
  109. RCC_ConfigRtcClk(RCC_RTCCLK_SRC_HSE_DIV32);
  110. #endif
  111. #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
  112. SynchPrediv = 0x1E8; // 8M/128 = 62.5KHz
  113. AsynchPrediv = 0x7F; // value range: 0-7F
  114. #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
  115. SynchPrediv = 0x7A0; // 8M/32 = 250KHz
  116. AsynchPrediv = 0x7F; // value range: 0-7F
  117. #endif
  118. #endif /* BSP_RTC_USING_HSE */
  119. #ifdef BSP_RTC_USING_LSE
  120. rt_kprintf("rtc clock source is set lse!\n");
  121. /* Enable the LSE OSC32_IN PC14 */
  122. RCC_EnableLsi(DISABLE); // LSI is turned off here to ensure that only one clock is turned on
  123. #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
  124. RCC_ConfigLse(RCC_LSE_ENABLE);
  125. while (RCC_GetFlagStatus(RCC_FLAG_LSERD) == RESET)
  126. {
  127. }
  128. #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
  129. RCC_ConfigLse(RCC_LSE_ENABLE,0x28);
  130. while (RCC_GetFlagStatus(RCC_LDCTRL_FLAG_LSERD) == RESET)
  131. {
  132. }
  133. #endif
  134. RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSE);
  135. SynchPrediv = 0xFF; // 32.768KHz
  136. AsynchPrediv = 0x7F; // value range: 0-7F
  137. #endif /* BSP_RTC_USING_LSE */
  138. #ifdef BSP_RTC_USING_LSI
  139. rt_kprintf("rtc clock source is set lsi!\n");
  140. /* Enable the LSI OSC */
  141. RCC_EnableLsi(ENABLE);
  142. #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
  143. while (RCC_GetFlagStatus(RCC_FLAG_LSIRD) == RESET)
  144. {
  145. }
  146. #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
  147. while (RCC_GetFlagStatus(RCC_CTRLSTS_FLAG_LSIRD) == RESET)
  148. {
  149. }
  150. #endif
  151. RCC_ConfigRtcClk(RCC_RTCCLK_SRC_LSI);
  152. #if defined(SOC_N32G45X) || defined(SOC_N32WB452) || defined(SOC_N32G4FR)
  153. SynchPrediv = 0x136; // 39.64928KHz
  154. AsynchPrediv = 0x7F; // value range: 0-7F
  155. #elif defined(SOC_N32L43X) || defined(SOC_N32L40X) || defined(SOC_N32G43X)
  156. SynchPrediv = 0x14A; // 41828Hz
  157. AsynchPrediv = 0x7F; // value range: 0-7F
  158. #endif
  159. #endif /* BSP_RTC_USING_LSI */
  160. /* Enable the RTC Clock */
  161. RCC_EnableRtcClk(ENABLE);
  162. RTC_WaitForSynchro();
  163. if (rt_rtc_config() != RT_EOK)
  164. {
  165. rt_kprintf("rtc init failed.\n");
  166. return -RT_ERROR;
  167. }
  168. BKP_WriteBkpData(BKP_DAT1, USER_WRITE_BKP_DAT1_DATA);
  169. }
  170. return RT_EOK;
  171. }
  172. static rt_err_t n32_rtc_get_secs(time_t *sec)
  173. {
  174. struct timeval tv;
  175. n32_rtc_get_timeval(&tv);
  176. *(time_t *) sec = tv.tv_sec;
  177. rt_kprintf("RTC: get rtc_time %d.\n", *sec);
  178. return RT_EOK;
  179. }
  180. static rt_err_t n32_rtc_set_secs(time_t *sec)
  181. {
  182. rt_err_t result = RT_EOK;
  183. if (set_rtc_time_stamp(*sec))
  184. {
  185. result = -RT_ERROR;
  186. }
  187. rt_kprintf("RTC: set rtc_time %d.\n", *sec);
  188. return result;
  189. }
  190. static const struct rt_rtc_ops n32_rtc_ops =
  191. {
  192. n32_rtc_init,
  193. n32_rtc_get_secs,
  194. n32_rtc_set_secs,
  195. RT_NULL,
  196. RT_NULL,
  197. n32_rtc_get_timeval,
  198. RT_NULL,
  199. };
  200. static rt_rtc_dev_t n32_rtc_dev;
  201. static int rt_hw_rtc_init(void)
  202. {
  203. rt_err_t result;
  204. n32_rtc_dev.ops = &n32_rtc_ops;
  205. result = rt_hw_rtc_register(&n32_rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR, RT_NULL);
  206. if (result != RT_EOK)
  207. {
  208. rt_kprintf("rtc register error code: %d.\n", result);
  209. return result;
  210. }
  211. else
  212. {
  213. rt_kprintf("rtc initialize success.\n");
  214. }
  215. return RT_EOK;
  216. }
  217. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  218. #endif /* BSP_USING_RTC */