mirror of https://github.com/ARMmbed/mbed-os.git
				
				
				
			ESP8266: handles reset ready as OOB
Makes possible to recover from spurious resets addiotionally to planned ones.pull/9473/head
							parent
							
								
									f2abdcbcc6
								
							
						
					
					
						commit
						876a397101
					
				| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
#include "PinNames.h"
 | 
			
		||||
#include "platform/Callback.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
#include "rtos/Kernel.h"
 | 
			
		||||
 | 
			
		||||
#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),
 | 
			
		||||
      _closed(false),
 | 
			
		||||
      _busy(false),
 | 
			
		||||
      _reset_check(_rmutex),
 | 
			
		||||
      _reset_done(false),
 | 
			
		||||
      _conn_status(NSAPI_STATUS_DISCONNECTED)
 | 
			
		||||
{
 | 
			
		||||
    _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("ALREADY CONNECTED", callback(this, &ESP8266::_oob_conn_already));
 | 
			
		||||
    _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
 | 
			
		||||
    //https://techtutorialsx.com/2017/01/21/esp8266-watchdog-functions/
 | 
			
		||||
    _parser.oob("wdt reset", callback(this, &ESP8266::_oob_watchdog_reset));
 | 
			
		||||
| 
						 | 
				
			
			@ -234,20 +238,31 @@ bool ESP8266::startup(int mode)
 | 
			
		|||
 | 
			
		||||
bool ESP8266::reset(void)
 | 
			
		||||
{
 | 
			
		||||
    static const int ESP8266_BOOTTIME = 10000; // [ms]
 | 
			
		||||
    bool done = false;
 | 
			
		||||
 | 
			
		||||
    _smutex.lock();
 | 
			
		||||
    set_timeout(ESP8266_CONNECT_TIMEOUT);
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < 2; i++) {
 | 
			
		||||
        if (_parser.send("AT+RST")
 | 
			
		||||
                && _parser.recv("OK\n")
 | 
			
		||||
                && _parser.recv("ready")) {
 | 
			
		||||
            done = true;
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    unsigned long int start_time = rtos::Kernel::get_ms_count();
 | 
			
		||||
    _reset_done = false;
 | 
			
		||||
    set_timeout(ESP8266_RECV_TIMEOUT);
 | 
			
		||||
    if (!_parser.send("AT+RST") || !_parser.recv("OK\n")) {
 | 
			
		||||
        tr_debug("reset(): AT+RST failed or no response");
 | 
			
		||||
        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);
 | 
			
		||||
    set_timeout();
 | 
			
		||||
    _smutex.unlock();
 | 
			
		||||
| 
						 | 
				
			
			@ -963,6 +978,25 @@ void ESP8266::_oob_watchdog_reset()
 | 
			
		|||
               "_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()
 | 
			
		||||
{
 | 
			
		||||
    char status[5];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,7 @@
 | 
			
		|||
#include "platform/ATCmdParser.h"
 | 
			
		||||
#include "platform/Callback.h"
 | 
			
		||||
#include "platform/mbed_error.h"
 | 
			
		||||
#include "rtos/ConditionVariable.h"
 | 
			
		||||
#include "rtos/Mutex.h"
 | 
			
		||||
 | 
			
		||||
// Various timeouts for different ESP8266 operations
 | 
			
		||||
| 
						 | 
				
			
			@ -396,6 +397,7 @@ private:
 | 
			
		|||
    PinName _serial_rts;
 | 
			
		||||
    PinName _serial_cts;
 | 
			
		||||
    rtos::Mutex _smutex; // Protect serial port access
 | 
			
		||||
    rtos::Mutex _rmutex; // Reset protection
 | 
			
		||||
 | 
			
		||||
    // AT Command Parser
 | 
			
		||||
    mbed::ATCmdParser _parser;
 | 
			
		||||
| 
						 | 
				
			
			@ -435,6 +437,7 @@ private:
 | 
			
		|||
    void _oob_watchdog_reset();
 | 
			
		||||
    void _oob_busy();
 | 
			
		||||
    void _oob_tcp_data_hdlr();
 | 
			
		||||
    void _oob_reset();
 | 
			
		||||
 | 
			
		||||
    // OOB state variables
 | 
			
		||||
    int _connect_error;
 | 
			
		||||
| 
						 | 
				
			
			@ -444,6 +447,8 @@ private:
 | 
			
		|||
    bool _closed;
 | 
			
		||||
    bool _error;
 | 
			
		||||
    bool _busy;
 | 
			
		||||
    rtos::ConditionVariable _reset_check;
 | 
			
		||||
    bool _reset_done;
 | 
			
		||||
 | 
			
		||||
    // Modem's address info
 | 
			
		||||
    char _ip_buffer[16];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -577,6 +577,10 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size)
 | 
			
		|||
        return NSAPI_ERROR_NO_SOCKET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_sock_i[socket->id].open) {
 | 
			
		||||
        return NSAPI_ERROR_CONNECTION_LOST;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!size) {
 | 
			
		||||
        // Firmware limitation
 | 
			
		||||
        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;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!_sock_i[socket->id].open) {
 | 
			
		||||
        return NSAPI_ERROR_CONNECTION_LOST;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    int32_t recv;
 | 
			
		||||
    if (socket->proto == NSAPI_TCP) {
 | 
			
		||||
        recv = _esp.recv_tcp(socket->id, data, size);
 | 
			
		||||
| 
						 | 
				
			
			@ -791,6 +799,10 @@ void ESP8266Interface::update_conn_state_cb()
 | 
			
		|||
        default:
 | 
			
		||||
            _initialized = false;
 | 
			
		||||
            _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
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue