libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
esp_usb_dev.cpp
1#include "esp_usb_dev.hpp"
2
3#if SOC_USB_OTG_SUPPORTED && defined(CONFIG_IDF_TARGET_ESP32S3) && \
4 CONFIG_IDF_TARGET_ESP32S3
5
6#include <cstring>
7#include <new>
8
9#include "esp32s3/rom/usb/cdc_acm.h"
10#include "esp32s3/rom/usb/usb_dc.h"
11#include "esp32s3/rom/usb/usb_device.h"
12#include "esp_attr.h"
13#include "esp_err.h"
14#include "esp_private/usb_phy.h"
15#include "esp_usb.hpp"
16#include "esp_usb_ep.hpp"
17#include "soc/interrupts.h"
18
19namespace Detail = LibXR::ESPUSBDetail;
20
21namespace LibXR
22{
23
24ESP32USBDevice::ESP32USBDevice(
25 const std::initializer_list<EPConfig> ep_cfgs,
26 USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid,
27 uint16_t bcd,
28 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> lang_list,
29 const std::initializer_list<const std::initializer_list<USB::ConfigDescriptorItem*>>
30 configs,
31 ConstRawData uid)
32 : USB::EndpointPool(ep_cfgs.size() * 2U),
33 USB::DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::FULL, packet_size, vid,
34 pid, bcd, lang_list, configs, uid)
35{
36 ASSERT(ep_cfgs.size() > 0U && ep_cfgs.size() <= ENDPOINT_COUNT);
37
38 auto cfg_it = ep_cfgs.begin();
39
40 auto* ep0_out = new ESP32USBEndpoint(*this, USB::Endpoint::EPNumber::EP0,
41 USB::Endpoint::Direction::OUT, cfg_it->buffer);
42 auto* ep0_in = new ESP32USBEndpoint(*this, USB::Endpoint::EPNumber::EP0,
43 USB::Endpoint::Direction::IN, cfg_it->buffer);
44
45 SetEndpoint0(ep0_in, ep0_out);
46 endpoint_map_.in[0] = ep0_in;
47 endpoint_map_.out[0] = ep0_out;
48
49 auto ep_num = USB::Endpoint::EPNumber::EP1;
50 for (++cfg_it; cfg_it != ep_cfgs.end();
51 ++cfg_it, ep_num = USB::Endpoint::NextEPNumber(ep_num))
52 {
53 ASSERT(USB::Endpoint::EPNumberToInt8(ep_num) < ENDPOINT_COUNT);
54
55 if (cfg_it->direction_hint == EPConfig::DirectionHint::BothDirections)
56 {
57 auto* ep_out = new ESP32USBEndpoint(*this, ep_num, USB::Endpoint::Direction::OUT,
58 cfg_it->buffer);
59 auto* ep_in = new ESP32USBEndpoint(*this, ep_num, USB::Endpoint::Direction::IN,
60 cfg_it->buffer);
61 endpoint_map_.out[USB::Endpoint::EPNumberToInt8(ep_num)] = ep_out;
62 endpoint_map_.in[USB::Endpoint::EPNumberToInt8(ep_num)] = ep_in;
63 Put(ep_out);
64 Put(ep_in);
65 }
66 else
67 {
68 const auto direction = (cfg_it->direction_hint == EPConfig::DirectionHint::InOnly)
69 ? USB::Endpoint::Direction::IN
70 : USB::Endpoint::Direction::OUT;
71 auto* ep = new ESP32USBEndpoint(*this, ep_num, direction, cfg_it->buffer);
72 if (direction == USB::Endpoint::Direction::IN)
73 {
74 endpoint_map_.in[USB::Endpoint::EPNumberToInt8(ep_num)] = ep;
75 }
76 else
77 {
78 endpoint_map_.out[USB::Endpoint::EPNumberToInt8(ep_num)] = ep;
79 }
80 Put(ep);
81 }
82 }
83}
84
85void ESP32USBDevice::Init(bool in_isr)
86{
87 ResetFifoState();
88 USB::DeviceCore::Init(in_isr);
89}
90
91void ESP32USBDevice::Deinit(bool in_isr) { USB::DeviceCore::Deinit(in_isr); }
92
93ErrorCode ESP32USBDevice::SetAddress(uint8_t address, USB::DeviceCore::Context context)
94{
95 if (context == USB::DeviceCore::Context::SETUP_BEFORE_STATUS)
96 {
97 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
98 dev->dcfg_reg.devaddr = address;
99 }
100 return ErrorCode::OK;
101}
102
103void ESP32USBDevice::Start(bool)
104{
105 if (runtime_.started)
106 {
107 return;
108 }
109
110 EnsureRomUsbCleaned();
111 ASSERT(EnsurePhyReady());
112 ASSERT(EnsureInterruptReady());
113
114 InitializeCore();
115 if (IsInited())
116 {
117 USB::DeviceCore::Deinit(false);
118 USB::DeviceCore::Init(false);
119 }
120
121 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
122 dev->dctl_reg.sftdiscon = 0;
123 dev->gahbcfg_reg.glbllntrmsk = 1;
124 if (runtime_.intr_handle != nullptr)
125 {
126 esp_intr_enable(runtime_.intr_handle);
127 }
128 runtime_.started = true;
129}
130
131void ESP32USBDevice::Stop(bool)
132{
133 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
134 dev->gahbcfg_reg.glbllntrmsk = 0;
135 dev->gintmsk_reg.val = 0;
136 if (runtime_.intr_handle != nullptr)
137 {
138 esp_intr_disable(runtime_.intr_handle);
139 }
140 dev->dctl_reg.sftdiscon = 1;
141 runtime_.started = false;
142}
143
144void IRAM_ATTR ESP32USBDevice::IsrEntry(void* arg)
145{
146 auto* self = static_cast<ESP32USBDevice*>(arg);
147 if (self != nullptr)
148 {
149 self->HandleInterrupt();
150 }
151}
152
153bool ESP32USBDevice::EnsurePhyReady()
154{
155 if (runtime_.phy_ready)
156 {
157 return true;
158 }
159
160 usb_phy_config_t phy_conf = {
161 .controller = USB_PHY_CTRL_OTG,
162 .target = USB_PHY_TARGET_INT,
163 .otg_mode = USB_OTG_MODE_DEVICE,
164 .otg_speed = USB_PHY_SPEED_UNDEFINED,
165 .ext_io_conf = nullptr,
166 .otg_io_conf = nullptr,
167 };
168
169 usb_phy_handle_t handle = nullptr;
170 if (usb_new_phy(&phy_conf, &handle) != ESP_OK)
171 {
172 return false;
173 }
174
175 runtime_.phy_handle = handle;
176 runtime_.phy_ready = true;
177 return true;
178}
179
180bool ESP32USBDevice::EnsureInterruptReady()
181{
182 if (runtime_.irq_ready)
183 {
184 return true;
185 }
186
187 if (esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED,
188 IsrEntry, this, &runtime_.intr_handle) != ESP_OK)
189 {
190 runtime_.intr_handle = nullptr;
191 return false;
192 }
193
194 runtime_.irq_ready = true;
195 return true;
196}
197
198void ESP32USBDevice::EnsureRomUsbCleaned()
199{
200 if (runtime_.rom_usb_cleaned)
201 {
202 return;
203 }
204
205 usb_dev_deinit();
206 usb_dw_ctrl_deinit();
207 uart_acm_dev = nullptr;
208 runtime_.rom_usb_cleaned = true;
209}
210
211void ESP32USBDevice::InitializeCore()
212{
213 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
214
215 dev->gahbcfg_reg.glbllntrmsk = 0;
216
217 while (!dev->grstctl_reg.ahbidle)
218 {
219 }
220
221 dev->gusbcfg_reg.forcehstmode = 0;
222 dev->gusbcfg_reg.forcedevmode = 1;
223 dev->gusbcfg_reg.physel = 1;
224 dev->gusbcfg_reg.usbtrdtim = 5;
225 dev->gusbcfg_reg.toutcal = 7;
226 dev->gusbcfg_reg.srpcap = 0;
227 dev->gusbcfg_reg.hnpcap = 0;
228
229 dev->grstctl_reg.csftrst = 1;
230 while (dev->grstctl_reg.csftrst)
231 {
232 }
233 while (!dev->grstctl_reg.ahbidle)
234 {
235 }
236
237 dev->pcgcctl_reg.stoppclk = 0;
238 dev->pcgcctl_reg.gatehclk = 0;
239 dev->pcgcctl_reg.pwrclmp = 0;
240 dev->pcgcctl_reg.rstpdwnmodule = 0;
241 dev->gotgctl_reg.avalidoven = 0;
242 dev->gotgctl_reg.bvalidoven = 1;
243 dev->gotgctl_reg.bvalidovval = 1;
244
245 ClearTxFifoRegisters();
246
247 FlushFifos();
248 ResetDeviceState();
249
250 dev->gintsts_reg.val = 0xFFFFFFFFU;
251 dev->gotgint_reg.val = 0xFFFFFFFFU;
252 dev->gintmsk_reg.val = 0U;
253 dev->gahbcfg_reg.hbstlen = Detail::DMA_BURST_INCR4;
254 dev->gahbcfg_reg.dmaen = DmaEnabled() ? 1U : 0U;
255 dev->gahbcfg_reg.nptxfemplvl = 1;
256 dev->gahbcfg_reg.ptxfemplvl = 1;
257 dev->dcfg_reg.descdma = 0;
258 dev->dcfg_reg.nzstsouthshk = 1;
259 dev->gintmsk_reg.usbrstmsk = 1;
260 dev->gintmsk_reg.enumdonemsk = 1;
261 dev->gintmsk_reg.usbsuspmsk = 1;
262 dev->gintmsk_reg.wkupintmsk = 1;
263 dev->gintmsk_reg.rxflvlmsk = DmaEnabled() ? 0U : 1U;
264 dev->gintmsk_reg.oepintmsk = 1;
265 dev->gintmsk_reg.iepintmsk = 1;
266 dev->gintmsk_reg.otgintmsk = 1;
267}
268
269void ESP32USBDevice::ClearTxFifoRegisters()
270{
271 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
272 dev->gnptxfsiz_reg.val = 0U;
273 const size_t tx_fifo_reg_count =
274 sizeof(dev->dieptxf_regs) / sizeof(dev->dieptxf_regs[0]);
275 for (size_t i = 0U; i < tx_fifo_reg_count; ++i)
276 {
277 dev->dieptxf_regs[i].val = 0U;
278 }
279}
280
281void ESP32USBDevice::FlushFifos()
282{
283 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
284 dev->grstctl_reg.txfnum = Detail::FLUSH_ALL_TX_FIFO;
285 dev->grstctl_reg.txfflsh = 1;
286 while (dev->grstctl_reg.txfflsh)
287 {
288 }
289 dev->grstctl_reg.rxfflsh = 1;
290 while (dev->grstctl_reg.rxfflsh)
291 {
292 }
293}
294
295void ESP32USBDevice::ResetFifoState()
296{
297 fifo_state_.depth_words = Detail::GetHardwareFifoDepthWords();
298 ASSERT(fifo_state_.depth_words > 0U);
299 fifo_state_.rx_words =
300 Detail::CalcConfiguredRxFifoWords(64U, ENDPOINT_COUNT, DmaEnabled());
301 fifo_state_.tx_next_words = fifo_state_.rx_words;
302 std::memset(fifo_state_.tx_words, 0, sizeof(fifo_state_.tx_words));
303 std::memset(fifo_state_.tx_bound, 0, sizeof(fifo_state_.tx_bound));
304 fifo_state_.allocated_in = 0U;
305}
306
307void ESP32USBDevice::ResetDeviceState()
308{
309 ResetFifoState();
310 ResetControlState();
311
312 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
313 dev->grxfsiz_reg.rxfdep = fifo_state_.rx_words;
314 ClearTxFifoRegisters();
315}
316
317void ESP32USBDevice::ResetEndpointHardwareState()
318{
319 for (uint8_t i = 0; i < ENDPOINT_COUNT; ++i)
320 {
321 if (endpoint_map_.in[i] != nullptr)
322 {
323 static_cast<ESP32USBEndpoint*>(endpoint_map_.in[i])->ResetHardwareState();
324 }
325 if (endpoint_map_.out[i] != nullptr)
326 {
327 static_cast<ESP32USBEndpoint*>(endpoint_map_.out[i])->ResetHardwareState();
328 }
329 }
330}
331
332void ESP32USBDevice::ReloadSetupPacketCount()
333{
334 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
335 dev->doeptsiz0_reg.val = 0U;
336 if (DmaEnabled())
337 {
338 dev->doeptsiz0_reg.xfersize = 3U * SETUP_PACKET_BYTES;
339 dev->doeptsiz0_reg.pktcnt = 1U;
340 dev->doeptsiz0_reg.supcnt = 3U;
341 ASSERT(Detail::CacheSyncDmaBuffer(setup_packet_, SETUP_DMA_BUFFER_BYTES, false));
342 dev->doepdma0_reg.dmaaddr =
343 static_cast<uint32_t>(reinterpret_cast<uintptr_t>(setup_packet_));
344 dev->doepctl0_reg.cnak = 1;
345 dev->doepctl0_reg.epena = 1;
346 if (endpoint_map_.out[0] != nullptr)
347 {
348 static_cast<ESP32USBEndpoint*>(endpoint_map_.out[0])->ep0_out_phase_ =
349 ESP32USBEndpoint::Ep0OutPhase::SETUP;
350 }
351 }
352 else
353 {
354 dev->doeptsiz0_reg.pktcnt = 1U;
355 dev->doeptsiz0_reg.xfersize = 3U * SETUP_PACKET_BYTES;
356 dev->doeptsiz0_reg.supcnt = 3U;
357 }
358}
359
360void ESP32USBDevice::ResetControlState() { control_ = {}; }
361
362void ESP32USBDevice::UpdateSetupState(const uint8_t* setup)
363{
364 control_.setup_direction_out = (setup != nullptr) && ((setup[0] & 0x80U) == 0U);
365}
366
367void IRAM_ATTR ESP32USBDevice::HandleInterrupt()
368{
369 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
370 for (uint32_t guard = 0; guard < INTERRUPT_DISPATCH_GUARD; ++guard)
371 {
372 usb_dwc_gintsts_reg_t pending = {};
373 pending.val = dev->gintsts_reg.val & dev->gintmsk_reg.val;
374
375 if (pending.val == 0U)
376 {
377 break;
378 }
379
380 if (pending.usbrst)
381 {
382 dev->gintsts_reg.usbrst = 1;
383 HandleBusReset(true);
384 }
385
386 if (pending.enumdone)
387 {
388 dev->gintsts_reg.enumdone = 1;
389 const uint32_t enum_speed = dev->dsts_reg.enumspd;
390 if (enum_speed != Detail::ENUM_SPEED_FULL_30_TO_60_MHZ &&
391 enum_speed != Detail::ENUM_SPEED_FULL_48_MHZ)
392 {
393 ASSERT(false);
394 }
395 }
396
397 if (pending.usbsusp)
398 {
399 dev->gintsts_reg.usbsusp = 1;
400 }
401
402 if (pending.wkupint)
403 {
404 dev->gintsts_reg.wkupint = 1;
405 }
406
407 if (!DmaEnabled() && pending.rxflvl)
408 {
409 dev->gintmsk_reg.rxflvlmsk = 0;
410 while (dev->gintsts_reg.rxflvl)
411 {
412 HandleRxFifoLevel();
413 }
414 dev->gintmsk_reg.rxflvlmsk = 1;
415 }
416
417 if (pending.oepint)
418 {
419 HandleEndpointInterrupt(true, false);
420 }
421
422 if (pending.iepint)
423 {
424 HandleEndpointInterrupt(true, true);
425 }
426
427 if (pending.otgint)
428 {
429 const uint32_t otg_status = dev->gotgint_reg.val;
430 dev->gotgint_reg.val = otg_status;
431 }
432 }
433}
434
435void ESP32USBDevice::HandleBusReset(bool in_isr)
436{
437 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
438
439 for (uint8_t i = 0; i < ENDPOINT_COUNT; ++i)
440 {
441 if (i == 0U)
442 {
443 Detail::DisableOutEndpointAndWait(dev->doepctl0_reg);
444 }
445 else
446 {
447 Detail::DisableOutEndpointAndWait(dev->out_eps[i - 1U].doepctl_reg);
448 }
449 }
450
451 for (uint8_t i = 0; i < ENDPOINT_COUNT; ++i)
452 {
453 if (i == 0U)
454 {
455 if (dev->diepctl0_reg.epena)
456 {
457 dev->diepctl0_reg.snak = 1;
458 dev->diepctl0_reg.epdis = 1;
459 }
460 }
461 else if (dev->in_eps[i - 1U].diepctl_reg.epena)
462 {
463 dev->in_eps[i - 1U].diepctl_reg.snak = 1;
464 dev->in_eps[i - 1U].diepctl_reg.epdis = 1;
465 }
466 }
467
468 dev->daintmsk_reg.val = 0U;
469 dev->doepmsk_reg.val = 0U;
470 dev->diepmsk_reg.val = 0U;
471 dev->diepempmsk_reg.val = 0U;
472 dev->doepmsk_reg.setupmsk = 1;
473 dev->doepmsk_reg.xfercomplmsk = 1;
474 dev->doepmsk_reg.epdisbldmsk = 1;
475 dev->doepmsk_reg.ahberrmsk = 1;
476 dev->doepmsk_reg.outtknepdismsk = 1;
477 dev->doepmsk_reg.stsphsercvdmsk = 1;
478 dev->doepmsk_reg.outpkterrmsk = 1;
479 dev->doepmsk_reg.bnaoutintrmsk = 1;
480 dev->doepmsk_reg.bbleerrmsk = 1;
481 dev->doepmsk_reg.nakmsk = 1;
482 dev->doepmsk_reg.nyetmsk = 1;
483 dev->diepmsk_reg.xfercomplmsk = 1;
484 dev->diepmsk_reg.timeoutmsk = 1;
485
486 FlushFifos();
487 ResetDeviceState();
488 ResetEndpointHardwareState();
489
490 dev->dcfg_reg.devaddr = 0U;
491
492 if (IsInited())
493 {
494 Deinit(in_isr);
495 Init(in_isr);
496 }
497
498 ReloadSetupPacketCount();
499}
500
501void ESP32USBDevice::HandleEndpointInterrupt(bool in_isr, bool in_dir)
502{
503 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
504 const uint32_t daint = dev->daint_reg.val & dev->daintmsk_reg.val;
505 const uint32_t bits = in_dir ? (daint & 0xFFFFU) : ((daint >> 16U) & 0xFFFFU);
506
507 for (uint8_t ep_num = 0; ep_num < ENDPOINT_COUNT; ++ep_num)
508 {
509 if ((bits & (1UL << ep_num)) == 0U)
510 {
511 continue;
512 }
513
514 USB::Endpoint* ep = in_dir ? endpoint_map_.in[ep_num] : endpoint_map_.out[ep_num];
515 if (ep == nullptr)
516 {
517 continue;
518 }
519
520 auto* esp_ep = static_cast<ESP32USBEndpoint*>(ep);
521 if (in_dir)
522 {
523 esp_ep->HandleInInterrupt(in_isr);
524 }
525 else
526 {
527 esp_ep->HandleOutInterrupt(in_isr);
528 }
529 }
530}
531
532void ESP32USBDevice::HandleRxFifoLevel()
533{
534 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
535 usb_dwc_grxstsp_reg_t status = {};
536 status.val = dev->grxstsp_reg.val;
537 const uint8_t ep_num = static_cast<uint8_t>(status.chnum);
538
539 if (DmaEnabled())
540 {
541 if ((ep_num < ENDPOINT_COUNT) && (endpoint_map_.out[ep_num] != nullptr))
542 {
543 static_cast<ESP32USBEndpoint*>(endpoint_map_.out[ep_num])
544 ->ObserveDmaRxStatus(status.pktsts, status.bcnt);
545 }
546 return;
547 }
548
549 switch (status.pktsts)
550 {
551 case Detail::RX_STATUS_GLOBAL_OUT_NAK:
552 break;
553
554 case Detail::RX_STATUS_SETUP_DATA:
555 Detail::ReadFifoPacket(Detail::GetEndpointFifo(dev, 0), setup_packet_,
556 sizeof(setup_packet_));
557 UpdateSetupState(setup_packet_);
558 break;
559
560 case Detail::RX_STATUS_SETUP_DONE:
561 ReloadSetupPacketCount();
562 break;
563
564 case Detail::RX_STATUS_DATA:
565 {
566 USB::Endpoint* ep = (ep_num < ENDPOINT_COUNT) ? endpoint_map_.out[ep_num] : nullptr;
567 if (ep != nullptr)
568 {
569 static_cast<ESP32USBEndpoint*>(ep)->HandleRxData(status.bcnt);
570 }
571 else
572 {
573 uint8_t sink[64] = {};
574 Detail::ReadFifoPacket(Detail::GetEndpointFifo(dev, 0), sink, status.bcnt);
575 }
576 break;
577 }
578
579 case Detail::RX_STATUS_TRANSFER_COMPLETE:
580 default:
581 break;
582 }
583}
584
585bool ESP32USBDevice::AllocateTxFifo(uint8_t ep_num, uint16_t packet_size, bool is_bulk,
586 uint16_t& fifo_words)
587{
588 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
589 const uint8_t max_in_ep_num =
590 static_cast<uint8_t>(sizeof(dev->dieptxf_regs) / sizeof(dev->dieptxf_regs[0]));
591
592 (void)is_bulk;
593
594 if (ep_num > max_in_ep_num)
595 {
596 return false;
597 }
598
599 const uint16_t words = Detail::CalcTxFifoWords(packet_size, DmaEnabled());
600 if (!fifo_state_.tx_bound[ep_num] && (fifo_state_.allocated_in >= IN_ENDPOINT_LIMIT))
601 {
602 return false;
603 }
604
605 for (uint8_t index = 0U; index <= ep_num; ++index)
606 {
607 const uint16_t requested_words =
608 (index == ep_num) ? words : Detail::ESP32_SX_FS_MIN_TX_FIFO_WORDS;
609 if (fifo_state_.tx_words[index] != 0U)
610 {
611 if (fifo_state_.tx_words[index] < requested_words)
612 {
613 return false;
614 }
615 continue;
616 }
617
618 const uint16_t next_words =
619 static_cast<uint16_t>(fifo_state_.tx_next_words + requested_words);
620 if (next_words > fifo_state_.depth_words)
621 {
622 return false;
623 }
624
625 const uint32_t tx_fifo_reg =
626 Detail::PackTxFifoSizeReg(fifo_state_.tx_next_words, requested_words);
627 if (index == 0U)
628 {
629 dev->gnptxfsiz_reg.val = tx_fifo_reg;
630 }
631 else
632 {
633 dev->dieptxf_regs[index - 1U].val = tx_fifo_reg;
634 }
635
636 fifo_state_.tx_words[index] = requested_words;
637 fifo_state_.tx_next_words = next_words;
638 }
639
640 if (!fifo_state_.tx_bound[ep_num])
641 {
642 fifo_state_.tx_bound[ep_num] = true;
643 fifo_state_.allocated_in++;
644 }
645 fifo_words = words;
646 return true;
647}
648
649bool ESP32USBDevice::EnsureRxFifo(uint16_t packet_size)
650{
651 auto* dev = reinterpret_cast<usb_dwc_dev_t*>(Detail::DWC2_FS_REG_BASE);
652 const uint16_t needed =
653 Detail::CalcConfiguredRxFifoWords(packet_size, ENDPOINT_COUNT, DmaEnabled());
654 if (needed <= fifo_state_.rx_words)
655 {
656 return true;
657 }
658
659 if (fifo_state_.tx_next_words != fifo_state_.rx_words)
660 {
661 return false;
662 }
663
664 if (needed > fifo_state_.depth_words)
665 {
666 return false;
667 }
668
669 fifo_state_.rx_words = needed;
670 fifo_state_.tx_next_words = needed;
671 dev->grxfsiz_reg.rxfdep = fifo_state_.rx_words;
672 return true;
673}
674
675} // namespace LibXR
676
677#endif
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
Definition desc_dev.hpp:75
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ FULL
已满 | Full