3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
5#include "ch32_usb_rcc.hpp"
9using namespace LibXR::USB;
16constexpr uint8_t OTG_FS_CLEARABLE_MASK = USBFS_UIF_FIFO_OV | USBFS_UIF_HST_SOF |
17 USBFS_UIF_SUSPEND | USBFS_UIF_TRANSFER |
18 USBFS_UIF_DETECT | USBFS_UIF_BUS_RST;
20static void ClearPendingOtgFsInterrupts()
24 const uint16_t INTFGST = *
reinterpret_cast<volatile uint16_t*
>(
25 reinterpret_cast<uintptr_t
>(&USBFSD->INT_FG));
26 const uint8_t INTFLAG =
static_cast<uint8_t
>(INTFGST & 0x00FFu);
27 const uint8_t
PENDING =
static_cast<uint8_t
>(INTFLAG & OTG_FS_CLEARABLE_MASK);
45extern "C" __attribute__((interrupt(
"WCH-Interrupt-fast"))) void USBFS_IRQHandler(
void)
47 auto* usb = LibXR::CH32USBOtgFS::self_;
48 if (usb ==
nullptr || !usb->IsInited())
50 ClearPendingOtgFsInterrupts();
54 auto& map = LibXR::CH32EndpointOtgFs::map_otg_fs_;
58 auto* out0 = map[0][OUT_IDX];
59 auto* in0 = map[0][IN_IDX];
60 ASSERT(out0 !=
nullptr);
61 ASSERT(in0 !=
nullptr);
71 const uint16_t INTFGST = *
reinterpret_cast<volatile uint16_t*
>(
72 reinterpret_cast<uintptr_t
>(&USBFSD->INT_FG));
74 const uint8_t INTFLAG =
static_cast<uint8_t
>(INTFGST & 0x00FFu);
75 const uint8_t INTST =
static_cast<uint8_t
>((INTFGST >> 8) & 0x00FFu);
77 const uint8_t
PENDING =
static_cast<uint8_t
>(INTFLAG & OTG_FS_CLEARABLE_MASK);
83 uint8_t clear_mask = 0;
87 if (
PENDING & USBFS_UIF_BUS_RST)
99 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
100 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
102 clear_mask |= USBFS_UIF_BUS_RST;
107 if (
PENDING & USBFS_UIF_SUSPEND)
117 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
118 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
120 clear_mask |= USBFS_UIF_SUSPEND;
123 if (
PENDING & USBFS_UIF_TRANSFER)
125 const uint8_t TOKEN = INTST & USBFS_UIS_TOKEN_MASK;
126 const uint8_t EPNUM = INTST & USBFS_UIS_ENDP_MASK;
128 auto& ep = map[EPNUM];
132 case USBFS_UIS_TOKEN_SETUP:
138 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
139 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
147 true,
reinterpret_cast<const SetupPacket*
>(out0->GetBuffer().addr_));
151 case USBFS_UIS_TOKEN_OUT:
155 const uint16_t LEN = USBFSD->RX_LEN;
158 ep[OUT_IDX]->TransferComplete(LEN);
163 case USBFS_UIS_TOKEN_IN:
169 ep[IN_IDX]->TransferComplete(0);
178 clear_mask |= USBFS_UIF_TRANSFER;
181 clear_mask |=
static_cast<uint8_t
>(
PENDING & ~clear_mask);
182 USBFSD->INT_FG = clear_mask;
186CH32USBOtgFS::CH32USBOtgFS(
187 const std::initializer_list<EPConfig> EP_CFGS,
190 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
191 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
195 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::
FULL, packet_size, vid,
196 pid, bcd, LANG_LIST, CONFIGS, uid)
198 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointOtgFs::EP_OTG_FS_MAX_SIZE);
200 auto cfgs_itr = EP_CFGS.begin();
203 new CH32EndpointOtgFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
204 cfgs_itr->buffer,
false);
206 new CH32EndpointOtgFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
207 cfgs_itr->buffer,
false);
213 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
216 if (cfgs_itr->is_in == -1)
218 auto ep_out =
new CH32EndpointOtgFs(ep_index, USB::Endpoint::Direction::OUT,
219 cfgs_itr->buffer,
false);
220 USB::EndpointPool::Put(ep_out);
222 auto ep_in =
new CH32EndpointOtgFs(ep_index, USB::Endpoint::Direction::IN,
223 cfgs_itr->buffer,
false);
224 USB::EndpointPool::Put(ep_in);
228 auto ep =
new CH32EndpointOtgFs(
230 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
231 cfgs_itr->buffer,
true);
232 USB::EndpointPool::Put(ep);
240 if (context == USB::DeviceCore::Context::STATUS_IN_COMPLETE)
242 USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | address;
243 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
244 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK;
249void CH32USBOtgFS::Start(
bool)
253 LibXR::CH32UsbRcc::ConfigureUsb48M();
254#if defined(RCC_USBCLK48MCLKSource_USBPHY) && defined(RCC_AHBPeriph_USBHS)
255 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
257#if defined(RCC_AHBPeriph_USBFS)
258 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);
259#elif defined(RCC_AHBPeriph_USBOTGFS)
260 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBOTGFS, ENABLE);
262 USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
263 USBFSH->BASE_CTRL = 0x00;
264 USBFSD->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER;
265 USBFSD->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
266 USBFSD->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN;
267 NVIC_EnableIRQ(USBFS_IRQn);
271void CH32USBOtgFS::Stop(
bool)
273 USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
274 USBFSD->BASE_CTRL = 0x00;
275 NVIC_DisableIRQ(USBFS_IRQn);
只读原始数据视图 / Immutable raw data view
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)