From d114f54dcefca93438033ae3f7e1b36eaf561138 Mon Sep 17 00:00:00 2001 From: Kevin Bracey Date: Thu, 13 Feb 2020 16:40:11 +0200 Subject: [PATCH] ESP8266: Convert to Chrono --- .../wifi/esp8266-driver/ESP8266/ESP8266.cpp | 32 ++++++++------- .../wifi/esp8266-driver/ESP8266/ESP8266.h | 37 +++++++++-------- .../wifi/esp8266-driver/ESP8266Interface.cpp | 40 ++++++++++++------- .../wifi/esp8266-driver/ESP8266Interface.h | 8 ++-- 4 files changed, 68 insertions(+), 49 deletions(-) diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp index d1dc3ee559..81f6c64cfc 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.cpp @@ -40,6 +40,8 @@ using namespace mbed; +using namespace std::chrono; +using std::milli; ESP8266::ESP8266(PinName tx, PinName rx, bool debug, PinName rts, PinName cts) : _sdk_v(-1, -1, -1), @@ -275,12 +277,12 @@ bool ESP8266::startup(int mode) bool ESP8266::reset(void) { - static const int ESP8266_BOOTTIME = 10000; // [ms] + static const auto ESP8266_BOOTTIME = 10s; bool done = false; _smutex.lock(); - unsigned long int start_time = rtos::Kernel::get_ms_count(); + auto start_time = rtos::Kernel::Clock::now(); _reset_done = false; set_timeout(ESP8266_RECV_TIMEOUT); for (int i = 0; i < 2; i++) { @@ -291,10 +293,10 @@ bool ESP8266::reset(void) while (!_reset_done) { _process_oob(ESP8266_RECV_TIMEOUT, true); // UART mutex claimed -> need to check for OOBs ourselves - if (_reset_done || (rtos::Kernel::get_ms_count() - start_time >= ESP8266_BOOTTIME)) { + if (_reset_done || rtos::Kernel::Clock::now() - start_time >= ESP8266_BOOTTIME) { break; } - rtos::ThisThread::sleep_for(100); + rtos::ThisThread::sleep_for(100ms); } done = _reset_done; @@ -494,12 +496,12 @@ int8_t ESP8266::rssi() return rssi; } -int ESP8266::scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned t_max, unsigned t_min) +int ESP8266::scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, duration t_max, duration t_min) { _smutex.lock(); // Default timeout plus time spend scanning each channel - set_timeout(ESP8266_MISC_TIMEOUT + 13 * (t_max ? t_max : ESP8266_SCAN_TIME_MAX_DEFAULT)); + set_timeout(ESP8266_MISC_TIMEOUT + 13 * (t_max != t_max.zero() ? t_max : duration(ESP8266_SCAN_TIME_MAX_DEFAULT))); _scan_r.res = res; _scan_r.limit = limit; @@ -508,7 +510,7 @@ int ESP8266::scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned bool ret_parse_send = true; if (FW_AT_LEAST_VERSION(_at_v.major, _at_v.minor, _at_v.patch, 0, ESP8266_AT_VERSION_WIFI_SCAN_CHANGE)) { - ret_parse_send = _parser.send("AT+CWLAP=,,,%u,%u,%u", (mode == SCANMODE_ACTIVE ? 0 : 1), t_min, t_max); + ret_parse_send = _parser.send("AT+CWLAP=,,,%u,%u,%u", (mode == SCANMODE_ACTIVE ? 0 : 1), t_min.count(), t_max.count()); } else { ret_parse_send = _parser.send("AT+CWLAP"); } @@ -844,7 +846,7 @@ void ESP8266::_oob_packet_hdlr() _packets_end = &packet->next; } -void ESP8266::_process_oob(uint32_t timeout, bool all) +void ESP8266::_process_oob(duration timeout, bool all) { set_timeout(timeout); // Poll for inbound packets @@ -853,14 +855,14 @@ void ESP8266::_process_oob(uint32_t timeout, bool all) set_timeout(); } -void ESP8266::bg_process_oob(uint32_t timeout, bool all) +void ESP8266::bg_process_oob(duration timeout, bool all) { _smutex.lock(); _process_oob(timeout, all); _smutex.unlock(); } -int32_t ESP8266::_recv_tcp_passive(int id, void *data, uint32_t amount, uint32_t timeout) +int32_t ESP8266::_recv_tcp_passive(int id, void *data, uint32_t amount, duration timeout) { int32_t ret = NSAPI_ERROR_WOULD_BLOCK; @@ -923,7 +925,7 @@ BUSY: return ret; } -int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout) +int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, duration timeout) { if (_tcp_passive) { return _recv_tcp_passive(id, data, amount, timeout); @@ -981,7 +983,7 @@ int32_t ESP8266::recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout) return NSAPI_ERROR_WOULD_BLOCK; } -int32_t ESP8266::recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, uint32_t timeout) +int32_t ESP8266::recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, duration timeout) { _smutex.lock(); set_timeout(timeout); @@ -1099,9 +1101,9 @@ bool ESP8266::close(int id) return false; } -void ESP8266::set_timeout(uint32_t timeout_ms) +void ESP8266::set_timeout(duration timeout) { - _parser.set_timeout(timeout_ms); + _parser.set_timeout(timeout.count()); } bool ESP8266::readable() @@ -1172,7 +1174,7 @@ bool ESP8266::get_sntp_time(std::tm *t) memset(buf, 0, 25); bool done = _parser.send("AT+CIPSNTPTIME?") - && _parser.scanf("+CIPSNTPTIME:%24c", &buf) + && _parser.scanf("+CIPSNTPTIME:%24c", buf) && _parser.recv("OK\n"); _smutex.unlock(); diff --git a/components/wifi/esp8266-driver/ESP8266/ESP8266.h b/components/wifi/esp8266-driver/ESP8266/ESP8266.h index e93c5cc956..d9027d8df5 100644 --- a/components/wifi/esp8266-driver/ESP8266/ESP8266.h +++ b/components/wifi/esp8266-driver/ESP8266/ESP8266.h @@ -28,32 +28,35 @@ #include "PinNames.h" #include "platform/ATCmdParser.h" #include "platform/Callback.h" +#include "platform/mbed_chrono.h" #include "platform/mbed_error.h" #include "rtos/Mutex.h" #include "rtos/ThisThread.h" #include "features/netsocket/SocketAddress.h" // Various timeouts for different ESP8266 operations +// (some of these can't use literal form as they're needed for defaults in this header, where +// we shouldn't add a using directive for them. Defines only used in the C++ file can use literals). #ifndef ESP8266_CONNECT_TIMEOUT -#define ESP8266_CONNECT_TIMEOUT 15000 +#define ESP8266_CONNECT_TIMEOUT 15s #endif #ifndef ESP8266_SEND_TIMEOUT -#define ESP8266_SEND_TIMEOUT 2000 +#define ESP8266_SEND_TIMEOUT 2s #endif #ifndef ESP8266_RECV_TIMEOUT -#define ESP8266_RECV_TIMEOUT 2000 +#define ESP8266_RECV_TIMEOUT std::chrono::seconds(2) #endif #ifndef ESP8266_MISC_TIMEOUT -#define ESP8266_MISC_TIMEOUT 2000 +#define ESP8266_MISC_TIMEOUT std::chrono::seconds(2) #endif #ifndef ESP8266_DNS_TIMEOUT -#define ESP8266_DNS_TIMEOUT 15000 +#define ESP8266_DNS_TIMEOUT 15s #endif -#define ESP8266_SCAN_TIME_MIN 0 // [ms] -#define ESP8266_SCAN_TIME_MAX 1500 // [ms] -#define ESP8266_SCAN_TIME_MIN_DEFAULT 120 // [ms] -#define ESP8266_SCAN_TIME_MAX_DEFAULT 360 // [ms] +#define ESP8266_SCAN_TIME_MIN 0ms +#define ESP8266_SCAN_TIME_MAX 1500ms +#define ESP8266_SCAN_TIME_MIN_DEFAULT 120ms +#define ESP8266_SCAN_TIME_MAX_DEFAULT 360ms // Firmware version #define ESP8266_SDK_VERSION 2000000 @@ -237,7 +240,9 @@ public: * @return Number of entries in @a res, or if @a count was 0 number of available networks, negative on error * see @a nsapi_error */ - int scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, unsigned t_max, unsigned t_min); + int scan(WiFiAccessPoint *res, unsigned limit, scan_mode mode, + std::chrono::duration t_max, + std::chrono::duration t_min); /**Perform a dns query * @@ -292,7 +297,7 @@ public: * @param amount number of bytes to be received * @return the number of bytes received */ - int32_t recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, uint32_t timeout = ESP8266_RECV_TIMEOUT); + int32_t recv_udp(struct esp8266_socket *socket, void *data, uint32_t amount, mbed::chrono::milliseconds_u32 timeout = ESP8266_RECV_TIMEOUT); /** * Receives stream data from an open TCP socket @@ -302,7 +307,7 @@ public: * @param amount number of bytes to be received * @return the number of bytes received */ - int32_t recv_tcp(int id, void *data, uint32_t amount, uint32_t timeout = ESP8266_RECV_TIMEOUT); + int32_t recv_tcp(int id, void *data, uint32_t amount, mbed::chrono::milliseconds_u32 timeout = ESP8266_RECV_TIMEOUT); /** * Closes a socket @@ -317,7 +322,7 @@ public: * * @param timeout_ms timeout of the connection */ - void set_timeout(uint32_t timeout_ms = ESP8266_MISC_TIMEOUT); + void set_timeout(mbed::chrono::milliseconds_u32 timeout = ESP8266_MISC_TIMEOUT); /** * Checks if data is available @@ -454,7 +459,7 @@ public: * @param timeout AT parser receive timeout * @param if TRUE, process all OOBs instead of only one */ - void bg_process_oob(uint32_t timeout, bool all); + void bg_process_oob(std::chrono::duration timeout, bool all); /** * Flush the serial port input buffers. @@ -485,7 +490,7 @@ private: // FW version specific settings and functionalities bool _tcp_passive; - int32_t _recv_tcp_passive(int id, void *data, uint32_t amount, uint32_t timeout); + int32_t _recv_tcp_passive(int id, void *data, uint32_t amount, std::chrono::duration timeout); mbed::Callback _callback; // UART settings @@ -518,7 +523,7 @@ private: size_t _heap_usage; // (Socket data buffer usage) // OOB processing - void _process_oob(uint32_t timeout, bool all); + void _process_oob(std::chrono::duration timeout, bool all); // OOB message handlers void _oob_packet_hdlr(); diff --git a/components/wifi/esp8266-driver/ESP8266Interface.cpp b/components/wifi/esp8266-driver/ESP8266Interface.cpp index 8cfa6b8d7a..b1c2dad284 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.cpp +++ b/components/wifi/esp8266-driver/ESP8266Interface.cpp @@ -31,6 +31,8 @@ #include "platform/mbed_debug.h" #include "rtos/ThisThread.h" +using namespace std::chrono; + #ifndef MBED_CONF_ESP8266_DEBUG #define MBED_CONF_ESP8266_DEBUG false #endif @@ -196,7 +198,7 @@ void ESP8266Interface::PowerPin::power_on() if (_pwr_pin.is_connected()) { _pwr_pin = MBED_CONF_ESP8266_POWER_ON_POLARITY; tr_debug("power_on(): HW power-on."); - ThisThread::sleep_for(MBED_CONF_ESP8266_POWER_ON_TIME_MS); + ThisThread::sleep_for(milliseconds(MBED_CONF_ESP8266_POWER_ON_TIME_MS)); } } @@ -205,7 +207,7 @@ void ESP8266Interface::PowerPin::power_off() if (_pwr_pin.is_connected()) { _pwr_pin = !MBED_CONF_ESP8266_POWER_ON_POLARITY; tr_debug("power_off(): HW power-off."); - ThisThread::sleep_for(MBED_CONF_ESP8266_POWER_OFF_TIME_MS); + ThisThread::sleep_for(milliseconds(MBED_CONF_ESP8266_POWER_OFF_TIME_MS)); } } @@ -260,14 +262,14 @@ void ESP8266Interface::_connect_async() return; } _connect_retval = _esp.connect(ap_ssid, ap_pass); - int timeleft_ms = ESP8266_INTERFACE_CONNECT_TIMEOUT_MS - _conn_timer.read_ms(); + auto timepassed = _conn_timer.elapsed_time(); if (_connect_retval == NSAPI_ERROR_OK || _connect_retval == NSAPI_ERROR_AUTH_FAILURE || _connect_retval == NSAPI_ERROR_NO_SSID - || ((_if_blocking == true) && (timeleft_ms <= 0))) { + || ((_if_blocking == true) && (timepassed >= ESP8266_INTERFACE_CONNECT_TIMEOUT))) { _connect_event_id = 0; _conn_timer.stop(); - if (timeleft_ms <= 0 && _connect_retval != NSAPI_ERROR_OK) { + if (timepassed >= ESP8266_INTERFACE_CONNECT_TIMEOUT && _connect_retval != NSAPI_ERROR_OK) { _connect_retval = NSAPI_ERROR_CONNECTION_TIMEOUT; } if (_connect_retval != NSAPI_ERROR_OK) { @@ -279,7 +281,7 @@ void ESP8266Interface::_connect_async() #endif } else { // Postpone to give other stuff time to run - _connect_event_id = _global_event_queue->call_in(ESP8266_INTERFACE_CONNECT_INTERVAL_MS, + _connect_event_id = _global_event_queue->call_in(ESP8266_INTERFACE_CONNECT_INTERVAL, callback(this, &ESP8266Interface::_connect_async)); if (!_connect_event_id) { MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \ @@ -411,11 +413,11 @@ void ESP8266Interface::_disconnect_async() { _cmutex.lock(); _disconnect_retval = _esp.disconnect() ? NSAPI_ERROR_OK : NSAPI_ERROR_DEVICE_ERROR; - int timeleft_ms = ESP8266_INTERFACE_CONNECT_TIMEOUT_MS - _conn_timer.read_ms(); + auto timepassed = _conn_timer.elapsed_time(); - if (_disconnect_retval == NSAPI_ERROR_OK || ((_if_blocking == true) && (timeleft_ms <= 0))) { + if (_disconnect_retval == NSAPI_ERROR_OK || ((_if_blocking == true) && (timepassed >= ESP8266_INTERFACE_CONNECT_TIMEOUT))) { - if (timeleft_ms <= 0 && _connect_retval != NSAPI_ERROR_OK) { + if (timepassed >= ESP8266_INTERFACE_CONNECT_TIMEOUT && _connect_retval != NSAPI_ERROR_OK) { _disconnect_retval = NSAPI_ERROR_CONNECTION_TIMEOUT; } else { if (_conn_stat != NSAPI_STATUS_DISCONNECTED) { @@ -436,7 +438,7 @@ void ESP8266Interface::_disconnect_async() } else { // Postpone to give other stuff time to run _disconnect_event_id = _global_event_queue->call_in( - ESP8266_INTERFACE_CONNECT_INTERVAL_MS, + ESP8266_INTERFACE_CONNECT_INTERVAL, callback(this, &ESP8266Interface::_disconnect_async)); if (!_disconnect_event_id) { MBED_ERROR( @@ -612,10 +614,10 @@ int8_t ESP8266Interface::get_rssi() int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count) { - return scan(res, count, SCANMODE_ACTIVE, 0, 0); + return scan(res, count, SCANMODE_ACTIVE); } -int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count, scan_mode mode, unsigned t_max, unsigned t_min) +int ESP8266Interface::scan(WiFiAccessPoint *res, unsigned count, scan_mode mode, mbed::chrono::milliseconds_u32 t_max, mbed::chrono::milliseconds_u32 t_min) { if (t_max > ESP8266_SCAN_TIME_MAX) { return NSAPI_ERROR_PARAMETER; @@ -735,7 +737,15 @@ nsapi_error_t ESP8266Interface::_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 - ThisThread::sleep_for(2); // Documentation says 200 us; need 2 ticks to get minimum 1 ms. + // First need to round up when converting to kernel ticks (eg 200us -> 1ms). + auto delay = duration_cast(200us); + if (delay < 200us) { + delay++; + } + // Then need to round the clock-resolution duration up; if we were at the end of a tick + // period, it might flip immediately. + delay++; + ThisThread::sleep_for(delay); _esp.flush(); _rst_pin.rst_deassert(); } else { @@ -898,7 +908,7 @@ int ESP8266Interface::socket_send(void *handle, const void *data, unsigned size) && socket->proto == NSAPI_TCP && core_util_atomic_cas_u8(&_cbs[socket->id].deferred, &expect_false, true)) { tr_debug("socket_send(...): Postponing SIGIO from the device."); - if (!_global_event_queue->call_in(50, callback(this, &ESP8266Interface::event_deferred))) { + if (!_global_event_queue->call_in(50ms, callback(this, &ESP8266Interface::event_deferred))) { MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \ "socket_send(): unable to add event to queue. Increase \"events.shared-eventsize\"\n"); } @@ -1055,7 +1065,7 @@ void ESP8266Interface::event() { if (!_oob_event_id) { // Throttles event creation by using arbitrary small delay - _oob_event_id = _global_event_queue->call_in(50, callback(this, &ESP8266Interface::proc_oob_evnt)); + _oob_event_id = _global_event_queue->call_in(50ms, callback(this, &ESP8266Interface::proc_oob_evnt)); if (!_oob_event_id) { MBED_ERROR(MBED_MAKE_ERROR(MBED_MODULE_DRIVER, MBED_ERROR_CODE_ENOMEM), \ "ESP8266Interface::event(): unable to add event to queue. Increase \"events.shared-eventsize\"\n"); diff --git a/components/wifi/esp8266-driver/ESP8266Interface.h b/components/wifi/esp8266-driver/ESP8266Interface.h index d371bb457b..c53db055a4 100644 --- a/components/wifi/esp8266-driver/ESP8266Interface.h +++ b/components/wifi/esp8266-driver/ESP8266Interface.h @@ -31,6 +31,7 @@ #include "features/netsocket/WiFiAccessPoint.h" #include "features/netsocket/WiFiInterface.h" #include "platform/Callback.h" +#include "platform/mbed_chrono.h" #if MBED_CONF_RTOS_PRESENT #include "rtos/ConditionVariable.h" #endif @@ -38,8 +39,8 @@ #define ESP8266_SOCKET_COUNT 5 -#define ESP8266_INTERFACE_CONNECT_INTERVAL_MS (5000) -#define ESP8266_INTERFACE_CONNECT_TIMEOUT_MS (2 * ESP8266_CONNECT_TIMEOUT + ESP8266_INTERFACE_CONNECT_INTERVAL_MS) +#define ESP8266_INTERFACE_CONNECT_INTERVAL 5s +#define ESP8266_INTERFACE_CONNECT_TIMEOUT (2 * ESP8266_CONNECT_TIMEOUT + ESP8266_INTERFACE_CONNECT_INTERVAL) #ifdef TARGET_FF_ARDUINO #ifndef MBED_CONF_ESP8266_TX @@ -219,7 +220,8 @@ public: * see @a nsapi_error */ virtual int scan(WiFiAccessPoint *res, unsigned count, scan_mode mode = SCANMODE_PASSIVE, - unsigned t_max = 0, unsigned t_min = 0); + mbed::chrono::milliseconds_u32 t_max = mbed::chrono::milliseconds_u32(0), + mbed::chrono::milliseconds_u32 t_min = mbed::chrono::milliseconds_u32(0)); /** Translates a hostname to an IP address with specific version *