Skip to content

Commit 0a1dbe6

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 3ec31c9 commit 0a1dbe6

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

esphome/components/uart/uart.cpp

+29-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;
@@ -273,6 +275,18 @@ void UARTComponent::write_str(const char *str) {
273275
}
274276
ESP_LOGVV(TAG, " Wrote \"%s\"", str);
275277
}
278+
void UARTComponent::end() {
279+
if (this->hw_serial_ != nullptr)
280+
this->hw_serial_->end();
281+
else if (this->sw_serial_ != nullptr)
282+
this->sw_serial_->end();
283+
}
284+
void UARTComponent::begin() {
285+
if (this->hw_serial_ != nullptr)
286+
this->hw_serial_->begin(this->baud_rate_, static_cast<SerialConfig>(get_config()));
287+
else if (this->sw_serial_ != nullptr)
288+
this->sw_serial_->begin();
289+
}
276290
bool UARTComponent::read_byte(uint8_t *data) {
277291
if (!this->check_read_timeout_())
278292
return false;
@@ -338,19 +352,33 @@ void UARTComponent::flush() {
338352
this->sw_serial_->flush();
339353
}
340354
}
341-
355+
void ESP8266SoftwareSerial::end() {
356+
/* Because of this bug: https://github.com/esp8266/Arduino/issues/6049
357+
* detach_interrupt can't called.
358+
* So simply reset rx_in_pos and rx_out_pos even if it's totally racy with
359+
* the interrupt.
360+
*/
361+
// this->gpio_rx_pin_->detach_interrupt();
362+
this->rx_in_pos_ = 0;
363+
this->rx_out_pos_ = 0;
364+
}
365+
void ESP8266SoftwareSerial::begin() {
366+
this->gpio_rx_pin_->attach_interrupt(ESP8266SoftwareSerial::gpio_intr, this, FALLING);
367+
}
342368
void ESP8266SoftwareSerial::setup(int8_t tx_pin, int8_t rx_pin, uint32_t baud_rate, uint8_t stop_bits, uint32_t nr_bits,
343369
std::string &parity) {
344370
this->bit_time_ = F_CPU / baud_rate;
345371
if (tx_pin != -1) {
346372
auto pin = GPIOPin(tx_pin, OUTPUT);
373+
this->gpio_tx_pin_ = &pin;
347374
pin.setup();
348375
this->tx_pin_ = pin.to_isr();
349376
this->tx_pin_->digital_write(true);
350377
}
351378
if (rx_pin != -1) {
352379
auto pin = GPIOPin(rx_pin, INPUT);
353380
pin.setup();
381+
this->gpio_rx_pin_ = &pin;
354382
this->rx_pin_ = pin.to_isr();
355383
this->rx_buffer_ = new uint8_t[this->rx_buffer_size_];
356384
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)