From 9857ee1c1735e5516502bf799b9b73a2215e1435 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 4 Dec 2018 11:11:05 +0200 Subject: [PATCH 1/5] [ESP8266] Adds support for controlling HW reset of the modem from the driver While connecting will run HW reset for the modem if reset wire is attached to a know pin. --- .../wifi/esp8266-driver/ESP8266/ESP8266.cpp | 13 ++++- .../wifi/esp8266-driver/ESP8266Interface.cpp | 48 ++++++++++++++++++- .../wifi/esp8266-driver/ESP8266Interface.h | 16 ++++++- components/wifi/esp8266-driver/mbed_lib.json | 4 ++ 4 files changed, 77 insertions(+), 4 deletions(-) diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp index 4efc314672..673cf1f888 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp @@ -91,9 +91,18 @@ ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts) bool ESP8266::at_available() { + bool ready = false; + _smutex.lock(); - bool ready = _parser.send("AT") - && _parser.recv("OK\n"); + // Might take a while to respond after HW reset + for(int i = 0; i < 5; i++) { + ready = _parser.send("AT") + && _parser.recv("OK\n"); + if (ready) { + break; + } + tr_debug("waiting AT response"); + } _smutex.unlock(); return ready; diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index 10e8f7c4a2..dfa7bfdf26 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -27,6 +27,7 @@ #include "mbed_trace.h" #include "platform/Callback.h" #include "platform/mbed_debug.h" +#include "platform/mbed_wait_api.h" #ifndef MBED_CONF_ESP8266_DEBUG #define MBED_CONF_ESP8266_DEBUG false @@ -40,6 +41,10 @@ #define MBED_CONF_ESP8266_CTS NC #endif +#ifndef MBED_CONF_ESP8266_RST +#define MBED_CONF_ESP8266_RST NC +#endif + #define TRACE_GROUP "ESPI" // ESP8266 Interface using namespace mbed; @@ -47,6 +52,7 @@ using namespace mbed; #if defined MBED_CONF_ESP8266_TX && defined MBED_CONF_ESP8266_RX ESP8266Interface::ESP8266Interface() : _esp(MBED_CONF_ESP8266_TX, MBED_CONF_ESP8266_RX, MBED_CONF_ESP8266_DEBUG, MBED_CONF_ESP8266_RTS, MBED_CONF_ESP8266_CTS), + _rst_pin(MBED_CONF_ESP8266_RST), // Notice that Pin7 CH_EN cannot be left floating if used as reset _ap_sec(NSAPI_SECURITY_UNKNOWN), _initialized(false), _started(false), @@ -71,8 +77,9 @@ ESP8266Interface::ESP8266Interface() #endif // ESP8266Interface implementation -ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName rts, PinName cts) +ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName rts, PinName cts, PinName rst) : _esp(tx, rx, debug, rts, cts), + _rst_pin(rst), _ap_sec(NSAPI_SECURITY_UNKNOWN), _initialized(false), _started(false), @@ -102,6 +109,35 @@ ESP8266Interface::~ESP8266Interface() } } +ESP8266Interface::ResetPin::ResetPin(PinName rst_pin) : _rst_pin(mbed::DigitalOut(rst_pin, 1)) +{ +} + +void ESP8266Interface::ResetPin::assert() +{ + if (_rst_pin.is_connected()) { + _rst_pin = 0; + // If you happen to use Pin7 CH_EN as reset pin, not needed otherwise + // https://www.espressif.com/sites/default/files/documentation/esp8266_hardware_design_guidelines_en.pdf + wait_us(200); + tr_debug("HW reset asserted"); + } +} + +void ESP8266Interface::ResetPin::deassert() +{ + if (_rst_pin.is_connected()) { + // Notice that Pin7 CH_EN cannot be left floating if used as reset + _rst_pin = 1; + tr_debug("HW reset deasserted"); + } +} + +bool ESP8266Interface::ResetPin::is_connected() +{ + return _rst_pin.is_connected(); +} + int ESP8266Interface::connect(const char *ssid, const char *pass, nsapi_security_t security, uint8_t channel) { @@ -224,6 +260,8 @@ int ESP8266Interface::set_channel(uint8_t channel) int ESP8266Interface::disconnect() { + _initialized = false; + if (_conn_stat == NSAPI_STATUS_DISCONNECTED) { return NSAPI_ERROR_NO_CONNECTION; @@ -313,6 +351,8 @@ bool ESP8266Interface::_get_firmware_ok() nsapi_error_t ESP8266Interface::_init(void) { if (!_initialized) { + _hw_reset(); + if (!_esp.at_available()) { return NSAPI_ERROR_DEVICE_ERROR; } @@ -343,6 +383,12 @@ nsapi_error_t ESP8266Interface::_init(void) return NSAPI_ERROR_OK; } +void ESP8266Interface::_hw_reset() +{ + _rst_pin.assert(); + _rst_pin.deassert(); +} + nsapi_error_t ESP8266Interface::_startup(const int8_t wifi_mode) { if (!_started) { diff --git a/components/wifi/esp8266-driver/ESP8266Interface.h b/components/wifi/esp8266-driver/ESP8266Interface.h index fadee0375b..a89e92a307 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.h +++ b/components/wifi/esp8266-driver/ESP8266Interface.h @@ -18,6 +18,7 @@ #define ESP8266_INTERFACE_H #if DEVICE_SERIAL && defined(MBED_CONF_EVENTS_PRESENT) && defined(MBED_CONF_NSAPI_PRESENT) && defined(MBED_CONF_RTOS_PRESENT) +#include "drivers/DigitalOut.h" #include "ESP8266/ESP8266.h" #include "events/EventQueue.h" #include "events/mbed_shared_queues.h" @@ -59,7 +60,7 @@ public: * @param rx RX pin * @param debug Enable debugging */ - ESP8266Interface(PinName tx, PinName rx, bool debug = false, PinName rts = NC, PinName cts = NC); + ESP8266Interface(PinName tx, PinName rx, bool debug = false, PinName rts = NC, PinName cts = NC, PinName rst = NC); /** * @brief ESP8266Interface default destructor @@ -320,6 +321,18 @@ private: ESP8266 _esp; void update_conn_state_cb(); + // HW reset pin + class ResetPin { + public: + ResetPin(PinName rst_pin); + void assert(); + void deassert(); + bool is_connected(); + private: + mbed::DigitalOut _rst_pin; + } _rst_pin; + + // Credentials static const int ESP8266_SSID_MAX_LENGTH = 32; /* 32 is what 802.11 defines as longest possible name */ char ap_ssid[ESP8266_SSID_MAX_LENGTH + 1]; /* The longest possible name; +1 for the \0 */ @@ -339,6 +352,7 @@ private: int _initialized; bool _get_firmware_ok(); nsapi_error_t _init(void); + void _hw_reset(); int _started; nsapi_error_t _startup(const int8_t wifi_mode); diff --git a/components/wifi/esp8266-driver/mbed_lib.json b/components/wifi/esp8266-driver/mbed_lib.json index 021d696e4a..28337d8077 100644 --- a/components/wifi/esp8266-driver/mbed_lib.json +++ b/components/wifi/esp8266-driver/mbed_lib.json @@ -17,6 +17,10 @@ "help": "CTS pin for serial connection, defaults to Not Connected", "value": null }, + "rst": { + "help": "RESET pin for the modem, defaults to Not Connected", + "value": null + }, "debug": { "help": "Enable debug logs. [true/false]", "value": false From 12fa3e59bbad64525abaa0e7cf3b6e0f169742c6 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 4 Dec 2018 17:05:51 +0200 Subject: [PATCH 2/5] Fixes AT command timeout values from reset&connect --- .../wifi/esp8266-driver/ESP8266/ESP8266.cpp | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp index 673cf1f888..71573abc31 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp @@ -233,6 +233,8 @@ bool ESP8266::startup(int mode) bool ESP8266::reset(void) { + bool done = false; + _smutex.lock(); set_timeout(ESP8266_CONNECT_TIMEOUT); @@ -240,15 +242,16 @@ bool ESP8266::reset(void) if (_parser.send("AT+RST") && _parser.recv("OK\n") && _parser.recv("ready")) { - _clear_socket_packets(ESP8266_ALL_SOCKET_IDS); - _smutex.unlock(); - return true; + done = true; + break; } } + + _clear_socket_packets(ESP8266_ALL_SOCKET_IDS); set_timeout(); _smutex.unlock(); - return false; + return done; } bool ESP8266::dhcp(bool enabled, int mode) @@ -285,14 +288,14 @@ bool ESP8266::cond_enable_tcp_passive_mode() nsapi_error_t ESP8266::connect(const char *ap, const char *passPhrase) { + nsapi_error_t ret = NSAPI_ERROR_OK; + _smutex.lock(); set_timeout(ESP8266_CONNECT_TIMEOUT); _parser.send("AT+CWJAP_CUR=\"%s\",\"%s\"", ap, passPhrase); if (!_parser.recv("OK\n")) { if (_fail) { - _smutex.unlock(); - nsapi_error_t ret; if (_connect_error == 1) { ret = NSAPI_ERROR_CONNECTION_TIMEOUT; } else if (_connect_error == 2) { @@ -302,16 +305,15 @@ nsapi_error_t ESP8266::connect(const char *ap, const char *passPhrase) } else { ret = NSAPI_ERROR_NO_CONNECTION; } - _fail = false; _connect_error = 0; - return ret; } } + set_timeout(); _smutex.unlock(); - return NSAPI_ERROR_OK; + return ret; } bool ESP8266::disconnect(void) From 8415e49835d36ee9a994e1b79c3f8f036490e040 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Tue, 4 Dec 2018 17:18:52 +0200 Subject: [PATCH 3/5] Fixes connect, and network-status logic --- .../wifi/esp8266-driver/ESP8266Interface.cpp | 54 ++++++++----------- .../wifi/esp8266-driver/ESP8266Interface.h | 1 - 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index dfa7bfdf26..76e9e859f4 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -55,7 +55,6 @@ ESP8266Interface::ESP8266Interface() _rst_pin(MBED_CONF_ESP8266_RST), // Notice that Pin7 CH_EN cannot be left floating if used as reset _ap_sec(NSAPI_SECURITY_UNKNOWN), _initialized(false), - _started(false), _conn_stat(NSAPI_STATUS_DISCONNECTED), _conn_stat_cb(NULL), _global_event_queue(NULL), @@ -73,6 +72,8 @@ ESP8266Interface::ESP8266Interface() _sock_i[i].open = false; _sock_i[i].sport = 0; } + + _oob2global_event_queue(); } #endif @@ -82,7 +83,6 @@ ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName r _rst_pin(rst), _ap_sec(NSAPI_SECURITY_UNKNOWN), _initialized(false), - _started(false), _conn_stat(NSAPI_STATUS_DISCONNECTED), _conn_stat_cb(NULL), _global_event_queue(NULL), @@ -100,6 +100,8 @@ ESP8266Interface::ESP8266Interface(PinName tx, PinName rx, bool debug, PinName r _sock_i[i].open = false; _sock_i[i].sport = 0; } + + _oob2global_event_queue(); } ESP8266Interface::~ESP8266Interface() @@ -183,10 +185,6 @@ int ESP8266Interface::connect() return status; } - if (!_oob_event_id) { - _oob2global_event_queue(); - } - if (get_ip_address()) { return NSAPI_ERROR_IS_CONNECTED; } @@ -195,22 +193,12 @@ int ESP8266Interface::connect() if (status != NSAPI_ERROR_OK) { return status; } - _started = true; if (!_esp.dhcp(true, 1)) { return NSAPI_ERROR_DHCP_FAILURE; } - int connect_error = _esp.connect(ap_ssid, ap_pass); - if (connect_error) { - return connect_error; - } - - if (!get_ip_address()) { - return NSAPI_ERROR_DHCP_FAILURE; - } - - return NSAPI_ERROR_OK; + return _esp.connect(ap_ssid, ap_pass); } int ESP8266Interface::set_credentials(const char *ssid, const char *pass, nsapi_security_t security) @@ -272,8 +260,13 @@ int ESP8266Interface::disconnect() if (ret == NSAPI_ERROR_OK) { // Try to lure the nw status update from ESP8266, might come later _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true); - // In case the status update arrives later - _conn_stat = NSAPI_STATUS_DISCONNECTED; + // In case the status update arrives later inform upper layers manually + if (_conn_stat != NSAPI_STATUS_DISCONNECTED) { + _conn_stat = NSAPI_STATUS_DISCONNECTED; + if (_conn_stat_cb) { + _conn_stat_cb(NSAPI_EVENT_CONNECTION_STATUS_CHANGE, _conn_stat); + } + } } return ret; @@ -281,10 +274,6 @@ int ESP8266Interface::disconnect() const char *ESP8266Interface::get_ip_address() { - if (!_started) { - return NULL; - } - const char *ip_buff = _esp.ip_addr(); if (!ip_buff || strcmp(ip_buff, "0.0.0.0") == 0) { return NULL; @@ -300,17 +289,17 @@ const char *ESP8266Interface::get_mac_address() const char *ESP8266Interface::get_gateway() { - return _started ? _esp.gateway() : NULL; + return _conn_stat != NSAPI_STATUS_DISCONNECTED ? _esp.gateway() : NULL; } const char *ESP8266Interface::get_netmask() { - return _started ? _esp.netmask() : NULL; + return _conn_stat != NSAPI_STATUS_DISCONNECTED ? _esp.netmask() : NULL; } int8_t ESP8266Interface::get_rssi() { - return _started ? _esp.rssi() : 0; + return _esp.rssi(); } int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count) @@ -391,7 +380,7 @@ void ESP8266Interface::_hw_reset() nsapi_error_t ESP8266Interface::_startup(const int8_t wifi_mode) { - if (!_started) { + if (_conn_stat == NSAPI_STATUS_DISCONNECTED) { if (!_esp.startup(wifi_mode)) { return NSAPI_ERROR_DEVICE_ERROR; } @@ -692,8 +681,13 @@ WiFiInterface *WiFiInterface::get_default_instance() void ESP8266Interface::update_conn_state_cb() { + nsapi_connection_status_t prev_stat = _conn_stat; _conn_stat = _esp.connection_status(); + if (prev_stat == _conn_stat) { + return; + } + switch (_conn_stat) { // Doesn't require changes case NSAPI_STATUS_CONNECTING: @@ -701,16 +695,12 @@ void ESP8266Interface::update_conn_state_cb() break; // Start from scratch if connection drops/is dropped case NSAPI_STATUS_DISCONNECTED: - _started = false; break; // Handled on AT layer case NSAPI_STATUS_LOCAL_UP: case NSAPI_STATUS_ERROR_UNSUPPORTED: default: - _started = false; _initialized = false; - _global_event_queue->cancel(_oob_event_id); - _oob_event_id = 0; _conn_stat = NSAPI_STATUS_DISCONNECTED; } @@ -722,8 +712,6 @@ void ESP8266Interface::update_conn_state_cb() void ESP8266Interface::proc_oob_evnt() { - if (_initialized) { _esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true); - } } #endif diff --git a/components/wifi/esp8266-driver/ESP8266Interface.h b/components/wifi/esp8266-driver/ESP8266Interface.h index a89e92a307..06d4e6685e 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.h +++ b/components/wifi/esp8266-driver/ESP8266Interface.h @@ -353,7 +353,6 @@ private: bool _get_firmware_ok(); nsapi_error_t _init(void); void _hw_reset(); - int _started; nsapi_error_t _startup(const int8_t wifi_mode); //sigio From 02aeab29d3ea88dac6ddcd277d46d1c4571bca65 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Fri, 7 Dec 2018 14:59:51 +0200 Subject: [PATCH 4/5] [ESP8266] powers down the modem on disconnect --- components/wifi/esp8266-driver/ESP8266Interface.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index 76e9e859f4..ff73589fef 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -109,6 +109,9 @@ ESP8266Interface::~ESP8266Interface() if (_oob_event_id) { _global_event_queue->cancel(_oob_event_id); } + + // Power down the modem + _rst_pin.assert(); } ESP8266Interface::ResetPin::ResetPin(PinName rst_pin) : _rst_pin(mbed::DigitalOut(rst_pin, 1)) @@ -119,9 +122,6 @@ void ESP8266Interface::ResetPin::assert() { if (_rst_pin.is_connected()) { _rst_pin = 0; - // If you happen to use Pin7 CH_EN as reset pin, not needed otherwise - // https://www.espressif.com/sites/default/files/documentation/esp8266_hardware_design_guidelines_en.pdf - wait_us(200); tr_debug("HW reset asserted"); } } @@ -269,6 +269,9 @@ int ESP8266Interface::disconnect() } } + // Power down the modem + _rst_pin.assert(); + return ret; } @@ -375,6 +378,9 @@ nsapi_error_t ESP8266Interface::_init(void) void ESP8266Interface::_hw_reset() { _rst_pin.assert(); + // If you happen to use Pin7 CH_EN as reset pin, not needed otherwise + // https://www.espressif.com/sites/default/files/documentation/esp8266_hardware_design_guidelines_en.pdf + wait_us(200); _rst_pin.deassert(); } From e4de165a325d0e4714667bca98892da687d2a3d8 Mon Sep 17 00:00:00 2001 From: Veijo Pesonen Date: Mon, 10 Dec 2018 15:05:34 +0200 Subject: [PATCH 5/5] [ESP8266] Fixes namespace collision --- components/wifi/esp8266-driver/ESP8266Interface.cpp | 12 ++++++------ components/wifi/esp8266-driver/ESP8266Interface.h | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index ff73589fef..4b71fc689a 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -111,14 +111,14 @@ ESP8266Interface::~ESP8266Interface() } // Power down the modem - _rst_pin.assert(); + _rst_pin.rst_assert(); } ESP8266Interface::ResetPin::ResetPin(PinName rst_pin) : _rst_pin(mbed::DigitalOut(rst_pin, 1)) { } -void ESP8266Interface::ResetPin::assert() +void ESP8266Interface::ResetPin::rst_assert() { if (_rst_pin.is_connected()) { _rst_pin = 0; @@ -126,7 +126,7 @@ void ESP8266Interface::ResetPin::assert() } } -void ESP8266Interface::ResetPin::deassert() +void ESP8266Interface::ResetPin::rst_deassert() { if (_rst_pin.is_connected()) { // Notice that Pin7 CH_EN cannot be left floating if used as reset @@ -270,7 +270,7 @@ int ESP8266Interface::disconnect() } // Power down the modem - _rst_pin.assert(); + _rst_pin.rst_assert(); return ret; } @@ -377,11 +377,11 @@ nsapi_error_t ESP8266Interface::_init(void) void ESP8266Interface::_hw_reset() { - _rst_pin.assert(); + _rst_pin.rst_assert(); // If you happen to use Pin7 CH_EN as reset pin, not needed otherwise // https://www.espressif.com/sites/default/files/documentation/esp8266_hardware_design_guidelines_en.pdf wait_us(200); - _rst_pin.deassert(); + _rst_pin.rst_deassert(); } nsapi_error_t ESP8266Interface::_startup(const int8_t wifi_mode) diff --git a/components/wifi/esp8266-driver/ESP8266Interface.h b/components/wifi/esp8266-driver/ESP8266Interface.h index 06d4e6685e..b50f9dbfd4 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.h +++ b/components/wifi/esp8266-driver/ESP8266Interface.h @@ -325,8 +325,8 @@ private: class ResetPin { public: ResetPin(PinName rst_pin); - void assert(); - void deassert(); + void rst_assert(); + void rst_deassert(); bool is_connected(); private: mbed::DigitalOut _rst_pin;