libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
LibXR::ESP32UART Class Reference
Inheritance diagram for LibXR::ESP32UART:
[legend]
Collaboration diagram for LibXR::ESP32UART:
[legend]

Public Member Functions

 ESP32UART (uart_port_t uart_num, int tx_pin, int rx_pin, int rts_pin=PIN_NO_CHANGE, int cts_pin=PIN_NO_CHANGE, size_t rx_buffer_size=1024, size_t tx_buffer_size=512, uint32_t tx_queue_size=5, UART::Configuration config={115200, UART::Parity::NO_PARITY, 8, 1}, bool enable_dma=true)
 
ErrorCode SetConfig (UART::Configuration config) override
 设置 UART 配置 / Sets the UART configuration
 
ErrorCode SetLoopback (bool enable)
 
- Public Member Functions inherited from LibXR::UART
template<typename ReadPortType = ReadPort, typename WritePortType = WritePort>
 UART (ReadPortType *read_port, WritePortType *write_port)
 UART 构造函数 / UART constructor.
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< WriteOperation, std::decay_t<OperationType>>>>
ErrorCode Write (ConstRawData data, OperationType &&op, bool in_isr=false)
 
template<typename OperationType , typename = std::enable_if_t<std::is_base_of_v< ReadOperation, std::decay_t<OperationType>>>>
ErrorCode Read (RawData data, OperationType &&op, bool in_isr=false)
 

Static Public Member Functions

static ErrorCode WriteFun (WritePort &port, bool in_isr)
 
static ErrorCode ReadFun (ReadPort &port, bool in_isr)
 

Static Public Attributes

static constexpr int PIN_NO_CHANGE = -1
 

Private Member Functions

ErrorCode InitUartHardware ()
 
ErrorCode ConfigurePins ()
 
ErrorCode InstallUartIsr ()
 
void ConfigureRxInterruptPath ()
 
ErrorCode TryStartTx (bool in_isr)
 
bool LoadActiveTxFromQueue (bool in_isr)
 
bool LoadPendingTxFromQueue (bool in_isr)
 
bool DequeueTxToBuffer (uint8_t *buffer, size_t &size, WriteInfoBlock &info, bool in_isr)
 
bool StartActiveTransfer (bool in_isr)
 
bool StartAndReportActive (bool in_isr)
 
void ClearActiveTx ()
 
void ClearPendingTx ()
 
void FillTxFifo (bool in_isr)
 
void PushRxBytes (const uint8_t *data, size_t size, bool in_isr)
 
void DrainRxFifoFromIsr ()
 
void HandleRxInterrupt (uint32_t uart_intr_status)
 
void HandleTxInterrupt (uint32_t uart_intr_status)
 
void HandleUartInterrupt ()
 
void OnTxTransferDone (bool in_isr, ErrorCode result)
 

Static Private Member Functions

static uint8_t * AllocateTxStorage (size_t size)
 
static ErrorCode ResolveUartPeriph (uart_port_t uart_num, periph_module_t &out)
 
static bool ResolveWordLength (uint8_t data_bits, uart_word_length_t &out)
 
static bool ResolveStopBits (uint8_t stop_bits, uart_stop_bits_t &out)
 
static uart_parity_t ResolveParity (UART::Parity parity)
 
static void UartIsrEntry (void *arg)
 

Private Attributes

uart_port_t uart_num_
 
int tx_pin_
 
int rx_pin_
 
int rts_pin_
 
int cts_pin_
 
UART::Configuration config_
 
uint8_t * rx_isr_buffer_ = nullptr
 
size_t rx_isr_buffer_size_ = 0
 
uint8_t * tx_storage_ = nullptr
 
size_t tx_storage_size_ = 0
 
size_t tx_buffer_size_ = 0
 
uint8_t * tx_active_buffer_ = nullptr
 
uint8_t * tx_pending_buffer_ = nullptr
 
size_t tx_active_length_ = 0
 
size_t tx_pending_length_ = 0
 
size_t tx_active_offset_ = 0
 
WriteInfoBlock tx_active_info_ = {}
 
WriteInfoBlock tx_pending_info_ = {}
 
Flag::Plain tx_busy_
 
Flag::Plain in_tx_isr_
 
bool tx_active_valid_ = false
 
bool tx_pending_valid_ = false
 
bool uart_hw_enabled_ = false
 
uart_hal_context_t uart_hal_ = {}
 
intr_handle_t uart_intr_handle_ = nullptr
 
bool uart_isr_installed_ = false
 
bool dma_requested_ = true
 
ReadPort _read_port
 
WritePort _write_port
 

Additional Inherited Members

- Public Types inherited from LibXR::UART
enum class  Parity : uint8_t { NO_PARITY = 0 , EVEN = 1 , ODD = 2 }
 奇偶校验模式 / Parity mode More...
 
- Data Fields inherited from LibXR::UART
ReadPortread_port_
 读取端口 / Read port
 
WritePortwrite_port_
 写入端口 / Write port
 

Detailed Description

Definition at line 27 of file esp_uart.hpp.

Constructor & Destructor Documentation

◆ ESP32UART()

