Skip to content

Commit f790fdd

Browse files
author
Cruz Monrreal
authored
Merge pull request #9421 from VeijoPesonen/feature-esp8266_nonblocking_connect
ESP8266: implements possibility to decide between non-blocking/blocking connect.
2 parents 0c6f0e4 + c4d96e6 commit f790fdd

File tree

2 files changed

+122
-6
lines changed

2 files changed

+122
-6
lines changed

components/wifi/esp8266-driver/ESP8266Interface.cpp

Lines changed: 103 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,14 @@ ESP8266Interface::ESP8266Interface()
5555
: _esp(MBED_CONF_ESP8266_TX, MBED_CONF_ESP8266_RX, MBED_CONF_ESP8266_DEBUG, MBED_CONF_ESP8266_RTS, MBED_CONF_ESP8266_CTS),
5656
_rst_pin(MBED_CONF_ESP8266_RST), // Notice that Pin7 CH_EN cannot be left floating if used as reset
5757
_ap_sec(NSAPI_SECURITY_UNKNOWN),
58+
_if_blocking(true),
59+
_if_connected(_cmutex),
5860
_initialized(false),
5961
_conn_stat(NSAPI_STATUS_DISCONNECTED),
6062
_conn_stat_cb(NULL),
6163
_global_event_queue(NULL),
62-
_oob_event_id(0)
64+
_oob_event_id(0),
65+
_connect_event_id(0)
6366
{
6467
memset(_cbs, 0, sizeof(_cbs));
6568
memset(ap_ssid, 0, sizeof(ap_ssid));
@@ -83,11 +86,14 @@ ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName r
8386
: _esp(tx, rx, debug, rts, cts),
8487
_rst_pin(rst),
8588
_ap_sec(NSAPI_SECURITY_UNKNOWN),
89+
_if_blocking(true),
90+
_if_connected(_cmutex),
8691
_initialized(false),
8792
_conn_stat(NSAPI_STATUS_DISCONNECTED),
8893
_conn_stat_cb(NULL),
8994
_global_event_queue(NULL),
90-
_oob_event_id(0)
95+
_oob_event_id(0),
96+
_connect_event_id(0)
9197
{
9298
memset(_cbs, 0, sizeof(_cbs));
9399
memset(ap_ssid, 0, sizeof(ap_ssid));
@@ -111,6 +117,12 @@ ESP8266Interface::~ESP8266Interface()
111117
_global_event_queue->cancel(_oob_event_id);
112118
}
113119

120+
_cmutex.lock();
121+
if (_connect_event_id) {
122+
_global_event_queue->cancel(_connect_event_id);
123+
}
124+
_cmutex.unlock();
125+
114126
// Power down the modem
115127
_rst_pin.rst_assert();
116128
}
@@ -167,9 +179,36 @@ void ESP8266Interface::_oob2global_event_queue()
167179
}
168180
}
169181

182+
void ESP8266Interface::_connect_async()
183+
{
184+
_cmutex.lock();
185+
if (!_connect_event_id) {
186+
tr_debug("_connect_async(): cancelled");
187+
_cmutex.unlock();
188+
return;
189+
}
190+
191+
if (_esp.connect(ap_ssid, ap_pass) != NSAPI_ERROR_OK) {
192+
// Postpone to give other stuff time to run
193+
_connect_event_id = _global_event_queue->call_in(ESP8266_CONNECT_TIMEOUT, callback(this, &ESP8266Interface::_connect_async));
194+
195+
if (!_connect_event_id) {
196+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
197+
"_connect_async(): unable to add event to queue");
198+
}
199+
} else {
200+
_connect_event_id = 0;
201+
_if_connected.notify_all();
202+
}
203+
_cmutex.unlock();
204+
}
205+
170206
int ESP8266Interface::connect()
171207
{
172-
nsapi_error_t status;
208+
nsapi_error_t status = _conn_status_to_error();
209+
if (status != NSAPI_ERROR_NO_CONNECTION) {
210+
return status;
211+
}
173212

174213
if (strlen(ap_ssid) == 0) {
175214
return NSAPI_ERROR_NO_SSID;
@@ -194,11 +233,32 @@ int ESP8266Interface::connect()
194233
return NSAPI_ERROR_DHCP_FAILURE;
195234
}
196235

197-
return _esp.connect(ap_ssid, ap_pass);
236+
_cmutex.lock();
237+
238+
MBED_ASSERT(!_connect_event_id);
239+
_connect_event_id = _global_event_queue->call(callback(this, &ESP8266Interface::_connect_async));
240+
241+
if (!_connect_event_id) {
242+
MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \
243+
"connect(): unable to add event to queue");
244+
}
245+
246+
while (_if_blocking && (_conn_status_to_error() != NSAPI_ERROR_IS_CONNECTED)) {
247+
_if_connected.wait();
248+
}
249+
250+
_cmutex.unlock();
251+
252+
return NSAPI_ERROR_OK;
198253
}
199254

