rtc.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include "cst92f2x.h"
  2. #include "rtc.h"
  3. #include "pwrmgr.h"
  4. #include "uart.h"
  5. #include "OSAL_Clock.h"
  6. #include "clock.h"
  7. #include "log.h"
  8. #include "global_config.h"
  9. #include "jump_function.h"
  10. #define UTC_START_TIME 946656000 //2000.1.1 0:0:0
  11. #define UPDATA_TICK 300000000 //updata interval tick(unit:s)(300s)
  12. #define RTC_COUNT_OF_5MIN 9830400 //32768*5*60
  13. #define RTC_COUNT_OF_12HOUR 1415577600 //32768*12*60*60
  14. #define RTC_COUNT_OF_12HOUR_1MIN 1417543680 //32768*(13*60+1)*60 12HOUR+1MIN
  15. /**
  16. * @struct RtcCtl_t
  17. * @brief RTC control information
  18. */
  19. typedef struct {
  20. uint64_t prevUpdateBase;
  21. uint32_t prevUpdateTicks;
  22. uint32_t lastTicks;
  23. }RtcCtl_t;
  24. static RtcCtl_t rtcCtl;
  25. static uint32_t tick_unit = 0;
  26. static uint32_t rtc_cnt_track=0;
  27. uint32_t get_rtc_counter(void)
  28. {
  29. uint32_t cnt0,cnt1;
  30. while(1)
  31. {
  32. cnt0 =((*(volatile unsigned int *)0x4000f028) & 0xFFFFFFFF);
  33. cnt1 =((*(volatile unsigned int *)0x4000f028) & 0xFFFFFFFF);
  34. if(cnt1==cnt0)
  35. break;
  36. }
  37. return cnt1;
  38. }
  39. /**
  40. * @fn static void HalRtcUpdate(void)
  41. * @brief Update RTC time. this function or HalRtcGetTime(UTCTimeStruct *getTime) function should be called periodically, the periodic time < 512s, recommend 60s
  42. * @param none.
  43. * @return none
  44. */
  45. static void HalRtcUpdate(void)
  46. {
  47. uint32_t tick;
  48. uint32_t delta_time;
  49. uint32_t temp;
  50. uint32_t cnt_track;
  51. tick = get_rtc_counter();
  52. if(pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW)
  53. {
  54. delta_time = tick - rtcCtl.lastTicks;
  55. temp = ((((delta_time &0xffff0000)>>16)*rtc_cnt_track)<<8)
  56. +(((delta_time &0xffff)*rtc_cnt_track)>>8);
  57. rtcCtl.prevUpdateTicks = temp;
  58. if(temp > UPDATA_TICK)//5min
  59. {
  60. cnt_track = *(volatile uint32_t *)0x4000f064 & 0x1ffff;
  61. rtc_cnt_track = (cnt_track>CRY32_16_CYCLE_16MHZ_CYCLE_MAX || cnt_track<CRY32_16_CYCLE_16MHZ_CYCLE_MIN)
  62. ? rtc_cnt_track : cnt_track;
  63. rtcCtl.lastTicks = tick;
  64. rtcCtl.prevUpdateBase += temp;
  65. rtcCtl.prevUpdateTicks = 0;
  66. }
  67. RTC_TIMEBASE = rtcCtl.prevUpdateBase+rtcCtl.prevUpdateTicks;
  68. }
  69. else
  70. {
  71. if(tick < rtcCtl.prevUpdateTicks)
  72. {
  73. if( ((uint32_t)(tick-rtcCtl.prevUpdateTicks)) < RTC_COUNT_OF_12HOUR_1MIN )
  74. {
  75. rtcCtl.prevUpdateBase += RTC_CNT_RANGE;
  76. }
  77. }
  78. rtcCtl.prevUpdateTicks = tick;
  79. RTC_TIMEBASE = rtcCtl.prevUpdateBase;
  80. }
  81. // LOG("track:%x\r\n", rtc_cnt_track);
  82. // LOG("base:%x%08x\r\n", (uint32)((uint64_t)rtcCtl.prevUpdateBase>>32), ((uint32)rtcCtl.prevUpdateBase&0xFFFFFFFF));
  83. // LOG("tick:%x,last:%x\r\n", tick, rtcCtl.lastTicks);
  84. // LOG("prev:%x\r\n", rtcCtl.prevUpdateTicks);
  85. // LOG("%d\r\n", tick);
  86. }
  87. /**
  88. * @fn void HalRtcGetTime(UTCTimeStruct *getTime)
  89. * @brief Get RTC time. this function or HalRtcUpdate(void) function should be called periodically, the periodic time < 512s, recommend 60s
  90. * @param getTime: current time output value.
  91. * @return none
  92. */
  93. void HalRtcGetTime(UTCTimeStruct *getTime)
  94. {
  95. uint64_t tickSum;
  96. uint32_t time;
  97. HalRtcUpdate();
  98. tickSum = rtcCtl.prevUpdateTicks + rtcCtl.prevUpdateBase;
  99. time = tickSum/tick_unit;
  100. osal_ConvertUTCTime(getTime, time);
  101. }
  102. /**
  103. * @fn void HalRtcSetTime(UTCTimeStruct *setTime)
  104. * @brief Set RTC time.
  105. * @param setTime: time set value.
  106. * @return none
  107. */
  108. void HalRtcSetTime(UTCTimeStruct *setTime)
  109. {
  110. rtcCtl.prevUpdateBase = (uint64_t)osal_ConvertUTCSecs(setTime)*tick_unit;
  111. if(pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW)
  112. {
  113. rtcCtl.prevUpdateTicks = 0;
  114. rtcCtl.lastTicks = get_rtc_counter();
  115. }
  116. else
  117. {
  118. rtcCtl.prevUpdateTicks = get_rtc_counter();
  119. }
  120. rtcCtl.prevUpdateBase -= rtcCtl.prevUpdateTicks;
  121. REG_RTC_CC2 = 0xAA55AA;
  122. RTC_TIMEBASE = rtcCtl.prevUpdateBase;
  123. }
  124. /**
  125. * @fn UTCTime HalRtcGet_Utc(void)
  126. * @brief Get RTC time. this function or HalRtcUpdate(void) function should be called periodically, the periodic time < 512s, recommend 60s
  127. * @param getTime: current time output value.
  128. * @return none
  129. */
  130. UTCTime HalRtcGet_Utc(void)
  131. {
  132. uint64_t tickSum;
  133. uint32_t time;
  134. HalRtcUpdate();
  135. tickSum = rtcCtl.prevUpdateTicks + rtcCtl.prevUpdateBase;
  136. time = tickSum/tick_unit+UTC_START_TIME;
  137. return time;
  138. }
  139. /**
  140. * @fn void HalRtcSet_Utc(UTCTime utc)
  141. * @brief Set RTC time.
  142. * @param setTime: time set value.
  143. * @return none
  144. */
  145. void HalRtcSet_Utc(UTCTime utc)
  146. {
  147. rtcCtl.prevUpdateBase = (uint64_t)(utc-UTC_START_TIME)*tick_unit;
  148. if(pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW)
  149. {
  150. rtcCtl.prevUpdateTicks = 0;
  151. rtcCtl.lastTicks = get_rtc_counter();
  152. }
  153. else
  154. {
  155. rtcCtl.prevUpdateTicks = get_rtc_counter();
  156. }
  157. rtcCtl.prevUpdateBase -= rtcCtl.prevUpdateTicks;
  158. REG_RTC_CC2 = 0xAA55AA;
  159. RTC_TIMEBASE = rtcCtl.prevUpdateBase;
  160. }
  161. void __attribute__((used)) HalRtcIRQHandler(void)
  162. {
  163. if(pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW)
  164. {
  165. *(volatile uint32_t *) 0x4000f030 = (get_rtc_counter() + RTC_COUNT_OF_5MIN)&0xFFFFFFFF;
  166. }
  167. else
  168. {
  169. *(volatile uint32_t *) 0x4000f030 = (get_rtc_counter() + RTC_COUNT_OF_12HOUR)&0xFFFFFFFF;
  170. }
  171. HalRtcUpdate();
  172. }
  173. void HalRtcWakeupHandler(void)
  174. {
  175. NVIC_EnableIRQ((IRQn_Type)RTC_IRQn);
  176. HalRtcUpdate();
  177. }
  178. /**
  179. * @fn void HalRtcInit(void)
  180. * @brief RTC Init.
  181. * @param none.
  182. * @return none.
  183. */
  184. void HalRtcInit(void)
  185. {
  186. uint32_t rtcValue;
  187. UTCTimeStruct setTime;
  188. if(pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW)
  189. {
  190. tick_unit = US_OF_S;
  191. }
  192. else
  193. {
  194. tick_unit = RTC_CLK_FREQ;
  195. }
  196. rtcValue = REG_RTC_CC2 & 0xffffff;
  197. LOG("rtcValue:%04x\r\n",rtcValue);
  198. if(rtcValue != 0xAA55AA)//RTC don't be initized, init RTC
  199. {
  200. //set time:2019.1.1 00:00:00
  201. setTime.year = 2019;
  202. setTime.month = 0;
  203. setTime.day = 0;
  204. setTime.hour = 0;
  205. setTime.minutes = 0;
  206. setTime.seconds = 0;
  207. HalRtcSetTime(&setTime);
  208. LOG("InitTime:%d/%d/%d %d:%d:%d\r\n", setTime.year,setTime.month+1,setTime.day+1,setTime.hour,setTime.minutes,setTime.seconds);
  209. }
  210. else//system reset
  211. {
  212. rtcCtl.lastTicks = get_rtc_counter();
  213. rtcCtl.prevUpdateTicks = get_rtc_counter();
  214. rtcCtl.prevUpdateBase = RTC_TIMEBASE;
  215. HalRtcGetTime(&setTime);
  216. LOG("recover:%d/%d/%d %d:%d:%d\r\n", setTime.year,setTime.month+1,setTime.day+1,setTime.hour,setTime.minutes,setTime.seconds);
  217. }
  218. rtc_cnt_track = *(volatile uint32_t *)0x4000f064 & 0x1ffff;
  219. rtc_cnt_track = (rtc_cnt_track>CRY32_16_CYCLE_16MHZ_CYCLE_MAX || rtc_cnt_track<CRY32_16_CYCLE_16MHZ_CYCLE_MIN)
  220. ? STD_RC32_16_CYCLE_16MHZ_CYCLE : rtc_cnt_track;
  221. if(pGlobal_config[LL_SWITCH] & RC32_TRACKINK_ALLOW)
  222. {
  223. *(volatile uint32_t *) 0x4000f030 = (get_rtc_counter() + RTC_COUNT_OF_5MIN)&0xFFFFFFFF;
  224. }
  225. else
  226. {
  227. *(volatile uint32_t *) 0x4000f030 = (get_rtc_counter() + RTC_COUNT_OF_12HOUR)&0xFFFFFFFF;
  228. }
  229. JUMP_FUNCTION(RTC_IRQ_HANDLER) = (uint32_t)&HalRtcIRQHandler;
  230. *(volatile uint32_t *) 0x4000f024 |= BIT(16)|BIT(21);
  231. NVIC_SetPriority((IRQn_Type)RTC_IRQn, IRQ_PRIO_HAL);
  232. NVIC_EnableIRQ((IRQn_Type)RTC_IRQn);
  233. hal_pwrmgr_register(MOD_RTC, NULL, HalRtcWakeupHandler);
  234. }