LibXR::ESP32UART::ESP32UART ( uart_port_t uart_num,
int tx_pin,
int rx_pin,
int rts_pin = PIN_NO_CHANGE,
int cts_pin = PIN_NO_CHANGE,
size_t rx_buffer_size = 1024,
size_t tx_buffer_size = 512,
uint32_t tx_queue_size = 5,
UART::Configuration config = {115200, UART::Parity::NO_PARITY, 8, 1},
bool enable_dma = true )

Definition at line 73 of file esp_uart.cpp.

76 : UART(&_read_port, &_write_port),
77 uart_num_(uart_num),
78 tx_pin_(tx_pin),
79 rx_pin_(rx_pin),
80 rts_pin_(rts_pin),
81 cts_pin_(cts_pin),
82 config_(config),
83 rx_isr_buffer_(new (std::nothrow) uint8_t[rx_buffer_size]),
84 rx_isr_buffer_size_(rx_buffer_size),
85 tx_storage_(AllocateTxStorage(tx_buffer_size * 2)),
86 tx_storage_size_(tx_buffer_size * 2),
87 tx_buffer_size_(tx_buffer_size),
88 dma_requested_(enable_dma),
89 _read_port(rx_buffer_size),
90 _write_port(tx_queue_size, tx_buffer_size)
91{
92 ASSERT(!IsConsoleUartInUse(uart_num_));
93 ASSERT(uart_num_ < UART_NUM_MAX);
94 ASSERT(uart_num_ < SOC_UART_HP_NUM);
95 ASSERT(rx_isr_buffer_size_ > 0);
96 ASSERT(tx_buffer_size_ > 0);
97 ASSERT(rx_isr_buffer_ != nullptr);
98 ASSERT(tx_storage_ != nullptr);
99 ASSERT(tx_storage_size_ >= (tx_buffer_size_ * 2U));
100
101 tx_active_buffer_ = tx_storage_;
102 tx_pending_buffer_ = tx_storage_ + tx_buffer_size_;
103 tx_active_length_ = 0;
104 tx_pending_length_ = 0;
105
106 _read_port = ReadFun;
107 _write_port = WriteFun;
108
109 if (InitUartHardware() != ErrorCode::OK)
110 {
111 ASSERT(false);
112 return;
113 }
114
115#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
116 if (dma_requested_)
117 {
118 if (InitDmaBackend() != ErrorCode::OK)
119 {
120 ASSERT(false);
121 return;
122 }
123 }
124
125 if (!dma_backend_enabled_)
126 {
127 if (InstallUartIsr() != ErrorCode::OK)
128 {
129 ASSERT(false);
130 return;
131 }
132 ConfigureRxInterruptPath();
133 }
134#else
135 if (InstallUartIsr() != ErrorCode::OK)
136 {
137 ASSERT(false);
138 return;
139 }
140 ConfigureRxInterruptPath();
141#endif
142}
UART(ReadPortType *read_port, WritePortType *write_port)
UART 构造函数 / UART constructor.
Definition uart.hpp:66
@ OK
操作成功 | Operation successful
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
Definition libxr_rw.hpp:356
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
Definition libxr_rw.hpp:352

Member Function Documentation

◆ AllocateTxStorage()

uint8_t * LibXR::ESP32UART::AllocateTxStorage ( size_t size)
staticprivate

Definition at line 40 of file esp_uart.cpp.

41{
42 void* aligned = heap_caps_aligned_alloc(
43 4, size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT);
44 if (aligned != nullptr)
45 {
46 return static_cast<uint8_t*>(aligned);
47 }
48
49 return static_cast<uint8_t*>(
50 heap_caps_malloc(size, MALLOC_CAP_INTERNAL | MALLOC_CAP_DMA | MALLOC_CAP_8BIT));
51}

◆ ClearActiveTx()

void IRAM_ATTR LibXR::ESP32UART::ClearActiveTx ( )
private

Definition at line 402 of file esp_uart.cpp.

403{
404 tx_active_length_ = 0;
405 tx_active_offset_ = 0;
406 tx_active_info_ = {};
407 tx_active_valid_ = false;
408}

◆ ClearPendingTx()

void IRAM_ATTR LibXR::ESP32UART::ClearPendingTx ( )
private

Definition at line 410 of file esp_uart.cpp.

411{
412 tx_pending_length_ = 0;
413 tx_pending_info_ = {};
414 tx_pending_valid_ = false;
415}

◆ ConfigurePins()

ErrorCode LibXR::ESP32UART::ConfigurePins ( )
private

Definition at line 352 of file esp_uart.cpp.

