diff options
| -rw-r--r-- | shared-bindings/socket/__init__.c | 2 | ||||
| -rw-r--r-- | shared-bindings/wiznet/wiznet5k.c | 53 | ||||
| -rw-r--r-- | shared-module/network/__init__.c | 10 | ||||
| -rw-r--r-- | shared-module/network/__init__.h | 6 | ||||
| -rw-r--r-- | shared-module/wiznet/wiznet5k.c | 82 | ||||
| -rw-r--r-- | shared-module/wiznet/wiznet5k.h | 7 |
6 files changed, 113 insertions, 47 deletions
diff --git a/shared-bindings/socket/__init__.c b/shared-bindings/socket/__init__.c index c59724efc..8e34c3700 100644 --- a/shared-bindings/socket/__init__.c +++ b/shared-bindings/socket/__init__.c @@ -248,7 +248,7 @@ STATIC mp_int_t _socket_recv_into(mod_network_socket_obj_t *sock, byte *buf, mp_ if (ret == -1) { mp_raise_OSError(_errno); } - return len; + return ret; } diff --git a/shared-bindings/wiznet/wiznet5k.c b/shared-bindings/wiznet/wiznet5k.c index 6d43e8992..878095b2a 100644 --- a/shared-bindings/wiznet/wiznet5k.c +++ b/shared-bindings/wiznet/wiznet5k.c @@ -41,6 +41,7 @@ #include "shared-bindings/digitalio/DigitalInOut.h" #include "shared-bindings/digitalio/DriveMode.h" #include "shared-bindings/busio/SPI.h" +#include "shared-bindings/microcontroller/Pin.h" #include "shared-module/network/__init__.h" #include "shared-module/wiznet/wiznet5k.h" @@ -50,25 +51,44 @@ //| :class:`WIZNET5K` -- wrapper for Wiznet 5500 Ethernet interface //| =============================================================== //| -//| .. class:: WIZNET5K(spi, cs, rst) +//| .. class:: WIZNET5K(spi, cs, rst, dhcp=True) //| //| Create a new WIZNET5500 interface using the specified pins //| -//| :param spi: spi bus to use -//| :param cs: pin to use for Chip Select -//| :param rst: pin to sue for Reset +//| :param ~busio.SPI spi: spi bus to use +//| :param ~microcontroller.Pin cs: pin to use for Chip Select +//| :param ~microcontroller.Pin rst: pin to use for Reset (optional) +//| :param bool dhcp: boolean flag, whether to start DHCP automatically (optional, keyword only, default True) +//| +//| * The reset pin is optional: if supplied it is used to reset the +//| wiznet board before initialization. +//| * The SPI bus will be initialized appropriately by this library. +//| * At present, the WIZNET5K object is a singleton, so only one WizNet +//| interface is supported at a time. //| -STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *args, mp_map_t *kw_args) { - // check arguments - mp_arg_check_num(n_args, kw_args, 3, 3, false); - - return wiznet5k_create(args[0], args[1], args[2]); +STATIC mp_obj_t wiznet5k_make_new(const mp_obj_type_t *type, size_t n_args, const mp_obj_t *pos_args, mp_map_t *kw_args) { + enum { ARG_spi, ARG_cs, ARG_rst, ARG_dhcp }; + static const mp_arg_t allowed_args[] = { + { MP_QSTR_spi, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_cs, MP_ARG_REQUIRED | MP_ARG_OBJ }, + { MP_QSTR_rst, MP_ARG_OBJ, { .u_obj = mp_const_none } }, + { MP_QSTR_dhcp, MP_ARG_KW_ONLY | MP_ARG_BOOL, { .u_bool = true } }, + }; + mp_arg_val_t args[MP_ARRAY_SIZE(allowed_args)]; + mp_arg_parse_all(n_args, pos_args, kw_args, MP_ARRAY_SIZE(allowed_args), allowed_args, args); + // TODO check type of ARG_spi? + assert_pin(args[ARG_cs].u_obj, false); + assert_pin(args[ARG_rst].u_obj, true); // may be NULL + + mp_obj_t ret = wiznet5k_create(args[ARG_spi].u_obj, args[ARG_cs].u_obj, args[ARG_rst].u_obj); + if (args[ARG_dhcp].u_bool) wiznet5k_start_dhcp(); + return ret; } //| .. attribute:: connected //| -//| is this device physically connected? +//| (boolean, readonly) is this device physically connected? //| STATIC mp_obj_t wiznet5k_connected_get_value(mp_obj_t self_in) { @@ -86,7 +106,9 @@ const mp_obj_property_t wiznet5k_connected_obj = { //| .. attribute:: dhcp //| -//| is DHCP active on this device? (set to true to activate DHCP, false to turn it off) +//| (boolean, readwrite) is DHCP active on this device? +//| +//| * set to True to activate DHCP, False to turn it off //| STATIC mp_obj_t wiznet5k_dhcp_get_value(mp_obj_t self_in) { @@ -99,9 +121,11 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(wiznet5k_dhcp_get_value_obj, wiznet5k_dhcp_get_ STATIC mp_obj_t wiznet5k_dhcp_set_value(mp_obj_t self_in, mp_obj_t value) { (void)self_in; if (mp_obj_is_true(value)) { - wiznet5k_start_dhcp(); + int ret = wiznet5k_start_dhcp(); + if (ret) mp_raise_OSError(ret); } else { - wiznet5k_stop_dhcp(); + int ret = wiznet5k_stop_dhcp(); + if (ret) mp_raise_OSError(ret); } return mp_const_none; } @@ -120,6 +144,7 @@ const mp_obj_property_t wiznet5k_dhcp_obj = { //| (ip_address, subnet_mask, gateway_address, dns_server) //| //| Or can be called with the same tuple to set those parameters. +//| Setting ifconfig parameters turns DHCP off, if it was on. //| STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { @@ -136,6 +161,7 @@ STATIC mp_obj_t wiznet5k_ifconfig(size_t n_args, const mp_obj_t *args) { return mp_obj_new_tuple(4, tuple); } else { // set + wiznet5k_stop_dhcp(); mp_obj_t *items; mp_obj_get_array_fixed_n(args[1], 4, &items); netutils_parse_ipv4_addr(items[0], netinfo.ip, NETUTILS_BIG); @@ -178,6 +204,7 @@ const mod_network_nic_type_t mod_network_nic_type_wiznet5k = { .settimeout = wiznet5k_socket_settimeout, .ioctl = wiznet5k_socket_ioctl, .timer_tick = wiznet5k_socket_timer_tick, + .deinit = wiznet5k_socket_deinit, }; #endif // MICROPY_PY_WIZNET5K diff --git a/shared-module/network/__init__.c b/shared-module/network/__init__.c index a674e8478..96648b260 100644 --- a/shared-module/network/__init__.c +++ b/shared-module/network/__init__.c @@ -43,6 +43,12 @@ void network_module_init(void) { } void network_module_deinit(void) { + for (mp_uint_t i = 0; i < MP_STATE_PORT(mod_network_nic_list).len; i++) { + mp_obj_t nic = MP_STATE_PORT(mod_network_nic_list).items[i]; + mod_network_nic_type_t *nic_type = (mod_network_nic_type_t*)mp_obj_get_type(nic); + if (nic_type->deinit != NULL) nic_type->deinit(nic); + } + mp_obj_list_set_len(&MP_STATE_PORT(mod_network_nic_list), 0); } void network_module_background(void) { @@ -93,3 +99,7 @@ void network_module_create_random_mac_address(uint8_t *mac) { mac[4] = (uint8_t)(rb2 >> 8); mac[5] = (uint8_t)(rb2); } + +uint16_t network_module_create_random_source_tcp_port(void) { + return 0xc000 | shared_modules_random_getrandbits(14); +} diff --git a/shared-module/network/__init__.h b/shared-module/network/__init__.h index 00a3c3957..f4eb05bb5 100644 --- a/shared-module/network/__init__.h +++ b/shared-module/network/__init__.h @@ -25,11 +25,12 @@ * THE SOFTWARE. */ -void network_module_create_random_mac_address(uint8_t *mac); - #ifndef MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H #define MICROPY_INCLUDED_SHARED_MODULE_NETWORK___INIT___H +void network_module_create_random_mac_address(uint8_t *mac); +uint16_t network_module_create_random_source_tcp_port(void); + #define MOD_NETWORK_IPADDR_BUF_SIZE (4) #define MOD_NETWORK_AF_INET (2) @@ -62,6 +63,7 @@ typedef struct _mod_network_nic_type_t { int (*settimeout)(struct _mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); int (*ioctl)(struct _mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); void (*timer_tick)(struct _mod_network_socket_obj_t *socket); + void (*deinit)(struct _mod_network_socket_obj_t *socket); } mod_network_nic_type_t; typedef struct _mod_network_socket_obj_t { diff --git a/shared-module/wiznet/wiznet5k.c b/shared-module/wiznet/wiznet5k.c index ee732859a..3c5c5f0c8 100644 --- a/shared-module/wiznet/wiznet5k.c +++ b/shared-module/wiznet/wiznet5k.c @@ -93,6 +93,16 @@ int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_ } } +int get_available_socket(wiznet5k_obj_t *wiz) { + for (uint8_t sn = 0; sn < _WIZCHIP_SOCK_NUM_; sn++) { + if ((wiz->socket_used & (1 << sn)) == 0) { + wiz->socket_used |= (1 << sn); + return sn; + } + } + return -1; +} + int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { if (socket->u_param.domain != MOD_NETWORK_AF_INET) { *_errno = MP_EAFNOSUPPORT; @@ -107,13 +117,7 @@ int wiznet5k_socket_socket(mod_network_socket_obj_t *socket, int *_errno) { if (socket->u_param.fileno == -1) { // 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); - socket->u_param.fileno = sn; - break; - } - } + socket->u_param.fileno = get_available_socket(&wiznet5k_obj); if (socket->u_param.fileno == -1) { // too many open sockets *_errno = MP_EMFILE; @@ -199,8 +203,12 @@ int wiznet5k_socket_accept(mod_network_socket_obj_t *socket, mod_network_socket_ } int wiznet5k_socket_connect(mod_network_socket_obj_t *socket, byte *ip, mp_uint_t port, int *_errno) { + uint16_t src_port = network_module_create_random_source_tcp_port(); + // make sure same outgoing port number can't be in use by two different sockets. + src_port = (src_port & ~(_WIZCHIP_SOCK_NUM_ - 1)) | socket->u_param.fileno; + // use "bind" function to open the socket in client mode - if (wiznet5k_socket_bind(socket, ip, 0, _errno) != 0) { + if (wiznet5k_socket_bind(socket, NULL, src_port, _errno) != 0) { return -1; } @@ -318,33 +326,56 @@ int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, m } void wiznet5k_socket_timer_tick(mod_network_socket_obj_t *socket) { - if (wiznet5k_obj.dhcp_active) { + if (wiznet5k_obj.dhcp_socket >= 0) { DHCP_time_handler(); DHCP_run(); } } -void wiznet5k_start_dhcp(void) { +int wiznet5k_start_dhcp(void) { + // XXX this should throw an error if DHCP fails static DHCP_INIT_BUFFER_TYPE dhcp_buf[DHCP_INIT_BUFFER_SIZE]; - if (!wiznet5k_obj.dhcp_active) { + if (wiznet5k_obj.dhcp_socket < 0) { // Set up the socket to listen on UDP 68 before calling DHCP_init - WIZCHIP_EXPORT(socket)(0, MOD_NETWORK_SOCK_DGRAM, DHCP_CLIENT_PORT, 0); - DHCP_init(0, dhcp_buf); - wiznet5k_obj.dhcp_active = 1; + wiznet5k_obj.dhcp_socket = get_available_socket(&wiznet5k_obj); + if (wiznet5k_obj.dhcp_socket < 0) return MP_EMFILE; + + WIZCHIP_EXPORT(socket)(wiznet5k_obj.dhcp_socket, MOD_NETWORK_SOCK_DGRAM, DHCP_CLIENT_PORT, 0); + DHCP_init(wiznet5k_obj.dhcp_socket, dhcp_buf); } + return 0; } -void wiznet5k_stop_dhcp(void) { - if (wiznet5k_obj.dhcp_active) { - wiznet5k_obj.dhcp_active = 0; +int wiznet5k_stop_dhcp(void) { + if (wiznet5k_obj.dhcp_socket >= 0) { DHCP_stop(); - WIZCHIP_EXPORT(close)(0); + WIZCHIP_EXPORT(close)(wiznet5k_obj.dhcp_socket); + wiznet5k_obj.socket_used &= ~(1 << wiznet5k_obj.dhcp_socket); + wiznet5k_obj.dhcp_socket = -1; } + return 0; } bool wiznet5k_check_dhcp(void) { - return wiznet5k_obj.dhcp_active; + return wiznet5k_obj.dhcp_socket >= 0; +} + +void wiznet5k_reset(void) { + if (wiznet5k_obj.rst.pin) { + // hardware reset if using RST pin + common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 0); + mp_hal_delay_us(10); // datasheet says 2us + common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 1); + mp_hal_delay_ms(150); // datasheet says 150ms + } else { + // otherwise, software reset + wizchip_sw_reset(); + } +} + +void wiznet5k_socket_deinit(mod_network_socket_obj_t *socket) { + wiznet5k_reset(); } /// Create and return a WIZNET5K object. @@ -354,9 +385,8 @@ mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in) { wiznet5k_obj.base.type = (mp_obj_type_t*)&mod_network_nic_type_wiznet5k; wiznet5k_obj.cris_state = 0; wiznet5k_obj.spi = MP_OBJ_TO_PTR(spi_in); - common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.cs, cs_in); - common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.rst, rst_in); wiznet5k_obj.socket_used = 0; + wiznet5k_obj.dhcp_socket = -1; /*!< SPI configuration */ // XXX probably should check if the provided SPI is already configured, and @@ -369,13 +399,11 @@ mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in) { 8 // 8 BITS ); + common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.cs, cs_in); common_hal_digitalio_digitalinout_switch_to_output(&wiznet5k_obj.cs, 1, DRIVE_MODE_PUSH_PULL); - common_hal_digitalio_digitalinout_switch_to_output(&wiznet5k_obj.rst, 1, DRIVE_MODE_PUSH_PULL); - common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 0); - mp_hal_delay_us(10); // datasheet says 2us - common_hal_digitalio_digitalinout_set_value(&wiznet5k_obj.rst, 1); - mp_hal_delay_ms(160); // datasheet says 150ms + if (rst_in) common_hal_digitalio_digitalinout_construct(&wiznet5k_obj.rst, rst_in); + wiznet5k_reset(); reg_wizchip_cris_cbfunc(wiz_cris_enter, wiz_cris_exit); reg_wizchip_cs_cbfunc(wiz_cs_select, wiz_cs_deselect); @@ -394,8 +422,6 @@ mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in) { // seems we need a small delay after init mp_hal_delay_ms(250); - wiznet5k_start_dhcp(); - // register with network module network_module_register_nic(&wiznet5k_obj); diff --git a/shared-module/wiznet/wiznet5k.h b/shared-module/wiznet/wiznet5k.h index 1284a44fd..0154831c7 100644 --- a/shared-module/wiznet/wiznet5k.h +++ b/shared-module/wiznet/wiznet5k.h @@ -39,7 +39,7 @@ typedef struct _wiznet5k_obj_t { digitalio_digitalinout_obj_t cs; digitalio_digitalinout_obj_t rst; uint8_t socket_used; - bool dhcp_active; + int8_t dhcp_socket; // -1 for DHCP not in use } wiznet5k_obj_t; int wiznet5k_gethostbyname(mp_obj_t nic, const char *name, mp_uint_t len, uint8_t *out_ip); @@ -57,11 +57,12 @@ int wiznet5k_socket_setsockopt(mod_network_socket_obj_t *socket, mp_uint_t level int wiznet5k_socket_settimeout(mod_network_socket_obj_t *socket, mp_uint_t timeout_ms, int *_errno); int wiznet5k_socket_ioctl(mod_network_socket_obj_t *socket, mp_uint_t request, mp_uint_t arg, int *_errno); void wiznet5k_socket_timer_tick(mod_network_socket_obj_t *socket); +void wiznet5k_socket_deinit(mod_network_socket_obj_t *socket); mp_obj_t wiznet5k_socket_disconnect(mp_obj_t self_in); mp_obj_t wiznet5k_create(mp_obj_t spi_in, mp_obj_t cs_in, mp_obj_t rst_in); -void wiznet5k_start_dhcp(void); -void wiznet5k_stop_dhcp(void); +int wiznet5k_start_dhcp(void); +int wiznet5k_stop_dhcp(void); bool wiznet5k_check_dhcp(void); extern const mod_network_nic_type_t mod_network_nic_type_wiznet5k; |
