libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
esp_uart.hpp
1#pragma once
2
3#include <atomic>
4#include <cstddef>
5#include <cstdint>
6
7#include "double_buffer.hpp"
8#include "driver/gpio.h"
9#include "esp_def.hpp"
10#include "esp_intr_alloc.h"
11#include "flag.hpp"
12#include "hal/uart_hal.h"
13#include "hal/uart_types.h"
14#include "soc/periph_defs.h"
15#include "soc/soc_caps.h"
16#include "uart.hpp"
17
18#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
19#include "esp_private/gdma.h"
20#include "esp_private/gdma_link.h"
21#include "hal/uhci_hal.h"
22#endif
23
24namespace LibXR
25{
26
27class ESP32UART;
28
38{
39 public:
46 explicit ESP32UARTReadPort(size_t size, ESP32UART& owner)
47 : ReadPort(size), owner_(owner)
48 {
49 }
50
54 void OnRxDequeue(bool in_isr) override;
55
56 ESP32UARTReadPort& operator=(ReadFun fun)
57 {
59 return *this;
60 }
61
62 private:
64};
65
75class ESP32UART : public UART
76{
77 friend class ESP32UARTReadPort;
78
79 public:
80 static constexpr int PIN_NO_CHANGE = -1;
81
86 ESP32UART(uart_port_t uart_num, int tx_pin, int rx_pin, int rts_pin = PIN_NO_CHANGE,
87 int cts_pin = PIN_NO_CHANGE, size_t rx_buffer_size = 1024,
88 size_t tx_buffer_size = 512, uint32_t tx_queue_size = 5,
89 UART::Configuration config = {115200, UART::Parity::NO_PARITY, 8, 1},
90 bool enable_dma = true);
91
97
102 ErrorCode SetLoopback(bool enable);
103
108 static ErrorCode WriteFun(WritePort& port, bool in_isr);
109
114 static ErrorCode ReadFun(ReadPort& port, bool in_isr);
115
116 private:
121 static uint8_t* AllocateTxStorage(size_t size);
122
127 static ErrorCode ResolveUartPeriph(uart_port_t uart_num, periph_module_t& out);
128
133 static bool ResolveWordLength(uint8_t data_bits, uart_word_length_t& out);
134
139 static bool ResolveStopBits(uint8_t stop_bits, uart_stop_bits_t& out);
140
145 static uart_parity_t ResolveParity(UART::Parity parity);
146
151 static void UartIsrEntry(void* arg);
152
153#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
158 static bool DmaTxEofCallback(gdma_channel_handle_t dma_chan,
159 gdma_event_data_t* event_data, void* user_data);
160
165 static bool DmaTxDescrErrCallback(gdma_channel_handle_t dma_chan,
166 gdma_event_data_t* event_data, void* user_data);
167
172 static bool DmaRxDoneCallback(gdma_channel_handle_t dma_chan,
173 gdma_event_data_t* event_data, void* user_data);
174
179 static bool DmaRxDescrErrCallback(gdma_channel_handle_t dma_chan,
180 gdma_event_data_t* event_data, void* user_data);
181#endif
182
188
194
200
206
207#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
212 ErrorCode InitDmaBackend();
213
218 bool StartDmaTx();
219
224 void HandleDmaRxDone(gdma_event_data_t* event_data);
225
230 void HandleDmaRxError();
231
236 void HandleDmaTxError();
237
242 void PushDmaRxData(size_t recv_size, bool in_isr);
243#endif
244
249 ErrorCode TryStartTx(bool in_isr);
250
255 bool LoadActiveTxFromQueue(bool in_isr);
256
261 bool LoadPendingTxFromQueue(bool in_isr);
262
268
273 bool StartPendingTxIfIdle(bool in_isr);
274
279 bool DequeueTxToBuffer(uint8_t* buffer, size_t& size, WriteInfoBlock& info,
280 bool in_isr);
281
286 bool StartActiveTransfer(bool in_isr);
287
292 bool StartAndReportActive(bool in_isr);
293
298 void ClearActiveTx();
299
304 void ClearPendingTx();
305
310 void FillTxFifo(bool in_isr);
311
316 void PushRxBytes(const uint8_t* data, size_t size, bool in_isr);
317
322 void DrainRxFifo(bool in_isr);
323
328 void HandleRxInterrupt(uint32_t uart_intr_status);
329
334 void HandleTxInterrupt(uint32_t uart_intr_status);
335
340 void HandleUartInterrupt();
341
346 void OnTxTransferDone(bool in_isr, ErrorCode result);
347
348 uart_port_t uart_num_;
353
355
356 uint8_t* rx_isr_buffer_ = nullptr;
358
359 uint8_t* tx_storage_ = nullptr;
362 size_t tx_active_length_ = 0U;
363 size_t tx_active_offset_ = 0U;
364 bool tx_active_valid_ = false;
367
368 bool uart_hw_enabled_ = false;
369 uart_hal_context_t uart_hal_ = {};
370 intr_handle_t uart_intr_handle_ = nullptr;
371 bool uart_isr_installed_ = false;
372 bool dma_requested_ = true;
373
376
377#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
378 bool dma_backend_enabled_ = false;
379 uhci_hal_context_t uhci_hal_ = {};
380 gdma_channel_handle_t tx_dma_channel_ = nullptr;
381 gdma_channel_handle_t rx_dma_channel_ = nullptr;
382 uintptr_t tx_dma_head_addr_[2] = {0U, 0U};
383 gdma_link_list_handle_t rx_dma_link_ = nullptr;
384 uint8_t* rx_dma_storage_ = nullptr;
385 size_t rx_dma_chunk_size_ = 0;
386 uint32_t rx_dma_node_index_ = 0;
387#endif
388
390};
391
392} // namespace LibXR
双缓冲区管理类 / Double buffer manager class
ESP32 UART backend with FIFO and optional GDMA fast paths.
Definition esp_uart.hpp:76
static ErrorCode ResolveUartPeriph(uart_port_t uart_num, periph_module_t &out)
Map one UART index to its peripheral module.
Definition esp_uart.cpp:81
ErrorCode TryStartTx(bool in_isr)
Try to start queued transmit work.
Definition esp_uart.cpp:496
ErrorCode SetConfig(UART::Configuration config) override
Apply a new UART framing and baud configuration.
Definition esp_uart.cpp:185
UART::Configuration config_
Current UART framing configuration.
Definition esp_uart.hpp:354
ErrorCode SetLoopback(bool enable)
Toggle UART peripheral internal loopback mode.
Definition esp_uart.cpp:267
void HandleUartInterrupt()
Dispatch pending UART interrupt reasons.
int rx_pin_
RX GPIO pin or PIN_NO_CHANGE.
Definition esp_uart.hpp:350
int tx_pin_
TX GPIO pin or PIN_NO_CHANGE.
Definition esp_uart.hpp:349
bool LoadActiveTxFromQueue(bool in_isr)
Load one active TX request from the queue.
Definition esp_uart.cpp:540
void ConfigureRxInterruptPath()
Program RX interrupt thresholds and masks.
Definition esp_uart.cpp:170
bool dma_requested_
Constructor preference for DMA mode.
Definition esp_uart.hpp:372
intr_handle_t uart_intr_handle_
Registered UART interrupt handle.
Definition esp_uart.hpp:370
Flag::Plain tx_busy_
Hardware TX engine currently owns the request.
Definition esp_uart.hpp:365
bool StartActiveTransfer(bool in_isr)
Start the active request on the selected TX backend.
Definition esp_uart.cpp:734
uint8_t * rx_isr_buffer_
Scratch buffer used by the RX ISR path.
Definition esp_uart.hpp:356
uart_hal_context_t uart_hal_
ESP-IDF UART HAL context.
Definition esp_uart.hpp:369
uint8_t * tx_storage_
Backing storage for the TX half-buffers.
Definition esp_uart.hpp:359
ErrorCode InitUartHardware()
Initialize UART hardware and base HAL state.
Definition esp_uart.cpp:351
static uart_parity_t ResolveParity(UART::Parity parity)
Convert configured parity into the HAL enum.
Definition esp_uart.cpp:333
size_t rx_isr_buffer_size_
Size of rx_isr_buffer_.
Definition esp_uart.hpp:357
void FillTxFifo(bool in_isr)
Drain active TX bytes into the UART FIFO backend.
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)
Create and initialize one ESP32 UART instance.
Definition esp_uart.cpp:104
bool tx_active_valid_
Whether the active TX metadata is valid.
Definition esp_uart.hpp:364
void OnTxTransferDone(bool in_isr, ErrorCode result)
Finalize one TX transfer result.
Definition esp_uart.cpp:807
WritePort _write_port
Write-side queue bridge exposed to UART.
Definition esp_uart.hpp:375
void DrainRxFifo(bool in_isr)
Drain pending bytes from the hardware RX FIFO.
WriteInfoBlock tx_active_info_
Metadata for the active TX request.
Definition esp_uart.hpp:361
void HandleTxInterrupt(uint32_t uart_intr_status)
Handle TX-side UART interrupt reasons.
int cts_pin_
CTS GPIO pin or PIN_NO_CHANGE.
Definition esp_uart.hpp:352
bool LoadPendingTxFromQueue(bool in_isr)
Preload one pending TX request for DMA mode.
Definition esp_uart.cpp:578
Flag::Plain in_tx_isr_
Reentry guard while processing TX ISR work.
Definition esp_uart.hpp:366
bool StartAndReportActive(bool in_isr)
Start the active request and report queue completion ownership.
Definition esp_uart.cpp:475
int rts_pin_
RTS GPIO pin or PIN_NO_CHANGE.
Definition esp_uart.hpp:351
bool StartPendingTxIfIdle(bool in_isr)
Start the current pending DMA request when TX is fully idle.
Definition esp_uart.cpp:654
void HandleRxInterrupt(uint32_t uart_intr_status)
Handle RX-side UART interrupt reasons.
bool DequeueTxToBuffer(uint8_t *buffer, size_t &size, WriteInfoBlock &info, bool in_isr)
Dequeue one TX payload into the selected buffer.
Definition esp_uart.cpp:684
ESP32UARTReadPort _read_port
Read-side queue bridge exposed to UART.
Definition esp_uart.hpp:374
DoubleBuffer tx_dma_buffer_
TX double-buffer view for the DMA path.
Definition esp_uart.hpp:360
bool uart_isr_installed_
UART ISR installation state.
Definition esp_uart.hpp:371
void ClearActiveTx()
Clear active TX state.
Definition esp_uart.cpp:451
static uint8_t * AllocateTxStorage(size_t size)
Allocate DMA-capable backing storage for TX buffers.
Definition esp_uart.cpp:66
static bool ResolveStopBits(uint8_t stop_bits, uart_stop_bits_t &out)
Convert configured stop bits into the HAL enum.
Definition esp_uart.cpp:316
uart_port_t uart_num_
Selected UART peripheral index.
Definition esp_uart.hpp:348
size_t tx_active_offset_
Bytes already emitted for the active request.
Definition esp_uart.hpp:363
bool PromotePendingTxToActive()
Promote one preloaded DMA pending request into the active slot.
Definition esp_uart.cpp:620
static bool ResolveWordLength(uint8_t data_bits, uart_word_length_t &out)
Convert configured data bits into the HAL enum.
Definition esp_uart.cpp:293
bool uart_hw_enabled_
UART hardware block was initialized.
Definition esp_uart.hpp:368
void PushRxBytes(const uint8_t *data, size_t size, bool in_isr)
Push RX bytes into the software queue.
Definition esp_uart.cpp:771
size_t tx_active_length_
Active TX payload length in bytes.
Definition esp_uart.hpp:362
static constexpr int PIN_NO_CHANGE
Sentinel for an unmapped GPIO.
Definition esp_uart.hpp:80
void ClearPendingTx()
Clear pending TX state.
Definition esp_uart.cpp:461
ErrorCode InstallUartIsr()
Install the UART interrupt handler.
ErrorCode ConfigurePins()
Configure the selected GPIO pins.
Definition esp_uart.cpp:399
Flag::Atomic rx_fifo_draining_
RX FIFO drain reentry gate.
Definition esp_uart.hpp:389
static void UartIsrEntry(void *arg)
UART ISR trampoline.
ESP32 UART 读端口 / ESP32 UART read port.
Definition esp_uart.hpp:38
ESP32UART & owner_
所属 UART 后端 / Owning UART backend
Definition esp_uart.hpp:63
void OnRxDequeue(bool in_isr) override
软件队列出队后的回调 / Callback after software RX dequeue
Definition esp_uart.cpp:52
ESP32UARTReadPort(size_t size, ESP32UART &owner)
构造读端口 / Construct the read port
Definition esp_uart.hpp:46
原子标志位 / Atomic flag
Definition flag.hpp:32
普通标志位(非原子)/ Non-atomic flag
Definition flag.hpp:115
ReadPort class for handling read operations.
Definition read_port.hpp:18
ReadPort & operator=(ReadFun fun)
赋值运算符重载,用于设置读取函数。 Overloaded assignment operator to set the read function.
Definition read_port.cpp:28
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
Parity
奇偶校验模式 / Parity mode
Definition uart.hpp:29
@ NO_PARITY
无校验 / No parity
WritePort class for handling write operations.
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read notifications.
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44