353{
354 if (tx_pin_ >= 0)
355 {
356 if (!GPIO_IS_VALID_OUTPUT_GPIO(tx_pin_))
357 {
358 return ErrorCode::ARG_ERR;
359 }
360 esp_rom_gpio_pad_select_gpio(static_cast<uint32_t>(tx_pin_));
361 esp_rom_gpio_connect_out_signal(
362 tx_pin_, UART_PERIPH_SIGNAL(uart_num_, SOC_UART_TX_PIN_IDX), false, false);
363 }
364
365 if (rx_pin_ >= 0)
366 {
367 if (!GPIO_IS_VALID_GPIO(rx_pin_))
368 {
369 return ErrorCode::ARG_ERR;
370 }
371 gpio_input_enable(static_cast<gpio_num_t>(rx_pin_));
372 esp_rom_gpio_connect_in_signal(
373 rx_pin_, UART_PERIPH_SIGNAL(uart_num_, SOC_UART_RX_PIN_IDX), false);
374 }
375
376 if (rts_pin_ >= 0)
377 {
378 if (!GPIO_IS_VALID_OUTPUT_GPIO(rts_pin_))
379 {
380 return ErrorCode::ARG_ERR;
381 }
382 esp_rom_gpio_pad_select_gpio(static_cast<uint32_t>(rts_pin_));
383 esp_rom_gpio_connect_out_signal(
384 rts_pin_, UART_PERIPH_SIGNAL(uart_num_, SOC_UART_RTS_PIN_IDX), false, false);
385 }
386
387 if (cts_pin_ >= 0)
388 {
389 if (!GPIO_IS_VALID_GPIO(cts_pin_))
390 {
391 return ErrorCode::ARG_ERR;
392 }
393 gpio_pullup_en(static_cast<gpio_num_t>(cts_pin_));
394 gpio_input_enable(static_cast<gpio_num_t>(cts_pin_));
395 esp_rom_gpio_connect_in_signal(
396 cts_pin_, UART_PERIPH_SIGNAL(uart_num_, SOC_UART_CTS_PIN_IDX), false);
397 }
398
399 return ErrorCode::OK;
400}
@ ARG_ERR
参数错误 | Argument error

◆ ConfigureRxInterruptPath()

void LibXR::ESP32UART::ConfigureRxInterruptPath ( )
private

Definition at line 144 of file esp_uart.cpp.

145{
146 const size_t rx_full_floor = 16;
147 const size_t rx_full_ceil = std::max<size_t>(rx_full_floor, SOC_UART_FIFO_LEN / 4);
148 const uint16_t full_thr = static_cast<uint16_t>(std::min<size_t>(
149 rx_full_ceil, std::max<size_t>(rx_full_floor, rx_isr_buffer_size_ / 16)));
150
151 uart_hal_set_rxfifo_full_thr(&uart_hal_, full_thr);
152 uart_hal_set_rx_timeout(&uart_hal_, kRxToutThreshold);
153 uart_hal_clr_intsts_mask(&uart_hal_, kUartRxIntrMask);
154 uart_hal_ena_intr_mask(&uart_hal_, kUartRxIntrMask);
155}

◆ DequeueTxToBuffer()

bool IRAM_ATTR LibXR::ESP32UART::DequeueTxToBuffer ( uint8_t * buffer,
size_t & size,
WriteInfoBlock & info,
bool in_isr )
private

Definition at line 502 of file esp_uart.cpp.

504{
505 (void)in_isr;
506 (void)buffer;
507
508 WriteInfoBlock peek_info = {};
509 if (write_port_->queue_info_->Peek(peek_info) != ErrorCode::OK)
510 {
511 return false;
512 }
513
514 if (peek_info.data.size_ > tx_buffer_size_)
515 {
516 ASSERT(false);
517 return false;
518 }
519
520#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
521 if (dma_backend_enabled_)
522 {
523 if (write_port_->queue_data_->PopBatch(buffer, peek_info.data.size_) != ErrorCode::OK)
524 {
525 return false;
526 }
527 }
528#endif
529
530 if (write_port_->queue_info_->Pop(info) != ErrorCode::OK)
531 {
532 return false;
533 }
534
535 size = peek_info.data.size_;
536 return true;
537}
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:54

◆ DrainRxFifoFromIsr()

void IRAM_ATTR LibXR::ESP32UART::DrainRxFifoFromIsr ( )
private

Definition at line 126 of file esp_uart_fifo.cpp.

127{
128 bool pushed_any = false;
129 while (uart_hal_get_rxfifo_len(&uart_hal_) > 0U)
130 {
131 const size_t fifo_len = uart_hal_get_rxfifo_len(&uart_hal_);
132 const size_t write_len = std::min(fifo_len, read_port_->queue_data_->EmptySize());
133 if (write_len == 0U)
134 {
135 break;
136 }
137
138 const ErrorCode push_ec = read_port_->queue_data_->PushWithWriter(
139 write_len,
140 [this](uint8_t* buffer, size_t chunk_size) -> ErrorCode
141 {
142 int read_len = static_cast<int>(chunk_size);
143 uart_hal_read_rxfifo(&uart_hal_, buffer, &read_len);
144 return (read_len == static_cast<int>(chunk_size)) ? ErrorCode::OK
146 });
147
148 if ((push_ec == ErrorCode::FULL) || (push_ec == ErrorCode::EMPTY))
149 {
150 break;
151 }
152 if (push_ec != ErrorCode::OK)
153 {
154 ASSERT(false);
155 break;
156 }
157
158 pushed_any = true;
159 }
160
161 if (pushed_any)
162 {
164 }
165}
size_t EmptySize()
计算队列剩余可用空间 / Calculates the remaining available space in the queue
ErrorCode PushWithWriter(size_t size, Writer &&writer)
通过写入器回调写入固定长度数据(单生产者) / Push fixed-size data via writer callback (single producer)
void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:193
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:53
ErrorCode
定义错误码枚举
Definition libxr_def.hpp:64
@ EMPTY
为空 | Empty
@ FULL
已满 | Full

◆ FillTxFifo()

