1#include "esp_usb_dev.hpp"
3#if SOC_USB_OTG_SUPPORTED && defined(CONFIG_IDF_TARGET_ESP32S3) && \
4 CONFIG_IDF_TARGET_ESP32S3
9#include "esp32s3/rom/usb/cdc_acm.h"
10#include "esp32s3/rom/usb/usb_dc.h"
11#include "esp32s3/rom/usb/usb_device.h"
14#include "esp_private/usb_phy.h"
16#include "esp_usb_ep.hpp"
17#include "soc/interrupts.h"
25 const std::initializer_list<EPConfig> ep_cfgs,
28 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> lang_list,
29 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
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)
36 ASSERT(ep_cfgs.size() > 0U && ep_cfgs.size() <= ENDPOINT_COUNT);
38 auto cfg_it = ep_cfgs.begin();
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);
45 SetEndpoint0(ep0_in, ep0_out);
46 endpoint_map_.in[0] = ep0_in;
47 endpoint_map_.out[0] = ep0_out;
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))
53 DEV_ASSERT(USB::Endpoint::EPNumberToInt8(ep_num) < ENDPOINT_COUNT);
55 if (cfg_it->direction_hint == EPConfig::DirectionHint::BothDirections)
57 auto* ep_out =
new ESP32USBEndpoint(*
this, ep_num, USB::Endpoint::Direction::OUT,
59 auto* ep_in =
new ESP32USBEndpoint(*
this, ep_num, USB::Endpoint::Direction::IN,
61 endpoint_map_.out[USB::Endpoint::EPNumberToInt8(ep_num)] = ep_out;
62 endpoint_map_.in[USB::Endpoint::EPNumberToInt8(ep_num)] = ep_in;
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)
74 endpoint_map_.in[USB::Endpoint::EPNumberToInt8(ep_num)] = ep;
78 endpoint_map_.out[USB::Endpoint::EPNumberToInt8(ep_num)] = ep;
85void ESP32USBDevice::Init(
bool in_isr)
90 USB::DeviceCore::Init(in_isr);
93void ESP32USBDevice::Deinit(
bool in_isr) { USB::DeviceCore::Deinit(in_isr); }
97ErrorCode ESP32USBDevice::SetAddress(uint8_t address, USB::DeviceCore::Context context)
99 if (context == USB::DeviceCore::Context::SETUP_BEFORE_STATUS)
101 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
102 dev->dcfg_reg.devaddr = address;
104 return ErrorCode::OK;
107void ESP32USBDevice::Start(
bool)
112 if (runtime_.started)
117 EnsureRomUsbCleaned();
118 [[maybe_unused]]
const auto ensure_phy_ready_result = EnsurePhyReady();
119 REQUIRE(ensure_phy_ready_result);
120 [[maybe_unused]]
const auto ensure_interrupt_ready_result = EnsureInterruptReady();
121 REQUIRE(ensure_interrupt_ready_result);
126 USB::DeviceCore::Deinit(
false);
127 USB::DeviceCore::Init(
false);
130 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
131 dev->dctl_reg.sftdiscon = 0;
132 dev->gahbcfg_reg.glbllntrmsk = 1;
133 if (runtime_.intr_handle !=
nullptr)
135 esp_intr_enable(runtime_.intr_handle);
137 runtime_.started =
true;
140void ESP32USBDevice::Stop(
bool)
144 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
145 dev->gahbcfg_reg.glbllntrmsk = 0;
146 dev->gintmsk_reg.val = 0;
147 if (runtime_.intr_handle !=
nullptr)
149 esp_intr_disable(runtime_.intr_handle);
151 dev->dctl_reg.sftdiscon = 1;
152 runtime_.started =
false;
155void IRAM_ATTR ESP32USBDevice::IsrEntry(
void* arg)
157 auto* self =
static_cast<ESP32USBDevice*
>(arg);
160 self->HandleInterrupt();
164bool ESP32USBDevice::EnsurePhyReady()
168 if (runtime_.phy_ready)
173 usb_phy_config_t phy_conf = {
174 .controller = USB_PHY_CTRL_OTG,
175 .target = USB_PHY_TARGET_INT,
176 .otg_mode = USB_OTG_MODE_DEVICE,
177 .otg_speed = USB_PHY_SPEED_UNDEFINED,
178 .ext_io_conf =
nullptr,
179 .otg_io_conf =
nullptr,
182 usb_phy_handle_t handle =
nullptr;
183 if (usb_new_phy(&phy_conf, &handle) != ESP_OK)
188 runtime_.phy_handle = handle;
189 runtime_.phy_ready =
true;
193bool ESP32USBDevice::EnsureInterruptReady()
197 if (runtime_.irq_ready)
202 if (esp_intr_alloc(ETS_USB_INTR_SOURCE, ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_INTRDISABLED,
203 IsrEntry,
this, &runtime_.intr_handle) != ESP_OK)
205 runtime_.intr_handle =
nullptr;
209 runtime_.irq_ready =
true;
213void ESP32USBDevice::EnsureRomUsbCleaned()
217 if (runtime_.rom_usb_cleaned)
223 usb_dw_ctrl_deinit();
224 uart_acm_dev =
nullptr;
225 runtime_.rom_usb_cleaned =
true;
228void ESP32USBDevice::InitializeCore()
233 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
235 dev->gahbcfg_reg.glbllntrmsk = 0;
237 while (!dev->grstctl_reg.ahbidle)
241 dev->gusbcfg_reg.forcehstmode = 0;
242 dev->gusbcfg_reg.forcedevmode = 1;
243 dev->gusbcfg_reg.physel = 1;
244 dev->gusbcfg_reg.usbtrdtim = 5;
245 dev->gusbcfg_reg.toutcal = 7;
246 dev->gusbcfg_reg.srpcap = 0;
247 dev->gusbcfg_reg.hnpcap = 0;
249 dev->grstctl_reg.csftrst = 1;
250 while (dev->grstctl_reg.csftrst)
253 while (!dev->grstctl_reg.ahbidle)
257 dev->pcgcctl_reg.stoppclk = 0;
258 dev->pcgcctl_reg.gatehclk = 0;
259 dev->pcgcctl_reg.pwrclmp = 0;
260 dev->pcgcctl_reg.rstpdwnmodule = 0;
261 dev->gotgctl_reg.avalidoven = 0;
262 dev->gotgctl_reg.bvalidoven = 1;
263 dev->gotgctl_reg.bvalidovval = 1;
265 ClearTxFifoRegisters();
270 dev->gintsts_reg.val = 0xFFFFFFFFU;
271 dev->gotgint_reg.val = 0xFFFFFFFFU;
272 dev->gintmsk_reg.val = 0U;
273 dev->gahbcfg_reg.hbstlen = ESPUSBDetail::DMA_BURST_INCR4;
274 dev->gahbcfg_reg.dmaen = DmaEnabled() ? 1U : 0U;
275 dev->gahbcfg_reg.nptxfemplvl = 1;
276 dev->gahbcfg_reg.ptxfemplvl = 1;
277 dev->dcfg_reg.descdma = 0;
278 dev->dcfg_reg.nzstsouthshk = 1;
279 dev->gintmsk_reg.usbrstmsk = 1;
280 dev->gintmsk_reg.enumdonemsk = 1;
281 dev->gintmsk_reg.usbsuspmsk = 1;
282 dev->gintmsk_reg.wkupintmsk = 1;
283 dev->gintmsk_reg.rxflvlmsk = DmaEnabled() ? 0U : 1U;
284 dev->gintmsk_reg.oepintmsk = 1;
285 dev->gintmsk_reg.iepintmsk = 1;
286 dev->gintmsk_reg.otgintmsk = 1;
289void ESP32USBDevice::ClearTxFifoRegisters()
293 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
294 dev->gnptxfsiz_reg.val = 0U;
295 const size_t tx_fifo_reg_count =
296 sizeof(dev->dieptxf_regs) /
sizeof(dev->dieptxf_regs[0]);
297 for (
size_t i = 0U; i < tx_fifo_reg_count; ++i)
299 dev->dieptxf_regs[i].val = 0U;
303void ESP32USBDevice::FlushFifos()
307 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
308 dev->grstctl_reg.txfnum = ESPUSBDetail::FLUSH_ALL_TX_FIFO;
309 dev->grstctl_reg.txfflsh = 1;
310 while (dev->grstctl_reg.txfflsh)
313 dev->grstctl_reg.rxfflsh = 1;
314 while (dev->grstctl_reg.rxfflsh)
319void ESP32USBDevice::ResetFifoState()
324 fifo_state_.depth_words = ESPUSBDetail::GetHardwareFifoDepthWords();
325 fifo_state_.rx_words =
326 ESPUSBDetail::CalcConfiguredRxFifoWords(64U, ENDPOINT_COUNT, DmaEnabled());
327 fifo_state_.tx_next_words = fifo_state_.rx_words;
328 std::memset(fifo_state_.tx_words, 0,
sizeof(fifo_state_.tx_words));
329 std::memset(fifo_state_.tx_bound, 0,
sizeof(fifo_state_.tx_bound));
330 fifo_state_.allocated_in = 0U;
333void ESP32USBDevice::ResetDeviceState()
343 DEV_ASSERT(fifo_state_.depth_words > 0U);
346 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
347 dev->grxfsiz_reg.rxfdep = fifo_state_.rx_words;
348 ClearTxFifoRegisters();
351void ESP32USBDevice::ResetEndpointHardwareState()
355 for (uint8_t i = 0; i < ENDPOINT_COUNT; ++i)
357 if (endpoint_map_.in[i] !=
nullptr)
359 static_cast<ESP32USBEndpoint*
>(endpoint_map_.in[i])->ResetHardwareState();
361 if (endpoint_map_.out[i] !=
nullptr)
363 static_cast<ESP32USBEndpoint*
>(endpoint_map_.out[i])->ResetHardwareState();
368void ESP32USBDevice::ReloadSetupPacketCount()
372 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
373 dev->doeptsiz0_reg.val = 0U;
376 dev->doeptsiz0_reg.xfersize = 3U * SETUP_PACKET_BYTES;
377 dev->doeptsiz0_reg.pktcnt = 1U;
378 dev->doeptsiz0_reg.supcnt = 3U;
379 const auto cache_sync_dma_buffer_result =
380 ESPUSBDetail::CacheSyncDmaBuffer(setup_packet_, SETUP_DMA_BUFFER_BYTES,
false);
381 REQUIRE(cache_sync_dma_buffer_result);
382 dev->doepdma0_reg.dmaaddr =
383 static_cast<uint32_t
>(
reinterpret_cast<uintptr_t
>(setup_packet_));
384 dev->doepctl0_reg.cnak = 1;
385 dev->doepctl0_reg.epena = 1;
386 if (endpoint_map_.out[0] !=
nullptr)
388 static_cast<ESP32USBEndpoint*
>(endpoint_map_.out[0])->ep0_out_phase_ =
389 ESP32USBEndpoint::Ep0OutPhase::SETUP;
394 dev->doeptsiz0_reg.pktcnt = 1U;
395 dev->doeptsiz0_reg.xfersize = 3U * SETUP_PACKET_BYTES;
396 dev->doeptsiz0_reg.supcnt = 3U;
400void ESP32USBDevice::ResetControlState() { control_ = {}; }
404void ESP32USBDevice::UpdateSetupState(
const uint8_t* setup)
406 control_.setup_direction_out = (setup !=
nullptr) && ((setup[0] & 0x80U) == 0U);
409void IRAM_ATTR ESP32USBDevice::HandleInterrupt()
413 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
414 for (uint32_t guard = 0; guard < INTERRUPT_DISPATCH_GUARD; ++guard)
416 usb_dwc_gintsts_reg_t pending = {};
417 pending.val = dev->gintsts_reg.val & dev->gintmsk_reg.val;
419 if (pending.val == 0U)
426 dev->gintsts_reg.usbrst = 1;
427 HandleBusReset(
true);
430 if (pending.enumdone)
432 dev->gintsts_reg.enumdone = 1;
433 const uint32_t enum_speed = dev->dsts_reg.enumspd;
434 if (enum_speed != ESPUSBDetail::ENUM_SPEED_FULL_30_TO_60_MHZ &&
435 enum_speed != ESPUSBDetail::ENUM_SPEED_FULL_48_MHZ)
437 REQUIRE_FROM_CALLBACK(
false,
true);
443 dev->gintsts_reg.usbsusp = 1;
448 dev->gintsts_reg.wkupint = 1;
451 if (!DmaEnabled() && pending.rxflvl)
453 dev->gintmsk_reg.rxflvlmsk = 0;
454 while (dev->gintsts_reg.rxflvl)
458 dev->gintmsk_reg.rxflvlmsk = 1;
463 HandleEndpointInterrupt(
true,
false);
468 HandleEndpointInterrupt(
true,
true);
473 const uint32_t otg_status = dev->gotgint_reg.val;
474 dev->gotgint_reg.val = otg_status;
479void ESP32USBDevice::HandleBusReset(
bool in_isr)
484 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
486 for (uint8_t i = 0; i < ENDPOINT_COUNT; ++i)
490 ESPUSBDetail::DisableOutEndpointAndWait(dev->doepctl0_reg);
494 ESPUSBDetail::DisableOutEndpointAndWait(dev->out_eps[i - 1U].doepctl_reg);
498 for (uint8_t i = 0; i < ENDPOINT_COUNT; ++i)
502 if (dev->diepctl0_reg.epena)
504 dev->diepctl0_reg.snak = 1;
505 dev->diepctl0_reg.epdis = 1;
508 else if (dev->in_eps[i - 1U].diepctl_reg.epena)
510 dev->in_eps[i - 1U].diepctl_reg.snak = 1;
511 dev->in_eps[i - 1U].diepctl_reg.epdis = 1;
515 dev->daintmsk_reg.val = 0U;
516 dev->doepmsk_reg.val = 0U;
517 dev->diepmsk_reg.val = 0U;
518 dev->diepempmsk_reg.val = 0U;
519 dev->doepmsk_reg.setupmsk = 1;
520 dev->doepmsk_reg.xfercomplmsk = 1;
521 dev->doepmsk_reg.epdisbldmsk = 1;
522 dev->doepmsk_reg.ahberrmsk = 1;
523 dev->doepmsk_reg.outtknepdismsk = 1;
524 dev->doepmsk_reg.stsphsercvdmsk = 1;
525 dev->doepmsk_reg.outpkterrmsk = 1;
526 dev->doepmsk_reg.bnaoutintrmsk = 1;
527 dev->doepmsk_reg.bbleerrmsk = 1;
528 dev->doepmsk_reg.nakmsk = 1;
529 dev->doepmsk_reg.nyetmsk = 1;
530 dev->diepmsk_reg.xfercomplmsk = 1;
531 dev->diepmsk_reg.timeoutmsk = 1;
535 ResetEndpointHardwareState();
537 dev->dcfg_reg.devaddr = 0U;
545 ReloadSetupPacketCount();
548void ESP32USBDevice::HandleEndpointInterrupt(
bool in_isr,
bool in_dir)
553 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
554 const uint32_t daint = dev->daint_reg.val & dev->daintmsk_reg.val;
555 const uint32_t bits = in_dir ? (daint & 0xFFFFU) : ((daint >> 16U) & 0xFFFFU);
557 for (uint8_t ep_num = 0; ep_num < ENDPOINT_COUNT; ++ep_num)
559 if ((bits & (1UL << ep_num)) == 0U)
564 USB::Endpoint* ep = in_dir ? endpoint_map_.in[ep_num] : endpoint_map_.out[ep_num];
570 auto* esp_ep =
static_cast<ESP32USBEndpoint*
>(ep);
573 esp_ep->HandleInInterrupt(in_isr);
577 esp_ep->HandleOutInterrupt(in_isr);
582void ESP32USBDevice::HandleRxFifoLevel()
587 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
588 usb_dwc_grxstsp_reg_t status = {};
589 status.val = dev->grxstsp_reg.val;
590 const uint8_t ep_num =
static_cast<uint8_t
>(status.chnum);
594 if ((ep_num < ENDPOINT_COUNT) && (endpoint_map_.out[ep_num] !=
nullptr))
596 static_cast<ESP32USBEndpoint*
>(endpoint_map_.out[ep_num])
597 ->ObserveDmaRxStatus(status.pktsts, status.bcnt);
602 switch (status.pktsts)
604 case ESPUSBDetail::RX_STATUS_GLOBAL_OUT_NAK:
607 case ESPUSBDetail::RX_STATUS_SETUP_DATA:
608 ESPUSBDetail::ReadFifoPacket(ESPUSBDetail::GetEndpointFifo(dev, 0), setup_packet_,
609 sizeof(setup_packet_));
610 UpdateSetupState(setup_packet_);
613 case ESPUSBDetail::RX_STATUS_SETUP_DONE:
614 ReloadSetupPacketCount();
617 case ESPUSBDetail::RX_STATUS_DATA:
619 USB::Endpoint* ep = (ep_num < ENDPOINT_COUNT) ? endpoint_map_.out[ep_num] : nullptr;
622 static_cast<ESP32USBEndpoint*
>(ep)->HandleRxData(status.bcnt);
626 uint8_t sink[64] = {};
627 ESPUSBDetail::ReadFifoPacket(ESPUSBDetail::GetEndpointFifo(dev, 0), sink,
633 case ESPUSBDetail::RX_STATUS_TRANSFER_COMPLETE:
639bool ESP32USBDevice::AllocateTxFifo(uint8_t ep_num, uint16_t packet_size,
bool is_bulk,
640 uint16_t& fifo_words)
645 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
646 const uint8_t max_in_ep_num =
647 static_cast<uint8_t
>(
sizeof(dev->dieptxf_regs) /
sizeof(dev->dieptxf_regs[0]));
651 if (ep_num > max_in_ep_num)
656 const uint16_t words = ESPUSBDetail::CalcTxFifoWords(packet_size, DmaEnabled());
657 if (!fifo_state_.tx_bound[ep_num] && (fifo_state_.allocated_in >= IN_ENDPOINT_LIMIT))
662 for (uint8_t index = 0U; index <= ep_num; ++index)
664 const uint16_t requested_words =
665 (index == ep_num) ? words : ESPUSBDetail::ESP32_SX_FS_MIN_TX_FIFO_WORDS;
666 if (fifo_state_.tx_words[index] != 0U)
668 if (fifo_state_.tx_words[index] < requested_words)
675 const uint16_t next_words =
676 static_cast<uint16_t
>(fifo_state_.tx_next_words + requested_words);
677 if (next_words > fifo_state_.depth_words)
682 const uint32_t tx_fifo_reg =
683 ESPUSBDetail::PackTxFifoSizeReg(fifo_state_.tx_next_words, requested_words);
686 dev->gnptxfsiz_reg.val = tx_fifo_reg;
690 dev->dieptxf_regs[index - 1U].val = tx_fifo_reg;
693 fifo_state_.tx_words[index] = requested_words;
694 fifo_state_.tx_next_words = next_words;
697 if (!fifo_state_.tx_bound[ep_num])
699 fifo_state_.tx_bound[ep_num] =
true;
700 fifo_state_.allocated_in++;
706bool ESP32USBDevice::EnsureRxFifo(uint16_t packet_size)
711 auto* dev =
reinterpret_cast<usb_dwc_dev_t*
>(ESPUSBDetail::DWC2_FS_REG_BASE);
712 const uint16_t needed =
713 ESPUSBDetail::CalcConfiguredRxFifoWords(packet_size, ENDPOINT_COUNT, DmaEnabled());
714 if (needed <= fifo_state_.rx_words)
719 if (fifo_state_.tx_next_words != fifo_state_.rx_words)
724 if (needed > fifo_state_.depth_words)
729 fifo_state_.rx_words = needed;
730 fifo_state_.tx_next_words = needed;
731 dev->grxfsiz_reg.rxfdep = fifo_state_.rx_words;
ESP32USBDevice(const std::initializer_list< EPConfig > ep_cfgs, USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid, uint16_t bcd, const std::initializer_list< const USB::DescriptorStrings::LanguagePack * > lang_list, const std::initializer_list< const std::initializer_list< USB::ConfigDescriptorItem * > > configs, ConstRawData uid={nullptr, 0})
构造 ESP32-S3 USB device core / Construct the ESP32-S3 USB device core
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes