diff options
Diffstat (limited to 'fw/fe310/eos/dev/net.c')
| -rw-r--r-- | fw/fe310/eos/dev/net.c | 282 |
1 files changed, 158 insertions, 124 deletions
diff --git a/fw/fe310/eos/dev/net.c b/fw/fe310/eos/dev/net.c index c1fd9b5..7ab4947 100644 --- a/fw/fe310/eos/dev/net.c +++ b/fw/fe310/eos/dev/net.c @@ -7,7 +7,6 @@ #include "eos.h" #include "log.h" -#include "msgq.h" #include "event.h" #include "soc/interrupt.h" @@ -24,36 +23,36 @@ #define NET_DETECT_TIMEOUT 1000 #define NET_SIZE_HDR 3 +#define NET_SIZE_BUFQ 2 + #define NET_STATE_FLAG_RUN 0x0001 -#define NET_STATE_FLAG_INIT 0x0002 -#define NET_STATE_FLAG_XCHG 0x0004 -#define NET_STATE_FLAG_ONEW 0x0010 -#define NET_STATE_FLAG_SYNC 0x0020 -#define NET_STATE_FLAG_RTS 0x0040 -#define NET_STATE_FLAG_CTS 0x0080 +#define NET_STATE_FLAG_RTS 0x0002 +#define NET_STATE_FLAG_CTS 0x0004 +#define NET_STATE_FLAG_INIT 0x0010 +#define NET_STATE_FLAG_XCHG 0x0020 +#define NET_STATE_FLAG_ONEW 0x0040 +#define NET_STATE_FLAG_SYNC 0x0080 #define NET_STATE_FLAG_SLEEP 0x0100 #define NET_STATE_FLAG_SLEEP_REQ 0x0200 #define NET_STATE_FLAG_ABSENT 0x0400 - -#define NET_FLAG_MORE 0x01 -#define NET_FLAG_SYNC 0x02 -#define NET_FLAG_REPL 0x04 +#define NET_STATE_FLAG_ERR_SIZE 0x0800 #define MIN(X, Y) (((X) < (Y)) ? (X) : (Y)) #define MAX(X, Y) (((X) > (Y)) ? (X) : (Y)) static EOSBufQ net_buf_q; -static unsigned char *net_bufq_array[EOS_NET_SIZE_BUFQ]; -static unsigned char net_bufq_buffer[EOS_NET_SIZE_BUFQ][EOS_NET_SIZE_BUF] __attribute__((section (".itim2"))); +static unsigned char *net_bufq_array[NET_SIZE_BUFQ]; +static unsigned char net_bufq_buffer[NET_SIZE_BUFQ][EOS_NET_MTU] __attribute__((section (".itim2"))); static EOSMsgQ net_send_q; -static EOSMsgItem net_sndq_array[EOS_NET_SIZE_BUFQ]; +static EOSMsgItem net_sndq_array[NET_SIZE_BUFQ]; static volatile uint16_t net_state_flags = 0; static volatile unsigned char net_state_type = 0; static uint32_t net_state_len_tx = 0; static volatile uint32_t net_state_len_rx = 0; static unsigned char *net_state_buf = NULL; +static uint16_t net_state_buf_sz = 0; static volatile uint8_t net_state_next_cnt = 0; static unsigned char * volatile net_state_next_buf = NULL; @@ -96,8 +95,8 @@ static void net_xchg_sleep_req(void) { SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; } -static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t len) { - net_state_flags &= ~NET_STATE_FLAG_CTS; +static void net_xchg_start(unsigned char type, EOSMessage *msg, uint16_t len) { + net_state_flags &= ~(NET_STATE_FLAG_CTS | NET_STATE_FLAG_ERR_SIZE); net_state_flags |= (NET_STATE_FLAG_INIT | NET_STATE_FLAG_XCHG); if (net_state_next_cnt && (net_state_next_buf == NULL)) type |= EOS_NET_MTYPE_FLAG_ONEW; @@ -106,7 +105,8 @@ static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t l net_state_type = type; net_state_len_tx = len; net_state_len_rx = 0; - net_state_buf = buffer; + net_state_buf = msg->buffer; + net_state_buf_sz = msg->size; SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; SPI1_REG(SPI_REG_TXFIFO) = type; @@ -116,23 +116,24 @@ 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) { +static int net_xchg_next(EOSMessage *_msg) { unsigned char type; - unsigned char *buffer = NULL; + EOSMessage msg; uint16_t len; - int do_release = _buffer ? 1 : 0; + int do_release = _msg ? 1 : 0; - eos_msgq_pop(&net_send_q, &type, &buffer, &len); + eos_msgq_pop(&net_send_q, &type, &msg, &len); if (type) { - net_xchg_start(type, buffer, len); + net_xchg_start(type, &msg, len); } else if (net_state_flags & NET_STATE_FLAG_RTS) { - if (_buffer) { - buffer = _buffer; + if (_msg) { + msg = *_msg; do_release = 0; } else { - buffer = eos_bufq_pop(&net_buf_q); + msg.buffer = eos_bufq_pop(&net_buf_q); + msg.size = EOS_NET_MTU; } - if (buffer) net_xchg_start(0, buffer, 0); + if (msg.buffer) net_xchg_start(0, &msg, 0); } return do_release; @@ -155,42 +156,50 @@ static void net_handle_xchg(void) { r3 = 0; } - net_state_type = (r1 & EOS_NET_MTYPE_MASK); + net_state_type = r1; net_state_len_rx = (r2 & 0xFF) << 8; net_state_len_rx |= (r3 & 0xFF); len = MAX(net_state_len_tx, net_state_len_rx); - // esp32 dma workaraund + /* esp32 dma workaraund */ if (len < 8 - NET_SIZE_HDR) { len = 8 - NET_SIZE_HDR; } else if ((len + NET_SIZE_HDR) % 4 != 0) { len = ((len + NET_SIZE_HDR)/4 + 1) * 4 - NET_SIZE_HDR; } - if (len > EOS_NET_MTU) { + if (len > net_state_buf_sz) { + net_state_type = 0; + net_state_len_tx = 0; + net_state_len_rx = 0; + net_state_flags |= NET_STATE_FLAG_ERR_SIZE; net_state_flags &= ~NET_STATE_FLAG_XCHG; SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; SPI1_REG(SPI_REG_IE) = 0x0; return; } - _eos_spi_xchg_init(net_state_buf, len, 0); + _eos_spi_xchg_init(net_state_buf, net_state_buf_sz, len, 0); SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM); SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM; return; } eos_spi_handle_xchg(); - if (SPI1_REG(SPI_REG_CSMODE) == SPI_CSMODE_AUTO) { // exchange done + if (SPI1_REG(SPI_REG_CSMODE) == SPI_CSMODE_AUTO) { + /* exchange done */ if (!(net_state_flags & NET_STATE_FLAG_SYNC)) { if (net_state_type) { if (net_state_type == EOS_NET_MTYPE_SLEEP) { net_state_flags |= NET_STATE_FLAG_SLEEP; eos_bufq_push(&net_buf_q, net_state_buf); } else { + EOSMessage msg; int rv; - rv = eos_evtq_push_isr(EOS_EVT_NET | (net_state_type & ~EOS_EVT_MASK), net_state_buf, net_state_len_rx); + msg.buffer = net_state_buf; + msg.size = net_state_buf_sz; + rv = eos_evtq_push_isr(EOS_EVT_NET | (net_state_type & EOS_NET_MTYPE_MASK), &msg, net_state_len_rx); if (rv) { EOS_LOG(EOS_LOG_ERR, "NET XCHG EVTQ PUSH ERR:%d\n", rv); eos_bufq_push(&net_buf_q, net_state_buf); @@ -202,7 +211,7 @@ static void net_handle_xchg(void) { eos_bufq_push(&net_buf_q, net_state_buf); } } - net_state_flags &= ~(NET_STATE_FLAG_ONEW | NET_STATE_FLAG_XCHG); + net_state_flags &= ~(NET_STATE_FLAG_XCHG | NET_STATE_FLAG_ONEW); } } @@ -232,13 +241,20 @@ static void net_handle_rts(void) { } } -static void net_handle_evt(unsigned char type, unsigned char *buffer, uint16_t len) { - unsigned char idx = (type & ~EOS_EVT_MASK); +static void net_handle_evt(unsigned char type, EOSMessage *msg, uint16_t len) { + unsigned char idx; - if (idx && (idx <= EOS_NET_MAX_MTYPE)) { - net_handler[idx - 1](type, buffer, len); + idx = type & EOS_NET_MTYPE_FLAG_BRIDGE ? EOS_NET_MTYPE_BRIDGE : (type & ~EOS_EVT_MASK); + type &= ~EOS_EVT_MASK; + if (msg && (idx < EOS_NET_MAX_MTYPE)) { + net_handler[idx](type, msg, len); } else { - eos_net_bad_handler(type, buffer, len); + eos_net_bad_handler(type, msg, len); + } + if (msg && msg->buffer) { + eos_net_free(msg, 0); + } else { + eos_net_release(); } } @@ -268,17 +284,17 @@ static int net_acquire(unsigned char reserved) { return ret; } -static void evt_handler_wrapper(unsigned char type, unsigned char *buffer, uint16_t len, uint8_t idx) { +static void evt_handler_wrapper(unsigned char type, EOSMessage *msg, uint16_t len, uint8_t idx) { uint16_t flag = (uint16_t)1 << idx; int rv; rv = net_acquire(net_wrapper_acq & flag); if (rv) { - eos_evtq_get_handler(type)(type, buffer, len); + eos_evtq_get_handler(type)(type, msg, len); eos_net_release(); net_wrapper_acq &= ~flag; } else { - rv = eos_evtq_push_widx(type, buffer, len, &idx); + rv = eos_evtq_push_widx(type, msg, len, &idx); if (rv) { EOS_LOG(EOS_LOG_ERR, "NET WRAPPER EVTQ PUSH ERR:%d\n", rv); return; @@ -288,7 +304,7 @@ 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, uint8_t _idx) { +static void evt_handler(unsigned char type, EOSMessage *msg, uint16_t len, uint8_t _idx) { unsigned char idx = (type & EOS_EVT_MASK) >> 4; if (idx && (idx <= EOS_EVT_MAX)) { @@ -296,12 +312,12 @@ static void evt_handler(unsigned char type, unsigned char *buffer, uint16_t len, idx--; if (flag & net_flags_acq[idx]) { - evt_handler_wrapper(type, buffer, len, _idx); + evt_handler_wrapper(type, msg, len, _idx); } else { - eos_evtq_get_handler(type)(type, buffer, len); + eos_evtq_get_handler(type)(type, msg, len); } } else { - eos_evtq_bad_handler(type, buffer, len); + eos_evtq_bad_handler(type, msg, len); } } @@ -329,23 +345,31 @@ static void net_wait4cts(void) { } } -static void net_wake(void) { +static int net_wake(void) { + uint32_t start, timeout; + + start = eos_get_tick(); + timeout = NET_DETECT_TIMEOUT; while (net_state_flags & NET_STATE_FLAG_SLEEP) { + if (timeout && (eos_tdelta_ms(start) > timeout)) return EOS_ERR_NOTFOUND; net_xchg_reset(); eos_sleep(10); set_csr(mstatus, MSTATUS_MIE); clear_csr(mstatus, MSTATUS_MIE); } + + return EOS_OK; } static int net_select(int *dsel) { + int rv; + *dsel = 0; if (net_state_flags & NET_STATE_FLAG_ABSENT) return EOS_ERR_NOTFOUND; if (net_state_flags & NET_STATE_FLAG_SLEEP_REQ) return EOS_ERR_BUSY; + rv = EOS_OK; if (!(net_state_flags & NET_STATE_FLAG_RUN)) { - int rv; - set_csr(mstatus, MSTATUS_MIE); rv = eos_spi_select(EOS_SPI_DEV_NET); clear_csr(mstatus, MSTATUS_MIE); @@ -353,9 +377,9 @@ static int net_select(int *dsel) { *dsel = 1; } /* wake up remote if sleeping */ - net_wake(); + if (net_state_flags & NET_STATE_FLAG_SLEEP) rv = net_wake(); - return EOS_OK; + return rv; } static void net_deselect(void) { @@ -388,9 +412,9 @@ static void net_stop(void) { int eos_net_init(void) { int i; - eos_msgq_init(&net_send_q, net_sndq_array, EOS_NET_SIZE_BUFQ); - eos_bufq_init(&net_buf_q, net_bufq_array, EOS_NET_SIZE_BUFQ); - for (i=0; i<EOS_NET_SIZE_BUFQ; i++) { + eos_msgq_init(&net_send_q, net_sndq_array, NET_SIZE_BUFQ); + eos_bufq_init(&net_buf_q, net_bufq_array, NET_SIZE_BUFQ); + for (i=0; i<NET_SIZE_BUFQ; i++) { eos_bufq_push(&net_buf_q, net_bufq_buffer[i]); } @@ -417,15 +441,16 @@ int eos_net_init(void) { int eos_net_run(void) { uint8_t wakeup_cause; - int rv; + int rv, rst; rv = EOS_OK; net_start(); wakeup_cause = eos_pwr_wakeup_cause(); + rst = (wakeup_cause == EOS_PWR_WAKE_RST); clear_csr(mstatus, MSTATUS_MIE); - if (wakeup_cause == EOS_PWR_WAKE_RST) { + if (rst) { uint32_t start, timeout; start = eos_get_tick(); @@ -436,18 +461,11 @@ int eos_net_run(void) { break; } } - if (!rv) { - GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << NET_PIN_CTS); - } else { - net_state_flags |= NET_STATE_FLAG_ABSENT; - EOS_LOG(EOS_LOG_ERR, "NET DEVICE ABSENT\n"); - } } else { if (eos_aon_load4net()) { /* device previously declared as absent */ - net_state_flags |= NET_STATE_FLAG_ABSENT; - } else if (!(net_state_flags & NET_STATE_FLAG_CTS)) { - /* will assume that remote device is sleeping */ + rv = EOS_ERR_NOTFOUND; + } else { net_state_flags |= NET_STATE_FLAG_SLEEP; } } @@ -455,14 +473,26 @@ int eos_net_run(void) { /* set initial state */ 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; - net_resume(); + GPIO_REG(GPIO_PULLUP_EN) &= ~(1 << NET_PIN_CTS); + /* wake up remote */ + if (!rst) rv = net_wake(); + if (!rv) net_resume(); + } else { + net_state_flags |= NET_STATE_FLAG_ABSENT; + EOS_LOG(EOS_LOG_ERR, "NET DEVICE ABSENT\n"); } set_csr(mstatus, MSTATUS_MIE); + /* save absent state */ + if (rst) eos_aon_save4net(!!rv); + + if (rv) net_stop(); return rv; } void eos_net_start(void) { + if (net_state_flags & NET_STATE_FLAG_ABSENT) return; + net_start(); clear_csr(mstatus, MSTATUS_MIE); @@ -471,6 +501,8 @@ void eos_net_start(void) { } void eos_net_stop(void) { + if (net_state_flags & NET_STATE_FLAG_ABSENT) return; + clear_csr(mstatus, MSTATUS_MIE); net_pause(); set_csr(mstatus, MSTATUS_MIE); @@ -516,26 +548,16 @@ void eos_net_wake(void) { set_csr(mstatus, MSTATUS_MIE); } -void eos_net_save2aon(void) { - int absent; - - clear_csr(mstatus, MSTATUS_MIE); - absent = !!(net_state_flags & NET_STATE_FLAG_ABSENT); - set_csr(mstatus, MSTATUS_MIE); - eos_aon_save4net(absent); -} - -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); +void eos_net_bad_handler(unsigned char type, EOSMessage *msg, uint16_t len) { + eos_evtq_bad_handler(type, msg, len); } void eos_net_set_handler(unsigned char mtype, eos_evt_handler_t handler) { if (handler == NULL) handler = eos_net_bad_handler; - if (mtype && (mtype <= EOS_NET_MAX_MTYPE)) net_handler[mtype - 1] = handler; + if (mtype < EOS_NET_MAX_MTYPE) net_handler[mtype] = handler; } -void eos_net_acquire_for_evt(unsigned char type, char acq) { +void eos_net_acquire_for_evt(unsigned char type, int acq) { unsigned char idx = (type & EOS_EVT_MASK) >> 4; uint16_t flag = type & ~EOS_EVT_MASK ? (uint16_t)1 << (type & ~EOS_EVT_MASK) : 0xFFFF; @@ -547,7 +569,9 @@ void eos_net_acquire_for_evt(unsigned char type, char acq) { } void eos_net_acquire(void) { - unsigned char acq = net_acquire(0); + int acq; + + acq = net_acquire(0); if (!acq) net_acquire(1); } @@ -560,56 +584,59 @@ void eos_net_release(void) { set_csr(mstatus, MSTATUS_MIE); } -unsigned char *eos_net_alloc(void) { - unsigned char *rv = NULL; +void eos_net_alloc(EOSMessage *msg) { + msg->buffer = NULL; + msg->size = 0; - while (rv == NULL) { + while (msg->buffer == NULL) { clear_csr(mstatus, MSTATUS_MIE); if (net_state_next_buf) { - rv = net_state_next_buf; + msg->buffer = net_state_next_buf; + msg->size = EOS_NET_MTU; net_state_next_buf = NULL; } else { asm volatile ("wfi"); } set_csr(mstatus, MSTATUS_MIE); } - - return rv; } -void eos_net_free(unsigned char *buffer, unsigned char more) { - uint8_t do_release = 1; - +void eos_net_free(EOSMessage *msg, int more) { clear_csr(mstatus, MSTATUS_MIE); if ((more || net_state_next_cnt) && (net_state_next_buf == NULL)) { - net_state_next_buf = buffer; + net_state_next_buf = msg->buffer; } else { + int do_release = 1; + if ((net_state_flags & NET_STATE_FLAG_RUN) && (net_state_flags & NET_STATE_FLAG_CTS)) { - do_release = net_xchg_next(buffer); + do_release = net_xchg_next(msg); } if (do_release) { - eos_bufq_push(&net_buf_q, buffer); + eos_bufq_push(&net_buf_q, msg->buffer); } } + msg->buffer = NULL; + msg->size = 0; set_csr(mstatus, MSTATUS_MIE); } -static int net_xchg(unsigned char *type, unsigned char *buffer, uint16_t *len, unsigned char flags) { +static int net_xchg(unsigned char *type, EOSMessage *msg, uint16_t *len, unsigned char flags) { int rv = EOS_OK; int sync = 0, dsel = 0; unsigned char _type = *type & EOS_NET_MTYPE_MASK; uint16_t _len = *len; - if (flags & NET_FLAG_MORE) _type |= EOS_NET_MTYPE_FLAG_ONEW; - if (flags & NET_FLAG_REPL) _type |= EOS_NET_MTYPE_FLAG_REPL; - if (flags & NET_FLAG_SYNC) sync = 1; + if ((flags & EOS_NET_FLAG_REPL) && (_type & EOS_NET_MTYPE_FLAG_BRIDGE)) return EOS_ERR; + + if (flags & EOS_NET_FLAG_REPL) flags |= EOS_NET_FLAG_SYNC; + + if (flags & EOS_NET_FLAG_MORE) _type |= EOS_NET_MTYPE_FLAG_ONEW; + if (flags & EOS_NET_FLAG_REPL) _type |= EOS_NET_MTYPE_FLAG_REPL; + if (flags & EOS_NET_FLAG_SYNC) sync = 1; clear_csr(mstatus, MSTATUS_MIE); rv = net_select(&dsel); - if (rv) { - set_csr(mstatus, MSTATUS_MIE); - return rv; - } + if (rv) goto net_xchg_fin; if (dsel) sync = 1; if (sync) { @@ -617,51 +644,58 @@ static int net_xchg(unsigned char *type, unsigned char *buffer, uint16_t *len, u net_pause(); net_wait4cts(); net_state_flags |= NET_STATE_FLAG_SYNC; - net_xchg_start(_type, buffer, _len); - if (flags & NET_FLAG_REPL) { + net_xchg_start(_type, msg, _len); + if (flags & EOS_NET_FLAG_REPL) { net_wait4cts(); - net_xchg_start(0, buffer, 0); + net_xchg_start(0, msg, 0); } net_wait4xchg(); net_state_flags &= ~NET_STATE_FLAG_SYNC; - *type = net_state_type & EOS_NET_MTYPE_MASK; - *len = net_state_len_rx; + if (flags & EOS_NET_FLAG_REPL) { + *type = 0; + *len = 0; + rv = (net_state_flags & NET_STATE_FLAG_ERR_SIZE) ? EOS_ERR_SIZE : EOS_OK; + if (!rv) { + *type = net_state_type & EOS_NET_MTYPE_MASK; + *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, msg, _len); } else { - rv = eos_msgq_push(&net_send_q, _type, buffer, _len); + rv = eos_msgq_push(&net_send_q, _type, msg, _len); } } +net_xchg_fin: set_csr(mstatus, MSTATUS_MIE); - if (sync && !(flags & NET_FLAG_SYNC)) eos_net_free(buffer, !!(flags & NET_FLAG_MORE)); + if (!(flags & EOS_NET_FLAG_SYNC)) { + if (sync || rv) { + eos_net_free(msg, !!(flags & EOS_NET_FLAG_MORE)); + } else { + msg->buffer = NULL; + msg->size = 0; + } + } if (dsel) net_deselect(); return rv; } -int eos_net_send(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char more) { - int rv; - - rv = net_xchg(&type, buffer, &len, more ? NET_FLAG_MORE : 0); - if (rv) eos_net_free(buffer, more); - return rv; +int eos_net_send(unsigned char type, EOSMessage *msg, uint16_t len, int more) { + return net_xchg(&type, msg, &len, more ? EOS_NET_FLAG_MORE : 0); } -int eos_net_send_sync(unsigned char type, unsigned char *buffer, uint16_t len) { - return net_xchg(&type, buffer, &len, NET_FLAG_SYNC); +int eos_net_send_sync(unsigned char type, EOSMessage *msg, uint16_t len) { + return net_xchg(&type, msg, &len, EOS_NET_FLAG_SYNC); } -int eos_net_xchg(unsigned char *type, unsigned char *buffer, uint16_t *len) { - return net_xchg(type, buffer, len, (NET_FLAG_SYNC | NET_FLAG_REPL)); +int eos_net_xchg(unsigned char *type, EOSMessage *msg, uint16_t *len) { + return net_xchg(type, msg, len, EOS_NET_FLAG_REPL); } -int _eos_net_send(unsigned char type, unsigned char *buffer, uint16_t len, unsigned char async, unsigned char more) { - if (async) { - return eos_net_send(type, buffer, len, more); - } else { - return eos_net_send_sync(type, buffer, len); - } +int _eos_net_send(unsigned char type, EOSMessage *msg, uint16_t len, unsigned char flags) { + return net_xchg(&type, msg, &len, flags); } |