void IRAM_ATTR LibXR::ESP32UART::FillTxFifo ( bool in_isr)
private

Definition at line 52 of file esp_uart_fifo.cpp.

53{
54 if (!tx_active_valid_)
55 {
56 return;
57 }
58
59#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
60 if (dma_backend_enabled_)
61 {
62 while (tx_active_offset_ < tx_active_length_)
63 {
64 if (uart_hal_get_txfifo_len(&uart_hal_) == 0)
65 {
66 break;
67 }
68
69 uint32_t write_size = 0;
70 const uint8_t* src = tx_active_buffer_ + tx_active_offset_;
71 const uint32_t remaining =
72 static_cast<uint32_t>(tx_active_length_ - tx_active_offset_);
73
74 uart_hal_write_txfifo(&uart_hal_, src, remaining, &write_size);
75 if (write_size == 0)
76 {
77 break;
78 }
79
80 tx_active_offset_ += write_size;
81 }
82 }
83 else
84#endif
85 {
86 while (tx_active_offset_ < tx_active_length_)
87 {
88 const uint32_t fifo_space = uart_hal_get_txfifo_len(&uart_hal_);
89 if (fifo_space == 0U)
90 {
91 break;
92 }
93
94 const size_t remaining = tx_active_length_ - tx_active_offset_;
95 const size_t chunk_size = std::min<size_t>(remaining, fifo_space);
96
97 const ErrorCode pop_ec = write_port_->queue_data_->PopWithReader(
98 chunk_size,
99 [this](const uint8_t* src, size_t size) -> ErrorCode
100 {
101 uint32_t write_size = 0;
102 uart_hal_write_txfifo(&uart_hal_, src, static_cast<uint32_t>(size),
103 &write_size);
104 return (write_size == static_cast<uint32_t>(size)) ? ErrorCode::OK
106 });
107 if (pop_ec != ErrorCode::OK)
108 {
109 ASSERT(false);
110 break;
111 }
112
113 tx_active_offset_ += chunk_size;
114 }
115 }
116
117 if ((tx_active_offset_ < tx_active_length_) || !in_isr)
118 {
119 return;
120 }
121
122 uart_hal_disable_intr_mask(&uart_hal_, UART_INTR_TXFIFO_EMPTY);
123 OnTxTransferDone(true, ErrorCode::OK);
124}
ErrorCode PopWithReader(size_t size, Reader &&reader)
通过读取器回调弹出固定长度数据(单消费者) / Pop fixed-size data via reader callback (single consumer)

◆ HandleRxInterrupt()

void IRAM_ATTR LibXR::ESP32UART::HandleRxInterrupt ( uint32_t uart_intr_status)
private

Definition at line 167 of file esp_uart_fifo.cpp.

168{
169 const bool has_overflow = (uart_intr_status & UART_INTR_RXFIFO_OVF) != 0U;
170 const bool has_rx_data =
171 (uart_intr_status & (UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT)) != 0U;
172
173 if (!has_overflow && !has_rx_data)
174 {
175 return;
176 }
177
178 if (has_overflow)
179 {
180 // Overrun means at least one incoming byte was dropped. Keep remaining FIFO
181 // bytes to minimize extra loss instead of resetting the whole RX FIFO.
182 uart_hal_clr_intsts_mask(&uart_hal_, UART_INTR_RXFIFO_OVF);
183 }
184
185 DrainRxFifoFromIsr();
186 uart_hal_clr_intsts_mask(&uart_hal_, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT);
187}

◆ HandleTxInterrupt()

void IRAM_ATTR LibXR::ESP32UART::HandleTxInterrupt ( uint32_t uart_intr_status)
private

Definition at line 189 of file esp_uart_fifo.cpp.

190{
191 if ((uart_intr_status & UART_INTR_TXFIFO_EMPTY) == 0U)
192 {
193 return;
194 }
195
196 Flag::ScopedRestore tx_flag(in_tx_isr_);
197 FillTxFifo(true);
198 uart_hal_clr_intsts_mask(&uart_hal_, UART_INTR_TXFIFO_EMPTY);
199}

◆ HandleUartInterrupt()

void IRAM_ATTR LibXR::ESP32UART::HandleUartInterrupt ( )
private

Definition at line 201 of file esp_uart_fifo.cpp.

202{
203 uint32_t uart_intr_status = uart_hal_get_intsts_mask(&uart_hal_);
204
205 while (uart_intr_status != 0)
206 {
207 if (uart_intr_status & kUartRxIntrMask)
208 {
209 HandleRxInterrupt(uart_intr_status);
210 }
211
212 if (uart_intr_status & kUartTxIntrMask)
213 {
214 HandleTxInterrupt(uart_intr_status);
215 }
216
217 uart_intr_status = uart_hal_get_intsts_mask(&uart_hal_);
218 }
219}

◆ InitUartHardware()

ErrorCode LibXR::ESP32UART::InitUartHardware ( )
private

Definition at line 306 of file esp_uart.cpp.

