libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_usb_devfs.cpp
1// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
2// ch32_usb_devfs.cpp (classic FSDEV / PMA)
3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
5#include "ch32_usbcan_shared.hpp"
6#include "ep.hpp"
7
8using namespace LibXR;
9using namespace LibXR::USB;
10
11#if defined(RCC_APB1Periph_USB)
12
13namespace
14{
15
16static void ch32_usb_clock48m_config()
17{
18 RCC_ClocksTypeDef clk{};
19 RCC_GetClocksFreq(&clk);
20
21 const uint32_t SYSCLK_HZ = clk.SYSCLK_Frequency;
22
23#if defined(RCC_USBCLKSource_PLLCLK_Div1) && defined(RCC_USBCLKSource_PLLCLK_Div2) && \
24 defined(RCC_USBCLKSource_PLLCLK_Div3)
25 if (SYSCLK_HZ == 144000000u)
26 {
27 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3);
28 }
29 else if (SYSCLK_HZ == 96000000u)
30 {
31 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
32 }
33 else if (SYSCLK_HZ == 48000000u)
34 {
35 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);
36 }
37#if defined(RCC_USB5PRE_JUDGE) && defined(RCC_USBCLKSource_PLLCLK_Div5)
38 else if (SYSCLK_HZ == 240000000u)
39 {
40 ASSERT(RCC_USB5PRE_JUDGE() == SET);
41 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div5);
42 }
43#endif
44 else
45 {
46 ASSERT(false);
47 }
48
49#elif defined(RCC_USBCLK48MCLKSource_PLLCLK) && \
50 defined(RCC_USBFSCLKSource_PLLCLK_Div1) && \
51 defined(RCC_USBFSCLKSource_PLLCLK_Div2) && defined(RCC_USBFSCLKSource_PLLCLK_Div3)
52 RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_PLLCLK);
53
54 if (SYSCLK_HZ == 144000000u)
55 {
56 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div3);
57 }
58 else if (SYSCLK_HZ == 96000000u)
59 {
60 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div2);
61 }
62 else if (SYSCLK_HZ == 48000000u)
63 {
64 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div1);
65 }
66 else
67 {
68 ASSERT(false);
69 }
70
71#else
72 (void)SYSCLK_HZ;
73#endif
74}
75
76} // namespace
77
78#ifdef USB_BASE
79static constexpr uintptr_t USBDEV_REG_BASE = USB_BASE;
80#else
81static constexpr uintptr_t USBDEV_REG_BASE = 0x40005C00UL;
82#endif
83
84static inline volatile uint16_t* usbdev_cntr()
85{
86 // MMIO fixed physical base address.
87 // NOLINTNEXTLINE(performance-no-int-to-ptr)
88 return reinterpret_cast<volatile uint16_t*>(USBDEV_REG_BASE + 0x40U);
89}
90static inline volatile uint16_t* usbdev_istr()
91{
92 return reinterpret_cast<volatile uint16_t*>(USBDEV_REG_BASE + 0x44U);
93}
94static inline volatile uint16_t* usbdev_daddr()
95{
96 return reinterpret_cast<volatile uint16_t*>(USBDEV_REG_BASE + 0x4CU);
97}
98static inline volatile uint16_t* usbdev_btable()
99{
100 return reinterpret_cast<volatile uint16_t*>(USBDEV_REG_BASE + 0x50U);
101}
102static inline volatile uint16_t* usbdev_ep_reg(uint8_t ep)
103{
104 return reinterpret_cast<volatile uint16_t*>(USBDEV_REG_BASE +
105 static_cast<uintptr_t>(ep) * 4U);
106}
107
108// Compatibility aliases for classic USBLIB-style macro names.
109#if !defined(USB_ISTR_CTR) && defined(ISTR_CTR)
110#define USB_ISTR_CTR ISTR_CTR
111#endif
112#if !defined(USB_ISTR_RESET) && defined(ISTR_RESET)
113#define USB_ISTR_RESET ISTR_RESET
114#endif
115#if !defined(USB_ISTR_SUSP) && defined(ISTR_SUSP)
116#define USB_ISTR_SUSP ISTR_SUSP
117#endif
118#if !defined(USB_ISTR_WKUP) && defined(ISTR_WKUP)
119#define USB_ISTR_WKUP ISTR_WKUP
120#endif
121#if !defined(USB_ISTR_EP_ID) && defined(ISTR_EP_ID)
122#define USB_ISTR_EP_ID ISTR_EP_ID
123#endif
124
125#if !defined(USB_CNTR_FRES) && defined(CNTR_FRES)
126#define USB_CNTR_FRES CNTR_FRES
127#endif
128#if !defined(USB_CNTR_CTRM) && defined(CNTR_CTRM)
129#define USB_CNTR_CTRM CNTR_CTRM
130#endif
131#if !defined(USB_CNTR_RESETM) && defined(CNTR_RESETM)
132#define USB_CNTR_RESETM CNTR_RESETM
133#endif
134#if !defined(USB_CNTR_SUSPM) && defined(CNTR_SUSPM)
135#define USB_CNTR_SUSPM CNTR_SUSPM
136#endif
137#if !defined(USB_CNTR_WKUPM) && defined(CNTR_WKUPM)
138#define USB_CNTR_WKUPM CNTR_WKUPM
139#endif
140
141#if !defined(USB_DADDR_EF) && defined(DADDR_EF)
142#define USB_DADDR_EF DADDR_EF
143#endif
144
145#if !defined(USB_EP_CTR_TX) && defined(EP_CTR_TX)
146#define USB_EP_CTR_TX EP_CTR_TX
147#endif
148#if !defined(USB_EP_CTR_RX) && defined(EP_CTR_RX)
149#define USB_EP_CTR_RX EP_CTR_RX
150#endif
151#if !defined(USB_EP_SETUP) && defined(EP_SETUP)
152#define USB_EP_SETUP EP_SETUP
153#endif
154#if !defined(USB_EP_KIND) && defined(EP_KIND)
155#define USB_EP_KIND EP_KIND
156#endif
157#if !defined(USB_EP_T_FIELD) && defined(EP_T_FIELD)
158#define USB_EP_T_FIELD EP_T_FIELD
159#endif
160#if !defined(USB_EPADDR_FIELD) && defined(EPADDR_FIELD)
161#define USB_EPADDR_FIELD EPADDR_FIELD
162#endif
163
164#ifndef USB_ISTR_CTR
165#define USB_ISTR_CTR 0x8000u
166#endif
167#ifndef USB_ISTR_RESET
168#define USB_ISTR_RESET 0x0400u
169#endif
170#ifndef USB_ISTR_SUSP
171#define USB_ISTR_SUSP 0x0800u
172#endif
173#ifndef USB_ISTR_WKUP
174#define USB_ISTR_WKUP 0x1000u
175#endif
176#ifndef USB_ISTR_EP_ID
177#define USB_ISTR_EP_ID 0x000Fu
178#endif
179
180#ifndef USB_CNTR_FRES
181#define USB_CNTR_FRES 0x0001u
182#endif
183#ifndef USB_CNTR_CTRM
184#define USB_CNTR_CTRM 0x8000u
185#endif
186#ifndef USB_CNTR_RESETM
187#define USB_CNTR_RESETM 0x0400u
188#endif
189#ifndef USB_CNTR_SUSPM
190#define USB_CNTR_SUSPM 0x0800u
191#endif
192#ifndef USB_CNTR_WKUPM
193#define USB_CNTR_WKUPM 0x1000u
194#endif
195
196#ifndef USB_DADDR_EF
197#define USB_DADDR_EF 0x0080u
198#endif
199
200#ifndef USB_EP_CTR_RX
201#define USB_EP_CTR_RX 0x8000u
202#endif
203#ifndef USB_EP_CTR_TX
204#define USB_EP_CTR_TX 0x0080u
205#endif
206#ifndef USB_EP_SETUP
207#define USB_EP_SETUP 0x0800u
208#endif
209#ifndef USB_EP_KIND
210#define USB_EP_KIND 0x0100u
211#endif
212#ifndef USB_EP_T_FIELD
213#define USB_EP_T_FIELD 0x0600u
214#endif
215#ifndef USB_EPADDR_FIELD
216#define USB_EPADDR_FIELD 0x000Fu
217#endif
218
219#ifndef USB_EP_TX_NAK
220#define USB_EP_TX_NAK 0x0020u
221#endif
222#ifndef USB_EP_RX_DIS
223#define USB_EP_RX_DIS 0x0000u
224#endif
225#ifndef USB_EP_RX_STALL
226#define USB_EP_RX_STALL 0x1000u
227#endif
228#ifndef USB_EP_RX_NAK
229#define USB_EP_RX_NAK 0x2000u
230#endif
231#ifndef USB_EP_RX_VALID
232#define USB_EP_RX_VALID 0x3000u
233#endif
234
235#ifndef USB_EPREG_MASK
236#define USB_EPREG_MASK \
237 (USB_EP_CTR_RX | USB_EP_SETUP | USB_EP_T_FIELD | USB_EP_KIND | USB_EP_CTR_TX | \
238 USB_EPADDR_FIELD)
239#endif
240
241static inline void usbdev_clear_istr(uint16_t mask)
242{
243 *usbdev_istr() = static_cast<uint16_t>(~mask);
244}
245
246static inline void usbdev_set_ep_address(uint8_t ep, uint8_t addr)
247{
248 volatile uint16_t* reg = usbdev_ep_reg(ep);
249 const uint16_t CUR = *reg;
250
251 const uint16_t V = static_cast<uint16_t>(USB_EP_CTR_RX | USB_EP_CTR_TX |
252 (CUR & (USB_EPREG_MASK & ~USB_EPADDR_FIELD)) |
253 (addr & USB_EPADDR_FIELD));
254
255 *reg = V;
256}
257
258static LibXR::RawData select_buffer_dev_fs(USB::Endpoint::EPNumber ep_num,
260 const LibXR::RawData& buffer)
261{
262 if (ep_num == USB::Endpoint::EPNumber::EP0)
263 {
264 return buffer;
265 }
266
267 const size_t HALF = buffer.size_ / 2;
268 if (dir == USB::Endpoint::Direction::OUT)
269 {
270 return LibXR::RawData(buffer.addr_, HALF);
271 }
272 return LibXR::RawData(reinterpret_cast<uint8_t*>(buffer.addr_) + HALF, HALF);
273}
274
275static void usbdev_fs_irqhandler()
276{
277 auto& map = LibXR::CH32EndpointDevFs::map_dev_fs_;
278
279 constexpr uint8_t OUT_IDX = static_cast<uint8_t>(LibXR::USB::Endpoint::Direction::OUT);
280 constexpr uint8_t IN_IDX = static_cast<uint8_t>(LibXR::USB::Endpoint::Direction::IN);
281
282 while (true)
283 {
284 const uint16_t ISTR = *usbdev_istr();
285
286 if (ISTR & USB_ISTR_RESET)
287 {
288 usbdev_clear_istr(USB_ISTR_RESET);
289
290 *usbdev_daddr() = USB_DADDR_EF;
291 *usbdev_btable() = 0;
292
293 LibXR::CH32EndpointDevFs::ResetPMAAllocator();
294
295 LibXR::CH32USBDeviceFS::self_->Deinit(true);
296 LibXR::CH32USBDeviceFS::self_->Init(true);
297
298 if (map[0][OUT_IDX])
299 {
300 map[0][OUT_IDX]->SetState(LibXR::USB::Endpoint::State::IDLE);
301 }
302 if (map[0][IN_IDX])
303 {
304 map[0][IN_IDX]->SetState(LibXR::USB::Endpoint::State::IDLE);
305 }
306
307 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
308 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
309 continue;
310 }
311
312 if (ISTR & USB_ISTR_SUSP)
313 {
314 usbdev_clear_istr(USB_ISTR_SUSP);
315
316 LibXR::CH32USBDeviceFS::self_->Deinit(true);
317 LibXR::CH32USBDeviceFS::self_->Init(true);
318
319 if (map[0][OUT_IDX])
320 {
321 map[0][OUT_IDX]->SetState(LibXR::USB::Endpoint::State::IDLE);
322 }
323 if (map[0][IN_IDX])
324 {
325 map[0][IN_IDX]->SetState(LibXR::USB::Endpoint::State::IDLE);
326 }
327
328 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
329 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_NAK);
330 continue;
331 }
332
333 if (ISTR & USB_ISTR_WKUP)
334 {
335 usbdev_clear_istr(USB_ISTR_WKUP);
336 continue;
337 }
338
339 if ((ISTR & USB_ISTR_CTR) == 0)
340 {
341 break;
342 }
343
344 const uint8_t EP_ID = static_cast<uint8_t>(ISTR & USB_ISTR_EP_ID);
345
346 uint16_t epr = *usbdev_ep_reg(EP_ID);
347
348 if (epr & USB_EP_CTR_RX)
349 {
350 if (EP_ID == 0)
351 {
352 if (epr & USB_EP_SETUP)
353 {
354 // New SETUP starts a fresh control transfer; only clear pending CTR flags here.
355 // EP0 RX/TX status is armed by control-transfer handlers
356 // (OnSetupPacket/Transfer).
357 if (epr & USB_EP_CTR_TX)
358 {
359 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
360 }
361 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
362
363 if (map[0][OUT_IDX])
364 {
365 map[0][OUT_IDX]->CopyRxDataToBuffer(sizeof(LibXR::USB::SetupPacket));
366 LibXR::CH32USBDeviceFS::self_->OnSetupPacket(
367 true, reinterpret_cast<const LibXR::USB::SetupPacket*>(
368 map[0][OUT_IDX]->GetBuffer().addr_));
369 }
370
371 continue;
372 }
373 else
374 {
375 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
376 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(0);
377 if (map[0][OUT_IDX])
378 {
379 map[0][OUT_IDX]->TransferComplete(LEN);
380 }
381 }
382 }
383 else
384 {
385 LibXR::CH32EndpointDevFs::ClearEpCtrRx(EP_ID);
386 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(EP_ID);
387 if (map[EP_ID][OUT_IDX])
388 {
389 map[EP_ID][OUT_IDX]->TransferComplete(LEN);
390 }
391 }
392 }
393
394 epr = *usbdev_ep_reg(EP_ID);
395
396 if (epr & USB_EP_CTR_TX)
397 {
398 if (EP_ID == 0)
399 {
400 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
401 if (map[0][IN_IDX])
402 {
403 map[0][IN_IDX]->TransferComplete(0);
404 }
405 }
406 else
407 {
408 LibXR::CH32EndpointDevFs::ClearEpCtrTx(EP_ID);
409 if (map[EP_ID][IN_IDX])
410 {
411 map[EP_ID][IN_IDX]->TransferComplete(0);
412 }
413 }
414 }
415 }
416}
417
418static void usb_irq_thunk() { usbdev_fs_irqhandler(); }
419
420// NOLINTNEXTLINE(readability-identifier-naming)
421extern "C" __attribute__((interrupt)) void USBWakeUp_IRQHandler(void)
422{
423#if defined(EXTI_Line18)
424 EXTI_ClearITPendingBit(EXTI_Line18);
425#endif
426}
427
428CH32USBDeviceFS::CH32USBDeviceFS(
429 const std::initializer_list<EPConfig> EP_CFGS,
430 USB::DeviceDescriptor::PacketSize0 packet_size, uint16_t vid, uint16_t pid,
431 uint16_t bcd,
432 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
433 const std::initializer_list<const std::initializer_list<USB::ConfigDescriptorItem*>>
434 CONFIGS,
435 ConstRawData uid)
436 : USB::EndpointPool(EP_CFGS.size() * 2),
437 USB::DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::FULL, packet_size, vid,
438 pid, bcd, LANG_LIST, CONFIGS, uid)
439{
440 self_ = this;
441
442 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
443
444 auto cfgs_itr = EP_CFGS.begin();
445
446 auto ep0_out =
447 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
448 cfgs_itr->buffer, false);
449 auto ep0_in =
450 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
451 cfgs_itr->buffer, false);
452
453 USB::EndpointPool::SetEndpoint0(ep0_in, ep0_out);
454
455 USB::Endpoint::EPNumber ep_index = USB::Endpoint::EPNumber::EP1;
456
457 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
458 ++cfgs_itr, ep_index = USB::Endpoint::NextEPNumber(ep_index))
459 {
460 if (cfgs_itr->is_in == -1)
461 {
462 auto ep_out = new CH32EndpointDevFs(
463 ep_index, USB::Endpoint::Direction::OUT,
464 select_buffer_dev_fs(ep_index, USB::Endpoint::Direction::OUT, cfgs_itr->buffer),
465 false);
466 USB::EndpointPool::Put(ep_out);
467
468 auto ep_in = new CH32EndpointDevFs(
469 ep_index, USB::Endpoint::Direction::IN,
470 select_buffer_dev_fs(ep_index, USB::Endpoint::Direction::IN, cfgs_itr->buffer),
471 false);
472 USB::EndpointPool::Put(ep_in);
473 }
474 else
475 {
476 auto ep = new CH32EndpointDevFs(
477 ep_index,
478 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
479 cfgs_itr->buffer, true);
480 USB::EndpointPool::Put(ep);
481 }
482 }
483}
484
485ErrorCode CH32USBDeviceFS::SetAddress(uint8_t address, USB::DeviceCore::Context context)
486{
487 if (context == USB::DeviceCore::Context::STATUS_IN)
488 {
489 const uint8_t N_EP = static_cast<uint8_t>(CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
490 for (uint8_t i = 0; i < N_EP; i++)
491 {
492 usbdev_set_ep_address(i, i);
493 }
494
495 *usbdev_daddr() = static_cast<uint16_t>(USB_DADDR_EF | address);
496
497 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
498 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
499 }
500 return ErrorCode::OK;
501}
502
503void CH32USBDeviceFS::Start(bool)
504{
505 LibXR::CH32UsbCanShared::usb_inited.store(true, std::memory_order_release);
506 LibXR::CH32UsbCanShared::register_usb_irq(&usb_irq_thunk);
507
508 ch32_usb_clock48m_config();
509 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
510
511#if defined(RCC_APB2Periph_GPIOA) && defined(GPIOA) && defined(GPIO_Pin_11) && \
512 defined(GPIO_Pin_12) && defined(GPIO_Mode_Out_PP) && defined(GPIO_Speed_50MHz) && \
513 defined(GPIO_Mode_IN_FLOATING)
514 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
515
516 GPIO_InitTypeDef gpio{};
517 gpio.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
518 gpio.GPIO_Speed = GPIO_Speed_50MHz;
519 gpio.GPIO_Mode = GPIO_Mode_Out_PP;
520 GPIO_Init(GPIOA, &gpio);
521 GPIO_ResetBits(GPIOA, GPIO_Pin_11 | GPIO_Pin_12);
522
523 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
524 GPIO_Init(GPIOA, &gpio);
525#endif
526
527 *usbdev_cntr() = USB_CNTR_FRES;
528 *usbdev_cntr() = 0;
529
530 usbdev_clear_istr(0xFFFFu);
531 *usbdev_btable() = 0;
532
533 *usbdev_cntr() = static_cast<uint16_t>(USB_CNTR_RESETM | USB_CNTR_SUSPM |
534 USB_CNTR_WKUPM | USB_CNTR_CTRM);
535
536#if defined(EXTEN_USBD_LS)
537 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_LS;
538#endif
539
540 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
541 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
542 NVIC_EnableIRQ(USBWakeUp_IRQn);
543
544#if defined(EXTEN_USBD_PU_EN)
545 EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
546#endif
547
548 *usbdev_daddr() = USB_DADDR_EF;
549
550 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
551 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
552
553 // DeviceCore::Init() may arm OUT endpoints before FSDEV reset/BTABLE initialization.
554 // Re-arm non-EP0 OUT endpoints that remain BUSY after hardware initialization.
555 auto& ep_map = LibXR::CH32EndpointDevFs::map_dev_fs_;
556 constexpr uint8_t OUT_IDX = static_cast<uint8_t>(LibXR::USB::Endpoint::Direction::OUT);
557 const uint8_t N_EP = static_cast<uint8_t>(LibXR::CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
558 for (uint8_t ep = 1; ep < N_EP; ++ep)
559 {
560 auto* out = ep_map[ep][OUT_IDX];
561 if (out == nullptr)
562 {
563 continue;
564 }
565 if (out->GetState() != LibXR::USB::Endpoint::State::BUSY)
566 {
567 continue;
568 }
569 (void)out->Transfer(out->MaxTransferSize());
570 }
571}
572
573void CH32USBDeviceFS::Stop(bool)
574{
575 LibXR::CH32UsbCanShared::register_usb_irq(nullptr);
576 LibXR::CH32UsbCanShared::usb_inited.store(false, std::memory_order_release);
577
578#if defined(EXTEN_USBD_PU_EN)
579 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
580#endif
581
582 if (!LibXR::CH32UsbCanShared::can1_active())
583 {
584 NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
585 NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
586 }
587 NVIC_DisableIRQ(USBWakeUp_IRQn);
588
589 *usbdev_cntr() = USB_CNTR_FRES;
590}
591
592#endif // defined(RCC_APB1Periph_USB)
593
594// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
常量原始数据封装类。 A class for encapsulating constant raw data.
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
USB 设备协议栈核心:EP0 控制传输、描述符、配置、标准/类/厂商请求 USB device core: EP0 control transfer, descriptors,...
Definition dev_core.hpp:179
Context
控制传输上下文 / Control transfer context
Definition dev_core.hpp:188
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
Definition desc_dev.hpp:75
EPNumber
端点号 Endpoint number
Definition ep.hpp:41
Direction
端点方向 Endpoint direction
Definition ep.hpp:30
@ IN
输入方向 / IN direction
@ OUT
输出方向 / OUT direction
static constexpr EPNumber NextEPNumber(EPNumber ep)
获取下一个端点号 / Get the next endpoint number
Definition ep.hpp:127
USB端点池类 / USB endpoint pool class.
Definition ep_pool.hpp:23
void SetEndpoint0(Endpoint *ep0_in, Endpoint *ep0_out)
设置端点0的IN/OUT对象 / Set Endpoint 0 IN/OUT objects
Definition ep_pool.cpp:96
LibXR 命名空间
Definition ch32_can.hpp:14
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)
Definition core.hpp:57