mirror of
https://github.com/esphome/esphome.git
synced 2024-11-10 17:27:45 +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
219fe41831
commit
072b2c445c
11 changed files with 289 additions and 180 deletions
|
@ -32,9 +32,11 @@ void DallasComponent::setup() {
|
||||||
ESP_LOGCONFIG(TAG, "Setting up DallasComponent...");
|
ESP_LOGCONFIG(TAG, "Setting up DallasComponent...");
|
||||||
|
|
||||||
yield();
|
yield();
|
||||||
disable_interrupts();
|
std::vector<uint64_t> raw_sensors;
|
||||||
std::vector<uint64_t> raw_sensors = this->one_wire_->search_vec();
|
{
|
||||||
enable_interrupts();
|
InterruptLock lock;
|
||||||
|
raw_sensors = this->one_wire_->search_vec();
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &address : raw_sensors) {
|
for (auto &address : raw_sensors) {
|
||||||
std::string s = uint64_to_string(address);
|
std::string s = uint64_to_string(address);
|
||||||
|
@ -108,16 +110,17 @@ DallasTemperatureSensor *DallasComponent::get_sensor_by_index(uint8_t index, uin
|
||||||
void DallasComponent::update() {
|
void DallasComponent::update() {
|
||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
|
|
||||||
disable_interrupts();
|
|
||||||
bool result;
|
bool result;
|
||||||
if (!this->one_wire_->reset()) {
|
{
|
||||||
result = false;
|
InterruptLock lock;
|
||||||
} else {
|
if (!this->one_wire_->reset()) {
|
||||||
result = true;
|
result = false;
|
||||||
this->one_wire_->skip();
|
} else {
|
||||||
this->one_wire_->write8(DALLAS_COMMAND_START_CONVERSION);
|
result = true;
|
||||||
|
this->one_wire_->skip();
|
||||||
|
this->one_wire_->write8(DALLAS_COMMAND_START_CONVERSION);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enable_interrupts();
|
|
||||||
|
|
||||||
if (!result) {
|
if (!result) {
|
||||||
ESP_LOGE(TAG, "Requesting conversion failed");
|
ESP_LOGE(TAG, "Requesting conversion failed");
|
||||||
|
@ -127,9 +130,11 @@ void DallasComponent::update() {
|
||||||
|
|
||||||
for (auto *sensor : this->sensors_) {
|
for (auto *sensor : this->sensors_) {
|
||||||
this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] {
|
this->set_timeout(sensor->get_address_name(), sensor->millis_to_wait_for_conversion(), [this, sensor] {
|
||||||
disable_interrupts();
|
bool res;
|
||||||
bool res = sensor->read_scratch_pad();
|
{
|
||||||
enable_interrupts();
|
InterruptLock lock;
|
||||||
|
res = sensor->read_scratch_pad();
|
||||||
|
}
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
ESP_LOGW(TAG, "'%s' - Reseting bus for read failed!", sensor->get_name().c_str());
|
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_;
|
return this->address_name_;
|
||||||
}
|
}
|
||||||
bool DallasTemperatureSensor::read_scratch_pad() {
|
bool ICACHE_RAM_ATTR DallasTemperatureSensor::read_scratch_pad() {
|
||||||
ESPOneWire *wire = this->parent_->one_wire_;
|
ESPOneWire *wire = this->parent_->one_wire_;
|
||||||
if (!wire->reset()) {
|
if (!wire->reset()) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -185,9 +190,11 @@ bool DallasTemperatureSensor::read_scratch_pad() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool DallasTemperatureSensor::setup_sensor() {
|
bool DallasTemperatureSensor::setup_sensor() {
|
||||||
disable_interrupts();
|
bool r;
|
||||||
bool r = this->read_scratch_pad();
|
{
|
||||||
enable_interrupts();
|
InterruptLock lock;
|
||||||
|
r = this->read_scratch_pad();
|
||||||
|
}
|
||||||
|
|
||||||
if (!r) {
|
if (!r) {
|
||||||
ESP_LOGE(TAG, "Reading scratchpad failed: reset");
|
ESP_LOGE(TAG, "Reading scratchpad failed: reset");
|
||||||
|
@ -222,20 +229,21 @@ bool DallasTemperatureSensor::setup_sensor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ESPOneWire *wire = this->parent_->one_wire_;
|
ESPOneWire *wire = this->parent_->one_wire_;
|
||||||
disable_interrupts();
|
{
|
||||||
if (wire->reset()) {
|
InterruptLock lock;
|
||||||
wire->select(this->address_);
|
if (wire->reset()) {
|
||||||
wire->write8(DALLAS_COMMAND_WRITE_SCRATCH_PAD);
|
wire->select(this->address_);
|
||||||
wire->write8(this->scratch_pad_[2]); // high alarm temp
|
wire->write8(DALLAS_COMMAND_WRITE_SCRATCH_PAD);
|
||||||
wire->write8(this->scratch_pad_[3]); // low alarm temp
|
wire->write8(this->scratch_pad_[2]); // high alarm temp
|
||||||
wire->write8(this->scratch_pad_[4]); // resolution
|
wire->write8(this->scratch_pad_[3]); // low alarm temp
|
||||||
wire->reset();
|
wire->write8(this->scratch_pad_[4]); // resolution
|
||||||
|
wire->reset();
|
||||||
|
|
||||||
// write value to EEPROM
|
// write value to EEPROM
|
||||||
wire->select(this->address_);
|
wire->select(this->address_);
|
||||||
wire->write8(0x48);
|
wire->write8(0x48);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enable_interrupts();
|
|
||||||
|
|
||||||
delay(20); // allow it to finish operation
|
delay(20); // allow it to finish operation
|
||||||
wire->reset();
|
wire->reset();
|
||||||
|
|
|
@ -12,7 +12,7 @@ const int ONE_WIRE_ROM_SEARCH = 0xF0;
|
||||||
|
|
||||||
ESPOneWire::ESPOneWire(GPIOPin *pin) : pin_(pin) {}
|
ESPOneWire::ESPOneWire(GPIOPin *pin) : pin_(pin) {}
|
||||||
|
|
||||||
bool HOT ESPOneWire::reset() {
|
bool HOT ICACHE_RAM_ATTR ESPOneWire::reset() {
|
||||||
uint8_t retries = 125;
|
uint8_t retries = 125;
|
||||||
|
|
||||||
// Wait for communication to clear
|
// Wait for communication to clear
|
||||||
|
@ -39,7 +39,7 @@ bool HOT ESPOneWire::reset() {
|
||||||
return r;
|
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.
|
// Initiate write/read by pulling low.
|
||||||
this->pin_->pin_mode(OUTPUT);
|
this->pin_->pin_mode(OUTPUT);
|
||||||
this->pin_->digital_write(false);
|
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
|
// Initiate read slot by pulling LOW for at least 1µs
|
||||||
this->pin_->pin_mode(OUTPUT);
|
this->pin_->pin_mode(OUTPUT);
|
||||||
this->pin_->digital_write(false);
|
this->pin_->digital_write(false);
|
||||||
|
@ -76,43 +76,43 @@ bool HOT ESPOneWire::read_bit() {
|
||||||
return r;
|
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++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
this->write_bit(bool((1u << i) & val));
|
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++) {
|
for (uint8_t i = 0; i < 64; i++) {
|
||||||
this->write_bit(bool((1ULL << i) & val));
|
this->write_bit(bool((1ULL << i) & val));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t ESPOneWire::read8() {
|
uint8_t ICACHE_RAM_ATTR ESPOneWire::read8() {
|
||||||
uint8_t ret = 0;
|
uint8_t ret = 0;
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
ret |= (uint8_t(this->read_bit()) << i);
|
ret |= (uint8_t(this->read_bit()) << i);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
uint64_t ESPOneWire::read64() {
|
uint64_t ICACHE_RAM_ATTR ESPOneWire::read64() {
|
||||||
uint64_t ret = 0;
|
uint64_t ret = 0;
|
||||||
for (uint8_t i = 0; i < 8; i++) {
|
for (uint8_t i = 0; i < 8; i++) {
|
||||||
ret |= (uint64_t(this->read_bit()) << i);
|
ret |= (uint64_t(this->read_bit()) << i);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
void ESPOneWire::select(uint64_t address) {
|
void ICACHE_RAM_ATTR ESPOneWire::select(uint64_t address) {
|
||||||
this->write8(ONE_WIRE_ROM_SELECT);
|
this->write8(ONE_WIRE_ROM_SELECT);
|
||||||
this->write64(address);
|
this->write64(address);
|
||||||
}
|
}
|
||||||
void ESPOneWire::reset_search() {
|
void ICACHE_RAM_ATTR ESPOneWire::reset_search() {
|
||||||
this->last_discrepancy_ = 0;
|
this->last_discrepancy_ = 0;
|
||||||
this->last_device_flag_ = false;
|
this->last_device_flag_ = false;
|
||||||
this->last_family_discrepancy_ = 0;
|
this->last_family_discrepancy_ = 0;
|
||||||
this->rom_number_ = 0;
|
this->rom_number_ = 0;
|
||||||
}
|
}
|
||||||
uint64_t HOT ESPOneWire::search() {
|
uint64_t HOT ICACHE_RAM_ATTR ESPOneWire::search() {
|
||||||
if (this->last_device_flag_) {
|
if (this->last_device_flag_) {
|
||||||
return 0u;
|
return 0u;
|
||||||
}
|
}
|
||||||
|
@ -196,7 +196,7 @@ uint64_t HOT ESPOneWire::search() {
|
||||||
|
|
||||||
return this->rom_number_;
|
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;
|
std::vector<uint64_t> res;
|
||||||
|
|
||||||
this->reset_search();
|
this->reset_search();
|
||||||
|
@ -206,12 +206,12 @@ std::vector<uint64_t> ESPOneWire::search_vec() {
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
void ESPOneWire::skip() {
|
void ICACHE_RAM_ATTR ESPOneWire::skip() {
|
||||||
this->write8(0xCC); // skip ROM
|
this->write8(0xCC); // skip ROM
|
||||||
}
|
}
|
||||||
GPIOPin *ESPOneWire::get_pin() { return this->pin_; }
|
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 dallas
|
||||||
} // namespace esphome
|
} // namespace esphome
|
||||||
|
|
|
@ -71,80 +71,101 @@ void DHT::set_dht_model(DHTModel model) {
|
||||||
this->model_ = model;
|
this->model_ = model;
|
||||||
this->is_auto_detect_ = model == DHT_MODEL_AUTO_DETECT;
|
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;
|
*humidity = NAN;
|
||||||
*temperature = NAN;
|
*temperature = NAN;
|
||||||
|
|
||||||
disable_interrupts();
|
int error_code = 0;
|
||||||
this->pin_->digital_write(false);
|
int8_t i = 0;
|
||||||
this->pin_->pin_mode(OUTPUT);
|
|
||||||
this->pin_->digital_write(false);
|
|
||||||
|
|
||||||
if (this->model_ == DHT_MODEL_DHT11) {
|
|
||||||
delayMicroseconds(18000);
|
|
||||||
} else if (this->model_ == DHT_MODEL_SI7021) {
|
|
||||||
delayMicroseconds(500);
|
|
||||||
this->pin_->digital_write(true);
|
|
||||||
delayMicroseconds(40);
|
|
||||||
} else {
|
|
||||||
delayMicroseconds(800);
|
|
||||||
}
|
|
||||||
this->pin_->pin_mode(INPUT_PULLUP);
|
|
||||||
delayMicroseconds(40);
|
|
||||||
|
|
||||||
uint8_t data[5] = {0, 0, 0, 0, 0};
|
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++) {
|
{
|
||||||
uint32_t start_time = micros();
|
InterruptLock lock;
|
||||||
|
|
||||||
// Wait for rising edge
|
this->pin_->digital_write(false);
|
||||||
while (!this->pin_->digital_read()) {
|
this->pin_->pin_mode(OUTPUT);
|
||||||
if (micros() - start_time > 90) {
|
this->pin_->digital_write(false);
|
||||||
enable_interrupts();
|
|
||||||
if (report_errors) {
|
if (this->model_ == DHT_MODEL_DHT11) {
|
||||||
if (i < 0) {
|
delayMicroseconds(18000);
|
||||||
ESP_LOGW(TAG, "Waiting for DHT communication to clear failed!");
|
} else if (this->model_ == DHT_MODEL_SI7021) {
|
||||||
} else {
|
delayMicroseconds(500);
|
||||||
ESP_LOGW(TAG, "Rising edge for bit %d failed!", i);
|
this->pin_->digital_write(true);
|
||||||
}
|
delayMicroseconds(40);
|
||||||
|
} else {
|
||||||
|
delayMicroseconds(800);
|
||||||
|
}
|
||||||
|
this->pin_->pin_mode(INPUT_PULLUP);
|
||||||
|
delayMicroseconds(40);
|
||||||
|
|
||||||
|
uint8_t bit = 7;
|
||||||
|
uint8_t byte = 0;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (i < 0)
|
||||||
|
error_code = 1;
|
||||||
|
else
|
||||||
|
error_code = 2;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
if (error_code != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
start_time = micros();
|
start_time = micros();
|
||||||
uint32_t end_time = start_time;
|
uint32_t end_time = start_time;
|
||||||
|
|
||||||
// Wait for falling edge
|
// Wait for falling edge
|
||||||
while (this->pin_->digital_read()) {
|
while (this->pin_->digital_read()) {
|
||||||
if ((end_time = micros()) - start_time > 90) {
|
if ((end_time = micros()) - start_time > 90) {
|
||||||
enable_interrupts();
|
if (i < 0)
|
||||||
if (report_errors) {
|
error_code = 3;
|
||||||
if (i < 0) {
|
else
|
||||||
ESP_LOGW(TAG, "Requesting data from DHT failed!");
|
error_code = 4;
|
||||||
} else {
|
break;
|
||||||
ESP_LOGW(TAG, "Falling edge for bit %d failed!", i);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
if (error_code != 0)
|
||||||
|
break;
|
||||||
|
|
||||||
if (i < 0)
|
if (i < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (end_time - start_time >= 40) {
|
if (end_time - start_time >= 40) {
|
||||||
data[byte] |= 1 << bit;
|
data[byte] |= 1 << bit;
|
||||||
|
}
|
||||||
|
if (bit == 0) {
|
||||||
|
bit = 7;
|
||||||
|
byte++;
|
||||||
|
} else
|
||||||
|
bit--;
|
||||||
}
|
}
|
||||||
if (bit == 0) {
|
|
||||||
bit = 7;
|
|
||||||
byte++;
|
|
||||||
} 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,
|
ESP_LOGVV(TAG,
|
||||||
"Data: Hum=0b" BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN
|
"Data: Hum=0b" BYTE_TO_BINARY_PATTERN BYTE_TO_BINARY_PATTERN
|
||||||
|
|
|
@ -42,23 +42,24 @@ bool HX711Sensor::read_sensor_(uint32_t *result) {
|
||||||
this->status_clear_warning();
|
this->status_clear_warning();
|
||||||
uint32_t data = 0;
|
uint32_t data = 0;
|
||||||
|
|
||||||
disable_interrupts();
|
{
|
||||||
for (uint8_t i = 0; i < 24; i++) {
|
InterruptLock lock;
|
||||||
this->sck_pin_->digital_write(true);
|
for (uint8_t i = 0; i < 24; i++) {
|
||||||
delayMicroseconds(1);
|
this->sck_pin_->digital_write(true);
|
||||||
data |= uint32_t(this->dout_pin_->digital_read()) << (23 - i);
|
delayMicroseconds(1);
|
||||||
this->sck_pin_->digital_write(false);
|
data |= uint32_t(this->dout_pin_->digital_read()) << (23 - i);
|
||||||
delayMicroseconds(1);
|
this->sck_pin_->digital_write(false);
|
||||||
}
|
delayMicroseconds(1);
|
||||||
|
}
|
||||||
|
|
||||||
// Cycle clock pin for gain setting
|
// Cycle clock pin for gain setting
|
||||||
for (uint8_t i = 0; i < this->gain_; i++) {
|
for (uint8_t i = 0; i < this->gain_; i++) {
|
||||||
this->sck_pin_->digital_write(true);
|
this->sck_pin_->digital_write(true);
|
||||||
delayMicroseconds(1);
|
delayMicroseconds(1);
|
||||||
this->sck_pin_->digital_write(false);
|
this->sck_pin_->digital_write(false);
|
||||||
delayMicroseconds(1);
|
delayMicroseconds(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
enable_interrupts();
|
|
||||||
|
|
||||||
if (data & 0x800000ULL) {
|
if (data & 0x800000ULL) {
|
||||||
data |= 0xFF000000ULL;
|
data |= 0xFF000000ULL;
|
||||||
|
|
|
@ -67,22 +67,22 @@ void RemoteTransmitterComponent::send_internal(uint32_t send_times, uint32_t sen
|
||||||
uint32_t on_time, off_time;
|
uint32_t on_time, off_time;
|
||||||
this->calculate_on_off_time_(this->temp_.get_carrier_frequency(), &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++) {
|
for (uint32_t i = 0; i < send_times; i++) {
|
||||||
disable_interrupts();
|
{
|
||||||
for (int32_t item : this->temp_.get_data()) {
|
InterruptLock lock;
|
||||||
if (item > 0) {
|
for (int32_t item : this->temp_.get_data()) {
|
||||||
const auto length = uint32_t(item);
|
if (item > 0) {
|
||||||
this->mark_(on_time, off_time, length);
|
const auto length = uint32_t(item);
|
||||||
} else {
|
this->mark_(on_time, off_time, length);
|
||||||
const auto length = uint32_t(-item);
|
} else {
|
||||||
this->space_(length);
|
const auto length = uint32_t(-item);
|
||||||
|
this->space_(length);
|
||||||
|
}
|
||||||
|
App.feed_wdt();
|
||||||
}
|
}
|
||||||
App.feed_wdt();
|
|
||||||
}
|
}
|
||||||
enable_interrupts();
|
|
||||||
|
|
||||||
if (i + 1 < send_times) {
|
if (i + 1 < send_times) {
|
||||||
delay(send_wait / 1000UL);
|
delay_microseconds_accurate(send_wait);
|
||||||
delayMicroseconds(send_wait % 1000UL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -295,24 +295,25 @@ void ICACHE_RAM_ATTR HOT ESP8266SoftwareSerial::write_byte(uint8_t data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
disable_interrupts();
|
{
|
||||||
uint32_t wait = this->bit_time_;
|
InterruptLock lock;
|
||||||
const uint32_t start = ESP.getCycleCount();
|
uint32_t wait = this->bit_time_;
|
||||||
// Start bit
|
const uint32_t start = ESP.getCycleCount();
|
||||||
this->write_bit_(false, &wait, start);
|
// Start bit
|
||||||
this->write_bit_(data & (1 << 0), &wait, start);
|
this->write_bit_(false, &wait, start);
|
||||||
this->write_bit_(data & (1 << 1), &wait, start);
|
this->write_bit_(data & (1 << 0), &wait, start);
|
||||||
this->write_bit_(data & (1 << 2), &wait, start);
|
this->write_bit_(data & (1 << 1), &wait, start);
|
||||||
this->write_bit_(data & (1 << 3), &wait, start);
|
this->write_bit_(data & (1 << 2), &wait, start);
|
||||||
this->write_bit_(data & (1 << 4), &wait, start);
|
this->write_bit_(data & (1 << 3), &wait, start);
|
||||||
this->write_bit_(data & (1 << 5), &wait, start);
|
this->write_bit_(data & (1 << 4), &wait, start);
|
||||||
this->write_bit_(data & (1 << 6), &wait, start);
|
this->write_bit_(data & (1 << 5), &wait, start);
|
||||||
this->write_bit_(data & (1 << 7), &wait, start);
|
this->write_bit_(data & (1 << 6), &wait, start);
|
||||||
// Stop bit
|
this->write_bit_(data & (1 << 7), &wait, start);
|
||||||
this->write_bit_(true, &wait, start);
|
// Stop bit
|
||||||
if (this->stop_bits_ == 2)
|
this->write_bit_(true, &wait, start);
|
||||||
this->wait_(&wait, start);
|
if (this->stop_bits_ == 2)
|
||||||
enable_interrupts();
|
this->wait_(&wait, start);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void ICACHE_RAM_ATTR ESP8266SoftwareSerial::wait_(uint32_t *wait, const uint32_t &start) {
|
void ICACHE_RAM_ATTR ESP8266SoftwareSerial::wait_(uint32_t *wait, const uint32_t &start) {
|
||||||
while (ESP.getCycleCount() - start < *wait)
|
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);
|
this->wait_(wait, start);
|
||||||
return this->rx_pin_->digital_read();
|
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->tx_pin_->digital_write(bit);
|
||||||
this->wait_(wait, start);
|
this->wait_(wait, start);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,16 @@
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/dns.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/helpers.h"
|
||||||
#include "esphome/core/log.h"
|
#include "esphome/core/log.h"
|
||||||
|
@ -74,6 +82,19 @@ bool WiFiComponent::wifi_apply_power_save_() {
|
||||||
}
|
}
|
||||||
return wifi_set_sleep_type(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) {
|
bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||||
// enable STA
|
// enable STA
|
||||||
if (!this->wifi_mode_(true, {}))
|
if (!this->wifi_mode_(true, {}))
|
||||||
|
@ -94,6 +115,13 @@ bool WiFiComponent::wifi_sta_ip_config_(optional<ManualIP> manual_ip) {
|
||||||
|
|
||||||
bool ret = true;
|
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 {};
|
struct ip_info info {};
|
||||||
info.ip.addr = static_cast<uint32_t>(manual_ip->static_ip);
|
info.ip.addr = static_cast<uint32_t>(manual_ip->static_ip);
|
||||||
info.gw.addr = static_cast<uint32_t>(manual_ip->gateway);
|
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);
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,10 +169,31 @@ IPAddress WiFiComponent::wifi_sta_ip_() {
|
||||||
return {ip.ip.addr};
|
return {ip.ip.addr};
|
||||||
}
|
}
|
||||||
bool WiFiComponent::wifi_apply_hostname_() {
|
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) {
|
if (!ret) {
|
||||||
ESP_LOGV(TAG, "Setting WiFi Hostname failed!");
|
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;
|
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-_";
|
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 crc8(uint8_t *data, uint8_t len) {
|
||||||
uint8_t crc = 0;
|
uint8_t crc = 0;
|
||||||
|
|
||||||
|
@ -193,8 +178,8 @@ void delay_microseconds_accurate(uint32_t usec) {
|
||||||
if (usec <= 16383UL) {
|
if (usec <= 16383UL) {
|
||||||
delayMicroseconds(usec);
|
delayMicroseconds(usec);
|
||||||
} else {
|
} else {
|
||||||
delay(usec / 1000UL);
|
delay(usec / 16383UL);
|
||||||
delayMicroseconds(usec % 1000UL);
|
delayMicroseconds(usec % 16383UL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -330,4 +315,13 @@ std::string hexencode(const uint8_t *data, uint32_t len) {
|
||||||
return res;
|
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
|
} // 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.
|
/// 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);
|
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.
|
protected:
|
||||||
void enable_interrupts();
|
#ifdef ARDUINO_ARCH_ESP8266
|
||||||
|
uint32_t xt_state_;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
/// Calculate a crc8 of data with the provided data length.
|
/// Calculate a crc8 of data with the provided data length.
|
||||||
uint8_t crc8(uint8_t *data, uint8_t len);
|
uint8_t crc8(uint8_t *data, uint8_t len);
|
||||||
|
|
|
@ -105,16 +105,18 @@ void ESPPreferences::save_esp8266_flash_() {
|
||||||
return;
|
return;
|
||||||
|
|
||||||
ESP_LOGVV(TAG, "Saving preferences to flash...");
|
ESP_LOGVV(TAG, "Saving preferences to flash...");
|
||||||
disable_interrupts();
|
SpiFlashOpResult erase_res, write_res = SPI_FLASH_RESULT_OK;
|
||||||
auto erase_res = spi_flash_erase_sector(get_esp8266_flash_sector());
|
{
|
||||||
|
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) {
|
if (erase_res != SPI_FLASH_RESULT_OK) {
|
||||||
enable_interrupts();
|
|
||||||
ESP_LOGV(TAG, "Erase ESP8266 flash failed!");
|
ESP_LOGV(TAG, "Erase ESP8266 flash failed!");
|
||||||
return;
|
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) {
|
if (write_res != SPI_FLASH_RESULT_OK) {
|
||||||
ESP_LOGV(TAG, "Write ESP8266 flash failed!");
|
ESP_LOGV(TAG, "Write ESP8266 flash failed!");
|
||||||
return;
|
return;
|
||||||
|
@ -173,9 +175,11 @@ ESPPreferences::ESPPreferences()
|
||||||
void ESPPreferences::begin() {
|
void ESPPreferences::begin() {
|
||||||
this->flash_storage_ = new uint32_t[ESP8266_FLASH_STORAGE_SIZE];
|
this->flash_storage_ = new uint32_t[ESP8266_FLASH_STORAGE_SIZE];
|
||||||
ESP_LOGVV(TAG, "Loading preferences from flash...");
|
ESP_LOGVV(TAG, "Loading preferences from flash...");
|
||||||
disable_interrupts();
|
|
||||||
spi_flash_read(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
{
|
||||||
enable_interrupts();
|
InterruptLock lock;
|
||||||
|
spi_flash_read(get_esp8266_flash_address(), this->flash_storage_, ESP8266_FLASH_STORAGE_SIZE * 4);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type, bool in_flash) {
|
ESPPreferenceObject ESPPreferences::make_preference(size_t length, uint32_t type, bool in_flash) {
|
||||||
|
|
|
@ -60,6 +60,7 @@ FILTER_PLATFORMIO_LINES = [
|
||||||
r"Using cache: .*",
|
r"Using cache: .*",
|
||||||
r'Installing dependencies',
|
r'Installing dependencies',
|
||||||
r'.* @ .* is already installed',
|
r'.* @ .* is already installed',
|
||||||
|
r'Building in .* mode',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue