summaryrefslogtreecommitdiff
path: root/code/fe310/eos/timer.c
diff options
context:
space:
mode:
Diffstat (limited to 'code/fe310/eos/timer.c')
-rw-r--r--code/fe310/eos/timer.c118
1 files changed, 79 insertions, 39 deletions
diff --git a/code/fe310/eos/timer.c b/code/fe310/eos/timer.c
index b287317..2bbeec8 100644
--- a/code/fe310/eos/timer.c
+++ b/code/fe310/eos/timer.c
@@ -11,30 +11,40 @@
#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y))
#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y))
-static eos_timer_fptr_t timer_ext_handler = NULL;
-volatile uint64_t timer_next = 0;
-volatile uint64_t timer_next_evt = 0;
+static eos_timer_fptr_t timer_handler[EOS_TIMER_MAX_ETYPE + 1];
+static uint64_t timer_next[EOS_TIMER_MAX_ETYPE + 1];
extern EOSMsgQ _eos_event_q;
+static void timer_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) {
+ unsigned char idx = (type & ~EOS_EVT_MASK) - 1;
+
+ if ((idx < EOS_TIMER_MAX_ETYPE) && timer_handler[idx]) {
+ timer_handler[idx](type);
+ } else {
+ eos_evtq_bad_handler(type, buffer, len);
+ }
+}
+
void eos_timer_handle(void) {
+ int i;
volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
- volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
+ uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
uint64_t now = *mtime;
-
- if (timer_next && (timer_next <= now)) {
- uint32_t next = timer_ext_handler();
- if (next) {
- timer_next = now + next;
- } else {
- timer_next = 0;
+ uint64_t next = 0;
+
+ for (i = 0; i <= EOS_TIMER_MAX_ETYPE; i++) {
+ if (timer_next[i] && (timer_next[i] <= now)) {
+ timer_next[i] = 0;
+ if (i == EOS_TIMER_MAX_ETYPE) {
+ timer_handler[EOS_TIMER_MAX_ETYPE](0);
+ } else {
+ eos_msgq_push(&_eos_event_q, EOS_EVT_TIMER | i + 1, NULL, 0);
+ }
}
+ next = next && timer_next[i] ? MIN(next, timer_next[i]) : (next ? next : timer_next[i]);
}
- if (timer_next_evt && (timer_next_evt <= now)) {
- eos_msgq_push(&_eos_event_q, EOS_EVT_TIMER, NULL, 0);
- timer_next_evt = 0;
- }
- *mtimecmp = (timer_next && timer_next_evt) ? MIN(timer_next, timer_next_evt) : (timer_next ? timer_next : timer_next_evt);
+ *mtimecmp = next;
if (*mtimecmp == 0) clear_csr(mie, MIP_MTIP);
}
@@ -43,51 +53,81 @@ void handle_m_time_interrupt(void) {
}
void eos_timer_init(void) {
+ int i;
volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
- *mtimecmp = 0;
+
clear_csr(mie, MIP_MTIP);
+ *mtimecmp = 0;
+ for (i = 0; i <= EOS_TIMER_MAX_ETYPE; i++) {
+ timer_next[i] = 0;
+ timer_handler[i] = NULL;
+ }
+ eos_evtq_set_handler(EOS_EVT_TIMER, timer_handler_evt);
}
-void eos_timer_set(uint32_t tick, unsigned char is_evt) {
+void eos_timer_set(uint32_t tick, unsigned char evt) {
+ int i;
volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME);
- volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
-
+ uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
+ uint64_t next = 0;
+ uint64_t now;
+
clear_csr(mie, MIP_MTIP);
- uint64_t now = *mtime;
- uint64_t next = now + tick;
- if (is_evt) {
- if ((timer_next_evt == 0) || (next < timer_next_evt)) timer_next_evt = next;
- next = timer_next ? MIN(timer_next, timer_next_evt) : timer_next_evt;
- } else if (timer_ext_handler) {
- if ((timer_next == 0) || (next < timer_next)) timer_next = next;
- next = timer_next_evt ? MIN(timer_next, timer_next_evt) : timer_next;
+ now = *mtime;
+ if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
+ evt--;
+ } else if (evt == 0) {
+ evt = EOS_TIMER_MAX_ETYPE;
+ } else {
+ return;
+ }
+ if ((timer_next[evt] == 0) || (now + tick < timer_next[evt])) timer_next[evt] = now + tick;
+ for (i = 0; i <= EOS_TIMER_MAX_ETYPE; i++) {
+ next = next && timer_next[i] ? MIN(next, timer_next[i]) : (next ? next : timer_next[i]);
}
- if ((*mtimecmp == 0) || (next < *mtimecmp)) *mtimecmp = next;
+ *mtimecmp = next;
if (*mtimecmp != 0) set_csr(mie, MIP_MTIP);
}
-void eos_timer_clear(unsigned char is_evt) {
- volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
+void eos_timer_clear(unsigned char evt) {
+ int i;
+ uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
+ uint64_t next = 0;
clear_csr(mie, MIP_MTIP);
- if (is_evt) {
- timer_next_evt = 0;
- *mtimecmp = timer_next;
+ if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
+ evt--;
+ } else if (evt == 0) {
+ evt = EOS_TIMER_MAX_ETYPE;
} else {
- timer_next = 0;
- *mtimecmp = timer_next_evt;
+ return;
}
+ timer_next[evt] = 0;
+ for (i = 0; i <= EOS_TIMER_MAX_ETYPE; i++) {
+ next = next && timer_next[i] ? MIN(next, timer_next[i]) : (next ? next : timer_next[i]);
+ }
+ *mtimecmp = next;
if (*mtimecmp != 0) set_csr(mie, MIP_MTIP);
}
-void eos_timer_set_handler(eos_timer_fptr_t handler) {
- volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
+void eos_timer_set_handler(unsigned char evt, eos_timer_fptr_t handler, uint8_t flags) {
+ uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
clear_csr(mie, MIP_MTIP);
- timer_ext_handler = handler;
+
+ if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) {
+ evt--;
+ } else if (evt == 0) {
+ evt = EOS_TIMER_MAX_ETYPE;
+ } else {
+ return;
+ }
+ timer_handler[evt] = handler;
+ if (flags) eos_evtq_set_flags(EOS_EVT_TIMER | evt, flags);
+
if (*mtimecmp != 0) set_csr(mie, MIP_MTIP);
}