307{
308 if (uart_num_ >= UART_NUM_MAX)
309 {
311 }
312
313 periph_module_t uart_module = PERIPH_MODULE_MAX;
314 if (ResolveUartPeriph(uart_num_, uart_module) != ErrorCode::OK)
315 {
317 }
318
319 uart_hal_.dev = UART_LL_GET_HW(uart_num_);
320 if (uart_hal_.dev == nullptr)
321 {
323 }
324
325 periph_module_enable(uart_module);
326 periph_module_reset(uart_module);
327
328 uart_ll_sclk_enable(uart_hal_.dev);
329 uart_hal_init(&uart_hal_, uart_num_);
330
331 uart_hw_enabled_ = true;
332 if (SetConfig(config_) != ErrorCode::OK)
333 {
334 uart_hw_enabled_ = false;
335 return ErrorCode::INIT_ERR;
336 }
337
338 if (ConfigurePins() != ErrorCode::OK)
339 {
340 uart_hw_enabled_ = false;
341 return ErrorCode::INIT_ERR;
342 }
343
344 uart_hal_txfifo_rst(&uart_hal_);
345 uart_hal_rxfifo_rst(&uart_hal_);
346 uart_hal_clr_intsts_mask(&uart_hal_, UINT32_MAX);
347 uart_hal_disable_intr_mask(&uart_hal_, UINT32_MAX);
348
349 return ErrorCode::OK;
350}
ErrorCode SetConfig(UART::Configuration config) override
设置 UART 配置 / Sets the UART configuration
Definition esp_uart.cpp:157
@ INIT_ERR
初始化错误 | Initialization error
@ NOT_SUPPORT
不支持 | Not supported

◆ InstallUartIsr()

ErrorCode LibXR::ESP32UART::InstallUartIsr ( )
private

Definition at line 26 of file esp_uart_fifo.cpp.

27{
28 if (uart_isr_installed_)
29 {
30 return ErrorCode::OK;
31 }
32
33#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S3
34 // Classic ESP32/S3 can enter cache-disabled flash windows while UART IRQ is active.
35 // The current WritePort path is not fully IRAM-safe, so keep this IRQ non-IRAM.
36 constexpr int kUartIntrFlags = 0;
37#else
38 constexpr int kUartIntrFlags = ESP_INTR_FLAG_IRAM;
39#endif
40
41 const esp_err_t err = esp_intr_alloc(uart_periph_signal[uart_num_].irq, kUartIntrFlags,
42 UartIsrEntry, this, &uart_intr_handle_);
43 if (err != ESP_OK)
44 {
46 }
47
48 uart_isr_installed_ = true;
49 return ErrorCode::OK;
50}

◆ LoadActiveTxFromQueue()

bool IRAM_ATTR LibXR::ESP32UART::LoadActiveTxFromQueue ( bool in_isr)
private

Definition at line 467 of file esp_uart.cpp.

468{
469 (void)in_isr;
470
471 size_t active_length = 0U;
472 if (!DequeueTxToBuffer(tx_active_buffer_, active_length, tx_active_info_, in_isr))
473 {
474 return false;
475 }
476
477 tx_active_length_ = active_length;
478 tx_active_valid_ = true;
479 return true;
480}

◆ LoadPendingTxFromQueue()

bool IRAM_ATTR LibXR::ESP32UART::LoadPendingTxFromQueue ( bool in_isr)
private

Definition at line 482 of file esp_uart.cpp.

483{
484 (void)in_isr;
485
486 if (tx_pending_valid_)
487 {
488 return false;
489 }
490
491 size_t pending_length = 0U;
492 if (!DequeueTxToBuffer(tx_pending_buffer_, pending_length, tx_pending_info_, in_isr))
493 {
494 return false;
495 }
496
497 tx_pending_length_ = pending_length;
498 tx_pending_valid_ = true;
499 return true;
500}

◆ OnTxTransferDone()

void IRAM_ATTR LibXR::ESP32UART::OnTxTransferDone ( bool in_isr,
ErrorCode result )
private

Definition at line 600 of file esp_uart.cpp.

601{
602 Flag::ScopedRestore tx_flag(in_tx_isr_);
603 tx_busy_.Clear();
604
605 ClearActiveTx();
606
607 if ((result != ErrorCode::OK) && tx_pending_valid_)
608 {
609 write_port_->Finish(in_isr, ErrorCode::FAILED, tx_pending_info_);
610 ClearPendingTx();
611 }
612
613 if (result != ErrorCode::OK)
614 {
615 ClearPendingTx();
616 return;
617 }
618
619 if (tx_pending_valid_)
620 {
621 std::swap(tx_active_buffer_, tx_pending_buffer_);
622 tx_active_length_ = tx_pending_length_;
623 tx_pending_length_ = 0;
624 tx_active_info_ = tx_pending_info_;
625 tx_active_valid_ = true;
626 ClearPendingTx();
627 (void)StartAndReportActive(in_isr);
628 }
629 else
630 {
631 if (LoadActiveTxFromQueue(in_isr))
632 {
633 (void)StartAndReportActive(in_isr);
634 }
635 }
636
637 if (!tx_pending_valid_)
638 {
639 (void)LoadPendingTxFromQueue(in_isr);
640 }
641}
void Clear() noexcept
清除标志 / Clear the flag
Definition flag.hpp:130
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:294
@ FAILED
操作失败 | Operation failed

◆ PushRxBytes()

void IRAM_ATTR LibXR::ESP32UART::PushRxBytes ( const uint8_t * data,
size_t size,
bool in_isr )
private

