stm32f4_rtc.c 6.2 KB

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