3#include <ti/driverlib/dl_dma.h>
4#include <ti/driverlib/dl_uart_main.h>
11#include "libxr_type.hpp"
12#include "serialized_service.hpp"
13#include "ti_msp_dl_config.h"
122 uint32_t tx_queue_size = 5U, uint32_t rx_queue_capacity = 128U,
170#if defined(UART0_BASE)
174#if defined(UART1_BASE)
178#if defined(UART2_BASE)
182#if defined(UART3_BASE)
186#if defined(UART4_BASE)
190#if defined(UART5_BASE)
194#if defined(UART6_BASE)
198#if defined(UART7_BASE)
209 enum class ConfigState : uint32_t
216 static constexpr uint8_t MAX_UART_INSTANCES = 8U;
217 static_assert(DMA_SYS_N_DMA_CHANNEL <= 16U);
218 static constexpr uint8_t MAX_DMA_CHANNELS =
static_cast<uint8_t
>(DMA_SYS_N_DMA_CHANNEL);
219 static constexpr uint32_t MSPM0_UART_DMA_MAX_TRANSFER_SIZE = 0xFFFFU;
221 static constexpr uint32_t EVENT_WRITE = 1U << 0U;
222 static constexpr uint32_t EVENT_DMA_DONE_TX = 1U << 1U;
223 static constexpr uint32_t EVENT_EOT_DONE = 1U << 2U;
224 static constexpr uint32_t EVENT_CONFIG = 1U << 3U;
225 static constexpr uint32_t EVENT_RX_WORK = 1U << 4U;
227 static constexpr uint32_t RX_ERROR_INTERRUPT_MASK =
228 DL_UART_INTERRUPT_OVERRUN_ERROR | DL_UART_INTERRUPT_BREAK_ERROR |
229 DL_UART_INTERRUPT_PARITY_ERROR | DL_UART_INTERRUPT_FRAMING_ERROR |
230 DL_UART_INTERRUPT_NOISE_ERROR;
232 static constexpr uint32_t RX_INTERRUPT_MASK = DL_UART_INTERRUPT_RX;
233 static constexpr uint32_t RX_TIMEOUT_INTERRUPT_MASK =
234 DL_UART_INTERRUPT_RX_TIMEOUT_ERROR;
235 static constexpr uint32_t RX_GAP_INTERRUPT_MASK = DL_UART_INTERRUPT_LINC0_MATCH;
236 static constexpr uint32_t TX_DONE_INTERRUPT_MASK = DL_UART_INTERRUPT_DMA_DONE_TX;
237 static constexpr uint32_t EOT_INTERRUPT_MASK = DL_UART_INTERRUPT_EOT_DONE;
240 void HandleService(uint32_t events,
bool in_isr);
242 void FillTx(
bool in_isr);
244 void HandleTxDone(
bool in_isr);
246 void HandleRxWork(
bool in_isr);
248 void HandleMainRx(
bool in_isr);
250 void HandleExtendRx(
bool in_isr);
252 void NotifyReadSpace(
bool in_isr);
254 void HandleUartInterrupt();
256 void HandleRxDmaInterrupt();
259 [[nodiscard]]
ErrorCode ValidateConfig(UART::Configuration config)
const;
261 void ApplyConfig(UART::Configuration config);
263 void TryApplyPublishedConfig(
bool in_isr);
265 void ConfigureTxDma();
267 void ConfigureRxDma();
269 void StartDataPath();
273 void DiscardRxFifo();
275 void StartTxDma(uint8_t half,
size_t size);
278 [[nodiscard]] uint8_t* TxHalf(uint8_t half)
const
280 return static_cast<uint8_t*
>(tx_dma_storage_.
addr_) +
281 static_cast<size_t>(half) * tx_half_size_;
285 [[nodiscard]]
size_t RxCapacity()
const {
return rx_dma_storage_.
size_; }
288 static uint32_t DmaCompleteMask(uint8_t channel)
290 return channel < MAX_DMA_CHANNELS ? (1UL << channel) : 0U;
294 static uint32_t DmaEarlyMask(uint8_t channel)
296 return channel < 8U ? (1UL << (16U + channel)) : 0U;
300 static uint32_t DmaRawMask(uint8_t channel,
bool half)
302 return DmaCompleteMask(channel) | (half ? DmaEarlyMask(channel) : 0U);
308 RawData tx_dma_storage_{};
310 RawData rx_dma_storage_{};
312 size_t tx_half_size_ = 0U;
314 std::array<size_t, 2U> tx_half_size_used_{};
316 int8_t active_half_ = -1;
319 bool tx_draining_ =
false;
321 size_t rx_dma_cursor_ = 0U;
324 SerializedService service_{};
326 std::atomic<ConfigState> config_state_{ConfigState::EMPTY};
328 UART::Configuration pending_config_{};
331 static MSPM0UART* instance_map_[MAX_UART_INSTANCES];
339template <IRQn_Type UartIrqn, uint32_t TxDmaChannel, IRQn_Type TxDmaOwnerIrqn,
341MSPM0UART::Resources MakeMSPM0MainUartResources(UART_Regs* instance, uint32_t clock_freq,
342 uint8_t tx_dma_trigger)
344 static_assert(TxBinding);
345 static_assert(TxDmaOwnerIrqn == UartIrqn);
346 static_assert(TxDmaChannel < DMA_SYS_N_DMA_CHANNEL);
353 static_cast<uint8_t
>(TxDmaChannel),
359template <IRQn_Type UartIrqn, uint32_t TxDmaChannel, IRQn_Type TxDmaOwnerIrqn,
360 bool TxBinding, uint32_t RxDmaChannel, IRQn_Type RxDmaOwnerIrqn,
bool RxBinding,
361 bool ExtendCapable,
bool FullRxChannel,
bool HalfRxInterrupt>
362MSPM0UART::Resources MakeMSPM0ExtendUartResources(UART_Regs* instance,
364 uint8_t tx_dma_trigger,
365 uint8_t rx_dma_trigger)
367 static_assert(TxBinding);
368 static_assert(RxBinding);
369 static_assert(TxDmaOwnerIrqn == UartIrqn);
370 static_assert(RxDmaOwnerIrqn == UartIrqn);
371 static_assert(TxDmaChannel < DMA_SYS_N_DMA_CHANNEL);
372 static_assert(RxDmaChannel < DMA_SYS_N_DMA_FULL_CHANNEL);
373 static_assert(TxDmaChannel != RxDmaChannel);
374 static_assert(ExtendCapable);
375 static_assert(FullRxChannel);
376 static_assert(!HalfRxInterrupt || RxDmaChannel < 8U);
383 static_cast<uint8_t
>(TxDmaChannel),
385 static_cast<uint8_t
>(RxDmaChannel),
391#define LIBXR_MSPM0_UART_CAT_IMPL(left, right) left##right
392#define LIBXR_MSPM0_UART_CAT(left, right) LIBXR_MSPM0_UART_CAT_IMPL(left, right)
393#define LIBXR_MSPM0_UART_PROPERTY(name, suffix) LIBXR_MSPM0_UART_CAT(name, suffix)
394#define LIBXR_MSPM0_UART_DMA_CHANNEL(name) LIBXR_MSPM0_UART_CAT(name, _CHAN_ID)
395#define LIBXR_MSPM0_UART_DMA_PROPERTY(name, suffix) LIBXR_MSPM0_UART_CAT(name, suffix)
396#define LIBXR_MSPM0_UART_DMA_TRIGGER_IMPL(instance, direction) \
397 DMA_##instance##_##direction##_TRIG
398#define LIBXR_MSPM0_UART_DMA_TRIGGER(instance, direction) \
399 LIBXR_MSPM0_UART_DMA_TRIGGER_IMPL(instance, direction)
411#define MSPM0_UART_MAIN_INIT(name, tx_dma, tx_storage_addr, tx_storage_size, \
412 tx_queue_size, rx_queue_capacity) \
413 ::LibXR::Detail::MakeMSPM0MainUartResources< \
414 name##_INST_INT_IRQN, static_cast<uint32_t>(LIBXR_MSPM0_UART_DMA_CHANNEL(tx_dma)), \
415 LIBXR_MSPM0_UART_DMA_PROPERTY(tx_dma, _LIBXR_UART_IRQN), \
416 static_cast<bool>(LIBXR_MSPM0_UART_DMA_PROPERTY(tx_dma, _LIBXR_UART_TX))>( \
417 name##_INST, name##_INST_FREQUENCY, \
418 static_cast<uint8_t>(LIBXR_MSPM0_UART_DMA_TRIGGER(name##_INST, TX))), \
419 ::LibXR::RawData{static_cast<void*>(tx_storage_addr), (tx_storage_size)}, \
420 ::LibXR::RawData{}, (tx_queue_size), (rx_queue_capacity), \
421 ::LibXR::MSPM0UART::BuildConfigFromSysCfg(name##_INST, \
422 static_cast<uint32_t>(name##_BAUD_RATE))
435#define MSPM0_UART_EXTEND_INIT(name, tx_dma, rx_dma, tx_storage_addr, tx_storage_size, \
436 tx_queue_size, rx_dma_storage_addr, rx_dma_storage_size, \
438 ::LibXR::Detail::MakeMSPM0ExtendUartResources< \
439 name##_INST_INT_IRQN, static_cast<uint32_t>(LIBXR_MSPM0_UART_DMA_CHANNEL(tx_dma)), \
440 LIBXR_MSPM0_UART_DMA_PROPERTY(tx_dma, _LIBXR_UART_IRQN), \
441 static_cast<bool>(LIBXR_MSPM0_UART_DMA_PROPERTY(tx_dma, _LIBXR_UART_TX)), \
442 static_cast<uint32_t>(LIBXR_MSPM0_UART_DMA_CHANNEL(rx_dma)), \
443 LIBXR_MSPM0_UART_DMA_PROPERTY(rx_dma, _LIBXR_UART_IRQN), \
444 static_cast<bool>(LIBXR_MSPM0_UART_DMA_PROPERTY(rx_dma, _LIBXR_UART_RX)), \
445 static_cast<bool>(LIBXR_MSPM0_UART_PROPERTY(name, _LIBXR_EXTEND_CAPABLE)), \
446 static_cast<bool>(LIBXR_MSPM0_UART_DMA_PROPERTY(rx_dma, _LIBXR_FULL_CHANNEL)), \
447 static_cast<bool>(LIBXR_MSPM0_UART_DMA_PROPERTY(rx_dma, _LIBXR_HALF_INTERRUPT))>( \
448 name##_INST, name##_INST_FREQUENCY, \
449 static_cast<uint8_t>(LIBXR_MSPM0_UART_DMA_TRIGGER(name##_INST, TX)), \
450 static_cast<uint8_t>(LIBXR_MSPM0_UART_DMA_TRIGGER(name##_INST, RX))), \
451 ::LibXR::RawData{static_cast<void*>(tx_storage_addr), (tx_storage_size)}, \
452 ::LibXR::RawData{static_cast<void*>(rx_dma_storage_addr), (rx_dma_storage_size)}, \
453 (tx_queue_size), (rx_queue_capacity), \
454 ::LibXR::MSPM0UART::BuildConfigFromSysCfg(name##_INST, \
455 static_cast<uint32_t>(name##_BAUD_RATE))
使用双缓冲 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.
bool RxHalfInterruptEnabled() const
查询是否使用接收半传输通知 / Check RX half-transfer notification use.
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.
RxMode GetRxMode() const
获取构造时选择的接收路径 / Get the selected RX path.
通知串口恢复接收的读端口 / Read port that resumes UART reception.
void OnReadQueueSpaceAvailable(bool in_isr) override
发布接收空间可用通知 / Publish RX space availability.
void SetOwner(MSPM0UART *owner)
在串口初始化时绑定后端 / Bind the backend during UART initialization.
MSPM0UARTReadPort(size_t capacity)
按字节容量构造接收队列 / Construct an RX queue with the byte capacity.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
基于 SPSC 字节队列的读端口 / Read endpoint backed by an SPSC byte queue.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
@ NO_PARITY
无校验 / No parity
基于 SPSC 字节队列的写端口 / Write endpoint backed by an SPSC byte queue.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
void(* WriteFun)(WritePort &port, bool in_isr)
写入进度通知函数类型 / Write progress notification function type.
由 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.