Skip to content

Commit 0960d64

Browse files
iabdalkaderdpgeorge
authored andcommitted
extmod/network_ninaw10: Switch to using soft-timer for polling.
This patch simplifies the connection and sockets polling code, by switching to a soft-timer to schedule polling code, and by using one node for scheduling. This also fixes any issues that could result from using a heap allocated machine_timer, and includes better handling of the sockets poll list. Signed-off-by: iabdalkader <[email protected]>
1 parent 50f31cc commit 0960d64

File tree

1 file changed

+74
-39
lines changed

1 file changed

+74
-39
lines changed

extmod/network_ninaw10.c

Lines changed: 74 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
#include "py/misc.h"
4343
#include "py/mperrno.h"
4444
#include "shared/netutils/netutils.h"
45+
#include "shared/runtime/softtimer.h"
4546
#include "extmod/modnetwork.h"
4647
#include "modmachine.h"
4748

@@ -50,6 +51,7 @@
5051
typedef struct _nina_obj_t {
5152
mp_obj_base_t base;
5253
bool active;
54+
bool poll_enable;
5355
uint32_t itf;
5456
mp_uint_t security;
5557
char ssid[NINA_MAX_SSID_LEN + 1];
@@ -71,30 +73,64 @@ typedef struct _nina_obj_t {
7173
#define SO_ERROR (0x1007)
7274
#define SO_TYPE (0x1008)
7375
#define SO_NO_CHECK (0x100a)
76+
#define NINAW10_POLL_INTERVAL (100)
7477

7578
#define is_nonblocking_error(errno) ((errno) == MP_EAGAIN || (errno) == MP_EWOULDBLOCK || (errno) == MP_EINPROGRESS)
7679

7780
#define debug_printf(...) // mp_printf(&mp_plat_print, __VA_ARGS__)
7881

7982
static uint16_t bind_port = BIND_PORT_RANGE_MIN;
8083
const mp_obj_type_t mod_network_nic_type_nina;
81-
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
82-
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
83-
static mp_sched_node_t mp_wifi_sockpoll_node;
84-
static mp_sched_node_t mp_wifi_connpoll_node;
84+
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, false, MOD_NETWORK_STA_IF};
85+
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, false, MOD_NETWORK_AP_IF};
86+
static mp_sched_node_t mp_wifi_poll_node;
87+
static soft_timer_entry_t mp_wifi_poll_timer;
88+
STATIC void network_ninaw10_deinit(void);
89+
90+
STATIC bool network_ninaw10_poll_list_is_empty(void) {
91+
return MP_STATE_PORT(mp_wifi_poll_list) == NULL ||
92+
MP_STATE_PORT(mp_wifi_poll_list)->len == 0;
93+
}
94+
95+
STATIC void network_ninaw10_poll_list_insert(mp_obj_t socket) {
96+
if (MP_STATE_PORT(mp_wifi_poll_list) == NULL) {
97+
MP_STATE_PORT(mp_wifi_poll_list) = mp_obj_new_list(0, NULL);
98+
}
99+
mp_obj_list_append(MP_STATE_PORT(mp_wifi_poll_list), socket);
100+
}
101+
102+
STATIC void network_ninaw10_poll_list_remove(mp_obj_t socket) {
103+
if (MP_STATE_PORT(mp_wifi_poll_list) == NULL) {
104+
return;
105+
}
106+
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_poll_list), socket);
107+
if (MP_STATE_PORT(mp_wifi_poll_list)->len == 0) {
108+
MP_STATE_PORT(mp_wifi_poll_list) = NULL;
109+
}
110+
}
85111

86112
STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
87113
(void)node;
88-
for (mp_uint_t i = 0; i < MP_STATE_PORT(mp_wifi_sockpoll_list)->len; i++) {
89-
mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_sockpoll_list)->items[i];
114+
for (mp_uint_t i = 0; MP_STATE_PORT(mp_wifi_poll_list) && i < MP_STATE_PORT(mp_wifi_poll_list)->len;) {
115+
mod_network_socket_obj_t *socket = MP_STATE_PORT(mp_wifi_poll_list)->items[i];
90116
uint8_t flags = 0;
91117
if (socket->callback == MP_OBJ_NULL || nina_socket_poll(socket->fileno, &flags) < 0) {
92-
// remove from poll list on error.
118+
// Remove socket from poll list on error.
93119
socket->callback = MP_OBJ_NULL;
94-
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
95-
} else if (flags & SOCKET_POLL_RD) {
120+
network_ninaw10_poll_list_remove(socket);
121+
// Check the same index on the next iteration.
122+
continue;
123+
}
124+
if (flags & SOCKET_POLL_RD) {
96125
mp_call_function_1(socket->callback, MP_OBJ_FROM_PTR(socket));
97126
}
127+
i++;
128+
debug_printf("poll_sockets(%d) -> flags %d\n", socket->fileno, flags);
129+
}
130+
131+
if (!network_ninaw10_poll_list_is_empty()) {
132+
// Reschedule the sockets polling code.
133+
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
98134
}
99135
}
100136

