mirror of
https://github.com/esphome/esphome.git
synced 2024-12-22 13:34:54 +01:00
Add ESP8266 core v2.6.2 (#905)
* Add ESP8266 core v2.6.2 * Upstream ESP8266 Wifi fixes * Replace disable_interrupt with InterruptLock C++ class * Update code to use InterruptLock * Lint * Update dht.cpp * Improve InterruptLock docs, mark as ICACHE_RAM_ATTR * Fixes
This commit is contained in:
parent
bba6d6897d
commit
7a6df38515
12 changed files with 291 additions and 180 deletions
|
@ -32,9 +32,11 @@ void DallasComponent::setup() {
|
|||
ESP_LOGCONFIG(TAG, "Setting up DallasComponent...");
|
||||
|
||||
yield();
|
||||
disable_interrupts();
|
||||
std::vector<uint64_t> raw_sensors = this->one_wire_->search_vec();
|
||||
enable_interrupts();
|
||||
std::vector<uint64_t> raw_sensors;
|
||||
{
|
||||
InterruptLock lock;
|
||||
raw_sensors = this->one_wire_->search_vec();
|
||||
}
|
||||
|
||||
for (auto &address : raw_sensors) {
|
||||
std::string s = uint64_to_string(address);
|
||||
|
@ -108,8 +110,9 @@ DallasTemperatureSensor *DallasComponent::get_sensor_by_index(uint8_t index, uin
|
|||
void DallasComponent::update() {
|
||||
this->status_clear_warning();
|
||||
|
||||
disable_interrupts();
|
||||
bool result;
|
||||
{
|
||||
InterruptLock lock;
|
||||
if (!this->one_wire_->reset()) {
|
||||
result = false;
|
||||
} else {
|
||||
|
@ -117,7 +120,7 @@ void DallasComponent::update() {
|
|||
this->one_wire_->skip();
|
||||
this->one_wire_->write8(DALLAS_COMMAND_START_CONVERSION);
|
||||
}
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
ESP_LOGE(TAG, "Requesting conversion failed");
|
||||
|
@ -127,9 +130,11 @@ void DallasComponent::update() {
|
|||
|
||||
for (auto *sensor : this->sensors_) {
|
||||
this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] {
|
||||
disable_interrupts();
|
||||
bool res = sensor->read_scratch_pad();
|
||||
enable_interrupts();
|
||||
bool res;
|
||||
{
|
||||
InterruptLock lock;
|
||||
res = sensor->read_scratch_pad();
|
||||
}
|
||||
|
||||
if (!res) {
|
||||
ESP_LOGW(TAG, "'%s' - Reseting bus for read failed!", sensor->get_name().c_str());
|
||||
|
@ -170,7 +175,7 @@ const std::string &DallasTemperatureSensor::get_address_name() {
|
|||
|
||||
return this->address_name_;
|
||||
}
|
||||
bool DallasTemperatureSensor::read_scratch_pad() {
|
||||
bool ICACHE_RAM_ATTR DallasTemperatureSensor::read_scratch_pad() {
|
||||
ESPOneWire *wire = this->parent_->one_wire_;
|
||||
if (!wire->reset()) {
|
||||
return false;
|
||||
|
@ -185,9 +190,11 @@ bool DallasTemperatureSensor::read_scratch_pad() {
|
|||
return true;
|
||||
}
|
||||
bool DallasTemperatureSensor::setup_sensor() {
|
||||
disable_interrupts();
|
||||
bool r = this->read_scratch_pad();
|
||||
enable_interrupts();
|
||||
bool r;
|
||||
{
|
||||
InterruptLock lock;
|
||||
r = this->read_scratch_pad();
|
||||
}
|
||||
|
||||
if (!r) {
|
||||
ESP_LOGE(TAG, "Reading scratchpad failed: reset");
|
||||
|
@ -222,7 +229,8 @@ bool DallasTemperatureSensor::setup_sensor() {
|
|||
}
|
||||
|
||||
ESPOneWire *wire = this->parent_->one_wire_;
|
||||
disable_interrupts();
|
||||
{
|
||||
InterruptLock lock;
|
||||
if (wire->reset()) {
|
||||
wire->select(this->address_);
|
||||
wire->write8(DALLAS_COMMAND_WRITE_SCRATCH_PAD);
|
||||
|
@ -235,7 +243,7 @@ bool DallasTemperatureSensor::setup_sensor() {
|
|||
wire->select(this->address_);
|
||||
wire->write8(0x48);
|
||||
}
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
delay(20); // allow it to finish operation
|
||||
wire->reset();
|
||||
|
|
|
@ -12,7 +12,7 @@ const int ONE_WIRE_ROM_SEARCH = 0xF0;
|
|||
|
||||
ESPOneWire::ESPOneWire(GPIOPin *pin) : pin_(pin) {}
|
||||
|
||||
bool HOT ESPOneWire::reset() {
|
||||
bool HOT ICACHE_RAM_ATTR ESPOneWire::reset() {
|
||||
uint8_t retries = 125;
|
||||
|
||||
// Wait for communication to clear
|
||||
|
@ -39,7 +39,7 @@ bool HOT ESPOneWire::reset() {
|
|||
return r;
|
||||
}
|
||||
|
||||
void HOT ESPOneWire::write_bit(bool bit) {
|
||||
void HOT ICACHE_RAM_ATTR ESPOneWire::write_bit(bool bit) {
|
||||
// Initiate write/read by pulling low.
|
||||
this->pin_->pin_mode(OUTPUT);
|
||||
this->pin_->digital_write(false);
|
||||
|
@ -60,7 +60,7 @@ void HOT ESPOneWire::write_bit(bool bit) {
|
|||
}
|
||||
}
|
||||
|
||||
bool HOT ESPOneWire::read_bit() {
|
||||
bool HOT ICACHE_RAM_ATTR ESPOneWire::read_bit() {
|
||||
// Initiate read slot by pulling LOW for at least 1µs
|
||||
this->pin_->pin_mode(OUTPUT);
|
||||
this->pin_->digital_write(false);
|
||||
|
@ -76,43 +76,43 @@ bool HOT ESPOneWire::read_bit() {
|
|||
return r;
|
||||
}
|
||||
|
||||
void ESPOneWire::write8(uint8_t val) {
|
||||
void ICACHE_RAM_ATTR ESPOneWire::write8(uint8_t val) {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
this->write_bit(bool((1u << i) & val));
|
||||
}
|
||||
}
|
||||
|
||||
void ESPOneWire::write64(uint64_t val) {
|
||||
void ICACHE_RAM_ATTR ESPOneWire::write64(uint64_t val) {
|
||||
for (uint8_t i = 0; i < 64; i++) {
|
||||
this->write_bit(bool((1ULL << i) & val));
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ESPOneWire::read8() {
|
||||
uint8_t ICACHE_RAM_ATTR ESPOneWire::read8() {
|
||||
uint8_t ret = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
ret |= (uint8_t(this->read_bit()) << i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
uint64_t ESPOneWire::read64() {
|
||||
uint64_t ICACHE_RAM_ATTR ESPOneWire::read64() {
|
||||
uint64_t ret = 0;
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
ret |= (uint64_t(this->read_bit()) << i);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
void ESPOneWire::select(uint64_t address) {
|
||||
void ICACHE_RAM_ATTR ESPOneWire::select(uint64_t address) {
|
||||
this->write8(ONE_WIRE_ROM_SELECT);
|
||||
this->write64(address);
|
||||
}
|
||||
void ESPOneWire::reset_search() {
|
||||
void ICACHE_RAM_ATTR ESPOneWire::reset_search() {
|
||||
this->last_discrepancy_ = 0;
|
||||
this->last_device_flag_ = false;
|
||||
this->last_family_discrepancy_ = 0;
|
||||
this->rom_number_ = 0;
|
||||
}
|
||||
uint64_t HOT ESPOneWire::search() {
|
||||
uint64_t HOT ICACHE_RAM_ATTR ESPOneWire::search() {
|
||||
if (this->last_device_flag_) {
|
||||
return 0u;
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ uint64_t HOT ESPOneWire::search() {
|
|||
|
||||
return this->rom_number_;
|
||||
}
|
||||
std::vector<uint64_t> ESPOneWire::search_vec() {
|
||||
std::vector<uint64_t> ICACHE_RAM_ATTR ESPOneWire::search_vec() {
|
||||
std::vector<uint64_t> res;
|
||||
|
||||
this->reset_search();
|
||||
|
@ -206,12 +206,12 @@ std::vector<uint64_t> ESPOneWire::search_vec() {
|
|||
|
||||
return res;
|
||||
}
|
||||
void ESPOneWire::skip() {
|
||||
void ICACHE_RAM_ATTR ESPOneWire::skip() {
|
||||
this->write8(0xCC); // skip ROM
|
||||
}
|
||||
GPIOPin *ESPOneWire::get_pin() { return this->pin_; }
|
||||
|
||||
uint8_t *ESPOneWire::rom_number8_() { return reinterpret_cast<uint8_t *>(&this->rom_number_); }
|
||||
uint8_t ICACHE_RAM_ATTR *ESPOneWire::rom_number8_() { return reinterpret_cast<uint8_t *>(&this->rom_number_); }
|
||||
|
||||
} // namespace dallas
|
||||
} // namespace esphome
|
||||
|
|
|
@ -71,11 +71,17 @@ void DHT::set_dht_model(DHTModel model) {
|
|||
this->model_ = model;
|
||||
this->is_auto_detect_ = model == DHT_MODEL_AUTO_DETECT;
|
||||
}
|
||||
bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_errors) {
|
||||
bool HOT ICACHE_RAM_ATTR DHT::read_sensor_(float *temperature, float *humidity, bool report_errors) {
|
||||
*humidity = NAN;
|
||||
*temperature = NAN;
|
||||
|
||||
disable_interrupts();
|
||||
int error_code = 0;
|
||||
int8_t i = 0;
|
||||
uint8_t data[5] = {0, 0, 0, 0, 0};
|
||||
|
||||
{
|
||||
InterruptLock lock;
|
||||
|
||||
this->pin_->digital_write(false);
|
||||
this->pin_->pin_mode(OUTPUT);
|
||||
this->pin_->digital_write(false);
|
||||
|
@ -92,27 +98,24 @@ bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_erro
|
|||
this->pin_->pin_mode(INPUT_PULLUP);
|
||||
delayMicroseconds(40);
|
||||
|
||||
uint8_t data[5] = {0, 0, 0, 0, 0};
|
||||
uint8_t bit = 7;
|
||||
uint8_t byte = 0;
|
||||
|
||||
for (int8_t i = -1; i < 40; i++) {
|
||||
for (i = -1; i < 40; i++) {
|
||||
uint32_t start_time = micros();
|
||||
|
||||
// Wait for rising edge
|
||||
while (!this->pin_->digital_read()) {
|
||||
if (micros() - start_time > 90) {
|
||||
enable_interrupts();
|
||||
if (report_errors) {
|
||||
if (i < 0) {
|
||||
ESP_LOGW(TAG, "Waiting for DHT communication to clear failed!");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Rising edge for bit %d failed!", i);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (i < 0)
|
||||
error_code = 1;
|
||||
else
|
||||
error_code = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (error_code != 0)
|
||||
break;
|
||||
|
||||
start_time = micros();
|
||||
uint32_t end_time = start_time;
|
||||
|
@ -120,17 +123,15 @@ bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_erro
|
|||
// Wait for falling edge
|
||||
while (this->pin_->digital_read()) {
|
||||
if ((end_time = micros()) - start_time > 90) {
|
||||
enable_interrupts();
|
||||
if (report_errors) {
|
||||
if (i < 0) {
|
||||
ESP_LOGW(TAG, "Requesting data from DHT failed!");
|
||||
} else {
|
||||
ESP_LOGW(TAG, "Falling edge for bit %d failed!", i);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
if (i < 0)
|
||||
error_code = 3;
|
||||
else
|
||||
error_code = 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (error_code != 0)
|
||||
break;
|
||||
|
||||
if (i < 0)
|
||||
continue;
|
||||
|
@ -144,7 +145,27 @@ bool HOT DHT::read_sensor_(float *temperature, float *humidity, bool report_erro
|
|||
} else
|
||||
bit--;
|
||||
}
|
||||
enable_interrupts();
|
||||
}
|
||||
if (!report_errors && error_code != 0)
|
||||
return false;
|
||||
|
||||
switch (error_code) {
|
||||
case 1:
|
||||
ESP_LOGW(TAG, "Waiting for DHT communication to clear failed!");
|
||||
return false;
|
||||
case 2:
|
||||
ESP_LOGW(TAG, "Rising edge for bit %d failed!", i);
|
||||
return false;
|
||||
case 3:
|
||||
ESP_LOGW(TAG, "Requesting data from DHT failed!");
|
||||
return false;
|
||||
case 4:
|
||||
ESP_LOGW(TAG, "Falling edge for bit %d failed!", i);
|
||||
return false;
|
||||
case 0:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ESP_LOGVV(TAG,
|
||||
"Data: Hum=0b" BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN
|
||||
|
|
|
@ -42,7 +42,8 @@ bool HX711Sensor::read_sensor_(uint32_t *result) {
|
|||
this->status_clear_warning();
|
||||
uint32_t data = 0;
|
||||
|
||||
disable_interrupts();
|
||||
{
|
||||
InterruptLock lock;
|
||||
for (uint8_t i = 0; i < 24; i++) {
|
||||
this->sck_pin_->digital_write(true);
|
||||
delayMicroseconds(1);
|
||||
|
@ -58,7 +59,7 @@ bool HX711Sensor::read_sensor_(uint32_t *result) {
|
|||
this->sck_pin_->digital_write(false);
|
||||
delayMicroseconds(1);
|
||||
}
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
if (data & 0x800000ULL) {
|
||||
data |= 0xFF000000ULL;
|
||||
|
|
|
@ -67,7 +67,8 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|||
uint32_t on_time, off_time;
|
||||
this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &on_time, &off_time);
|
||||
for (uint32_t i = 0; i < send_times; i++) {
|
||||
disable_interrupts();
|
||||
{
|
||||
InterruptLock lock;
|
||||
for (int32_t item : this->temp_.get_data()) {
|
||||
if (item > 0) {
|
||||
const auto length = uint32_t(item);
|
||||
|
@ -78,11 +79,10 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
|||
}
|
||||
App.feed_wdt();
|
||||
}
|
||||
enable_interrupts();
|
||||
}
|
||||
|
||||
if (i + 1 < send_times) {
|
||||
delay(send_wait / 1000UL);
|
||||
delayMicroseconds(send_wait % 1000UL);
|
||||
delay_microseconds_accurate(send_wait);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -295,7 +295,8 @@ void ICACHE_RAM_ATTR HOT ESP8266SoftwareSerial::write_byte(uint8_t data) {
|
|||
return;
|
||||
}
|
||||
|
||||
disable_interrupts();
|
||||
{
|
||||
InterruptLock lock;
|
||||
uint32_t wait = this->bit_time_;
|
||||
const uint32_t start = ESP.getCycleCount();
|
||||
// Start bit
|
||||
|
@ -312,7 +313,7 @@ void ICACHE_RAM_ATTR HOT ESP8266SoftwareSerial::write_byte(uint8_t data) {
|
|||
this->write_bit_(true, &wait, start);
|
||||
if (this->stop_bits_ == 2)
|
||||
this->wait_(&wait, start);
|
||||
enable_interrupts();
|
||||
}
|
||||
}
|
||||
void ICACHE_RAM_ATTR ESP8266SoftwareSerial::wait_(uint32_t *wait, const uint32_t &start) {
|
||||
while (ESP.getCycleCount() - start < *wait)
|
||||
|
@ -323,7 +324,7 @@ bool ICACHE_RAM_ATTR ESP8266SoftwareSerial::read_bit_(uint32_t *wait, const uint
|
|||
this->wait_(wait, start);
|
||||
return this->rx_pin_->digital_read();
|
||||
}
|
||||
void ESP8266SoftwareSerial::write_bit_(bool bit, uint32_t *wait, const uint32_t &start) {
|
||||
void ICACHE_RAM_ATTR ESP8266SoftwareSerial::write_bit_(bool bit, uint32_t *wait, const uint32_t &start) {
|
||||
this->tx_pin_->digital_write(bit);
|
||||
this->wait_(wait, start);
|
||||
}
|
||||
|
|
|
@ -6,8 +6,16 @@
|
|||
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
|
||||
extern "C" {
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/dns.h"
|
||||
#include "lwip/dhcp.h"
|
||||
#include "lwip/init.h" // LWIP_VERSION_
|
||||
#if LWIP_IPV6
|
||||
#include "lwip/netif.h" // struct netif
|
||||
#endif
|
||||
}
|
||||
|
||||
#include "esphome/core/helpers.h"
|
||||
#include "esphome/core/log.h"
|
||||
|
@ -74,6 +82,19 @@ bool WiFiComponent::wifi_apply_power_save_() {
|
|||
}
|
||||
return wifi_set_sleep_type(power_save);
|
||||
}
|
||||
|
||||
#if LWIP_VERSION_MAJOR != 1
|
||||
/*
|
||||
lwip v2 needs to be notified of IP changes, see also
|
||||
https://github.com/d-a-v/Arduino/blob/0e7d21e17144cfc5f53c016191daca8723e89ee8/libraries/ESP8266WiFi/src/ESP8266WiFiSTA.cpp#L251
|
||||
*/
|
||||
#undef netif_set_addr // need to call lwIP-v1.4 netif_set_addr()
|
||||
extern "C" {
|
||||
struct netif *eagle_lwip_getif(int netif_index);
|
||||
void netif_set_addr(struct netif *netif, const ip4_addr_t *ip, const ip4_addr_t *netmask, const ip4_addr_t *gw);
|
||||
};
|
||||
#endif
|
||||
|
||||
bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||
// enable STA
|
||||
if (!this->wifi_mode_(true, {}))
|
||||
|
@ -94,6 +115,13 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
|||
|
||||
bool ret = true;
|
||||
|
||||
#if LWIP_VERSION_MAJOR != 1
|
||||
// get current->previous IP address
|
||||
// (check below)
|
||||
ip_info previp{};
|
||||
wifi_get_ip_info(STATION_IF, &previp);
|
||||
#endif
|
||||
|
||||
struct ip_info info {};
|
||||
info.ip.addr = static_cast<uint32_t>(manual_ip->static_ip);
|
||||
info.gw.addr = static_cast<uint32_t>(manual_ip->gateway);
|
||||
|
@ -122,6 +150,14 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
|||
dns_setserver(1, &dns);
|
||||
}
|
||||
|
||||
#if LWIP_VERSION_MAJOR != 1
|
||||
// trigger address change by calling lwIP-v1.4 api
|
||||
// only when ip is already set by other mean (generally dhcp)
|
||||
if (previp.ip.addr != 0 && previp.ip.addr != info.ip.addr) {
|
||||
netif_set_addr(eagle_lwip_getif(STATION_IF), reinterpret_cast<const ip4_addr_t *>(&info.ip),
|
||||
reinterpret_cast<const ip4_addr_t *>(&info.netmask), reinterpret_cast<const ip4_addr_t *>(&info.gw));
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -133,10 +169,31 @@ IPAddress WiFiComponent::wifi_sta_ip_() {
|
|||
return {ip.ip.addr};
|
||||
}
|
||||
bool WiFiComponent::wifi_apply_hostname_() {
|
||||
bool ret = wifi_station_set_hostname(const_cast<char *>(App.get_name().c_str()));
|
||||
const std::string &hostname = App.get_name();
|
||||
bool ret = wifi_station_set_hostname(const_cast<char *>(hostname.c_str()));
|
||||
if (!ret) {
|
||||
ESP_LOGV(TAG, "Setting WiFi Hostname failed!");
|
||||
}
|
||||
|
||||
// inform dhcp server of hostname change using dhcp_renew()
|
||||
for (netif *intf = netif_list; intf; intf = intf->next) {
|
||||
// unconditionally update all known interfaces
|
||||
#if LWIP_VERSION_MAJOR == 1
|
||||
intf->hostname = (char *) wifi_station_get_hostname();
|
||||
#else
|
||||
intf->hostname = wifi_station_get_hostname();
|
||||
#endif
|
||||
if (netif_dhcp_data(intf) != nullptr) {
|
||||
// renew already started DHCP leases
|
||||
err_t lwipret = dhcp_renew(intf);
|
||||
if (lwipret != ERR_OK) {
|
||||
ESP_LOGW(TAG, "wifi_apply_hostname_(%s): lwIP error %d on interface %c%c (index %d)", intf->hostname,
|
||||
(int) lwipret, intf->name[0], intf->name[1], intf->num);
|
||||
ret = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -156,21 +156,6 @@ ParseOnOffState parse_on_off(const char *str, const char *on, const char *off) {
|
|||
|
||||
const char *HOSTNAME_CHARACTER_WHITELIST = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_";
|
||||
|
||||
void disable_interrupts() {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
portDISABLE_INTERRUPTS();
|
||||
#else
|
||||
noInterrupts();
|
||||
#endif
|
||||
}
|
||||
void enable_interrupts() {
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
portENABLE_INTERRUPTS();
|
||||
#else
|
||||
interrupts();
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t crc8(uint8_t *data, uint8_t len) {
|
||||
uint8_t crc = 0;
|
||||
|
||||
|
@ -193,8 +178,8 @@ void delay_microseconds_accurate(uint32_t usec) {
|
|||
if (usec <= 16383UL) {
|
||||
delayMicroseconds(usec);
|
||||
} else {
|
||||
delay(usec / 1000UL);
|
||||
delayMicroseconds(usec % 1000UL);
|
||||
delay(usec / 16383UL);
|
||||
delayMicroseconds(usec % 16383UL);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,4 +315,13 @@ std::string hexencode(const uint8_t *data, uint32_t len) {
|
|||
return res;
|
||||
}
|
||||
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
ICACHE_RAM_ATTR InterruptLock::InterruptLock() { xt_state_ = xt_rsil(15); }
|
||||
ICACHE_RAM_ATTR InterruptLock::~InterruptLock() { xt_wsr_ps(xt_state_); }
|
||||
#endif
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
ICACHE_RAM_ATTR InterruptLock::InterruptLock() { portENABLE_INTERRUPTS(); }
|
||||
ICACHE_RAM_ATTR InterruptLock::~InterruptLock() { portDISABLE_INTERRUPTS(); }
|
||||
#endif
|
||||
|
||||
} // namespace esphome
|
||||
|
|
|
@ -133,16 +133,38 @@ uint16_t encode_uint16(uint8_t msb, uint8_t lsb);
|
|||
/// Decode a 16-bit unsigned integer into an array of two values: most significant byte, least significant byte.
|
||||
std::array<uint8_t, 2> decode_uint16(uint16_t value);
|
||||
|
||||
/** Cross-platform method to disable interrupts.
|
||||
/***
|
||||
* An interrupt helper class.
|
||||
*
|
||||
* Useful when you need to do some timing-dependent communication.
|
||||
* This behaves like std::lock_guard. As long as the value is visible in the current stack, all interrupts
|
||||
* (including flash reads) will be disabled.
|
||||
*
|
||||
* @see Do not forget to call `enable_interrupts()` again or otherwise things will go very wrong.
|
||||
* Please note all functions called when the interrupt lock must be marked ICACHE_RAM_ATTR (loading code into
|
||||
* instruction cache is done via interrupts; disabling interrupts prevents data not already in cache from being
|
||||
* pulled from flash).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```cpp
|
||||
* // interrupts are enabled
|
||||
* {
|
||||
* InterruptLock lock;
|
||||
* // do something
|
||||
* // interrupts are disabled
|
||||
* }
|
||||
* // interrupts are enabled
|
||||
* ```
|
||||
*/
|
||||
void disable_interrupts();
|
||||
class InterruptLock {
|
||||
public:
|
||||
InterruptLock();
|
||||
~InterruptLock();
|
||||
|
||||
/// Cross-platform method to enable interrupts after they have been disabled.
|
||||
void enable_interrupts();
|
||||
protected:
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
uint32_t xt_state_;
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Calculate a crc8 of data with the provided data length.
|
||||
uint8_t crc8(uint8_t *data, uint8_t len);
|
||||
|
|
|
@ -105,16 +105,18 @@ void ESPPreferences::save_esp8266_flash_() {
|
|||
return;
|
||||
|
||||
ESP_LOGVV(TAG, "Saving preferences to flash...");
|
||||
disable_interrupts();
|
||||
auto erase_res = spi_flash_erase_sector(get_esp8266_flash_sector());
|
||||
SpiFlashOpResult erase_res, write_res = SPI_FLASH_RESULT_OK;
|
||||
{
|
||||
InterruptLock lock;
|
||||
erase_res = spi_flash_erase_sector(get_esp8266_flash_sector());
|
||||
if (erase_res == SPI_FLASH_RESULT_OK) {
|
||||
write_res = spi_flash_write(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
||||
}
|
||||
}
|
||||
if (erase_res != SPI_FLASH_RESULT_OK) {
|
||||
enable_interrupts();
|
||||
ESP_LOGV(TAG, "Erase ESP8266 flash failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
auto write_res = spi_flash_write(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
||||
enable_interrupts();
|
||||
if (write_res != SPI_FLASH_RESULT_OK) {
|
||||
ESP_LOGV(TAG, "Write ESP8266 flash failed!");
|
||||
return;
|
||||
|
@ -173,9 +175,11 @@ ESPPreferences::ESPPreferences()
|
|||
void ESPPreferences::begin() {
|
||||
this->flash_storage_ = new uint32_t[ESP8266_FLASH_STORAGE_SIZE];
|
||||
ESP_LOGVV(TAG, "Loading preferences from flash...");
|
||||
disable_interrupts();
|
||||
|
||||
{
|
||||
InterruptLock lock;
|
||||
spi_flash_read(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
||||
enable_interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type, bool in_flash) {
|
||||
|
|
|
@ -45,6 +45,8 @@ def validate_board(value):
|
|||
validate_platform = cv.one_of('ESP32', 'ESP8266', upper=True)
|
||||
|
||||
PLATFORMIO_ESP8266_LUT = {
|
||||
'2.6.2': 'espressif8266@2.3.1',
|
||||
'2.6.1': 'espressif8266@2.3.0',
|
||||
'2.5.2': 'espressif8266@2.2.3',
|
||||
'2.5.1': 'espressif8266@2.1.0',
|
||||
'2.5.0': 'espressif8266@2.0.1',
|
||||
|
|
|
@ -60,6 +60,7 @@ FILTER_PLATFORMIO_LINES = [
|
|||
r"Using cache: .*",
|
||||
r'Installing dependencies',
|
||||
r'.* @ .* is already installed',
|
||||
r'Building in .* mode',
|
||||
]
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue