3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
5#include "ch32_usb_rcc.hpp"
9using namespace LibXR::USB;
14extern "C" __attribute__((interrupt(
"WCH-Interrupt-fast"))) void USBFS_IRQHandler(
void)
16 auto& map = LibXR::CH32EndpointOtgFs::map_otg_fs_;
21 constexpr uint8_t CLEARABLE_MASK = USBFS_UIF_FIFO_OV | USBFS_UIF_HST_SOF |
22 USBFS_UIF_SUSPEND | USBFS_UIF_TRANSFER |
23 USBFS_UIF_DETECT | USBFS_UIF_BUS_RST;
24 auto* out0 = map[0][OUT_IDX];
25 auto* in0 = map[0][IN_IDX];
26 ASSERT(out0 !=
nullptr);
27 ASSERT(in0 !=
nullptr);
37 const uint16_t INTFGST = *
reinterpret_cast<volatile uint16_t*
>(
38 reinterpret_cast<uintptr_t
>(&USBFSD->INT_FG));
40 const uint8_t INTFLAG =
static_cast<uint8_t
>(INTFGST & 0x00FFu);
41 const uint8_t INTST =
static_cast<uint8_t
>((INTFGST >> 8) & 0x00FFu);
43 const uint8_t
PENDING =
static_cast<uint8_t
>(INTFLAG & CLEARABLE_MASK);
49 uint8_t clear_mask = 0;
53 if (
PENDING & USBFS_UIF_BUS_RST)
57 LibXR::CH32USBOtgFS::self_->Deinit(
true);
58 LibXR::CH32USBOtgFS::self_->Init(
true);
65 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
66 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
68 clear_mask |= USBFS_UIF_BUS_RST;
73 if (
PENDING & USBFS_UIF_SUSPEND)
75 LibXR::CH32USBOtgFS::self_->Deinit(
true);
76 LibXR::CH32USBOtgFS::self_->Init(
true);
83 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
84 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
86 clear_mask |= USBFS_UIF_SUSPEND;
89 if (
PENDING & USBFS_UIF_TRANSFER)
91 const uint8_t TOKEN = INTST & USBFS_UIS_TOKEN_MASK;
92 const uint8_t EPNUM = INTST & USBFS_UIS_ENDP_MASK;
94 auto& ep = map[EPNUM];
98 case USBFS_UIS_TOKEN_SETUP:
104 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
105 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
112 LibXR::CH32USBOtgFS::self_->OnSetupPacket(
113 true,
reinterpret_cast<const SetupPacket*
>(out0->GetBuffer().addr_));
117 case USBFS_UIS_TOKEN_OUT:
121 const uint16_t LEN = USBFSD->RX_LEN;
124 ep[OUT_IDX]->TransferComplete(LEN);
129 case USBFS_UIS_TOKEN_IN:
135 ep[IN_IDX]->TransferComplete(0);
144 clear_mask |= USBFS_UIF_TRANSFER;
147 clear_mask |=
static_cast<uint8_t
>(
PENDING & ~clear_mask);
148 USBFSD->INT_FG = clear_mask;
152CH32USBOtgFS::CH32USBOtgFS(
153 const std::initializer_list<EPConfig> EP_CFGS,
156 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
157 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
161 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::
FULL, packet_size, vid,
162 pid, bcd, LANG_LIST, CONFIGS, uid)
165 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointOtgFs::EP_OTG_FS_MAX_SIZE);
167 auto cfgs_itr = EP_CFGS.begin();
170 new CH32EndpointOtgFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
171 cfgs_itr->buffer,
false);
173 new CH32EndpointOtgFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
174 cfgs_itr->buffer,
false);
180 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
183 if (cfgs_itr->is_in == -1)
185 auto ep_out =
new CH32EndpointOtgFs(ep_index, USB::Endpoint::Direction::OUT,
186 cfgs_itr->buffer,
false);
187 USB::EndpointPool::Put(ep_out);
189 auto ep_in =
new CH32EndpointOtgFs(ep_index, USB::Endpoint::Direction::IN,
190 cfgs_itr->buffer,
false);
191 USB::EndpointPool::Put(ep_in);
195 auto ep =
new CH32EndpointOtgFs(
197 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
198 cfgs_itr->buffer,
true);
199 USB::EndpointPool::Put(ep);
207 if (context == USB::DeviceCore::Context::STATUS_IN_COMPLETE)
209 USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | address;
210 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
211 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK;
216void CH32USBOtgFS::Start(
bool)
220 LibXR::CH32UsbRcc::ConfigureUsb48M();
221#if defined(RCC_USBCLK48MCLKSource_USBPHY) && defined(RCC_AHBPeriph_USBHS)
222 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
224#if defined(RCC_AHBPeriph_USBFS)
225 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);
226#elif defined(RCC_AHBPeriph_USBOTGFS)
227 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBOTGFS, ENABLE);
229 USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
230 USBFSH->BASE_CTRL = 0x00;
231 USBFSD->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER;
232 USBFSD->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
233 USBFSD->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN;
234 NVIC_EnableIRQ(USBFS_IRQn);
237void CH32USBOtgFS::Stop(
bool)
239 USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
240 USBFSD->BASE_CTRL = 0x00;
241 NVIC_DisableIRQ(USBFS_IRQn);
常量原始数据封装类。 A class for encapsulating constant raw 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
@ 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)