libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::STM32UART Class Reference

使用循环接收 DMA 和双缓冲发送的 STM32 串口 / STM32 UART with circular RX DMA and double-buffered TX. More...

#include <stm32_uart.hpp>

Inheritance diagram for LibXR::STM32UART:
[legend]
Collaboration diagram for LibXR::STM32UART:
[legend]

Public Member Functions

 STM32UART (UART_HandleTypeDef *uart_handle, RawData dma_buff_rx, RawData dma_buff_tx, uint32_t tx_queue_size=5)
 构造串口并关联 DMA 缓冲区 / Construct a UART with DMA buffers.
 
ErrorCode SetConfig (UART::Configuration config, bool in_isr=false) override
 提交串口配置请求 / Submit a UART configuration request.
 
void SetRxDMA (bool in_isr=false)
 初始化循环接收 DMA 并检查启动结果 / Initialize circular RX DMA and check startup.
 
void TxCompleteIRQHandler ()
 通知发送完成,交给后端释放半区 / Notify TX completion to release the active half.
 
void RxEventIRQHandler ()
 通知接收位置变化 / Notify RX position changes.
 
void ErrorIRQHandler ()
 通知错误,由后端处理器启动中止 / Report an error; the service initiates the abort.
 
void AbortCompleteIRQHandler ()
 
- 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 void WriteFun (WritePort &port, bool in_isr)
 通知后端处理已提交的写请求 / Notify the backend of released writes.
 

Public Attributes

ReadPort _read_port
 接收字节队列与读请求 / RX byte queue and read requests.
 
WritePort _write_port
 写请求及发送字节队列 / Write requests and TX byte queue.
 
RawData dma_buff_rx_
 调用者提供的接收 DMA 缓冲区 / Caller-provided RX DMA buffer.
 
DoubleBuffer dma_buff_tx_
 当前与待发送的 DMA 半区 / Active and pending TX DMA halves.
 
size_t last_rx_pos_ = 0
 上次已处理的 DMA 接收位置 / Last processed RX DMA position.
 
UART_HandleTypeDef * uart_handle_
 
Flag::Plain tx_busy_
 发送半区是否在使用,仅后端处理器访问 / TX half in use; service-only access.
 
stm32_uart_id_t id_ = STM32_UART_ID_ERROR
 
- Public Attributes inherited from LibXR::UART
ReadPort * read_port_
 读取端口 / Read port
 
WritePort * write_port_
 写入端口 / Write port
 

Static Public Attributes

static STM32UART * map [STM32_UART_NUMBER] = {nullptr}
 

Additional Inherited Members

- Public Types inherited from LibXR::UART
enum class  Parity : uint8_t { NO_PARITY = 0 , EVEN = 1 , ODD = 2 }
 奇偶校验模式 / Parity mode More...
 

Detailed Description

使用循环接收 DMA 和双缓冲发送的 STM32 串口 / STM32 UART with circular RX DMA and double-buffered TX.

写请求完整复制到发送缓冲半区后完成,DMA 完成仅释放半区。接收持续运行, 按 DMA 位置变化向 ReadPort 发布数据;软件队列放不下的部分作为接收溢出丢弃。 Writes complete once copied into a TX half; DMA completion only releases that half. RX runs continuously and publishes observed DMA bytes to ReadPort, discarding any overflow beyond available software capacity.

Precondition
调用遵守 ReadPort/WritePort 约定;DMA 缓冲区满足平台访问和对齐要求,运行期间有效。 Follow the port contracts. DMA buffers must meet platform access/alignment requirements and remain valid throughout operation.
H5 的 RX 句柄已挂接静止的循环链表,缓冲区长度是 4 的倍数,每段不超过 65535 字节;TX 使用普通单次 DMA。相关 UART/DMA 中断具有相同抢占优先级。 On H5, RX starts with a stopped circular seed list. The buffer size is a multiple of four, with at most 65535 bytes per node; TX uses normal one-shot DMA. Related UART/DMA IRQs share a preemption priority.

Definition at line 137 of file stm32_uart.hpp.

Constructor & Destructor Documentation

◆ STM32UART()

STM32UART::STM32UART ( UART_HandleTypeDef * uart_handle,
RawData dma_buff_rx,
RawData dma_buff_tx,
uint32_t tx_queue_size = 5 )

构造串口并关联 DMA 缓冲区 / Construct a UART with DMA buffers.

Parameters
uart_handle已初始化的 HAL 句柄 / Initialized HAL handle.
dma_buff_rx接收 DMA 缓冲区 / RX DMA buffer.
dma_buff_tx双缓冲发送存储,每半区容纳一个请求 / TX storage, one request per half.
tx_queue_size写请求队列容量,启用发送时须大于零 / Positive TX request capacity.

Definition at line 398 of file stm32_uart.cpp.

