libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
mspm0_uart.cpp
1#include "mspm0_uart.hpp"
2
3#include <atomic>
4
5using namespace LibXR;
6
7MSPM0UART* MSPM0UART::instance_map_[MAX_UART_INSTANCES] = {nullptr};
8
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;
13
14static constexpr uint32_t MSPM0_UART_BASE_INTERRUPT_MASK =
15 // RX/TX + 地址匹配 + 错误中断;超时中断按需在 Read() 时动态开关 / RX, TX,
16 // address-match and error IRQs; timeout IRQ is enabled on demand in Read().
17 DL_UART_INTERRUPT_RX | DL_UART_INTERRUPT_TX | DL_UART_INTERRUPT_ADDRESS_MATCH |
18 MSPM0_UART_RX_ERROR_INTERRUPT_MASK;
19
20MSPM0UART::MSPM0UART(Resources res, RawData rx_stage_buffer, uint32_t tx_queue_size,
21 uint32_t tx_buffer_size, UART::Configuration config)
22 : UART(&_read_port, &_write_port),
23 _read_port(rx_stage_buffer.size_),
24 _write_port(tx_queue_size, tx_buffer_size),
25 res_(res)
26{
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);
33
34 _read_port = ReadFun;
35 _write_port = WriteFun;
36
37 ASSERT(res_.index < MAX_UART_INSTANCES);
38 ASSERT(instance_map_[res_.index] == nullptr);
39 instance_map_[res_.index] = this;
40
41 NVIC_ClearPendingIRQ(res_.irqn);
42 NVIC_EnableIRQ(res_.irqn);
43
44 const ErrorCode SET_CFG_ANS = SetConfig(config);
45 ASSERT(SET_CFG_ANS == ErrorCode::OK);
46}
47
48UART::Configuration MSPM0UART::BuildConfigFromSysCfg(UART_Regs* instance,
49 uint32_t baudrate)
50{
51 ASSERT(instance != nullptr);
52 ASSERT(baudrate > 0U);
53
54 UART::Configuration config = {baudrate, UART::Parity::NO_PARITY, 8U, 1U};
55
56 switch (DL_UART_getWordLength(instance))
57 {
58 case DL_UART_WORD_LENGTH_5_BITS:
59 config.data_bits = 5U;
60 break;
61 case DL_UART_WORD_LENGTH_6_BITS:
62 config.data_bits = 6U;
63 break;
64 case DL_UART_WORD_LENGTH_7_BITS:
65 config.data_bits = 7U;
66 break;
67 case DL_UART_WORD_LENGTH_8_BITS:
68 default:
69 config.data_bits = 8U;
70 break;
71 }
72
73 switch (DL_UART_getParityMode(instance))
74 {
75 case DL_UART_PARITY_NONE:
77 break;
78 case DL_UART_PARITY_EVEN:
80 break;
81 case DL_UART_PARITY_ODD:
83 break;
84 default:
85 // LibXR UART config only supports none/even/odd parity.
86 ASSERT(false);
88 break;
89 }
90
91 config.stop_bits = (DL_UART_getStopBits(instance) == DL_UART_STOP_BITS_TWO) ? 2U : 1U;
92 return config;
93}
94
96{
97 if (config.baudrate == 0)
98 {
99 return ErrorCode::ARG_ERR;
100 }
101
102 if (config.data_bits < 5 || config.data_bits > 8)
103 {
104 return ErrorCode::ARG_ERR;
105 }
106
107 if (config.stop_bits != 1 && config.stop_bits != 2)
108 {
109 return ErrorCode::ARG_ERR;
110 }
111
112 DL_UART_WORD_LENGTH word_length = DL_UART_WORD_LENGTH_8_BITS;
113 switch (config.data_bits)
114 {
115 case 5:
116 word_length = DL_UART_WORD_LENGTH_5_BITS;
117 break;
118 case 6:
119 word_length = DL_UART_WORD_LENGTH_6_BITS;
120 break;
121 case 7:
122 word_length = DL_UART_WORD_LENGTH_7_BITS;
123 break;
124 case 8:
125 word_length = DL_UART_WORD_LENGTH_8_BITS;
126 break;
127 default:
128 return ErrorCode::ARG_ERR;
129 }
130
131 DL_UART_PARITY parity = DL_UART_PARITY_NONE;
132 switch (config.parity)
133 {
135 parity = DL_UART_PARITY_NONE;
136 break;
138 parity = DL_UART_PARITY_EVEN;
139 break;
141 parity = DL_UART_PARITY_ODD;
142 break;
143 default:
144 return ErrorCode::ARG_ERR;
145 }
146
147 const DL_UART_STOP_BITS STOP_BITS =
148 (config.stop_bits == 2) ? DL_UART_STOP_BITS_TWO : DL_UART_STOP_BITS_ONE;
149
150 DL_UART_changeConfig(res_.instance);
151
152 DL_UART_setWordLength(res_.instance, word_length);
153 DL_UART_setParityMode(res_.instance, parity);
154 DL_UART_setStopBits(res_.instance, STOP_BITS);
155
156 DL_UART_enableFIFOs(res_.instance);
157 DL_UART_setTXFIFOThreshold(res_.instance, DL_UART_TX_FIFO_LEVEL_ONE_ENTRY);
158
159 DL_UART_configBaudRate(res_.instance, res_.clock_freq, config.baudrate);
160
161 ApplyRxTimeoutMode();
162
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());
167
168 tx_active_valid_ = false;
169 tx_active_remaining_ = 0;
170 tx_active_total_ = 0;
171
172 DL_UART_enable(res_.instance);
173
174 return ErrorCode::OK;
175}
176
177ErrorCode MSPM0UART::WriteFun(WritePort& port, bool)
178{
179 auto* uart = LibXR::ContainerOf(&port, &MSPM0UART::_write_port);
180 DL_UART_enableInterrupt(uart->res_.instance, DL_UART_INTERRUPT_TX);
181 uart->res_.instance->CPU_INT.ISET = DL_UART_INTERRUPT_TX;
182 return ErrorCode::PENDING;
183}
184
185ErrorCode MSPM0UART::ReadFun(ReadPort& port, bool)
186{
187 auto* uart = LibXR::ContainerOf(&port, &MSPM0UART::_read_port);
188 const uint32_t TIMEOUT_MASK = uart->GetTimeoutInterruptMask();
189 if (TIMEOUT_MASK != 0U)
190 {
191 // 仅在有挂起读请求时启用超时中断,避免空闲无效触发 / Enable timeout IRQ
192 // only when a read request is pending to avoid idle false triggers.
193 if (uart->rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
194 {
195 // 以本次 Read 请求开始作为超时计时起点 / Start timeout timing from this
196 // Read request boundary.
197 uart->ResetLinCounter();
198 }
199
200 DL_UART_clearInterruptStatus(uart->res_.instance, TIMEOUT_MASK);
201 DL_UART_enableInterrupt(uart->res_.instance, TIMEOUT_MASK);
202 }
203
204 return ErrorCode::PENDING;
205}
206
207MSPM0UART::RxTimeoutMode MSPM0UART::ResolveRxTimeoutMode() const
208{
209 // 分发规则 / Dispatch rule:
210 // 1) [LIN路径 / LIN path] UART0 且存在 LIN compare 宏配置 -> LIN_COMPARE
211 // 2) [LIN路径 / LIN path] 运行时探测到 LIN counter+compare 已启用 -> LIN_COMPARE
212 // 3) [BYTE路径 / BYTE path] 其他情况 -> BYTE_INTERRUPT
213#if defined(UART_0_INST) && defined(UART_0_COUNTER_COMPARE_VALUE)
214 if (res_.instance == UART_0_INST)
215 {
216 // 本项目 UART0 在 SysConfig 中配置为 LIN 扩展实例 / UART0 is configured as a
217 // LIN extend instance by SysConfig in this project.
218 // [LIN路径 / LIN path] 固定走 LIN compare / Force LIN compare path.
219 return RxTimeoutMode::LIN_COMPARE;
220 }
221#endif
222
223 if (DL_UART_isLINCounterEnabled(res_.instance) &&
224 DL_UART_isLINCounterCompareMatchEnabled(res_.instance))
225 {
226 // [LIN路径 / LIN path] 非 UART0 按寄存器能力探测:若 LIN counter+compare
227 // 已启用则走 LIN /
228 // For non-UART0, use LIN path when LIN counter+compare are already enabled.
229 return RxTimeoutMode::LIN_COMPARE;
230 }
231
232 // [BYTE路径 / BYTE path] 不满足 LIN 条件时回落到按字节中断路径 /
233 // Fall back to byte-interrupt path when LIN conditions are not met.
234 return RxTimeoutMode::BYTE_INTERRUPT;
235}
236
237uint32_t MSPM0UART::GetTimeoutInterruptMask() const
238{
239 switch (rx_timeout_mode_)
240 {
241 // [LIN路径 / LIN path] 使用 LINC0 compare match 作为帧间超时事件 /
242 // Use LINC0 compare match as frame-gap timeout event.
243 case RxTimeoutMode::LIN_COMPARE:
244 return DL_UART_INTERRUPT_LINC0_MATCH;
245 // [BYTE路径 / BYTE path] 不使用硬件超时中断 /
246 // No hardware timeout interrupt in byte-interrupt mode.
247 case RxTimeoutMode::BYTE_INTERRUPT:
248 default:
249 return 0;
250 }
251}
252
253uint32_t MSPM0UART::GetTimeoutInterruptEnabledMask() const
254{
255 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
256 if (TIMEOUT_MASK == 0U)
257 {
258 return 0U;
259 }
260 return DL_UART_getEnabledInterrupts(res_.instance, TIMEOUT_MASK);
261}
262
263uint32_t MSPM0UART::GetTimeoutInterruptMaskedStatus() const
264{
265 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
266 if (TIMEOUT_MASK == 0U)
267 {
268 return 0U;
269 }
270 return DL_UART_getEnabledInterruptStatus(res_.instance, TIMEOUT_MASK);
271}
272
273uint32_t MSPM0UART::GetTimeoutInterruptRawStatus() const
274{
275 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
276 if (TIMEOUT_MASK == 0U)
277 {
278 return 0U;
279 }
280 return DL_UART_getRawInterruptStatus(res_.instance, TIMEOUT_MASK);
281}
282
283uint32_t MSPM0UART::GetRxInterruptTimeoutValue() const
284{
285 return DL_UART_getRXInterruptTimeout(res_.instance);
286}
287
288uint32_t MSPM0UART::GetRxFifoThresholdValue() const
289{
290 return static_cast<uint32_t>(DL_UART_getRXFIFOThreshold(res_.instance));
291}
292
293void MSPM0UART::ResetLinCounter()
294{
295 if (rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
296 {
297 DL_UART_setLINCounterValue(res_.instance, 0);
298 }
299}
300
301void MSPM0UART::ApplyRxTimeoutMode()
302{
303 rx_timeout_mode_ = ResolveRxTimeoutMode();
304
305 // 基础 UART 配置对 LIN/BYTE 两条路径一致,先统一配置后再处理模式差异 /
306 // Apply shared UART settings first, then patch mode-specific differences.
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);
312
313 switch (rx_timeout_mode_)
314 {
315 // [LIN路径 / LIN path] 使能 LIN counter/compare,超时事件来自 LINC0_MATCH。
316 // [LIN路径 / LIN path] Enable LIN counter/compare; timeout event is LINC0_MATCH.
317 case RxTimeoutMode::LIN_COMPARE:
318 if (!DL_UART_isLINCounterEnabled(res_.instance))
319 {
320 DL_UART_enableLINCounter(res_.instance);
321 }
322 if (!DL_UART_isLINCounterCompareMatchEnabled(res_.instance))
323 {
324 DL_UART_enableLINCounterCompareMatch(res_.instance);
325 }
326#if defined(UART_0_COUNTER_COMPARE_VALUE)
327 DL_UART_setLINCounterCompareValue(res_.instance, UART_0_COUNTER_COMPARE_VALUE);
328#endif
329 DL_UART_disableLINCountWhileLow(res_.instance);
330 ResetLinCounter();
331 break;
332
333 // [BYTE路径 / BYTE path] 仅保留按字节 RX 中断,不依赖超时中断。
334 // [BYTE路径 / BYTE path] Keep plain per-byte RX interrupt; no timeout IRQ.
335 case RxTimeoutMode::BYTE_INTERRUPT:
336 default:
337 break;
338 }
339}
340
341void MSPM0UART::OnInterrupt(uint8_t index)
342{
343 if (index >= MAX_UART_INSTANCES)
344 {
345 return;
346 }
347
348 auto* uart = instance_map_[index];
349 if (uart == nullptr)
350 {
351 return;
352 }
353
354 uart->HandleInterrupt();
355}
356
357void MSPM0UART::HandleInterrupt()
358{
359 const uint32_t TIMEOUT_MASK = GetTimeoutInterruptMask();
360 const uint32_t IRQ_MASK = MSPM0_UART_BASE_INTERRUPT_MASK | TIMEOUT_MASK;
361
362 uint32_t pending = DL_UART_getEnabledInterruptStatus(res_.instance, IRQ_MASK);
363 if (TIMEOUT_MASK != 0U)
364 {
365 // LIN compare 在部分路径需读取 RAW 位,避免漏掉超时事件 / For LIN
366 // compare, raw status is required on some paths to avoid missing timeout events.
367 pending |= DL_UART_getRawInterruptStatus(res_.instance, TIMEOUT_MASK);
368 }
369
370 const uint32_t PENDING = pending;
371 if (PENDING == 0U)
372 {
373 return;
374 }
375
376 constexpr uint32_t RX_PENDING_MASK =
377 DL_UART_INTERRUPT_RX | DL_UART_INTERRUPT_ADDRESS_MATCH;
378 if ((PENDING & RX_PENDING_MASK) != 0U)
379 {
380 HandleRxInterrupt(TIMEOUT_MASK);
381 if ((PENDING & DL_UART_INTERRUPT_ADDRESS_MATCH) != 0U)
382 {
383 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_ADDRESS_MATCH);
384 }
385 }
386
387 if (TIMEOUT_MASK != 0U)
388 {
389 HandleRxTimeoutInterrupt(PENDING, TIMEOUT_MASK);
390 }
391
392 if ((PENDING & DL_UART_INTERRUPT_OVERRUN_ERROR) != 0U)
393 {
394 HandleErrorInterrupt(DL_UART_IIDX_OVERRUN_ERROR);
395 }
396 if ((PENDING & DL_UART_INTERRUPT_BREAK_ERROR) != 0U)
397 {
398 HandleErrorInterrupt(DL_UART_IIDX_BREAK_ERROR);
399 }
400 if ((PENDING & DL_UART_INTERRUPT_PARITY_ERROR) != 0U)
401 {
402 HandleErrorInterrupt(DL_UART_IIDX_PARITY_ERROR);
403 }
404 if ((PENDING & DL_UART_INTERRUPT_FRAMING_ERROR) != 0U)
405 {
406 HandleErrorInterrupt(DL_UART_IIDX_FRAMING_ERROR);
407 }
408 if ((PENDING & DL_UART_INTERRUPT_NOISE_ERROR) != 0U)
409 {
410 HandleErrorInterrupt(DL_UART_IIDX_NOISE_ERROR);
411 }
412
413 if ((PENDING & DL_UART_INTERRUPT_TX) != 0U)
414 {
415 HandleTxInterrupt(true);
416 }
417}
418
419void MSPM0UART::HandleRxInterrupt(uint32_t timeout_mask)
420{
421 bool pushed = false;
422 bool received = false;
423
424 DrainRxFIFO(received, pushed);
425
426 if (received && rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
427 {
428 // [LIN路径 / LIN path] 连续接收时重置 LIN 计数器,避免帧内误超时 /
429 // Reset LIN counter on data reception to avoid in-frame timeout.
430 ResetLinCounter();
431 }
432
433 if (pushed)
434 {
436 }
437
438 if (timeout_mask != 0U &&
439 read_port_->busy_.load(std::memory_order_relaxed) != ReadPort::BusyState::PENDING)
440 {
441 // 无挂起读请求时关闭超时中断,减少无意义 IRQ / Disable timeout IRQ when no
442 // pending read remains.
443 DL_UART_disableInterrupt(res_.instance, timeout_mask);
444 DL_UART_clearInterruptStatus(res_.instance, timeout_mask);
445 }
446
447 DL_UART_clearInterruptStatus(res_.instance, DL_UART_INTERRUPT_RX);
448}
449
450void MSPM0UART::DrainRxFIFO(bool& received, bool& pushed)
451{
452 while (!DL_UART_isRXFIFOEmpty(res_.instance))
453 {
454 const uint8_t RX_BYTE = DL_UART_receiveData(res_.instance);
455 received = true;
456
457 if (read_port_->queue_data_->Push(RX_BYTE) == ErrorCode::OK)
458 {
459 pushed = true;
460 }
461 else
462 {
463 rx_drop_count_++;
464 }
465 }
466}
467
468void MSPM0UART::HandleRxTimeoutInterrupt(uint32_t pending, uint32_t timeout_mask)
469{
470 // [BYTE路径 / BYTE path] timeout_mask=0,直接返回;本函数实际只在 LIN 路径生效。
471 // In BYTE path timeout_mask is 0, so this function is effectively LIN-only.
472 if ((timeout_mask == 0U) || ((pending & timeout_mask) == 0U))
473 {
474 return;
475 }
476
477 rx_timeout_count_++;
478 DL_UART_clearInterruptStatus(res_.instance, pending & timeout_mask);
479
480 // FULL 阈值模式下短帧可能滞留在 HW FIFO,直到超时中断到来 / In
481 // FULL-threshold modes, short frames may remain in HW FIFO until timeout IRQ.
482 // 先拉取 FIFO,让已有数据先走正常队列完成路径 / Drain FIFO first so already
483 // received bytes take the normal queue-completion path.
484 bool pushed = false;
485 bool received = false;
486
487 DrainRxFIFO(received, pushed);
488
489 if (pushed)
490 {
492 }
493
494 if (rx_timeout_mode_ == RxTimeoutMode::LIN_COMPARE)
495 {
496 ResetLinCounter();
497 }
498
499 // Timeout is a frame/readiness boundary, not a read error. Read(size=0) waiters
500 // complete through ProcessPendingReads() once bytes are queued; exact-size reads keep
501 // waiting until enough bytes arrive or their own BLOCK timeout fires.
502 DL_UART_disableInterrupt(res_.instance, timeout_mask);
503}
504
505void MSPM0UART::HandleTxInterrupt(bool in_isr)
506{
507 // 发送状态机:取写请求并尽量填满 TX FIFO,直到该请求完成 / TX state machine:
508 // fetch one write request and keep filling TX FIFO until it completes.
509 while (true)
510 {
511 if (!tx_active_valid_)
512 {
513 if (write_port_->queue_info_->Pop(tx_active_info_) != ErrorCode::OK)
514 {
515 DisableTxInterrupt();
516
517 if (write_port_->queue_info_->Size() > 0)
518 {
519 DL_UART_enableInterrupt(res_.instance, DL_UART_INTERRUPT_TX);
520 res_.instance->CPU_INT.ISET = DL_UART_INTERRUPT_TX;
521 }
522
523 return;
524 }
525
526 tx_active_total_ = tx_active_info_.data.size_;
527 tx_active_remaining_ = tx_active_total_;
528 tx_active_valid_ = true;
529 }
530
531 while (tx_active_remaining_ > 0 && !DL_UART_isTXFIFOFull(res_.instance))
532 {
533 uint8_t tx_byte = 0;
534 if (write_port_->queue_data_->Pop(tx_byte) != ErrorCode::OK)
535 {
536 write_port_->Finish(in_isr, ErrorCode::FAILED, tx_active_info_);
537 tx_active_valid_ = false;
538 tx_active_remaining_ = 0;
539 tx_active_total_ = 0;
540 DisableTxInterrupt();
541 return;
542 }
543
544 DL_UART_transmitData(res_.instance, tx_byte);
545 tx_active_remaining_--;
546 }
547
548 if (tx_active_remaining_ > 0)
549 {
550 return;
551 }
552
553 write_port_->Finish(in_isr, ErrorCode::OK, tx_active_info_);
554 tx_active_valid_ = false;
555 tx_active_remaining_ = 0;
556 tx_active_total_ = 0;
557 }
558}
559
560void MSPM0UART::HandleErrorInterrupt(DL_UART_IIDX iidx)
561{
562 uint32_t clear_mask = 0;
563
564 switch (iidx)
565 {
566 case DL_UART_IIDX_OVERRUN_ERROR:
567 clear_mask = DL_UART_INTERRUPT_OVERRUN_ERROR;
568 break;
569
570 case DL_UART_IIDX_BREAK_ERROR:
571 clear_mask = DL_UART_INTERRUPT_BREAK_ERROR;
572 break;
573
574 case DL_UART_IIDX_PARITY_ERROR:
575 clear_mask = DL_UART_INTERRUPT_PARITY_ERROR;
576 break;
577
578 case DL_UART_IIDX_FRAMING_ERROR:
579 clear_mask = DL_UART_INTERRUPT_FRAMING_ERROR;
580 break;
581
582 case DL_UART_IIDX_NOISE_ERROR:
583 clear_mask = DL_UART_INTERRUPT_NOISE_ERROR;
584 break;
585
586 default:
587 break;
588 }
589
590 if (clear_mask != 0)
591 {
592 DL_UART_clearInterruptStatus(res_.instance, clear_mask);
593 }
594}
595
596void MSPM0UART::DisableTxInterrupt()
597{
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);
601}
602
603#if defined(UART0_BASE)
604extern "C" void UART0_IRQHandler(void) // NOLINT
605{
606 LibXR::MSPM0UART::OnInterrupt(0);
607}
608#endif
609
610#if defined(UART1_BASE)
611extern "C" void UART1_IRQHandler(void) // NOLINT
612{
613 LibXR::MSPM0UART::OnInterrupt(1);
614}
615#endif
616
617#if defined(UART2_BASE)
618extern "C" void UART2_IRQHandler(void) // NOLINT
619{
620 LibXR::MSPM0UART::OnInterrupt(2);
621}
622#endif
623
624#if defined(UART3_BASE)
625extern "C" void UART3_IRQHandler(void) // NOLINT
626{
627 LibXR::MSPM0UART::OnInterrupt(3);
628}
629#endif
630
631#if defined(UART4_BASE)
632extern "C" void UART4_IRQHandler(void) { LibXR::MSPM0UART::OnInterrupt(4); }
633#endif
634
635#if defined(UART5_BASE)
636extern "C" void UART5_IRQHandler(void) { LibXR::MSPM0UART::OnInterrupt(5); }
637#endif
638
639#if defined(UART6_BASE)
640extern "C" void UART6_IRQHandler(void) { LibXR::MSPM0UART::OnInterrupt(6); }
641#endif
642
643#if defined(UART7_BASE)
644extern "C" void UART7_IRQHandler(void) { LibXR::MSPM0UART::OnInterrupt(7); }
645#endif
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.
Definition libxr_rw.hpp:388
std::atomic< BusyState > busy_
Shared read-progress handoff state. 共享的读进度交接状态。
Definition libxr_rw.hpp:422
LockFreeQueue< uint8_t > * queue_data_
RX payload queue. 接收数据字节队列。
Definition libxr_rw.hpp:420
void ProcessPendingReads(bool in_isr)
Processes pending reads.
Definition libxr_rw.cpp:198
通用异步收发传输(UART)基类 / Abstract base class for Universal Asynchronous Receiver-Transmitter (UART)
Definition uart.hpp:19
ReadPort * read_port_
读取端口 / Read port
Definition uart.hpp:53
@ NO_PARITY
无校验 / No parity
@ ODD
奇校验 / Odd parity
@ EVEN
偶校验 / Even parity
WritePort * write_port_
写入端口 / Write port
Definition uart.hpp:54
WritePort class for handling write operations.
Definition libxr_rw.hpp:558
void Finish(bool in_isr, ErrorCode ans, WriteInfoBlock &info)
更新写入操作的状态。 Updates the status of the write operation.
Definition libxr_rw.cpp:320
LockFreeQueue< uint8_t > * queue_data_
Payload queue for pending write bytes. 挂起写入字节的数据队列。
Definition libxr_rw.hpp:604
LockFreeQueue< WriteInfoBlock > * queue_info_
Metadata queue for pending write batches. 挂起写批次的元数据队列。
Definition libxr_rw.hpp:602
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ FAILED
操作失败 | Operation failed
@ PENDING
等待中 | Pending
@ OK
操作成功 | Operation successful
@ ARG_ERR
参数错误 | Argument error
ErrorCode(* ReadFun)(ReadPort &port, bool in_isr)
Function pointer type for read notifications.
Definition libxr_rw.hpp:365
ErrorCode(* WriteFun)(WritePort &port, bool in_isr)
Function pointer type for write operations.
Definition libxr_rw.hpp:354
OwnerType * ContainerOf(MemberType *ptr, MemberType OwnerType::*member) noexcept
通过成员指针恢复其所属对象指针
Definition libxr_def.hpp:79
UART 配置结构体 / UART configuration structure.
Definition uart.hpp:44
uint8_t stop_bits
停止位长度 / Number of stop bits
Definition uart.hpp:50
Parity parity
校验模式 / Parity mode
Definition uart.hpp:47
uint8_t data_bits
数据位长度 / Number of data bits
Definition uart.hpp:48
uint32_t baudrate
波特率 / Baud rate
Definition uart.hpp:45
ConstRawData data
Data buffer. 数据缓冲区。
Definition libxr_rw.hpp:379