rtc.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #include "rtc.h"
  2. #include "lwip/apps/sntp.h"
  3. #include "settings_api.h"
  4. #include <string.h>
  5. //TM_RTC_t calendar;
  6. /* Days in a month */
  7. uint8_t TM_RTC_Months[2][12] = {
  8. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Not leap year */
  9. {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} /* Leap year */
  10. };
  11. // monthly correction data sheet
  12. const uint8_t table_week[12] = {0, 3, 3, 6, 1, 4, 6, 2, 5, 0, 3, 5};
  13. // monmonth data table of common year
  14. const uint8_t mon_table[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  15. /* Internal RTC defines */
  16. #define TM_RTC_LEAP_YEAR(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
  17. #define TM_RTC_DAYS_IN_YEAR(x) TM_RTC_LEAP_YEAR(x) ? 366 : 365
  18. #define TM_RTC_OFFSET_YEAR 1970
  19. #define TM_RTC_SECONDS_PER_DAY 86400
  20. #define TM_RTC_SECONDS_PER_HOUR 3600
  21. #define TM_RTC_SECONDS_PER_MINUTE 60
  22. #define TM_RTC_BCD2BIN(x) ((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
  23. #define TM_RTC_CHAR2NUM(x) ((x) - '0')
  24. #define TM_RTC_CHARISNUM(x) ((x) >= '0' && (x) <= '9')
  25. extern SemaphoreHandle_t flash_mutex;
  26. /**
  27. * @brief rtc peripheral initialization.
  28. * @param calendar
  29. * @retval 0: rtc already init
  30. 1: rtc init
  31. */
  32. uint8_t TM_RTC_Init(void)
  33. {
  34. TM_RTC_t datatime;
  35. // enable pwc and bpr clocks
  36. crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
  37. crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
  38. // enable the battery-powered domain write operations
  39. pwc_battery_powered_domain_access(TRUE);
  40. // check if rtc is initialized
  41. if (bpr_data_read(BPR_DATA4) != 0x1234)
  42. {
  43. // reset battery-powered domain register
  44. bpr_reset();
  45. // enable the lext osc
  46. crm_clock_source_enable(CRM_CLOCK_SOURCE_LEXT, TRUE);
  47. // wait lext is ready
  48. while(crm_flag_get(CRM_LEXT_STABLE_FLAG) == RESET);
  49. // select the rtc clock source
  50. crm_rtc_clock_select(CRM_RTC_CLOCK_LEXT);
  51. // enable rtc clock
  52. crm_rtc_clock_enable(TRUE);
  53. // wait for rtc registers update
  54. rtc_wait_update_finish();
  55. // wait for the register write to complete
  56. rtc_wait_config_finish();
  57. // set rtc divider: set rtc period to 1sec
  58. rtc_divider_set(32767);
  59. // wait for the register write to complete
  60. rtc_wait_config_finish();
  61. // set date and time
  62. datatime.date = 1;
  63. datatime.day = 1;
  64. datatime.month = 1;
  65. datatime.year = 0;
  66. datatime.hours = 0;
  67. datatime.minutes = 0;
  68. datatime.seconds = 0;
  69. TM_RTC_SetDateTime(&datatime);
  70. // writes data to bpr register
  71. bpr_data_write(BPR_DATA4, 0x1234);
  72. return 1;
  73. }
  74. else
  75. {
  76. // wait for rtc registers update
  77. rtc_wait_update_finish();
  78. // wait for the register write to complete
  79. rtc_wait_config_finish();
  80. return 0;
  81. }
  82. }
  83. //
  84. void TM_RTC_SetDataTimeUnix(uint32_t unixTime)
  85. {
  86. TM_RTC_t data;
  87. TM_RTC_GetDateTimeFromUnix(&data, unixTime);
  88. rtc_counter_set(unixTime);
  89. rtc_wait_config_finish();
  90. }
  91. /**
  92. * @brief set time. convert the input clock to a second.
  93. * the time basic : 1970.1.1
  94. * legitimate year: 1970 ~ 2099
  95. * @param calendar
  96. * @retval 0: set time right.
  97. * 1: set time failed.
  98. */
  99. TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data)
  100. {
  101. uint32_t seccount = 0;
  102. if (data->year > 99 ||
  103. data->month == 0 ||
  104. data->month > 12 ||
  105. data->date == 0 ||
  106. data->date > TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + data->year) ? 1 : 0][data->month - 1] ||
  107. data->hours > 23 ||
  108. data->minutes > 59 ||
  109. data->seconds > 59 ||
  110. data->day == 0 ||
  111. data->day > 7)
  112. {
  113. return TM_RTC_Result_Error;
  114. }
  115. // enable pwc and bpr clocks
  116. crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
  117. crm_periph_clock_enable(CRM_BPR_PERIPH_CLOCK, TRUE);
  118. // enable write access to bpr domain
  119. pwc_battery_powered_domain_access(TRUE);
  120. // set the rtc counter value
  121. seccount = TM_RTC_GetUnixTimeStamp(data);
  122. rtc_counter_set(seccount);
  123. // wait for the register write to complete
  124. rtc_wait_config_finish();
  125. return TM_RTC_Result_Ok;
  126. }
  127. //
  128. TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str)
  129. {
  130. TM_RTC_t tmp;
  131. uint8_t i = 0;
  132. // Get date
  133. tmp.date = 0;
  134. while (TM_RTC_CHARISNUM(*(str + i))) {
  135. tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
  136. i++;
  137. }
  138. i++;
  139. // Get month
  140. tmp.month = 0;
  141. while (TM_RTC_CHARISNUM(*(str + i))) {
  142. tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
  143. i++;
  144. }
  145. i++;
  146. // Get year
  147. tmp.year = 0;
  148. while (TM_RTC_CHARISNUM(*(str + i))) {
  149. tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
  150. i++;
  151. }
  152. i++;
  153. // Get day in a week
  154. tmp.day = 0;
  155. while (TM_RTC_CHARISNUM(*(str + i))) {
  156. tmp.day = tmp.day * 10 + TM_RTC_CHAR2NUM(*(str + i));
  157. i++;
  158. }
  159. i++;
  160. // Get hours
  161. tmp.hours = 0;
  162. while (TM_RTC_CHARISNUM(*(str + i))) {
  163. tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
  164. i++;
  165. }
  166. i++;
  167. // Get minutes
  168. tmp.minutes = 0;
  169. while (TM_RTC_CHARISNUM(*(str + i))) {
  170. tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
  171. i++;
  172. }
  173. i++;
  174. // Get seconds
  175. tmp.seconds = 0;
  176. while (TM_RTC_CHARISNUM(*(str + i))) {
  177. tmp.seconds = tmp.seconds * 10 + TM_RTC_CHAR2NUM(*(str + i));
  178. i++;
  179. }
  180. i++;
  181. // Return status from set date time function
  182. return TM_RTC_SetDateTime(&tmp);
  183. }
  184. //
  185. void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format)
  186. {
  187. (void)format;
  188. uint32_t unix = rtc_counter_get();
  189. TM_RTC_GetDateTimeFromUnix(data, unix);
  190. }
  191. //
  192. uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data)
  193. {
  194. uint32_t days = 0, seconds = 0;
  195. uint16_t i;
  196. uint16_t year = (uint16_t)(data->year + 2000);
  197. // Year is below offset year
  198. if (year < TM_RTC_OFFSET_YEAR) {
  199. return 0;
  200. }
  201. // Days in back years
  202. for (i = TM_RTC_OFFSET_YEAR; i < year; i++) {
  203. days += TM_RTC_DAYS_IN_YEAR(i);
  204. }
  205. // Days in current year
  206. for (i = 1; i < data->month; i++) {
  207. days += TM_RTC_Months[TM_RTC_LEAP_YEAR(year)][i - 1];
  208. }
  209. // Day starts with 1
  210. days += data->date - 1;
  211. seconds = days * TM_RTC_SECONDS_PER_DAY;
  212. seconds += data->hours * TM_RTC_SECONDS_PER_HOUR;
  213. seconds += data->minutes * TM_RTC_SECONDS_PER_MINUTE;
  214. seconds += data->seconds;
  215. // seconds = days * 86400;
  216. return seconds;
  217. }
  218. //
  219. void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix)
  220. {
  221. uint16_t year;
  222. // Store unix time to unix in struct
  223. data->unix = unix;
  224. // Get seconds from unix
  225. data->seconds = unix % 60;
  226. // Go to minutes
  227. unix /= 60;
  228. // Get minutes
  229. data->minutes = unix % 60;
  230. // Go to hours
  231. unix /= 60;
  232. // Get hours
  233. data->hours = unix % 24;
  234. // Go to days
  235. unix /= 24;
  236. // Get week day
  237. // Monday is day one
  238. data->day = (unix + 3) % 7 + 1;
  239. // Get year
  240. year = 1970;
  241. while (1) {
  242. if (TM_RTC_LEAP_YEAR(year)) {
  243. if (unix >= 366) {
  244. unix -= 366;
  245. } else {
  246. break;
  247. }
  248. } else if (unix >= 365) {
  249. unix -= 365;
  250. } else {
  251. break;
  252. }
  253. year++;
  254. }
  255. // Get year in xx format
  256. data->year = (uint8_t) (year - 2000);
  257. // Get month
  258. for (data->month = 0; data->month < 12; data->month++) {
  259. if (TM_RTC_LEAP_YEAR(year) && unix >= (uint32_t)TM_RTC_Months[1][data->month]) {
  260. unix -= TM_RTC_Months[1][data->month];
  261. } else if (unix >= (uint32_t)TM_RTC_Months[0][data->month]) {
  262. unix -= TM_RTC_Months[0][data->month];
  263. } else {
  264. break;
  265. }
  266. }
  267. // Get month
  268. // Month starts with 1
  269. data->month++;
  270. // Get date
  271. // Date starts with 1
  272. data->date = unix + 1;
  273. }
  274. //
  275. void TM_RTC_PrintTime(void)
  276. {
  277. TM_RTC_t data;
  278. uint32_t unix = rtc_counter_get();
  279. TM_RTC_GetDateTimeFromUnix(&data, unix);
  280. printf("%02d.%02d.%02d %02d:%02d:%02d\r\n", data.date, data.month, data.year,
  281. data.hours, data.minutes, data.seconds);
  282. }
  283. //
  284. uint32_t RTC_GetUnixTime(void)
  285. {
  286. TM_RTC_t currentTime;
  287. TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
  288. return TM_RTC_GetUnixTimeStamp(&currentTime);
  289. }
  290. #if 0
  291. //
  292. void sntp_config(void)
  293. {
  294. sntp_setoperatingmode(SNTP_OPMODE_POLL);
  295. sntp_setservername(0, sSettings.sSNTP.ip1);
  296. sntp_setservername(1, sSettings.sSNTP.ip2);
  297. sntp_init();
  298. }
  299. //
  300. void lwip_time_sinhro(uint32_t utime)
  301. {
  302. printf("SNTP: sinhro hook: %u\n\r", utime);
  303. utime += 3600*(int)sSettings.sSNTP.timeZone;
  304. TM_RTC_SetDataTimeUnix(utime);
  305. }
  306. #endif