401 _read_port(dma_buff_rx.size_),
402 _write_port(tx_queue_size, dma_buff_tx.size_ / 2),
403 dma_buff_rx_(dma_buff_rx),
404 dma_buff_tx_(dma_buff_tx),
405 uart_handle_(uart_handle),
406 id_(stm32_uart_get_id(uart_handle_->Instance))
407#if defined(LIBXR_STM32_UART_GPDMA)
408 ,
409 gpdma_adapter_(uart_handle)
410#endif
411{
412 ASSERT(id_ != STM32_UART_ID_ERROR);
413 ASSERT(dma_buff_rx.size_ == 0U || dma_buff_rx.addr_ != nullptr);
414
415 map[id_] = this;
416
417 if ((uart_handle->Init.Mode & UART_MODE_TX) == UART_MODE_TX)
418 {
419 ASSERT(tx_queue_size > 0U);
420 ASSERT(uart_handle_->hdmatx != NULL);
421#if defined(LIBXR_STM32_UART_GPDMA)
422 ASSERT(uart_handle_->hdmatx->Mode == DMA_NORMAL);
423#endif
425 }
426
427#if defined(LIBXR_STM32_UART_GPDMA)
428 tx_service_.Invoke(TX_EVENT_START_RX, false, [this](uint32_t events, bool in_isr)
429 { HandleTxService(events, in_isr); });
430#else
431 SetRxDMA(false);
432#endif
433}
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
RawData dma_buff_rx_
调用者提供的接收 DMA 缓冲区 / Caller-provided RX DMA buffer.
void SetRxDMA(bool in_isr=false)
初始化循环接收 DMA 并检查启动结果 / Initialize circular RX DMA and check startup.
DoubleBuffer dma_buff_tx_
当前与待发送的 DMA 半区 / Active and pending TX DMA halves.
WritePort _write_port
写请求及发送字节队列 / Write requests and TX byte queue.
ReadPort _read_port
接收字节队列与读请求 / RX byte queue and read requests.
bool Invoke(uint32_t events, bool in_isr, Handler &&handler) noexcept
发布事件并尝试取得执行权 / Publish events and attempt to claim execution.
UART(ReadPortType *read_port, WritePortType *write_port)
UART 构造函数 / UART constructor.
Definition uart.hpp:68
void(* WriteFun)(WritePort &port, bool in_isr)
写入进度通知函数类型 / Write progress notification function type.

Member Function Documentation

◆ AbortCompleteIRQHandler()

void STM32UART::AbortCompleteIRQHandler ( )

通知 HAL 中止完成,由后端恢复收发 / Notify HAL abort completion for backend recovery.

Definition at line 653 of file stm32_uart.cpp.

654{
655 tx_service_.Invoke(TX_EVENT_ABORT, true, [this](uint32_t events, bool in_isr)
656 { HandleTxService(events, in_isr); });
657}

◆ ErrorIRQHandler()

void STM32UART::ErrorIRQHandler ( )

通知错误,由后端处理器启动中止 / Report an error; the service initiates the abort.

Definition at line 647 of file stm32_uart.cpp.

648{
649 tx_service_.Invoke(TX_EVENT_ERROR, true, [this](uint32_t events, bool in_isr)
650 { HandleTxService(events, in_isr); });
651}

◆ RxEventIRQHandler()

void STM32UART::RxEventIRQHandler ( )

通知接收位置变化 / Notify RX position changes.

Definition at line 641 of file stm32_uart.cpp.

642{
643 tx_service_.Invoke(TX_EVENT_RX_WORK, true, [this](uint32_t events, bool in_isr)
644 { HandleTxService(events, in_isr); });
645}

◆ SetConfig()

ErrorCode STM32UART::SetConfig ( UART::Configuration config,
bool in_isr = false )
overridevirtual

提交串口配置请求 / Submit a UART configuration request.

Parameters
config目标配置 / Requested configuration.
in_isr当前调用是否在中断中 / Whether this call is in an ISR.
Returns
接纳返回 OK,配置槽被占用返回 BUSY,参数不支持返回 ARG_ERR 或 NOT_SUPPORT。 OK on admission, BUSY for an occupied slot, ARG_ERR or NOT_SUPPORT for unsupported settings.
Note
接纳后在发送空闲时应用,期间保留已准备的 DMA 数据;不保证返回前已经生效。 Applies when TX is idle while preserving prepared DMA data. May apply after return.

Implements LibXR::UART.

Definition at line 435 of file stm32_uart.cpp.

436{
437 if (config.baudrate == 0U)
438 {
439 return ErrorCode::ARG_ERR;
440 }
441
442 switch (config.parity)
443 {
447 break;
448 default:
450 }
451
452 if (!Stm32DataBitsSupported(config))
453 {
454 return ErrorCode::ARG_ERR;
455 }
456
457 if (!Stm32StopBitsSupported(config))
458 {
459 return ErrorCode::ARG_ERR;
460 }
461
462 ConfigState expected = ConfigState::EMPTY;
463 if (!config_state_.compare_exchange_strong(expected, ConfigState::RESERVED,
464 std::memory_order_acq_rel,
465 std::memory_order_acquire))
466 {
467 return ErrorCode::BUSY;
468 }
469
470 pending_config_ = config;
471 tx_service_.Invoke(TX_EVENT_CONFIG, in_isr, [this](uint32_t events, bool owner_in_isr)
472 { HandleTxService(events, owner_in_isr); });
473 return ErrorCode::OK;
474}
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
@ BUSY
忙碌 / Busy
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45

