summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorUros Majstorovic <majstor@majstor.org>2019-10-18 18:38:00 +0200
committerUros Majstorovic <majstor@majstor.org>2019-10-18 18:38:00 +0200
commit85500fe0d01b691a9bdd8c2330d26d66bc2bc177 (patch)
treec320c642ebb942d1b3692701d50c4a46e50e49f3
parentf74dcae328e3650acf6b12499a55548b46117877 (diff)
added spi driver
-rw-r--r--code/fe310/eos/Makefile4
-rw-r--r--code/fe310/eos/ecp.c13
-rw-r--r--code/fe310/eos/eos.c6
-rw-r--r--code/fe310/eos/eos.h2
-rw-r--r--code/fe310/eos/event.c10
-rw-r--r--code/fe310/eos/i2s.c4
-rw-r--r--code/fe310/eos/interrupt.c4
-rw-r--r--code/fe310/eos/interrupt.h1
-rw-r--r--code/fe310/eos/msgq.c5
-rw-r--r--code/fe310/eos/net.c226
-rw-r--r--code/fe310/eos/net.h4
-rw-r--r--code/fe310/eos/net_def.h4
-rw-r--r--code/fe310/eos/spi.c284
-rw-r--r--code/fe310/eos/spi.h25
-rw-r--r--code/fe310/eos/spi_def.h15
-rw-r--r--code/fe310/eos/timer.c6
-rw-r--r--code/fe310/eos/trap_entry.S4
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)