3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
5#include "ch32_usbcan_shared.hpp"
9using namespace LibXR::USB;
11#if defined(RCC_APB1Periph_USB)
16static void ch32_usb_clock48m_config()
18 RCC_ClocksTypeDef clk{};
19 RCC_GetClocksFreq(&clk);
21 const uint32_t SYSCLK_HZ = clk.SYSCLK_Frequency;
23#if defined(RCC_USBCLKSource_PLLCLK_Div1) && defined(RCC_USBCLKSource_PLLCLK_Div2) && \
24 defined(RCC_USBCLKSource_PLLCLK_Div3)
25 if (SYSCLK_HZ == 144000000u)
27 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3);
29 else if (SYSCLK_HZ == 96000000u)
31 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
33 else if (SYSCLK_HZ == 48000000u)
35 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);
37#if defined(RCC_USB5PRE_JUDGE) && defined(RCC_USBCLKSource_PLLCLK_Div5)
38 else if (SYSCLK_HZ == 240000000u)
40 ASSERT(RCC_USB5PRE_JUDGE() == SET);
41 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div5);
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);
54 if (SYSCLK_HZ == 144000000u)
56 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div3);
58 else if (SYSCLK_HZ == 96000000u)
60 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div2);
62 else if (SYSCLK_HZ == 48000000u)
64 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div1);
79static constexpr uintptr_t USBDEV_REG_BASE = USB_BASE;
81static constexpr uintptr_t USBDEV_REG_BASE = 0x40005C00UL;
84static inline volatile uint16_t* usbdev_cntr()
88 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x40U);
90static inline volatile uint16_t* usbdev_istr()
92 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x44U);
94static inline volatile uint16_t* usbdev_daddr()
96 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x4CU);
98static inline volatile uint16_t* usbdev_btable()
100 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE + 0x50U);
102static inline volatile uint16_t* usbdev_ep_reg(uint8_t ep)
104 return reinterpret_cast<volatile uint16_t*
>(USBDEV_REG_BASE +
105 static_cast<uintptr_t
>(ep) * 4U);
109#if !defined(USB_ISTR_CTR) && defined(ISTR_CTR)
110#define USB_ISTR_CTR ISTR_CTR
112#if !defined(USB_ISTR_RESET) && defined(ISTR_RESET)
113#define USB_ISTR_RESET ISTR_RESET
115#if !defined(USB_ISTR_SUSP) && defined(ISTR_SUSP)
116#define USB_ISTR_SUSP ISTR_SUSP
118#if !defined(USB_ISTR_WKUP) && defined(ISTR_WKUP)
119#define USB_ISTR_WKUP ISTR_WKUP
121#if !defined(USB_ISTR_EP_ID) && defined(ISTR_EP_ID)
122#define USB_ISTR_EP_ID ISTR_EP_ID
125#if !defined(USB_CNTR_FRES) && defined(CNTR_FRES)
126#define USB_CNTR_FRES CNTR_FRES
128#if !defined(USB_CNTR_CTRM) && defined(CNTR_CTRM)
129#define USB_CNTR_CTRM CNTR_CTRM
131#if !defined(USB_CNTR_RESETM) && defined(CNTR_RESETM)
132#define USB_CNTR_RESETM CNTR_RESETM
134#if !defined(USB_CNTR_SUSPM) && defined(CNTR_SUSPM)
135#define USB_CNTR_SUSPM CNTR_SUSPM
137#if !defined(USB_CNTR_WKUPM) && defined(CNTR_WKUPM)
138#define USB_CNTR_WKUPM CNTR_WKUPM
141#if !defined(USB_DADDR_EF) && defined(DADDR_EF)
142#define USB_DADDR_EF DADDR_EF
145#if !defined(USB_EP_CTR_TX) && defined(EP_CTR_TX)
146#define USB_EP_CTR_TX EP_CTR_TX
148#if !defined(USB_EP_CTR_RX) && defined(EP_CTR_RX)
149#define USB_EP_CTR_RX EP_CTR_RX
151#if !defined(USB_EP_SETUP) && defined(EP_SETUP)
152#define USB_EP_SETUP EP_SETUP
154#if !defined(USB_EP_KIND) && defined(EP_KIND)
155#define USB_EP_KIND EP_KIND
157#if !defined(USB_EP_T_FIELD) && defined(EP_T_FIELD)
158#define USB_EP_T_FIELD EP_T_FIELD
160#if !defined(USB_EPADDR_FIELD) && defined(EPADDR_FIELD)
161#define USB_EPADDR_FIELD EPADDR_FIELD
165#define USB_ISTR_CTR 0x8000u
167#ifndef USB_ISTR_RESET
168#define USB_ISTR_RESET 0x0400u
171#define USB_ISTR_SUSP 0x0800u
174#define USB_ISTR_WKUP 0x1000u
176#ifndef USB_ISTR_EP_ID
177#define USB_ISTR_EP_ID 0x000Fu
181#define USB_CNTR_FRES 0x0001u
184#define USB_CNTR_CTRM 0x8000u
186#ifndef USB_CNTR_RESETM
187#define USB_CNTR_RESETM 0x0400u
189#ifndef USB_CNTR_SUSPM
190#define USB_CNTR_SUSPM 0x0800u
192#ifndef USB_CNTR_WKUPM
193#define USB_CNTR_WKUPM 0x1000u
197#define USB_DADDR_EF 0x0080u
201#define USB_EP_CTR_RX 0x8000u
204#define USB_EP_CTR_TX 0x0080u
207#define USB_EP_SETUP 0x0800u
210#define USB_EP_KIND 0x0100u
212#ifndef USB_EP_T_FIELD
213#define USB_EP_T_FIELD 0x0600u
215#ifndef USB_EPADDR_FIELD
216#define USB_EPADDR_FIELD 0x000Fu
220#define USB_EP_TX_NAK 0x0020u
223#define USB_EP_RX_DIS 0x0000u
225#ifndef USB_EP_RX_STALL
226#define USB_EP_RX_STALL 0x1000u
229#define USB_EP_RX_NAK 0x2000u
231#ifndef USB_EP_RX_VALID
232#define USB_EP_RX_VALID 0x3000u
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 | \
241static inline void usbdev_clear_istr(uint16_t mask)
243 *usbdev_istr() =
static_cast<uint16_t
>(~mask);
246static inline void usbdev_set_ep_address(uint8_t ep, uint8_t addr)
248 volatile uint16_t* reg = usbdev_ep_reg(ep);
249 const uint16_t CUR = *reg;
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));
262 if (ep_num == USB::Endpoint::EPNumber::EP0)
267 const size_t HALF = buffer.
size_ / 2;
268 if (dir == USB::Endpoint::Direction::OUT)
275static void usbdev_fs_irqhandler()
277 auto& map = LibXR::CH32EndpointDevFs::map_dev_fs_;
284 const uint16_t ISTR = *usbdev_istr();
286 if (ISTR & USB_ISTR_RESET)
288 usbdev_clear_istr(USB_ISTR_RESET);
290 *usbdev_daddr() = USB_DADDR_EF;
291 *usbdev_btable() = 0;
293 LibXR::CH32EndpointDevFs::ResetPMAAllocator();
295 LibXR::CH32USBDeviceFS::self_->Deinit(
true);
296 LibXR::CH32USBDeviceFS::self_->Init(
true);
307 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
308 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
312 if (ISTR & USB_ISTR_SUSP)
314 usbdev_clear_istr(USB_ISTR_SUSP);
316 LibXR::CH32USBDeviceFS::self_->Deinit(
true);
317 LibXR::CH32USBDeviceFS::self_->Init(
true);
328 LibXR::CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
329 LibXR::CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_NAK);
333 if (ISTR & USB_ISTR_WKUP)
335 usbdev_clear_istr(USB_ISTR_WKUP);
339 if ((ISTR & USB_ISTR_CTR) == 0)
344 const uint8_t EP_ID =
static_cast<uint8_t
>(ISTR & USB_ISTR_EP_ID);
346 uint16_t epr = *usbdev_ep_reg(EP_ID);
348 if (epr & USB_EP_CTR_RX)
352 if (epr & USB_EP_SETUP)
357 if (epr & USB_EP_CTR_TX)
359 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
361 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
366 LibXR::CH32USBDeviceFS::self_->OnSetupPacket(
368 map[0][OUT_IDX]->GetBuffer().addr_));
375 LibXR::CH32EndpointDevFs::ClearEpCtrRx(0);
376 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(0);
379 map[0][OUT_IDX]->TransferComplete(LEN);
385 LibXR::CH32EndpointDevFs::ClearEpCtrRx(EP_ID);
386 const uint16_t LEN = LibXR::CH32EndpointDevFs::GetRxCount(EP_ID);
387 if (map[EP_ID][OUT_IDX])
389 map[EP_ID][OUT_IDX]->TransferComplete(LEN);
394 epr = *usbdev_ep_reg(EP_ID);
396 if (epr & USB_EP_CTR_TX)
400 LibXR::CH32EndpointDevFs::ClearEpCtrTx(0);
403 map[0][IN_IDX]->TransferComplete(0);
408 LibXR::CH32EndpointDevFs::ClearEpCtrTx(EP_ID);
409 if (map[EP_ID][IN_IDX])
411 map[EP_ID][IN_IDX]->TransferComplete(0);
418static void usb_irq_thunk() { usbdev_fs_irqhandler(); }
421extern "C" __attribute__((interrupt))
void USBWakeUp_IRQHandler(
void)
423#if defined(EXTI_Line18)
424 EXTI_ClearITPendingBit(EXTI_Line18);
428CH32USBDeviceFS::CH32USBDeviceFS(
429 const std::initializer_list<EPConfig> EP_CFGS,
432 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
433 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
437 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::FULL, packet_size, vid,
438 pid, bcd, LANG_LIST, CONFIGS, uid)
442 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointDevFs::EP_DEV_FS_MAX_SIZE);
444 auto cfgs_itr = EP_CFGS.begin();
447 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
448 cfgs_itr->buffer,
false);
450 new CH32EndpointDevFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
451 cfgs_itr->buffer,
false);
457 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
460 if (cfgs_itr->is_in == -1)
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),
466 USB::EndpointPool::Put(ep_out);
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),
472 USB::EndpointPool::Put(ep_in);
476 auto ep =
new CH32EndpointDevFs(
478 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
479 cfgs_itr->buffer,
true);
480 USB::EndpointPool::Put(ep);
487 if (context == USB::DeviceCore::Context::STATUS_IN)
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++)
492 usbdev_set_ep_address(i, i);
495 *usbdev_daddr() =
static_cast<uint16_t
>(USB_DADDR_EF | address);
497 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
498 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
500 return ErrorCode::OK;
503void CH32USBDeviceFS::Start(
bool)
505 LibXR::CH32UsbCanShared::usb_inited.store(
true, std::memory_order_release);
506 LibXR::CH32UsbCanShared::register_usb_irq(&usb_irq_thunk);
508 ch32_usb_clock48m_config();
509 RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE);
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);
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);
523 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
524 GPIO_Init(GPIOA, &gpio);
527 *usbdev_cntr() = USB_CNTR_FRES;
530 usbdev_clear_istr(0xFFFFu);
531 *usbdev_btable() = 0;
533 *usbdev_cntr() =
static_cast<uint16_t
>(USB_CNTR_RESETM | USB_CNTR_SUSPM |
534 USB_CNTR_WKUPM | USB_CNTR_CTRM);
536#if defined(EXTEN_USBD_LS)
537 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_LS;
540 NVIC_EnableIRQ(USB_LP_CAN1_RX0_IRQn);
541 NVIC_EnableIRQ(USB_HP_CAN1_TX_IRQn);
542 NVIC_EnableIRQ(USBWakeUp_IRQn);
544#if defined(EXTEN_USBD_PU_EN)
545 EXTEN->EXTEN_CTR |= EXTEN_USBD_PU_EN;
548 *usbdev_daddr() = USB_DADDR_EF;
550 CH32EndpointDevFs::SetEpTxStatus(0, USB_EP_TX_NAK);
551 CH32EndpointDevFs::SetEpRxStatus(0, USB_EP_RX_VALID);
555 auto& ep_map = LibXR::CH32EndpointDevFs::map_dev_fs_;
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)
560 auto* out = ep_map[ep][OUT_IDX];
569 (void)out->Transfer(out->MaxTransferSize());
573void CH32USBDeviceFS::Stop(
bool)
575 LibXR::CH32UsbCanShared::register_usb_irq(
nullptr);
576 LibXR::CH32UsbCanShared::usb_inited.store(
false, std::memory_order_release);
578#if defined(EXTEN_USBD_PU_EN)
579 EXTEN->EXTEN_CTR &= ~EXTEN_USBD_PU_EN;
582 if (!LibXR::CH32UsbCanShared::can1_active())
584 NVIC_DisableIRQ(USB_LP_CAN1_RX0_IRQn);
585 NVIC_DisableIRQ(USB_HP_CAN1_TX_IRQn);
587 NVIC_DisableIRQ(USBWakeUp_IRQn);
589 *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
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)