diff options
Diffstat (limited to 'fw/fe310/eos/net.c')
-rw-r--r-- | fw/fe310/eos/net.c | 223 |
1 files changed, 130 insertions, 93 deletions
diff --git a/fw/fe310/eos/net.c b/fw/fe310/eos/net.c index 5edb013..197c2b1 100644 --- a/fw/fe310/eos/net.c +++ b/fw/fe310/eos/net.c @@ -20,12 +20,12 @@ #include "net.h" #define NET_STATE_FLAG_RUN 0x01 -#define NET_STATE_FLAG_RST 0x02 -#define NET_STATE_FLAG_RTS 0x04 -#define NET_STATE_FLAG_CTS 0x08 -#define NET_STATE_FLAG_INIT 0x10 -#define NET_STATE_FLAG_ONEW 0x20 -#define NET_STATE_FLAG_XCHG 0x40 +#define NET_STATE_FLAG_INIT 0x02 +#define NET_STATE_FLAG_XCHG 0x04 +#define NET_STATE_FLAG_ONEW 0x10 +#define NET_STATE_FLAG_REPW 0x20 +#define NET_STATE_FLAG_RTS 0x40 +#define NET_STATE_FLAG_CTS 0x80 #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) @@ -54,12 +54,11 @@ static int net_xchg_sleep(void) { int i; int rv = EOS_OK; volatile uint32_t x = 0; - net_state_flags &= ~NET_STATE_FLAG_CTS; SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; - SPI1_REG(SPI_REG_TXFIFO) = 0xff; + SPI1_REG(SPI_REG_TXFIFO) = 0xFF; while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); if (x & 0xFF) rv = EOS_ERR_BUSY; @@ -77,6 +76,7 @@ static int net_xchg_sleep(void) { static void net_xchg_wake(void) { int i; volatile uint32_t x = 0; + net_state_flags &= ~NET_STATE_FLAG_CTS; SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; @@ -90,13 +90,15 @@ static void net_xchg_wake(void) { } static void net_xchg_reset(void) { + volatile uint32_t x = 0; net_state_flags &= ~NET_STATE_FLAG_CTS; - net_state_flags |= (NET_STATE_FLAG_RST | NET_STATE_FLAG_XCHG); SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; + SPI1_REG(SPI_REG_TXFIFO) = 0; - SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(0); - SPI1_REG(SPI_REG_IE) = SPI_IP_RXWM; + while ((x = SPI1_REG(SPI_REG_RXFIFO)) & SPI_RXFIFO_EMPTY); + + SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; } static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t len) { @@ -105,6 +107,7 @@ static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t l if (net_state_next_cnt && (net_state_next_buf == NULL)) type |= EOS_NET_MTYPE_FLAG_ONEW; if (type & EOS_NET_MTYPE_FLAG_ONEW) net_state_flags |= NET_STATE_FLAG_ONEW; + if (type & EOS_NET_MTYPE_FLAG_REPW) net_state_flags |= NET_STATE_FLAG_REPW; net_state_type = type; net_state_len_tx = len; @@ -123,40 +126,36 @@ static int net_xchg_next(unsigned char *_buffer) { unsigned char type; unsigned char *buffer = NULL; uint16_t len; + int ret = _buffer ? 1 : 0; eos_msgq_pop(&net_send_q, &type, &buffer, &len); if (type) { net_xchg_start(type, buffer, len); } else if (net_state_flags & NET_STATE_FLAG_RTS) { - if (_buffer == NULL) _buffer = eos_bufq_pop(&net_buf_q); if (_buffer) { - net_xchg_start(0, _buffer, 0); - return 0; + buffer = _buffer; + ret = 0; + } else { + buffer = eos_bufq_pop(&net_buf_q); } + if (buffer) net_xchg_start(0, buffer, 0); } - return 1; + + return ret; } static void net_handle_xchg(void) { volatile uint32_t r1, r2, r3; uint32_t len; - if (net_state_flags & NET_STATE_FLAG_RST) { - net_state_flags &= ~(NET_STATE_FLAG_RST | NET_STATE_FLAG_XCHG); - - r1 = SPI1_REG(SPI_REG_RXFIFO); - SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; - SPI1_REG(SPI_REG_IE) = 0x0; - - return; - } else if (net_state_flags & NET_STATE_FLAG_INIT) { + if (net_state_flags & NET_STATE_FLAG_INIT) { net_state_flags &= ~NET_STATE_FLAG_INIT; r1 = SPI1_REG(SPI_REG_RXFIFO); r2 = SPI1_REG(SPI_REG_RXFIFO); r3 = SPI1_REG(SPI_REG_RXFIFO); - if (net_state_flags & NET_STATE_FLAG_ONEW) { + if (net_state_flags & (NET_STATE_FLAG_ONEW | NET_STATE_FLAG_REPW)) { r1 = 0; r2 = 0; r3 = 0; @@ -189,14 +188,18 @@ static void net_handle_xchg(void) { eos_spi_handle_xchg(); if (SPI1_REG(SPI_REG_CSMODE) == SPI_CSMODE_AUTO) { // exchange done - if (net_state_type) { - int r = eos_evtq_push_isr(EOS_EVT_NET | net_state_type, net_state_buf, net_state_len_rx); - if (r) eos_bufq_push(&net_buf_q, net_state_buf); - } else if (((net_state_flags & NET_STATE_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) { - net_state_next_buf = net_state_buf; - net_state_flags &= ~NET_STATE_FLAG_ONEW; + if (net_state_flags & NET_STATE_FLAG_REPW) { + net_state_flags &= ~NET_STATE_FLAG_REPW; } else { - eos_bufq_push(&net_buf_q, net_state_buf); + if (net_state_type) { + int r = eos_evtq_push_isr(EOS_EVT_NET | net_state_type, net_state_buf, net_state_len_rx); + if (r) eos_bufq_push(&net_buf_q, net_state_buf); + } else if (((net_state_flags & NET_STATE_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) { + net_state_next_buf = net_state_buf; + net_state_flags &= ~NET_STATE_FLAG_ONEW; + } else { + eos_bufq_push(&net_buf_q, net_state_buf); + } } net_state_flags &= ~NET_STATE_FLAG_XCHG; } @@ -216,7 +219,9 @@ static void net_handle_rts(void) { if (GPIO_REG(GPIO_RISE_IP) & rts_offset) { GPIO_REG(GPIO_RISE_IP) = rts_offset; net_state_flags |= NET_STATE_FLAG_RTS; - if ((net_state_flags & NET_STATE_FLAG_RUN) && (net_state_flags & NET_STATE_FLAG_CTS)) net_xchg_reset(); + if ((net_state_flags & NET_STATE_FLAG_RUN) && (net_state_flags & NET_STATE_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_STATE_FLAG_RTS; @@ -272,10 +277,12 @@ static void evt_handler_wrapper(unsigned char type, unsigned char *buffer, uint1 } static void evt_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); + unsigned char idx = (type & EOS_EVT_MASK) >> 4; - if (idx < EOS_EVT_MAX_EVT) { + if (idx && (idx <= EOS_EVT_MAX_EVT)) { + uint16_t flag = (uint16_t)1 << (type & ~EOS_EVT_MASK); + + idx--; if (flag & net_flags_acq[idx]) { evt_handler_wrapper(type, buffer, len, idx, flag); } else { @@ -286,6 +293,17 @@ static void evt_handler(unsigned char type, unsigned char *buffer, uint16_t len) } } +static void net_pause(void) { + net_state_flags &= ~NET_STATE_FLAG_RUN; +} + +static void net_resume(void) { + net_state_flags |= NET_STATE_FLAG_RUN; + if (net_state_flags & NET_STATE_FLAG_CTS) { + net_xchg_next(NULL); + } +} + void eos_net_init(void) { int i; @@ -317,18 +335,33 @@ void eos_net_init(void) { 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, IRQ_PRIORITY_NET_RTS, net_handle_rts); + + /* set initial state */ + clear_csr(mstatus, MSTATUS_MIE); + if (GPIO_REG(GPIO_INPUT_VAL) & (1 << NET_PIN_CTS)) net_state_flags |= NET_STATE_FLAG_CTS; + if (GPIO_REG(GPIO_INPUT_VAL) & (1 << NET_PIN_RTS)) net_state_flags |= NET_STATE_FLAG_RTS; + set_csr(mstatus, MSTATUS_MIE); } -void eos_net_start(void) { +void eos_net_start(uint8_t wakeup_cause) { eos_intr_set_handler(INT_SPI1_BASE, net_handle_xchg); SPI1_REG(SPI_REG_SCKDIV) = eos_spi_div(EOS_SPI_DEV_NET); SPI1_REG(SPI_REG_CSID) = eos_spi_csid(EOS_SPI_DEV_NET); clear_csr(mstatus, MSTATUS_MIE); - net_state_flags |= NET_STATE_FLAG_RUN; - if (net_state_flags & NET_STATE_FLAG_CTS) { - net_xchg_next(NULL); + if (wakeup_cause) { + if (wakeup_cause != EOS_PWR_WAKE_BTN) { + net_xchg_wake(); + } + if (!(net_state_flags & NET_STATE_FLAG_CTS)) { + while (!(GPIO_REG(GPIO_RISE_IP) & (1 << NET_PIN_CTS))) { + asm volatile ("wfi"); + } + GPIO_REG(GPIO_RISE_IP) = (1 << NET_PIN_CTS); + } + net_xchg_reset(); } + net_resume(); set_csr(mstatus, MSTATUS_MIE); } @@ -395,39 +428,6 @@ int eos_net_sleep(uint32_t timeout) { return rv; } -int eos_net_wake(uint8_t source) { - int rv = EOS_OK; - - clear_csr(mstatus, MSTATUS_MIE); - if (net_state_flags & NET_STATE_FLAG_RUN) rv = EOS_ERR; - set_csr(mstatus, MSTATUS_MIE); - - if (rv) return rv; - - eos_intr_set_handler(INT_SPI1_BASE, net_handle_xchg); - SPI1_REG(SPI_REG_SCKDIV) = eos_spi_div(EOS_SPI_DEV_NET); - SPI1_REG(SPI_REG_CSID) = eos_spi_csid(EOS_SPI_DEV_NET); - - clear_csr(mstatus, MSTATUS_MIE); - net_state_flags |= NET_STATE_FLAG_RUN; - if (source) { - if (source != EOS_PWR_WAKE_BTN) { - net_xchg_wake(); - } - if (!(net_state_flags & NET_STATE_FLAG_CTS)) { - while (!(GPIO_REG(GPIO_RISE_IP) & (1 << NET_PIN_CTS))) { - asm volatile ("wfi"); - } - GPIO_REG(GPIO_RISE_IP) = (1 << NET_PIN_CTS); - } - net_xchg_reset(); - if (GPIO_REG(GPIO_INPUT_VAL) & (1 << NET_PIN_RTS)) net_state_flags |= NET_STATE_FLAG_RTS; - } - set_csr(mstatus, MSTATUS_MIE); - - return rv; -} - void eos_net_bad_handler(unsigned char type, unsigned char *buffer, uint16_t len) { eos_evtq_bad_handler(type, buffer, len); if (buffer) eos_net_free(buffer, 0); @@ -439,10 +439,11 @@ void eos_net_set_handler(unsigned char mtype, eos_evt_handler_t handler) { } void eos_net_acquire_for_evt(unsigned char type, char acq) { - unsigned char idx = ((type & EOS_EVT_MASK) >> 4) - 1; - uint16_t flag = type & ~EOS_EVT_MASK ? (uint16_t)1 << ((type & ~EOS_EVT_MASK) - 1) : 0xFFFF; + unsigned char idx = (type & EOS_EVT_MASK) >> 4; + uint16_t flag = type & ~EOS_EVT_MASK ? (uint16_t)1 << (type & ~EOS_EVT_MASK) : 0xFFFF; - if (idx < EOS_EVT_MAX_EVT) { + if (idx && (idx <= EOS_EVT_MAX_EVT)) { + idx--; net_flags_acq[idx] &= ~flag; if (acq) net_flags_acq[idx] |= flag; } @@ -486,45 +487,81 @@ void 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_STATE_FLAG_RUN) && (net_state_flags & NET_STATE_FLAG_CTS)) do_release = net_xchg_next(buffer); - if (do_release) eos_bufq_push(&net_buf_q, buffer); + if ((net_state_flags & NET_STATE_FLAG_RUN) && (net_state_flags & NET_STATE_FLAG_CTS)) { + do_release = net_xchg_next(buffer); + } + if (do_release) { + eos_bufq_push(&net_buf_q, buffer); + } } set_csr(mstatus, MSTATUS_MIE); } -int eos_net_send(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char more) { +static int net_xchg(unsigned char *type, unsigned char *buffer, uint16_t *len) { int rv = EOS_OK; - - if (more) type |= EOS_NET_MTYPE_FLAG_ONEW; + int _sync = 0; + unsigned char _type = *type; + uint16_t _len = *len; + uint8_t spi_dev = EOS_SPI_DEV_NET; clear_csr(mstatus, MSTATUS_MIE); - if ((type & EOS_NET_MTYPE_FLAG_ONEW) && !(net_state_flags & NET_STATE_FLAG_RUN)) { - uint8_t spi_dev; + if ((_type & EOS_NET_MTYPE_FLAG_REPW) || ((_type & EOS_NET_MTYPE_FLAG_ONEW) && !(net_state_flags & NET_STATE_FLAG_RUN))) _sync = 1; + + if (!(net_state_flags & NET_STATE_FLAG_RUN) && _sync) { + int _rv; set_csr(mstatus, MSTATUS_MIE); spi_dev = eos_spi_dev(); - rv = eos_spi_deselect(); - if (rv) return rv; - + _rv = eos_spi_deselect(); + if (_rv) return _rv; clear_csr(mstatus, MSTATUS_MIE); + } + + if (_sync) { + net_pause(); while (!(net_state_flags & NET_STATE_FLAG_CTS)) { asm volatile ("wfi"); set_csr(mstatus, MSTATUS_MIE); clear_csr(mstatus, MSTATUS_MIE); } - net_xchg_start(type, buffer, len); - set_csr(mstatus, MSTATUS_MIE); - - eos_spi_select(spi_dev); + net_xchg_start(_type, buffer, _len); + if (_type & EOS_NET_MTYPE_FLAG_REPW) { + while (!(net_state_flags & NET_STATE_FLAG_CTS)) { + asm volatile ("wfi"); + set_csr(mstatus, MSTATUS_MIE); + clear_csr(mstatus, MSTATUS_MIE); + } + net_xchg_start(0, buffer, 0); + while (net_state_flags & NET_STATE_FLAG_XCHG) { + asm volatile ("wfi"); + set_csr(mstatus, MSTATUS_MIE); + clear_csr(mstatus, MSTATUS_MIE); + } + *type = net_state_type; + *len = net_state_len_rx; + } + net_resume(); } else { if ((net_state_flags & NET_STATE_FLAG_RUN) && (net_state_flags & NET_STATE_FLAG_CTS)) { - net_xchg_start(type, buffer, len); + net_xchg_start(_type, buffer, _len); } else { - rv = eos_msgq_push(&net_send_q, type, buffer, len); + rv = eos_msgq_push(&net_send_q, _type, buffer, _len); if (rv) eos_bufq_push(&net_buf_q, buffer); } - set_csr(mstatus, MSTATUS_MIE); } + set_csr(mstatus, MSTATUS_MIE); + if (spi_dev != EOS_SPI_DEV_NET) eos_spi_select(spi_dev); + return rv; } + +int eos_net_send(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char more) { + if (more) type |= EOS_NET_MTYPE_FLAG_ONEW; + return net_xchg(&type, buffer, &len); +} + +int eos_net_xchg(unsigned char *type, unsigned char *buffer, uint16_t *len) { + *type |= EOS_NET_MTYPE_FLAG_REPW; + return net_xchg(type, buffer, len); +} |