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 usbdev_fs_irqhandler()
215 auto& map = LibXR::CH32EndpointDevFs::map_dev_fs_;
219 auto* out0 = map[0][OUT_IDX];
220 auto* in0 = map[0][IN_IDX];
221 ASSERT(out0 !=
nullptr);
222 ASSERT(in0 !=
nullptr);
226 const uint16_t ISTR = *usbdev_istr();
232 if (ISTR & USB_ISTR_RESET)
234 usbdev_clear_istr(USB_ISTR_RESET);
236 *usbdev_daddr() = USB_DADDR_EF;
237 *usbdev_btable() = 0;
239 LibXR::CH32EndpointDevFs::ResetPMAAllocator();
241 LibXR::CH32USBDeviceFS::self_->Deinit(
true);
242 LibXR::CH32USBDeviceFS::self_->Init(
true);
247 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
248 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
256 if (ISTR & USB_ISTR_SUSP)
258 usbdev_clear_istr(USB_ISTR_SUSP);
260 LibXR::CH32USBDeviceFS::self_->Deinit(
true);
261 LibXR::CH32USBDeviceFS::self_->Init(
true);
266 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
267 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_NAK);
271 if (ISTR & USB_ISTR_WKUP)
273 usbdev_clear_istr(USB_ISTR_WKUP);
277 if ((ISTR & USB_ISTR_CTR) == 0)
284 const uint8_t EP_ID =
static_cast<uint8_t
>(ISTR & USB_ISTR_EP_ID);
286 uint16_t epr = *usbdev_ep_reg(EP_ID);
288 if (epr & USB_EP_CTR_RX)
292 if (epr & USB_EP_SETUP)
298 if (epr & USB_EP_CTR_TX)
300 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
302 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
305 LibXR::CH32USBDeviceFS::self_->OnSetupPacket(
315 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
316 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(0);
317 out0->TransferComplete(LEN);
324 LibXR::CH32EndpointDevFs::ClearEpCtrRx(EP_ID);
325 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(EP_ID);
326 if (map[EP_ID][OUT_IDX])
328 map[EP_ID][OUT_IDX]->TransferComplete(LEN);
333 epr = *usbdev_ep_reg(EP_ID);
335 if (epr & USB_EP_CTR_TX)
341 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
342 in0->TransferComplete(0);
348 LibXR::CH32EndpointDevFs::ClearEpCtrTx(EP_ID);
349 if (map[EP_ID][IN_IDX])
351 map[EP_ID][IN_IDX]->TransferComplete(0);
358static void usb_irq_thunk() { usbdev_fs_irqhandler(); }
361extern "C" __attribute__((interrupt(
"WCH-Interrupt-fast"))) void USBWakeUp_IRQHandler(
364#if defined(EXTI_Line18)
365 EXTI_ClearITPendingBit(EXTI_Line18);
369CH32USBDeviceFS::CH32USBDeviceFS(
370 const std::initializer_list<EPConfig> EP_CFGS,
373 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
374 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
378 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::
FULL, packet_size, vid,
379 pid, bcd, LANG_LIST, CONFIGS, uid)
383 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
385 auto cfgs_itr = EP_CFGS.begin();
388 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
389 cfgs_itr->buffer,
false);
391 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
392 cfgs_itr->buffer,
false);
398 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
401 if (cfgs_itr->is_in == -1)
403 auto ep_out =
new CH32EndpointDevFs(
404 ep_index, USB::Endpoint::Direction::OUT,
405 select_buffer_dev_fs(ep_index, USB::Endpoint::Direction::OUT, cfgs_itr->buffer),
407 USB::EndpointPool::Put(ep_out);
409 auto ep_in =
new CH32EndpointDevFs(
410 ep_index, USB::Endpoint::Direction::IN,
411 select_buffer_dev_fs(ep_index, USB::Endpoint::Direction::IN, cfgs_itr->buffer),
413 USB::EndpointPool::Put(ep_in);
417 auto ep =
new CH32EndpointDevFs(
419 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
420 cfgs_itr->buffer,
true);
421 USB::EndpointPool::Put(ep);
429 if (context == USB::DeviceCore::Context::STATUS_IN_COMPLETE)
431 const uint8_t N_EP =
static_cast<uint8_t
>(CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
432 for (uint8_t i = 0; i < N_EP; i++)
434 usbdev_set_ep_address(i, i);
437 *usbdev_daddr() =
static_cast<uint16_t
>(USB_DADDR_EF | address);
439 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
440 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
445void CH32USBDeviceFS::Start(
bool)
447 LibXR::CH32UsbCanShared::usb_inited.store(
true, std::memory_order_release);
448 LibXR::CH32UsbCanShared::register_usb_irq(&usb_irq_thunk);
454 LibXR::CH32UsbRcc::ConfigureUsb48M();
455#if defined(RCC_USBCLK48MCLKSource_USBPHY) && defined(RCC_AHBPeriph_USBHS)
456 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
458 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
460#if defined(RCC_APB2Periph_GPIOA) && defined(GPIOA) && defined(GPIO_Pin_11) && \
461 defined(GPIO_Pin_12) && defined(GPIO_Mode_Out_PP) && defined(GPIO_Speed_50MHz) && \
462 defined(GPIO_Mode_IN_FLOATING)
463 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
465 GPIO_InitTypeDef gpio{};
466 gpio.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12;
467 gpio.GPIO_Speed = GPIO_Speed_50MHz;
468 gpio.GPIO_Mode = GPIO_Mode_Out_PP;
469 GPIO_Init(GPIOA, &gpio);
470 GPIO_ResetBits(GPIOA, GPIO_Pin_11 | GPIO_Pin_12);
472 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
473 GPIO_Init(GPIOA, &gpio);
476 *usbdev_cntr() = USB_CNTR_FRES;
479 usbdev_clear_istr(0xFFFFu);
480 *usbdev_btable() = 0;
482 *usbdev_cntr() =
static_cast<uint16_t
>(USB_CNTR_RESETM | USB_CNTR_SUSPM |
483 USB_CNTR_WKUPM | USB_CNTR_CTRM);
485#if defined(EXTEN_USBD_LS)
486 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_LS;
489 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
490 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
491 NVIC_EnableIRQ(USBWakeUp_IRQn);
493#if defined(EXTEN_USBD_PU_EN)
494 EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
497 *usbdev_daddr() = USB_DADDR_EF;
499 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
500 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
506 auto& ep_map = LibXR::CH32EndpointDevFs::map_dev_fs_;
508 const uint8_t N_EP =
static_cast<uint8_t
>(LibXR::CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
509 for (uint8_t ep = 1; ep < N_EP; ++ep)
511 auto* out = ep_map[ep][OUT_IDX];
520 (void)out->Transfer(out->MaxTransferSize());
524void CH32USBDeviceFS::Stop(
bool)
526 LibXR::CH32UsbCanShared::register_usb_irq(
nullptr);
527 LibXR::CH32UsbCanShared::usb_inited.store(
false, std::memory_order_release);
529#if defined(EXTEN_USBD_PU_EN)
530 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
533 if (!LibXR::CH32UsbCanShared::can1_active())
535 NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
536 NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
538 NVIC_DisableIRQ(USBWakeUp_IRQn);
540 *usbdev_cntr() = USB_CNTR_FRES;
常量原始数据封装类。 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,...
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)