@@ -104,10 +140,8 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
104140
int status = nina_connection_status();
105141
if (status == NINA_STATUS_CONNECTED) {
106142
// Connected to AP, nothing else to do.
107-
return;
108-
}
109-
110-
if (status != NINA_STATUS_NO_SSID_AVAIL) {
143+
self->poll_enable = false;
144+
} else if (status != NINA_STATUS_NO_SSID_AVAIL) {
111145
// If not connected, and no connection in progress, the connection attempt has failed.
112146
// Read the ESP failure reason, reconnect and reschedule the connection polling code.
113147
int reason = nina_connection_reason();
@@ -124,21 +158,23 @@ STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
124158
}
125159
} else {
126160
// Will not attempt to reconnect if there's another error code set.
127-
return;
161+
self->poll_enable = false;
128162
}
129163
}
130164

131-
// Reschedule the connection polling code.
132-
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
165+
// Reinsert the timer to schedule the polling code.
166+
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
133167
}
134168

135-
STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
136-
if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
137-
mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
169+
STATIC void network_ninaw10_timer_callback(soft_timer_entry_t *self) {
170+
debug_printf("timer_callback() poll status STA: %d AP: %d SOCKETS: %d\n",
171+
network_nina_wl_sta.poll_enable, network_nina_wl_ap.poll_enable, !network_ninaw10_poll_list_is_empty());
172+
if (network_nina_wl_sta.poll_enable) {
173+
mp_sched_schedule_node(&mp_wifi_poll_node, network_ninaw10_poll_connect);
174+
} else if (!network_ninaw10_poll_list_is_empty()) {
175+
mp_sched_schedule_node(&mp_wifi_poll_node, network_ninaw10_poll_sockets);
138176
}
139-
return mp_const_none;
140177
}
141-
STATIC MP_DEFINE_CONST_FUN_OBJ_1(network_ninaw10_timer_callback_obj, network_ninaw10_timer_callback);
142178

