From e9de433ecf4feecbfb611ffce66f239788197da8 Mon Sep 17 00:00:00 2001 From: Jared Hancock Date: Sat, 6 Apr 2024 12:14:43 -0500 Subject: [PATCH] wiznet5k: Add support for using interrupt without lwIP. Signed-off-by: Jared Hancock --- extmod/network_wiznet5k.c | 84 ++++++++++++++++++++++++++++++--------- 1 file changed, 65 insertions(+), 19 deletions(-) diff --git a/extmod/network_wiznet5k.c b/extmod/network_wiznet5k.c index 121aafc9cf..b96fdc3514 100644 --- a/extmod/network_wiznet5k.c +++ b/extmod/network_wiznet5k.c @@ -99,9 +99,9 @@ typedef struct _wiznet5k_obj_t { void (*spi_transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest); mp_hal_pin_obj_t cs; mp_hal_pin_obj_t rst; - #if WIZNET5K_WITH_LWIP_STACK mp_hal_pin_obj_t pin_intn; bool use_interrupt; + #if WIZNET5K_WITH_LWIP_STACK uint8_t eth_frame[1514]; uint32_t trace_flags; struct netif netif; @@ -177,11 +177,7 @@ static void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) { getSHAR(mac); } -#if WIZNET5K_WITH_LWIP_STACK - void wiznet5k_try_poll(void); -static void wiznet5k_lwip_init(wiznet5k_obj_t *self); - static mp_obj_t mpy_wiznet_read_int(mp_obj_t none_in) { (void)none_in; // Handle incoming data, unless the SPI bus is busy @@ -204,6 +200,9 @@ static void wiznet5k_config_interrupt(bool enabled) { ); } +#if WIZNET5K_WITH_LWIP_STACK +static void wiznet5k_lwip_init(wiznet5k_obj_t *self); + void wiznet5k_deinit(void) { for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) { if (netif == &wiznet5k_obj.netif) { @@ -357,6 +356,14 @@ void wiznet5k_poll(void) { #if WIZNET5K_PROVIDED_STACK +void wiznet5k_try_poll(void) { + // There's really nothing to do here. The interrupt that triggered this will + // release a WFE() wait and will trigger a poll() loop which will + // wiznet5k_socket_ioctl will detect the readable or writeable state of the + // respective socket. + (void)0; +} + static void wiz_dhcp_assign(void) { getIPfromDHCP(wiznet5k_obj.netinfo.ip); getGWfromDHCP(wiznet5k_obj.netinfo.gw); @@ -395,6 +402,17 @@ static void wiznet5k_init(void) { }; wiznet5k_obj.netinfo = netinfo; + if (wiznet5k_obj.use_interrupt) { + mp_hal_pin_input(wiznet5k_obj.pin_intn); + wiznet5k_config_interrupt(true); + wizchip_setinterruptmask(IK_SOCK_ALL); + + #if _WIZCHIP_ == W5100S + // Enable interrupt pin + setMR2(getMR2() | MR2_G_IEN); + #endif + } + // register with network module mod_network_register_nic(&wiznet5k_obj); @@ -453,6 +471,11 @@ static int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) } socket->_private = NULL; + + // Enable data receive interrupt + if (wiznet5k_obj.use_interrupt) { + setSn_IMR(socket->fileno, (Sn_IR_RECV | Sn_IR_CON | Sn_IR_DISCON)); + } } // WIZNET does not have a concept of pure "open socket". You need to know @@ -470,7 +493,14 @@ static void wiznet5k_socket_close(mod_network_socket_obj_t *socket) { if (sn < _WIZCHIP_SOCK_NUM_) { wiznet5k_obj.socket_used &= ~(1 << sn); WIZCHIP_EXPORT(close)(sn); + + // Disable receive interrupts + if (wiznet5k_obj.use_interrupt) { + setSn_IMR(sn, 0); + } } + + socket->_private = NULL; } static int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { @@ -729,14 +759,35 @@ static int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_ } static int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) { + uint8_t sn = (uint8_t)socket->fileno; + if (request == MP_STREAM_POLL) { int ret = 0; - if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->fileno) != 0) { - ret |= MP_STREAM_POLL_RD; + if (sn < _WIZCHIP_SOCK_NUM_) { + if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(sn) != 0) { + ret |= MP_STREAM_POLL_RD; + } + if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(sn) != 0) { + ret |= MP_STREAM_POLL_WR; + } + + uint8_t status = getSn_SR(sn); + if (status == SOCK_CLOSE_WAIT || getSn_IR(sn) & Sn_IR_DISCON) { + // Peer-closed socket is both readable and writable: read will + // return EOF, write - error. Without this poll will hang on a + // socket which was closed by peer. + ret |= arg & (MP_STREAM_POLL_RD | MP_STREAM_POLL_WR); + } else if (status == SOCK_CLOSED) { + ret |= MP_STREAM_POLL_ERR; + } + } else { + ret |= MP_STREAM_POLL_NVAL; } - if (arg & MP_STREAM_POLL_WR && getSn_TX_FSR(socket->fileno) != 0) { - ret |= MP_STREAM_POLL_WR; + + if (wiznet5k_obj.use_interrupt) { + setSn_IR(sn, (Sn_IR_RECV | Sn_IR_CON | Sn_IR_DISCON)); } + return ret; } else { *_errno = MP_EINVAL; @@ -773,6 +824,8 @@ static void wiznet5k_dhcp_init(wiznet5k_obj_t *self) { if (ret == DHCP_IP_LEASED) { ctlnetwork(CN_GET_NETINFO, &self->netinfo); } + + wizchip_clrinterrupt(IK_SOCK_1); } #endif // WIZNET5K_PROVIDED_STACK @@ -786,11 +839,10 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size mp_obj_base_t *spi; mp_hal_pin_obj_t cs; mp_hal_pin_obj_t rst; - - #if WIZNET5K_WITH_LWIP_STACK mp_hal_pin_obj_t pin_intn = (mp_hal_pin_obj_t)NULL; bool use_interrupt = false; + #if WIZNET5K_WITH_LWIP_STACK // Bring down interface while configuring wiznet5k_obj.netif.flags = 0; #endif @@ -813,7 +865,7 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size cs = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_CS)})); rst = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_RST)})); - #if WIZNET5K_WITH_LWIP_STACK && defined(MICROPY_HW_WIZNET_PIN_INTN) + #ifdef MICROPY_HW_WIZNET_PIN_INTN pin_intn = mp_hal_get_pin_obj(mp_pin_make_new(NULL, 1, 0, (mp_obj_t[]) {MP_OBJ_NEW_SMALL_INT(MICROPY_HW_WIZNET_PIN_INTN)})); use_interrupt = true; #endif @@ -822,20 +874,14 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size #endif { // If passing in args, must supply spi, pin_cs, pin_rst and optionally pin_intn - #if WIZNET5K_WITH_LWIP_STACK mp_arg_check_num(n_args, n_kw, 3, 4, false); - #else - mp_arg_check_num(n_args, n_kw, 3, 3, false); - #endif spi = mp_hal_get_spi_obj(args[0]); cs = mp_hal_get_pin_obj(args[1]); rst = mp_hal_get_pin_obj(args[2]); - #if WIZNET5K_WITH_LWIP_STACK if (n_args > 3) { pin_intn = mp_hal_get_pin_obj(args[3]); use_interrupt = true; } - #endif } mp_hal_pin_output(cs); @@ -848,9 +894,9 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size wiznet5k_obj.spi_transfer = ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(spi->type, protocol))->transfer; wiznet5k_obj.cs = cs; wiznet5k_obj.rst = rst; - #if WIZNET5K_WITH_LWIP_STACK wiznet5k_obj.pin_intn = pin_intn; wiznet5k_obj.use_interrupt = use_interrupt; + #if WIZNET5K_WITH_LWIP_STACK wiznet5k_obj.trace_flags = 0; #else // WIZNET5K_PROVIDED_STACK wiznet5k_obj.active = false;