kopia lustrzana https://github.com/micropython/micropython
Merge 710bf834cf
into 5114f2c1ea
commit
a44d97fc60
|
@ -37,6 +37,7 @@
|
||||||
#if MICROPY_PY_NETWORK_WIZNET5K
|
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||||
|
|
||||||
#include "shared/netutils/netutils.h"
|
#include "shared/netutils/netutils.h"
|
||||||
|
#include "shared/runtime/softtimer.h"
|
||||||
#include "extmod/modnetwork.h"
|
#include "extmod/modnetwork.h"
|
||||||
#include "extmod/modmachine.h"
|
#include "extmod/modmachine.h"
|
||||||
#include "extmod/virtpin.h"
|
#include "extmod/virtpin.h"
|
||||||
|
@ -74,6 +75,14 @@
|
||||||
#include "lib/wiznet5k/Internet/DNS/dns.h"
|
#include "lib/wiznet5k/Internet/DNS/dns.h"
|
||||||
#include "lib/wiznet5k/Internet/DHCP/dhcp.h"
|
#include "lib/wiznet5k/Internet/DHCP/dhcp.h"
|
||||||
|
|
||||||
|
// Poll WIZnet every 64ms by default (if not using interrupt pin)
|
||||||
|
#define WIZNET5K_TICK_RATE_MS 64
|
||||||
|
// In DHCP.c, RIP_MSG max size is defined as 312 + 256 (sadly, not in the header)
|
||||||
|
#define MAX_DHCP_BUF_SIZE 568
|
||||||
|
|
||||||
|
// Soft timer for polling and running DHCP in the background.
|
||||||
|
static soft_timer_entry_t mp_network_soft_timer;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef printf
|
#ifndef printf
|
||||||
|
@ -99,9 +108,9 @@ typedef struct _wiznet5k_obj_t {
|
||||||
void (*spi_transfer)(mp_obj_base_t *obj, size_t len, const uint8_t *src, uint8_t *dest);
|
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 cs;
|
||||||
mp_hal_pin_obj_t rst;
|
mp_hal_pin_obj_t rst;
|
||||||
#if WIZNET5K_WITH_LWIP_STACK
|
|
||||||
mp_hal_pin_obj_t pin_intn;
|
mp_hal_pin_obj_t pin_intn;
|
||||||
bool use_interrupt;
|
bool use_interrupt;
|
||||||
|
#if WIZNET5K_WITH_LWIP_STACK
|
||||||
uint8_t eth_frame[1514];
|
uint8_t eth_frame[1514];
|
||||||
uint32_t trace_flags;
|
uint32_t trace_flags;
|
||||||
struct netif netif;
|
struct netif netif;
|
||||||
|
@ -110,9 +119,21 @@ typedef struct _wiznet5k_obj_t {
|
||||||
wiz_NetInfo netinfo;
|
wiz_NetInfo netinfo;
|
||||||
uint8_t socket_used;
|
uint8_t socket_used;
|
||||||
bool active;
|
bool active;
|
||||||
|
uint8_t *dhcp_buf;
|
||||||
|
uint8_t dhcp_retry;
|
||||||
|
uint8_t dhcp_state;
|
||||||
|
mp_int_t dhcp_socket;
|
||||||
|
uint32_t dhcp_timeout;
|
||||||
#endif
|
#endif
|
||||||
} wiznet5k_obj_t;
|
} wiznet5k_obj_t;
|
||||||
|
|
||||||
|
#if WIZNET5K_PROVIDED_STACK
|
||||||
|
typedef struct _wiznet5k_socket_extra_t {
|
||||||
|
byte remote_ip[4];
|
||||||
|
mp_uint_t remote_port;
|
||||||
|
} wiznet5k_socket_extra_t;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if WIZNET5K_WITH_LWIP_STACK
|
#if WIZNET5K_WITH_LWIP_STACK
|
||||||
#define IS_ACTIVE(self) (self->netif.flags & NETIF_FLAG_UP)
|
#define IS_ACTIVE(self) (self->netif.flags & NETIF_FLAG_UP)
|
||||||
#else // WIZNET5K_PROVIDED_STACK
|
#else // WIZNET5K_PROVIDED_STACK
|
||||||
|
@ -170,11 +191,7 @@ static void wiznet5k_get_mac_address(wiznet5k_obj_t *self, uint8_t mac[6]) {
|
||||||
getSHAR(mac);
|
getSHAR(mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WIZNET5K_WITH_LWIP_STACK
|
|
||||||
|
|
||||||
void wiznet5k_try_poll(void);
|
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) {
|
static mp_obj_t mpy_wiznet_read_int(mp_obj_t none_in) {
|
||||||
(void)none_in;
|
(void)none_in;
|
||||||
// Handle incoming data, unless the SPI bus is busy
|
// Handle incoming data, unless the SPI bus is busy
|
||||||
|
@ -197,6 +214,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) {
|
void wiznet5k_deinit(void) {
|
||||||
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
|
for (struct netif *netif = netif_list; netif != NULL; netif = netif->next) {
|
||||||
if (netif == &wiznet5k_obj.netif) {
|
if (netif == &wiznet5k_obj.netif) {
|
||||||
|
@ -350,6 +370,59 @@ void wiznet5k_poll(void) {
|
||||||
|
|
||||||
#if WIZNET5K_PROVIDED_STACK
|
#if WIZNET5K_PROVIDED_STACK
|
||||||
|
|
||||||
|
static mp_int_t wiznet5k_allocate_socket(void) {
|
||||||
|
// get first unused socket number
|
||||||
|
for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
|
||||||
|
if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
|
||||||
|
wiznet5k_obj.socket_used |= (1 << sn);
|
||||||
|
return sn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern uint8_t DHCP_SOCKET;
|
||||||
|
static void wiznet5k_dhcp_poll(void) {
|
||||||
|
if (wiznet5k_obj.dhcp_socket != -1) {
|
||||||
|
wiznet5k_obj.dhcp_state = DHCP_run();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wiznet5k_obj.dhcp_state == DHCP_IP_LEASED) {
|
||||||
|
// Every few seconds, check in about renewing the IP
|
||||||
|
if (wiznet5k_obj.dhcp_socket != -1) {
|
||||||
|
// Release socket and reset timeout
|
||||||
|
wiznet5k_obj.socket_used &= ~(1 << wiznet5k_obj.dhcp_socket);
|
||||||
|
wiznet5k_obj.dhcp_socket = -1;
|
||||||
|
|
||||||
|
// Run about once per minute
|
||||||
|
wiznet5k_obj.dhcp_timeout = mp_hal_ticks_ms() + 60000;
|
||||||
|
} else if (mp_hal_ticks_ms() > wiznet5k_obj.dhcp_timeout) {
|
||||||
|
mp_uint_t sn = wiznet5k_allocate_socket();
|
||||||
|
if (sn != -1) {
|
||||||
|
DHCP_SOCKET = sn;
|
||||||
|
wiznet5k_obj.dhcp_socket = sn;
|
||||||
|
wiznet5k_obj.dhcp_state = DHCP_run();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (wiznet5k_obj.dhcp_state == DHCP_FAILED || wiznet5k_obj.dhcp_state == DHCP_STOPPED) {
|
||||||
|
if (wiznet5k_obj.dhcp_socket != -1) {
|
||||||
|
wiznet5k_obj.socket_used &= ~(1 << wiznet5k_obj.dhcp_socket);
|
||||||
|
wiznet5k_obj.dhcp_socket = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void wiznet5k_try_poll(void) {
|
||||||
|
// If using DHCP for the interface, periodically renew/update the address
|
||||||
|
wiznet5k_dhcp_poll();
|
||||||
|
|
||||||
|
// 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(s).
|
||||||
|
}
|
||||||
|
|
||||||
static void wiz_dhcp_assign(void) {
|
static void wiz_dhcp_assign(void) {
|
||||||
getIPfromDHCP(wiznet5k_obj.netinfo.ip);
|
getIPfromDHCP(wiznet5k_obj.netinfo.ip);
|
||||||
getGWfromDHCP(wiznet5k_obj.netinfo.gw);
|
getGWfromDHCP(wiznet5k_obj.netinfo.gw);
|
||||||
|
@ -359,7 +432,7 @@ static void wiz_dhcp_assign(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wiz_dhcp_update(void) {
|
static void wiz_dhcp_update(void) {
|
||||||
;
|
wiz_dhcp_assign();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -367,6 +440,22 @@ static void wiz_dhcp_conflict(void) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This is called by soft_timer and executes at PendSV level.
|
||||||
|
static void mp_network_soft_timer_callback(soft_timer_entry_t *self) {
|
||||||
|
wiznet5k_try_poll();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void mod_network_wiznet5k_poll_init(void) {
|
||||||
|
soft_timer_static_init(
|
||||||
|
&mp_network_soft_timer,
|
||||||
|
SOFT_TIMER_MODE_PERIODIC,
|
||||||
|
WIZNET5K_TICK_RATE_MS,
|
||||||
|
mp_network_soft_timer_callback
|
||||||
|
);
|
||||||
|
|
||||||
|
soft_timer_reinsert(&mp_network_soft_timer, WIZNET5K_TICK_RATE_MS);
|
||||||
|
}
|
||||||
|
|
||||||
static void wiznet5k_init(void) {
|
static void wiznet5k_init(void) {
|
||||||
// Configure wiznet provided TCP / socket interface
|
// Configure wiznet provided TCP / socket interface
|
||||||
|
|
||||||
|
@ -388,21 +477,46 @@ static void wiznet5k_init(void) {
|
||||||
};
|
};
|
||||||
wiznet5k_obj.netinfo = netinfo;
|
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
|
// register with network module
|
||||||
mod_network_register_nic(&wiznet5k_obj);
|
mod_network_register_nic(&wiznet5k_obj);
|
||||||
|
mod_network_wiznet5k_poll_init();
|
||||||
|
|
||||||
wiznet5k_obj.active = true;
|
wiznet5k_obj.active = true;
|
||||||
|
wiznet5k_obj.dhcp_socket = -1;
|
||||||
|
wiznet5k_obj.dhcp_state = DHCP_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
|
static int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip) {
|
||||||
uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8};
|
uint8_t dns_ip[MOD_NETWORK_IPADDR_BUF_SIZE] = {8, 8, 8, 8};
|
||||||
uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
|
uint8_t *buf = m_new(uint8_t, MAX_DNS_BUF_SIZE);
|
||||||
DNS_init(2, buf);
|
mp_int_t sn = wiznet5k_allocate_socket();
|
||||||
|
if (sn == -1) {
|
||||||
|
return -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
DNS_init(sn, buf);
|
||||||
if (wiznet5k_obj.netinfo.dns[0]) {
|
if (wiznet5k_obj.netinfo.dns[0]) {
|
||||||
memcpy(dns_ip, wiznet5k_obj.netinfo.dns, MOD_NETWORK_IPADDR_BUF_SIZE);
|
memcpy(dns_ip, wiznet5k_obj.netinfo.dns, MOD_NETWORK_IPADDR_BUF_SIZE);
|
||||||
}
|
}
|
||||||
mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip);
|
mp_int_t ret = DNS_run(dns_ip, (uint8_t *)name, out_ip);
|
||||||
m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
|
m_del(uint8_t, buf, MAX_DNS_BUF_SIZE);
|
||||||
|
|
||||||
|
// NOTE: DNS_run will close the socket, so it just needs to be marked as
|
||||||
|
// unused here and clear any interrupts.
|
||||||
|
wiznet5k_obj.socket_used &= ~(1 << sn);
|
||||||
|
wizchip_clrinterrupt(IK_SOCK_0 << sn);
|
||||||
|
|
||||||
if (ret == 1) {
|
if (ret == 1) {
|
||||||
// success
|
// success
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -432,18 +546,19 @@ static int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno)
|
||||||
|
|
||||||
if (socket->fileno == -1) {
|
if (socket->fileno == -1) {
|
||||||
// get first unused socket number
|
// get first unused socket number
|
||||||
for (mp_uint_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) {
|
socket->fileno = wiznet5k_allocate_socket();
|
||||||
if ((wiznet5k_obj.socket_used & (1 << sn)) == 0) {
|
|
||||||
wiznet5k_obj.socket_used |= (1 << sn);
|
|
||||||
socket->fileno = sn;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (socket->fileno == -1) {
|
if (socket->fileno == -1) {
|
||||||
// too many open sockets
|
// too many open sockets
|
||||||
*_errno = MP_EMFILE;
|
*_errno = MP_EMFILE;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// WIZNET does not have a concept of pure "open socket". You need to know
|
||||||
|
@ -461,12 +576,27 @@ static void wiznet5k_socket_close(mod_network_socket_obj_t *socket) {
|
||||||
if (sn < _WIZCHIP_SOCK_NUM_) {
|
if (sn < _WIZCHIP_SOCK_NUM_) {
|
||||||
wiznet5k_obj.socket_used &= ~(1 << sn);
|
wiznet5k_obj.socket_used &= ~(1 << sn);
|
||||||
WIZCHIP_EXPORT(close)(sn);
|
WIZCHIP_EXPORT(close)(sn);
|
||||||
|
|
||||||
|
// Disable receive interrupts
|
||||||
|
if (wiznet5k_obj.use_interrupt) {
|
||||||
|
setSn_IMR(sn, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_del(wiznet5k_socket_extra_t, socket->_private, 1);
|
||||||
|
socket->_private = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
|
static int wiznet5k_socket_bind(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) {
|
||||||
|
uint8_t flag = 0;
|
||||||
|
if (socket->timeout == 0) {
|
||||||
|
// Setup non-blocking mode
|
||||||
|
flag |= SOCK_IO_NONBLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
// open the socket in server mode (if port != 0)
|
// open the socket in server mode (if port != 0)
|
||||||
mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->fileno, socket->type, port, 0);
|
mp_int_t ret = WIZCHIP_EXPORT(socket)(socket->fileno, socket->type, port, flag);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wiznet5k_socket_close(socket);
|
wiznet5k_socket_close(socket);
|
||||||
*_errno = -ret;
|
*_errno = -ret;
|
||||||
|
@ -531,22 +661,51 @@ static int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, m
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// now connect
|
// WIZnet doesn't support connect on UDP sockets. TODO: Stash the remote
|
||||||
MP_THREAD_GIL_EXIT();
|
// information for use with the ::send method, if used on this UDP socket.
|
||||||
mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->fileno, ip, port);
|
if (socket->type == Sn_MR_TCP) {
|
||||||
MP_THREAD_GIL_ENTER();
|
// now connect
|
||||||
|
MP_THREAD_GIL_EXIT();
|
||||||
|
mp_int_t ret = WIZCHIP_EXPORT(connect)(socket->fileno, ip, port);
|
||||||
|
MP_THREAD_GIL_ENTER();
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
wiznet5k_socket_close(socket);
|
wiznet5k_socket_close(socket);
|
||||||
*_errno = -ret;
|
*_errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
|
}
|
||||||
|
else if (ret == SOCK_BUSY) {
|
||||||
|
*_errno = MP_EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (socket->type == Sn_MR_UDP) {
|
||||||
|
// For POSIX usage of ::send later, stash the remote IP and port
|
||||||
|
wiznet5k_socket_extra_t *extra = m_new_maybe(wiznet5k_socket_extra_t, 1);
|
||||||
|
if (extra == NULL) {
|
||||||
|
*_errno = MP_ENOMEM;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy(extra->remote_ip, ip, 4);
|
||||||
|
extra->remote_port = port;
|
||||||
|
socket->_private = extra;
|
||||||
}
|
}
|
||||||
|
|
||||||
// success
|
// success
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, byte *ip, mp_uint_t port, int *_errno);
|
||||||
static mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
|
static mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const byte *buf, mp_uint_t len, int *_errno) {
|
||||||
|
if (socket->type == Sn_MR_UDP) {
|
||||||
|
if (socket->_private != NULL) {
|
||||||
|
wiznet5k_socket_extra_t *extra = (wiznet5k_socket_extra_t*) socket->_private;
|
||||||
|
return wiznet5k_socket_sendto(socket, buf, len, extra->remote_ip, extra->remote_port, _errno);
|
||||||
|
}
|
||||||
|
*_errno = MP_ENOTCONN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
MP_THREAD_GIL_EXIT();
|
MP_THREAD_GIL_EXIT();
|
||||||
mp_int_t ret = WIZCHIP_EXPORT(send)(socket->fileno, (byte *)buf, len);
|
mp_int_t ret = WIZCHIP_EXPORT(send)(socket->fileno, (byte *)buf, len);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
|
@ -557,10 +716,25 @@ static mp_uint_t wiznet5k_socket_send(mod_network_socket_obj_t *socket, const by
|
||||||
*_errno = -ret;
|
*_errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (ret == SOCK_BUSY && getSn_SR(socket->fileno) == SOCK_ESTABLISHED) {
|
||||||
|
*_errno = MP_EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
|
static mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, int *_errno) {
|
||||||
|
if (socket->timeout > 0) {
|
||||||
|
mp_uint_t start = mp_hal_ticks_ms();
|
||||||
|
while (getSn_SR(socket->fileno) == SOCK_ESTABLISHED && getSn_RX_RSR(socket->fileno) == 0) {
|
||||||
|
if (mp_hal_ticks_ms() - start > socket->timeout) {
|
||||||
|
*_errno = MP_ETIMEDOUT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mp_event_wait_ms(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MP_THREAD_GIL_EXIT();
|
MP_THREAD_GIL_EXIT();
|
||||||
mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->fileno, buf, len);
|
mp_int_t ret = WIZCHIP_EXPORT(recv)(socket->fileno, buf, len);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
|
@ -571,6 +745,12 @@ static mp_uint_t wiznet5k_socket_recv(mod_network_socket_obj_t *socket, byte *bu
|
||||||
*_errno = -ret;
|
*_errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
// NOTE: SOCK_BUSY is zero (0) which is confusing if the socket is closed
|
||||||
|
// and at EOF
|
||||||
|
else if (ret == SOCK_BUSY && getSn_SR(socket->fileno) == SOCK_ESTABLISHED) {
|
||||||
|
*_errno = MP_EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,11 +771,27 @@ static mp_uint_t wiznet5k_socket_sendto(mod_network_socket_obj_t *socket, const
|
||||||
*_errno = -ret;
|
*_errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (ret == SOCK_BUSY) {
|
||||||
|
*_errno = MP_EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
static mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte *buf, mp_uint_t len, byte *ip, mp_uint_t *port, int *_errno) {
|
||||||
uint16_t port2;
|
uint16_t port2;
|
||||||
|
|
||||||
|
if (socket->timeout > 0) {
|
||||||
|
mp_uint_t start = mp_hal_ticks_ms();
|
||||||
|
while (getSn_SR(socket->fileno) != SOCK_CLOSED && getSn_RX_RSR(socket->fileno) == 0) {
|
||||||
|
if (mp_hal_ticks_ms() - start > socket->timeout) {
|
||||||
|
*_errno = MP_ETIMEDOUT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mp_event_wait_ms(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MP_THREAD_GIL_EXIT();
|
MP_THREAD_GIL_EXIT();
|
||||||
mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->fileno, buf, len, ip, &port2);
|
mp_int_t ret = WIZCHIP_EXPORT(recvfrom)(socket->fileno, buf, len, ip, &port2);
|
||||||
MP_THREAD_GIL_ENTER();
|
MP_THREAD_GIL_ENTER();
|
||||||
|
@ -605,38 +801,79 @@ static mp_uint_t wiznet5k_socket_recvfrom(mod_network_socket_obj_t *socket, byte
|
||||||
*_errno = -ret;
|
*_errno = -ret;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
else if (ret == SOCK_BUSY) {
|
||||||
|
*_errno = MP_EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
|
static int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
|
||||||
// TODO
|
switch (opt) {
|
||||||
*_errno = MP_EINVAL;
|
// level: SOL_SOCKET
|
||||||
return -1;
|
case MOD_NETWORK_SO_REUSEADDR:
|
||||||
|
case MOD_NETWORK_SO_BROADCAST:
|
||||||
|
// Implied/not-required in Wiznet sockets
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
*_errno = MP_EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
|
static int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno) {
|
||||||
// TODO
|
uint8_t arg;
|
||||||
*_errno = MP_EINVAL;
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/*
|
|
||||||
if (timeout_ms == 0) {
|
if (timeout_ms == 0) {
|
||||||
// set non-blocking mode
|
// set non-blocking mode
|
||||||
uint8_t arg = SOCK_IO_NONBLOCK;
|
arg = SOCK_IO_NONBLOCK;
|
||||||
WIZCHIP_EXPORT(ctlsocket)(socket->fileno, CS_SET_IOMODE, &arg);
|
|
||||||
}
|
}
|
||||||
*/
|
else {
|
||||||
|
arg = SOCK_IO_BLOCK;
|
||||||
|
}
|
||||||
|
|
||||||
|
mp_int_t ret = WIZCHIP_EXPORT(ctlsocket)(socket->fileno, CS_SET_IOMODE, &arg);
|
||||||
|
if (ret < 0) {
|
||||||
|
*_errno = -ret;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
socket->timeout = timeout_ms;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno) {
|
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) {
|
if (request == MP_STREAM_POLL) {
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
if (arg & MP_STREAM_POLL_RD && getSn_RX_RSR(socket->fileno) != 0) {
|
if (sn < _WIZCHIP_SOCK_NUM_) {
|
||||||
ret |= MP_STREAM_POLL_RD;
|
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;
|
return ret;
|
||||||
} else {
|
} else {
|
||||||
*_errno = MP_EINVAL;
|
*_errno = MP_EINVAL;
|
||||||
|
@ -645,23 +882,31 @@ static int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t req
|
||||||
}
|
}
|
||||||
|
|
||||||
static void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
|
static void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
|
||||||
uint8_t test_buf[2048];
|
|
||||||
uint8_t ret = 0;
|
|
||||||
uint8_t dhcp_retry = 0;
|
uint8_t dhcp_retry = 0;
|
||||||
|
self->dhcp_state = DHCP_STOPPED;
|
||||||
|
self->dhcp_buf = m_new_maybe(uint8_t, MAX_DHCP_BUF_SIZE);
|
||||||
|
if (self->dhcp_buf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
while (ret != DHCP_IP_LEASED) {
|
self->dhcp_socket = wiznet5k_allocate_socket();
|
||||||
|
if (self->dhcp_socket == -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
while (self->dhcp_state != DHCP_IP_LEASED) {
|
||||||
mp_uint_t timeout = mp_hal_ticks_ms() + 3000;
|
mp_uint_t timeout = mp_hal_ticks_ms() + 3000;
|
||||||
DHCP_init(1, test_buf);
|
DHCP_init(self->dhcp_socket, self->dhcp_buf);
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
ret = DHCP_run();
|
mpy_wiznet_yield();
|
||||||
if (ret == DHCP_IP_LEASED) {
|
if (self->dhcp_state == DHCP_IP_LEASED) {
|
||||||
break;
|
break;
|
||||||
} else if (ret == DHCP_FAILED || mp_hal_ticks_ms() > timeout) {
|
} else if (self->dhcp_state == DHCP_FAILED || mp_hal_ticks_ms() > timeout) {
|
||||||
dhcp_retry++;
|
dhcp_retry++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mpy_wiznet_yield();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dhcp_retry > 3) {
|
if (dhcp_retry > 3) {
|
||||||
|
@ -673,6 +918,8 @@ static void wiznet5k_dhcp_init(wiznet5k_obj_t *self) {
|
||||||
if (ret == DHCP_IP_LEASED) {
|
if (ret == DHCP_IP_LEASED) {
|
||||||
ctlnetwork(CN_GET_NETINFO, &self->netinfo);
|
ctlnetwork(CN_GET_NETINFO, &self->netinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wizchip_clrinterrupt(IK_SOCK_0 << self->dhcp_socket);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // WIZNET5K_PROVIDED_STACK
|
#endif // WIZNET5K_PROVIDED_STACK
|
||||||
|
@ -686,11 +933,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_obj_base_t *spi;
|
||||||
mp_hal_pin_obj_t cs;
|
mp_hal_pin_obj_t cs;
|
||||||
mp_hal_pin_obj_t rst;
|
mp_hal_pin_obj_t rst;
|
||||||
|
|
||||||
#if WIZNET5K_WITH_LWIP_STACK
|
|
||||||
mp_hal_pin_obj_t pin_intn = (mp_hal_pin_obj_t)NULL;
|
mp_hal_pin_obj_t pin_intn = (mp_hal_pin_obj_t)NULL;
|
||||||
bool use_interrupt = false;
|
bool use_interrupt = false;
|
||||||
|
|
||||||
|
#if WIZNET5K_WITH_LWIP_STACK
|
||||||
// Bring down interface while configuring
|
// Bring down interface while configuring
|
||||||
wiznet5k_obj.netif.flags = 0;
|
wiznet5k_obj.netif.flags = 0;
|
||||||
#endif
|
#endif
|
||||||
|
@ -713,7 +959,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)}));
|
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)}));
|
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)}));
|
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;
|
use_interrupt = true;
|
||||||
#endif
|
#endif
|
||||||
|
@ -722,20 +968,14 @@ static mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, size
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
// If passing in args, must supply spi, pin_cs, pin_rst and optionally pin_intn
|
// 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);
|
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]);
|
spi = mp_hal_get_spi_obj(args[0]);
|
||||||
cs = mp_hal_get_pin_obj(args[1]);
|
cs = mp_hal_get_pin_obj(args[1]);
|
||||||
rst = mp_hal_get_pin_obj(args[2]);
|
rst = mp_hal_get_pin_obj(args[2]);
|
||||||
#if WIZNET5K_WITH_LWIP_STACK
|
|
||||||
if (n_args > 3) {
|
if (n_args > 3) {
|
||||||
pin_intn = mp_hal_get_pin_obj(args[3]);
|
pin_intn = mp_hal_get_pin_obj(args[3]);
|
||||||
use_interrupt = true;
|
use_interrupt = true;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mp_hal_pin_output(cs);
|
mp_hal_pin_output(cs);
|
||||||
|
@ -748,9 +988,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.spi_transfer = ((mp_machine_spi_p_t *)MP_OBJ_TYPE_GET_SLOT(spi->type, protocol))->transfer;
|
||||||
wiznet5k_obj.cs = cs;
|
wiznet5k_obj.cs = cs;
|
||||||
wiznet5k_obj.rst = rst;
|
wiznet5k_obj.rst = rst;
|
||||||
#if WIZNET5K_WITH_LWIP_STACK
|
|
||||||
wiznet5k_obj.pin_intn = pin_intn;
|
wiznet5k_obj.pin_intn = pin_intn;
|
||||||
wiznet5k_obj.use_interrupt = use_interrupt;
|
wiznet5k_obj.use_interrupt = use_interrupt;
|
||||||
|
#if WIZNET5K_WITH_LWIP_STACK
|
||||||
wiznet5k_obj.trace_flags = 0;
|
wiznet5k_obj.trace_flags = 0;
|
||||||
#else // WIZNET5K_PROVIDED_STACK
|
#else // WIZNET5K_PROVIDED_STACK
|
||||||
wiznet5k_obj.active = false;
|
wiznet5k_obj.active = false;
|
||||||
|
@ -894,6 +1134,11 @@ static mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) {
|
||||||
} else {
|
} else {
|
||||||
// Set static IP addresses
|
// Set static IP addresses
|
||||||
self->netinfo.dhcp = NETINFO_STATIC;
|
self->netinfo.dhcp = NETINFO_STATIC;
|
||||||
|
self->dhcp_state = DHCP_STOPPED;
|
||||||
|
if (self->dhcp_buf) {
|
||||||
|
m_del(uint8_t, self->dhcp_buf, MAX_DHCP_BUF_SIZE);
|
||||||
|
self->dhcp_buf = NULL;
|
||||||
|
}
|
||||||
mp_obj_t *items;
|
mp_obj_t *items;
|
||||||
mp_obj_get_array_fixed_n(args[1], 4, &items);
|
mp_obj_get_array_fixed_n(args[1], 4, &items);
|
||||||
netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG);
|
netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG);
|
||||||
|
|
|
@ -218,6 +218,10 @@ extern const struct _mp_obj_type_t mod_network_nic_type_nina;
|
||||||
#if MICROPY_PY_NETWORK_WIZNET5K
|
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||||
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
||||||
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
|
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
|
||||||
|
// This Network interface requires the extended socket state for timeouts and non-blocking
|
||||||
|
#ifndef MICROPY_PY_SOCKET_EXTENDED_STATE
|
||||||
|
#define MICROPY_PY_SOCKET_EXTENDED_STATE (1)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define MICROPY_HW_NIC_WIZNET5K
|
#define MICROPY_HW_NIC_WIZNET5K
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -202,6 +202,10 @@ extern const struct _mp_obj_type_t mp_network_cyw43_type;
|
||||||
#if MICROPY_PY_NETWORK_WIZNET5K
|
#if MICROPY_PY_NETWORK_WIZNET5K
|
||||||
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
extern const struct _mp_obj_type_t mod_network_nic_type_wiznet5k;
|
||||||
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
|
#define MICROPY_HW_NIC_WIZNET5K { MP_ROM_QSTR(MP_QSTR_WIZNET5K), MP_ROM_PTR(&mod_network_nic_type_wiznet5k) },
|
||||||
|
// This Network interface requires the extended socket state for timeouts and non-blocking
|
||||||
|
#ifndef MICROPY_PY_SOCKET_EXTENDED_STATE
|
||||||
|
#define MICROPY_PY_SOCKET_EXTENDED_STATE (1)
|
||||||
|
#endif
|
||||||
#else
|
#else
|
||||||
#define MICROPY_HW_NIC_WIZNET5K
|
#define MICROPY_HW_NIC_WIZNET5K
|
||||||
#endif
|
#endif
|
||||||
|
|
Ładowanie…
Reference in New Issue