◆ SetRxDMA()

void STM32UART::SetRxDMA ( bool in_isr = false)

初始化循环接收 DMA 并检查启动结果 / Initialize circular RX DMA and check startup.

Definition at line 553 of file stm32_uart.cpp.

554{
555 if ((uart_handle_->Init.Mode & UART_MODE_RX) == UART_MODE_RX)
556 {
557 ASSERT(uart_handle_->hdmarx != NULL);
558
559#if defined(LIBXR_STM32_UART_GPDMA)
560 [[maybe_unused]] const auto start_linked_list_dma_rx_result =
561 gpdma_adapter_.StartLinkedListDmaRx(static_cast<uint8_t*>(dma_buff_rx_.addr_),
562 dma_buff_rx_.size_, in_isr);
563 REQUIRE_FROM_CALLBACK(start_linked_list_dma_rx_result == HAL_OK, in_isr);
564#else
565 uart_handle_->hdmarx->Init.Mode = DMA_CIRCULAR;
566 [[maybe_unused]] const auto dma_init_result = HAL_DMA_Init(uart_handle_->hdmarx);
567 REQUIRE_FROM_CALLBACK(dma_init_result == HAL_OK, in_isr);
568
569 [[maybe_unused]] const auto uart_ex_receive_to_idle_dma_result =
570 HAL_UARTEx_ReceiveToIdle_DMA(uart_handle_,
571 reinterpret_cast<uint8_t*>(dma_buff_rx_.addr_),
573 REQUIRE_FROM_CALLBACK(uart_ex_receive_to_idle_dma_result == HAL_OK, in_isr);
574#endif
575 }
576}

◆ TxCompleteIRQHandler()

void STM32UART::TxCompleteIRQHandler ( )

通知发送完成,交给后端释放半区 / Notify TX completion to release the active half.

Definition at line 635 of file stm32_uart.cpp.

636{
637 tx_service_.Invoke(TX_EVENT_DONE, true, [this](uint32_t events, bool in_isr)
638 { HandleTxService(events, in_isr); });
639}

◆ WriteFun()

void STM32UART::WriteFun ( WritePort & port,
bool in_isr )
static

通知后端处理已提交的写请求 / Notify the backend of released writes.

Definition at line 219 of file stm32_uart.cpp.

220{
221 auto* uart = LibXR::ContainerOf(&port, &STM32UART::_write_port);
222
223 uart->tx_service_.Invoke(TX_EVENT_WRITE, in_isr,
224 [uart](uint32_t events, bool owner_in_isr)
225 { uart->HandleTxService(events, owner_in_isr); });
226}
OwnerType * ContainerOf(MemberType *ptr, MemberType OwnerType::*member) noexcept
通过成员指针恢复其所属对象指针 Recover the owning object pointer from a member pointer

Member Data Documentation

◆ _read_port

ReadPort LibXR::STM32UART::_read_port

接收字节队列与读请求 / RX byte queue and read requests.

Definition at line 181 of file stm32_uart.hpp.

◆ _write_port

WritePort LibXR::STM32UART::_write_port

写请求及发送字节队列 / Write requests and TX byte queue.

Definition at line 183 of file stm32_uart.hpp.

◆ dma_buff_rx_

RawData LibXR::STM32UART::dma_buff_rx_

调用者提供的接收 DMA 缓冲区 / Caller-provided RX DMA buffer.

Definition at line 186 of file stm32_uart.hpp.

◆ dma_buff_tx_

DoubleBuffer LibXR::STM32UART::dma_buff_tx_

当前与待发送的 DMA 半区 / Active and pending TX DMA halves.

Definition at line 188 of file stm32_uart.hpp.

◆ id_

stm32_uart_id_t LibXR::STM32UART::id_ = STM32_UART_ID_ERROR

Definition at line 198 of file stm32_uart.hpp.

◆ last_rx_pos_

size_t LibXR::STM32UART::last_rx_pos_ = 0

上次已处理的 DMA 接收位置 / Last processed RX DMA position.

Definition at line 191 of file stm32_uart.hpp.

◆ map

STM32UART * STM32UART::map = {nullptr}
static

Definition at line 200 of file stm32_uart.hpp.

◆ tx_busy_

Flag::Plain LibXR::STM32UART::tx_busy_

发送半区是否在使用,仅后端处理器访问 / TX half in use; service-only access.

Definition at line 196 of file stm32_uart.hpp.

◆ uart_handle_

UART_HandleTypeDef* LibXR::STM32UART::uart_handle_

Definition at line 193 of file stm32_uart.hpp.


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