From 01c3e3af2394f863323b846fa304ff7e0a30e9df Mon Sep 17 00:00:00 2001 From: Uros Majstorovic Date: Tue, 16 Jan 2018 23:43:07 +0100 Subject: eos support --- code/fe310/eos/Makefile | 18 +++ code/fe310/eos/ecp.c | 66 ++++++++ code/fe310/eos/ecp.h | 3 + code/fe310/eos/eos.c | 17 +++ code/fe310/eos/eos.h | 6 + code/fe310/eos/event.c | 85 +++++++++++ code/fe310/eos/event.h | 16 ++ code/fe310/eos/interrupt.c | 53 +++++++ code/fe310/eos/interrupt.h | 8 + code/fe310/eos/msgq.c | 66 ++++++++ code/fe310/eos/msgq.h | 19 +++ code/fe310/eos/net.c | 365 +++++++++++++++++++++++++++++++++++++++++++++ code/fe310/eos/net.h | 20 +++ code/fe310/eos/spi.h | 32 ++++ code/fe310/eos/timer.c | 86 +++++++++++ code/fe310/eos/timer.h | 7 + 16 files changed, 867 insertions(+) create mode 100644 code/fe310/eos/Makefile create mode 100644 code/fe310/eos/ecp.c create mode 100644 code/fe310/eos/ecp.h create mode 100644 code/fe310/eos/eos.c create mode 100644 code/fe310/eos/eos.h create mode 100644 code/fe310/eos/event.c create mode 100644 code/fe310/eos/event.h create mode 100644 code/fe310/eos/interrupt.c create mode 100644 code/fe310/eos/interrupt.h create mode 100644 code/fe310/eos/msgq.c create mode 100644 code/fe310/eos/msgq.h create mode 100644 code/fe310/eos/net.c create mode 100644 code/fe310/eos/net.h create mode 100644 code/fe310/eos/spi.h create mode 100644 code/fe310/eos/timer.c create mode 100644 code/fe310/eos/timer.h (limited to 'code/fe310') diff --git a/code/fe310/eos/Makefile b/code/fe310/eos/Makefile new file mode 100644 index 0000000..573bca7 --- /dev/null +++ b/code/fe310/eos/Makefile @@ -0,0 +1,18 @@ +FE310_HOME=/opt/my/freedom-e-sdk + +CC=$(FE310_HOME)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/bin/riscv64-unknown-elf-gcc +AR=$(FE310_HOME)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/bin/riscv64-unknown-elf-ar + +CFLAGS=-O3 -fno-builtin-printf -march=rv32imac -mabi=ilp32 -mcmodel=medany -I$(FE310_HOME)/bsp/include -I$(FE310_HOME)/bsp/drivers -I$(FE310_HOME)/bsp/env -I$(FE310_HOME)/bsp/env/freedom-e300-hifive1 -I../.. + +obj = msgq.o event.o interrupt.o timer.o net.o eos.o ecp.o + + +%.o: %.c %.h + $(CC) $(CFLAGS) -c $< + +all: $(obj) + $(AR) rcs libeos.a $(obj) + +clean: + rm -f *.o *.a \ No newline at end of file diff --git a/code/fe310/eos/ecp.c b/code/fe310/eos/ecp.c new file mode 100644 index 0000000..433e693 --- /dev/null +++ b/code/fe310/eos/ecp.c @@ -0,0 +1,66 @@ +#include +#include + +#include "encoding.h" +#include "platform.h" + +#include "event.h" +#include "timer.h" +#include "net.h" + +#include "ecp.h" + +static ECPSocket *_sock = NULL; + +static unsigned char net_buf_reserved = 0; +static void timer_handler(unsigned char cmd, unsigned char *buffer, uint16_t len) { + int ok = eos_net_acquire(net_buf_reserved); + if (ok) { + ecp_cts_t next = ecp_timer_exe(_sock); + if (next) { + uint32_t tick = next * (uint64_t)RTC_FREQ / 1000; + eos_timer_set(tick, 1); + } + eos_net_release(1); + net_buf_reserved = 0; + } else { + net_buf_reserved = 1; + eos_evtq_push(EOS_EVT_TIMER, NULL, 0); + } +} + +static void packet_handler(unsigned char cmd, unsigned char *buffer, uint16_t len) { + ECPNetAddr addr; + size_t addr_len = sizeof(addr.host) + sizeof(addr.port); + + ECP2Buffer bufs; + ECPBuffer packet; + ECPBuffer payload; + unsigned char pld_buf[ECP_MAX_PLD]; + + bufs.packet = &packet; + bufs.payload = &payload; + + packet.buffer = buffer+addr_len; + packet.size = ECP_MAX_PKT; + payload.buffer = pld_buf; + payload.size = ECP_MAX_PLD; + + memcpy(addr.host, buffer, sizeof(addr.host)); + memcpy(&addr.port, buffer+sizeof(addr.host), sizeof(addr.port)); + ssize_t rv = ecp_pkt_handle(_sock, &addr, NULL, &bufs, len-addr_len); + if (bufs.packet->buffer) eos_net_free(buffer, 0); + eos_net_release(0); +} + +int ecp_init(ECPContext *ctx) { + int rv; + + rv = ecp_ctx_create(ctx); + if (rv) return rv; + + eos_evtq_set_handler(EOS_EVT_TIMER, timer_handler); + eos_evtq_set_handler(EOS_EVT_MASK_NET | EOS_NET_CMD_PKT, packet_handler); + + return ECP_OK; +} \ No newline at end of file diff --git a/code/fe310/eos/ecp.h b/code/fe310/eos/ecp.h new file mode 100644 index 0000000..95aed31 --- /dev/null +++ b/code/fe310/eos/ecp.h @@ -0,0 +1,3 @@ +#include + +int ecp_init(ECPContext *ctx); \ No newline at end of file diff --git a/code/fe310/eos/eos.c b/code/fe310/eos/eos.c new file mode 100644 index 0000000..3ad3b68 --- /dev/null +++ b/code/fe310/eos/eos.c @@ -0,0 +1,17 @@ +#include "event.h" +#include "interrupt.h" +#include "timer.h" +#include "net.h" + +#include "eos.h" + +void eos_init(void) { + eos_evtq_init(); + eos_intr_init(); + eos_timer_init(); + eos_net_init(); +} + +void eos_start(void) { + eos_net_start(15); +} \ No newline at end of file diff --git a/code/fe310/eos/eos.h b/code/fe310/eos/eos.h new file mode 100644 index 0000000..938030e --- /dev/null +++ b/code/fe310/eos/eos.h @@ -0,0 +1,6 @@ +#define EOS_OK 0 +#define EOS_ERR_Q_FULL -10 + +void eos_init(void); +void eos_start(void); + diff --git a/code/fe310/eos/event.c b/code/fe310/eos/event.c new file mode 100644 index 0000000..25f1fa1 --- /dev/null +++ b/code/fe310/eos/event.c @@ -0,0 +1,85 @@ +#include + +#include "encoding.h" +#include "platform.h" + +#include "eos.h" +#include "msgq.h" +#include "net.h" +#include "timer.h" +#include "event.h" + +static EOSMsgQ event_q; +static EOSMsgItem event_q_array[EOS_EVT_SIZE_Q]; + +static eos_evt_fptr_t evt_net_handler[EOS_NET_MAX_CMD]; +static eos_evt_fptr_t evt_timer_handler = NULL; +static eos_evt_fptr_t evt_ui_handler = NULL; + +static void bad_handler(unsigned char cmd, unsigned char *buffer, uint16_t len) { + printf("bad handler: %d\n", cmd); +} + +void eos_evtq_init(void) { + int i; + + for (i=0; i + +#define EOS_EVT_MASK_NET 0x80 +#define EOS_EVT_TIMER 0x01 +#define EOS_EVT_UI 0x02 + +#define EOS_EVT_SIZE_Q 4 + +typedef void (*eos_evt_fptr_t) (unsigned char, unsigned char *, uint16_t); + +void eos_evtq_init(void); +int eos_evtq_push(unsigned char cmd, unsigned char *buffer, uint16_t len); +void eos_evtq_pop(unsigned char *cmd, unsigned char **buffer, uint16_t *len); +void eos_evtq_handle(unsigned char cmd, unsigned char *buffer, uint16_t len); +void eos_evtq_loop(void); +void eos_evtq_set_handler(unsigned char cmd, eos_evt_fptr_t handler); \ No newline at end of file diff --git a/code/fe310/eos/interrupt.c b/code/fe310/eos/interrupt.c new file mode 100644 index 0000000..def1a24 --- /dev/null +++ b/code/fe310/eos/interrupt.c @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include + +#include "encoding.h" +#include "platform.h" +#include "plic/plic_driver.h" +#include "interrupt.h" + +// Global Instance data for the PLIC +// for use by the PLIC Driver. +static plic_instance_t plic; + +static eos_intr_fptr_t ext_interrupt_handler[PLIC_NUM_INTERRUPTS]; + +void handle_m_ext_interrupt(void) { + plic_source int_num = PLIC_claim_interrupt(&plic); + if ((int_num >=1 ) && (int_num < PLIC_NUM_INTERRUPTS) && (ext_interrupt_handler[int_num])) { + ext_interrupt_handler[int_num](); + } else { + printf("handle_m_ext_interrupt error\n\n"); + exit(1 + (uintptr_t) int_num); + } + PLIC_complete_interrupt(&plic, int_num); +} + +void eos_intr_init(void) { + for (int i = 0; i < PLIC_NUM_INTERRUPTS; i++){ + ext_interrupt_handler[i] = NULL; + } + + /************************************************************************** + * Set up the PLIC + **************************************************************************/ + PLIC_init(&plic, + PLIC_CTRL_ADDR, + PLIC_NUM_INTERRUPTS, + PLIC_NUM_PRIORITIES); + + // Enable Global (PLIC) interrupts. + set_csr(mie, MIP_MEIP); + + // Enable all interrupts + set_csr(mstatus, MSTATUS_MIE); +} + +void eos_intr_set_handler(uint8_t int_num, uint8_t priority, eos_intr_fptr_t handler) { + ext_interrupt_handler[int_num] = handler; + PLIC_enable_interrupt(&plic, int_num); + PLIC_set_priority(&plic, int_num, priority); +} diff --git a/code/fe310/eos/interrupt.h b/code/fe310/eos/interrupt.h new file mode 100644 index 0000000..7ef81b8 --- /dev/null +++ b/code/fe310/eos/interrupt.h @@ -0,0 +1,8 @@ +#include + +// Structures for registering different interrupt handlers +// for different parts of the application. +typedef void (*eos_intr_fptr_t) (void); + +void eos_intr_init(void); +void eos_intr_set_handler(uint8_t int_num, uint8_t priority, eos_intr_fptr_t handler); diff --git a/code/fe310/eos/msgq.c b/code/fe310/eos/msgq.c new file mode 100644 index 0000000..d242c69 --- /dev/null +++ b/code/fe310/eos/msgq.c @@ -0,0 +1,66 @@ +#include + +#include "eos.h" +#include "msgq.h" + +#define EOS_MSGQ_IDX_MASK(IDX, SIZE) ((IDX) & ((SIZE) - 1)) + +void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size) { + msgq->idx_r = 0; + msgq->idx_w = 0; + msgq->array = array; + msgq->size = size; +} + +int eos_msgq_push(EOSMsgQ *msgq, unsigned char cmd, unsigned char *buffer, uint16_t len) { + if (msgq->idx_w - msgq->idx_r == msgq->size) return EOS_ERR_Q_FULL; + + uint8_t idx = EOS_MSGQ_IDX_MASK(msgq->idx_w, msgq->size); + msgq->array[idx].cmd = cmd; + msgq->array[idx].buffer = buffer; + msgq->array[idx].len = len; + msgq->idx_w++; + return EOS_OK; +} + +void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *cmd, unsigned char **buffer, uint16_t *len) { + if (msgq->idx_r == msgq->idx_w) { + *cmd = 0; + *buffer = NULL; + } else { + uint8_t idx = EOS_MSGQ_IDX_MASK(msgq->idx_r, msgq->size); + *cmd = msgq->array[idx].cmd; + *buffer = msgq->array[idx].buffer; + *len = msgq->array[idx].len; + msgq->idx_r++; + } +} + +void eos_msgq_get(EOSMsgQ *msgq, unsigned char cmd, unsigned char **buffer, uint16_t *len) { + uint8_t idx = EOS_MSGQ_IDX_MASK(msgq->idx_r, msgq->size); + unsigned char _cmd = msgq->array[idx].cmd; + EOSMsgItem *tmp_item = &msgq->array[idx]; + + *buffer = msgq->array[idx].buffer; + *len = msgq->array[idx].len; + if (_cmd == cmd) { + msgq->idx_r++; + return; + } + for (idx = msgq->idx_r + 1; idx < msgq->idx_w; idx++) { + *tmp_item = msgq->array[EOS_MSGQ_IDX_MASK(idx, msgq->size)]; + msgq->array[EOS_MSGQ_IDX_MASK(idx, msgq->size)].cmd = _cmd; + msgq->array[EOS_MSGQ_IDX_MASK(idx, msgq->size)].buffer = *buffer; + msgq->array[EOS_MSGQ_IDX_MASK(idx, msgq->size)].len = *len; + _cmd = tmp_item->cmd; + *buffer = tmp_item->buffer; + *len = tmp_item->len; + if (_cmd == cmd) { + msgq->idx_r++; + return; + } + } + *buffer = NULL; + *len = 0; +} + diff --git a/code/fe310/eos/msgq.h b/code/fe310/eos/msgq.h new file mode 100644 index 0000000..05a5d80 --- /dev/null +++ b/code/fe310/eos/msgq.h @@ -0,0 +1,19 @@ +#include + +typedef struct EOSMsgItem { + unsigned char cmd; + unsigned char *buffer; + uint16_t len; +} EOSMsgItem; + +typedef struct EOSMsgQ { + uint8_t idx_r; + uint8_t idx_w; + uint8_t size; + EOSMsgItem *array; +} EOSMsgQ; + +void eos_msgq_init(EOSMsgQ *msgq, EOSMsgItem *array, uint8_t size); +int eos_msgq_push(EOSMsgQ *msgq, unsigned char cmd, unsigned char *buffer, uint16_t len); +void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *cmd, unsigned char **buffer, uint16_t *len); +void eos_msgq_get(EOSMsgQ *msgq, unsigned char cmd, unsigned char **buffer, uint16_t *len); \ No newline at end of file diff --git a/code/fe310/eos/net.c b/code/fe310/eos/net.c new file mode 100644 index 0000000..080da72 --- /dev/null +++ b/code/fe310/eos/net.c @@ -0,0 +1,365 @@ +#include +#include +#include +#include +#include + +#include "encoding.h" +#include "platform.h" +#include "plic/plic_driver.h" + +#include "eos.h" +#include "msgq.h" +#include "event.h" +#include "interrupt.h" +#include "net.h" +#include "spi.h" + +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) +#define SPI_BUFQ_IDX_MASK(IDX) ((IDX) & (SPI_SIZE_BUFQ - 1)) + +static volatile uint8_t spi_res = 0; +static volatile uint8_t spi_res_next = 0; +static volatile unsigned char *spi_res_buf = NULL; + +static EOSMsgQ spi_sndq; +static EOSMsgItem spi_sndq_array[SPI_SIZE_BUFQ]; + +static SPIBufQ spi_bufq; +static unsigned char spi_bufq_array[SPI_SIZE_BUFQ][SPI_SIZE_BUF]; + +static int spi_bufq_push(unsigned char *buffer) { + spi_bufq.array[SPI_BUFQ_IDX_MASK(spi_bufq.idx_w++)] = buffer; +} + +static unsigned char *spi_bufq_pop(void) { + if (spi_bufq.idx_r == spi_bufq.idx_w) return NULL; + return spi_bufq.array[SPI_BUFQ_IDX_MASK(spi_bufq.idx_r++)]; +} + +static volatile uint8_t spi_rdy = 0; +static volatile uint8_t spi_cts = 0; +static volatile uint8_t spi_rts = 0; +static SPIBuffer spi_buffer; + +static void spi_reset(void) { + int i; + volatile uint32_t r; + + spi_cts = 0; + // before starting a transaction, set SPI peripheral to desired mode + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; + + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = 0; + while ((r = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; +} + +static void spi_xchg(unsigned char cmd, unsigned char *buffer, uint16_t len) { + volatile uint32_t r1, r2; + + spi_cts = 0; + spi_buffer.buffer = buffer; + spi_buffer.len_rx = 0; + spi_buffer.idx_tx = 0; + spi_buffer.idx_rx = 0; + + if (spi_res_buf == NULL) { + if (cmd & EOS_NET_CMD_FLAG_ONEW) { + spi_res_next = 1; + } else if (spi_res) { + cmd |= EOS_NET_CMD_FLAG_ONEW; + } + } else if (cmd & EOS_NET_CMD_FLAG_ONEW) { + cmd &= ~EOS_NET_CMD_FLAG_ONEW; + } + + // before starting a transaction, set SPI peripheral to desired mode + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; + + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = ((cmd << 3) | (len >> 8)) & 0xFF; + + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = len & 0xFF; + + while ((r1 = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + while ((r2 = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + + if (cmd & EOS_NET_CMD_FLAG_ONEW) { + r1 = 0; + r2 = 0; + } + + spi_buffer.cmd = ((r1 & 0xFF) >> 3); + spi_buffer.len_rx = ((r1 & 0x07) << 8); + + spi_buffer.len_rx |= (r2 & 0xFF); + spi_buffer.len = MAX(len, spi_buffer.len_rx); + + // Work around esp32 bug + if (spi_buffer.len < 6) { + spi_buffer.len = 6; + } else if ((spi_buffer.len + 2) % 4 != 0) { + spi_buffer.len = ((spi_buffer.len + 2)/4 + 1) * 4 - 2; + } + + SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_CHUNK/2); + SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(SPI_SIZE_CHUNK - 1); + SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM | SPI_IP_RXWM; +} + +static int spi_xchg_next(unsigned char *_buffer) { + unsigned char cmd; + unsigned char *buffer = NULL; + uint16_t len; + + eos_msgq_pop(&spi_sndq, &cmd, &buffer, &len); + if (cmd) { + spi_xchg(cmd, buffer, len); + } else if (spi_rts) { + if (_buffer == NULL) _buffer = spi_bufq_pop(); + if (_buffer) { + spi_xchg(0, _buffer, 0); + return 0; + } + } + return 1; +} + +static void spi_xchg_handler(void) { + int i; + + if (SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM) { + uint16_t sz_chunk = MIN(spi_buffer.len - spi_buffer.idx_tx, SPI_SIZE_CHUNK); + for (i=0; i + +#define EOS_NET_CMD_FLAG_ONEW 0x10 + +#define EOS_NET_CMD_CONNECT 1 +#define EOS_NET_CMD_DISCONNECT 2 +#define EOS_NET_CMD_SCAN 3 +#define EOS_NET_CMD_PKT 4 + +#define EOS_NET_MAX_CMD 8 + +void eos_net_init(void); +void eos_net_start(uint32_t sckdiv); +void eos_net_stop(void); +int eos_net_reserve(unsigned char *buffer); +int eos_net_acquire(unsigned char reserved); +int eos_net_release(unsigned char reserved); +unsigned char *eos_net_alloc(void); +int eos_net_free(unsigned char *buffer, unsigned char reserve_next); +int eos_net_send(unsigned char cmd, unsigned char *buffer, uint16_t len); diff --git a/code/fe310/eos/spi.h b/code/fe310/eos/spi.h new file mode 100644 index 0000000..88e54bb --- /dev/null +++ b/code/fe310/eos/spi.h @@ -0,0 +1,32 @@ +#include + +#include "encoding.h" +#include "platform.h" + +#define SPI_MODE0 0x00 +#define SPI_MODE1 0x01 +#define SPI_MODE2 0x02 +#define SPI_MODE3 0x03 + +#define SPI_SIZE_BUF 1500 +#define SPI_SIZE_CHUNK 4 +#define SPI_SIZE_BUFQ 4 +#define SPI_GPIO_CTS_OFFSET PIN_2_OFFSET +#define SPI_GPIO_RTS_OFFSET PIN_3_OFFSET +#define SPI_IOF_MASK (((uint32_t)1 << IOF_SPI1_SCK) | ((uint32_t)1 << IOF_SPI1_MOSI) | ((uint32_t)1 << IOF_SPI1_MISO)) + +typedef struct SPIBuffer { + unsigned char cmd; + unsigned char *buffer; + uint16_t len; + uint16_t len_rx; + uint16_t idx_tx; + uint16_t idx_rx; +} SPIBuffer; + +typedef struct SPIBufQ { + uint8_t idx_r; + uint8_t idx_w; + unsigned char *array[SPI_SIZE_BUFQ]; +} SPIBufQ; + diff --git a/code/fe310/eos/timer.c b/code/fe310/eos/timer.c new file mode 100644 index 0000000..0a07ed9 --- /dev/null +++ b/code/fe310/eos/timer.c @@ -0,0 +1,86 @@ +#include +#include + +#include "encoding.h" +#include "platform.h" +#include "event.h" +#include "timer.h" + +#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; + +void handle_m_time_interrupt(void) { + volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME); + volatile 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; + } + } + if (timer_next_evt && (timer_next_evt <= now)) { + eos_evtq_push(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); + if (*mtimecmp == 0) clear_csr(mie, MIP_MTIP); +} + +void eos_timer_init(void) { + volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); + *mtimecmp = 0; + clear_csr(mie, MIP_MTIP); +} + +void eos_timer_set(uint32_t tick, unsigned char is_evt) { + volatile uint64_t *mtime = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIME); + volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); + + clear_csr(mstatus, MSTATUS_MIE); + + uint64_t now = *mtime; + uint64_t then = *mtimecmp; + 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; + } + if ((then == 0) || (next < then)) *mtimecmp = next; + if (then == 0) set_csr(mie, MIP_MTIP); + + set_csr(mstatus, MSTATUS_MIE); +} + +void eos_timer_clear(unsigned char is_evt) { + volatile uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); + + clear_csr(mstatus, MSTATUS_MIE); + + if (is_evt) { + timer_next_evt = 0; + *mtimecmp = timer_next; + } else { + timer_next = 0; + *mtimecmp = timer_next_evt; + } + if (*mtimecmp == 0) clear_csr(mie, MIP_MTIP); + + set_csr(mstatus, MSTATUS_MIE); +} + +void eos_timer_set_handler(eos_timer_fptr_t handler) { + clear_csr(mstatus, MSTATUS_MIE); + timer_ext_handler = handler; + set_csr(mstatus, MSTATUS_MIE); +} diff --git a/code/fe310/eos/timer.h b/code/fe310/eos/timer.h new file mode 100644 index 0000000..929283b --- /dev/null +++ b/code/fe310/eos/timer.h @@ -0,0 +1,7 @@ +#include + +typedef uint32_t (*eos_timer_fptr_t) (void); + +void eos_timer_init(void); +void eos_timer_set(uint32_t tick, unsigned char is_evt); +void eos_timer_set_handler(eos_timer_fptr_t handler); -- cgit v1.2.3