diff options
author | Uros Majstorovic <majstor@majstor.org> | 2019-10-18 18:38:00 +0200 |
---|---|---|
committer | Uros Majstorovic <majstor@majstor.org> | 2019-10-18 18:38:00 +0200 |
commit | 85500fe0d01b691a9bdd8c2330d26d66bc2bc177 (patch) | |
tree | c320c642ebb942d1b3692701d50c4a46e50e49f3 /code/fe310/eos | |
parent | f74dcae328e3650acf6b12499a55548b46117877 (diff) |
added spi driver
Diffstat (limited to 'code/fe310/eos')
-rw-r--r-- | code/fe310/eos/Makefile | 4 | ||||
-rw-r--r-- | code/fe310/eos/ecp.c | 13 | ||||
-rw-r--r-- | code/fe310/eos/eos.c | 6 | ||||
-rw-r--r-- | code/fe310/eos/eos.h | 2 | ||||
-rw-r--r-- | code/fe310/eos/event.c | 10 | ||||
-rw-r--r-- | code/fe310/eos/i2s.c | 4 | ||||
-rw-r--r-- | code/fe310/eos/interrupt.c | 4 | ||||
-rw-r--r-- | code/fe310/eos/interrupt.h | 1 | ||||
-rw-r--r-- | code/fe310/eos/msgq.c | 5 | ||||
-rw-r--r-- | code/fe310/eos/net.c | 226 | ||||
-rw-r--r-- | code/fe310/eos/net.h | 4 | ||||
-rw-r--r-- | code/fe310/eos/net_def.h | 4 | ||||
-rw-r--r-- | code/fe310/eos/spi.c | 284 | ||||
-rw-r--r-- | code/fe310/eos/spi.h | 25 | ||||
-rw-r--r-- | code/fe310/eos/spi_def.h | 15 | ||||
-rw-r--r-- | code/fe310/eos/timer.c | 6 | ||||
-rw-r--r-- | code/fe310/eos/trap_entry.S | 4 |
17 files changed, 447 insertions, 170 deletions
diff --git a/code/fe310/eos/Makefile b/code/fe310/eos/Makefile index a3fb640..94eb89a 100644 --- a/code/fe310/eos/Makefile +++ b/code/fe310/eos/Makefile @@ -6,8 +6,8 @@ CC = $(FE310_HOME)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/bin AR = $(FE310_HOME)/work/build/riscv-gnu-toolchain/riscv64-unknown-elf/prefix/bin/riscv64-unknown-elf-ar CFLAGS = $(CFLAGS_PL) -I../.. - -obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o i2s.o net.o ecp.o + +obj = trap_entry.o eos.o msgq.o event.o interrupt.o timer.o i2s.o spi.o net.o ecp.o %.o: %.c %.h diff --git a/code/fe310/eos/ecp.c b/code/fe310/eos/ecp.c index bf51b19..9611208 100644 --- a/code/fe310/eos/ecp.c +++ b/code/fe310/eos/ecp.c @@ -1,6 +1,7 @@ -#include <stddef.h> -#include <string.h> #include <stdlib.h> +#include <stdint.h> +#include <string.h> +#include <stdio.h> #include "encoding.h" #include "platform.h" @@ -25,12 +26,12 @@ static void timer_handler(unsigned char type) { static void packet_handler(unsigned char type, 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; @@ -56,10 +57,10 @@ static void packet_handler(unsigned char type, unsigned char *buffer, uint16_t l int ecp_init(ECPContext *ctx) { int rv; - + rv = ecp_ctx_create_vconn(ctx); if (rv) return rv; - + eos_timer_set_handler(EOS_TIMER_ETYPE_ECP, timer_handler, EOS_EVT_FLAG_NET_BUF_ACQ); /* XXX */ // eos_net_set_handler(EOS_NET_DATA_PKT, packet_handler, 0); diff --git a/code/fe310/eos/eos.c b/code/fe310/eos/eos.c index c4d0919..8459f48 100644 --- a/code/fe310/eos/eos.c +++ b/code/fe310/eos/eos.c @@ -1,6 +1,7 @@ #include "event.h" #include "interrupt.h" #include "timer.h" +#include "spi.h" #include "net.h" #include "i2s.h" @@ -11,9 +12,6 @@ void eos_init(void) { eos_intr_init(); eos_timer_init(); eos_net_init(); + eos_spi_init(); eos_i2s_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 index 8ca73e5..575a457 100644 --- a/code/fe310/eos/eos.h +++ b/code/fe310/eos/eos.h @@ -3,5 +3,3 @@ #define EOS_ERR_Q_EMPTY -11 void eos_init(void); -void eos_start(void); - diff --git a/code/fe310/eos/event.c b/code/fe310/eos/event.c index 25a4feb..bae110e 100644 --- a/code/fe310/eos/event.c +++ b/code/fe310/eos/event.c @@ -1,5 +1,5 @@ +#include <stdlib.h> #include <stdint.h> -#include <stdio.h> #include <unistd.h> #include "encoding.h" @@ -20,7 +20,7 @@ static volatile char evt_busy = 0; void eos_evtq_init(void) { int i; - + for (i=0; i<EOS_EVT_MAX_EVT; i++) { evt_handler[i] = eos_evtq_bad_handler; } @@ -48,7 +48,7 @@ static void evtq_handler_wrapper(unsigned char type, unsigned char *buffer, uint unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1; uint16_t flag = (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1); int ok; - + ok = eos_net_acquire(evt_handler_wrapper_acq[idx] & flag); if (ok) { evt_handler[idx](type, buffer, len); @@ -63,7 +63,7 @@ static void evtq_handler_wrapper(unsigned char type, unsigned char *buffer, uint static void evtq_handler(unsigned char type, unsigned char *buffer, uint16_t len) { unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1; uint16_t flag = (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1); - + if (idx >= EOS_EVT_MAX_EVT) { eos_evtq_bad_handler(type, buffer, len); return; @@ -77,7 +77,7 @@ static void evtq_handler(unsigned char type, unsigned char *buffer, uint16_t len void eos_evtq_set_handler(unsigned char type, eos_evt_fptr_t handler) { unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1; - + if (idx < EOS_EVT_MAX_EVT) evt_handler[idx] = handler; } diff --git a/code/fe310/eos/i2s.c b/code/fe310/eos/i2s.c index 6912f34..12a482f 100644 --- a/code/fe310/eos/i2s.c +++ b/code/fe310/eos/i2s.c @@ -1,5 +1,5 @@ -#include <unistd.h> -#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> #include "encoding.h" #include "platform.h" diff --git a/code/fe310/eos/interrupt.c b/code/fe310/eos/interrupt.c index 706d96b..0172fb8 100644 --- a/code/fe310/eos/interrupt.c +++ b/code/fe310/eos/interrupt.c @@ -56,6 +56,10 @@ void eos_intr_set(uint8_t int_num, uint8_t priority, eos_intr_fptr_t handler) { PLIC_enable_interrupt(&plic, int_num); } +void eos_intr_set_handler(uint8_t int_num, eos_intr_fptr_t handler) { + ext_interrupt_handler[int_num] = handler; +} + void eos_intr_set_priority(uint8_t int_num, uint8_t priority) { PLIC_set_priority(&plic, int_num, priority); } diff --git a/code/fe310/eos/interrupt.h b/code/fe310/eos/interrupt.h index 3ccfb21..3b5dc7e 100644 --- a/code/fe310/eos/interrupt.h +++ b/code/fe310/eos/interrupt.h @@ -6,6 +6,7 @@ typedef void (*eos_intr_fptr_t) (void); void eos_intr_init(void); void eos_intr_set(uint8_t int_num, uint8_t priority, eos_intr_fptr_t handler); +void eos_intr_set_handler(uint8_t int_num, eos_intr_fptr_t handler); void eos_intr_set_priority(uint8_t int_num, uint8_t priority); void eos_intr_enable(uint8_t int_num); void eos_intr_disable(uint8_t int_num); diff --git a/code/fe310/eos/msgq.c b/code/fe310/eos/msgq.c index 98ec4aa..d0fe405 100644 --- a/code/fe310/eos/msgq.c +++ b/code/fe310/eos/msgq.c @@ -1,4 +1,5 @@ -#include <stddef.h> +#include <stdlib.h> +#include <stdint.h> #include <string.h> #include "eos.h" @@ -44,7 +45,7 @@ void eos_msgq_pop(EOSMsgQ *msgq, unsigned char *type, unsigned char **buffer, ui int eos_msgq_get(EOSMsgQ *msgq, unsigned char type, unsigned char *selector, uint16_t sel_len, unsigned char **buffer, uint16_t *len) { uint8_t i, j, idx; - + if (msgq->idx_r == msgq->idx_w) { *buffer = NULL; *len = 0; diff --git a/code/fe310/eos/net.c b/code/fe310/eos/net.c index b8a5056..7d1803d 100644 --- a/code/fe310/eos/net.c +++ b/code/fe310/eos/net.c @@ -1,8 +1,5 @@ -#include <stdio.h> #include <stdlib.h> -#include <string.h> #include <stdint.h> -#include <unistd.h> #include "encoding.h" #include "platform.h" @@ -10,8 +7,11 @@ #include "eos.h" #include "msgq.h" #include "interrupt.h" +#include "event.h" #include "spi.h" +#include "spi_def.h" + #include "net.h" #include "net_def.h" @@ -31,17 +31,11 @@ static EOSMsgItem net_sndq_array[NET_SIZE_BUFQ]; static EOSNetBufQ net_buf_q; static unsigned char net_bufq_array[NET_SIZE_BUFQ][NET_SIZE_BUF]; -extern EOSMsgQ _eos_event_q; - -uint32_t _eos_spi_state_len = 0; -uint32_t _eos_spi_state_len_tx = 0; -uint32_t _eos_spi_state_len_rx = 0; -uint32_t _eos_spi_state_idx_tx = 0; -uint32_t _eos_spi_state_idx_rx = 0; -unsigned char *_eos_spi_state_buf = NULL; - static uint8_t net_state_flags = 0; static unsigned char net_state_type = 0; +static uint32_t net_state_len_tx = 0; +static uint32_t net_state_len_rx = 0; + static uint8_t net_state_next_cnt = 0; static unsigned char *net_state_next_buf = NULL; @@ -49,6 +43,22 @@ static eos_evt_fptr_t evt_handler[EOS_NET_MAX_MTYPE]; static uint16_t evt_handler_flags_buf_free = 0; static uint16_t evt_handler_flags_buf_acq = 0; +extern EOSMsgQ _eos_event_q; +extern uint32_t _eos_spi_state_len; +extern uint32_t _eos_spi_state_idx_tx; +extern uint32_t _eos_spi_state_idx_rx; +extern unsigned char *_eos_spi_state_buf; + +static void net_bufq_init(void) { + int i; + + net_buf_q.idx_r = 0; + net_buf_q.idx_w = NET_SIZE_BUFQ; + for (i=0; i<NET_SIZE_BUFQ; i++) { + net_buf_q.array[i] = net_bufq_array[i]; + } +} + static int net_bufq_push(unsigned char *buffer) { net_buf_q.array[NET_BUFQ_IDX_MASK(net_buf_q.idx_w++)] = buffer; return EOS_OK; @@ -80,12 +90,11 @@ static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t l if (type & EOS_NET_MTYPE_FLAG_ONEW) net_state_flags |= NET_FLAG_ONEW; net_state_type = type; + net_state_len_tx = len; + net_state_len_rx = 0; + _eos_spi_state_buf = buffer; - _eos_spi_state_len_tx = len; - _eos_spi_state_len_rx = 0; - _eos_spi_state_idx_tx = 0; - _eos_spi_state_idx_rx = 0; - + // before starting a transaction, set SPI peripheral to desired mode SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; @@ -96,28 +105,9 @@ static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t l SPI1_REG(SPI_REG_IE) = SPI_IP_RXWM; } -static int net_xchg_next(unsigned char *_buffer) { - unsigned char type; - unsigned char *buffer = NULL; - uint16_t len; - - eos_msgq_pop(&net_send_q, &type, &buffer, &len); - if (type) { - net_xchg_start(type, buffer, len); - } else if (net_state_flags & NET_FLAG_RTS) { - if (_buffer == NULL) _buffer = net_bufq_pop(); - if (_buffer) { - net_xchg_start(0, _buffer, 0); - return 0; - } - } - return 1; -} - -static void net_handler_xchg(void) { +static void net_xchg_handler(void) { volatile uint32_t r1, r2; - int i; - + if (net_state_flags & NET_FLAG_RST) { net_state_flags &= ~NET_FLAG_RST; @@ -133,16 +123,18 @@ static void net_handler_xchg(void) { r1 = SPI1_REG(SPI_REG_RXFIFO); r2 = SPI1_REG(SPI_REG_RXFIFO); - + if (net_state_type & EOS_NET_MTYPE_FLAG_ONEW) { r1 = 0; r2 = 0; } net_state_type = ((r1 & 0xFF) >> 3); - _eos_spi_state_len_rx = ((r1 & 0x07) << 8); - _eos_spi_state_len_rx |= (r2 & 0xFF); - _eos_spi_state_len = MAX(_eos_spi_state_len_tx, _eos_spi_state_len_rx); + net_state_len_rx = ((r1 & 0x07) << 8); + net_state_len_rx |= (r2 & 0xFF); + _eos_spi_state_len = MAX(net_state_len_tx, net_state_len_rx); + _eos_spi_state_idx_tx = 0; + _eos_spi_state_idx_rx = 0; // Work around esp32 bug if (_eos_spi_state_len < 6) { @@ -159,57 +151,54 @@ static void net_handler_xchg(void) { return; } - uint16_t sz_chunk = MIN(_eos_spi_state_len - _eos_spi_state_idx_tx, SPI_SIZE_CHUNK); - for (i=0; i<sz_chunk; i++) { - volatile uint32_t x = SPI1_REG(SPI_REG_TXFIFO); - if (x & SPI_TXFIFO_FULL) break; - SPI1_REG(SPI_REG_TXFIFO) = _eos_spi_state_buf[_eos_spi_state_idx_tx+i]; - } - _eos_spi_state_idx_tx += i; - - for (i=0; i<_eos_spi_state_idx_tx - _eos_spi_state_idx_rx; i++) { - volatile uint32_t x = SPI1_REG(SPI_REG_RXFIFO); - if (x & SPI_RXFIFO_EMPTY) break; - _eos_spi_state_buf[_eos_spi_state_idx_rx+i] = x & 0xFF; - } - _eos_spi_state_idx_rx += i; + eos_spi_xchg_handler(); +} - if (_eos_spi_state_idx_rx == _eos_spi_state_len) { - SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; - SPI1_REG(SPI_REG_IE) = 0x0; - if (net_state_type) { - int r = eos_msgq_push(&_eos_event_q, EOS_EVT_NET | net_state_type, _eos_spi_state_buf, _eos_spi_state_len_rx); - if (r) net_bufq_push(_eos_spi_state_buf); - } else if (((net_state_flags & NET_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) { - net_state_next_buf = _eos_spi_state_buf; - net_state_flags &= ~NET_FLAG_ONEW; - } else { - net_bufq_push(_eos_spi_state_buf); +static int net_xchg_next(unsigned char *_buffer) { + unsigned char type; + unsigned char *buffer = NULL; + uint16_t len; + + eos_msgq_pop(&net_send_q, &type, &buffer, &len); + if (type) { + net_xchg_start(type, buffer, len); + } else if (net_state_flags & NET_FLAG_RTS) { + if (_buffer == NULL) _buffer = net_bufq_pop(); + if (_buffer) { + net_xchg_start(0, _buffer, 0); + return 0; } - } else if (_eos_spi_state_idx_tx == _eos_spi_state_len) { - SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(MIN(_eos_spi_state_len - _eos_spi_state_idx_rx - 1, SPI_SIZE_WM - 1)); - SPI1_REG(SPI_REG_IE) = SPI_IP_RXWM; + } + return 1; +} + +void eos_net_xchg_done(void) { + if (net_state_type) { + int r = eos_msgq_push(&_eos_event_q, EOS_EVT_NET | net_state_type, _eos_spi_state_buf, net_state_len_rx); + if (r) net_bufq_push(_eos_spi_state_buf); + } else if (((net_state_flags & NET_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) { + net_state_next_buf = _eos_spi_state_buf; + net_state_flags &= ~NET_FLAG_ONEW; + } else { + net_bufq_push(_eos_spi_state_buf); } } static void net_handler_cts(void) { - GPIO_REG(GPIO_RISE_IP) = (0x1 << NET_PIN_CTS); + GPIO_REG(GPIO_RISE_IP) = (1 << NET_PIN_CTS); net_state_flags |= NET_FLAG_CTS; - if (net_state_flags & NET_FLAG_RDY) { + if (net_state_flags & NET_FLAG_RUN) { net_xchg_next(NULL); - } else { - uint32_t iof_mask = ((uint32_t)1 << NET_PIN_CS); - GPIO_REG(GPIO_IOF_EN) &= ~iof_mask; } } static void net_handler_rts(void) { - uint32_t rts_offset = (0x1 << NET_PIN_RTS); + uint32_t rts_offset = (1 << NET_PIN_RTS); if (GPIO_REG(GPIO_RISE_IP) & rts_offset) { GPIO_REG(GPIO_RISE_IP) = rts_offset; net_state_flags |= NET_FLAG_RTS; - if ((net_state_flags & NET_FLAG_RDY) && (net_state_flags & NET_FLAG_CTS)) net_xchg_reset(); + if ((net_state_flags & NET_FLAG_RUN) && (net_state_flags & NET_FLAG_CTS)) net_xchg_reset(); } else if (GPIO_REG(GPIO_FALL_IP) & rts_offset) { GPIO_REG(GPIO_FALL_IP) = rts_offset; net_state_flags &= ~NET_FLAG_RTS; @@ -253,76 +242,45 @@ void eos_net_set_handler(unsigned char mtype, eos_evt_fptr_t handler, uint8_t fl void eos_net_init(void) { int i; - - net_buf_q.idx_r = 0; - net_buf_q.idx_w = 0; - for (i=0; i<NET_SIZE_BUFQ; i++) { - net_bufq_push(net_bufq_array[i]); - } - eos_msgq_init(&net_send_q, net_sndq_array, NET_SIZE_BUFQ); - GPIO_REG(GPIO_IOF_SEL) &= ~SPI_IOF_MASK; - GPIO_REG(GPIO_IOF_EN) |= SPI_IOF_MASK; - eos_intr_set(INT_SPI1_BASE, 5, net_handler_xchg); - - GPIO_REG(GPIO_OUTPUT_EN) &= ~(0x1 << NET_PIN_CTS); - GPIO_REG(GPIO_PULLUP_EN) |= (0x1 << NET_PIN_CTS); - GPIO_REG(GPIO_INPUT_EN) |= (0x1 << NET_PIN_CTS); - GPIO_REG(GPIO_RISE_IE) |= (0x1 << NET_PIN_CTS); + GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << NET_PIN_CTS); + GPIO_REG(GPIO_PULLUP_EN) |= (1 << NET_PIN_CTS); + GPIO_REG(GPIO_INPUT_EN) |= (1 << NET_PIN_CTS); + GPIO_REG(GPIO_RISE_IE) |= (1 << NET_PIN_CTS); eos_intr_set(INT_GPIO_BASE + NET_PIN_CTS, 4, net_handler_cts); - - GPIO_REG(GPIO_OUTPUT_EN) &= ~(0x1 << NET_PIN_RTS); - GPIO_REG(GPIO_PULLUP_EN) |= (0x1 << NET_PIN_RTS); - GPIO_REG(GPIO_INPUT_EN) |= (0x1 << NET_PIN_RTS); - GPIO_REG(GPIO_RISE_IE) |= (0x1 << NET_PIN_RTS); - GPIO_REG(GPIO_FALL_IE) |= (0x1 << NET_PIN_RTS); + + GPIO_REG(GPIO_OUTPUT_EN) &= ~(1 << NET_PIN_RTS); + GPIO_REG(GPIO_PULLUP_EN) |= (1 << NET_PIN_RTS); + GPIO_REG(GPIO_INPUT_EN) |= (1 << NET_PIN_RTS); + GPIO_REG(GPIO_RISE_IE) |= (1 << NET_PIN_RTS); + GPIO_REG(GPIO_FALL_IE) |= (1 << NET_PIN_RTS); eos_intr_set(INT_GPIO_BASE + NET_PIN_RTS, 4, net_handler_rts); + net_bufq_init(); + eos_msgq_init(&net_send_q, net_sndq_array, NET_SIZE_BUFQ); for (i=0; i<EOS_NET_MAX_MTYPE; i++) { evt_handler[i] = eos_evtq_bad_handler; } eos_evtq_set_handler(EOS_EVT_NET, net_handler_evt); } -void eos_net_start(uint32_t sckdiv) { - uint32_t iof_mask = ((uint32_t)1 << NET_PIN_CS); - - GPIO_REG(GPIO_IOF_SEL) &= ~iof_mask; - GPIO_REG(GPIO_IOF_EN) |= iof_mask; - - SPI1_REG(SPI_REG_SCKDIV) = sckdiv; - SPI1_REG(SPI_REG_SCKMODE) = SPI_MODE0; - SPI1_REG(SPI_REG_FMT) = SPI_FMT_PROTO(SPI_PROTO_S) | - SPI_FMT_ENDIAN(SPI_ENDIAN_MSB) | - SPI_FMT_DIR(SPI_DIR_RX) | - SPI_FMT_LEN(8); - - // enable CS pin for selected channel/pin - SPI1_REG(SPI_REG_CSID) = NET_IDX_SS; - - // There is no way here to change the CS polarity. - // SPI1_REG(SPI_REG_CSDEF) = 0xFFFF; - +void eos_net_start(void) { + eos_intr_set_handler(INT_SPI1_BASE, net_xchg_handler); + SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_NET; + SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_NET; + clear_csr(mstatus, MSTATUS_MIE); - net_state_flags |= NET_FLAG_RDY; + net_state_flags |= NET_FLAG_RUN; if (net_state_flags & NET_FLAG_CTS) net_xchg_next(NULL); set_csr(mstatus, MSTATUS_MIE); } void eos_net_stop(void) { volatile uint8_t done = 0; - - clear_csr(mstatus, MSTATUS_MIE); - net_state_flags &= ~NET_FLAG_RDY; - if (net_state_flags & NET_FLAG_CTS) { - uint32_t iof_mask = ((uint32_t)1 << NET_PIN_CS); - GPIO_REG(GPIO_IOF_EN) &= ~iof_mask; - done = 1; - } - set_csr(mstatus, MSTATUS_MIE); - + while (!done) { clear_csr(mstatus, MSTATUS_MIE); + net_state_flags &= ~NET_FLAG_RUN; done = net_state_flags & NET_FLAG_CTS; if (!done) asm volatile ("wfi"); set_csr(mstatus, MSTATUS_MIE); @@ -331,7 +289,7 @@ void eos_net_stop(void) { int eos_net_acquire(unsigned char reserved) { int ret = 0; - + if (reserved) { while (!ret) { clear_csr(mstatus, MSTATUS_MIE); @@ -362,7 +320,7 @@ int eos_net_release(void) { if (!rv) net_state_next_buf = NULL; } set_csr(mstatus, MSTATUS_MIE); - + return rv; } @@ -379,7 +337,7 @@ unsigned char *eos_net_alloc(void) { } set_csr(mstatus, MSTATUS_MIE); } - + return ret; } @@ -391,7 +349,7 @@ int eos_net_free(unsigned char *buffer, unsigned char more) { if ((more || net_state_next_cnt) && (net_state_next_buf == NULL)) { net_state_next_buf = buffer; } else { - if ((net_state_flags & NET_FLAG_RDY) && (net_state_flags & NET_FLAG_CTS)) do_release = net_xchg_next(buffer); + if ((net_state_flags & NET_FLAG_RUN) && (net_state_flags & NET_FLAG_CTS)) do_release = net_xchg_next(buffer); if (do_release) rv = net_bufq_push(buffer); } set_csr(mstatus, MSTATUS_MIE); @@ -403,10 +361,10 @@ int eos_net_send(unsigned char type, unsigned char *buffer, uint16_t len) { int rv = EOS_OK; clear_csr(mstatus, MSTATUS_MIE); - if ((net_state_flags & NET_FLAG_RDY) && (net_state_flags & NET_FLAG_CTS)) { + if ((net_state_flags & NET_FLAG_RUN) && (net_state_flags & NET_FLAG_CTS)) { net_xchg_start(type, buffer, len); } else { - rv = eos_msgq_push(&net_send_q, EOS_EVT_NET | type, buffer, len); + rv = eos_msgq_push(&net_send_q, type, buffer, len); } set_csr(mstatus, MSTATUS_MIE); diff --git a/code/fe310/eos/net.h b/code/fe310/eos/net.h index d50ee94..4005fe5 100644 --- a/code/fe310/eos/net.h +++ b/code/fe310/eos/net.h @@ -16,8 +16,10 @@ #define EOS_NET_MAX_MTYPE 8 +void eos_net_xchg_done(void); + void eos_net_init(void); -void eos_net_start(uint32_t sckdiv); +void eos_net_start(void); void eos_net_stop(void); void eos_net_set_handler(unsigned char type, eos_evt_fptr_t handler, uint8_t flags); int eos_net_acquire(unsigned char reserved); diff --git a/code/fe310/eos/net_def.h b/code/fe310/eos/net_def.h index 2df2833..87e3fbe 100644 --- a/code/fe310/eos/net_def.h +++ b/code/fe310/eos/net_def.h @@ -3,10 +3,8 @@ #define NET_PIN_RTS 20 #define NET_PIN_CTS 22 -#define NET_PIN_CS 10 -#define NET_IDX_SS 3 -#define NET_FLAG_RDY 0x01 +#define NET_FLAG_RUN 0x01 #define NET_FLAG_RST 0x02 #define NET_FLAG_RTS 0x04 #define NET_FLAG_CTS 0x08 diff --git a/code/fe310/eos/spi.c b/code/fe310/eos/spi.c new file mode 100644 index 0000000..86a967d --- /dev/null +++ b/code/fe310/eos/spi.c @@ -0,0 +1,284 @@ +#include <stdlib.h> +#include <stdint.h> + +#include "encoding.h" +#include "platform.h" + +#include "eos.h" +#include "msgq.h" +#include "interrupt.h" +#include "event.h" + +#include "net.h" +#include "spi.h" +#include "spi_def.h" + +#define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) +#define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) +#define SPI_IOF_MASK (((uint32_t)1 << IOF_SPI1_SCK) | ((uint32_t)1 << IOF_SPI1_MOSI) | ((uint32_t)1 << IOF_SPI1_MISO)) | ((uint32_t)1 << IOF_SPI1_SS0) | ((uint32_t)1 << IOF_SPI1_SS2) | ((uint32_t)1 << IOF_SPI1_SS3) + +extern EOSMsgQ _eos_event_q; + +static uint8_t spi_dev; +static uint8_t spi_dev_cs; +static uint8_t spi_state_flags; + +uint32_t _eos_spi_state_len = 0; +uint32_t _eos_spi_state_idx_tx = 0; +uint32_t _eos_spi_state_idx_rx = 0; +unsigned char *_eos_spi_state_buf = NULL; + +static eos_evt_fptr_t evt_handler[EOS_SPI_MAX_DEV]; + +void spi_cs_set(void) { + /* cs low */ + if (SPI1_REG(SPI_REG_CSMODE) == SPI_CSMODE_OFF) { + GPIO_REG(GPIO_OUTPUT_VAL) &= ~(1 << spi_dev_cs); + } else { + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; + } + spi_state_flags &= ~SPI_FLAG_CS; +} + +void spi_cs_clear(void) { + /* cs high */ + if (SPI1_REG(SPI_REG_CSMODE) == SPI_CSMODE_OFF) { + GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << spi_dev_cs); + } else { + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; + } + spi_state_flags |= SPI_FLAG_CS; +} + +static void spi_flush(void) { + SPI1_REG(SPI_REG_RXCTRL) = SPI_TXWM(1); + while (!(SPI1_REG(SPI_REG_IP) & SPI_IP_TXWM)); + while (!(SPI1_REG(SPI_REG_RXFIFO) & SPI_RXFIFO_EMPTY)); +} + +static void spi_xchg_done(void) { + if (!(spi_state_flags & (EOS_SPI_FLAG_MORE | SPI_FLAG_CS))) spi_cs_clear(); + SPI1_REG(SPI_REG_IE) = 0x0; + spi_state_flags &= ~SPI_FLAG_XCHG; +} + +static void spi_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) { + unsigned char idx = (type & ~EOS_EVT_MASK) - 1; + if (idx < EOS_SPI_MAX_DEV) { + evt_handler[idx](type, buffer, len); + } else { + eos_evtq_bad_handler(type, buffer, len); + } +} + +void eos_spi_init(void) { + GPIO_REG(GPIO_OUTPUT_VAL) |= (1 << spi_dev_cs); + GPIO_REG(GPIO_INPUT_EN) &= ~(1 << SPI_CS_PIN_CAM); + GPIO_REG(GPIO_OUTPUT_EN) |= (1 << SPI_CS_PIN_CAM); + GPIO_REG(GPIO_OUTPUT_XOR) &= ~(1 << SPI_CS_PIN_CAM); + + SPI1_REG(SPI_REG_SCKMODE) = SPI_MODE0; + SPI1_REG(SPI_REG_FMT) = SPI_FMT_PROTO(SPI_PROTO_S) | + SPI_FMT_ENDIAN(SPI_ENDIAN_MSB) | + SPI_FMT_DIR(SPI_DIR_RX) | + SPI_FMT_LEN(8); + + GPIO_REG(GPIO_IOF_SEL) &= ~SPI_IOF_MASK; + GPIO_REG(GPIO_IOF_EN) |= SPI_IOF_MASK; + + // There is no way here to change the CS polarity. + // SPI1_REG(SPI_REG_CSDEF) = 0xFFFF; + + eos_intr_set(INT_SPI1_BASE, 5, NULL); + eos_evtq_set_handler(EOS_EVT_SPI, spi_handler_evt); + eos_spi_dev_release(); +} + +void eos_spi_dev_acquire(unsigned char dev) { + eos_net_stop(); + spi_dev = dev; + spi_state_flags = 0; + switch (dev) { + case EOS_SPI_DEV_DISP: + SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_DISP; + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; + SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_DISP; + break; + case EOS_SPI_DEV_CARD: + SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_CARD; + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; + SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_CARD; + break; + case EOS_SPI_DEV_CAM: + spi_dev_cs = SPI_CS_PIN_CAM; + SPI1_REG(SPI_REG_SCKDIV) = SPI_DIV_CAM; + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_OFF; + SPI1_REG(SPI_REG_CSID) = SPI_CS_IDX_NONE; + break; + } + eos_intr_set_handler(INT_SPI1_BASE, eos_spi_xchg_handler); +} + +void eos_spi_dev_release(void) { + eos_spi_xchg_wait(); + if (spi_state_flags & EOS_SPI_FLAG_TX) spi_flush(); + if (!(spi_state_flags & SPI_FLAG_CS)) spi_cs_clear(); + + spi_dev = EOS_SPI_DEV_NET; + eos_net_start(); +} + +void eos_spi_xchg(unsigned char *buffer, uint16_t len, uint8_t flags) { + if (!(flags & EOS_SPI_FLAG_TX) && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush(); + + spi_state_flags &= 0xF0; + spi_state_flags |= (SPI_FLAG_XCHG | flags); + _eos_spi_state_buf = buffer; + _eos_spi_state_len = len; + _eos_spi_state_idx_tx = 0; + _eos_spi_state_idx_rx = 0; + + if (spi_state_flags & SPI_FLAG_CS) spi_cs_set(); + SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM); + SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM; +} + +void eos_spi_xchg_handler(void) { + int i; + uint16_t sz_chunk = MIN(_eos_spi_state_len - _eos_spi_state_idx_tx, SPI_SIZE_CHUNK); + + for (i=0; i<sz_chunk; i++) { + volatile uint32_t x = SPI1_REG(SPI_REG_TXFIFO); + if (x & SPI_TXFIFO_FULL) break; + SPI1_REG(SPI_REG_TXFIFO) = _eos_spi_state_buf[_eos_spi_state_idx_tx+i]; + } + _eos_spi_state_idx_tx += i; + + for (i=0; i<_eos_spi_state_idx_tx - _eos_spi_state_idx_rx; i++) { + volatile uint32_t x = SPI1_REG(SPI_REG_RXFIFO); + if (x & SPI_RXFIFO_EMPTY) break; + _eos_spi_state_buf[_eos_spi_state_idx_rx+i] = x & 0xFF; + } + _eos_spi_state_idx_rx += i; + + if ((spi_state_flags & EOS_SPI_FLAG_TX) && _eos_spi_state_idx_tx == _eos_spi_state_len) { + spi_state_flags &= ~EOS_SPI_FLAG_TX; + spi_xchg_done(); + } else if (_eos_spi_state_idx_rx == _eos_spi_state_len) { + spi_xchg_done(); + if (spi_dev == EOS_SPI_DEV_NET) { + eos_net_xchg_done(); + } else { + eos_msgq_push(&_eos_event_q, EOS_EVT_SPI | spi_dev, _eos_spi_state_buf, _eos_spi_state_len); + } + } else if (_eos_spi_state_idx_tx == _eos_spi_state_len) { + SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(MIN(_eos_spi_state_len - _eos_spi_state_idx_rx - 1, SPI_SIZE_WM - 1)); + SPI1_REG(SPI_REG_IE) = SPI_IP_RXWM; + } +} + +void eos_spi_xchg_wait(void) { + volatile uint8_t done = 0; + + while (!done) { + clear_csr(mstatus, MSTATUS_MIE); + done = !(spi_state_flags & SPI_FLAG_XCHG); + if (!done) asm volatile ("wfi"); + set_csr(mstatus, MSTATUS_MIE); + } +} + +uint8_t eos_spi_xchg8(uint8_t data, uint8_t flags) { + volatile uint32_t x = 0; + uint8_t rx = !(flags & EOS_SPI_FLAG_TX); + + if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush(); + + spi_state_flags &= 0xF0; + spi_state_flags |= flags; + if (spi_state_flags & SPI_FLAG_CS) spi_cs_set(); + + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = data; + + if (rx) { + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + } + + if (!(spi_state_flags & (EOS_SPI_FLAG_MORE | SPI_FLAG_CS))) spi_cs_clear(); + + return x & 0xFF; +} + +uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags) { + volatile uint32_t x = 0; + uint8_t rx = !(flags & EOS_SPI_FLAG_TX); + uint16_t r; + + if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush(); + + spi_state_flags &= 0xF0; + spi_state_flags |= flags; + if (spi_state_flags & SPI_FLAG_CS) spi_cs_set(); + + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF00) >> 8; + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF); + + if (rx) { + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + r = (x & 0xFF) << 8; + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + r |= x & 0xFF; + } + + if (!(spi_state_flags & (EOS_SPI_FLAG_MORE | SPI_FLAG_CS))) spi_cs_clear(); + + return x & 0xFF; +} + +uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags) { + volatile uint32_t x = 0; + uint8_t rx = !(flags & EOS_SPI_FLAG_TX); + uint32_t r; + + if (rx && (spi_state_flags & EOS_SPI_FLAG_TX)) spi_flush(); + + spi_state_flags &= 0xF0; + spi_state_flags |= flags; + if (spi_state_flags & SPI_FLAG_CS) spi_cs_set(); + + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = (data & 0xFF000000) >> 24; + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = (data & 0x00FF0000) >> 16; + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = (data & 0x0000FF00) >> 8; + while (SPI1_REG(SPI_REG_TXFIFO) & SPI_TXFIFO_FULL); + SPI1_REG(SPI_REG_TXFIFO) = (data & 0x000000FF); + + if (rx) { + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + r = (x & 0xFF) << 24; + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + r |= (x & 0xFF) << 16; + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + r |= (x & 0xFF) << 8; + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + r |= x & 0xFF; + } + + if (!(spi_state_flags & (EOS_SPI_FLAG_MORE | SPI_FLAG_CS))) spi_cs_clear(); + + return r; +} + +void eos_spi_set_handler(unsigned char dev, eos_evt_fptr_t handler) { + if (dev && (dev <= EOS_SPI_MAX_DEV)) { + dev--; + } else { + return; + } + evt_handler[dev] = handler; +} diff --git a/code/fe310/eos/spi.h b/code/fe310/eos/spi.h index 9ef3745..b230924 100644 --- a/code/fe310/eos/spi.h +++ b/code/fe310/eos/spi.h @@ -1,8 +1,25 @@ #include <stdint.h> -#include "encoding.h" -#include "platform.h" +#define EOS_SPI_DEV_NET 0 +#define EOS_SPI_DEV_DISP 1 +#define EOS_SPI_DEV_CARD 2 +#define EOS_SPI_DEV_CAM 3 -#include "spi_def.h" +#define EOS_SPI_MAX_DEV 3 -#define SPI_IOF_MASK (((uint32_t)1 << IOF_SPI1_SCK) | ((uint32_t)1 << IOF_SPI1_MOSI) | ((uint32_t)1 << IOF_SPI1_MISO)) +#define EOS_SPI_FLAG_TX 0x01 +#define EOS_SPI_FLAG_MORE 0x02 + +void eos_spi_init(void); +void eos_spi_dev_acquire(unsigned char dev); +void eos_spi_dev_release(void); + +void eos_spi_xchg(unsigned char *buffer, uint16_t len, uint8_t flags); +void eos_spi_xchg_handler(void); +void eos_spi_xchg_wait(void); + +uint8_t eos_spi_xchg8(uint8_t data, uint8_t flags); +uint16_t eos_spi_xchg16(uint16_t data, uint8_t flags); +uint32_t eos_spi_xchg32(uint32_t data, uint8_t flags); + +void eos_spi_set_handler(unsigned char dev, eos_evt_fptr_t handler);
\ No newline at end of file diff --git a/code/fe310/eos/spi_def.h b/code/fe310/eos/spi_def.h index 0c90b6d..7c7f817 100644 --- a/code/fe310/eos/spi_def.h +++ b/code/fe310/eos/spi_def.h @@ -7,3 +7,18 @@ #define SPI_SIZE_CHUNK 4 #define SPI_SIZE_WM 2 +#define SPI_FLAG_XCHG 0x10 +#define SPI_FLAG_CS 0x20 + +#define SPI_DIV_NET 16 +#define SPI_DIV_DISP 16 +#define SPI_DIV_CARD 16 +#define SPI_DIV_CAM 16 + + +#define SPI_CS_IDX_NET 3 +#define SPI_CS_IDX_DISP 2 +#define SPI_CS_IDX_CARD 0 +#define SPI_CS_IDX_NONE 1 + +#define SPI_CS_PIN_CAM 23 diff --git a/code/fe310/eos/timer.c b/code/fe310/eos/timer.c index 25b7e7e..6589c06 100644 --- a/code/fe310/eos/timer.c +++ b/code/fe310/eos/timer.c @@ -1,5 +1,5 @@ -#include <stddef.h> -#include <stdio.h> +#include <stdlib.h> +#include <stdint.h> #include "encoding.h" #include "platform.h" @@ -88,7 +88,7 @@ void eos_timer_set(uint64_t tick, unsigned char evt, unsigned char b) { int i; uint64_t *mtimecmp = (uint64_t *) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); uint64_t next = 0; - + if (evt && (evt <= EOS_TIMER_MAX_ETYPE)) { evt--; } else if (evt == 0) { diff --git a/code/fe310/eos/trap_entry.S b/code/fe310/eos/trap_entry.S index 7b32050..91a44dc 100644 --- a/code/fe310/eos/trap_entry.S +++ b/code/fe310/eos/trap_entry.S @@ -404,8 +404,8 @@ _eos_i2s_start_pwm: ret -.global eos_flash_set -eos_flash_set: +.global _eos_flash_set +_eos_flash_set: li a3, SPI0_CTRL_ADDR sw x0, SPI_REG_FCTRL(a3) sw a0, SPI_REG_SCKDIV(a3) |