drv_rtc.c 7.7 KB

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