stm32f4_rtc.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2015-09-29 FlyM the first version.
  9. */
  10. #include <time.h>
  11. #include <rtthread.h>
  12. #include <stm32f4xx.h>
  13. #include "stm32f4_rtc.h"
  14. static int get_week(int year, int month, int day)
  15. {
  16. if (month==1||month==2)
  17. {
  18. year -=1;
  19. month +=12;
  20. }
  21. return (day+1+2*month+3*(month+1)/5+year+(year/4)-year/100+year/400)%7+1;
  22. }
  23. static struct rt_device rtc;
  24. static rt_err_t rt_rtc_open(rt_device_t dev, rt_uint16_t oflag)
  25. {
  26. if (dev->rx_indicate != RT_NULL)
  27. {
  28. /* Open Interrupt */
  29. }
  30. return RT_EOK;
  31. }
  32. static rt_size_t rt_rtc_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
  33. {
  34. return 0;
  35. }
  36. static rt_err_t rt_rtc_control(rt_device_t dev, int cmd, void *args)
  37. {
  38. rt_time_t *time;
  39. RT_ASSERT(dev != RT_NULL);
  40. switch (cmd)
  41. {
  42. case RT_DEVICE_CTRL_RTC_GET_TIME:
  43. {
  44. struct tm ct;
  45. RTC_TimeTypeDef t;
  46. RTC_DateTypeDef d;
  47. rt_memset(&ct,0,sizeof(struct tm));
  48. time = (rt_time_t *)args;
  49. /* read device */
  50. RTC_GetDate(RTC_Format_BIN,&d);
  51. RTC_GetTime(RTC_Format_BIN,&t);
  52. ct.tm_year = d.RTC_Year + 100;
  53. ct.tm_mon = d.RTC_Month - 1;
  54. ct.tm_mday = d.RTC_Date;
  55. ct.tm_wday = d.RTC_WeekDay;
  56. ct.tm_hour = t.RTC_Hours;
  57. ct.tm_min = t.RTC_Minutes;
  58. ct.tm_sec = t.RTC_Seconds;
  59. *time = mktime(&ct);
  60. }
  61. break;
  62. case RT_DEVICE_CTRL_RTC_SET_TIME:
  63. {
  64. struct tm *ct;
  65. struct tm tm_new;
  66. time_t *time;
  67. RTC_TimeTypeDef RTC_TimeStructure;
  68. RTC_InitTypeDef RTC_InitStructure;
  69. RTC_DateTypeDef RTC_DateStructure;
  70. time = (time_t *)args;
  71. /* lock scheduler. */
  72. rt_enter_critical();
  73. /* converts calendar time time into local time. */
  74. ct = localtime(time);
  75. /* copy the statically located variable */
  76. rt_memcpy(&tm_new, ct, sizeof(struct tm));
  77. /* unlock scheduler. */
  78. rt_exit_critical();
  79. /* Enable the PWR clock */
  80. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  81. /* Allow access to RTC */
  82. PWR_BackupAccessCmd(ENABLE);
  83. /* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
  84. //uwSynchPrediv = 0xFF;
  85. //uwAsynchPrediv = 0x7F;
  86. /* Configure the RTC data register and RTC prescaler */
  87. RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
  88. RTC_InitStructure.RTC_SynchPrediv = 0xFF;
  89. RTC_InitStructure.RTC_HourFormat = RTC_HourFormat_24;
  90. RTC_Init(&RTC_InitStructure);
  91. /* Set the date */
  92. RTC_DateStructure.RTC_Year = tm_new.tm_year - 100;
  93. RTC_DateStructure.RTC_Month = tm_new.tm_mon + 1;
  94. RTC_DateStructure.RTC_Date = tm_new.tm_mday;
  95. RTC_DateStructure.RTC_WeekDay = get_week(tm_new.tm_year+1900,tm_new.tm_mon+1,tm_new.tm_mday);
  96. RTC_SetDate(RTC_Format_BIN, &RTC_DateStructure);
  97. /* Set the time*/
  98. if (tm_new.tm_hour > 11)
  99. {
  100. RTC_TimeStructure.RTC_H12 = RTC_H12_PM;
  101. }
  102. else
  103. {
  104. RTC_TimeStructure.RTC_H12 = RTC_H12_AM;
  105. }
  106. RTC_TimeStructure.RTC_Hours = tm_new.tm_hour;
  107. RTC_TimeStructure.RTC_Minutes = tm_new.tm_min;
  108. RTC_TimeStructure.RTC_Seconds = tm_new.tm_sec;
  109. RTC_SetTime(RTC_Format_BIN, &RTC_TimeStructure);
  110. /* Indicator for the RTC configuration */
  111. RTC_WriteBackupRegister(RTC_BKP_DR0, 0x32F2);
  112. }
  113. break;
  114. }
  115. return RT_EOK;
  116. }
  117. /*******************************************************************************
  118. * Function Name : RTC_Configuration
  119. * Description : Configures the RTC.
  120. * Input : None
  121. * Output : None
  122. * Return : 0 reday,-1 error.
  123. *******************************************************************************/
  124. int RTC_Configuration(void)
  125. {
  126. /* Enable the PWR clock */
  127. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  128. /* Allow access to RTC */
  129. PWR_BackupAccessCmd(ENABLE);
  130. #if defined (RTC_CLOCK_SOURCE_LSI) /* LSI used as RTC source clock*/
  131. /* The RTC Clock may varies due to LSI frequency dispersion */
  132. /* Enable the LSI OSC */
  133. RCC_LSICmd(ENABLE);
  134. /* Wait till LSI is ready */
  135. while(RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET)
  136. {
  137. }
  138. /* Select the RTC Clock Source */
  139. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  140. /* ck_spre(1Hz) = RTCCLK(LSI) /(uwAsynchPrediv + 1)*(uwSynchPrediv + 1)*/
  141. //uwSynchPrediv = 0xFF;
  142. //uwAsynchPrediv = 0x7F;
  143. #elif defined (RTC_CLOCK_SOURCE_LSE) /* LSE used as RTC source clock */
  144. /* Enable the LSE OSC */
  145. RCC_LSEConfig(RCC_LSE_ON);
  146. /* Wait till LSE is ready */
  147. while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
  148. {
  149. }
  150. /* Select the RTC Clock Source */
  151. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  152. #else
  153. #error Please select the RTC Clock source inside the main.c file
  154. #endif /* RTC_CLOCK_SOURCE_LSI */
  155. /* Enable the RTC Clock */
  156. RCC_RTCCLKCmd(ENABLE);
  157. /* Wait for RTC APB registers synchronisation */
  158. RTC_WaitForSynchro();
  159. return 0;
  160. }
  161. void rt_hw_rtc_init(void)
  162. {
  163. rtc.type = RT_Device_Class_RTC;
  164. if (RTC_ReadBackupRegister(RTC_BKP_DR0) != 0x32F2)
  165. {
  166. rt_kprintf("rtc is not configured\n");
  167. rt_kprintf("please configure with set_date and set_time\n");
  168. if ( RTC_Configuration() != 0)
  169. {
  170. rt_kprintf("rtc configure fail...\r\n");
  171. return ;
  172. }
  173. }
  174. else
  175. {
  176. /* Wait for RTC registers synchronization */
  177. RTC_WaitForSynchro();
  178. }
  179. /* register rtc device */
  180. rtc.init = RT_NULL;
  181. rtc.open = rt_rtc_open;
  182. rtc.close = RT_NULL;
  183. rtc.read = rt_rtc_read;
  184. rtc.write = RT_NULL;
  185. rtc.control = rt_rtc_control;
  186. /* no private */
  187. rtc.user_data = RT_NULL;
  188. rt_device_register(&rtc, "rtc", RT_DEVICE_FLAG_RDWR);
  189. return;
  190. }
  191. #ifdef RT_USING_FINSH
  192. #include "finsh.h"
  193. void show_time(void)
  194. {
  195. RTC_TimeTypeDef t;
  196. RTC_DateTypeDef d;
  197. /* Get the current Date */
  198. RTC_GetDate(RTC_Format_BIN,&d);
  199. /* Get the current Time */
  200. RTC_GetTime(RTC_Format_BIN, &t);
  201. /* Display time Format : hh:mm:ss */
  202. rt_kprintf("Now Time = 20%02d %02d %02d[%02d]-%0.2d:%0.2d:%0.2d \r\n", \
  203. d.RTC_Year,d.RTC_Month,d.RTC_Date,d.RTC_WeekDay,t.RTC_Hours, t.RTC_Minutes, t.RTC_Seconds);
  204. }
  205. FINSH_FUNCTION_EXPORT(show_time, show current time.)
  206. #endif