libxr
Embedded C++ framework for bare-metal, RTOS and Linux
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 "esp_private/critical_section.h"
12#include "flag.hpp"
13#include "hal/uart_hal.h"
14#include "hal/uart_types.h"
15#include "serialized_service.hpp"
16#include "soc/periph_defs.h"
17#include "soc/soc_caps.h"
18#include "uart.hpp"
19
20#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
21#include "esp_private/gdma.h"
22#include "esp_private/gdma_link.h"
23#include "hal/uhci_hal.h"
24#endif
25
26namespace LibXR
27{
28
29class ESP32UART;
30
40{
41 public:
48 explicit ESP32UARTReadPort(size_t size, ESP32UART& owner)
49 : ReadPort(size), owner_(owner)
50 {
51 }
52
53 protected:
58 void OnReadQueueSpaceAvailable(bool in_isr) override;
59
60 private:
61 ESP32UART& owner_;
62};
63
80class ESP32UART : public UART
81{
82 friend class ESP32UARTReadPort;
83
84 public:
85 static constexpr int PIN_NO_CHANGE =
86 -1;
87
103 ESP32UART(uart_port_t uart_num, int tx_pin, int rx_pin, int rts_pin = PIN_NO_CHANGE,
104 int cts_pin = PIN_NO_CHANGE, size_t rx_buffer_size = 1024,
105 size_t tx_buffer_size = 512, uint32_t tx_queue_size = 5,
106 UART::Configuration config = {115200, UART::Parity::NO_PARITY, 8, 1},
107 bool enable_dma = true);
108
122 ErrorCode SetConfig(UART::Configuration config, bool in_isr = false) override;
123
130 ErrorCode SetLoopback(bool enable);
131
136 static void WriteFun(WritePort& port, bool in_isr);
137
138 private:
142 static uint8_t* AllocateTxStorage(size_t size);
143
148 static ErrorCode ResolveUartPeriph(uart_port_t uart_num, periph_module_t& out);
149
154 static bool ResolveWordLength(uint8_t data_bits, uart_word_length_t& out);
155
160 static bool ResolveStopBits(uint8_t stop_bits, uart_stop_bits_t& out);
161
165 static uart_parity_t ResolveParity(UART::Parity parity);
166
170 static void UartIsrEntry(void* arg);
171
172#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
176 static bool DmaTxEofCallback(gdma_channel_handle_t dma_chan,
177 gdma_event_data_t* event_data, void* user_data);
178
182 static bool DmaTxDescrErrCallback(gdma_channel_handle_t dma_chan,
183 gdma_event_data_t* event_data, void* user_data);
184
188 static bool DmaRxDoneCallback(gdma_channel_handle_t dma_chan,
189 gdma_event_data_t* event_data, void* user_data);
190
194 static bool DmaRxDescrErrCallback(gdma_channel_handle_t dma_chan,
195 gdma_event_data_t* event_data, void* user_data);
196#endif
197
201 ErrorCode InitUartHardware();
202
206 ErrorCode ConfigurePins();
207
211 ErrorCode InstallUartIsr();
212
216 void ConfigureRxInterruptPath();
217
218#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
222 ErrorCode InitDmaBackend();
223
227 bool StartDmaTx();
228
232 void HandleDmaRxDone(gdma_event_data_t* event_data, bool in_isr);
233
237 void HandleDmaRxError(bool in_isr);
238
240 void StopDmaRx(bool in_isr);
242 void ResetDmaRxDescriptors(bool in_isr);
244 void StartDmaRx(bool in_isr);
245
250 void HandleDmaTxError(bool in_isr);
251
252#endif
253
257 ErrorCode TryStartTx(bool in_isr);
258
263 bool LoadActiveTxFromQueue(bool in_isr);
264
269 bool LoadPendingTxFromQueue(bool in_isr);
270
274 bool PromotePendingTxToActive();
275
279 bool StartActiveTransfer(bool in_isr);
280
284 bool StartAndReportActive(bool in_isr);
285
289 void ClearActiveTx();
290
295 void FillTxFifo(bool in_isr);
296
300 void PushRxBytes(const uint8_t* data, size_t size, bool in_isr);
301
306 void DrainRxFifo(bool in_isr);
307
311 void HandleUartInterrupt();
312
314 void EnableUartInterrupt(uint32_t mask);
316 void DisableUartInterrupt(uint32_t mask);
318 void ClearUartInterrupt(uint32_t mask);
320 void DisableAndClearUartInterrupt(uint32_t mask);
322 uint32_t CaptureUartInterrupt(uint32_t mask);
323
328 void OnTxTransferDone(bool in_isr, ErrorCode result);
329
330 static constexpr uint32_t EVENT_WRITE = 1U << 0U;
331 static constexpr uint32_t EVENT_TX_DONE = 1U << 1U;
332 static constexpr uint32_t EVENT_RX_WORK = 1U << 2U;
333 static constexpr uint32_t EVENT_CONFIG = 1U << 3U;
334 static constexpr uint32_t EVENT_TX_WORK = 1U << 4U;
335 static constexpr uint32_t EVENT_TX_ERROR = 1U << 5U;
336 static constexpr uint32_t EVENT_RX_ERROR = 1U << 6U;
337
338 enum class ConfigState : uint8_t
339 {
340 EMPTY,
341 RESERVED,
342 PUBLISHED,
343 };
344
346 void ServiceEvents(uint32_t events, bool in_isr);
348 ErrorCode ApplyConfig(const UART::Configuration& config);
350 bool TryApplyPublishedConfig(bool in_isr);
351
352 uart_port_t uart_num_;
353 int tx_pin_;
354 int rx_pin_;
355 int rts_pin_;
356 int cts_pin_;
357
358 UART::Configuration config_;
359 uint32_t uart_sclk_hz_ = 0U;
360
361 uint8_t* rx_isr_buffer_ = nullptr;
362 size_t rx_isr_buffer_size_ = 0;
363
364 uint8_t* tx_storage_ = nullptr;
365 DoubleBuffer tx_dma_buffer_{};
366 size_t tx_active_length_ = 0U;
367 bool tx_active_valid_ = false;
368 Flag::Plain tx_busy_;
369
370 bool uart_hw_enabled_ = false;
371 uart_hal_context_t uart_hal_ = {};
372 intr_handle_t uart_intr_handle_ = nullptr;
373 bool uart_isr_installed_ = false;
374 bool dma_requested_ = true;
375
377 SerializedService service_{};
379 UART::Configuration requested_config_{};
381 std::atomic<uint8_t> config_state_{static_cast<uint8_t>(ConfigState::EMPTY)};
383 DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(irq_lock_)
384
385 ESP32UARTReadPort _read_port;
386 WritePort _write_port;
387
388#if SOC_GDMA_SUPPORTED && SOC_UHCI_SUPPORTED
389 bool dma_backend_enabled_ = false;
390 uhci_hal_context_t uhci_hal_ = {};
391 gdma_channel_handle_t tx_dma_channel_ = nullptr;
392 gdma_channel_handle_t rx_dma_channel_ = nullptr;
393 uintptr_t tx_dma_head_addr_[2] = {0U, 0U};
394 gdma_link_list_handle_t rx_dma_link_ = nullptr;
395 uint8_t* rx_dma_storage_ = nullptr;
396 size_t rx_dma_chunk_size_ = 0;
397 uint32_t rx_dma_node_index_ = 0;
398#endif
399};
400
401} // namespace LibXR
支持 FIFO 和 GDMA 的 ESP UART 后端 / ESP UART backend with FIFO and GDMA.
Definition esp_uart.hpp:81
ErrorCode SetLoopback(bool enable)
切换 UART 内部环回模式 / Toggle UART internal loopback.
Definition esp_uart.cpp:460
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)
构造并初始化 ESP UART / Construct and initialize an ESP UART.
Definition esp_uart.cpp:146
static constexpr int PIN_NO_CHANGE
保持引脚映射不变 / Keep pin mapping unchanged.
Definition esp_uart.hpp:85
ErrorCode SetConfig(UART::Configuration config, bool in_isr=false) override
提交帧格式和波特率配置 / Submit framing and baud configuration.
Definition esp_uart.cpp:226
ESP32 UART 读端口 / ESP32 UART read port.
Definition esp_uart.hpp:40
void OnReadQueueSpaceAvailable(bool in_isr) override
通知后端处理接收空间 / Notify the backend of RX space.
Definition esp_uart.cpp:98
ESP32UARTReadPort(size_t size, ESP32UART &owner)
构造读端口 / Construct the read port
Definition esp_uart.hpp:48
基于 SPSC 字节队列的读端口 / Read endpoint backed by an SPSC byte queue.
Definition read_port.hpp:30
通用异步收发传输(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
基于 SPSC 字节队列的写端口 / Write endpoint backed by an SPSC byte queue.
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ EMPTY
为空 / Empty
void(* WriteFun)(WritePort &port, bool in_isr)
写入进度通知函数类型 / Write progress notification function type.
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44