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;
99 return ErrorCode::ARG_ERR;
104 return ErrorCode::ARG_ERR;
109 return ErrorCode::ARG_ERR;
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;
128 return ErrorCode::ARG_ERR;
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;
144 return ErrorCode::ARG_ERR;
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);
174 return ErrorCode::OK;
177ErrorCode MSPM0UART::WriteFun(
WritePort& port)
179 auto* uart = CONTAINER_OF(&port,
MSPM0UART, _write_port);
180 if (port.queue_info_->Size() == 0)
182 return ErrorCode::OK;
185 DL_UART_enableInterrupt(uart->res_.instance, DL_UART_INTERRUPT_TX);
186 uart->res_.instance->CPU_INT.ISET = DL_UART_INTERRUPT_TX;
187 return ErrorCode::OK;
190ErrorCode MSPM0UART::ReadFun(
ReadPort& port)
192 auto* uart = CONTAINER_OF(&port,
MSPM0UART, _read_port);
193 const uint32_t TIMEOUT_MASK = uart->GetTimeoutInterruptMask();
194 if (TIMEOUT_MASK != 0U)
198 if (uart->rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
202 uart->ResetLinCounter();
205 DL_UART_clearInterruptStatus(uart->res_.instance, TIMEOUT_MASK);
206 DL_UART_enableInterrupt(uart->res_.instance, TIMEOUT_MASK);
209 return ErrorCode::EMPTY;
212MSPM0UART::RxTimeoutMode MSPM0UART::ResolveRxTimeoutMode()
const
218#if defined(UART_0_INST) && defined(UART_0_COUNTER_COMPARE_VALUE)
219 if (res_.instance == UART_0_INST)
224 return RxTimeoutMode::LIN_COMPARE;
228 if (DL_UART_isLINCounterEnabled(res_.instance) &&
229 DL_UART_isLINCounterCompareMatchEnabled(res_.instance))
234 return RxTimeoutMode::LIN_COMPARE;
239 return RxTimeoutMode::BYTE_INTERRUPT;
242uint32_t MSPM0UART::GetTimeoutInterruptMask()
const
244 switch (rx_timeout_mode_)
248 case RxTimeoutMode::LIN_COMPARE:
249 return DL_UART_INTERRUPT_LINC0_MATCH;
252 case RxTimeoutMode::BYTE_INTERRUPT:
258uint32_t MSPM0UART::GetTimeoutInterruptEnabledMask()
const
260 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
261 if (TIMEOUT_MASK == 0U)
265 return DL_UART_getEnabledInterrupts(res_.instance, TIMEOUT_MASK);
268uint32_t MSPM0UART::GetTimeoutInterruptMaskedStatus()
const
270 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
271 if (TIMEOUT_MASK == 0U)
275 return DL_UART_getEnabledInterruptStatus(res_.instance, TIMEOUT_MASK);
278uint32_t MSPM0UART::GetTimeoutInterruptRawStatus()
const
280 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
281 if (TIMEOUT_MASK == 0U)
285 return DL_UART_getRawInterruptStatus(res_.instance, TIMEOUT_MASK);
288uint32_t MSPM0UART::GetRxInterruptTimeoutValue()
const
290 return DL_UART_getRXInterruptTimeout(res_.instance);
293uint32_t MSPM0UART::GetRxFifoThresholdValue()
const
295 return static_cast<uint32_t
>(DL_UART_getRXFIFOThreshold(res_.instance));
298void MSPM0UART::ResetLinCounter()
300 if (rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
302 DL_UART_setLINCounterValue(res_.instance, 0);
306void MSPM0UART::ApplyRxTimeoutMode()
308 rx_timeout_mode_ = ResolveRxTimeoutMode();
312 DL_UART_setCommunicationMode(res_.instance, DL_UART_MODE_NORMAL);
313 DL_UART_setAddressMask(res_.instance, 0U);
314 DL_UART_setAddress(res_.instance, 0U);
315 DL_UART_setRXFIFOThreshold(res_.instance, DL_UART_RX_FIFO_LEVEL_ONE_ENTRY);
316 DL_UART_setRXInterruptTimeout(res_.instance, 0U);
318 switch (rx_timeout_mode_)
322 case RxTimeoutMode::LIN_COMPARE:
323 if (!DL_UART_isLINCounterEnabled(res_.instance))
325 DL_UART_enableLINCounter(res_.instance);
327 if (!DL_UART_isLINCounterCompareMatchEnabled(res_.instance))
329 DL_UART_enableLINCounterCompareMatch(res_.instance);
331#if defined(UART_0_COUNTER_COMPARE_VALUE)
332 DL_UART_setLINCounterCompareValue(res_.instance, UART_0_COUNTER_COMPARE_VALUE);
334 DL_UART_disableLINCountWhileLow(res_.instance);
340 case RxTimeoutMode::BYTE_INTERRUPT:
346void MSPM0UART::OnInterrupt(uint8_t index)
348 if (index >= MAX_UART_INSTANCES)
353 auto* uart = instance_map_[index];
359 uart->HandleInterrupt();
362void MSPM0UART::HandleInterrupt()
364 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
365 const uint32_t IRQ_MASK = MSPM0_UART_BASE_INTERRUPT_MASK | TIMEOUT_MASK;
367 uint32_t pending = DL_UART_getEnabledInterruptStatus(res_.instance, IRQ_MASK);
368 if (TIMEOUT_MASK != 0U)
372 pending |= DL_UART_getRawInterruptStatus(res_.instance, TIMEOUT_MASK);
375 const uint32_t PENDING = pending;
381 constexpr uint32_t RX_PENDING_MASK =
382 DL_UART_INTERRUPT_RX | DL_UART_INTERRUPT_ADDRESS_MATCH;
383 if ((PENDING & RX_PENDING_MASK) != 0U)
385 HandleRxInterrupt(TIMEOUT_MASK);
386 if ((PENDING & DL_UART_INTERRUPT_ADDRESS_MATCH) != 0U)
388 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_ADDRESS_MATCH);
392 if (TIMEOUT_MASK != 0U)
394 HandleRxTimeoutInterrupt(PENDING, TIMEOUT_MASK);
397 if ((PENDING & DL_UART_INTERRUPT_OVERRUN_ERROR) != 0U)
399 HandleErrorInterrupt(DL_UART_IIDX_OVERRUN_ERROR);
401 if ((PENDING & DL_UART_INTERRUPT_BREAK_ERROR) != 0U)
403 HandleErrorInterrupt(DL_UART_IIDX_BREAK_ERROR);
405 if ((PENDING & DL_UART_INTERRUPT_PARITY_ERROR) != 0U)
407 HandleErrorInterrupt(DL_UART_IIDX_PARITY_ERROR);
409 if ((PENDING & DL_UART_INTERRUPT_FRAMING_ERROR) != 0U)
411 HandleErrorInterrupt(DL_UART_IIDX_FRAMING_ERROR);
413 if ((PENDING & DL_UART_INTERRUPT_NOISE_ERROR) != 0U)
415 HandleErrorInterrupt(DL_UART_IIDX_NOISE_ERROR);
418 if ((PENDING & DL_UART_INTERRUPT_TX) != 0U)
420 HandleTxInterrupt(
true);
424void MSPM0UART::HandleRxInterrupt(uint32_t timeout_mask)
427 bool received =
false;
429 DrainRxFIFO(received, pushed);
431 if (received && rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
443 if (timeout_mask != 0U &&
448 DL_UART_disableInterrupt(res_.instance, timeout_mask);
449 DL_UART_clearInterruptStatus(res_.instance, timeout_mask);
452 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_RX);
455void MSPM0UART::DrainRxFIFO(
bool& received,
bool& pushed)
457 while (!DL_UART_isRXFIFOEmpty(res_.instance))
459 const uint8_t RX_BYTE = DL_UART_receiveData(res_.instance);
473void MSPM0UART::HandleRxTimeoutInterrupt(uint32_t pending, uint32_t timeout_mask)
477 if ((timeout_mask == 0U) || ((pending & timeout_mask) == 0U))
483 DL_UART_clearInterruptStatus(res_.instance, pending & timeout_mask);
490 bool received =
false;
492 DrainRxFIFO(received, pushed);
499 const bool PENDING_READ =
505 DL_UART_disableInterrupt(res_.instance, timeout_mask);
509 if (rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
514 CompletePendingReadOnTimeout(
true);
518 DL_UART_disableInterrupt(res_.instance, timeout_mask);
522void MSPM0UART::CompletePendingReadOnTimeout(
bool in_isr)
536 const size_t POP_SIZE = (AVAILABLE < REQUESTED) ? AVAILABLE : REQUESTED;
544 if (POP_ANS != ErrorCode::OK)
549 const ErrorCode STATUS =
552 (POP_SIZE == REQUESTED) ? ErrorCode::OK : ErrorCode::EMPTY;
556void MSPM0UART::HandleTxInterrupt(
bool in_isr)
562 if (!tx_active_valid_)
564 if (
write_port_->queue_info_->Pop(tx_active_info_) != ErrorCode::OK)
566 DisableTxInterrupt();
570 DL_UART_enableInterrupt(res_.instance, DL_UART_INTERRUPT_TX);
571 res_.instance->CPU_INT.ISET = DL_UART_INTERRUPT_TX;
577 tx_active_total_ = tx_active_info_.
data.
size_;
578 tx_active_remaining_ = tx_active_total_;
579 tx_active_valid_ =
true;
582 while (tx_active_remaining_ > 0 && !DL_UART_isTXFIFOFull(res_.instance))
588 tx_active_total_ - tx_active_remaining_);
589 tx_active_valid_ =
false;
590 tx_active_remaining_ = 0;
591 tx_active_total_ = 0;
592 DisableTxInterrupt();
596 DL_UART_transmitData(res_.instance, tx_byte);
597 tx_active_remaining_--;
600 if (tx_active_remaining_ > 0)
606 tx_active_valid_ =
false;
607 tx_active_remaining_ = 0;
608 tx_active_total_ = 0;
612void MSPM0UART::HandleErrorInterrupt(DL_UART_IIDX iidx)
614 uint32_t clear_mask = 0;
618 case DL_UART_IIDX_OVERRUN_ERROR:
619 clear_mask = DL_UART_INTERRUPT_OVERRUN_ERROR;
622 case DL_UART_IIDX_BREAK_ERROR:
623 clear_mask = DL_UART_INTERRUPT_BREAK_ERROR;
626 case DL_UART_IIDX_PARITY_ERROR:
627 clear_mask = DL_UART_INTERRUPT_PARITY_ERROR;
630 case DL_UART_IIDX_FRAMING_ERROR:
631 clear_mask = DL_UART_INTERRUPT_FRAMING_ERROR;
634 case DL_UART_IIDX_NOISE_ERROR:
635 clear_mask = DL_UART_INTERRUPT_NOISE_ERROR;
644 DL_UART_clearInterruptStatus(res_.instance, clear_mask);
648void MSPM0UART::DisableTxInterrupt()
650 DL_UART_disableInterrupt(res_.instance, DL_UART_INTERRUPT_TX);
651 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_TX);
652 NVIC_ClearPendingIRQ(res_.irqn);
655#if defined(UART0_BASE)
656extern "C" void UART0_IRQHandler(
void)
658 LibXR::MSPM0UART::OnInterrupt(0);
662#if defined(UART1_BASE)
663extern "C" void UART1_IRQHandler(
void)
665 LibXR::MSPM0UART::OnInterrupt(1);
669#if defined(UART2_BASE)
670extern "C" void UART2_IRQHandler(
void)
672 LibXR::MSPM0UART::OnInterrupt(2);
676#if defined(UART3_BASE)
677extern "C" void UART3_IRQHandler(
void)
679 LibXR::MSPM0UART::OnInterrupt(3);
683#if defined(UART4_BASE)
684extern "C" void UART4_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(4); }
687#if defined(UART5_BASE)
688extern "C" void UART5_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(5); }
691#if defined(UART6_BASE)
692extern "C" void UART6_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(6); }
695#if defined(UART7_BASE)
696extern "C" void UART7_IRQHandler(
void) { LibXR::MSPM0UART::OnInterrupt(7); }
size_t size_
数据大小(字节)。 The size of the data (in bytes).
ErrorCode Pop(ElementData &item)
从队列中弹出数据 / Pops data from the queue
ErrorCode Push(ElementData &&item)
向队列中推入数据 / Pushes data into the queue
size_t Size() const
获取当前队列中的元素数量 / Returns the number of elements currently in the queue
ErrorCode PopBatch(Data *data, size_t size)
批量弹出数据 / Pops multiple elements from the queue
ErrorCode SetConfig(UART::Configuration config) override
设置 UART 配置 / Sets the UART configuration
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
ReadPort class for handling read operations.
void Finish(bool in_isr, ErrorCode ans, ReadInfoBlock &info)
更新读取操作的状态。 Updates the status of the read operation.
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.
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read operations.
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
RawData data
Data buffer. 数据缓冲区。
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. 数据缓冲区。