ESPHome 2025.10.3
Loading...
Searching...
No Matches
uart_component_rp2040.cpp
Go to the documentation of this file.
1#ifdef USE_RP2040
6#include "esphome/core/log.h"
7
8#include <hardware/uart.h>
9
10#ifdef USE_LOGGER
12#endif
13
14namespace esphome {
15namespace uart {
16
17static const char *const TAG = "uart.arduino_rp2040";
18
20 uint16_t config = 0;
21
22 if (this->parity_ == UART_CONFIG_PARITY_NONE) {
23 config |= UART_PARITY_NONE;
24 } else if (this->parity_ == UART_CONFIG_PARITY_EVEN) {
25 config |= UART_PARITY_EVEN;
26 } else if (this->parity_ == UART_CONFIG_PARITY_ODD) {
27 config |= UART_PARITY_ODD;
28 }
29
30 switch (this->data_bits_) {
31 case 5:
32 config |= SERIAL_DATA_5;
33 break;
34 case 6:
35 config |= SERIAL_DATA_6;
36 break;
37 case 7:
38 config |= SERIAL_DATA_7;
39 break;
40 case 8:
41 config |= SERIAL_DATA_8;
42 break;
43 }
44
45 if (this->stop_bits_ == 1) {
46 config |= SERIAL_STOP_BIT_1;
47 } else {
48 config |= SERIAL_STOP_BIT_2;
49 }
50
51 return config;
52}
53
55 if (this->rx_pin_) {
56 this->rx_pin_->setup();
57 }
58 if (this->tx_pin_ && this->rx_pin_ != this->tx_pin_) {
59 this->tx_pin_->setup();
60 }
61
62 uint16_t config = get_config();
63
64 constexpr uint32_t valid_tx_uart_0 = __bitset({0, 12, 16, 28});
65 constexpr uint32_t valid_tx_uart_1 = __bitset({4, 8, 20, 24});
66
67 constexpr uint32_t valid_rx_uart_0 = __bitset({1, 13, 17, 29});
68 constexpr uint32_t valid_rx_uart_1 = __bitset({5, 9, 21, 25});
69
70 int8_t tx_hw = -1;
71 int8_t rx_hw = -1;
72
73 if (this->tx_pin_ != nullptr) {
74 if (this->tx_pin_->is_inverted()) {
75 ESP_LOGD(TAG, "An inverted TX pin %u can only be used with SerialPIO", this->tx_pin_->get_pin());
76 } else {
77 if (((1 << this->tx_pin_->get_pin()) & valid_tx_uart_0) != 0) {
78 tx_hw = 0;
79 } else if (((1 << this->tx_pin_->get_pin()) & valid_tx_uart_1) != 0) {
80 tx_hw = 1;
81 } else {
82 ESP_LOGD(TAG, "TX pin %u can only be used with SerialPIO", this->tx_pin_->get_pin());
83 }
84 }
85 }
86
87 if (this->rx_pin_ != nullptr) {
88 if (this->rx_pin_->is_inverted()) {
89 ESP_LOGD(TAG, "An inverted RX pin %u can only be used with SerialPIO", this->rx_pin_->get_pin());
90 } else {
91 if (((1 << this->rx_pin_->get_pin()) & valid_rx_uart_0) != 0) {
92 rx_hw = 0;
93 } else if (((1 << this->rx_pin_->get_pin()) & valid_rx_uart_1) != 0) {
94 rx_hw = 1;
95 } else {
96 ESP_LOGD(TAG, "RX pin %u can only be used with SerialPIO", this->rx_pin_->get_pin());
97 }
98 }
99 }
100
101#ifdef USE_LOGGER
102 if (tx_hw == rx_hw && logger::global_logger->get_uart() == tx_hw) {
103 ESP_LOGD(TAG, "Using SerialPIO as UART%d is taken by the logger", tx_hw);
104 tx_hw = -1;
105 rx_hw = -1;
106 }
107#endif
108
109 if (tx_hw == -1 || rx_hw == -1 || tx_hw != rx_hw) {
110 ESP_LOGV(TAG, "Using SerialPIO");
111 pin_size_t tx = this->tx_pin_ == nullptr ? SerialPIO::NOPIN : this->tx_pin_->get_pin();
112 pin_size_t rx = this->rx_pin_ == nullptr ? SerialPIO::NOPIN : this->rx_pin_->get_pin();
113 auto *serial = new SerialPIO(tx, rx, this->rx_buffer_size_); // NOLINT(cppcoreguidelines-owning-memory)
114 serial->begin(this->baud_rate_, config);
115 if (this->tx_pin_ != nullptr && this->tx_pin_->is_inverted())
116 gpio_set_outover(tx, GPIO_OVERRIDE_INVERT);
117 if (this->rx_pin_ != nullptr && this->rx_pin_->is_inverted())
118 gpio_set_inover(rx, GPIO_OVERRIDE_INVERT);
119 this->serial_ = serial;
120 } else {
121 ESP_LOGV(TAG, "Using Hardware Serial");
122 SerialUART *serial;
123 if (tx_hw == 0) {
124 serial = &Serial1;
125 } else {
126 serial = &Serial2;
127 }
128 serial->setTX(this->tx_pin_->get_pin());
129 serial->setRX(this->rx_pin_->get_pin());
130 serial->setFIFOSize(this->rx_buffer_size_);
131 serial->begin(this->baud_rate_, config);
132 this->serial_ = serial;
133 this->hw_serial_ = true;
134 }
135}
136
138 ESP_LOGCONFIG(TAG, "UART Bus:");
139 LOG_PIN(" TX Pin: ", tx_pin_);
140 LOG_PIN(" RX Pin: ", rx_pin_);
141 if (this->rx_pin_ != nullptr) {
142 ESP_LOGCONFIG(TAG, " RX Buffer Size: %u", this->rx_buffer_size_);
143 }
144 ESP_LOGCONFIG(TAG,
145 " Baud Rate: %u baud\n"
146 " Data Bits: %u\n"
147 " Parity: %s\n"
148 " Stop bits: %u",
149 this->baud_rate_, this->data_bits_, LOG_STR_ARG(parity_to_str(this->parity_)), this->stop_bits_);
150 if (this->hw_serial_) {
151 ESP_LOGCONFIG(TAG, " Using hardware serial");
152 } else {
153 ESP_LOGCONFIG(TAG, " Using SerialPIO");
154 }
155}
156
157void RP2040UartComponent::write_array(const uint8_t *data, size_t len) {
158 this->serial_->write(data, len);
159#ifdef USE_UART_DEBUGGER
160 for (size_t i = 0; i < len; i++) {
161 this->debug_callback_.call(UART_DIRECTION_TX, data[i]);
162 }
163#endif
164}
166 if (!this->check_read_timeout_())
167 return false;
168 *data = this->serial_->peek();
169 return true;
170}
171bool RP2040UartComponent::read_array(uint8_t *data, size_t len) {
172 if (!this->check_read_timeout_(len))
173 return false;
174 this->serial_->readBytes(data, len);
175#ifdef USE_UART_DEBUGGER
176 for (size_t i = 0; i < len; i++) {
177 this->debug_callback_.call(UART_DIRECTION_RX, data[i]);
178 }
179#endif
180 return true;
181}
182int RP2040UartComponent::available() { return this->serial_->available(); }
184 ESP_LOGVV(TAG, " Flushing");
185 this->serial_->flush();
186}
187
188} // namespace uart
189} // namespace esphome
190
191#endif // USE_RP2040
virtual void setup()=0
virtual uint8_t get_pin() const =0
virtual bool is_inverted() const =0
bool read_array(uint8_t *data, size_t len) override
void write_array(const uint8_t *data, size_t len) override
bool check_read_timeout_(size_t len=1)
CallbackManager< void(UARTDirection, uint8_t)> debug_callback_
Logger * global_logger
Definition logger.cpp:294
const char *const TAG
Definition spi.cpp:8
const LogString * parity_to_str(UARTParityOptions parity)
Definition uart.cpp:33
Providing packet encoding functions for exchanging data with a remote host.
Definition a01nyub.cpp:7
std::string size_t len
Definition helpers.h:304