#include #include #include "encoding.h" #include "platform.h" #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" #include "irq_def.h" #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]; static EOSMsgQ net_send_q; static EOSMsgItem net_sndq_array[EOS_NET_SIZE_BUFQ]; 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; 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 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_xchg_reset(void) { net_state_flags &= ~NET_STATE_FLAG_CTS; net_state_flags |= (NET_STATE_FLAG_RST | NET_STATE_FLAG_XCHG); // before starting a transaction, set SPI peripheral to desired mode 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; } static void net_xchg_start(unsigned char type, unsigned char *buffer, uint16_t len) { net_state_flags &= ~NET_STATE_FLAG_CTS; net_state_flags |= (NET_STATE_FLAG_INIT | NET_STATE_FLAG_XCHG); if (net_state_next_cnt && (net_state_next_buf == NULL)) type |= NET_MTYPE_FLAG_ONEW; if (type & NET_MTYPE_FLAG_ONEW) net_state_flags |= NET_STATE_FLAG_ONEW; net_state_type = type; net_state_len_tx = len; net_state_len_rx = 0; _eos_spi_state_buf = buffer; // before starting a transaction, set SPI peripheral to desired mode SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_HOLD; SPI1_REG(SPI_REG_TXFIFO) = ((type << 3) | (len >> 8)) & 0xFF; SPI1_REG(SPI_REG_TXFIFO) = len & 0xFF; SPI1_REG(SPI_REG_RXCTRL) = SPI_RXWM(1); 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_STATE_FLAG_RTS) { if (_buffer == NULL) _buffer = eos_bufq_pop(&net_buf_q); if (_buffer) { net_xchg_start(0, _buffer, 0); return 0; } } return 1; } void eos_net_xchg_done(void) { SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; if (net_state_type) { int r = eos_evtq_push_isr(EOS_EVT_NET | net_state_type, _eos_spi_state_buf, net_state_len_rx); if (r) eos_bufq_push(&net_buf_q, _eos_spi_state_buf); } else if (((net_state_flags & NET_STATE_FLAG_ONEW) || net_state_next_cnt) && (net_state_next_buf == NULL)) { net_state_next_buf = _eos_spi_state_buf; net_state_flags &= ~NET_STATE_FLAG_ONEW; } else { eos_bufq_push(&net_buf_q, _eos_spi_state_buf); } net_state_flags &= ~NET_STATE_FLAG_XCHG; } static void net_handler_xchg(void) { volatile uint32_t r1, r2; if (net_state_flags & NET_STATE_FLAG_RST) { net_state_flags &= ~NET_STATE_FLAG_RST; 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) { net_state_flags &= ~NET_STATE_FLAG_INIT; SPI1_REG(SPI_REG_TXCTRL) = SPI_TXWM(SPI_SIZE_WM); SPI1_REG(SPI_REG_IE) = SPI_IP_TXWM; r1 = SPI1_REG(SPI_REG_RXFIFO); r2 = SPI1_REG(SPI_REG_RXFIFO); if (net_state_flags & NET_STATE_FLAG_ONEW) { r1 = 0; r2 = 0; } net_state_type = ((r1 & 0xFF) >> 3); 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) { _eos_spi_state_len = 6; } else if ((_eos_spi_state_len + 2) % 4 != 0) { _eos_spi_state_len = ((_eos_spi_state_len + 2)/4 + 1) * 4 - 2; } if (_eos_spi_state_len > EOS_NET_SIZE_BUF) { SPI1_REG(SPI_REG_CSMODE) = SPI_CSMODE_AUTO; SPI1_REG(SPI_REG_IE) = 0x0; } return; } eos_spi_xchg_handler(); } static void net_handler_cts(void) { GPIO_REG(GPIO_RISE_IP) = (1 << NET_PIN_CTS); net_state_flags |= NET_STATE_FLAG_CTS; if (net_state_flags & NET_STATE_FLAG_RUN) { net_xchg_next(NULL); } } static void net_handler_rts(void) { 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_STATE_FLAG_RTS; 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; } } static void net_handler_evt(unsigned char type, unsigned char *buffer, uint16_t len) { unsigned char idx = (type & ~EOS_EVT_MASK) - 1; if (idx >= EOS_NET_MAX_MTYPE) { eos_evtq_bad_handler(type, buffer, len); eos_net_free(buffer, 0); return; } _eos_net_handle(type, buffer, len, idx, evt_handler, &evt_handler_flags_buf_free, &evt_handler_flags_buf_acq); } void 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