Skip to content

Commit 7dbe541

Browse files
author
Cruz Monrreal
authored
Merge pull request #9473 from VeijoPesonen/feature-esp8266_reset_handling
ESP8266: treats reset-ready-message as OOB
2 parents 7f24897 + cbbe2ff commit 7dbe541

File tree

4 files changed

+98
-26
lines changed

4 files changed

+98
-26
lines changed

components/wifi/esp8266-driver/ESP8266/ESP8266.cpp

Lines changed: 57 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "PinNames.h"
2626
#include "platform/Callback.h"
2727
#include "platform/mbed_error.h"
28+
#include "rtos/Kernel.h"
2829

2930
#define TRACE_GROUP "ESPA" // ESP8266 AT layer
3031

@@ -51,6 +52,8 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
5152
_sock_already(false),
5253
_closed(false),
5354
_busy(false),
55+
_reset_check(_rmutex),
56+
_reset_done(false),
5457
_conn_status(NSAPI_STATUS_DISCONNECTED)
5558
{
5659
_serial.set_baud(ESP8266_DEFAULT_BAUD_RATE);
@@ -71,6 +74,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
7174
_parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_err));
7275
_parser.oob("ALREADY CONNECTED", callback(this, &ESP8266::_oob_conn_already));
7376
_parser.oob("ERROR", callback(this, &ESP8266::_oob_err));
77+
_parser.oob("ready", callback(this, &ESP8266::_oob_ready));
7478
// Don't expect to find anything about the watchdog reset in official documentation
7579
//https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/
7680
_parser.oob("wdt reset", callback(this, &ESP8266::_oob_watchdog_reset));
@@ -183,14 +187,17 @@ bool ESP8266::start_uart_hw_flow_ctrl(void)
183187
bool done = true;
184188

