Skip to content

[ESP8266] Adds support for controlling HW reset of the modem from the… #8959

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Dec 11, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 22 additions & 11 deletions components/wifi/esp8266-driver/ESP8266/ESP8266.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -224,22 +233,25 @@ bool ESP8266::startup(int mode)

bool ESP8266::reset(void)
{
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")) {
_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)
Expand Down Expand Up @@ -276,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) {
Expand All @@ -293,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)
Expand Down
108 changes: 74 additions & 34 deletions components/wifi/esp8266-driver/ESP8266Interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -40,16 +41,20 @@
#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;

#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),
_conn_stat(NSAPI_STATUS_DISCONNECTED),
_conn_stat_cb(NULL),
_global_event_queue(NULL),
Expand All @@ -67,15 +72,17 @@ ESP8266Interface::ESP8266Interface()
_sock_i[i].open = false;
_sock_i[i].sport = 0;
}

_oob2global_event_queue();
}
#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),
_conn_stat(NSAPI_STATUS_DISCONNECTED),
_conn_stat_cb(NULL),
_global_event_queue(NULL),
Expand All @@ -93,13 +100,44 @@ 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()
{
if (_oob_event_id) {
_global_event_queue->cancel(_oob_event_id);
}

// Power down the modem
_rst_pin.rst_assert();
}

ESP8266Interface::ResetPin::ResetPin(PinName rst_pin) : _rst_pin(mbed::DigitalOut(rst_pin, 1))
{
}

void ESP8266Interface::ResetPin::rst_assert()
{
if (_rst_pin.is_connected()) {
_rst_pin = 0;
tr_debug("HW reset asserted");
}
}

void ESP8266Interface::ResetPin::rst_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,
Expand Down Expand Up @@ -147,10 +185,6 @@ int ESP8266Interface::connect()
return status;
}

if (!_oob_event_id) {
_oob2global_event_queue();
}

if (get_ip_address()) {
return NSAPI_ERROR_IS_CONNECTED;
}
Expand All @@ -159,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)
Expand Down Expand Up @@ -224,6 +248,8 @@ int ESP8266Interface::set_channel(uint8_t channel)

int ESP8266Interface::disconnect()
{
_initialized = false;

if (_conn_stat == NSAPI_STATUS_DISCONNECTED)
{
return NSAPI_ERROR_NO_CONNECTION;
Expand All @@ -234,19 +260,23 @@ 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);
}
}
}

// Power down the modem
_rst_pin.rst_assert();

return ret;
}

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;
Expand All @@ -262,17 +292,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)
Expand Down Expand Up @@ -313,6 +343,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;
}
Expand Down Expand Up @@ -343,9 +375,18 @@ nsapi_error_t ESP8266Interface::_init(void)
return NSAPI_ERROR_OK;
}

void ESP8266Interface::_hw_reset()
{
_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.rst_deassert();
}

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;
}
Expand Down Expand Up @@ -646,25 +687,26 @@ 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:
case NSAPI_STATUS_GLOBAL_UP:
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;
}

Expand All @@ -676,8 +718,6 @@ void ESP8266Interface::update_conn_state_cb()

void ESP8266Interface::proc_oob_evnt()
{
if (_initialized) {
_esp.bg_process_oob(ESP8266_RECV_TIMEOUT, true);
}
}
#endif
17 changes: 15 additions & 2 deletions components/wifi/esp8266-driver/ESP8266Interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -59,7 +60,7 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
* @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
Expand Down Expand Up @@ -320,6 +321,18 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
ESP8266 _esp;
void update_conn_state_cb();

// HW reset pin
class ResetPin {
public:
ResetPin(PinName rst_pin);
void rst_assert();
void rst_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 */
Expand All @@ -339,7 +352,7 @@ class ESP8266Interface : public NetworkStack, public WiFiInterface {
int _initialized;
bool _get_firmware_ok();
nsapi_error_t _init(void);
int _started;
void _hw_reset();
nsapi_error_t _startup(const int8_t wifi_mode);

//sigio
Expand Down
Loading