Merge pull request #6539 from s-hadinger/serial_iarm_send

Fix TasmotaSerial: move serial send to IRAM for high speed baud rates
This commit is contained in:
Theo Arends 2019-10-02 17:34:02 +02:00 committed by GitHub
commit 51076d02d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 51 additions and 19 deletions

View File

@ -1,6 +1,6 @@
{ {
"name": "TasmotaSerial", "name": "TasmotaSerial",
"version": "2.4.0", "version": "2.4.1",
"keywords": [ "keywords": [
"serial", "io", "TasmotaSerial" "serial", "io", "TasmotaSerial"
], ],

View File

@ -1,5 +1,5 @@
name=TasmotaSerial name=TasmotaSerial
version=2.4.0 version=2.4.1
author=Theo Arends author=Theo Arends
maintainer=Theo Arends <theo@arends.com> maintainer=Theo Arends <theo@arends.com>
sentence=Implementation of software serial with hardware serial fallback for ESP8266. sentence=Implementation of software serial with hardware serial fallback for ESP8266.

View File

@ -213,39 +213,68 @@ int TasmotaSerial::available()
#ifdef TM_SERIAL_USE_IRAM #ifdef TM_SERIAL_USE_IRAM
#define TM_SERIAL_WAIT_SND { while (ESP.getCycleCount() < (wait + start)) if (!m_high_speed) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts #define TM_SERIAL_WAIT_SND { while (ESP.getCycleCount() < (wait + start)) if (!m_high_speed) optimistic_yield(1); wait += m_bit_time; } // Watchdog timeouts
#define TM_SERIAL_WAIT_SND_FAST { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; }
#define TM_SERIAL_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; }
#define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); } #define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); }
#else #else
#define TM_SERIAL_WAIT_SND { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_SND { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; }
#define TM_SERIAL_WAIT_SND_FAST { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; }
#define TM_SERIAL_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; } #define TM_SERIAL_WAIT_RCV { while (ESP.getCycleCount() < (wait + start)); wait += m_bit_time; }
#define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); } #define TM_SERIAL_WAIT_RCV_LOOP { while (ESP.getCycleCount() < (wait + start)); }
#endif #endif
#ifdef TM_SERIAL_USE_IRAM
void ICACHE_RAM_ATTR TasmotaSerial::_fast_write(uint8_t b) {
#else
void TasmotaSerial::_fast_write(uint8_t b) {
#endif
uint32_t wait = m_bit_time;
uint32_t start = ESP.getCycleCount();
// Start bit;
digitalWrite(m_tx_pin, LOW);
TM_SERIAL_WAIT_SND_FAST;
for (uint32_t i = 0; i < 8; i++) {
digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW);
TM_SERIAL_WAIT_SND_FAST;
b >>= 1;
}
// Stop bit(s)
digitalWrite(m_tx_pin, HIGH);
for (uint32_t i = 0; i < m_stop_bits; i++) {
TM_SERIAL_WAIT_SND_FAST;
}
}
size_t TasmotaSerial::write(uint8_t b) size_t TasmotaSerial::write(uint8_t b)
{ {
if (m_hardserial) { if (m_hardserial) {
return Serial.write(b); return Serial.write(b);
} else { } else {
if (-1 == m_tx_pin) return 0; if (-1 == m_tx_pin) return 0;
if (m_high_speed) cli(); // Disable interrupts in order to get a clean transmit if (m_high_speed) {
uint32_t wait = m_bit_time; cli(); // Disable interrupts in order to get a clean transmit
//digitalWrite(m_tx_pin, HIGH); // already in HIGH mode _fast_write(b);
uint32_t start = ESP.getCycleCount(); sei();
// Start bit; } else {
digitalWrite(m_tx_pin, LOW); uint32_t wait = m_bit_time;
TM_SERIAL_WAIT_SND; //digitalWrite(m_tx_pin, HIGH); // already in HIGH mode
for (uint32_t i = 0; i < 8; i++) { uint32_t start = ESP.getCycleCount();
digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW); // Start bit;
TM_SERIAL_WAIT_SND; digitalWrite(m_tx_pin, LOW);
b >>= 1;
}
// Stop bit(s)
digitalWrite(m_tx_pin, HIGH);
// re-enable interrupts during stop bits, it's not an issue if they are longer than expected
if (m_high_speed) sei();
for (uint32_t i = 0; i < m_stop_bits; i++) {
TM_SERIAL_WAIT_SND; TM_SERIAL_WAIT_SND;
for (uint32_t i = 0; i < 8; i++) {
digitalWrite(m_tx_pin, (b & 1) ? HIGH : LOW);
TM_SERIAL_WAIT_SND;
b >>= 1;
}
// Stop bit(s)
digitalWrite(m_tx_pin, HIGH);
// re-enable interrupts during stop bits, it's not an issue if they are longer than expected
for (uint32_t i = 0; i < m_stop_bits; i++) {
TM_SERIAL_WAIT_SND;
}
} }
return 1; return 1;
} }
} }

View File

@ -81,6 +81,8 @@ class TasmotaSerial : public Stream {
bool m_high_speed = false; bool m_high_speed = false;
bool m_very_high_speed = false; // above 100000 bauds bool m_very_high_speed = false; // above 100000 bauds
uint8_t *m_buffer; uint8_t *m_buffer;
void _fast_write(uint8_t b); // IRAM minimized version
}; };
#endif // TasmotaSerial_h #endif // TasmotaSerial_h

View File

@ -11,6 +11,7 @@
* Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547) * Change command SetOption43 to make it more general. Now supports PS_16_DZ driver too (#6547)
* Change command handling by moving buffers up in chain solving MQTTlog support (#6524) * Change command handling by moving buffers up in chain solving MQTTlog support (#6524)
* Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540) * Change detection of non-MQTT commands by allowing non-space characters as delimiter (#6540)
* Fix TasmotaSerial: move serial send to IRAM for high speed baud rates
* *
* 6.6.0.13 20190922 * 6.6.0.13 20190922
* Add command EnergyReset4 x,x to initialize total usage for two tarrifs * Add command EnergyReset4 x,x to initialize total usage for two tarrifs