185189
#if DEVICE_SERIAL_FC
190+
_smutex.lock();
186191
if (_serial_rts != NC && _serial_cts != NC) {
187-
// Start board's flow control
188-
_serial.set_flow_control(SerialBase::RTSCTS, _serial_rts, _serial_cts);
189-
190192
// Start ESP8266's flow control
191193
done = _parser.send("AT+UART_CUR=%u,8,1,0,3", ESP8266_DEFAULT_BAUD_RATE)
192194
&& _parser.recv("OK\n");
193195

196+
if (done) {
197+
// Start board's flow control
198+
_serial.set_flow_control(SerialBase::RTSCTS, _serial_rts, _serial_cts);
199+
}
200+
194201
} else if (_serial_rts != NC) {
195202
_serial.set_flow_control(SerialBase::RTS, _serial_rts, NC);
196203

@@ -203,7 +210,14 @@ bool ESP8266::start_uart_hw_flow_ctrl(void)
203210
done = _parser.send("AT+UART_CUR=%u,8,1,0,1", ESP8266_DEFAULT_BAUD_RATE)
204211
&& _parser.recv("OK\n");
205212

206-
_serial.set_flow_control(SerialBase::CTS, NC, _serial_cts);
213+
if (done) {
214+
_serial.set_flow_control(SerialBase::CTS, NC, _serial_cts);
215+
}
216+
}
217+
_smutex.unlock();
218+
219+
if (!done) {
220+
tr_debug("Enable UART HW flow control: FAIL");
207221
}
208222
#else
209223
if (_serial_rts != NC || _serial_cts != NC) {
@@ -234,20 +248,35 @@ bool ESP8266::startup(int mode)
234248

235249
bool ESP8266::reset(void)
236250
{
251+
static const int ESP8266_BOOTTIME = 10000; // [ms]
237252
bool done = false;
238253

239254
_smutex.lock();
240-
set_timeout(ESP8266_CONNECT_TIMEOUT);
241255

256+
unsigned long int start_time = rtos::Kernel::get_ms_count();
257+
_reset_done = false;
258+
set_timeout(ESP8266_RECV_TIMEOUT);
242259
for (int i = 0; i < 2; i++) {
243-
if (_parser.send("AT+RST")
244-
&& _parser.recv("OK\n")
245-
&& _parser.recv("ready")) {
246-
done = true;
260+
if (!_parser.send("AT+RST") || !_parser.recv("OK\n")) {
261+
tr_debug("reset(): AT+RST failed or no response");
262+
continue;
263+
}
264+
265+
_rmutex.lock();
266+
while ((rtos::Kernel::get_ms_count() - start_time < ESP8266_BOOTTIME) && !_reset_done) {
267+
_process_oob(ESP8266_RECV_TIMEOUT, true); // UART mutex claimed -> need to check for OOBs ourselves
268+
_reset_check.wait_for(100); // Arbitrary relatively short delay
269+
}
270+
271+
done = _reset_done;
272+
_rmutex.unlock();
273+
if (done) {
247274
break;
248275
}
249276
}
250277

278+
tr_debug("reset(): done: %s", done ? "OK" : "FAIL");
279+
251280
_clear_socket_packets(ESP8266_ALL_SOCKET_IDS);
252281
set_timeout();
253282
_smutex.unlock();
@@ -963,6 +992,25 @@ void ESP8266::_oob_watchdog_reset()
963992
"_oob_watchdog_reset() modem watchdog reset triggered\n");
964993
}
965994

995+
void ESP8266::_oob_ready()
996+
{
997+
998+
_rmutex.lock();
999+
_reset_done = true;
1000+
_reset_check.notify_all();
1001+
_rmutex.unlock();
1002+
1003+
for (int i = 0; i < SOCKET_COUNT; i++) {
1004+
_sock_i[i].open = false;
1005+
}
1006+
1007+
// Makes possible to reinitialize
1008+
_conn_status = NSAPI_STATUS_ERROR_UNSUPPORTED;
1009+
_conn_stat_cb();
1010+
1011+
tr_debug("_oob_reset(): reset detected");
1012+
}
1013+
9661014
void ESP8266::_oob_busy()
9671015
{
9681016
char status[5];

components/wifi/esp8266-driver/ESP8266/ESP8266.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "platform/ATCmdParser.h"
2828
#include "platform/Callback.h"
2929
#include "platform/mbed_error.h"
30+
#include "rtos/ConditionVariable.h"
3031
#include "rtos/Mutex.h"
3132

3233
// Various timeouts for different ESP8266 operations
@@ -396,6 +397,7 @@ class ESP8266 {
396397
PinName _serial_rts;
397398
PinName _serial_cts;
398399
rtos::Mutex _smutex; // Protect serial port access
400+
rtos::Mutex _rmutex; // Reset protection
399401

400402
// AT Command Parser
401403
mbed::ATCmdParser _parser;
@@ -435,6 +437,7 @@ class ESP8266 {
435437
void _oob_watchdog_reset();
436438
void _oob_busy();
437439
void _oob_tcp_data_hdlr();
440+
void _oob_ready();
438441

439442
// OOB state variables
440443
int _connect_error;
@@ -444,6 +447,8 @@ class ESP8266 {
444447
bool _closed;
445448
bool _error;
446449
bool _busy;
450+
rtos::ConditionVariable _reset_check;
451+
bool _reset_done;
447452

448453
// Modem's address info
449454
char _ip_buffer[16];

components/wifi/esp8266-driver/ESP8266Interface.cpp

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ ESP8266Interface::ESP8266Interface()
7171

7272
_esp.sigio(this, &ESP8266Interface::event);
7373
_esp.set_timeout();
74-
_esp.attach(this, &ESP8266Interface::update_conn_state_cb);
74+
_esp.attach(this, &ESP8266Interface::refresh_conn_state_cb);
7575

7676
for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
7777
_sock_i[i].open = false;
@@ -102,7 +102,7 @@ ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName r
102102

103103
_esp.sigio(this, &ESP8266Interface::event);
104104
_esp.set_timeout();
105-
_esp.attach(this, &ESP8266Interface::update_conn_state_cb);
105+
_esp.attach(this, &ESP8266Interface::refresh_conn_state_cb);
106106

107107
for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
108108
_sock_i[i].open = false;
@@ -404,12 +404,7 @@ bool ESP8266Interface::_get_firmware_ok()
404404
nsapi_error_t ESP8266Interface::_init(void)
405405
{
406406
if (!_initialized) {
407-
_hw_reset();
408-
409-
if (!_esp.at_available()) {
410-
return NSAPI_ERROR_DEVICE_ERROR;
411-
}
412-
if (!_esp.reset()) {
407+
if (_reset() != NSAPI_ERROR_OK) {
413408
return NSAPI_ERROR_DEVICE_ERROR;
414409
}
415410
if (!_esp.echo_off()) {
@@ -436,7 +431,7 @@ nsapi_error_t ESP8266Interface::_init(void)
436431
return NSAPI_ERROR_OK;
437432
}
438433

439-
void ESP8266Interface::_hw_reset()
434+
nsapi_error_t ESP8266Interface::_reset()
440435
{
441436
if (_rst_pin.is_connected()) {
442437
_rst_pin.rst_assert();
@@ -445,7 +440,17 @@ void ESP8266Interface::_hw_reset()
445440
wait_ms(2); // Documentation says 200 us should have been enough, but experimentation shows that 1ms was not enough
446441
_esp.flush();
447442
_rst_pin.rst_deassert();
443+
} else {
444+
_esp.flush();
445+
if (!_esp.at_available()) {
446+
return NSAPI_ERROR_DEVICE_ERROR;
447+
}
448+
if (!_esp.reset()) {
449+
return NSAPI_ERROR_DEVICE_ERROR;
450+
}
448451
}
452+
453+
return _esp.at_available() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR;
449454
}
450455

451456
struct esp8266_socket {
@@ -577,6 +582,10 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
577582
return NSAPI_ERROR_NO_SOCKET;
578583
}
579584

585+
if (!_sock_i[socket->id].open) {
586+
return NSAPI_ERROR_CONNECTION_LOST;
587+
}
588+
580589
if (!size) {
581590
// Firmware limitation
582591
return socket->proto == NSAPI_TCP ? 0 : NSAPI_ERROR_UNSUPPORTED;
@@ -604,6 +613,10 @@ int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
604613
return NSAPI_ERROR_NO_SOCKET;
605614
}
606615

616+
if (!_sock_i[socket->id].open) {
617+
return NSAPI_ERROR_CONNECTION_LOST;
618+
}
619+
607620
int32_t recv;
608621
if (socket->proto == NSAPI_TCP) {
609622
recv = _esp.recv_tcp(socket->id, data, size);
@@ -768,15 +781,11 @@ WiFiInterface *WiFiInterface::get_default_instance()
768781

769782
#endif
770783

771-
void ESP8266Interface::update_conn_state_cb()
784+
void ESP8266Interface::refresh_conn_state_cb()
772785
{
773786
nsapi_connection_status_t prev_stat = _conn_stat;
774787
_conn_stat = _esp.connection_status();
775788

776-
if (prev_stat == _conn_stat) {
777-
return;
778-
}
779-
780789
switch (_conn_stat) {
781790
// Doesn't require changes
782791
case NSAPI_STATUS_CONNECTING:
@@ -791,8 +800,18 @@ void ESP8266Interface::update_conn_state_cb()
791800
default:
792801
_initialized = false;
793802
_conn_stat = NSAPI_STATUS_DISCONNECTED;
803+
for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
804+
_sock_i[i].open = false;
805+
_sock_i[i].sport = 0;
806+
}
794807
}
795808

809+
if (prev_stat == _conn_stat) {
810+
return;
811+
}
812+
813+
tr_debug("refresh_conn_state_cb(): changed to %d", _conn_stat);
814+
796815
// Inform upper layers
797816
if (_conn_stat_cb) {
798817
_conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat);

components/wifi/esp8266-driver/ESP8266Interface.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
328328
private:
329329
// AT layer
330330
ESP8266 _esp;
331-
void update_conn_state_cb();
331+
void refresh_conn_state_cb();
332332

333333
// HW reset pin
334334
class ResetPin {
@@ -365,10 +365,10 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
365365

366366
// Driver's state
367367
int _initialized;
368+
nsapi_error_t _connect_retval;
368369
bool _get_firmware_ok();
369370
nsapi_error_t _init(void);
370-
void _hw_reset();
371-
nsapi_error_t _connect_retval;
371+
nsapi_error_t _reset();
372372

373373
//sigio
374374
struct {

0 commit comments

Comments
 (0)