200255
int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security)
201256
{
257+
nsapi_error_t status = _conn_status_to_error();
258+
if (status != NSAPI_ERROR_NO_CONNECTION) {
259+
return status;
260+
}
261+
202262
_ap_sec = security;
203263

204264
if (!ssid) {
@@ -244,10 +304,16 @@ int ESP8266Interface::set_channel(uint8_t channel)
244304

245305
int ESP8266Interface::disconnect()
246306
{
307+
_cmutex.lock();
308+
if (_connect_event_id) {
309+
_global_event_queue->cancel(_connect_event_id);
310+
_connect_event_id = 0; // cancel asynchronous connection attempt if one is ongoing
311+
}
312+
_cmutex.unlock();
247313
_initialized = false;
248314

249-
if (_conn_stat == NSAPI_STATUS_DISCONNECTED || !get_ip_address())
250-
{
315+
nsapi_error_t status = _conn_status_to_error();
316+
if (status == NSAPI_ERROR_NO_CONNECTION || !get_ip_address()) {
251317
return NSAPI_ERROR_NO_CONNECTION;
252318
}
253319

@@ -716,4 +782,35 @@ void ESP8266Interface::proc_oob_evnt()
716782
_esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
717783
}
718784

785+
nsapi_error_t ESP8266Interface::_conn_status_to_error()
786+
{
787+
nsapi_error_t ret;
788+
789+
_esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
790+
791+
switch (_conn_stat) {
792+
case NSAPI_STATUS_DISCONNECTED:
793+
ret = NSAPI_ERROR_NO_CONNECTION;
794+
break;
795+
case NSAPI_STATUS_CONNECTING:
796+
ret = NSAPI_ERROR_ALREADY;
797+
break;
798+
case NSAPI_STATUS_GLOBAL_UP:
799+
ret = NSAPI_ERROR_IS_CONNECTED;
800+
break;
801+
default:
802+
ret = NSAPI_ERROR_DEVICE_ERROR;
803+
}
804+
805+
return ret;
806+
}
807+
808+
nsapi_error_t ESP8266Interface::set_blocking(bool blocking)
809+
{
810+
_if_blocking = blocking;
811+
812+
return NSAPI_ERROR_OK;
813+
}
814+
815+
719816
#endif

components/wifi/esp8266-driver/ESP8266Interface.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
#include "features/netsocket/WiFiAccessPoint.h"
3030
#include "features/netsocket/WiFiInterface.h"
3131
#include "platform/Callback.h"
32+
#include "rtos/ConditionVariable.h"
33+
#include "rtos/Mutex.h"
3234

3335
#define ESP8266_SOCKET_COUNT 5
3436

@@ -316,6 +318,13 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
316318
return this;
317319
}
318320

321+
/** Set blocking status of connect() which by default should be blocking.
322+
*
323+
* @param blocking Use true to make connect() blocking.
324+
* @return NSAPI_ERROR_OK on success, negative error code on failure.
325+
*/
326+
virtual nsapi_error_t set_blocking(bool blocking);
327+
319328
private:
320329
// AT layer
321330
ESP8266 _esp;
@@ -341,6 +350,12 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
341350
char ap_pass[ESP8266_PASSPHRASE_MAX_LENGTH + 1]; /* The longest possible passphrase; +1 for the \0 */
342351
nsapi_security_t _ap_sec;
343352

353+
bool _if_blocking; // NetworkInterface, blocking or not
354+
rtos::ConditionVariable _if_connected;
355+
356+
// connect status reporting
357+
nsapi_error_t _conn_status_to_error();
358+
344359
// Drivers's socket info
345360
struct _sock_info {
346361
bool open;
@@ -369,8 +384,12 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
369384
// Use global EventQueue
370385
events::EventQueue *_global_event_queue;
371386
int _oob_event_id;
387+
int _connect_event_id;
372388
void proc_oob_evnt();
373389
void _oob2global_event_queue();
390+
void _connect_async();
391+
rtos::Mutex _cmutex; // Protect asynchronous connection logic
392+
374393
};
375394
#endif
376395
#endif

0 commit comments

Comments
 (0)