extmod/network_ninaw10: Add support for socket events callback.

This commit is contained in:
iabdalkader 2022-05-14 14:39:19 +02:00 committed by Damien George
parent be83bdf9ec
commit 0bdfceacbe
5 changed files with 88 additions and 8 deletions

View File

@ -31,6 +31,8 @@
int nina_bsp_init(void); int nina_bsp_init(void);
int nina_bsp_deinit(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_read_irq(void);
int nina_bsp_spi_slave_select(uint32_t timeout); int nina_bsp_spi_slave_select(uint32_t timeout);
int nina_bsp_spi_slave_deselect(void); int nina_bsp_spi_slave_deselect(void);

View File

@ -90,6 +90,20 @@ int nina_bsp_deinit(void) {
return 0; 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) { int nina_bsp_read_irq(void) {
return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0); return mp_hal_pin_read(MICROPY_HW_NINA_GPIO0);
} }

View File

@ -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) { static int nina_send_command_read_ack(uint32_t cmd, uint32_t nargs, uint32_t width, nina_args_t *args) {
uint16_t size = 1; uint16_t size = 1;
uint8_t rval = SPI_ERR; uint8_t rval = SPI_ERR;
nina_bsp_atomic_enter();
if (nina_send_command(cmd, nargs, width, args) != 0 || if (nina_send_command(cmd, nargs, width, args) != 0 ||
nina_read_response(cmd, 1, ARG_8BITS, NINA_VALS({&size, &rval})) != 0) { nina_read_response(cmd, 1, ARG_8BITS, NINA_VALS({&size, &rval})) != 0) {
return -1; rval = -1;
} }
nina_bsp_atomic_exit();
return rval; return rval;
} }
static int nina_send_command_read_vals(uint32_t cmd, uint32_t nargs, 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) { 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 || if (nina_send_command(cmd, nargs, argsw, args) != 0 ||
nina_read_response(cmd, nvals, valsw, vals) != 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) { static void nina_fix_mac_addr(uint8_t *mac) {

View File

@ -43,6 +43,7 @@
#include "py/mperrno.h" #include "py/mperrno.h"
#include "shared/netutils/netutils.h" #include "shared/netutils/netutils.h"
#include "extmod/modnetwork.h" #include "extmod/modnetwork.h"
#include "modmachine.h"
#include "nina_wifi_drv.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 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; static uint16_t bind_port = BIND_PORT_RANGE_MIN;
const mod_network_nic_type_t mod_network_nic_type_nina; 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_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 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) { 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); 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, 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); 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 { } else {
nina_deinit(); nina_deinit();
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_NULL;
MP_STATE_PORT(mp_wifi_sockpoll_list) = MP_OBJ_NULL;
} }
self->active = active; self->active = active;
return mp_const_none; 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) { STATIC int network_ninaw10_socket_poll(mod_network_socket_obj_t *socket, uint32_t rwf, int *_errno) {
uint8_t flags = 0; 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) { if (socket->timeout == 0) {
// Non-blocking socket, next socket function will return EAGAIN // Non-blocking socket, next socket function will return EAGAIN
return 0; return 0;
} }
mp_uint_t start = mp_hal_ticks_ms(); 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)) { if (nina_socket_poll(socket->fileno, &flags) < 0 || (flags & SOCKET_POLL_ERR)) {
nina_socket_errno(_errno); 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; return -1;
} }
if (!(flags & rwf) && socket->timeout != -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 // set socket state
socket->fileno = fd; socket->fileno = fd;
socket->bound = false; socket->bound = false;
socket->callback = MP_OBJ_NULL;
return network_ninaw10_socket_setblocking(socket, false, _errno); return network_ninaw10_socket_setblocking(socket, false, _errno);
} }
STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) { STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
debug_printf("socket_close(%d)\n", socket->fileno); 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) { if (socket->fileno >= 0) {
nina_socket_close(socket->fileno); nina_socket_close(socket->fileno);
socket->fileno = -1; // Mark socket FD as invalid 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 // set socket state
socket2->fileno = fd; socket2->fileno = fd;
socket2->bound = false; socket2->bound = false;
socket2->timeout = -1;
socket2->callback = MP_OBJ_NULL;
return network_ninaw10_socket_setblocking(socket2, false, _errno); 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 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) { level, mp_uint_t opt, const void *optval, mp_uint_t optlen, int *_errno) {
debug_printf("socket_setsockopt(%d, %d)\n", socket->fileno, opt); 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); int ret = nina_socket_setsockopt(socket->fileno, level, opt, optval, optlen);
if (ret < 0) { if (ret < 0) {
nina_socket_errno(_errno); nina_socket_errno(_errno);

View File

@ -154,7 +154,7 @@ struct _mp_bluetooth_nimble_malloc_t;
#define MICROPY_PY_USOCKET_EXTENDED_STATE (1) #define MICROPY_PY_USOCKET_EXTENDED_STATE (1)
#endif #endif
// It also requires an additional root pointer for the SPI object. // 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; 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) }, #define MICROPY_HW_NIC_NINAW10 { MP_ROM_QSTR(MP_QSTR_WLAN), MP_ROM_PTR(&mod_network_nic_type_nina) },
#else #else