Skip to content

WIP: Circuitpython nickzoic 1800 wiznet socket #1837

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion shared-bindings/socket/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}


Expand Down
53 changes: 40 additions & 13 deletions shared-bindings/wiznet/wiznet5k.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -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;
}
Expand All @@ -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) {
Expand All @@ -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);
Expand Down Expand Up @@ -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
10 changes: 10 additions & 0 deletions shared-module/network/__init__.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
6 changes: 4 additions & 2 deletions shared-module/network/__init__.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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 {
Expand Down
82 changes: 54 additions & 28 deletions shared-module/wiznet/wiznet5k.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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.
Expand All @@ -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
Expand All @@ -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);
Expand All @@ -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);

Expand Down
7 changes: 4 additions & 3 deletions shared-module/wiznet/wiznet5k.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down