From 875b803483a064f08457a821dc090807149bd81b Mon Sep 17 00:00:00 2001 From: Carlos Garcia Saura Date: Wed, 10 Nov 2021 04:22:00 +0100 Subject: [PATCH] Remove "delay_microseconds_accurate()" and improve systemwide delayMicroseconds() (#2497) --- esphome/components/aht10/aht10.cpp | 2 +- esphome/components/esp32/core.cpp | 6 +----- esphome/components/esp8266/core.cpp | 2 +- .../remote_transmitter_esp32.cpp | 6 ++---- .../remote_transmitter_esp8266.cpp | 13 ++++++------ esphome/components/sdp3x/sdp3x.cpp | 3 ++- esphome/core/helpers.cpp | 21 ++++++++++--------- esphome/core/helpers.h | 2 +- 8 files changed, 25 insertions(+), 30 deletions(-) diff --git a/esphome/components/aht10/aht10.cpp b/esphome/components/aht10/aht10.cpp index 713199212c..e5e04ac181 100644 --- a/esphome/components/aht10/aht10.cpp +++ b/esphome/components/aht10/aht10.cpp @@ -73,7 +73,7 @@ void AHT10Component::update() { bool success = false; for (int i = 0; i < AHT10_ATTEMPTS; ++i) { ESP_LOGVV(TAG, "Attempt %d at %6u", i, millis()); - delay_microseconds_accurate(4); + delayMicroseconds(4); uint8_t reg = 0; if (this->write(®, 1) != i2c::ERROR_OK) { diff --git a/esphome/components/esp32/core.cpp b/esphome/components/esp32/core.cpp index 96047df535..359999120f 100644 --- a/esphome/components/esp32/core.cpp +++ b/esphome/components/esp32/core.cpp @@ -21,11 +21,7 @@ void IRAM_ATTR HOT yield() { vPortYield(); } uint32_t IRAM_ATTR HOT millis() { return (uint32_t)(esp_timer_get_time() / 1000ULL); } void IRAM_ATTR HOT delay(uint32_t ms) { vTaskDelay(ms / portTICK_PERIOD_MS); } uint32_t IRAM_ATTR HOT micros() { return (uint32_t) esp_timer_get_time(); } -void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { - auto start = (uint64_t) esp_timer_get_time(); - while (((uint64_t) esp_timer_get_time()) - start < us) - ; -} +void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { esp_restart(); // restart() doesn't always end execution diff --git a/esphome/components/esp8266/core.cpp b/esphome/components/esp8266/core.cpp index b78600e7a3..51f3ca50ec 100644 --- a/esphome/components/esp8266/core.cpp +++ b/esphome/components/esp8266/core.cpp @@ -12,7 +12,7 @@ void IRAM_ATTR HOT yield() { ::yield(); } uint32_t IRAM_ATTR HOT millis() { return ::millis(); } void IRAM_ATTR HOT delay(uint32_t ms) { ::delay(ms); } uint32_t IRAM_ATTR HOT micros() { return ::micros(); } -void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { ::delayMicroseconds(us); } +void IRAM_ATTR HOT delayMicroseconds(uint32_t us) { delay_microseconds_safe(us); } void arch_restart() { ESP.restart(); // NOLINT(readability-static-accessed-through-instance) // restart() doesn't always end execution diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp index 500d7193f3..c3b61b72c2 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp32.cpp @@ -121,10 +121,8 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen } else { this->status_clear_warning(); } - if (i + 1 < send_times) { - delay(send_wait / 1000UL); - delayMicroseconds(send_wait % 1000UL); - } + if (i + 1 < send_times) + delayMicroseconds(send_wait); } } diff --git a/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp b/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp index 33c01985d7..74e62d4e3b 100644 --- a/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp +++ b/esphome/components/remote_transmitter/remote_transmitter_esp8266.cpp @@ -36,7 +36,7 @@ void RemoteTransmitterComponent::calculate_on_off_time_(uint32_t carrier_frequen void RemoteTransmitterComponent::mark_(uint32_t on_time, uint32_t off_time, uint32_t usec) { if (this->carrier_duty_percent_ == 100 || (on_time == 0 && off_time == 0)) { this->pin_->digital_write(true); - delay_microseconds_accurate(usec); + delayMicroseconds(usec); this->pin_->digital_write(false); return; } @@ -48,19 +48,19 @@ void RemoteTransmitterComponent::mark_(uint32_t on_time, uint32_t off_time, uint const uint32_t elapsed = current_time - start_time; this->pin_->digital_write(true); - delay_microseconds_accurate(std::min(on_time, usec - elapsed)); + delayMicroseconds(std::min(on_time, usec - elapsed)); this->pin_->digital_write(false); if (elapsed + on_time >= usec) return; - delay_microseconds_accurate(std::min(usec - elapsed - on_time, off_time)); + delayMicroseconds(std::min(usec - elapsed - on_time, off_time)); current_time = micros(); } } void RemoteTransmitterComponent::space_(uint32_t usec) { this->pin_->digital_write(false); - delay_microseconds_accurate(usec); + delayMicroseconds(usec); } void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t send_wait) { ESP_LOGD(TAG, "Sending remote code..."); @@ -81,9 +81,8 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen } } - if (i + 1 < send_times) { - delay_microseconds_accurate(send_wait); - } + if (i + 1 < send_times) + delayMicroseconds(send_wait); } } diff --git a/esphome/components/sdp3x/sdp3x.cpp b/esphome/components/sdp3x/sdp3x.cpp index ba7a028f8e..b0d8bcc6c4 100644 --- a/esphome/components/sdp3x/sdp3x.cpp +++ b/esphome/components/sdp3x/sdp3x.cpp @@ -1,5 +1,6 @@ #include "sdp3x.h" #include "esphome/core/log.h" +#include "esphome/core/hal.h" #include "esphome/core/helpers.h" namespace esphome { @@ -25,7 +26,7 @@ void SDP3XComponent::setup() { ESP_LOGW(TAG, "Soft Reset SDP3X failed!"); // This sometimes fails for no good reason } - delay_microseconds_accurate(20000); + delayMicroseconds(20000); if (this->write(SDP3X_READ_ID1, 2) != i2c::ERROR_OK) { ESP_LOGE(TAG, "Read ID1 SDP3X failed!"); diff --git a/esphome/core/helpers.cpp b/esphome/core/helpers.cpp index ada9a48c3b..8cf972e4db 100644 --- a/esphome/core/helpers.cpp +++ b/esphome/core/helpers.cpp @@ -209,17 +209,18 @@ uint8_t crc8(uint8_t *data, uint8_t len) { return crc; } -void delay_microseconds_accurate(uint32_t usec) { - if (usec == 0) - return; - if (usec < 5000UL) { - delayMicroseconds(usec); - return; - } - uint32_t start = micros(); - while (micros() - start < usec) { - delay(0); +void delay_microseconds_safe(uint32_t us) { // avoids CPU locks that could trigger WDT or affect WiFi/BT stability + auto start = micros(); + const uint32_t lag = 5000; // microseconds, specifies the maximum time for a CPU busy-loop. + // it must be larger than the worst-case duration of a delay(1) call (hardware tasks) + // 5ms is conservative, it could be reduced when exact BT/WiFi stack delays are known + if (us > lag) { + delay((us - lag) / 1000UL); // note: in disabled-interrupt contexts delay() won't actually sleep + while (micros() - start < us - lag) + delay(1); // in those cases, this loop allows to yield for BT/WiFi stack tasks } + while (micros() - start < us) // fine delay the remaining usecs + ; } uint8_t reverse_bits_8(uint8_t x) { diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 905cb76170..040780e072 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -255,7 +255,7 @@ struct is_callable // NOLINT static constexpr auto value = decltype(test(nullptr))::value; // NOLINT }; -void delay_microseconds_accurate(uint32_t usec); +void delay_microseconds_safe(uint32_t us); template class Deduplicator { public: