libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
esp_usb_ep.cpp
1#include "esp_usb_ep.hpp"
2
3#if SOC_USB_OTG_SUPPORTED && defined(CONFIG_IDF_TARGET_ESP32S3) && \
4 CONFIG_IDF_TARGET_ESP32S3
5
6#include <algorithm>
7#include <cstring>
8
9#include "esp_heap_caps.h"
10#include "esp_usb.hpp"
11#include "esp_usb_dev.hpp"
12
13namespace Detail = LibXR::ESPUSBDetail;
14
15namespace LibXR
16{
17
18ESP32USBEndpoint::ESP32USBEndpoint(ESP32USBDevice& device, EPNumber number,
19 Direction direction, RawData buffer)
20 : USB::Endpoint(number, direction, buffer), device_(device)
21{
22}
23
24void ESP32USBEndpoint::Configure(const Config& cfg)
25{
26 ASSERT(cfg.direction == Direction::IN || cfg.direction == Direction::OUT);
27
28 auto& ep_cfg = GetConfig();
29 ep_cfg = cfg;
30 ep_cfg.max_packet_size = Detail::ClampPacketSize(cfg.type, cfg.max_packet_size);
31 if (ep_cfg.max_packet_size == 0U)
32 {
33 ep_cfg.max_packet_size = (cfg.type == Type::ISOCHRONOUS) ? 1023U : 64U;
34 }
35
36 auto buffer = GetBuffer();
37 if (buffer.size_ < ep_cfg.max_packet_size)
38 {
39 ep_cfg.max_packet_size = static_cast<uint16_t>(buffer.size_);
40 }
41
42 ASSERT(ep_cfg.max_packet_size > 0U);
43
44 if (device_.DmaEnabled() && (buffer.size_ > 0U) && !EnsureDmaShadow(buffer.size_))
45 {
46 SetState(State::ERROR);
47 return;
48 }
49
50 if (cfg.direction == Direction::IN)
51 {
52 const bool is_bulk = (cfg.type == Type::BULK);
53 if (!fifo_allocated_ &&
54 !device_.AllocateTxFifo(EPNumberToInt8(GetNumber()), ep_cfg.max_packet_size,
55 is_bulk, fifo_words_))
56 {
57 SetState(State::ERROR);
58 return;
59 }
60 fifo_allocated_ = true;
61 }
62 else
63 {
64 if (!device_.EnsureRxFifo(ep_cfg.max_packet_size))
65 {
66 SetState(State::ERROR);
67 return;
68 }
69 }
70
71 ActivateHardwareEndpoint();
72 ResetTransferState();
73 SetState(State::IDLE);
74}
75
76void ESP32USBEndpoint::Close()
77{
78 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
79 const uint8_t ep_num = EPNumberToInt8(GetNumber());
80
81 if (GetDirection() == Direction::IN)
82 {
83 if (ep_num == 0U)
84 {
85 if (dev->diepctl0_reg.epena)
86 {
87 Detail::DisableInEndpointAndWait(dev);
88 }
89 }
90 else
91 {
92 dev->diepempmsk_reg.val &= ~(1UL << ep_num);
93 if (dev->in_eps[ep_num - 1U].diepctl_reg.epena)
94 {
95 Detail::DisableInEndpointAndWait(dev, ep_num);
96 }
97 }
98 dev->daintmsk_reg.val &= ~(1UL << ep_num);
99 }
100 else
101 {
102 if (ep_num == 0U)
103 {
104 Detail::DisableOutEndpointAndWait(dev->doepctl0_reg);
105 }
106 else
107 {
108 Detail::DisableOutEndpointAndWait(dev->out_eps[ep_num - 1U].doepctl_reg);
109 }
110 dev->daintmsk_reg.val &= ~(1UL << (16U + ep_num));
111 }
112
113 ResetTransferState();
114 SetState(State::DISABLED);
115}
116
117ErrorCode ESP32USBEndpoint::Stall()
118{
119 const bool is_in = (GetDirection() == Direction::IN);
120 if ((GetState() == State::BUSY) && is_in)
121 {
122 return ErrorCode::BUSY;
123 }
124
125 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
126 const uint8_t ep_num = EPNumberToInt8(GetNumber());
127
128 if (is_in)
129 {
130 if (ep_num == 0U)
131 {
132 dev->diepctl0_reg.stall = 1;
133 }
134 else
135 {
136 dev->in_eps[ep_num - 1U].diepctl_reg.stall = 1;
137 }
138 }
139 else
140 {
141 if (ep_num == 0U)
142 {
143 dev->doepctl0_reg.stall = 1;
144 }
145 else
146 {
147 dev->out_eps[ep_num - 1U].doepctl_reg.stall = 1;
148 }
149 }
150
151 SetState(State::STALLED);
152 return ErrorCode::OK;
153}
154
155ErrorCode ESP32USBEndpoint::ClearStall()
156{
157 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
158 const uint8_t ep_num = EPNumberToInt8(GetNumber());
159
160 if (GetDirection() == Direction::IN)
161 {
162 if (ep_num == 0U)
163 {
164 dev->diepctl0_reg.stall = 0;
165 }
166 else
167 {
168 auto& reg = dev->in_eps[ep_num - 1U].diepctl_reg;
169 reg.stall = 0;
170 reg.setd0pid = 1;
171 }
172 }
173 else
174 {
175 if (ep_num == 0U)
176 {
177 dev->doepctl0_reg.stall = 0;
178 }
179 else
180 {
181 auto& reg = dev->out_eps[ep_num - 1U].doepctl_reg;
182 reg.stall = 0;
183 reg.setd0pid = 1;
184 }
185 }
186
187 SetState(State::IDLE);
188 return ErrorCode::OK;
189}
190
191ErrorCode ESP32USBEndpoint::Transfer(size_t size)
192{
193 if (GetState() == State::BUSY)
194 {
195 return ErrorCode::BUSY;
196 }
197
198 auto buffer = GetBuffer();
199 if (buffer.size_ < size)
200 {
201 return ErrorCode::NO_BUFF;
202 }
203
204 transfer_buffer_ = static_cast<uint8_t*>(buffer.addr_);
205 transfer_request_size_ = size;
206 transfer_actual_size_ = 0U;
207 transfer_queued_size_ = 0U;
208
209 const uint8_t ep_num = EPNumberToInt8(GetNumber());
210 if ((ep_num == 0U) && (GetDirection() == Direction::OUT))
211 {
212 ep0_out_phase_ = (size == 0U) ? Ep0OutPhase::STATUS : Ep0OutPhase::DATA;
213 }
214
215 if (UseDoubleBuffer() && GetDirection() == Direction::IN && size > 0U)
216 {
217 SwitchBuffer();
218 }
219
220 if (!PrepareTransferBuffer(size))
221 {
222 ResetTransferState();
223 return ErrorCode::NO_MEM;
224 }
225
226 SetState(State::BUSY);
227 ProgramTransfer(size);
228 return ErrorCode::OK;
229}
230
231size_t ESP32USBEndpoint::MaxTransferSize() const
232{
233 if (GetNumber() == EPNumber::EP0)
234 {
235 return MaxPacketSize();
236 }
237 return GetBuffer().size_;
238}
239
240void ESP32USBEndpoint::ResetHardwareState()
241{
242 fifo_allocated_ = false;
243 fifo_words_ = 0U;
244 ResetTransferState();
245 SetState(State::DISABLED);
246}
247
248void ESP32USBEndpoint::HandleInInterrupt(bool in_isr)
249{
250 const uint8_t ep_num = EPNumberToInt8(GetNumber());
251 usb_dwc_diepint_reg_t intr = {};
252 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
253
254 if (ep_num == 0U)
255 {
256 intr.val = dev->diepint0_reg.val;
257 dev->diepint0_reg.val = intr.val;
258 }
259 else
260 {
261 intr.val = dev->in_eps[ep_num - 1U].diepint_reg.val;
262 dev->in_eps[ep_num - 1U].diepint_reg.val = intr.val;
263 }
264
265 if (!device_.DmaEnabled() && intr.txfemp)
266 {
267 WriteMoreTxData();
268 if (transfer_queued_size_ >= transfer_request_size_)
269 {
270 dev->diepempmsk_reg.val &= ~(1UL << ep_num);
271 }
272 }
273
274 if (intr.xfercompl)
275 {
276 const bool rearm_ep0_setup = (ep_num == 0U) && device_.DmaEnabled() &&
277 (transfer_request_size_ == 0U) &&
278 device_.LastSetupDirectionOut();
279 dev->diepempmsk_reg.val &= ~(1UL << ep_num);
280 const size_t actual =
281 device_.DmaEnabled() ? GetCompletedTransferSize() : transfer_request_size_;
282 OnTransferCompleteCallback(in_isr, actual);
283 if (rearm_ep0_setup)
284 {
285 device_.ReloadSetupPacketCount();
286 }
287 if (GetState() != State::BUSY)
288 {
289 ResetTransferState();
290 }
291 }
292}
293
294void ESP32USBEndpoint::FinishPendingEp0InStatus(bool in_isr)
295{
296 if (!device_.DmaEnabled() || (device_.endpoint_map_.in[0] == nullptr))
297 {
298 return;
299 }
300
301 auto* ep0_in = static_cast<ESP32USBEndpoint*>(device_.endpoint_map_.in[0]);
302 if ((ep0_in->GetState() != State::BUSY) || (ep0_in->transfer_request_size_ != 0U))
303 {
304 return;
305 }
306
307 ep0_in->OnTransferCompleteCallback(in_isr, 0U);
308 if (ep0_in->GetState() != State::BUSY)
309 {
310 ep0_in->ResetTransferState();
311 }
312}
313
314void ESP32USBEndpoint::HandleOutInterrupt(bool in_isr)
315{
316 const uint8_t ep_num = EPNumberToInt8(GetNumber());
317 usb_dwc_doepint_reg_t intr = {};
318 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
319
320 if (ep_num == 0U)
321 {
322 intr.val = dev->doepint0_reg.val;
323 dev->doepint0_reg.val = intr.val;
324 }
325 else
326 {
327 intr.val = dev->out_eps[ep_num - 1U].doepint_reg.val;
328 dev->out_eps[ep_num - 1U].doepint_reg.val = intr.val;
329 }
330
331 const bool ep0_setup_related =
332 (ep_num == 0U) && (intr.setup || intr.stuppktrcvd || intr.back2backsetup);
333 const bool has_active_ep0_transfer =
334 (ep_num == 0U) && (GetState() == State::BUSY) &&
335 ((transfer_buffer_ != nullptr) || (transfer_request_size_ > 0U));
336
337 if (intr.xfercompl &&
338 ((ep_num != 0U) || ((ep0_out_phase_ != Ep0OutPhase::SETUP) && !ep0_setup_related &&
339 has_active_ep0_transfer)))
340 {
341 const size_t actual =
342 device_.DmaEnabled() ? GetCompletedTransferSize() : transfer_actual_size_;
343 ASSERT(FinishOutTransfer(actual));
344 if (ep_num == 0U)
345 {
346 FinishPendingEp0InStatus(in_isr);
347 }
348 OnTransferCompleteCallback(in_isr, actual);
349 if ((ep_num == 0U) && device_.DmaEnabled() && (transfer_request_size_ == 0U))
350 {
351 device_.ReloadSetupPacketCount();
352 }
353 if (GetState() != State::BUSY)
354 {
355 ResetTransferState();
356 }
357 }
358
359 if (intr.setup)
360 {
361 if (device_.DmaEnabled())
362 {
363 ASSERT(Detail::CacheSyncDmaBuffer(device_.setup_packet_,
364 ESP32USBDevice::kSetupDmaBufferBytes, false));
365 }
366 device_.UpdateSetupState(device_.setup_packet_);
367 const auto* setup = reinterpret_cast<const USB::SetupPacket*>(device_.setup_packet_);
368 const bool expect_out_data_stage =
369 ((setup->bmRequestType & 0x80U) == 0U) && (setup->wLength > 0U);
370
371 FinishPendingEp0InStatus(in_isr);
372 ep0_out_phase_ = Ep0OutPhase::SETUP;
373 ResetTransferState();
374 SetState(State::IDLE);
375
376 if (device_.endpoint_map_.in[0] != nullptr)
377 {
378 auto* ep0_in = static_cast<ESP32USBEndpoint*>(device_.endpoint_map_.in[0]);
379 if (ep0_in->GetState() == State::BUSY)
380 {
381 ep0_in->ResetTransferState();
382 ep0_in->SetState(State::IDLE);
383 }
384 }
385
386 if (device_.DmaEnabled() && !expect_out_data_stage)
387 {
388 device_.ReloadSetupPacketCount();
389 }
390 device_.OnSetupPacket(in_isr, setup);
391 }
392}
393
394void ESP32USBEndpoint::HandleRxData(size_t size)
395{
396 uint8_t* const dst = (transfer_buffer_ != nullptr)
397 ? (transfer_buffer_ + transfer_actual_size_)
398 : nullptr;
399 const size_t remain = (transfer_request_size_ > transfer_actual_size_)
400 ? (transfer_request_size_ - transfer_actual_size_)
401 : 0U;
402 const size_t copy_size = std::min(size, remain);
403 const size_t drop_size = size - copy_size;
404
405 if (copy_size > 0U)
406 {
407 Detail::ReadFifoPacket(
408 Detail::GetEndpointFifo(reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase),
409 0),
410 dst, copy_size);
411 transfer_actual_size_ += copy_size;
412 }
413
414 if (drop_size == 0U)
415 {
416 return;
417 }
418
419 uint8_t sink[64] = {};
420 size_t remain_drop = drop_size;
421 auto* fifo = Detail::GetEndpointFifo(
422 reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase), 0);
423 while (remain_drop > 0U)
424 {
425 const size_t chunk = std::min(remain_drop, sizeof(sink));
426 Detail::ReadFifoPacket(fifo, sink, chunk);
427 remain_drop -= chunk;
428 }
429}
430
431void ESP32USBEndpoint::ObserveDmaRxStatus(uint8_t pktsts, size_t size)
432{
433 if (!device_.DmaEnabled() || (GetDirection() != Direction::OUT))
434 {
435 return;
436 }
437
438 if (pktsts != Detail::kRxStatusData)
439 {
440 return;
441 }
442
443 dma_rx_status_seen_ = true;
444 dma_rx_status_bytes_ = std::min(transfer_request_size_, dma_rx_status_bytes_ + size);
445}
446
447void ESP32USBEndpoint::ResetTransferState()
448{
449 transfer_buffer_ = nullptr;
450 transfer_hw_buffer_ = nullptr;
451 transfer_request_size_ = 0U;
452 transfer_actual_size_ = 0U;
453 transfer_queued_size_ = 0U;
454 transfer_uses_shadow_ = false;
455 transfer_direct_sync_size_ = 0U;
456 dma_rx_status_bytes_ = 0U;
457 dma_rx_status_seen_ = false;
458}
459
460bool ESP32USBEndpoint::EnsureDmaShadow(size_t size)
461{
462 const size_t need = Detail::AlignUp(size, Detail::kUsbDmaAlignment);
463 if (need == 0U)
464 {
465 return true;
466 }
467
468 if ((dma_shadow_buffer_ != nullptr) && (dma_shadow_size_ >= need))
469 {
470 return true;
471 }
472
473 void* new_buffer =
474 heap_caps_aligned_alloc(Detail::kUsbDmaAlignment, need, Detail::kDmaMemoryCaps);
475 if (new_buffer == nullptr)
476 {
477 return false;
478 }
479
480 if (dma_shadow_buffer_ != nullptr)
481 {
482 heap_caps_free(dma_shadow_buffer_);
483 }
484
485 dma_shadow_buffer_ = static_cast<uint8_t*>(new_buffer);
486 dma_shadow_size_ = need;
487 return true;
488}
489
490bool ESP32USBEndpoint::PrepareTransferBuffer(size_t size)
491{
492 transfer_hw_buffer_ = transfer_buffer_;
493 transfer_uses_shadow_ = false;
494 transfer_direct_sync_size_ = 0U;
495
496 if (!device_.DmaEnabled() || (size == 0U))
497 {
498 return true;
499 }
500
501 if (GetDirection() == Direction::IN)
502 {
503 if (Detail::CanUseDirectInDmaBuffer(transfer_buffer_, size))
504 {
505 return Detail::CacheSyncDmaBuffer(transfer_hw_buffer_, size, true, true);
506 }
507 }
508 else
509 {
510 auto buffer = GetBuffer();
511 if (Detail::CanUseDirectOutDmaBuffer(buffer.addr_, buffer.size_))
512 {
513 transfer_direct_sync_size_ = buffer.size_;
514 return true;
515 }
516 }
517
518 if (!EnsureDmaShadow(size))
519 {
520 return false;
521 }
522
523 transfer_hw_buffer_ = dma_shadow_buffer_;
524 transfer_uses_shadow_ = true;
525
526 if (GetDirection() == Direction::IN)
527 {
528 ASSERT(transfer_buffer_ != nullptr);
529 std::memcpy(transfer_hw_buffer_, transfer_buffer_, size);
530 return Detail::CacheSyncDmaBuffer(
531 transfer_hw_buffer_, Detail::AlignUp(size, Detail::kUsbDmaAlignment), true);
532 }
533
534 return Detail::CacheSyncDmaBuffer(
535 transfer_hw_buffer_, Detail::AlignUp(size, Detail::kUsbDmaAlignment), false);
536}
537
538bool ESP32USBEndpoint::FinishOutTransfer(size_t actual_size)
539{
540 transfer_actual_size_ = actual_size;
541
542 if (!device_.DmaEnabled() || (actual_size == 0U))
543 {
544 return true;
545 }
546
547 ASSERT(transfer_hw_buffer_ != nullptr);
548
549 if (!transfer_uses_shadow_)
550 {
551 if (transfer_direct_sync_size_ == 0U)
552 {
553 return true;
554 }
555 return Detail::CacheSyncDmaBuffer(transfer_hw_buffer_, transfer_direct_sync_size_,
556 false);
557 }
558
559 ASSERT(transfer_buffer_ != nullptr);
560
561 if (!Detail::CacheSyncDmaBuffer(transfer_hw_buffer_,
562 Detail::AlignUp(actual_size, Detail::kUsbDmaAlignment),
563 false))
564 {
565 return false;
566 }
567
568 std::memcpy(transfer_buffer_, transfer_hw_buffer_, actual_size);
569 return true;
570}
571
572size_t ESP32USBEndpoint::GetRemainingTransferSize() const
573{
574 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
575 const uint8_t ep_num = EPNumberToInt8(GetNumber());
576
577 if (GetDirection() == Direction::IN)
578 {
579 if (ep_num == 0U)
580 {
581 return dev->dieptsiz0_reg.xfersize;
582 }
583 return dev->in_eps[ep_num - 1U].dieptsiz_reg.xfersize;
584 }
585
586 if (ep_num == 0U)
587 {
588 return dev->doeptsiz0_reg.xfersize;
589 }
590 return dev->out_eps[ep_num - 1U].doeptsiz_reg.xfersize;
591}
592
593size_t ESP32USBEndpoint::GetCompletedTransferSize() const
594{
595 if ((GetDirection() == Direction::OUT) && device_.DmaEnabled() && dma_rx_status_seen_)
596 {
597 return dma_rx_status_bytes_;
598 }
599
600 const size_t remaining = GetRemainingTransferSize();
601 return (remaining >= transfer_request_size_) ? 0U
602 : (transfer_request_size_ - remaining);
603}
604
605void ESP32USBEndpoint::ActivateHardwareEndpoint()
606{
607 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
608 const uint8_t ep_num = EPNumberToInt8(GetNumber());
609 auto& cfg = GetConfig();
610
611 if (GetDirection() == Direction::IN)
612 {
613 if (ep_num == 0U)
614 {
615 usb_dwc_diepctl0_reg_t ctl = {};
616 ctl.mps = Detail::EncodeEp0Mps(cfg.max_packet_size);
617 ctl.usbactep = 1;
618 ctl.eptype = static_cast<uint32_t>(cfg.type);
619 ctl.txfnum = 0;
620 dev->diepctl0_reg.val = ctl.val;
621 }
622 else
623 {
624 usb_dwc_diepctl_reg_t ctl = {};
625 ctl.mps = cfg.max_packet_size;
626 ctl.usbactep = 1;
627 ctl.eptype = static_cast<uint32_t>(cfg.type);
628 ctl.txfnum = ep_num;
629 ctl.setd0pid = 1;
630 dev->in_eps[ep_num - 1U].diepctl_reg.val = ctl.val;
631 }
632 dev->daintmsk_reg.val |= (1UL << ep_num);
633 }
634 else
635 {
636 if (ep_num == 0U)
637 {
638 usb_dwc_doepctl0_reg_t ctl = {};
639 ctl.mps = Detail::EncodeEp0Mps(cfg.max_packet_size);
640 ctl.usbactep = 1;
641 ctl.eptype = static_cast<uint32_t>(cfg.type);
642 dev->doepctl0_reg.val = ctl.val;
643 }
644 else
645 {
646 usb_dwc_doepctl_reg_t ctl = {};
647 ctl.mps = cfg.max_packet_size;
648 ctl.usbactep = 1;
649 ctl.eptype = static_cast<uint32_t>(cfg.type);
650 ctl.setd0pid = 1;
651 dev->out_eps[ep_num - 1U].doepctl_reg.val = ctl.val;
652 }
653 dev->daintmsk_reg.val |= (1UL << (16U + ep_num));
654 }
655}
656
657void ESP32USBEndpoint::ProgramTransfer(size_t size)
658{
659 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
660 const uint8_t ep_num = EPNumberToInt8(GetNumber());
661 const uint16_t pkt_count = Detail::PacketCount(size, MaxPacketSize());
662
663 if (GetDirection() == Direction::IN)
664 {
665 if (ep_num == 0U)
666 {
667 dev->dieptsiz0_reg.xfersize = static_cast<uint32_t>(size);
668 dev->dieptsiz0_reg.pktcnt = pkt_count;
669 if (device_.DmaEnabled() && (size > 0U))
670 {
671 dev->diepdma0_reg.dmaaddr =
672 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
673 }
674 Detail::StartEndpointTransfer(dev->diepctl0_reg);
675 }
676 else
677 {
678 auto& tsiz = dev->in_eps[ep_num - 1U].dieptsiz_reg;
679 tsiz.xfersize = static_cast<uint32_t>(size);
680 tsiz.pktcnt = pkt_count;
681 tsiz.mc = 1U;
682 if (device_.DmaEnabled() && (size > 0U))
683 {
684 dev->in_eps[ep_num - 1U].diepdma_reg.dmaddr =
685 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
686 }
687 Detail::StartEndpointTransfer(dev->in_eps[ep_num - 1U].diepctl_reg);
688 }
689
690 if (!device_.DmaEnabled() && (size > 0U))
691 {
692 WriteMoreTxData();
693 if ((ep_num != 0U) && (transfer_queued_size_ < transfer_request_size_))
694 {
695 dev->diepempmsk_reg.val |= (1UL << ep_num);
696 }
697 }
698 }
699 else
700 {
701 if (ep_num == 0U)
702 {
703 dev->doeptsiz0_reg.val = 0U;
704 dev->doeptsiz0_reg.xfersize =
705 static_cast<uint32_t>((size == 0U) ? MaxPacketSize() : size);
706 dev->doeptsiz0_reg.pktcnt = pkt_count;
707 if (device_.DmaEnabled() && (size > 0U))
708 {
709 dev->doepdma0_reg.dmaaddr =
710 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
711 }
712 Detail::StartEndpointTransfer(dev->doepctl0_reg);
713 }
714 else
715 {
716 auto& tsiz = dev->out_eps[ep_num - 1U].doeptsiz_reg;
717 tsiz.xfersize = static_cast<uint32_t>(size);
718 tsiz.pktcnt = pkt_count;
719 tsiz.rxdpid = 0U;
720 if (device_.DmaEnabled() && (size > 0U))
721 {
722 dev->out_eps[ep_num - 1U].doepdma_reg.dmaaddr =
723 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
724 }
725 Detail::StartEndpointTransfer(dev->out_eps[ep_num - 1U].doepctl_reg);
726 }
727 }
728}
729
730void ESP32USBEndpoint::WriteMoreTxData()
731{
732 if (transfer_buffer_ == nullptr || transfer_queued_size_ >= transfer_request_size_)
733 {
734 return;
735 }
736
737 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::kDwc2FsRegBase);
738 const uint8_t ep_num = EPNumberToInt8(GetNumber());
739 const volatile uint32_t* fifo = Detail::GetEndpointFifo(dev, ep_num);
740
741 while (transfer_queued_size_ < transfer_request_size_)
742 {
743 uint16_t fifo_words = 0U;
744 if (ep_num == 0U)
745 {
746 fifo_words = dev->dtxfsts0_reg.ineptxfspcavail;
747 }
748 else
749 {
750 fifo_words = dev->in_eps[ep_num - 1U].dtxfsts_reg.ineptxfspcavail;
751 }
752
753 const size_t remaining = transfer_request_size_ - transfer_queued_size_;
754 const size_t packet_size = std::min(remaining, static_cast<size_t>(MaxPacketSize()));
755 if (packet_size > static_cast<size_t>(fifo_words) * 4U)
756 {
757 break;
758 }
759
760 Detail::WriteFifoPacket(const_cast<volatile uint32_t*>(fifo),
761 transfer_buffer_ + transfer_queued_size_, packet_size);
762 transfer_queued_size_ += packet_size;
763 }
764}
765
766} // namespace LibXR
767
768#endif
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
Definition libxr_def.hpp:64