rtc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839
  1. /* Copyright 2018 Canaan Inc.
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. #include <stdint.h>
  16. #include <stdlib.h>
  17. #include <time.h>
  18. #include "encoding.h"
  19. #include "printf.h"
  20. #include "rtc.h"
  21. #include "sysctl.h"
  22. volatile rtc_t *const rtc = (volatile rtc_t *)RTC_BASE_ADDR;
  23. struct tm rtc_timer_date_time;
  24. struct tm rtc_alarm_date_time;
  25. typedef struct _rtc_instance_t
  26. {
  27. plic_irq_callback_t rtc_tick_callback;
  28. void *tick_ctx;
  29. plic_irq_callback_t rtc_alarm_callback;
  30. void *alarm_ctx;
  31. bool tick_is_single_shot;
  32. bool alarm_is_single_shot;
  33. bool tick_enable_by_alarm;
  34. bool tick_enable_by_user;
  35. rtc_tick_interrupt_mode_t tick_mode_by_user;
  36. rtc_tick_interrupt_mode_t tick_mode_by_alarm;
  37. } rtc_instance_t;
  38. rtc_instance_t rtc_instance = (rtc_instance_t){
  39. .tick_mode_by_user = -1,
  40. .tick_mode_by_alarm = RTC_INT_MAX,
  41. };
  42. int rtc_timer_set_mode(rtc_timer_mode_t timer_mode)
  43. {
  44. rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
  45. switch(timer_mode)
  46. {
  47. case RTC_TIMER_PAUSE:
  48. register_ctrl.read_enable = 0;
  49. register_ctrl.write_enable = 0;
  50. break;
  51. case RTC_TIMER_RUNNING:
  52. register_ctrl.read_enable = 1;
  53. register_ctrl.write_enable = 0;
  54. break;
  55. case RTC_TIMER_SETTING:
  56. register_ctrl.read_enable = 0;
  57. register_ctrl.write_enable = 1;
  58. break;
  59. default:
  60. register_ctrl.read_enable = 0;
  61. register_ctrl.write_enable = 0;
  62. break;
  63. }
  64. /* Get CPU current freq */
  65. unsigned long freq = sysctl_clock_get_freq(SYSCTL_CLOCK_CPU);
  66. /* Set threshold to 1/26000000 s */
  67. freq = freq / 26000000;
  68. /* Get current CPU cycle */
  69. unsigned long start_cycle = read_csr(mcycle);
  70. /* Wait for 1/26000000 s to sync data */
  71. while(read_csr(mcycle) - start_cycle < freq)
  72. continue;
  73. rtc->register_ctrl = register_ctrl;
  74. return 0;
  75. }
  76. rtc_timer_mode_t rtc_timer_get_mode(void)
  77. {
  78. rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
  79. rtc_timer_mode_t timer_mode = RTC_TIMER_PAUSE;
  80. if((!register_ctrl.read_enable) && (!register_ctrl.write_enable))
  81. {
  82. /* RTC_TIMER_PAUSE */
  83. timer_mode = RTC_TIMER_PAUSE;
  84. } else if((register_ctrl.read_enable) && (!register_ctrl.write_enable))
  85. {
  86. /* RTC_TIMER_RUNNING */
  87. timer_mode = RTC_TIMER_RUNNING;
  88. } else if((!register_ctrl.read_enable) && (register_ctrl.write_enable))
  89. {
  90. /* RTC_TIMER_SETTING */
  91. timer_mode = RTC_TIMER_RUNNING;
  92. } else
  93. {
  94. /* Something is error, reset timer mode */
  95. rtc_timer_set_mode(timer_mode);
  96. }
  97. return timer_mode;
  98. }
  99. static inline int rtc_in_range(int value, int min, int max)
  100. {
  101. return ((value >= min) && (value <= max));
  102. }
  103. int rtc_timer_set_tm(const struct tm *tm)
  104. {
  105. rtc_date_t timer_date;
  106. rtc_time_t timer_time;
  107. rtc_extended_t timer_extended;
  108. if(tm)
  109. {
  110. /*
  111. * Range of tm->tm_sec could be [0,61]
  112. *
  113. * Range of tm->tm_sec allows for a positive leap second. Two
  114. * leap seconds in the same minute are not allowed (the C90
  115. * range 0..61 was a defect)
  116. */
  117. if(rtc_in_range(tm->tm_sec, 0, 59))
  118. timer_time.second = tm->tm_sec;
  119. else
  120. return -1;
  121. /* Range of tm->tm_min could be [0,59] */
  122. if(rtc_in_range(tm->tm_min, 0, 59))
  123. timer_time.minute = tm->tm_min;
  124. else
  125. return -1;
  126. /* Range of tm->tm_hour could be [0, 23] */
  127. if(rtc_in_range(tm->tm_hour, 0, 23))
  128. timer_time.hour = tm->tm_hour;
  129. else
  130. return -1;
  131. /* Range of tm->tm_mday could be [1, 31] */
  132. if(rtc_in_range(tm->tm_mday, 1, 31))
  133. timer_date.day = tm->tm_mday;
  134. else
  135. return -1;
  136. /*
  137. * Range of tm->tm_mon could be [0, 11]
  138. * But in this RTC, date.month should be [1, 12]
  139. */
  140. if(rtc_in_range(tm->tm_mon, 0, 11))
  141. timer_date.month = tm->tm_mon + 1;
  142. else
  143. return -1;
  144. /*
  145. * Range of tm->tm_year is the years since 1900
  146. * But in this RTC, year is split into year and century
  147. * In this RTC, century range is [0,31], year range is [0,99]
  148. */
  149. int human_year = tm->tm_year + 1900;
  150. int rtc_year = human_year % 100;
  151. int rtc_century = human_year / 100;
  152. if(rtc_in_range(rtc_year, 0, 99) &&
  153. rtc_in_range(rtc_century, 0, 31))
  154. {
  155. timer_date.year = rtc_year;
  156. timer_extended.century = rtc_century;
  157. } else
  158. return -1;
  159. /* Range of tm->tm_wday could be [0, 6] */
  160. if(rtc_in_range(tm->tm_wday, 0, 6))
  161. timer_date.week = tm->tm_wday;
  162. else
  163. return -1;
  164. /* Set RTC mode to timer setting mode */
  165. rtc_timer_set_mode(RTC_TIMER_SETTING);
  166. /* Write value to RTC */
  167. rtc->date = timer_date;
  168. rtc->time = timer_time;
  169. rtc->extended = timer_extended;
  170. /* Set RTC mode to timer running mode */
  171. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  172. }
  173. return 0;
  174. }
  175. int rtc_alarm_set_tm(const struct tm *tm)
  176. {
  177. rtc_alarm_date_t alarm_date;
  178. rtc_alarm_time_t alarm_time;
  179. if(tm)
  180. {
  181. /*
  182. * Range of tm->tm_sec could be [0,61]
  183. *
  184. * Range of tm->tm_sec allows for a positive leap second. Two
  185. * leap seconds in the same minute are not allowed (the C90
  186. * range 0..61 was a defect)
  187. */
  188. if(rtc_in_range(tm->tm_sec, 0, 59))
  189. alarm_time.second = tm->tm_sec;
  190. else
  191. return -1;
  192. /* Range of tm->tm_min could be [0,59] */
  193. if(rtc_in_range(tm->tm_min, 0, 59))
  194. alarm_time.minute = tm->tm_min;
  195. else
  196. return -1;
  197. /* Range of tm->tm_hour could be [0, 23] */
  198. if(rtc_in_range(tm->tm_hour, 0, 23))
  199. alarm_time.hour = tm->tm_hour;
  200. else
  201. return -1;
  202. /* Range of tm->tm_mday could be [1, 31] */
  203. if(rtc_in_range(tm->tm_mday, 1, 31))
  204. alarm_date.day = tm->tm_mday;
  205. else
  206. return -1;
  207. /*
  208. * Range of tm->tm_mon could be [0, 11]
  209. * But in this RTC, date.month should be [1, 12]
  210. */
  211. if(rtc_in_range(tm->tm_mon, 0, 11))
  212. alarm_date.month = tm->tm_mon + 1;
  213. else
  214. return -1;
  215. /*
  216. * Range of tm->tm_year is the years since 1900
  217. * But in this RTC, year is split into year and century
  218. * In this RTC, century range is [0,31], year range is [0,99]
  219. */
  220. int human_year = tm->tm_year + 1900;
  221. int rtc_year = human_year % 100;
  222. int rtc_century = human_year / 100;
  223. if(rtc_in_range(rtc_year, 0, 99) &&
  224. rtc_in_range(rtc_century, 0, 31))
  225. {
  226. alarm_date.year = rtc_year;
  227. } else
  228. return -1;
  229. /* Range of tm->tm_wday could be [0, 6] */
  230. if(rtc_in_range(tm->tm_wday, 0, 6))
  231. alarm_date.week = tm->tm_wday;
  232. else
  233. return -1;
  234. /* Set RTC mode to timer setting mode */
  235. rtc_timer_set_mode(RTC_TIMER_SETTING);
  236. /* Write value to RTC */
  237. rtc->alarm_date = alarm_date;
  238. rtc->alarm_time = alarm_time;
  239. /* Set RTC mode to timer running mode */
  240. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  241. }
  242. return 0;
  243. }
  244. int rtc_year_is_leap(int year)
  245. {
  246. return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
  247. }
  248. int rtc_get_yday(int year, int month, int day)
  249. {
  250. static const int days[2][13] = {
  251. {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
  252. {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335}};
  253. int leap = rtc_year_is_leap(year);
  254. return days[leap][month] + day;
  255. }
  256. int rtc_get_wday(int year, int month, int day)
  257. {
  258. /* Magic method to get weekday */
  259. int weekday = (day += month < 3 ? year-- : year - 2, 23 * month / 9 + day + 4 + year / 4 - year / 100 + year / 400) % 7;
  260. return weekday;
  261. }
  262. struct tm *rtc_timer_get_tm(void)
  263. {
  264. if(rtc_timer_get_mode() != RTC_TIMER_RUNNING)
  265. return NULL;
  266. rtc_date_t timer_date = rtc->date;
  267. rtc_time_t timer_time = rtc->time;
  268. rtc_extended_t timer_extended = rtc->extended;
  269. struct tm *tm = &rtc_timer_date_time;
  270. tm->tm_sec = timer_time.second % 61; /* 0-60, follow C99 */
  271. tm->tm_min = timer_time.minute % 60; /* 0-59 */
  272. tm->tm_hour = timer_time.hour % 24; /* 0-23 */
  273. tm->tm_mday = timer_date.day % 32; /* 1-31 */
  274. tm->tm_mon = (timer_date.month - 1) % 12; /* 0-11 */
  275. tm->tm_year = (timer_date.year % 100) + (timer_extended.century * 100) - 1900;
  276. tm->tm_wday = timer_date.week % 7; /* 0-6 */
  277. tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday) % 366; /* 0-365 */
  278. tm->tm_isdst = -1;
  279. return tm;
  280. }
  281. struct tm *rtc_alarm_get_tm(void)
  282. {
  283. if(rtc_timer_get_mode() != RTC_TIMER_RUNNING)
  284. return NULL;
  285. rtc_alarm_date_t alarm_date = rtc->alarm_date;
  286. rtc_alarm_time_t alarm_time = rtc->alarm_time;
  287. rtc_extended_t timer_extended = rtc->extended;
  288. struct tm *tm = &rtc_alarm_date_time;
  289. tm->tm_sec = alarm_time.second % 61; /* 0-60, follow C99 */
  290. tm->tm_min = alarm_time.minute % 60; /* 0-59 */
  291. tm->tm_hour = alarm_time.hour % 24; /* 0-23 */
  292. tm->tm_mday = alarm_date.day % 32; /* 1-31 */
  293. tm->tm_mon = (alarm_date.month - 1) % 12; /* 0-11 */
  294. tm->tm_year = (alarm_date.year % 100) + (timer_extended.century * 100) - 1900;
  295. tm->tm_wday = alarm_date.week % 7; /* 0-6 */
  296. tm->tm_yday = rtc_get_yday(tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday) % 366; /* 0-365 */
  297. tm->tm_isdst = -1;
  298. return tm;
  299. }
  300. int rtc_timer_set(int year, int month, int day, int hour, int minute, int second)
  301. {
  302. struct tm date_time = {
  303. .tm_sec = second,
  304. .tm_min = minute,
  305. .tm_hour = hour,
  306. .tm_mday = day,
  307. .tm_mon = month - 1,
  308. .tm_year = year - 1900,
  309. .tm_wday = rtc_get_wday(year, month, day),
  310. .tm_yday = rtc_get_yday(year, month, day),
  311. .tm_isdst = -1,
  312. };
  313. return rtc_timer_set_tm(&date_time);
  314. }
  315. int rtc_timer_get(int *year, int *month, int *day, int *hour, int *minute, int *second)
  316. {
  317. struct tm *tm = rtc_timer_get_tm();
  318. if(tm)
  319. {
  320. if(year)
  321. *year = tm->tm_year + 1900;
  322. if(month)
  323. *month = tm->tm_mon + 1;
  324. if(day)
  325. *day = tm->tm_mday;
  326. if(hour)
  327. *hour = tm->tm_hour;
  328. if(minute)
  329. *minute = tm->tm_min;
  330. if(second)
  331. *second = tm->tm_sec;
  332. } else
  333. return -1;
  334. return 0;
  335. }
  336. int rtc_alarm_set(int year, int month, int day, int hour, int minute, int second)
  337. {
  338. struct tm date_time = {
  339. .tm_sec = second,
  340. .tm_min = minute,
  341. .tm_hour = hour,
  342. .tm_mday = day,
  343. .tm_mon = month - 1,
  344. .tm_year = year - 1900,
  345. .tm_wday = rtc_get_wday(year, month, day),
  346. .tm_yday = rtc_get_yday(year, month, day),
  347. .tm_isdst = -1,
  348. };
  349. return rtc_alarm_set_tm(&date_time);
  350. }
  351. int rtc_alarm_get(int *year, int *month, int *day, int *hour, int *minute, int *second)
  352. {
  353. struct tm *tm = rtc_alarm_get_tm();
  354. if(tm)
  355. {
  356. if(year)
  357. *year = tm->tm_year + 1900;
  358. if(month)
  359. *month = tm->tm_mon + 1;
  360. if(day)
  361. *day = tm->tm_mday;
  362. if(hour)
  363. *hour = tm->tm_hour;
  364. if(minute)
  365. *minute = tm->tm_min;
  366. if(second)
  367. *second = tm->tm_sec;
  368. } else
  369. return -1;
  370. return 0;
  371. }
  372. int rtc_timer_set_clock_frequency(unsigned int frequency)
  373. {
  374. rtc_initial_count_t initial_count;
  375. initial_count.count = frequency;
  376. /* Set RTC mode to timer setting mode */
  377. rtc_timer_set_mode(RTC_TIMER_SETTING);
  378. rtc->initial_count = initial_count;
  379. /* Set RTC mode to timer running mode */
  380. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  381. return 0;
  382. }
  383. unsigned int rtc_timer_get_clock_frequency(void)
  384. {
  385. return rtc->initial_count.count;
  386. }
  387. int rtc_timer_set_clock_count_value(unsigned int count)
  388. {
  389. rtc_current_count_t current_count;
  390. current_count.count = count;
  391. /* Set RTC mode to timer setting mode */
  392. rtc_timer_set_mode(RTC_TIMER_SETTING);
  393. rtc->current_count = current_count;
  394. /* Set RTC mode to timer running mode */
  395. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  396. return 0;
  397. }
  398. unsigned int rtc_timer_get_clock_count_value(void)
  399. {
  400. return rtc->current_count.count;
  401. }
  402. int rtc_tick_set_interrupt(int enable)
  403. {
  404. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  405. interrupt_ctrl.tick_enable = enable;
  406. /* Set RTC mode to timer setting mode */
  407. rtc_timer_set_mode(RTC_TIMER_SETTING);
  408. rtc->interrupt_ctrl = interrupt_ctrl;
  409. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  410. return 0;
  411. }
  412. int rtc_tick_get_interrupt(void)
  413. {
  414. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  415. return interrupt_ctrl.tick_enable;
  416. }
  417. int rtc_tick_set_interrupt_mode(rtc_tick_interrupt_mode_t mode)
  418. {
  419. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  420. interrupt_ctrl.tick_int_mode = mode;
  421. /* Set RTC mode to timer setting mode */
  422. rtc_timer_set_mode(RTC_TIMER_SETTING);
  423. rtc->interrupt_ctrl = interrupt_ctrl;
  424. /* Set RTC mode to timer running mode */
  425. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  426. return 0;
  427. }
  428. rtc_tick_interrupt_mode_t rtc_tick_get_interrupt_mode(void)
  429. {
  430. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  431. return interrupt_ctrl.tick_int_mode;
  432. }
  433. int rtc_alarm_set_interrupt(int enable)
  434. {
  435. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  436. interrupt_ctrl.alarm_enable = enable;
  437. /* Set RTC mode to timer setting mode */
  438. rtc_timer_set_mode(RTC_TIMER_SETTING);
  439. rtc->interrupt_ctrl = interrupt_ctrl;
  440. /* Set RTC mode to timer running mode */
  441. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  442. return 0;
  443. }
  444. int rtc_alarm_get_interrupt(void)
  445. {
  446. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  447. return interrupt_ctrl.alarm_enable;
  448. }
  449. int rtc_alarm_set_mask(rtc_mask_t mask)
  450. {
  451. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  452. interrupt_ctrl.alarm_compare_mask = *(uint8_t *)&mask;
  453. /* Set RTC mode to timer setting mode */
  454. rtc_timer_set_mode(RTC_TIMER_SETTING);
  455. rtc->interrupt_ctrl = interrupt_ctrl;
  456. /* Set RTC mode to timer running mode */
  457. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  458. return 0;
  459. }
  460. rtc_mask_t rtc_alarm_get_mask(void)
  461. {
  462. rtc_interrupt_ctrl_t interrupt_ctrl = rtc->interrupt_ctrl;
  463. uint8_t compare_mask = interrupt_ctrl.alarm_compare_mask;
  464. return *(rtc_mask_t *)&compare_mask;
  465. }
  466. int rtc_protect_set(int enable)
  467. {
  468. rtc_register_ctrl_t register_ctrl = rtc->register_ctrl;
  469. rtc_mask_t mask = {
  470. .second = 1, /* Second mask */
  471. .minute = 1, /* Minute mask */
  472. .hour = 1, /* Hour mask */
  473. .week = 1, /* Week mask */
  474. .day = 1, /* Day mask */
  475. .month = 1, /* Month mask */
  476. .year = 1, /* Year mask */
  477. };
  478. rtc_mask_t unmask = {
  479. .second = 0, /* Second mask */
  480. .minute = 0, /* Minute mask */
  481. .hour = 0, /* Hour mask */
  482. .week = 0, /* Week mask */
  483. .day = 0, /* Day mask */
  484. .month = 0, /* Month mask */
  485. .year = 0, /* Year mask */
  486. };
  487. if(enable)
  488. {
  489. /* Turn RTC in protect mode, no one can write time */
  490. register_ctrl.timer_mask = *(uint8_t *)&unmask;
  491. register_ctrl.alarm_mask = *(uint8_t *)&unmask;
  492. register_ctrl.initial_count_mask = 0;
  493. register_ctrl.interrupt_register_mask = 0;
  494. } else
  495. {
  496. /* Turn RTC in unprotect mode, everyone can write time */
  497. register_ctrl.timer_mask = *(uint8_t *)&mask;
  498. register_ctrl.alarm_mask = *(uint8_t *)&mask;
  499. register_ctrl.initial_count_mask = 1;
  500. register_ctrl.interrupt_register_mask = 1;
  501. }
  502. rtc->register_ctrl = register_ctrl;
  503. return 0;
  504. }
  505. int rtc_init(void)
  506. {
  507. /* Reset RTC */
  508. sysctl_reset(SYSCTL_RESET_RTC);
  509. /* Enable RTC */
  510. sysctl_clock_enable(SYSCTL_CLOCK_RTC);
  511. /* Unprotect RTC */
  512. rtc_protect_set(0);
  513. /* Set RTC clock frequency */
  514. rtc_timer_set_clock_frequency(
  515. sysctl_clock_get_freq(SYSCTL_CLOCK_IN0));
  516. rtc_timer_set_clock_count_value(1);
  517. /* Set RTC mode to timer running mode */
  518. rtc_timer_set_mode(RTC_TIMER_RUNNING);
  519. return 0;
  520. }
  521. int rtc_irq_callback(void *ctx)
  522. {
  523. rtc_instance_t *instance = (rtc_instance_t *)ctx;
  524. struct tm *now_tm = rtc_timer_get_tm();
  525. if(rtc_alarm_get_interrupt())
  526. {
  527. struct tm *alarm_tm = rtc_alarm_get_tm();
  528. rtc_mask_t alarm_mask = rtc_alarm_get_mask();
  529. if((*((uint8_t *)&alarm_mask) & 0xFE) == 0)
  530. {
  531. goto tick;
  532. }
  533. if(alarm_mask.year)
  534. {
  535. if(now_tm->tm_year != alarm_tm->tm_year)
  536. {
  537. goto tick;
  538. }
  539. }
  540. if(alarm_mask.month)
  541. {
  542. if(now_tm->tm_mon != alarm_tm->tm_mon)
  543. {
  544. goto tick;
  545. }
  546. }
  547. if(alarm_mask.day)
  548. {
  549. if(now_tm->tm_mday != alarm_tm->tm_mday)
  550. {
  551. goto tick;
  552. }
  553. }
  554. if(alarm_mask.hour)
  555. {
  556. if(now_tm->tm_hour != alarm_tm->tm_hour)
  557. {
  558. goto tick;
  559. }
  560. }
  561. if(alarm_mask.minute)
  562. {
  563. if(now_tm->tm_min != alarm_tm->tm_min)
  564. {
  565. goto tick;
  566. }
  567. }
  568. if(alarm_mask.second)
  569. {
  570. if(now_tm->tm_sec != alarm_tm->tm_sec)
  571. {
  572. goto tick;
  573. }
  574. }
  575. if(instance->alarm_is_single_shot)
  576. {
  577. rtc_alarm_set_interrupt(0);
  578. instance->tick_enable_by_alarm = false;
  579. instance->tick_mode_by_alarm = RTC_INT_MAX;
  580. if(instance->tick_enable_by_user)
  581. {
  582. if(instance->tick_mode_by_user > rtc_tick_get_interrupt_mode())
  583. {
  584. rtc_tick_set_interrupt(0);
  585. rtc_tick_set_interrupt_mode(instance->tick_mode_by_user);
  586. rtc_tick_set_interrupt(1);
  587. }
  588. } else
  589. {
  590. rtc_tick_set_interrupt(0);
  591. }
  592. }
  593. if(instance->rtc_alarm_callback)
  594. instance->rtc_alarm_callback(instance->alarm_ctx);
  595. }
  596. tick:
  597. if(instance->tick_enable_by_user)
  598. {
  599. switch(instance->tick_mode_by_user)
  600. {
  601. case RTC_INT_MINUTE:
  602. if(now_tm->tm_sec != 0)
  603. goto ret;
  604. break;
  605. case RTC_INT_HOUR:
  606. if(now_tm->tm_sec != 0 || now_tm->tm_min != 0)
  607. goto ret;
  608. break;
  609. case RTC_INT_DAY:
  610. if(now_tm->tm_sec != 0 || now_tm->tm_min != 0 || now_tm->tm_hour != 0)
  611. goto ret;
  612. break;
  613. case RTC_INT_SECOND:
  614. default:
  615. break;
  616. }
  617. if(instance->tick_is_single_shot)
  618. {
  619. rtc_tick_set_interrupt(0);
  620. instance->tick_enable_by_user = false;
  621. instance->tick_mode_by_user = -1;
  622. }
  623. if(instance->rtc_tick_callback)
  624. instance->rtc_tick_callback(instance->tick_ctx);
  625. }
  626. ret:
  627. return 0;
  628. }
  629. int rtc_tick_irq_register(bool is_single_shot, rtc_tick_interrupt_mode_t mode, plic_irq_callback_t callback, void *ctx, uint8_t priority)
  630. {
  631. plic_irq_disable(IRQN_RTC_INTERRUPT);
  632. rtc_tick_set_interrupt(0);
  633. rtc_instance.rtc_tick_callback = callback;
  634. rtc_instance.tick_ctx = ctx;
  635. rtc_instance.tick_is_single_shot = is_single_shot;
  636. rtc_instance.tick_enable_by_user = true;
  637. rtc_instance.tick_mode_by_user = mode;
  638. if(!rtc_instance.tick_enable_by_alarm || (rtc_instance.tick_enable_by_alarm && mode < rtc_tick_get_interrupt_mode()))
  639. {
  640. rtc_tick_set_interrupt_mode(mode);
  641. }
  642. plic_set_priority(IRQN_RTC_INTERRUPT, priority);
  643. plic_irq_register(IRQN_RTC_INTERRUPT, rtc_irq_callback, &rtc_instance);
  644. plic_irq_enable(IRQN_RTC_INTERRUPT);
  645. rtc_tick_set_interrupt(1);
  646. return 0;
  647. }
  648. void rtc_tick_irq_unregister(void)
  649. {
  650. /* Resolve interrupt dependency */
  651. if(!rtc_alarm_get_interrupt())
  652. {
  653. rtc_tick_set_interrupt(0);
  654. }
  655. rtc_instance.tick_enable_by_user = false;
  656. rtc_instance.tick_mode_by_user = -1;
  657. rtc_instance.rtc_tick_callback = NULL;
  658. rtc_instance.tick_ctx = NULL;
  659. if((!rtc_instance.rtc_tick_callback) && (!rtc_instance.rtc_alarm_callback))
  660. {
  661. plic_irq_unregister(IRQN_RTC_INTERRUPT);
  662. }
  663. }
  664. int rtc_alarm_irq_register(bool is_single_shot, rtc_mask_t mask, plic_irq_callback_t callback, void *ctx, uint8_t priority)
  665. {
  666. plic_irq_disable(IRQN_RTC_INTERRUPT);
  667. rtc_tick_set_interrupt(0);
  668. rtc_alarm_set_interrupt(0);
  669. rtc_instance.rtc_alarm_callback = callback;
  670. rtc_instance.alarm_ctx = ctx;
  671. rtc_instance.alarm_is_single_shot = is_single_shot;
  672. rtc_instance.tick_enable_by_alarm = true;
  673. if(mask.second)
  674. {
  675. rtc_instance.tick_mode_by_alarm = RTC_INT_SECOND;
  676. goto alarm_mode;
  677. }
  678. if(mask.minute)
  679. {
  680. rtc_instance.tick_mode_by_alarm = RTC_INT_MINUTE;
  681. goto alarm_mode;
  682. }
  683. if(mask.hour)
  684. {
  685. rtc_instance.tick_mode_by_alarm = RTC_INT_HOUR;
  686. goto alarm_mode;
  687. } else
  688. {
  689. rtc_instance.tick_mode_by_alarm = RTC_INT_DAY;
  690. }
  691. alarm_mode:
  692. if((rtc_instance.tick_enable_by_user && rtc_instance.tick_mode_by_alarm < rtc_tick_get_interrupt_mode()) || !rtc_instance.tick_enable_by_user)
  693. {
  694. rtc_tick_set_interrupt_mode(rtc_instance.tick_mode_by_alarm);
  695. }
  696. rtc_alarm_set_mask(mask);
  697. plic_set_priority(IRQN_RTC_INTERRUPT, priority);
  698. plic_irq_register(IRQN_RTC_INTERRUPT, rtc_irq_callback, &rtc_instance);
  699. plic_irq_enable(IRQN_RTC_INTERRUPT);
  700. rtc_alarm_set_interrupt(1);
  701. /* Must enable tick hardware interrupt */
  702. rtc_tick_set_interrupt(1);
  703. return 0;
  704. }
  705. void rtc_alarm_irq_unregister(void)
  706. {
  707. rtc_alarm_set_interrupt(0);
  708. rtc_instance.rtc_alarm_callback = NULL;
  709. rtc_instance.alarm_ctx = NULL;
  710. rtc_instance.tick_enable_by_alarm = false;
  711. rtc_instance.tick_mode_by_alarm = RTC_INT_MAX;
  712. if(rtc_instance.tick_enable_by_user)
  713. {
  714. if(rtc_instance.tick_mode_by_user > rtc_tick_get_interrupt_mode())
  715. {
  716. rtc_tick_set_interrupt(0);
  717. rtc_tick_set_interrupt_mode(rtc_instance.tick_mode_by_user);
  718. rtc_tick_set_interrupt(1);
  719. }
  720. } else
  721. {
  722. rtc_tick_set_interrupt(0);
  723. }
  724. if((!rtc_instance.rtc_tick_callback) && (!rtc_instance.rtc_alarm_callback))
  725. {
  726. plic_irq_unregister(IRQN_RTC_INTERRUPT);
  727. }
  728. }