Skip to content

Commit b9c1e4c

Browse files
iabdalkaderdpgeorge
authored andcommitted
drivers/ninaw10: Connect to WiFi asynchronously.
Before this patch, WiFi connection was blocking, and could raise exceptions if the connection failed for any reason (including timeouts). This doesn't match the behavior of other WiFi modules, which connect asynchronously, and requires handling of exceptions on connect. This change makes `connect()` work asynchronously by scheduling code to poll connection status, and handle reconnects (if needed), and return immediately without blocking.
1 parent 8a91c71 commit b9c1e4c

File tree

3 files changed

+79
-29
lines changed

3 files changed

+79
-29
lines changed

drivers/ninaw10/nina_wifi_drv.c

+8-29
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,7 @@ typedef enum {
108108
// Disonnect/status commands.
109109
NINA_CMD_DISCONNECT = 0x30,
110110
NINA_CMD_CONN_STATUS = 0x20,
111+
NINA_CMD_CONN_REASON = 0x1F,
111112

112113
// Interface config commands.
113114
NINA_CMD_SET_IF_CONFIG = 0x14,
@@ -173,19 +174,6 @@ typedef enum {
173174
NINA_CMD_CMD_DOWNLOAD_OTA = 0x67,
174175
} nina_cmd_t;
175176

176-
typedef enum {
177-
NINA_STATUS_IDLE = 0,
178-
NINA_STATUS_NO_SSID_AVAIL,
179-
NINA_STATUS_SCAN_COMPLETED,
180-
NINA_STATUS_CONNECTED,
181-
NINA_STATUS_CONNECT_FAILED,
182-
NINA_STATUS_CONNECTION_LOST,
183-
NINA_STATUS_DISCONNECTED,
184-
NINA_STATUS_AP_LISTENING,
185-
NINA_STATUS_AP_CONNECTED,
186-
NINA_STATUS_AP_FAILED
187-
} nina_status_t;
188-
189177
typedef enum {
190178
SOCKET_STATE_CLOSED = 0,
191179
SOCKET_STATE_LISTEN,
@@ -364,13 +352,15 @@ int nina_deinit(void) {
364352
return nina_bsp_deinit();
365353
}
366354

367-
static int nina_connection_status() {
355+
int nina_connection_status(void) {
368356
return nina_send_command_read_ack(NINA_CMD_CONN_STATUS, 0, ARG_8BITS, NULL);
369357
}
370358

371-
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
372-
uint8_t status = NINA_STATUS_CONNECT_FAILED;
359+
int nina_connection_reason(void) {
360+
return nina_send_command_read_ack(NINA_CMD_CONN_REASON, 0, ARG_8BITS, NULL);
361+
}
373362

363+
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
374364
if (key == NULL && security != NINA_SEC_OPEN) {
375365
return -1;
376366
}
@@ -398,18 +388,7 @@ int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t c
398388
return -1;
399389
}
400390

401-
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
402-
status = nina_connection_status();
403-
if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
404-
break;
405-
}
406-
407-
if ((mp_hal_ticks_ms() - start) >= NINA_CONNECT_TIMEOUT) {
408-
break;
409-
}
410-
}
411-
412-
return (status == NINA_STATUS_CONNECTED) ? 0 : -1;
391+
return 0;
413392
}
414393

