1#include "mspm0_uart.hpp"
7MSPM0UART* MSPM0UART::instance_map_[MAX_UART_INSTANCES] = {
nullptr};
9static constexpr uint32_t MSPM0_UART_RX_ERROR_INTERRUPT_MASK =
10 DL_UART_INTERRUPT_OVERRUN_ERROR | DL_UART_INTERRUPT_BREAK_ERROR |
11 DL_UART_INTERRUPT_PARITY_ERROR | DL_UART_INTERRUPT_FRAMING_ERROR |
12 DL_UART_INTERRUPT_NOISE_ERROR;
14static constexpr uint32_t MSPM0_UART_BASE_INTERRUPT_MASK =
17 DL_UART_INTERRUPT_RX | DL_UART_INTERRUPT_TX | DL_UART_INTERRUPT_ADDRESS_MATCH |
18 MSPM0_UART_RX_ERROR_INTERRUPT_MASK;
20MSPM0UART::MSPM0UART(Resources res,
RawData rx_stage_buffer, uint32_t tx_queue_size,
22 :
UART(&_read_port, &_write_port),
23 _read_port(rx_stage_buffer.size_),
24 _write_port(tx_queue_size, tx_buffer_size),
27 ASSERT(res_.instance !=
nullptr);
28 ASSERT(res_.clock_freq > 0);
29 ASSERT(rx_stage_buffer.
addr_ !=
nullptr);
30 ASSERT(rx_stage_buffer.
size_ > 0);
31 ASSERT(tx_queue_size > 0);
32 ASSERT(tx_buffer_size > 0);
37 ASSERT(res_.index < MAX_UART_INSTANCES);
38 ASSERT(instance_map_[res_.index] ==
nullptr);
39 instance_map_[res_.index] =
this;
41 NVIC_ClearPendingIRQ(res_.irqn);
42 NVIC_EnableIRQ(res_.irqn);
44 const ErrorCode SET_CFG_ANS = SetConfig(config);
45 ASSERT(SET_CFG_ANS == ErrorCode::OK);
51 ASSERT(instance !=
nullptr);
52 ASSERT(baudrate > 0U);
56 switch (DL_UART_getWordLength(instance))
58 case DL_UART_WORD_LENGTH_5_BITS:
61 case DL_UART_WORD_LENGTH_6_BITS:
64 case DL_UART_WORD_LENGTH_7_BITS:
67 case DL_UART_WORD_LENGTH_8_BITS:
73 switch (DL_UART_getParityMode(instance))
75 case DL_UART_PARITY_NONE:
78 case DL_UART_PARITY_EVEN:
81 case DL_UART_PARITY_ODD:
91 config.
stop_bits = (DL_UART_getStopBits(instance) == DL_UART_STOP_BITS_TWO) ? 2U : 1U;
112 DL_UART_WORD_LENGTH word_length = DL_UART_WORD_LENGTH_8_BITS;
116 word_length = DL_UART_WORD_LENGTH_5_BITS;
119 word_length = DL_UART_WORD_LENGTH_6_BITS;
122 word_length = DL_UART_WORD_LENGTH_7_BITS;
125 word_length = DL_UART_WORD_LENGTH_8_BITS;
131 DL_UART_PARITY parity = DL_UART_PARITY_NONE;
135 parity = DL_UART_PARITY_NONE;
138 parity = DL_UART_PARITY_EVEN;
141 parity = DL_UART_PARITY_ODD;
147 const DL_UART_STOP_BITS STOP_BITS =
148 (config.
stop_bits == 2) ? DL_UART_STOP_BITS_TWO : DL_UART_STOP_BITS_ONE;
150 DL_UART_changeConfig(res_.instance);
152 DL_UART_setWordLength(res_.instance, word_length);
153 DL_UART_setParityMode(res_.instance, parity);
154 DL_UART_setStopBits(res_.instance, STOP_BITS);
156 DL_UART_enableFIFOs(res_.instance);
157 DL_UART_setTXFIFOThreshold(res_.instance, DL_UART_TX_FIFO_LEVEL_ONE_ENTRY);
159 DL_UART_configBaudRate(res_.instance, res_.clock_freq, config.
baudrate);
161 ApplyRxTimeoutMode();
163 DL_UART_clearInterruptStatus(res_.instance, 0xFFFFFFFF);
164 DL_UART_enableInterrupt(res_.instance, MSPM0_UART_BASE_INTERRUPT_MASK);
165 DL_UART_disableInterrupt(res_.instance,
166 DL_UART_INTERRUPT_TX | GetTimeoutInterruptMask());
168 tx_active_valid_ =
false;
169 tx_active_remaining_ = 0;
170 tx_active_total_ = 0;
172 DL_UART_enable(res_.instance);
180 DL_UART_enableInterrupt(uart->res_.instance, DL_UART_INTERRUPT_TX);
181 uart->res_.instance->CPU_INT.ISET = DL_UART_INTERRUPT_TX;
188 const uint32_t TIMEOUT_MASK = uart->GetTimeoutInterruptMask();
189 if (TIMEOUT_MASK != 0U)
193 if (uart->rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
197 uart->ResetLinCounter();
200 DL_UART_clearInterruptStatus(uart->res_.instance, TIMEOUT_MASK);
201 DL_UART_enableInterrupt(uart->res_.instance, TIMEOUT_MASK);
207MSPM0UART::RxTimeoutMode MSPM0UART::ResolveRxTimeoutMode()
const
213#if defined(UART_0_INST) && defined(UART_0_COUNTER_COMPARE_VALUE)
214 if (res_.instance == UART_0_INST)
219 return RxTimeoutMode::LIN_COMPARE;
223 if (DL_UART_isLINCounterEnabled(res_.instance) &&
224 DL_UART_isLINCounterCompareMatchEnabled(res_.instance))
229 return RxTimeoutMode::LIN_COMPARE;
234 return RxTimeoutMode::BYTE_INTERRUPT;
237uint32_t MSPM0UART::GetTimeoutInterruptMask()
const
239 switch (rx_timeout_mode_)
243 case RxTimeoutMode::LIN_COMPARE:
244 return DL_UART_INTERRUPT_LINC0_MATCH;
247 case RxTimeoutMode::BYTE_INTERRUPT:
253uint32_t MSPM0UART::GetTimeoutInterruptEnabledMask()
const
255 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
256 if (TIMEOUT_MASK == 0U)
260 return DL_UART_getEnabledInterrupts(res_.instance, TIMEOUT_MASK);
263uint32_t MSPM0UART::GetTimeoutInterruptMaskedStatus()
const
265 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
266 if (TIMEOUT_MASK == 0U)
270 return DL_UART_getEnabledInterruptStatus(res_.instance, TIMEOUT_MASK);
273uint32_t MSPM0UART::GetTimeoutInterruptRawStatus()
const
275 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
276 if (TIMEOUT_MASK == 0U)
280 return DL_UART_getRawInterruptStatus(res_.instance, TIMEOUT_MASK);
283uint32_t MSPM0UART::GetRxInterruptTimeoutValue()
const
285 return DL_UART_getRXInterruptTimeout(res_.instance);
288uint32_t MSPM0UART::GetRxFifoThresholdValue()
const
290 return static_cast<uint32_t
>(DL_UART_getRXFIFOThreshold(res_.instance));
293void MSPM0UART::ResetLinCounter()
295 if (rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
297 DL_UART_setLINCounterValue(res_.instance, 0);
301void MSPM0UART::ApplyRxTimeoutMode()
303 rx_timeout_mode_ = ResolveRxTimeoutMode();
307 DL_UART_setCommunicationMode(res_.instance, DL_UART_MODE_NORMAL);
308 DL_UART_setAddressMask(res_.instance, 0U);
309 DL_UART_setAddress(res_.instance, 0U);
310 DL_UART_setRXFIFOThreshold(res_.instance, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY);
311 DL_UART_setRXInterruptTimeout(res_.instance, 0U);
313 switch (rx_timeout_mode_)
317 case RxTimeoutMode::LIN_COMPARE:
318 if (!DL_UART_isLINCounterEnabled(res_.instance))
320 DL_UART_enableLINCounter(res_.instance);
322 if (!DL_UART_isLINCounterCompareMatchEnabled(res_.instance))
324 DL_UART_enableLINCounterCompareMatch(res_.instance);
326#if defined(UART_0_COUNTER_COMPARE_VALUE)
327 DL_UART_setLINCounterCompareValue(res_.instance, UART_0_COUNTER_COMPARE_VALUE);
329 DL_UART_disableLINCountWhileLow(res_.instance);
335 case RxTimeoutMode::BYTE_INTERRUPT:
341void MSPM0UART::OnInterrupt(uint8_t index)
343 if (index >= MAX_UART_INSTANCES)
348 auto* uart = instance_map_[index];
354 uart->HandleInterrupt();
357void MSPM0UART::HandleInterrupt()
359 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
360 const uint32_t IRQ_MASK = MSPM0_UART_BASE_INTERRUPT_MASK | TIMEOUT_MASK;
362 uint32_t pending = DL_UART_getEnabledInterruptStatus(res_.instance, IRQ_MASK);
363 if (TIMEOUT_MASK != 0U)
367 pending |= DL_UART_getRawInterruptStatus(res_.instance, TIMEOUT_MASK);
370 const uint32_t
PENDING = pending;
376 constexpr uint32_t RX_PENDING_MASK =
377 DL_UART_INTERRUPT_RX | DL_UART_INTERRUPT_ADDRESS_MATCH;
378 if ((
PENDING & RX_PENDING_MASK) != 0U)
380 HandleRxInterrupt(TIMEOUT_MASK);
381 if ((
PENDING & DL_UART_INTERRUPT_ADDRESS_MATCH) != 0U)
383 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_ADDRESS_MATCH);
387 if (TIMEOUT_MASK != 0U)
389 HandleRxTimeoutInterrupt(
PENDING, TIMEOUT_MASK);
392 if ((
PENDING & DL_UART_INTERRUPT_OVERRUN_ERROR) != 0U)
394 HandleErrorInterrupt(DL_UART_IIDX_OVERRUN_ERROR);
396 if ((
PENDING & DL_UART_INTERRUPT_BREAK_ERROR) != 0U)
398 HandleErrorInterrupt(DL_UART_IIDX_BREAK_ERROR);
400 if ((
PENDING & DL_UART_INTERRUPT_PARITY_ERROR) != 0U)
402 HandleErrorInterrupt(DL_UART_IIDX_PARITY_ERROR);
404 if ((
PENDING & DL_UART_INTERRUPT_FRAMING_ERROR) != 0U)
406 HandleErrorInterrupt(DL_UART_IIDX_FRAMING_ERROR);
408 if ((
PENDING & DL_UART_INTERRUPT_NOISE_ERROR) != 0U)
410 HandleErrorInterrupt(DL_UART_IIDX_NOISE_ERROR);
413 if ((
PENDING & DL_UART_INTERRUPT_TX) != 0U)
415 HandleTxInterrupt(
true);
419void MSPM0UART::HandleRxInterrupt(uint32_t timeout_mask)
422 bool received =
false;
424 DrainRxFIFO(received, pushed);
426 if (received && rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
438 if (timeout_mask != 0U &&
443 DL_UART_disableInterrupt(res_.instance, timeout_mask);
444 DL_UART_clearInterruptStatus(res_.instance, timeout_mask);
447 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_RX);
450void MSPM0UART::DrainRxFIFO(
bool& received,
bool& pushed)
452 while (!DL_UART_isRXFIFOEmpty(res_.instance))
454 const uint8_t RX_BYTE = DL_UART_receiveData(res_.instance);
468void MSPM0UART::HandleRxTimeoutInterrupt(uint32_t pending, uint32_t timeout_mask)
472 if ((timeout_mask == 0U) || ((pending & timeout_mask) == 0U))
478 DL_UART_clearInterruptStatus(res_.instance, pending & timeout_mask);
485 bool received =
false;
487 DrainRxFIFO(received, pushed);
494 if (rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
502 DL_UART_disableInterrupt(res_.instance, timeout_mask);
505void MSPM0UART::HandleTxInterrupt(
bool in_isr)
511 if (!tx_active_valid_)
515 DisableTxInterrupt();
519 DL_UART_enableInterrupt(res_.instance, DL_UART_INTERRUPT_TX);
520 res_.instance->CPU_INT.ISET = DL_UART_INTERRUPT_TX;
526 tx_active_total_ = tx_active_info_.
data.
size_;
527 tx_active_remaining_ = tx_active_total_;
528 tx_active_valid_ =
true;
531 while (tx_active_remaining_ > 0 && !DL_UART_isTXFIFOFull(res_.instance))
537 tx_active_valid_ =
false;
538 tx_active_remaining_ = 0;
539 tx_active_total_ = 0;
540 DisableTxInterrupt();
544 DL_UART_transmitData(res_.instance, tx_byte);
545 tx_active_remaining_--;
548 if (tx_active_remaining_ > 0)
554 tx_active_valid_ =
false;
555 tx_active_remaining_ = 0;
556 tx_active_total_ = 0;
560void MSPM0UART::HandleErrorInterrupt(DL_UART_IIDX iidx)
562 uint32_t clear_mask = 0;
566 case DL_UART_IIDX_OVERRUN_ERROR:
567 clear_mask = DL_UART_INTERRUPT_OVERRUN_ERROR;
570 case DL_UART_IIDX_BREAK_ERROR:
571 clear_mask = DL_UART_INTERRUPT_BREAK_ERROR;
574 case DL_UART_IIDX_PARITY_ERROR:
575 clear_mask = DL_UART_INTERRUPT_PARITY_ERROR;
578 case DL_UART_IIDX_FRAMING_ERROR:
579 clear_mask = DL_UART_INTERRUPT_FRAMING_ERROR;
582 case DL_UART_IIDX_NOISE_ERROR:
583 clear_mask = DL_UART_INTERRUPT_NOISE_ERROR;
592 DL_UART_clearInterruptStatus(res_.instance, clear_mask);
596void MSPM0UART::DisableTxInterrupt()
598 DL_UART_disableInterrupt(res_.instance, DL_UART_INTERRUPT_TX);
599 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_TX);
600 NVIC_ClearPendingIRQ(res_.irqn);
603#if defined(UART0_BASE)
604extern "C" void UART0_IRQHandler(
void)
606 LibXR::MSPM0UART::OnInterrupt(0);
610#if defined(UART1_BASE)
611extern "C" void UART1_IRQHandler(
void)
613 LibXR::MSPM0UART::OnInterrupt(1);
617#if defined(UART2_BASE)
618extern "C" void UART2_IRQHandler(
void)
620 LibXR::MSPM0UART::OnInterrupt(2);
624#if defined(UART3_BASE)
625extern "C" void UART3_IRQHandler(
void)
627 LibXR::MSPM0UART::OnInterrupt(3);
631#if defined(UART4_BASE)
632extern "C" void UART4_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(4); }
635#if defined(UART5_BASE)
636extern "C" void UART5_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(5); }
639#if defined(UART6_BASE)
640extern "C" void UART6_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(6); }
643#if defined(UART7_BASE)
644extern "C" void UART7_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(7); }
size_t size_
数据字节数 / Data size in bytes
ErrorCode Pop(ElementData &item)
从队列中弹出数据 / Pops data from the queue
ErrorCode Push(ElementData &&item)
向队列中推入数据 / Pushes data into the queue
ErrorCode SetConfig(UART::Configuration config) override
设置 UART 配置 / Sets the UART configuration
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
ReadPort class for handling read operations.
std::atomic< BusyState > busy_
Shared read-progress handoff state. 共享的读进度交接状态。
LockFreeQueue< uint8_t > * queue_data_
RX payload queue. 接收数据字节队列。
void ProcessPendingReads(bool in_isr)
Processes pending reads.
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
ReadPort * read_port_
读取端口 / Read port
@ NO_PARITY
无校验 / No parity
WritePort * write_port_
写入端口 / Write port
WritePort class for handling write operations.
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
LockFreeQueue< uint8_t > * queue_data_
Payload queue for pending write bytes. 挂起写入字节的数据队列。
LockFreeQueue< WriteInfoBlock > * queue_info_
Metadata queue for pending write batches. 挂起写批次的元数据队列。
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
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.
OwnerType * ContainerOf(MemberType *ptr, MemberType OwnerType::*member) noexcept
通过成员指针恢复其所属对象指针
UART 配置结构体 / UART configuration structure.
uint8_t stop_bits
停止位长度 / Number of stop bits
Parity parity
校验模式 / Parity mode
uint8_t data_bits
数据位长度 / Number of data bits
uint32_t baudrate
波特率 / Baud rate
ConstRawData data
Data buffer. 数据缓冲区。