summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoriabdalkader <i.abdalkader@gmail.com>2022-05-14 14:39:19 +0200
committerDamien George <damien@micropython.org>2022-05-26 11:15:07 +1000
commit0bdfceacbe7e0c27c585579feb9c21d6be747974 (patch)
treedf7987647d7177872424302659942d84c44c0d15
parentbe83bdf9ecec2395545357c75bfc4625631e27d5 (diff)
extmod/network_ninaw10: Add support for socket events callback.
-rw-r--r--drivers/ninaw10/nina_bsp.h2
-rw-r--r--drivers/ninaw10/nina_wifi_bsp.c14
-rw-r--r--drivers/ninaw10/nina_wifi_drv.c11
-rw-r--r--extmod/network_ninaw10.c67
-rw-r--r--ports/rp2/mpconfigport.h2
5 files changed, 88 insertions, 8 deletions
diff --git a/drivers/ninaw10/nina_bsp.h b/drivers/ninaw10/nina_bsp.h
index 362583843..76c9b5b82 100644
--- a/drivers/ninaw10/nina_bsp.h
+++ b/drivers/ninaw10/nina_bsp.h
@@ -31,6 +31,8 @@
int nina_bsp_init(void);
int nina_bsp_deinit(void);
+int nina_bsp_atomic_enter(void);
+int nina_bsp_atomic_exit(void);
int nina_bsp_read_irq(void);
int nina_bsp_spi_slave_select(uint32_t timeout);
int nina_bsp_spi_slave_deselect(void);
diff --git a/drivers/ninaw10/nina_wifi_bsp.c b/drivers/ninaw10/nina_wifi_bsp.c
index 6d04f46ef..a65ef7fd8 100644
--- a/drivers/ninaw10/nina_wifi_bsp.c
+++ b/drivers/ninaw10/nina_wifi_bsp.c
@@ -90,6 +90,20 @@ int nina_bsp_deinit(void) {
return 0;
}
+int nina_bsp_atomic_enter(void) {
+ #if MICROPY_ENABLE_SCHEDULER
+ mp_sched_lock();
+ #endif
+ return 0;
+}
+
+int nina_bsp_atomic_exit(void) {
+ #if MICROPY_ENABLE_SCHEDULER
+ mp_sched_unlock();
+ #endif
+ return 0;
+}
+
int nina_bsp_read_irq(void) {
return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0);
}
diff --git a/drivers/ninaw10/nina_wifi_drv.c b/drivers/ninaw10/nina_wifi_drv.c
index 0131476a0..7a1167b2c 100644
--- a/drivers/ninaw10/nina_wifi_drv.c
+++ b/drivers/ninaw10/nina_wifi_drv.c
@@ -325,20 +325,25 @@ error_out:
static int nina_send_command_read_ack(uint32_t cmd, uint32_t nargs, uint32_t width, nina_args_t *args) {
uint16_t size = 1;
uint8_t rval = SPI_ERR;
+ nina_bsp_atomic_enter();
if (nina_send_command(cmd, nargs, width, args) != 0 ||
nina_read_response(cmd, 1, ARG_8BITS, NINA_VALS({&size, &rval})) != 0) {
- return -1;
+ rval = -1;
}
+ nina_bsp_atomic_exit();
return rval;
}
static int nina_send_command_read_vals(uint32_t cmd, uint32_t nargs,
uint32_t argsw, nina_args_t *args, uint32_t nvals, uint32_t valsw, nina_vals_t *vals) {
+ int ret = 0;
+ nina_bsp_atomic_enter();
if (nina_send_command(cmd, nargs, argsw, args) != 0 ||
nina_read_response(cmd, nvals, valsw, vals) != 0) {
- return -1;
+ ret = -1;
}
- return 0;
+ nina_bsp_atomic_exit();
+ return ret;
}
static void nina_fix_mac_addr(uint8_t *mac) {
diff --git a/extmod/network_ninaw10.c b/extmod/network_ninaw10.c
index 64b73d608..6921ed3f2 100644
--- a/extmod/network_ninaw10.c
+++ b/extmod/network_ninaw10.c
@@ -43,6 +43,7 @@
#include "py/mperrno.h"
#include "shared/netutils/netutils.h"
#include "extmod/modnetwork.h"
+#include "modmachine.h"
#include "nina_wifi_drv.h"
@@ -70,12 +71,41 @@ typedef struct _nina_obj_t {
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
-#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
+#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
const mod_network_nic_type_t mod_network_nic_type_nina;
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
+static mp_sched_node_t mp_wifi_sockpoll_node;
+
+STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
+ (void)node;
+ for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_wifi_sockpoll_list)->len; i++) {
+ mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_sockpoll_list)->items[i];
+ uint8_t flags = 0;
+ if (socket->callback == MP_OBJ_NULL || nina_socket_poll(socket->fileno, &flags) < 0) {
+ // remove from poll list on error.
+ socket->callback = MP_OBJ_NULL;
+ mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
+ } else if (flags) {
+ mp_call_function_1(socket->callback, MP_OBJ_FROM_PTR(socket));
+ if (flags & SOCKET_POLL_ERR) {
+ // remove from poll list on error.
+ socket->callback = MP_OBJ_NULL;
+ mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
+ }
+ }
+ }
+}
+
+STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
+ if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
+ mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
+ }
+ return mp_const_none;
+}
+STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_timer_callback_obj, network_ninaw10_timer_callback);
STATIC mp_obj_t network_ninaw10_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
mp_arg_check_num(n_args, n_kw, 0, 1, false);
@@ -122,8 +152,19 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
NINA_FW_VER_MIN_MAJOR, NINA_FW_VER_MIN_MINOR, NINA_FW_VER_MIN_PATCH, semver[NINA_FW_VER_MAJOR_OFFS] - 48,
semver[NINA_FW_VER_MINOR_OFFS] - 48, semver[NINA_FW_VER_PATCH_OFFS] - 48);
}
+ MP_STATE_PORT(mp_wifi_sockpoll_list) = mp_obj_new_list(0, NULL);
+ if (MP_STATE_PORT(mp_wifi_timer) == MP_OBJ_NULL) {
+ // Start sockets poll timer
+ mp_obj_t timer_args[] = {
+ MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10),
+ MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj),
+ };
+ MP_STATE_PORT(mp_wifi_timer) = machine_timer_type.make_new((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
+ }
} else {
nina_deinit();
+ MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_NULL;
+ MP_STATE_PORT(mp_wifi_sockpoll_list) = MP_OBJ_NULL;
}
self->active = active;
return mp_const_none;
@@ -354,16 +395,16 @@ STATIC int network_ninaw10_gethostbyname(mp_obj_t nic, const char *name, mp_uint
STATIC int network_ninaw10_socket_poll(mod_network_socket_obj_t *socket, uint32_t rwf, int *_errno) {
uint8_t flags = 0;
- debug_printf("socket_polling_rw(%d, %d)\n", socket->fileno, rwf);
+ debug_printf("socket_polling_rw(%d, %d, %d)\n", socket->fileno, socket->timeout, rwf);
if (socket->timeout == 0) {
// Non-blocking socket, next socket function will return EAGAIN
return 0;
}
mp_uint_t start = mp_hal_ticks_ms();
- while (!(flags & rwf)) {
+ for (; !(flags & rwf); mp_hal_delay_ms(5)) {
if (nina_socket_poll(socket->fileno, &flags) < 0 || (flags & SOCKET_POLL_ERR)) {
nina_socket_errno(_errno);
- debug_printf("socket_poll() -> errno %d\n", *_errno);
+ debug_printf("socket_poll(%d) -> errno %d flags %d\n", socket->fileno, *_errno, flags);
return -1;
}
if (!(flags & rwf) && socket->timeout != -1 &&
@@ -416,11 +457,18 @@ STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *
// set socket state
socket->fileno = fd;
socket->bound = false;
+ socket->callback = MP_OBJ_NULL;
return network_ninaw10_socket_setblocking(socket, false, _errno);
}
STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
debug_printf("socket_close(%d)\n", socket->fileno);
+ if (socket->callback != MP_OBJ_NULL) {
+ mp_sched_lock();
+ socket->callback = MP_OBJ_NULL;
+ mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
+ mp_sched_unlock();
+ }
if (socket->fileno >= 0) {
nina_socket_close(socket->fileno);
socket->fileno = -1; // Mark socket FD as invalid
@@ -493,6 +541,8 @@ STATIC int network_ninaw10_socket_accept(mod_network_socket_obj_t *socket,
// set socket state
socket2->fileno = fd;
socket2->bound = false;
+ socket2->timeout = -1;
+ socket2->callback = MP_OBJ_NULL;
return network_ninaw10_socket_setblocking(socket2, false, _errno);
}
@@ -635,6 +685,15 @@ STATIC mp_uint_t network_ninaw10_socket_recvfrom(mod_network_socket_obj_t *socke
STATIC int network_ninaw10_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) {
debug_printf("socket_setsockopt(%d, %d)\n", socket->fileno, opt);
+ if (opt == 20) {
+ mp_sched_lock();
+ socket->callback = (void *)optval;
+ if (socket->callback != MP_OBJ_NULL) {
+ mp_obj_list_append(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
+ }
+ mp_sched_unlock();
+ return 0;
+ }
int ret = nina_socket_setsockopt(socket->fileno, level, opt, optval, optlen);
if (ret < 0) {
nina_socket_errno(_errno);
diff --git a/ports/rp2/mpconfigport.h b/ports/rp2/mpconfigport.h
index 63faf36ea..3ded45fa1 100644
--- a/ports/rp2/mpconfigport.h
+++ b/ports/rp2/mpconfigport.h
@@ -154,7 +154,7 @@ struct _mp_bluetooth_nimble_malloc_t;
#define MICROPY_PY_USOCKET_EXTENDED_STATE (1)
#endif
// It also requires an additional root pointer for the SPI object.
-#define MICROPY_PORT_ROOT_POINTER_NINAW10 struct _machine_spi_obj_t *mp_wifi_spi;
+#define MICROPY_PORT_ROOT_POINTER_NINAW10 struct _machine_spi_obj_t *mp_wifi_spi; struct _machine_timer_obj_t *mp_wifi_timer; struct _mp_obj_list_t *mp_wifi_sockpoll_list;
extern const struct _mod_network_nic_type_t mod_network_nic_type_nina;
#define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) },
#else