libxr
Embedded C++ framework for bare-metal, RTOS and Linux
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 LibXR
14{
15
16ESP32USBEndpoint::ESP32USBEndpoint(ESP32USBDevice& device, EPNumber number,
17 Direction direction, RawData buffer)
18 : USB::Endpoint(number, direction, buffer), device_(device)
19{
20}
21
22void ESP32USBEndpoint::Configure(const Config& cfg)
23{
24 ASSERT(cfg.direction == Direction::IN || cfg.direction == Direction::OUT);
25
26 auto& ep_cfg = GetConfig();
27 ep_cfg = cfg;
28 ep_cfg.max_packet_size = ESPUSBDetail::ClampPacketSize(cfg.type, cfg.max_packet_size);
29 if (ep_cfg.max_packet_size == 0U)
30 {
31 ep_cfg.max_packet_size = (cfg.type == Type::ISOCHRONOUS) ? 1023U : 64U;
32 }
33
34 auto buffer = GetBuffer();
35 if (buffer.size_ < ep_cfg.max_packet_size)
36 {
37 ep_cfg.max_packet_size = static_cast<uint16_t>(buffer.size_);
38 }
39
40 ASSERT(ep_cfg.max_packet_size > 0U);
41
42 if (device_.DmaEnabled() && (buffer.size_ > 0U) && !EnsureDmaShadow(buffer.size_))
43 {
44 SetState(State::ERROR);
45 return;
46 }
47
48 if (cfg.direction == Direction::IN)
49 {
50 const bool is_bulk = (cfg.type == Type::BULK);
51 if (!fifo_allocated_ &&
52 !device_.AllocateTxFifo(EPNumberToInt8(GetNumber()), ep_cfg.max_packet_size,
53 is_bulk, fifo_words_))
54 {
55 SetState(State::ERROR);
56 return;
57 }
58 fifo_allocated_ = true;
59 }
60 else
61 {
62 if (!device_.EnsureRxFifo(ep_cfg.max_packet_size))
63 {
64 SetState(State::ERROR);
65 return;
66 }
67 }
68
69 ActivateHardwareEndpoint();
70 ResetTransferState();
71 SetState(State::IDLE);
72}
73
74void ESP32USBEndpoint::Close()
75{
76 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
77 const uint8_t ep_num = EPNumberToInt8(GetNumber());
78
79 if (GetDirection() == Direction::IN)
80 {
81 if (ep_num == 0U)
82 {
83 if (dev->diepctl0_reg.epena)
84 {
85 ESPUSBDetail::DisableInEndpointAndWait(dev);
86 }
87 }
88 else
89 {
90 dev->diepempmsk_reg.val &= ~(1UL << ep_num);
91 if (dev->in_eps[ep_num - 1U].diepctl_reg.epena)
92 {
93 ESPUSBDetail::DisableInEndpointAndWait(dev, ep_num);
94 }
95 }
96 dev->daintmsk_reg.val &= ~(1UL << ep_num);
97 }
98 else
99 {
100 if (ep_num == 0U)
101 {
102 ESPUSBDetail::DisableOutEndpointAndWait(dev->doepctl0_reg);
103 }
104 else
105 {
106 ESPUSBDetail::DisableOutEndpointAndWait(dev->out_eps[ep_num - 1U].doepctl_reg);
107 }
108 dev->daintmsk_reg.val &= ~(1UL << (16U + ep_num));
109 }
110
111 ResetTransferState();
112 SetState(State::DISABLED);
113}
114
115ErrorCode ESP32USBEndpoint::Stall()
116{
117 const bool is_in = (GetDirection() == Direction::IN);
118 if ((GetState() == State::BUSY) && is_in)
119 {
120 return ErrorCode::BUSY;
121 }
122
123 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
124 const uint8_t ep_num = EPNumberToInt8(GetNumber());
125
126 if (is_in)
127 {
128 if (ep_num == 0U)
129 {
130 dev->diepctl0_reg.stall = 1;
131 }
132 else
133 {
134 dev->in_eps[ep_num - 1U].diepctl_reg.stall = 1;
135 }
136 }
137 else
138 {
139 if (ep_num == 0U)
140 {
141 dev->doepctl0_reg.stall = 1;
142 }
143 else
144 {
145 dev->out_eps[ep_num - 1U].doepctl_reg.stall = 1;
146 }
147 }
148
149 SetState(State::STALLED);
150 return ErrorCode::OK;
151}
152
153ErrorCode ESP32USBEndpoint::ClearStall()
154{
155 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
156 const uint8_t ep_num = EPNumberToInt8(GetNumber());
157
158 if (GetDirection() == Direction::IN)
159 {
160 if (ep_num == 0U)
161 {
162 dev->diepctl0_reg.stall = 0;
163 }
164 else
165 {
166 auto& reg = dev->in_eps[ep_num - 1U].diepctl_reg;
167 reg.stall = 0;
168 reg.setd0pid = 1;
169 }
170 }
171 else
172 {
173 if (ep_num == 0U)
174 {
175 dev->doepctl0_reg.stall = 0;
176 }
177 else
178 {
179 auto& reg = dev->out_eps[ep_num - 1U].doepctl_reg;
180 reg.stall = 0;
181 reg.setd0pid = 1;
182 }
183 }
184
185 SetState(State::IDLE);
186 return ErrorCode::OK;
187}
188
189ErrorCode ESP32USBEndpoint::Transfer(size_t size)
190{
191 if (GetState() == State::BUSY)
192 {
193 return ErrorCode::BUSY;
194 }
195
196 auto buffer = GetBuffer();
197 if (buffer.size_ < size)
198 {
199 return ErrorCode::NO_BUFF;
200 }
201
202 transfer_buffer_ = static_cast<uint8_t*>(buffer.addr_);
203 transfer_request_size_ = size;
204 transfer_actual_size_ = 0U;
205 transfer_queued_size_ = 0U;
206
207 const uint8_t ep_num = EPNumberToInt8(GetNumber());
208 if ((ep_num == 0U) && (GetDirection() == Direction::OUT))
209 {
210 ep0_out_phase_ = (size == 0U) ? Ep0OutPhase::STATUS : Ep0OutPhase::DATA;
211 }
212
213 if (UseDoubleBuffer() && GetDirection() == Direction::IN && size > 0U)
214 {
215 SwitchBuffer();
216 }
217
218 if (!PrepareTransferBuffer(size))
219 {
220 ResetTransferState();
221 return ErrorCode::NO_MEM;
222 }
223
224 SetState(State::BUSY);
225 ProgramTransfer(size);
226 return ErrorCode::OK;
227}
228
229size_t ESP32USBEndpoint::MaxTransferSize() const
230{
231 if (GetNumber() == EPNumber::EP0)
232 {
233 return MaxPacketSize();
234 }
235 return GetBuffer().size_;
236}
237
238void ESP32USBEndpoint::ResetHardwareState()
239{
240 fifo_allocated_ = false;
241 fifo_words_ = 0U;
242 ResetTransferState();
243 SetState(State::DISABLED);
244}
245
246void ESP32USBEndpoint::HandleInInterrupt(bool in_isr)
247{
248 const uint8_t ep_num = EPNumberToInt8(GetNumber());
249 usb_dwc_diepint_reg_t intr = {};
250 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
251
252 if (ep_num == 0U)
253 {
254 intr.val = dev->diepint0_reg.val;
255 dev->diepint0_reg.val = intr.val;
256 }
257 else
258 {
259 intr.val = dev->in_eps[ep_num - 1U].diepint_reg.val;
260 dev->in_eps[ep_num - 1U].diepint_reg.val = intr.val;
261 }
262
263 if (!device_.DmaEnabled() && intr.txfemp)
264 {
265 WriteMoreTxData();
266 if (transfer_queued_size_ >= transfer_request_size_)
267 {
268 dev->diepempmsk_reg.val &= ~(1UL << ep_num);
269 }
270 }
271
272 if (intr.xfercompl)
273 {
274 const bool rearm_ep0_setup = (ep_num == 0U) && device_.DmaEnabled() &&
275 (transfer_request_size_ == 0U) &&
276 device_.LastSetupDirectionOut();
277 dev->diepempmsk_reg.val &= ~(1UL << ep_num);
278 const size_t actual =
279 device_.DmaEnabled() ? GetCompletedTransferSize() : transfer_request_size_;
280 OnTransferCompleteCallback(in_isr, actual);
281 if (rearm_ep0_setup)
282 {
283 device_.ReloadSetupPacketCount();
284 }
285 if (GetState() != State::BUSY)
286 {
287 ResetTransferState();
288 }
289 }
290}
291
292void ESP32USBEndpoint::FinishPendingEp0InStatus(bool in_isr)
293{
294 if (!device_.DmaEnabled() || (device_.endpoint_map_.in[0] == nullptr))
295 {
296 return;
297 }
298
299 auto* ep0_in = static_cast<ESP32USBEndpoint*>(device_.endpoint_map_.in[0]);
300 if ((ep0_in->GetState() != State::BUSY) || (ep0_in->transfer_request_size_ != 0U))
301 {
302 return;
303 }
304
305 ep0_in->OnTransferCompleteCallback(in_isr, 0U);
306 if (ep0_in->GetState() != State::BUSY)
307 {
308 ep0_in->ResetTransferState();
309 }
310}
311
312void ESP32USBEndpoint::HandleOutInterrupt(bool in_isr)
313{
314 const uint8_t ep_num = EPNumberToInt8(GetNumber());
315 usb_dwc_doepint_reg_t intr = {};
316 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
317
318 if (ep_num == 0U)
319 {
320 intr.val = dev->doepint0_reg.val;
321 dev->doepint0_reg.val = intr.val;
322 }
323 else
324 {
325 intr.val = dev->out_eps[ep_num - 1U].doepint_reg.val;
326 dev->out_eps[ep_num - 1U].doepint_reg.val = intr.val;
327 }
328
329 const bool ep0_setup_related =
330 (ep_num == 0U) && (intr.setup || intr.stuppktrcvd || intr.back2backsetup);
331 const bool has_active_ep0_transfer =
332 (ep_num == 0U) && (GetState() == State::BUSY) &&
333 ((transfer_buffer_ != nullptr) || (transfer_request_size_ > 0U));
334
335 if (intr.xfercompl &&
336 ((ep_num != 0U) || ((ep0_out_phase_ != Ep0OutPhase::SETUP) && !ep0_setup_related &&
337 has_active_ep0_transfer)))
338 {
339 const size_t actual =
340 device_.DmaEnabled() ? GetCompletedTransferSize() : transfer_actual_size_;
341 const auto finish_out_transfer_result = FinishOutTransfer(actual);
342 REQUIRE_FROM_CALLBACK(finish_out_transfer_result, in_isr);
343 if (ep_num == 0U)
344 {
345 FinishPendingEp0InStatus(in_isr);
346 }
347 OnTransferCompleteCallback(in_isr, actual);
348 if ((ep_num == 0U) && device_.DmaEnabled() && (transfer_request_size_ == 0U))
349 {
350 device_.ReloadSetupPacketCount();
351 }
352 if (GetState() != State::BUSY)
353 {
354 ResetTransferState();
355 }
356 }
357
358 if (intr.setup)
359 {
360 if (device_.DmaEnabled())
361 {
362 const auto cache_sync_dma_buffer_result = ESPUSBDetail::CacheSyncDmaBuffer(
363 device_.setup_packet_, ESP32USBDevice::SETUP_DMA_BUFFER_BYTES, false);
364 REQUIRE_FROM_CALLBACK(cache_sync_dma_buffer_result, in_isr);
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 ESPUSBDetail::ReadFifoPacket(
408 ESPUSBDetail::GetEndpointFifo(
409 reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE), 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 = ESPUSBDetail::GetEndpointFifo(
422 reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE), 0);
423 while (remain_drop > 0U)
424 {
425 const size_t chunk = std::min(remain_drop, sizeof(sink));
426 ESPUSBDetail::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 != ESPUSBDetail::RX_STATUS_DATA)
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 = ESPUSBDetail::AlignUp(size, ESPUSBDetail::USB_DMA_ALIGNMENT);
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 = heap_caps_aligned_alloc(ESPUSBDetail::USB_DMA_ALIGNMENT, need,
474 ESPUSBDetail::DMA_MEMORY_CAPS);
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 (ESPUSBDetail::CanUseDirectInDmaBuffer(transfer_buffer_, size))
504 {
505 return ESPUSBDetail::CacheSyncDmaBuffer(transfer_hw_buffer_, size, true, true);
506 }
507 }
508 else
509 {
510 auto buffer = GetBuffer();
511 if (ESPUSBDetail::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 DEV_ASSERT(transfer_buffer_ != nullptr);
529 std::memcpy(transfer_hw_buffer_, transfer_buffer_, size);
530 return ESPUSBDetail::CacheSyncDmaBuffer(
531 transfer_hw_buffer_, ESPUSBDetail::AlignUp(size, ESPUSBDetail::USB_DMA_ALIGNMENT),
532 true);
533 }
534
535 return ESPUSBDetail::CacheSyncDmaBuffer(
536 transfer_hw_buffer_, ESPUSBDetail::AlignUp(size, ESPUSBDetail::USB_DMA_ALIGNMENT),
537 false);
538}
539
540bool ESP32USBEndpoint::FinishOutTransfer(size_t actual_size)
541{
542 transfer_actual_size_ = actual_size;
543
544 if (!device_.DmaEnabled() || (actual_size == 0U))
545 {
546 return true;
547 }
548
549 DEV_ASSERT(transfer_hw_buffer_ != nullptr);
550
551 if (!transfer_uses_shadow_)
552 {
553 if (transfer_direct_sync_size_ == 0U)
554 {
555 return true;
556 }
557 return ESPUSBDetail::CacheSyncDmaBuffer(transfer_hw_buffer_,
558 transfer_direct_sync_size_, false);
559 }
560
561 DEV_ASSERT(transfer_buffer_ != nullptr);
562
563 if (!ESPUSBDetail::CacheSyncDmaBuffer(
564 transfer_hw_buffer_,
565 ESPUSBDetail::AlignUp(actual_size, ESPUSBDetail::USB_DMA_ALIGNMENT), false))
566 {
567 return false;
568 }
569
570 std::memcpy(transfer_buffer_, transfer_hw_buffer_, actual_size);
571 return true;
572}
573
574size_t ESP32USBEndpoint::GetRemainingTransferSize() const
575{
576 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
577 const uint8_t ep_num = EPNumberToInt8(GetNumber());
578
579 if (GetDirection() == Direction::IN)
580 {
581 if (ep_num == 0U)
582 {
583 return dev->dieptsiz0_reg.xfersize;
584 }
585 return dev->in_eps[ep_num - 1U].dieptsiz_reg.xfersize;
586 }
587
588 if (ep_num == 0U)
589 {
590 return dev->doeptsiz0_reg.xfersize;
591 }
592 return dev->out_eps[ep_num - 1U].doeptsiz_reg.xfersize;
593}
594
595size_t ESP32USBEndpoint::GetCompletedTransferSize() const
596{
597 if ((GetDirection() == Direction::OUT) && device_.DmaEnabled() && dma_rx_status_seen_)
598 {
599 return dma_rx_status_bytes_;
600 }
601
602 const size_t remaining = GetRemainingTransferSize();
603 return (remaining >= transfer_request_size_) ? 0U
604 : (transfer_request_size_ - remaining);
605}
606
607void ESP32USBEndpoint::ActivateHardwareEndpoint()
608{
609 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
610 const uint8_t ep_num = EPNumberToInt8(GetNumber());
611 auto& cfg = GetConfig();
612
613 if (GetDirection() == Direction::IN)
614 {
615 if (ep_num == 0U)
616 {
617 usb_dwc_diepctl0_reg_t ctl = {};
618 ctl.mps = ESPUSBDetail::EncodeEp0Mps(cfg.max_packet_size);
619 ctl.usbactep = 1;
620 ctl.eptype = static_cast<uint32_t>(cfg.type);
621 ctl.txfnum = 0;
622 dev->diepctl0_reg.val = ctl.val;
623 }
624 else
625 {
626 usb_dwc_diepctl_reg_t ctl = {};
627 ctl.mps = cfg.max_packet_size;
628 ctl.usbactep = 1;
629 ctl.eptype = static_cast<uint32_t>(cfg.type);
630 ctl.txfnum = ep_num;
631 ctl.setd0pid = 1;
632 dev->in_eps[ep_num - 1U].diepctl_reg.val = ctl.val;
633 }
634 dev->daintmsk_reg.val |= (1UL << ep_num);
635 }
636 else
637 {
638 if (ep_num == 0U)
639 {
640 usb_dwc_doepctl0_reg_t ctl = {};
641 ctl.mps = ESPUSBDetail::EncodeEp0Mps(cfg.max_packet_size);
642 ctl.usbactep = 1;
643 ctl.eptype = static_cast<uint32_t>(cfg.type);
644 dev->doepctl0_reg.val = ctl.val;
645 }
646 else
647 {
648 usb_dwc_doepctl_reg_t ctl = {};
649 ctl.mps = cfg.max_packet_size;
650 ctl.usbactep = 1;
651 ctl.eptype = static_cast<uint32_t>(cfg.type);
652 ctl.setd0pid = 1;
653 dev->out_eps[ep_num - 1U].doepctl_reg.val = ctl.val;
654 }
655 dev->daintmsk_reg.val |= (1UL << (16U + ep_num));
656 }
657}
658
659void ESP32USBEndpoint::ProgramTransfer(size_t size)
660{
661 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
662 const uint8_t ep_num = EPNumberToInt8(GetNumber());
663 const uint16_t pkt_count = ESPUSBDetail::PacketCount(size, MaxPacketSize());
664
665 if (GetDirection() == Direction::IN)
666 {
667 if (ep_num == 0U)
668 {
669 dev->dieptsiz0_reg.xfersize = static_cast<uint32_t>(size);
670 dev->dieptsiz0_reg.pktcnt = pkt_count;
671 if (device_.DmaEnabled() && (size > 0U))
672 {
673 dev->diepdma0_reg.dmaaddr =
674 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
675 }
676 ESPUSBDetail::StartEndpointTransfer(dev->diepctl0_reg);
677 }
678 else
679 {
680 auto& tsiz = dev->in_eps[ep_num - 1U].dieptsiz_reg;
681 tsiz.xfersize = static_cast<uint32_t>(size);
682 tsiz.pktcnt = pkt_count;
683 tsiz.mc = 1U;
684 if (device_.DmaEnabled() && (size > 0U))
685 {
686 dev->in_eps[ep_num - 1U].diepdma_reg.dmaddr =
687 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
688 }
689 ESPUSBDetail::StartEndpointTransfer(dev->in_eps[ep_num - 1U].diepctl_reg);
690 }
691
692 if (!device_.DmaEnabled() && (size > 0U))
693 {
694 WriteMoreTxData();
695 if ((ep_num != 0U) && (transfer_queued_size_ < transfer_request_size_))
696 {
697 dev->diepempmsk_reg.val |= (1UL << ep_num);
698 }
699 }
700 }
701 else
702 {
703 if (ep_num == 0U)
704 {
705 dev->doeptsiz0_reg.val = 0U;
706 dev->doeptsiz0_reg.xfersize =
707 static_cast<uint32_t>((size == 0U) ? MaxPacketSize() : size);
708 dev->doeptsiz0_reg.pktcnt = pkt_count;
709 if (device_.DmaEnabled() && (size > 0U))
710 {
711 dev->doepdma0_reg.dmaaddr =
712 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
713 }
714 ESPUSBDetail::StartEndpointTransfer(dev->doepctl0_reg);
715 }
716 else
717 {
718 auto& tsiz = dev->out_eps[ep_num - 1U].doeptsiz_reg;
719 tsiz.xfersize = static_cast<uint32_t>(size);
720 tsiz.pktcnt = pkt_count;
721 tsiz.rxdpid = 0U;
722 if (device_.DmaEnabled() && (size > 0U))
723 {
724 dev->out_eps[ep_num - 1U].doepdma_reg.dmaaddr =
725 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(transfer_hw_buffer_));
726 }
727 ESPUSBDetail::StartEndpointTransfer(dev->out_eps[ep_num - 1U].doepctl_reg);
728 }
729 }
730}
731
732void ESP32USBEndpoint::WriteMoreTxData()
733{
734 if (transfer_buffer_ == nullptr || transfer_queued_size_ >= transfer_request_size_)
735 {
736 return;
737 }
738
739 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(ESPUSBDetail::DWC2_FS_REG_BASE);
740 const uint8_t ep_num = EPNumberToInt8(GetNumber());
741 const volatile uint32_t* fifo = ESPUSBDetail::GetEndpointFifo(dev, ep_num);
742
743 while (transfer_queued_size_ < transfer_request_size_)
744 {
745 uint16_t fifo_words = 0U;
746 if (ep_num == 0U)
747 {
748 fifo_words = dev->dtxfsts0_reg.ineptxfspcavail;
749 }
750 else
751 {
752 fifo_words = dev->in_eps[ep_num - 1U].dtxfsts_reg.ineptxfspcavail;
753 }
754
755 const size_t remaining = transfer_request_size_ - transfer_queued_size_;
756 const size_t packet_size = std::min(remaining, static_cast<size_t>(MaxPacketSize()));
757 if (packet_size > static_cast<size_t>(fifo_words) * 4U)
758 {
759 break;
760 }
761
762 ESPUSBDetail::WriteFifoPacket(const_cast<volatile uint32_t*>(fifo),
763 transfer_buffer_ + transfer_queued_size_, packet_size);
764 transfer_queued_size_ += packet_size;
765 }
766}
767
768} // namespace LibXR
769
770#endif
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes