3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
5#include "ch32_usb_rcc.hpp"
6#include "ch32_usbcan_shared.hpp"
10using namespace LibXR::USB;
12#if defined(RCC_APB1Periph_USB)
15static constexpr uintptr_t USBDEV_REG_BASE = USB_BASE;
17static constexpr uintptr_t USBDEV_REG_BASE = 0x40005C00UL;
20static inline volatile uint16_t* usbdev_cntr()
25 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x40U);
27static inline volatile uint16_t* usbdev_istr()
29 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x44U);
31static inline volatile uint16_t* usbdev_daddr()
33 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x4CU);
35static inline volatile uint16_t* usbdev_btable()
37 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x50U);
39static inline volatile uint16_t* usbdev_ep_reg(uint8_t ep)
41 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE +
42 static_cast<uintptr_t
>(ep) * 4U);
47#if !defined(USB_ISTR_CTR) && defined(ISTR_CTR)
48#define USB_ISTR_CTR ISTR_CTR
50#if !defined(USB_ISTR_RESET) && defined(ISTR_RESET)
51#define USB_ISTR_RESET ISTR_RESET
53#if !defined(USB_ISTR_SUSP) && defined(ISTR_SUSP)
54#define USB_ISTR_SUSP ISTR_SUSP
56#if !defined(USB_ISTR_WKUP) && defined(ISTR_WKUP)
57#define USB_ISTR_WKUP ISTR_WKUP
59#if !defined(USB_ISTR_EP_ID) && defined(ISTR_EP_ID)
60#define USB_ISTR_EP_ID ISTR_EP_ID
63#if !defined(USB_CNTR_FRES) && defined(CNTR_FRES)
64#define USB_CNTR_FRES CNTR_FRES
66#if !defined(USB_CNTR_CTRM) && defined(CNTR_CTRM)
67#define USB_CNTR_CTRM CNTR_CTRM
69#if !defined(USB_CNTR_RESETM) && defined(CNTR_RESETM)
70#define USB_CNTR_RESETM CNTR_RESETM
72#if !defined(USB_CNTR_SUSPM) && defined(CNTR_SUSPM)
73#define USB_CNTR_SUSPM CNTR_SUSPM
75#if !defined(USB_CNTR_WKUPM) && defined(CNTR_WKUPM)
76#define USB_CNTR_WKUPM CNTR_WKUPM
79#if !defined(USB_DADDR_EF) && defined(DADDR_EF)
80#define USB_DADDR_EF DADDR_EF
83#if !defined(USB_EP_CTR_TX) && defined(EP_CTR_TX)
84#define USB_EP_CTR_TX EP_CTR_TX
86#if !defined(USB_EP_CTR_RX) && defined(EP_CTR_RX)
87#define USB_EP_CTR_RX EP_CTR_RX
89#if !defined(USB_EP_SETUP) && defined(EP_SETUP)
90#define USB_EP_SETUP EP_SETUP
92#if !defined(USB_EP_KIND) && defined(EP_KIND)
93#define USB_EP_KIND EP_KIND
95#if !defined(USB_EP_T_FIELD) && defined(EP_T_FIELD)
96#define USB_EP_T_FIELD EP_T_FIELD
98#if !defined(USB_EPADDR_FIELD) && defined(EPADDR_FIELD)
99#define USB_EPADDR_FIELD EPADDR_FIELD
103#define USB_ISTR_CTR 0x8000u
105#ifndef USB_ISTR_RESET
106#define USB_ISTR_RESET 0x0400u
109#define USB_ISTR_SUSP 0x0800u
112#define USB_ISTR_WKUP 0x1000u
114#ifndef USB_ISTR_EP_ID
115#define USB_ISTR_EP_ID 0x000Fu
119#define USB_CNTR_FRES 0x0001u
122#define USB_CNTR_CTRM 0x8000u
124#ifndef USB_CNTR_RESETM
125#define USB_CNTR_RESETM 0x0400u
127#ifndef USB_CNTR_SUSPM
128#define USB_CNTR_SUSPM 0x0800u
130#ifndef USB_CNTR_WKUPM
131#define USB_CNTR_WKUPM 0x1000u
135#define USB_DADDR_EF 0x0080u
139#define USB_EP_CTR_RX 0x8000u
142#define USB_EP_CTR_TX 0x0080u
145#define USB_EP_SETUP 0x0800u
148#define USB_EP_KIND 0x0100u
150#ifndef USB_EP_T_FIELD
151#define USB_EP_T_FIELD 0x0600u
153#ifndef USB_EPADDR_FIELD
154#define USB_EPADDR_FIELD 0x000Fu
158#define USB_EP_TX_NAK 0x0020u
161#define USB_EP_RX_DIS 0x0000u
163#ifndef USB_EP_RX_STALL
164#define USB_EP_RX_STALL 0x1000u
167#define USB_EP_RX_NAK 0x2000u
169#ifndef USB_EP_RX_VALID
170#define USB_EP_RX_VALID 0x3000u
173#ifndef USB_EPREG_MASK
174#define USB_EPREG_MASK \
175 (USB_EP_CTR_RX | USB_EP_SETUP | USB_EP_T_FIELD | USB_EP_KIND | USB_EP_CTR_TX | \
179static inline void usbdev_clear_istr(uint16_t mask)
181 *usbdev_istr() =
static_cast<uint16_t
>(~mask);
184static inline void usbdev_set_ep_address(uint8_t ep, uint8_t addr)
186 volatile uint16_t* reg = usbdev_ep_reg(ep);
187 const uint16_t CUR = *reg;
189 const uint16_t V =
static_cast<uint16_t
>(USB_EP_CTR_RX | USB_EP_CTR_TX |
190 (CUR & (USB_EPREG_MASK & ~USB_EPADDR_FIELD)) |
191 (addr & USB_EPADDR_FIELD));
200 if (ep_num == USB::Endpoint::EPNumber::EP0)
205 const size_t HALF = buffer.
size_ / 2;
206 if (dir == USB::Endpoint::Direction::OUT)
213static void drain_usbdev_fs_pending_irqs()
217 const uint16_t ISTR = *usbdev_istr();
219 if (ISTR & USB_ISTR_RESET)
221 usbdev_clear_istr(USB_ISTR_RESET);
225 if (ISTR & USB_ISTR_SUSP)
227 usbdev_clear_istr(USB_ISTR_SUSP);
231 if (ISTR & USB_ISTR_WKUP)
233 usbdev_clear_istr(USB_ISTR_WKUP);
237 if ((ISTR & USB_ISTR_CTR) == 0)
242 const uint8_t EP_ID =
static_cast<uint8_t
>(ISTR & USB_ISTR_EP_ID);
244 uint16_t epr = *usbdev_ep_reg(EP_ID);
245 if (epr & USB_EP_CTR_RX)
247 LibXR::CH32EndpointDevFs::ClearEpCtrRx(EP_ID);
250 epr = *usbdev_ep_reg(EP_ID);
251 if (epr & USB_EP_CTR_TX)
253 LibXR::CH32EndpointDevFs::ClearEpCtrTx(EP_ID);
264static void usbdev_fs_irqhandler()
266 auto* usb = LibXR::CH32USBDeviceFS::self_;
267 if (usb ==
nullptr || !usb->IsInited())
269 drain_usbdev_fs_pending_irqs();
273 auto& map = LibXR::CH32EndpointDevFs::map_dev_fs_;
277 auto* out0 = map[0][OUT_IDX];
278 auto* in0 = map[0][IN_IDX];
279 ASSERT(out0 !=
nullptr);
280 ASSERT(in0 !=
nullptr);
284 const uint16_t ISTR = *usbdev_istr();
290 if (ISTR & USB_ISTR_RESET)
292 usbdev_clear_istr(USB_ISTR_RESET);
294 *usbdev_daddr() = USB_DADDR_EF;
295 *usbdev_btable() = 0;
297 LibXR::CH32EndpointDevFs::ResetPMAAllocator();
305 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
306 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
314 if (ISTR & USB_ISTR_SUSP)
316 usbdev_clear_istr(USB_ISTR_SUSP);
324 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
325 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_NAK);
329 if (ISTR & USB_ISTR_WKUP)
331 usbdev_clear_istr(USB_ISTR_WKUP);
335 if ((ISTR & USB_ISTR_CTR) == 0)
342 const uint8_t EP_ID =
static_cast<uint8_t
>(ISTR & USB_ISTR_EP_ID);
344 uint16_t epr = *usbdev_ep_reg(EP_ID);
346 if (epr & USB_EP_CTR_RX)
350 if (epr & USB_EP_SETUP)
356 if (epr & USB_EP_CTR_TX)
358 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
360 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
364 out0->GetBuffer().addr_));
372 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
373 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(0);
374 out0->TransferComplete(LEN);
381 LibXR::CH32EndpointDevFs::ClearEpCtrRx(EP_ID);
382 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(EP_ID);
383 if (map[EP_ID][OUT_IDX])
385 map[EP_ID][OUT_IDX]->TransferComplete(LEN);
390 epr = *usbdev_ep_reg(EP_ID);
392 if (epr & USB_EP_CTR_TX)
398 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
399 in0->TransferComplete(0);
405 LibXR::CH32EndpointDevFs::ClearEpCtrTx(EP_ID);
406 if (map[EP_ID][IN_IDX])
408 map[EP_ID][IN_IDX]->TransferComplete(0);
415static void usb_irq_thunk() { usbdev_fs_irqhandler(); }
418extern "C" __attribute__((interrupt(
"WCH-Interrupt-fast"))) void USBWakeUp_IRQHandler(
421#if defined(EXTI_Line18)
422 EXTI_ClearITPendingBit(EXTI_Line18);
426CH32USBDeviceFS::CH32USBDeviceFS(
427 const std::initializer_list<EPConfig> EP_CFGS,
430 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
431 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
435 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::
FULL, packet_size, vid,
436 pid, bcd, LANG_LIST, CONFIGS, uid)
438 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
440 auto cfgs_itr = EP_CFGS.begin();
443 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
444 cfgs_itr->buffer,
false);
446 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
447 cfgs_itr->buffer,
false);
453 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
456 if (cfgs_itr->is_in == -1)
458 auto ep_out =
new CH32EndpointDevFs(
459 ep_index, USB::Endpoint::Direction::OUT,
460 select_buffer_dev_fs(ep_index, USB::Endpoint::Direction::OUT, cfgs_itr->buffer),
462 USB::EndpointPool::Put(ep_out);
464 auto ep_in =
new CH32EndpointDevFs(
465 ep_index, USB::Endpoint::Direction::IN,
466 select_buffer_dev_fs(ep_index, USB::Endpoint::Direction::IN, cfgs_itr->buffer),
468 USB::EndpointPool::Put(ep_in);
472 auto ep =
new CH32EndpointDevFs(
474 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
475 cfgs_itr->buffer,
true);
476 USB::EndpointPool::Put(ep);
484 if (context == USB::DeviceCore::Context::STATUS_IN_COMPLETE)
486 const uint8_t N_EP =
static_cast<uint8_t
>(CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
487 for (uint8_t i = 0; i < N_EP; i++)
489 usbdev_set_ep_address(i, i);
492 *usbdev_daddr() =
static_cast<uint16_t
>(USB_DADDR_EF | address);
494 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
495 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
500void CH32USBDeviceFS::Start(
bool)
506 LibXR::CH32UsbRcc::ConfigureUsb48M();
507#if defined(RCC_USBCLK48MCLKSource_USBPHY) && defined(RCC_AHBPeriph_USBHS)
508 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
510 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
512#if defined(RCC_APB2Periph_GPIOA) && defined(GPIOA) && defined(GPIO_Pin_11) && \
513 defined(GPIO_Pin_12) && defined(GPIO_Mode_Out_PP) && defined(GPIO_Speed_50MHz) && \
514 defined(GPIO_Mode_IN_FLOATING)
515 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
517 GPIO_InitTypeDef gpio{};
518 gpio.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
519 gpio.GPIO_Speed = GPIO_Speed_50MHz;
520 gpio.GPIO_Mode = GPIO_Mode_Out_PP;
521 GPIO_Init(GPIOA, &gpio);
522 GPIO_ResetBits(GPIOA, GPIO_Pin_11 | GPIO_Pin_12);
524 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
525 GPIO_Init(GPIOA, &gpio);
528 *usbdev_cntr() = USB_CNTR_FRES;
531 usbdev_clear_istr(0xFFFFu);
532 *usbdev_btable() = 0;
534 *usbdev_cntr() =
static_cast<uint16_t
>(USB_CNTR_RESETM | USB_CNTR_SUSPM |
535 USB_CNTR_WKUPM | USB_CNTR_CTRM);
537#if defined(EXTEN_USBD_LS)
538 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_LS;
541 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
542 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
543 NVIC_EnableIRQ(USBWakeUp_IRQn);
545#if defined(EXTEN_USBD_PU_EN)
546 EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
549 *usbdev_daddr() = USB_DADDR_EF;
551 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
552 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
558 auto& ep_map = LibXR::CH32EndpointDevFs::map_dev_fs_;
560 const uint8_t N_EP =
static_cast<uint8_t
>(LibXR::CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
561 for (uint8_t ep = 1; ep < N_EP; ++ep)
563 auto* out = ep_map[ep][OUT_IDX];
572 (void)out->Transfer(out->MaxTransferSize());
576 LibXR::CH32UsbCanShared::usb_inited.store(
true, std::memory_order_release);
577 LibXR::CH32UsbCanShared::register_usb_irq(&usb_irq_thunk);
580void CH32USBDeviceFS::Stop(
bool)
582 LibXR::CH32UsbCanShared::register_usb_irq(
nullptr);
583 LibXR::CH32UsbCanShared::usb_inited.store(
false, std::memory_order_release);
586#if defined(EXTEN_USBD_PU_EN)
587 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
590 if (!LibXR::CH32UsbCanShared::can1_active())
592 NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
593 NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
595 NVIC_DisableIRQ(USBWakeUp_IRQn);
597 *usbdev_cntr() = USB_CNTR_FRES;
只读原始数据视图 / Immutable raw data view
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
USB 设备协议栈核心:EP0 控制传输、描述符、配置、标准/类/厂商请求 USB device core: EP0 control transfer, descriptors,...
Context
控制传输上下文 / Control transfer context
PacketSize0
控制端点0最大包长度枚举 Packet size for endpoint 0 (bMaxPacketSize0)
EPNumber
端点号 Endpoint number
Direction
端点方向 Endpoint direction
@ OUT
输出方向 / OUT direction
static constexpr EPNumber NextEPNumber(EPNumber ep)
获取下一个端点号 / Get the next endpoint number
USB端点池类 / USB endpoint pool class.
void SetEndpoint0(Endpoint *ep0_in, Endpoint *ep0_out)
设置端点0的IN/OUT对象 / Set Endpoint 0 IN/OUT objects
@ OK
操作成功 | Operation successful
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)