Merge pull request #8959 from VeijoPesonen/feature-esp8266_reset_pin

[ESP8266] Adds support for controlling HW reset of the modem from the…
pull/9051/head
Martin Kojtal 2018-12-11 15:37:10 +01:00 committed by GitHub
commit 08d1127729
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 115 additions and 47 deletions

View File

@ -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;
@ -224,6 +233,8 @@ bool ESP8266::startup(int mode)
bool ESP8266::reset(void)
{
bool done = false;
_smutex.lock();
set_timeout(ESP8266_CONNECT_TIMEOUT);
@ -231,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)
@ -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) {
@ -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)

View File

@ -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,9 +52,9 @@ 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),
@ -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),
@ -93,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()
@ -100,6 +109,35 @@ 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,
@ -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;
}
@ -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)
@ -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;
@ -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;
@ -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)
@ -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;
}
@ -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;
}
@ -646,8 +687,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:
@ -655,16 +701,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;
}
@ -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

View File

@ -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 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 */
@ -339,7 +352,7 @@ private:
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

View File

@ -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