Definition at line 573 of file esp_uart.cpp.

574{
575 size_t offset = 0;
576 bool pushed_any = false;
577 while (offset < size)
578 {
579 const size_t free_space = read_port_->queue_data_->EmptySize();
580 if (free_space == 0)
581 {
582 break;
583 }
584
585 const size_t chunk = std::min(free_space, size - offset);
586 if (read_port_->queue_data_->PushBatch(data + offset, chunk) != ErrorCode::OK)
587 {
588 break;
589 }
590
591 offset += chunk;
592 pushed_any = true;
593 }
594
595 if (pushed_any)
596 {
598 }
599}
ErrorCode PushBatch(const Data *data, size_t size)
批量推入数据 / Pushes multiple elements into the queue

◆ ReadFun()

ErrorCode LibXR::ESP32UART::ReadFun ( ReadPort & port,
bool in_isr )
static

Definition at line 253 of file esp_uart.cpp.

253{ return ErrorCode::PENDING; }
@ PENDING
等待中 | Pending

◆ ResolveParity()

uart_parity_t LibXR::ESP32UART::ResolveParity ( UART::Parity parity)
staticprivate

Definition at line 291 of file esp_uart.cpp.

292{
293 switch (parity)
294 {
296 return UART_PARITY_DISABLE;
298 return UART_PARITY_EVEN;
300 return UART_PARITY_ODD;
301 default:
302 return UART_PARITY_DISABLE;
303 }
304}
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity

◆ ResolveStopBits()

bool LibXR::ESP32UART::ResolveStopBits ( uint8_t stop_bits,
uart_stop_bits_t & out )
staticprivate

Definition at line 276 of file esp_uart.cpp.

277{
278 switch (stop_bits)
279 {
280 case 1:
281 out = UART_STOP_BITS_1;
282 return true;
283 case 2:
284 out = UART_STOP_BITS_2;
285 return true;
286 default:
287 return false;
288 }
289}

◆ ResolveUartPeriph()

ErrorCode LibXR::ESP32UART::ResolveUartPeriph ( uart_port_t uart_num,
periph_module_t & out )
staticprivate

Definition at line 53 of file esp_uart.cpp.

54{
55 switch (uart_num)
56 {
57 case UART_NUM_0:
58 out = PERIPH_UART0_MODULE;
59 return ErrorCode::OK;
60 case UART_NUM_1:
61 out = PERIPH_UART1_MODULE;
62 return ErrorCode::OK;
63#if SOC_UART_HP_NUM > 2
64 case UART_NUM_2:
65 out = PERIPH_UART2_MODULE;
66 return ErrorCode::OK;
67#endif
68 default:
70 }
71}

◆ ResolveWordLength()

bool LibXR::ESP32UART::ResolveWordLength ( uint8_t data_bits,
uart_word_length_t & out )
staticprivate

Definition at line 255 of file esp_uart.cpp.

256{
257 switch (data_bits)
258 {
259 case 5:
260 out = UART_DATA_5_BITS;
261 return true;
262 case 6:
263 out = UART_DATA_6_BITS;
264 return true;
265 case 7:
266 out = UART_DATA_7_BITS;
267 return true;
268 case 8:
269 out = UART_DATA_8_BITS;
270 return true;
271 default:
272 return false;
273 }
274}

◆ SetConfig()

ErrorCode LibXR::ESP32UART::SetConfig ( UART::Configuration config)
overridevirtual

设置 UART 配置 / Sets the UART configuration

Parameters
configUART 配置信息 / UART configuration settings
Returns
返回操作状态,成功时返回 ErrorCode::OK,否则返回相应错误码 / Returns the operation status, ErrorCode::OK if successful, otherwise an error code

该方法为纯虚函数,子类必须实现具体的 UART 配置逻辑。 This is a pure virtual function. Subclasses must implement the specific UART configuration logic.

Implements LibXR::UART.

Definition at line 157 of file esp_uart.cpp.