143179
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) {
144180
mp_arg_check_num(n_args, n_kw, 0, 1, false);
@@ -157,6 +193,7 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
157193
nina_obj_t *self = MP_OBJ_TO_PTR(args[0]);
158194
if (n_args == 2) {
159195
bool active = mp_obj_is_true(args[1]);
196+
network_ninaw10_deinit();
160197
if (active) {
161198
int error = 0;
162199
if ((error = nina_init()) != 0) {
@@ -185,19 +222,9 @@ STATIC mp_obj_t network_ninaw10_active(size_t n_args, const mp_obj_t *args) {
185222
NINA_FW_VER_MIN_MAJOR, NINA_FW_VER_MIN_MINOR, NINA_FW_VER_MIN_PATCH, semver[NINA_FW_VER_MAJOR_OFFS] - 48,
186223
semver[NINA_FW_VER_MINOR_OFFS] - 48, semver[NINA_FW_VER_PATCH_OFFS] - 48);
187224
}
188-
MP_STATE_PORT(mp_wifi_sockpoll_list) = mp_obj_new_list(0, NULL);
189-
if (MP_STATE_PORT(mp_wifi_timer) == MP_OBJ_NULL) {
190-
// Start sockets poll timer
191-
mp_obj_t timer_args[] = {
192-
MP_OBJ_NEW_QSTR(MP_QSTR_freq), MP_OBJ_NEW_SMALL_INT(10),
193-
MP_OBJ_NEW_QSTR(MP_QSTR_callback), MP_OBJ_FROM_PTR(&network_ninaw10_timer_callback_obj),
194-
};
195-
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_TYPE_GET_SLOT(&machine_timer_type, make_new)((mp_obj_t)&machine_timer_type, 0, 2, timer_args);
196-
}
225+
soft_timer_static_init(&mp_wifi_poll_timer, SOFT_TIMER_MODE_ONE_SHOT, 0, network_ninaw10_timer_callback);
197226
} else {
198227
nina_deinit();
199-
MP_STATE_PORT(mp_wifi_timer) = MP_OBJ_NULL;
200-
MP_STATE_PORT(mp_wifi_sockpoll_list) = MP_OBJ_NULL;
201228
}
202229
self->active = active;
203230
return mp_const_none;
@@ -278,7 +305,8 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
278305
self->security = security;
279306
strncpy(self->key, key, NINA_MAX_WPA_LEN);
280307
strncpy(self->ssid, ssid, NINA_MAX_SSID_LEN);
281-
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
308+
self->poll_enable = true;
309+
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
282310
} else {
283311
mp_uint_t channel = args[ARG_channel].u_int;
284312

@@ -528,10 +556,8 @@ STATIC int network_ninaw10_socket_socket(mod_network_socket_obj_t *socket, int *
528556
STATIC void network_ninaw10_socket_close(mod_network_socket_obj_t *socket) {
529557
debug_printf("socket_close(%d)\n", socket->fileno);
530558
if (socket->callback != MP_OBJ_NULL) {
531-
mp_sched_lock();
532559
socket->callback = MP_OBJ_NULL;
533-
mp_obj_list_remove(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
534-
mp_sched_unlock();
560+
network_ninaw10_poll_list_remove(socket);
535561
}
536562
if (socket->fileno >= 0) {
537563
nina_socket_close(socket->fileno);
@@ -739,7 +765,8 @@ STATIC int network_ninaw10_socket_setsockopt(mod_network_socket_obj_t *socket, m
739765
mp_sched_lock();
740766
socket->callback = (void *)optval;
741767
if (socket->callback != MP_OBJ_NULL) {
742-
mp_obj_list_append(MP_STATE_PORT(mp_wifi_sockpoll_list), socket);
768+
network_ninaw10_poll_list_insert(socket);
769+
soft_timer_reinsert(&mp_wifi_poll_timer, NINAW10_POLL_INTERVAL);
743770
}
744771
mp_sched_unlock();
745772
return 0;
@@ -803,6 +830,14 @@ STATIC int network_ninaw10_socket_ioctl(mod_network_socket_obj_t *socket, mp_uin
803830
return ret;
804831
}
805832

833+
STATIC void network_ninaw10_deinit(void) {
834+
// On soft-reboot, gc_sweep_all is called and all open sockets are closed
835+
// and collected. Make sure that the driver is not keeping any references
836+
// to collected sockets in the poll list.
837+
soft_timer_remove(&mp_wifi_poll_timer);
838+
MP_STATE_PORT(mp_wifi_poll_list) = NULL;
839+
}
840+
806841
STATIC const mp_rom_map_elem_t nina_locals_dict_table[] = {
807842
{ MP_ROM_QSTR(MP_QSTR_active), MP_ROM_PTR(&network_ninaw10_active_obj) },
808843
{ MP_ROM_QSTR(MP_QSTR_scan), MP_ROM_PTR(&network_ninaw10_scan_obj) },
@@ -826,6 +861,7 @@ STATIC MP_DEFINE_CONST_DICT(nina_locals_dict, nina_locals_dict_table);
826861

827862
STATIC const mod_network_nic_protocol_t mod_network_nic_protocol_nina = {
828863
.gethostbyname = network_ninaw10_gethostbyname,
864+
.deinit = network_ninaw10_deinit,
829865
.socket = network_ninaw10_socket_socket,
830866
.close = network_ninaw10_socket_close,
831867
.bind = network_ninaw10_socket_bind,
@@ -851,7 +887,6 @@ MP_DEFINE_CONST_OBJ_TYPE(
851887
);
852888

853889
MP_REGISTER_ROOT_POINTER(struct _machine_spi_obj_t *mp_wifi_spi);
854-
MP_REGISTER_ROOT_POINTER(struct _machine_timer_obj_t *mp_wifi_timer);
855-
MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_sockpoll_list);
890+
MP_REGISTER_ROOT_POINTER(struct _mp_obj_list_t *mp_wifi_poll_list);
856891

857892
#endif // #if MICROPY_PY_BLUETOOTH && MICROPY_PY_NETWORK_NINAW10

0 commit comments

Comments
 (0)