ESP8266: handles reset ready as OOB

Makes possible to recover from spurious resets addiotionally to planned
ones.
pull/9473/head
Veijo Pesonen 2019-01-23 15:11:14 +02:00
parent f2abdcbcc6
commit 876a397101
3 changed files with 59 additions and 8 deletions

View File

@ -25,6 +25,7 @@
#include "PinNames.h" #include "PinNames.h"
#include "platform/Callback.h" #include "platform/Callback.h"
#include "platform/mbed_error.h" #include "platform/mbed_error.h"
#include "rtos/Kernel.h"
#define TRACE_GROUP "ESPA" // ESP8266 AT layer #define TRACE_GROUP "ESPA" // ESP8266 AT layer
@ -51,6 +52,8 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
_sock_already(false), _sock_already(false),
_closed(false), _closed(false),
_busy(false), _busy(false),
_reset_check(_rmutex),
_reset_done(false),
_conn_status(NSAPI_STATUS_DISCONNECTED) _conn_status(NSAPI_STATUS_DISCONNECTED)
{ {
_serial.set_baud(ESP8266_DEFAULT_BAUD_RATE); _serial.set_baud(ESP8266_DEFAULT_BAUD_RATE);
@ -71,6 +74,7 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts)
_parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_err)); _parser.oob("UNLINK", callback(this, &ESP8266::_oob_socket_close_err));
_parser.oob("ALREADY CONNECTED", callback(this, &ESP8266::_oob_conn_already)); _parser.oob("ALREADY CONNECTED", callback(this, &ESP8266::_oob_conn_already));
_parser.oob("ERROR", callback(this, &ESP8266::_oob_err)); _parser.oob("ERROR", callback(this, &ESP8266::_oob_err));
_parser.oob("ready", callback(this, &ESP8266::_oob_reset));
// Don't expect to find anything about the watchdog reset in official documentation // Don't expect to find anything about the watchdog reset in official documentation
//https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/ //https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/
_parser.oob("wdt reset", callback(this, &ESP8266::_oob_watchdog_reset)); _parser.oob("wdt reset", callback(this, &ESP8266::_oob_watchdog_reset));
@ -234,20 +238,31 @@ bool ESP8266::startup(int mode)
bool ESP8266::reset(void) bool ESP8266::reset(void)
{ {
static const int ESP8266_BOOTTIME = 10000; // [ms]
bool done = false; bool done = false;
_smutex.lock(); _smutex.lock();
set_timeout(ESP8266_CONNECT_TIMEOUT);
for (int i = 0; i < 2; i++) { unsigned long int start_time = rtos::Kernel::get_ms_count();
if (_parser.send("AT+RST") _reset_done = false;
&& _parser.recv("OK\n") set_timeout(ESP8266_RECV_TIMEOUT);
&& _parser.recv("ready")) { if (!_parser.send("AT+RST") || !_parser.recv("OK\n")) {
done = true; tr_debug("reset(): AT+RST failed or no response");
break; goto EXIT;
}
} }
_rmutex.lock();
while ((rtos::Kernel::get_ms_count() - start_time < ESP8266_BOOTTIME) && !_reset_done) {
_process_oob(ESP8266_RECV_TIMEOUT, true); // UART mutex claimed -> need to check for OOBs ourselves
_reset_check.wait_for(100); // Arbitrary relatively short delay
}
done = _reset_done;
_rmutex.unlock();
tr_debug("reset(): done: %s", done ? "OK" : "FAIL");
EXIT:
_clear_socket_packets(ESP8266_ALL_SOCKET_IDS); _clear_socket_packets(ESP8266_ALL_SOCKET_IDS);
set_timeout(); set_timeout();
_smutex.unlock(); _smutex.unlock();
@ -963,6 +978,25 @@ void ESP8266::_oob_watchdog_reset()
"_oob_watchdog_reset() modem watchdog reset triggered\n"); "_oob_watchdog_reset() modem watchdog reset triggered\n");
} }
void ESP8266::_oob_reset()
{
_rmutex.lock();
_reset_done = true;
_reset_check.notify_all();
_rmutex.unlock();
for (int i = 0; i < SOCKET_COUNT; i++) {
_sock_i[i].open = false;
}
// Makes possible to reinitialize
_conn_status = NSAPI_STATUS_ERROR_UNSUPPORTED;
_conn_stat_cb();
tr_debug("_oob_reset(): reset detected");
}
void ESP8266::_oob_busy() void ESP8266::_oob_busy()
{ {
char status[5]; char status[5];

View File

@ -27,6 +27,7 @@
#include "platform/ATCmdParser.h" #include "platform/ATCmdParser.h"
#include "platform/Callback.h" #include "platform/Callback.h"
#include "platform/mbed_error.h" #include "platform/mbed_error.h"
#include "rtos/ConditionVariable.h"
#include "rtos/Mutex.h" #include "rtos/Mutex.h"
// Various timeouts for different ESP8266 operations // Various timeouts for different ESP8266 operations
@ -396,6 +397,7 @@ private:
PinName _serial_rts; PinName _serial_rts;
PinName _serial_cts; PinName _serial_cts;
rtos::Mutex _smutex; // Protect serial port access rtos::Mutex _smutex; // Protect serial port access
rtos::Mutex _rmutex; // Reset protection
// AT Command Parser // AT Command Parser
mbed::ATCmdParser _parser; mbed::ATCmdParser _parser;
@ -435,6 +437,7 @@ private:
void _oob_watchdog_reset(); void _oob_watchdog_reset();
void _oob_busy(); void _oob_busy();
void _oob_tcp_data_hdlr(); void _oob_tcp_data_hdlr();
void _oob_reset();
// OOB state variables // OOB state variables
int _connect_error; int _connect_error;
@ -444,6 +447,8 @@ private:
bool _closed; bool _closed;
bool _error; bool _error;
bool _busy; bool _busy;
rtos::ConditionVariable _reset_check;
bool _reset_done;
// Modem's address info // Modem's address info
char _ip_buffer[16]; char _ip_buffer[16];

View File

@ -577,6 +577,10 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
return NSAPI_ERROR_NO_SOCKET; return NSAPI_ERROR_NO_SOCKET;
} }
if (!_sock_i[socket->id].open) {
return NSAPI_ERROR_CONNECTION_LOST;
}
if (!size) { if (!size) {
// Firmware limitation // Firmware limitation
return socket->proto == NSAPI_TCP ? 0 : NSAPI_ERROR_UNSUPPORTED; return socket->proto == NSAPI_TCP ? 0 : NSAPI_ERROR_UNSUPPORTED;
@ -604,6 +608,10 @@ int ESP8266Interface::socket_recv(void *handle, void *data, unsigned size)
return NSAPI_ERROR_NO_SOCKET; return NSAPI_ERROR_NO_SOCKET;
} }
if (!_sock_i[socket->id].open) {
return NSAPI_ERROR_CONNECTION_LOST;
}
int32_t recv; int32_t recv;
if (socket->proto == NSAPI_TCP) { if (socket->proto == NSAPI_TCP) {
recv = _esp.recv_tcp(socket->id, data, size); recv = _esp.recv_tcp(socket->id, data, size);
@ -791,6 +799,10 @@ void ESP8266Interface::update_conn_state_cb()
default: default:
_initialized = false; _initialized = false;
_conn_stat = NSAPI_STATUS_DISCONNECTED; _conn_stat = NSAPI_STATUS_DISCONNECTED;
for (int i = 0; i < ESP8266_SOCKET_COUNT; i++) {
_sock_i[i].open = false;
_sock_i[i].sport = 0;
}
} }
// Inform upper layers // Inform upper layers