158{
159 if (!uart_hw_enabled_)
160 {
162 }
163
164 uart_word_length_t word_length = UART_DATA_8_BITS;
165 uart_stop_bits_t stop_bits = UART_STOP_BITS_1;
166
167 if (!ResolveWordLength(config.data_bits, word_length))
168 {
169 return ErrorCode::ARG_ERR;
170 }
171
172 if (!ResolveStopBits(config.stop_bits, stop_bits))
173 {
174 return ErrorCode::ARG_ERR;
175 }
176
177 const uart_sclk_t sclk = UART_SCLK_DEFAULT;
178 uart_hal_set_sclk(&uart_hal_, static_cast<soc_module_clk_t>(sclk));
179
180 uint32_t sclk_hz = 0;
181 if ((esp_clk_tree_src_get_freq_hz(static_cast<soc_module_clk_t>(sclk),
182 ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED,
183 &sclk_hz) != ESP_OK) ||
184 (sclk_hz == 0))
185 {
186 return ErrorCode::INIT_ERR;
187 }
188
189 if (!uart_hal_set_baudrate(&uart_hal_, config.baudrate, sclk_hz))
190 {
191 return ErrorCode::INIT_ERR;
192 }
193
194 uart_hal_set_data_bit_num(&uart_hal_, word_length);
195 uart_hal_set_stop_bits(&uart_hal_, stop_bits);
196 uart_hal_set_parity(&uart_hal_, ResolveParity(config.parity));
197 uart_hal_set_hw_flow_ctrl(&uart_hal_, UART_HW_FLOWCTRL_DISABLE, 0);
198 uart_hal_set_mode(&uart_hal_, UART_MODE_UART);
199 uart_hal_set_txfifo_empty_thr(&uart_hal_, kTxEmptyThreshold);
200 // Drop stale hardware RX FIFO bytes from the previous baud.
201 // Keep software read queue semantics aligned with ST/CH (no read_port reset).
202 uart_hal_rxfifo_rst(&uart_hal_);
203 uart_hal_clr_intsts_mask(&uart_hal_, UART_INTR_RXFIFO_FULL | UART_INTR_RXFIFO_TOUT);
204
205#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
206 if (dma_backend_enabled_)
207 {
208 // Re-align the circular RX DMA window after reconfig to avoid
209 // carrying stale pre-switch bytes into the next frame.
210 HandleDmaRxError();
211 }
212#endif
213
214 // Align with ST/CH SetConfig semantics: if TX was in-flight during
215 // reconfiguration, keep transfer progression instead of surfacing BUSY.
216 if (tx_busy_.IsSet() && tx_active_valid_)
217 {
218#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
219 if (dma_backend_enabled_)
220 {
221 (void)StartDmaTx();
222 }
223 else
224#endif
225 {
226 uart_hal_clr_intsts_mask(&uart_hal_, kUartTxIntrMask);
227 uart_hal_ena_intr_mask(&uart_hal_, kUartTxIntrMask);
228 FillTxFifo(false);
229 }
230 }
231
232 config_ = config;
233 return ErrorCode::OK;
234}
bool IsSet() const noexcept
判断是否已置位 / Check whether the flag is set
Definition flag.hpp:138
@ STATE_ERR
状态错误 | State error

◆ SetLoopback()

ErrorCode LibXR::ESP32UART::SetLoopback ( bool enable)

Definition at line 236 of file esp_uart.cpp.

237{
238 if (!uart_hw_enabled_)
239 {
241 }
242
243 uart_ll_set_loop_back(uart_hal_.dev, enable);
244 return ErrorCode::OK;
245}

◆ StartActiveTransfer()

bool IRAM_ATTR LibXR::ESP32UART::StartActiveTransfer ( bool in_isr)
private

Definition at line 539 of file esp_uart.cpp.

540{
541 if (!tx_active_valid_)
542 {
543 return false;
544 }
545
546 if (tx_busy_.TestAndSet())
547 {
548 return true;
549 }
550
551 tx_active_offset_ = 0;
552
553#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
554 if (dma_backend_enabled_)
555 {
556 if (StartDmaTx())
557 {
558 return true;
559 }
560
561 tx_busy_.Clear();
562 return false;
563 }
564#endif
565
566 uart_hal_clr_intsts_mask(&uart_hal_, kUartTxIntrMask);
567 uart_hal_ena_intr_mask(&uart_hal_, kUartTxIntrMask);
568 FillTxFifo(false);
569
570 return true;
571}
bool TestAndSet() noexcept
测试并置位:置位并返回旧状态 / Test-and-set: set and return previous state
Definition flag.hpp:146

◆ StartAndReportActive()

bool IRAM_ATTR LibXR::ESP32UART::StartAndReportActive ( bool in_isr)
private

Definition at line 417 of file esp_uart.cpp.

418{
419 if (!StartActiveTransfer(in_isr))
420 {
421 write_port_->Finish(in_isr, ErrorCode::FAILED, tx_active_info_);
422 ClearActiveTx();
423 return false;
424 }
425
426 // Align with STM/CH semantics: once the active write is kicked to HW,
427 // WritePort owns the completion notification and the ISR only advances queues.
428 write_port_->Finish(in_isr, ErrorCode::OK, tx_active_info_);
429 return true;
430}

◆ TryStartTx()

ErrorCode IRAM_ATTR LibXR::ESP32UART::TryStartTx ( bool in_isr)
private

Definition at line 432 of file esp_uart.cpp.

433{
434 if (in_tx_isr_.IsSet())
435 {
436 return ErrorCode::PENDING;
437 }
438 if (!tx_active_valid_)
439 {
440 (void)LoadActiveTxFromQueue(in_isr);
441 }
442
443 if (!tx_busy_.IsSet() && tx_active_valid_)
444 {
445 if (!StartActiveTransfer(in_isr))
446 {
447 ClearActiveTx();
448 return ErrorCode::FAILED;
449 }
450
451 // Current op completion is reported by WritePort when TryStartTx returns OK.
452 if (!tx_pending_valid_)
453 {
454 (void)LoadPendingTxFromQueue(in_isr);
455 }
456 return ErrorCode::OK;
457 }
458
459 if (!tx_pending_valid_)
460 {
461 (void)LoadPendingTxFromQueue(in_isr);
462 }
463
464 return ErrorCode::PENDING;
465}

◆ UartIsrEntry()

void IRAM_ATTR LibXR::ESP32UART::UartIsrEntry ( void * arg)
staticprivate

Definition at line 17 of file esp_uart_fifo.cpp.

