drv_rtc.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. /*
  2. * Copyright (C) 2018 Shanghai Eastsoft Microelectronics Co., Ltd.
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-10-23 yuzrain the first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include <rtdevice.h>
  13. #include <string.h>
  14. #include <sys/time.h>
  15. #include "board.h"
  16. #include "drv_rtc.h"
  17. #ifdef RT_USING_RTC
  18. /**
  19. * @brief Time structure
  20. */
  21. typedef struct
  22. {
  23. uint8_t hour; /**< Hours */
  24. uint8_t minute; /**< Minutes */
  25. uint8_t second; /**< Seconds */
  26. uint16_t sub_sec; /**< Sub-seconds */
  27. } rtc_time_t;
  28. /**
  29. * @brief Date structure
  30. */
  31. typedef struct
  32. {
  33. uint8_t week; /**< Weeks */
  34. uint8_t day; /**< days */
  35. uint8_t month; /**< months */
  36. uint8_t year; /**< years */
  37. } rtc_date_t;
  38. static rt_uint32_t bcd_to_dec(rt_uint32_t bcd)
  39. {
  40. return ((bcd & 0xF) + ((bcd >> 4) & 0xF) * 10);
  41. }
  42. static void rtc_get_time(rtc_time_t *time)
  43. {
  44. rt_uint32_t tmp = RTC->TIME;
  45. time->second = bcd_to_dec(tmp & 0x7F);
  46. time->minute = bcd_to_dec((tmp >> 8) & 0x7F);
  47. time->hour = bcd_to_dec((tmp >> 16) & 0x7F);
  48. return;
  49. }
  50. static void rtc_get_date(rtc_date_t *date)
  51. {
  52. uint32_t tmp = RTC->CAL;
  53. date->day = bcd_to_dec(tmp & 0x3F);
  54. date->month = bcd_to_dec((tmp >> 8) & 0x1F);
  55. date->year = bcd_to_dec((tmp >> 16) & 0xFF);
  56. date->week = bcd_to_dec((RTC->TIME >> 24) & 0x7);
  57. return;
  58. }
  59. static rt_err_t es32f0_rtc_control(rt_device_t dev, int cmd, void *args)
  60. {
  61. rt_err_t result = RT_EOK;
  62. struct tm time_temp;
  63. struct tm *pNow;
  64. rt_uint16_t timout = 0xFFF;
  65. rtc_time_t *time = rt_malloc(sizeof(rtc_time_t));
  66. rtc_date_t *date = rt_malloc(sizeof(rtc_date_t));
  67. switch (cmd)
  68. {
  69. case RT_DEVICE_CTRL_RTC_GET_TIME:
  70. {
  71. /* Wait RTC data ready then read */
  72. while ((--timout)&&((RTC->STAT & RTC_STAT_SYNDONE_MSK) != RTC_STAT_SYNDONE_MSK));
  73. if (timout == 0)
  74. result = RT_ERROR;
  75. /* Read */
  76. rtc_get_time(time);
  77. rtc_get_date(date);
  78. time_temp.tm_sec = time->second;
  79. time_temp.tm_min = time->minute;
  80. time_temp.tm_hour = time->hour;
  81. time_temp.tm_wday = date->week - 1;
  82. time_temp.tm_mday = date->day;
  83. time_temp.tm_mon = date->month - 1;
  84. time_temp.tm_year = date->year - 1900 + 2000;
  85. *((time_t *)args) = timegm(&time_temp);
  86. break;
  87. }
  88. case RT_DEVICE_CTRL_RTC_SET_TIME:
  89. {
  90. rt_enter_critical();
  91. /* converts calendar time time into local time. */
  92. pNow = gmtime((const time_t *)args);
  93. /* copy the statically located variable */
  94. memcpy(&time_temp, pNow, sizeof(struct tm));
  95. /* unlock scheduler. */
  96. rt_exit_critical();
  97. time->hour = time_temp.tm_hour;
  98. time->minute = time_temp.tm_min;
  99. time->second = time_temp.tm_sec;
  100. date->year = time_temp.tm_year + 1900 - 2000;
  101. date->month = time_temp.tm_mon + 1;
  102. date->day = time_temp.tm_mday;
  103. /* Stop RTC */
  104. CLEAR_BIT(RTC->CON, RTC_CON_RTCEN_MSK);
  105. WRITE_REG(RTC->TIME, ((time->hour/10)<<RTC_TIME_HOUR_T_POSS) /* hour */
  106. |((time->hour%10)<<RTC_TIME_HOUR_U_POSS)
  107. |((time->minute/10)<<RTC_TIME_MIN_T_POSS) /* minute */
  108. |((time->minute%10)<<RTC_TIME_MIN_U_POSS)
  109. |((time->second/10)<<RTC_TIME_SEC_T_POSS) /* second */
  110. |((time->second%10)<<RTC_TIME_SEC_U_POSS));
  111. WRITE_REG(RTC->CAL, ((date->year/10)<<RTC_CAL_YEAR_T_POSS) /* year */
  112. |((date->year%10)<<RTC_CAL_YEAR_U_POSS)
  113. |((date->month/10)<<RTC_CAL_MON_T_POS) /* month */
  114. |((date->month%10)<<RTC_CAL_MON_U_POSS)
  115. |((date->day/10)<<RTC_CAL_DATE_T_POSS) /* date */
  116. |((date->day%10)<<RTC_CAL_DATE_U_POSS));
  117. /* start RTC */
  118. SET_BIT(RTC->CON, RTC_CON_RTCEN_MSK);
  119. break;
  120. }
  121. case RT_DEVICE_CTRL_RTC_GET_ALARM:
  122. break;
  123. case RT_DEVICE_CTRL_RTC_SET_ALARM:
  124. break;
  125. default:
  126. break;
  127. }
  128. rt_free(time);
  129. rt_free(date);
  130. return result;
  131. }
  132. #ifdef RT_USING_DEVICE_OPS
  133. const static struct rt_device_ops es32f0_rtc_ops =
  134. {
  135. RT_NULL,
  136. RT_NULL,
  137. RT_NULL,
  138. RT_NULL,
  139. RT_NULL,
  140. es32f0_rtc_control
  141. };
  142. #endif
  143. static struct rt_device rtc_dev;
  144. #define RTC_SOURCE_LOSC 0x1
  145. #define RTC_SOURCE_LRC 0x2
  146. int rt_hw_rtc_init(void)
  147. {
  148. rt_err_t ret = RT_EOK;
  149. rt_uint16_t timout = 0xFFFF;
  150. rt_uint32_t rtc_clk = 32768-1;
  151. rt_uint8_t rtc_src = RTC_SOURCE_LOSC;
  152. /*
  153. * Config RTC clock
  154. * We config the external 32.768K crystal as RTC clock source for the first
  155. * choice. If external 32.768K crystal is not ready, we will choose LRC.
  156. */
  157. /* Enable LOSC then wait it ready */
  158. if ((RCU->CON & RCU_CON_LOSCON_MSK) != RCU_CON_LOSCON_MSK)
  159. SET_BIT(RCU->CON, RCU_CON_LOSCON_MSK);
  160. /* Wait external 32.768K crystal ready */
  161. while (((RCU->CON & RCU_CON_LOSCRDY_MSK) != RCU_CON_LOSCRDY_MSK)&&(--timout));
  162. if (timout == 0)
  163. {
  164. /* We use LRC if external 32.768K crystal is not ready */
  165. if ((RCU->CON & RCU_CON_LRCON_MSK) != RCU_CON_LRCON_MSK)
  166. SET_BIT(RCU->CON, RCU_CON_LRCON_MSK);
  167. /* Wait LRC ready */
  168. timout = 0xFF;
  169. while (((RCU->CON & RCU_CON_LRCRDY_MSK) != RCU_CON_LRCRDY_MSK)&&(--timout));
  170. rtc_clk = 32000-1;
  171. rtc_src = RTC_SOURCE_LRC;
  172. }
  173. /* Open RTC clock */
  174. SET_BIT(RCU->AHBEN, RCU_AHBEN_RTCEN_MSK);
  175. /* Reset RTC */
  176. SET_BIT(RCU->AHBRST, RCU_AHBRST_RTCEN_MSK);
  177. CLEAR_BIT(RCU->AHBRST, RCU_AHBRST_RTCEN_MSK);
  178. CLEAR_BIT(RTC->CON, RTC_CON_RTCEN_MSK);
  179. /* Config RTC clock source */
  180. MODIFY_REG(RTC->CON, RTC_CON_CKSEL_MSK, rtc_src<<RTC_CON_CKSEL_POSS);
  181. MODIFY_REG(RTC->CON, RTC_CON_PSCALE_MSK|RTC_CON_SCALE_MSK,
  182. ((rtc_clk&0x7F)<<RTC_CON_PSCALE_POSS)|
  183. (((rtc_clk>>7)&0xFF)<<RTC_CON_SCALE_POSS));
  184. /* Set default time - Wed Oct 30 08:00:00 2019 */
  185. WRITE_REG(RTC->TIME, (0x3<<RTC_TIME_WEEK_POSS) /* week */
  186. |(0x0<<RTC_TIME_HOUR_T_POSS) /* hour */
  187. |(0x8<<RTC_TIME_HOUR_U_POSS)
  188. |(0x0<<RTC_TIME_MIN_T_POSS) /* minute */
  189. |(0x0<<RTC_TIME_MIN_U_POSS)
  190. |(0x0<<RTC_TIME_SEC_T_POSS) /* second */
  191. |(0x0<<RTC_TIME_SEC_U_POSS));
  192. WRITE_REG(RTC->CAL, (0x1<<RTC_CAL_YEAR_T_POSS) /* year */
  193. |(0x9<<RTC_CAL_YEAR_U_POSS)
  194. |(0x1<<RTC_CAL_MON_T_POS) /* month */
  195. |(0x0<<RTC_CAL_MON_U_POSS)
  196. |(0x3<<RTC_CAL_DATE_T_POSS) /* date */
  197. |(0x0<<RTC_CAL_DATE_U_POSS));
  198. /* RTC start */
  199. SET_BIT(RTC->CON, RTC_CON_RTCEN_MSK);
  200. rtc_dev.type = RT_Device_Class_RTC;
  201. rtc_dev.rx_indicate = RT_NULL;
  202. rtc_dev.tx_complete = RT_NULL;
  203. #ifdef RT_USING_DEVICE_OPS
  204. rtc_dev.ops = &es32f0_rtc_ops;
  205. #else
  206. rtc_dev.init = RT_NULL;
  207. rtc_dev.open = RT_NULL;
  208. rtc_dev.close = RT_NULL;
  209. rtc_dev.read = RT_NULL;
  210. rtc_dev.write = RT_NULL;
  211. rtc_dev.control = es32f0_rtc_control;
  212. #endif
  213. rtc_dev.user_data = RTC;
  214. ret = rt_device_register(&rtc_dev, "rtc", RT_DEVICE_FLAG_RDWR);
  215. return ret;
  216. }
  217. INIT_DEVICE_EXPORT(rt_hw_rtc_init);
  218. #endif