415394
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel) {
@@ -439,7 +418,7 @@ int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t
439418

440419
for (mp_uint_t start = mp_hal_ticks_ms(); ; mp_hal_delay_ms(10)) {
441420
status = nina_connection_status();
442-
if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL) && (status != NINA_STATUS_SCAN_COMPLETED)) {
421+
if ((status != NINA_STATUS_IDLE) && (status != NINA_STATUS_NO_SSID_AVAIL)) {
443422
break;
444423
}
445424

drivers/ninaw10/nina_wifi_drv.h

+26
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,17 @@
4646
#define NINA_FW_VER_MINOR_OFFS (2)
4747
#define NINA_FW_VER_PATCH_OFFS (4)
4848

49+
#define NINA_ESP_REASON_AUTH_EXPIRE (2)
50+
#define NINA_ESP_REASON_ASSOC_EXPIRE (4)
51+
#define NINA_ESP_REASON_NOT_AUTHED (6)
52+
#define NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT (15)
53+
#define NINA_ESP_REASON_BEACON_TIMEOUT (200)
54+
#define NINA_ESP_REASON_NO_AP_FOUND (201)
55+
#define NINA_ESP_REASON_AUTH_FAIL (202)
56+
#define NINA_ESP_REASON_ASSOC_FAIL (203)
57+
#define NINA_ESP_REASON_HANDSHAKE_TIMEOUT (204)
58+
#define NINA_ESP_REASON_CONNECTION_FAIL (205)
59+
4960
typedef enum {
5061
NINA_SEC_INVALID = 0,
5162
NINA_SEC_OPEN,
@@ -59,6 +70,19 @@ typedef enum {
5970
NINA_SOCKET_TYPE_RAW = 3,
6071
} nina_socket_type_t;
6172

73+
typedef enum {
74+
NINA_STATUS_IDLE = 0,
75+
NINA_STATUS_NO_SSID_AVAIL = 1,
76+
NINA_STATUS_SCAN_COMPLETED = 2,
77+
NINA_STATUS_CONNECTED = 3,
78+
NINA_STATUS_CONNECT_FAILED = 4,
79+
NINA_STATUS_CONNECTION_LOST = 5,
80+
NINA_STATUS_DISCONNECTED = 6,
81+
NINA_STATUS_AP_LISTENING = 7,
82+
NINA_STATUS_AP_CONNECTED = 8,
83+
NINA_STATUS_AP_FAILED = 9
84+
} nina_status_t;
85+
6286
typedef struct {
6387
uint8_t ip_addr[NINA_IPV4_ADDR_LEN];
6488
uint8_t subnet_addr[NINA_IPV4_ADDR_LEN];
@@ -85,6 +109,8 @@ typedef int (*nina_scan_callback_t)(nina_scan_result_t *, void *);
85109

86110
int nina_init(void);
87111
int nina_deinit(void);
112+
int nina_connection_status(void);
113+
int nina_connection_reason(void);
88114
int nina_connect(const char *ssid, uint8_t security, const char *key, uint16_t channel);
89115
int nina_start_ap(const char *ssid, uint8_t security, const char *key, uint16_t channel);
90116
int nina_disconnect(void);

extmod/network_ninaw10.c

+45
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,9 @@ typedef struct _nina_obj_t {
5151
mp_obj_base_t base;
5252
bool active;
5353
uint32_t itf;
54+
mp_uint_t security;
55+
char ssid[NINA_MAX_SSID_LEN + 1];
56+
char key[NINA_MAX_WPA_LEN + 1];
5457
} nina_obj_t;
5558

5659
// For auto-binding UDP sockets
@@ -78,6 +81,7 @@ const mod_network_nic_type_t mod_network_nic_type_nina;
7881
static nina_obj_t network_nina_wl_sta = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_STA_IF};
7982
static nina_obj_t network_nina_wl_ap = {{(mp_obj_type_t *)&mod_network_nic_type_nina}, false, MOD_NETWORK_AP_IF};
8083
static mp_sched_node_t mp_wifi_sockpoll_node;
84+
static mp_sched_node_t mp_wifi_connpoll_node;
8185

8286
STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
8387
(void)node;
@@ -99,6 +103,40 @@ STATIC void network_ninaw10_poll_sockets(mp_sched_node_t *node) {
99103
}
100104
}
101105

106+
STATIC void network_ninaw10_poll_connect(mp_sched_node_t *node) {
107+
nina_obj_t *self = &network_nina_wl_sta;
108+
109+
int status = nina_connection_status();
110+
if (status == NINA_STATUS_CONNECTED) {
111+
// Connected to AP, nothing else to do.
112+
return;
113+
}
114+
115+
if (status != NINA_STATUS_NO_SSID_AVAIL) {
116+
// If not connected, and no connection in progress, the connection attempt has failed.
117+
// Read the ESP failure reason, reconnect and reschedule the connection polling code.
118+
int reason = nina_connection_reason();
119+
if (reason == NINA_ESP_REASON_AUTH_EXPIRE ||
120+
reason == NINA_ESP_REASON_ASSOC_EXPIRE ||
121+
reason == NINA_ESP_REASON_NOT_AUTHED ||
122+
reason == NINA_ESP_REASON_4WAY_HANDSHAKE_TIMEOUT ||
123+
reason >= NINA_ESP_REASON_BEACON_TIMEOUT) {
124+
debug_printf(&mp_plat_print, "poll_connect() status: %d reason %d\n", status, reason);
125+
if (nina_connect(self->ssid, self->security, self->key, 0) != 0) {
126+
mp_raise_msg_varg(&mp_type_OSError,
127+
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"),
128+
self->ssid, self->security, self->key);
129+
}
130+
} else {
131+
// Will not attempt to reconnect if there's another error code set.
132+
return;
133+
}
134+
}
135+
136+
// Reschedule the connection polling code.
137+
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
138+
}
139+
102140
STATIC mp_obj_t network_ninaw10_timer_callback(mp_obj_t none_in) {
103141
if (MP_STATE_PORT(mp_wifi_sockpoll_list) != MP_OBJ_NULL && MP_STATE_PORT(mp_wifi_sockpoll_list)->len) {
104142
mp_sched_schedule_node(&mp_wifi_sockpoll_node, network_ninaw10_poll_sockets);
@@ -240,6 +278,12 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
240278
mp_raise_msg_varg(&mp_type_OSError,
241279
MP_ERROR_TEXT("could not connect to ssid=%s, sec=%d, key=%s\n"), ssid, security, key);
242280
}
281+
282+
// Save connection info to re-connect if needed.
283+
self->security = security;
284+
strncpy(self->key, key, NINA_MAX_WPA_LEN);
285+
strncpy(self->ssid, ssid, NINA_MAX_SSID_LEN);
286+
mp_sched_schedule_node(&mp_wifi_connpoll_node, network_ninaw10_poll_connect);
243287
} else {
244288
mp_uint_t channel = args[ARG_channel].u_int;
245289

@@ -252,6 +296,7 @@ STATIC mp_obj_t network_ninaw10_connect(mp_uint_t n_args, const mp_obj_t *pos_ar
252296
mp_raise_msg(&mp_type_OSError, MP_ERROR_TEXT("failed to start in AP mode"));
253297
}
254298
}
299+
255300
return mp_const_none;
256301
}
257302
STATIC MP_DEFINE_CONST_FUN_OBJ_KW(network_ninaw10_connect_obj, 1, network_ninaw10_connect);

0 commit comments

Comments
 (0)