Skip to content

Commit 3110fad

Browse files
committed
uart: support begin and end methods.
A component may need to reset uart buffer/status by using begin() and end() methods. This is useful for example when a component needs to be sure it is not reading garbage from previously received data over uart. For end() methods with software serial, disabling interrupt is currently impossible because of a bug in esp8266 Core: esp8266/Arduino#6049 Signed-off-by: 0hax <[email protected]>
1 parent 64f6c9d commit 3110fad

File tree

2 files changed

+41
-1
lines changed

2 files changed

+41
-1
lines changed

esphome/components/uart/uart.cpp

+32-1
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ void UARTComponent::write_str(const char *str) {
121121
this->hw_serial_->write(str);
122122
ESP_LOGVV(TAG, " Wrote \"%s\"", str);
123123
}
124+
void UARTComponent::end() { this->hw_serial_->end(); }
125+
void UARTComponent::begin() { this->hw_serial_->begin(this->baud_rate_, get_config()); }
124126
bool UARTComponent::read_byte(uint8_t *data) {
125127
if (!this->check_read_timeout_())
126128
return false;
@@ -272,6 +274,18 @@ void UARTComponent::write_str(const char *str) {
272274
}
273275
ESP_LOGVV(TAG, " Wrote \"%s\"", str);
274276
}
277+
void UARTComponent::end() {
278+
if (this->hw_serial_ != nullptr)
279+
this->hw_serial_->end();
280+
else if (this->sw_serial_ != nullptr)
281+
this->sw_serial_->end();
282+
}
283+
void UARTComponent::begin() {
284+
if (this->hw_serial_ != nullptr)
285+
this->hw_serial_->begin(this->baud_rate_, static_cast<SerialConfig>(get_config()));
286+
else if (this->sw_serial_ != nullptr)
287+
this->sw_serial_->begin();
288+
}
275289
bool UARTComponent::read_byte(uint8_t *data) {
276290
if (!this->check_read_timeout_())
277291
return false;
@@ -337,7 +351,22 @@ void UARTComponent::flush() {
337351
this->sw_serial_->flush();
338352
}
339353
}
340-
354+
void ESP8266SoftwareSerial::end() {
355+
/* Because of this bug: https://github.com/esp8266/Arduino/issues/6049
356+
* detach_interrupt can't called.
357+
* So simply reset rx_in_pos and rx_out_pos even if it's totally racy with
358+
* the interrupt.
359+
*/
360+
// this->gpio_rx_pin_->detach_interrupt();
361+
this->rx_in_pos_ = 0;
362+
this->rx_out_pos_ = 0;
363+
}
364+
void ESP8266SoftwareSerial::begin() {
365+
/* attach_interrupt() is also not safe because gpio_intr() may
366+
* endup with arg == nullptr.
367+
*/
368+
// this->gpio_rx_pin_->attach_interrupt(ESP8266SoftwareSerial::gpio_intr, this, FALLING);
369+
}
341370
void ESP8266SoftwareSerial::setup(int8_t tx_pin, int8_t rx_pin, uint32_t baud_rate, uint8_t stop_bits, uint32_t nr_bits,
342371
std::string &parity) {
343372
this->bit_time_ = F_CPU / baud_rate;
@@ -346,13 +375,15 @@ void ESP8266SoftwareSerial::setup(int8_t tx_pin, int8_t rx_pin, uint32_t baud_ra
346375
this->parity_ = parity;
347376
if (tx_pin != -1) {
348377
auto pin = GPIOPin(tx_pin, OUTPUT);
378+
this->gpio_tx_pin_ = &pin;
349379
pin.setup();
350380
this->tx_pin_ = pin.to_isr();
351381
this->tx_pin_->digital_write(true);
352382
}
353383
if (rx_pin != -1) {
354384
auto pin = GPIOPin(rx_pin, INPUT);
355385
pin.setup();
386+
this->gpio_rx_pin_ = &pin;
356387
this->rx_pin_ = pin.to_isr();
357388
this->rx_buffer_ = new uint8_t[this->rx_buffer_size_];
358389
pin.attach_interrupt(ESP8266SoftwareSerial::gpio_intr, this, FALLING);

esphome/components/uart/uart.h

+9
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,11 @@ class ESP8266SoftwareSerial {
2222

2323
int available();
2424

25+
void begin();
26+
void end();
27+
GPIOPin *gpio_tx_pin_{nullptr};
28+
GPIOPin *gpio_rx_pin_{nullptr};
29+
2530
protected:
2631
static void gpio_intr(ESP8266SoftwareSerial *arg);
2732

@@ -58,6 +63,8 @@ class UARTComponent : public Component, public Stream {
5863
void write_array(const std::vector<uint8_t> &data) { this->write_array(&data[0], data.size()); }
5964

6065
void write_str(const char *str);
66+
void end();
67+
void begin();
6168

6269
bool peek_byte(uint8_t *data);
6370

@@ -139,6 +146,8 @@ class UARTDevice : public Stream {
139146
size_t write(uint8_t data) override { return this->parent_->write(data); }
140147
int read() override { return this->parent_->read(); }
141148
int peek() override { return this->parent_->peek(); }
149+
void end() { this->parent_->end(); }
150+
void begin() { this->parent_->begin(); }
142151

143152
/// Check that the configuration of the UART bus matches the provided values and otherwise print a warning
144153
void check_uart_settings(uint32_t baud_rate, uint8_t stop_bits = 1);

0 commit comments

Comments
 (0)