18{
19 auto* self = static_cast<ESP32UART*>(arg);
20 if (self != nullptr)
21 {
22 self->HandleUartInterrupt();
23 }
24}

◆ WriteFun()

ErrorCode IRAM_ATTR LibXR::ESP32UART::WriteFun ( WritePort & port,
bool in_isr )
static

Definition at line 247 of file esp_uart.cpp.

248{
249 auto* uart = CONTAINER_OF(&port, ESP32UART, _write_port);
250 return uart->TryStartTx(in_isr);
251}

Field Documentation

◆ _read_port

ReadPort LibXR::ESP32UART::_read_port
private

Definition at line 166 of file esp_uart.hpp.

◆ _write_port

WritePort LibXR::ESP32UART::_write_port
private

Definition at line 167 of file esp_uart.hpp.

◆ config_

UART::Configuration LibXR::ESP32UART::config_
private

Definition at line 139 of file esp_uart.hpp.

◆ cts_pin_

int LibXR::ESP32UART::cts_pin_
private

Definition at line 137 of file esp_uart.hpp.

◆ dma_requested_

bool LibXR::ESP32UART::dma_requested_ = true
private

Definition at line 164 of file esp_uart.hpp.

◆ in_tx_isr_

Flag::Plain LibXR::ESP32UART::in_tx_isr_
private

Definition at line 156 of file esp_uart.hpp.

◆ PIN_NO_CHANGE

int LibXR::ESP32UART::PIN_NO_CHANGE = -1
staticconstexpr

Definition at line 30 of file esp_uart.hpp.

◆ rts_pin_

int LibXR::ESP32UART::rts_pin_
private

Definition at line 136 of file esp_uart.hpp.

◆ rx_isr_buffer_

uint8_t* LibXR::ESP32UART::rx_isr_buffer_ = nullptr
private

Definition at line 141 of file esp_uart.hpp.

◆ rx_isr_buffer_size_

size_t LibXR::ESP32UART::rx_isr_buffer_size_ = 0
private

Definition at line 142 of file esp_uart.hpp.

◆ rx_pin_

int LibXR::ESP32UART::rx_pin_
private

Definition at line 135 of file esp_uart.hpp.

◆ tx_active_buffer_

uint8_t* LibXR::ESP32UART::tx_active_buffer_ = nullptr
private

Definition at line 147 of file esp_uart.hpp.

◆ tx_active_info_

WriteInfoBlock LibXR::ESP32UART::tx_active_info_ = {}
private

Definition at line 153 of file esp_uart.hpp.

153{};

◆ tx_active_length_

size_t LibXR::ESP32UART::tx_active_length_ = 0
private

Definition at line 149 of file esp_uart.hpp.

◆ tx_active_offset_

size_t LibXR::ESP32UART::tx_active_offset_ = 0
private

Definition at line 151 of file esp_uart.hpp.

◆ tx_active_valid_

bool LibXR::ESP32UART::tx_active_valid_ = false
private

Definition at line 157 of file esp_uart.hpp.

◆ tx_buffer_size_

size_t LibXR::ESP32UART::tx_buffer_size_ = 0
private

Definition at line 146 of file esp_uart.hpp.

◆ tx_busy_

Flag::Plain LibXR::ESP32UART::tx_busy_
private

Definition at line 155 of file esp_uart.hpp.

◆ tx_pending_buffer_

uint8_t* LibXR::ESP32UART::tx_pending_buffer_ = nullptr
private

Definition at line 148 of file esp_uart.hpp.

◆ tx_pending_info_

WriteInfoBlock LibXR::ESP32UART::tx_pending_info_ = {}
private

Definition at line 154 of file esp_uart.hpp.

154{};

◆ tx_pending_length_

size_t LibXR::ESP32UART::tx_pending_length_ = 0
private

Definition at line 150 of file esp_uart.hpp.

◆ tx_pending_valid_

bool LibXR::ESP32UART::tx_pending_valid_ = false
private

Definition at line 158 of file esp_uart.hpp.

◆ tx_pin_

int LibXR::ESP32UART::tx_pin_
private

Definition at line 134 of file esp_uart.hpp.

◆ tx_storage_

uint8_t* LibXR::ESP32UART::tx_storage_ = nullptr
private

Definition at line 144 of file esp_uart.hpp.

◆ tx_storage_size_

size_t LibXR::ESP32UART::tx_storage_size_ = 0
private

Definition at line 145 of file esp_uart.hpp.

◆ uart_hal_

uart_hal_context_t LibXR::ESP32UART::uart_hal_ = {}
private

Definition at line 161 of file esp_uart.hpp.

161{};

◆ uart_hw_enabled_

bool LibXR::ESP32UART::uart_hw_enabled_ = false
private

Definition at line 160 of file esp_uart.hpp.

◆ uart_intr_handle_

intr_handle_t LibXR::ESP32UART::uart_intr_handle_ = nullptr
private

Definition at line 162 of file esp_uart.hpp.

◆ uart_isr_installed_

bool LibXR::ESP32UART::uart_isr_installed_ = false
private

Definition at line 163 of file esp_uart.hpp.

◆ uart_num_

uart_port_t LibXR::ESP32UART::uart_num_
private

Definition at line 133 of file esp_uart.hpp.


The documentation for this class was generated from the following files: