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