1#include "mspm0_uart.hpp"
12constexpr uint64_t UART_UINT32_MAX = 0xFFFFFFFFULL;
13constexpr uint64_t UART_BAUD_DIVISOR_MIN = 1ULL << 6U;
14constexpr uint64_t UART_BAUD_DIVISOR_MAX = 0xFFFFULL << 6U;
15constexpr DL_DMA_Config UART_DMA_TX_CONFIG = {
17 .triggerType = DL_DMA_TRIGGER_TYPE_EXTERNAL,
18 .transferMode = DL_DMA_SINGLE_TRANSFER_MODE,
19 .extendedMode = DL_DMA_NORMAL_MODE,
20 .srcWidth = DL_DMA_WIDTH_BYTE,
21 .destWidth = DL_DMA_WIDTH_BYTE,
22 .srcIncrement = DL_DMA_ADDR_INCREMENT,
23 .destIncrement = DL_DMA_ADDR_UNCHANGED,
26#if defined(DEVICE_HAS_DMA_FULL_CHANNEL)
27constexpr DL_DMA_Config UART_DMA_RX_CONFIG = {
29 .triggerType = DL_DMA_TRIGGER_TYPE_EXTERNAL,
30 .transferMode = DL_DMA_FULL_CH_REPEAT_SINGLE_TRANSFER_MODE,
31 .extendedMode = DL_DMA_NORMAL_MODE,
32 .srcWidth = DL_DMA_WIDTH_BYTE,
33 .destWidth = DL_DMA_WIDTH_BYTE,
34 .srcIncrement = DL_DMA_ADDR_UNCHANGED,
35 .destIncrement = DL_DMA_ADDR_INCREMENT,
41bool BaudRateRepresentable(uint32_t clock_freq, uint32_t baudrate)
43 if (baudrate == 0U || baudrate > (UART_UINT32_MAX / 16U))
48 const uint64_t clock = clock_freq;
49 const uint64_t baud = baudrate;
50 uint64_t divisor = 0U;
51 if ((baud * 8U) > clock)
53 if (clock > (UART_UINT32_MAX / 64U))
57 divisor = (clock * 64U) / (baud * 3U);
59 else if ((baud * 16U) > clock)
61 if (clock > (UART_UINT32_MAX / 8U))
65 const uint64_t half_baud = baud / 2U;
70 divisor = (((clock * 8U) / half_baud) + 1U) / 2U;
74 if (clock > (UART_UINT32_MAX / 8U))
78 divisor = (((clock * 8U) / baud) + 1U) / 2U;
81 return divisor >= UART_BAUD_DIVISOR_MIN && divisor <= UART_BAUD_DIVISOR_MAX;
88 if (clock_freq == 0U || config.
baudrate == 0U)
93 const uint64_t parity_bits = config.
parity == UART::Parity::NO_PARITY ? 0U : 1U;
95 const uint64_t gap_bits = high_bits + (1U + high_bits);
96 const uint64_t numerator =
static_cast<uint64_t
>(clock_freq) * gap_bits;
97 return (numerator / config.
baudrate) + ((numerator % config.
baudrate) != 0U ? 1U : 0U);
102MSPM0UART* MSPM0UART::instance_map_[MAX_UART_INSTANCES] = {
nullptr};
105 uint32_t tx_queue_size, uint32_t rx_queue_capacity,
107 :
UART(&_read_port, &_write_port),
108 _read_port(rx_queue_capacity),
109 _write_port(tx_queue_size, tx_dma_storage.size_ / 2U),
111 tx_dma_storage_(tx_dma_storage),
112 rx_dma_storage_(rx_dma_storage),
113 tx_half_size_(tx_dma_storage.size_ / 2U)
117 ASSERT(res_.
index < MAX_UART_INSTANCES);
119 ASSERT(instance_map_[res_.
index] ==
nullptr);
120 ASSERT(tx_dma_storage_.
addr_ !=
nullptr);
121 ASSERT(tx_dma_storage_.
size_ > 1U);
122 ASSERT((tx_dma_storage_.
size_ % 2U) == 0U);
123 ASSERT((
reinterpret_cast<uintptr_t
>(tx_dma_storage_.
addr_) %
alignof(
size_t)) == 0U);
124 ASSERT((tx_dma_storage_.
size_ % (2U *
alignof(
size_t))) == 0U);
125 ASSERT(tx_half_size_ <= MSPM0_UART_DMA_MAX_TRANSFER_SIZE);
126 ASSERT(tx_queue_size > 0U);
127 ASSERT(rx_queue_capacity > 0U);
131 ASSERT(rx_dma_storage_.
addr_ !=
nullptr);
132 ASSERT(rx_dma_storage_.
size_ > 1U);
133 ASSERT((rx_dma_storage_.
size_ % 2U) == 0U);
134 ASSERT(rx_dma_storage_.
size_ <= MSPM0_UART_DMA_MAX_TRANSFER_SIZE);
139 ASSERT(rx_dma_storage_.
addr_ ==
nullptr);
140 ASSERT(rx_dma_storage_.
size_ == 0U);
156 for (
const MSPM0UART* other : instance_map_)
158 if (other ==
nullptr)
183 NVIC_DisableIRQ(res_.
irqn);
184 NVIC_ClearPendingIRQ(res_.
irqn);
191 instance_map_[res_.
index] =
this;
195 NVIC_SetPriority(res_.
irqn, 1U);
196 NVIC_EnableIRQ(res_.
irqn);
213 const uint64_t gap = GapCompare(res_.
clock_freq, config);
214 if (gap == 0U || gap > std::numeric_limits<uint16_t>::max())
225 ASSERT(instance !=
nullptr);
226 ASSERT(baudrate > 0U);
229 switch (DL_UART_getWordLength(instance))
231 case DL_UART_WORD_LENGTH_5_BITS:
234 case DL_UART_WORD_LENGTH_6_BITS:
237 case DL_UART_WORD_LENGTH_7_BITS:
240 case DL_UART_WORD_LENGTH_8_BITS:
246 switch (DL_UART_getParityMode(instance))
248 case DL_UART_PARITY_NONE:
251 case DL_UART_PARITY_EVEN:
254 case DL_UART_PARITY_ODD:
261 config.
stop_bits = DL_UART_getStopBits(instance) == DL_UART_STOP_BITS_TWO ? 2U : 1U;
267 const ErrorCode validation = ValidateConfig(config);
273 ConfigState expected = ConfigState::EMPTY;
274 if (!config_state_.compare_exchange_strong(expected, ConfigState::RESERVED,
275 std::memory_order_acq_rel,
276 std::memory_order_acquire))
283 pending_config_ = config;
284 service_.
Invoke(EVENT_CONFIG, in_isr, [
this](uint32_t events,
bool owner_in_isr)
285 { HandleService(events, owner_in_isr); });
292 uart->service_.Invoke(EVENT_WRITE, in_isr, [uart](uint32_t events,
bool owner_in_isr)
293 { uart->HandleService(events, owner_in_isr); });
296void MSPM0UART::NotifyReadSpace(
bool in_isr)
298 service_.
Invoke(EVENT_RX_WORK, in_isr, [
this](uint32_t events,
bool owner_in_isr)
299 { HandleService(events, owner_in_isr); });
302void MSPM0UART::HandleService(uint32_t events,
bool in_isr)
304 if ((events & EVENT_CONFIG) != 0U)
306 DEV_ASSERT_FROM_CALLBACK(
307 config_state_.load(std::memory_order_acquire) == ConfigState::RESERVED, in_isr);
308 config_state_.store(ConfigState::PUBLISHED, std::memory_order_release);
311 if ((events & EVENT_DMA_DONE_TX) != 0U)
313 HandleTxDone(in_isr);
316 if ((events & EVENT_RX_WORK) != 0U)
318 HandleRxWork(in_isr);
321 if ((events & EVENT_EOT_DONE) != 0U)
323 tx_draining_ =
false;
324 DL_UART_disableInterrupt(res_.
instance, EOT_INTERRUPT_MASK);
327 if ((events & (EVENT_CONFIG | EVENT_DMA_DONE_TX | EVENT_EOT_DONE | EVENT_RX_WORK)) !=
330 TryApplyPublishedConfig(in_isr);
333 if (events != 0U && config_state_.load(std::memory_order_acquire) == ConfigState::EMPTY)
335 if ((events & (EVENT_WRITE | EVENT_DMA_DONE_TX | EVENT_CONFIG | EVENT_EOT_DONE)) !=
343void MSPM0UART::FillTx(
bool in_isr)
345 while (config_state_.load(std::memory_order_acquire) == ConfigState::EMPTY)
347 if (active_half_ < 0)
349 for (uint8_t half = 0U; half < 2U; ++half)
351 if (tx_half_size_used_[half] != 0U)
353 if (config_state_.load(std::memory_order_acquire) != ConfigState::EMPTY)
357 active_half_ =
static_cast<int8_t
>(half);
358 StartTxDma(half, tx_half_size_used_[half]);
365 for (uint8_t i = 0U; i < 2U; ++i)
367 if (tx_half_size_used_[i] == 0U)
385 if (config_state_.load(std::memory_order_acquire) != ConfigState::EMPTY)
391 DEV_ASSERT_FROM_CALLBACK(size > 0U && size <= tx_half_size_, in_isr);
392 queue.PopAll(TxHalf(free_half));
393 tx_half_size_used_[free_half] = size;
396 if (active_half_ < 0 &&
397 config_state_.load(std::memory_order_acquire) == ConfigState::EMPTY)
399 active_half_ =
static_cast<int8_t
>(free_half);
400 StartTxDma(free_half, size);
405void MSPM0UART::HandleTxDone(
bool in_isr)
407 DEV_ASSERT_FROM_CALLBACK(active_half_ >= 0 && active_half_ < 2, in_isr);
408 const uint8_t completed =
static_cast<uint8_t
>(active_half_);
409 tx_half_size_used_[completed] = 0U;
412 const uint8_t next = completed ^ 1U;
413 if (tx_half_size_used_[next] != 0U &&
414 config_state_.load(std::memory_order_acquire) == ConfigState::EMPTY)
416 active_half_ =
static_cast<int8_t
>(next);
417 StartTxDma(next, tx_half_size_used_[next]);
421 DL_UART_disableInterrupt(res_.
instance, TX_DONE_INTERRUPT_MASK);
422 DL_UART_disableDMATransmitEvent(res_.
instance);
426void MSPM0UART::HandleRxWork(
bool in_isr)
430 HandleMainRx(in_isr);
434 HandleExtendRx(in_isr);
438void MSPM0UART::HandleMainRx(
bool in_isr)
441 if (queue.EmptySize() != 0U)
443 DL_UART_enableInterrupt(res_.
instance, RX_INTERRUPT_MASK);
446 while (!DL_UART_isRXFIFOEmpty(res_.
instance))
448 if (queue.EmptySize() == 0U)
450 DL_UART_disableInterrupt(res_.
instance, RX_INTERRUPT_MASK);
454 const uint8_t
byte = DL_UART_receiveData(res_.
instance);
455 [[maybe_unused]]
const auto push_batch_result = queue.PushBatch(&
byte, 1U);
456 DEV_ASSERT_FROM_CALLBACK(push_batch_result ==
ErrorCode::OK, in_isr);
461void MSPM0UART::HandleExtendRx(
bool in_isr)
463 const size_t capacity = RxCapacity();
464 DEV_ASSERT_FROM_CALLBACK(capacity > 1U, in_isr);
466 const uint32_t remaining = DL_DMA_getTransferSize(DMA, res_.
dma_rx_channel);
467 DEV_ASSERT_FROM_CALLBACK(remaining <= capacity, in_isr);
469 const size_t position = remaining == 0U ? capacity : capacity - remaining;
470 const size_t cursor = rx_dma_cursor_;
471 DEV_ASSERT_FROM_CALLBACK(cursor < capacity, in_isr);
473 const size_t first_size = position >= cursor ? position - cursor : capacity - cursor;
474 const size_t second_size = position >= cursor ? 0U : position;
475 const size_t observed = first_size + second_size;
478 size_t accepted = std::min(observed, queue.EmptySize());
479 size_t first_accepted = std::min(first_size, accepted);
480 if (first_accepted != 0U)
482 auto* source =
static_cast<const uint8_t*
>(rx_dma_storage_.
addr_) + cursor;
483 [[maybe_unused]]
const auto push_batch_result =
484 queue.PushBatch(source, first_accepted);
485 DEV_ASSERT_FROM_CALLBACK(push_batch_result ==
ErrorCode::OK, in_isr);
486 accepted -= first_accepted;
490 [[maybe_unused]]
const auto push_batch_result =
491 queue.PushBatch(
static_cast<const uint8_t*
>(rx_dma_storage_.
addr_), accepted);
492 DEV_ASSERT_FROM_CALLBACK(push_batch_result ==
ErrorCode::OK, in_isr);
497 rx_dma_cursor_ = position == capacity ? 0U : position;
501void MSPM0UART::HandleUartInterrupt()
503 constexpr uint32_t MASK = RX_ERROR_INTERRUPT_MASK | RX_INTERRUPT_MASK |
504 RX_TIMEOUT_INTERRUPT_MASK | TX_DONE_INTERRUPT_MASK |
505 EOT_INTERRUPT_MASK | RX_GAP_INTERRUPT_MASK;
506 const uint32_t pending = DL_UART_getEnabledInterruptStatus(res_.
instance, MASK);
512 if ((pending & RX_TIMEOUT_INTERRUPT_MASK) != 0U)
514 DL_UART_disableInterrupt(res_.
instance, RX_TIMEOUT_INTERRUPT_MASK);
516 DL_UART_clearInterruptStatus(res_.
instance, pending & MASK);
518 uint32_t events = 0U;
520 (RX_INTERRUPT_MASK | RX_TIMEOUT_INTERRUPT_MASK | RX_GAP_INTERRUPT_MASK)) != 0U)
522 events |= EVENT_RX_WORK;
524 if ((pending & TX_DONE_INTERRUPT_MASK) != 0U)
526 events |= EVENT_DMA_DONE_TX;
528 if ((pending & EOT_INTERRUPT_MASK) != 0U)
530 events |= EVENT_EOT_DONE;
535 service_.
Invoke(events,
true, [
this](uint32_t handled,
bool in_isr)
536 { HandleService(handled, in_isr); });
540void MSPM0UART::HandleRxDmaInterrupt()
542 service_.
Invoke(EVENT_RX_WORK,
true, [
this](uint32_t events,
bool in_isr)
543 { HandleService(events, in_isr); });
548 if (index < MAX_UART_INSTANCES && instance_map_[index] !=
nullptr)
550 instance_map_[index]->HandleUartInterrupt();
556 uint32_t owned_mask = 0U;
561 owned_mask |= DmaRawMask(uart->res_.dma_rx_channel, uart->res_.rx_half_interrupt);
565 if (owned_mask == 0U)
570 const uint32_t pending = DL_DMA_getEnabledInterruptStatus(DMA, owned_mask);
578 const uint32_t mask =
579 DmaRawMask(uart->res_.dma_rx_channel, uart->res_.rx_half_interrupt);
580 const uint32_t hit = pending & mask;
583 DL_DMA_clearInterruptStatus(DMA, hit);
584 uart->HandleRxDmaInterrupt();
592 DEV_ASSERT_FROM_CALLBACK(owner_ !=
nullptr, in_isr);
593 owner_->NotifyReadSpace(in_isr);
596void MSPM0UART::ConfigureTxDma()
598 DL_DMA_Config config = UART_DMA_TX_CONFIG;
601 DL_DMA_clearInterruptStatus(DMA, DmaCompleteMask(res_.
dma_tx_channel));
605void MSPM0UART::ConfigureRxDma()
607#if defined(DEVICE_HAS_DMA_FULL_CHANNEL)
613 DL_DMA_Config config = UART_DMA_RX_CONFIG;
619 static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(&res_.
instance->RXDATA)));
622 static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(rx_dma_storage_.
addr_)));
624 static_cast<uint16_t
>(rx_dma_storage_.
size_));
627 DL_DMA_Full_Ch_setEarlyInterruptThreshold(DMA, res_.
dma_rx_channel,
628 DL_DMA_EARLY_INTERRUPT_THRESHOLD_HALF);
644 DL_UART_WORD_LENGTH word_length = DL_UART_WORD_LENGTH_8_BITS;
648 word_length = DL_UART_WORD_LENGTH_5_BITS;
651 word_length = DL_UART_WORD_LENGTH_6_BITS;
654 word_length = DL_UART_WORD_LENGTH_7_BITS;
663 DL_UART_PARITY parity = DL_UART_PARITY_NONE;
666 parity = DL_UART_PARITY_EVEN;
670 parity = DL_UART_PARITY_ODD;
673 DL_UART_setWordLength(res_.
instance, word_length);
674 DL_UART_setParityMode(res_.
instance, parity);
675 DL_UART_setStopBits(res_.
instance, config.
stop_bits == 2U ? DL_UART_STOP_BITS_TWO
676 : DL_UART_STOP_BITS_ONE);
677 DL_UART_setCommunicationMode(res_.
instance, DL_UART_MODE_NORMAL);
678 DL_UART_setDirection(res_.
instance, DL_UART_DIRECTION_TX_RX);
680 DL_UART_setTXFIFOThreshold(res_.
instance, DL_UART_TX_FIFO_LEVEL_ONE_ENTRY);
681 DL_UART_setRXFIFOThreshold(res_.
instance, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY);
682 DL_UART_setRXInterruptTimeout(res_.
instance, 0U);
687 DL_UART_setLINCounterValue(res_.
instance, 0U);
688 DL_UART_setLINCounterCompareValue(
690 DL_UART_enableLINCounterCompareMatch(res_.
instance);
691 DL_UART_disableLINCountWhileLow(res_.
instance);
692 DL_UART_enableLINCounterClearOnFallingEdge(res_.
instance);
693 DL_UART_enableLINCounter(res_.
instance);
697void MSPM0UART::StartDataPath()
699 DL_UART_disableInterrupt(res_.
instance, 0xFFFFFFFFU);
700 DL_UART_clearInterruptStatus(res_.
instance, 0xFFFFFFFFU);
701 DL_UART_clearDMATransmitEventStatus(res_.
instance);
702 DL_UART_clearDMAReceiveEventStatus(res_.
instance, DL_UART_DMA_INTERRUPT_RX);
703 DL_UART_disableDMAReceiveEvent(res_.
instance, DL_UART_DMA_INTERRUPT_RX);
704 DL_UART_disableDMATransmitEvent(res_.
instance);
705 DL_UART_enableInterrupt(res_.
instance, RX_ERROR_INTERRUPT_MASK);
709 DL_UART_enableInterrupt(res_.
instance, RX_INTERRUPT_MASK);
714 DL_DMA_clearInterruptStatus(DMA, dma_mask);
715 DL_DMA_enableInterrupt(DMA, dma_mask);
717 DL_UART_enableInterrupt(res_.
instance, RX_GAP_INTERRUPT_MASK);
718 DL_UART_enableDMAReceiveEvent(res_.
instance, DL_UART_DMA_INTERRUPT_RX);
726void MSPM0UART::StopDataPath()
728 DL_UART_disableInterrupt(res_.
instance, RX_ERROR_INTERRUPT_MASK | RX_INTERRUPT_MASK |
729 RX_TIMEOUT_INTERRUPT_MASK |
730 TX_DONE_INTERRUPT_MASK |
731 EOT_INTERRUPT_MASK | RX_GAP_INTERRUPT_MASK);
732 DL_UART_disableDMAReceiveEvent(res_.
instance, DL_UART_DMA_INTERRUPT_RX);
733 DL_UART_disableDMATransmitEvent(res_.
instance);
742void MSPM0UART::DiscardRxFifo()
744 while (!DL_UART_isRXFIFOEmpty(res_.
instance))
746 (void)DL_UART_receiveData(res_.
instance);
750void MSPM0UART::StartTxDma(uint8_t half,
size_t size)
752 DEV_ASSERT(half < 2U);
753 DEV_ASSERT(size > 0U && size <= tx_half_size_);
756 DL_DMA_clearInterruptStatus(DMA, DmaCompleteMask(res_.
dma_tx_channel));
758 static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(TxHalf(half))));
761 static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(&res_.
instance->TXDATA)));
762 DL_DMA_setTransferSize(DMA, res_.
dma_tx_channel,
static_cast<uint16_t
>(size));
763 DL_UART_clearInterruptStatus(res_.
instance,
764 TX_DONE_INTERRUPT_MASK | EOT_INTERRUPT_MASK);
766 DL_UART_enableInterrupt(res_.
instance, TX_DONE_INTERRUPT_MASK);
767 DL_UART_enableDMATransmitEvent(res_.
instance);
772void MSPM0UART::TryApplyPublishedConfig(
bool in_isr)
774 if (config_state_.load(std::memory_order_acquire) != ConfigState::PUBLISHED)
779 if (active_half_ >= 0)
791 DL_UART_enableInterrupt(res_.
instance, EOT_INTERRUPT_MASK);
803 config_state_.store(ConfigState::EMPTY, std::memory_order_release);
807 service_.
Publish(EVENT_WRITE | EVENT_RX_WORK);
811#if defined(UART0_BASE)
814#if defined(UART1_BASE)
817#if defined(UART2_BASE)
820#if defined(UART3_BASE)
823#if defined(UART4_BASE)
826#if defined(UART5_BASE)
829#if defined(UART6_BASE)
832#if defined(UART7_BASE)
使用双缓冲 DMA 发送的 MSPM0 串口 / MSPM0 UART with double-buffered DMA TX.
static constexpr uint8_t ResolveIndex(IRQn_Type irqn)
根据 UART 中断号取得实例编号 / Resolve an instance index from its UART IRQ.
static void OnDmaInterrupt()
分派本驱动登记的接收 DMA 中断 / Dispatch registered UART RX DMA interrupts.
static constexpr uint8_t INVALID_DMA_CHANNEL
无 DMA 通道的标记 / Sentinel for no DMA channel.
static void WriteFun(WritePort &port, bool in_isr)
通知已提交的写请求 / Notify released write requests.
ErrorCode SetConfig(UART::Configuration config, bool in_isr=false) override
提交串口配置 / Submit a UART configuration.
static UART::Configuration BuildConfigFromSysCfg(UART_Regs *instance, uint32_t baudrate)
MSPM0UART(Resources res, RawData tx_dma_storage, RawData rx_dma_storage, uint32_t tx_queue_size=5U, uint32_t rx_queue_capacity=128U, UART::Configuration config={115200, UART::Parity::NO_PARITY, 8U, 1U})
构造串口并配置所选 DMA 路径 / Construct the UART and selected DMA paths.
@ EXTEND_DMA
扩展 UART DMA / Extend UART DMA.
@ MAIN_BYTE_IRQ
主 UART 字节中断 / Main UART byte interrupts.
static void OnInterrupt(uint8_t index)
按实例编号分派 UART 中断 / Dispatch a UART IRQ by instance index.
void OnReadQueueSpaceAvailable(bool in_isr) override
发布接收空间可用通知 / Publish RX space availability.
void SetOwner(MSPM0UART *owner)
在串口初始化时绑定后端 / Bind the backend during UART initialization.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
void Publish()
结束本次写入并通知挂起读 / End production and notify a pending read.
ReadQueue GetReadQueue(bool in_isr=false)
获取后端接收入队接口 / Obtain the backend RX producer interface.
bool Invoke(uint32_t events, bool in_isr, Handler &&handler) noexcept
发布事件并尝试取得执行权 / Publish events and attempt to claim execution.
void Publish(uint32_t events) noexcept
为已有或确定会出现的执行者发布事件 / Publish for an active or guaranteed executor.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
@ NO_PARITY
无校验 / No parity
size_t AvailableSize() const
获取当前队头的剩余长度 / Get the current front remainder.
基于 SPSC 字节队列的写端口 / Write endpoint backed by an SPSC byte queue.
WriteQueue GetWriteQueue(bool in_isr=false)
获取已提交队头的出队接口 / Obtain a consumer interface for the released front.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ OK
操作成功 / Operation successful
@ ARG_ERR
参数错误 / Argument error
void(* WriteFun)(WritePort &port, bool in_isr)
写入进度通知函数类型 / Write progress notification function type.
OwnerType * ContainerOf(MemberType *ptr, MemberType OwnerType::*member) noexcept
通过成员指针恢复其所属对象指针 Recover the owning object pointer from a member pointer
由 BSP 提供的 UART 与 DMA 绑定 / UART and DMA bindings supplied by the BSP.
uint8_t dma_rx_channel
接收 FULL-DMA 通道,Main 使用无效编号 / RX full channel, invalid for Main.
RxMode rx_mode
选择的接收路径 / Selected RX path.
uint32_t clock_freq
UART 输入时钟频率 / UART input clock frequency.
uint8_t dma_rx_trigger
UART 接收 DMA 触发源,Main 为零 / RX DMA trigger, zero for Main.
UART_Regs * instance
UART 寄存器 / UART registers.
bool rx_half_interrupt
是否使用接收半传输中断 / Enable RX half-transfer interrupts.
IRQn_Type irqn
UART 中断号 / UART interrupt number.
uint8_t index
ResolveIndex 返回的编号 / Index returned by ResolveIndex.
uint8_t dma_tx_channel
发送 DMA 通道 / TX DMA channel.
uint8_t dma_tx_trigger
UART 发送 DMA 触发源 / UART TX DMA trigger.
UART 配置结构体 / UART configuration structure.
uint8_t stop_bits
停止位长度 / Number of stop bits
uint32_t baudrate
波特率 / Baud rate