3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
8using namespace LibXR::USB;
15static void ch32_usb_clock48_m_config()
17 RCC_ClocksTypeDef clk{};
18 RCC_GetClocksFreq(&clk);
20 const uint32_t SYSCLK_HZ = clk.SYSCLK_Frequency;
22#if defined(RCC_USBCLKSource_PLLCLK_Div1) && defined(RCC_USBCLKSource_PLLCLK_Div2) && \
23 defined(RCC_USBCLKSource_PLLCLK_Div3)
24 if (SYSCLK_HZ == 144000000u)
26 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div3);
28 else if (SYSCLK_HZ == 96000000u)
30 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div2);
32 else if (SYSCLK_HZ == 48000000u)
34 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div1);
36#if defined(RCC_USB5PRE_JUDGE) && defined(RCC_USBCLKSource_PLLCLK_Div5)
37 else if (SYSCLK_HZ == 240000000u)
39 ASSERT(RCC_USB5PRE_JUDGE() == SET);
40 RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_Div5);
48#elif defined(RCC_USBCLK48MCLKSource_PLLCLK) && \
49 defined(RCC_USBFSCLKSource_PLLCLK_Div1) && \
50 defined(RCC_USBFSCLKSource_PLLCLK_Div2) && defined(RCC_USBFSCLKSource_PLLCLK_Div3)
51 RCC_USBCLK48MConfig(RCC_USBCLK48MCLKSource_PLLCLK);
53 if (SYSCLK_HZ == 144000000u)
55 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div3);
57 else if (SYSCLK_HZ == 96000000u)
59 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div2);
61 else if (SYSCLK_HZ == 48000000u)
63 RCC_USBFSCLKConfig(RCC_USBFSCLKSource_PLLCLK_Div1);
75static void ch32_usbfs_rcc_enable()
77 ch32_usb_clock48_m_config();
79#if defined(RCC_AHBPeriph_USBFS)
80 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);
81#elif defined(RCC_AHBPeriph_USBOTGFS)
82 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBOTGFS, ENABLE);
89extern "C" __attribute__((interrupt))
void USBFS_IRQHandler(
void)
91 auto& map = LibXR::CH32EndpointOtgFs::map_otg_fs_;
96 constexpr uint8_t CLEARABLE_MASK = USBFS_UIF_FIFO_OV | USBFS_UIF_HST_SOF |
97 USBFS_UIF_SUSPEND | USBFS_UIF_TRANSFER |
98 USBFS_UIF_DETECT | USBFS_UIF_BUS_RST;
102 const uint16_t INTFGST = *
reinterpret_cast<volatile uint16_t*
>(
103 reinterpret_cast<uintptr_t
>(&USBFSD->INT_FG));
105 const uint8_t INTFLAG =
static_cast<uint8_t
>(INTFGST & 0x00FFu);
106 const uint8_t INTST =
static_cast<uint8_t
>((INTFGST >> 8) & 0x00FFu);
108 const uint8_t PENDING =
static_cast<uint8_t
>(INTFLAG & CLEARABLE_MASK);
114 uint8_t clear_mask = 0;
116 if (PENDING & USBFS_UIF_BUS_RST)
118 USBFSD->DEV_ADDR = 0;
120 LibXR::CH32USBOtgFS::self_->Deinit(
true);
121 LibXR::CH32USBOtgFS::self_->Init(
true);
134 map[0][OUT_IDX]->tog_ =
true;
138 map[0][IN_IDX]->tog_ =
true;
141 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
142 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
144 clear_mask |= USBFS_UIF_BUS_RST;
147 if (PENDING & USBFS_UIF_SUSPEND)
149 LibXR::CH32USBOtgFS::self_->Deinit(
true);
150 LibXR::CH32USBOtgFS::self_->Init(
true);
163 map[0][OUT_IDX]->tog_ =
true;
167 map[0][IN_IDX]->tog_ =
true;
170 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
171 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
173 clear_mask |= USBFS_UIF_SUSPEND;
176 if (PENDING & USBFS_UIF_TRANSFER)
178 const uint8_t TOKEN = INTST & USBFS_UIS_TOKEN_MASK;
179 const uint8_t EPNUM = INTST & USBFS_UIS_ENDP_MASK;
181 auto& ep = map[EPNUM];
185 case USBFS_UIS_TOKEN_SETUP:
187 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
188 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_NAK;
201 map[0][OUT_IDX]->tog_ =
true;
205 map[0][IN_IDX]->tog_ =
true;
208 LibXR::CH32USBOtgFS::self_->OnSetupPacket(
210 reinterpret_cast<const SetupPacket*
>(map[0][OUT_IDX]->GetBuffer().addr_));
214 case USBFS_UIS_TOKEN_OUT:
216 const uint16_t LEN = USBFSD->RX_LEN;
219 ep[OUT_IDX]->TransferComplete(LEN);
224 case USBFS_UIS_TOKEN_IN:
228 ep[IN_IDX]->TransferComplete(0);
237 clear_mask |= USBFS_UIF_TRANSFER;
240 clear_mask |=
static_cast<uint8_t
>(PENDING & ~clear_mask);
241 USBFSD->INT_FG = clear_mask;
245CH32USBOtgFS::CH32USBOtgFS(
246 const std::initializer_list<EPConfig> EP_CFGS,
249 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
250 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
254 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::FULL, packet_size, vid,
255 pid, bcd, LANG_LIST, CONFIGS, uid)
258 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointOtgFs::EP_OTG_FS_MAX_SIZE);
260 auto cfgs_itr = EP_CFGS.begin();
263 new CH32EndpointOtgFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
264 cfgs_itr->buffer,
false);
266 new CH32EndpointOtgFs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
267 cfgs_itr->buffer,
false);
273 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
276 if (cfgs_itr->is_in == -1)
278 auto ep_out =
new CH32EndpointOtgFs(ep_index, USB::Endpoint::Direction::OUT,
279 cfgs_itr->buffer,
false);
280 USB::EndpointPool::Put(ep_out);
282 auto ep_in =
new CH32EndpointOtgFs(ep_index, USB::Endpoint::Direction::IN,
283 cfgs_itr->buffer,
false);
284 USB::EndpointPool::Put(ep_in);
288 auto ep =
new CH32EndpointOtgFs(
290 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
291 cfgs_itr->buffer,
true);
292 USB::EndpointPool::Put(ep);
299 if (context == USB::DeviceCore::Context::STATUS_IN)
301 USBFSD->DEV_ADDR = (USBFSD->DEV_ADDR & USBFS_UDA_GP_BIT) | address;
302 USBFSD->UEP0_TX_CTRL = USBFS_UEP_T_RES_NAK;
303 USBFSD->UEP0_RX_CTRL = USBFS_UEP_R_RES_ACK;
305 return ErrorCode::OK;
308void CH32USBOtgFS::Start(
bool)
310 ch32_usbfs_rcc_enable();
311 USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
312 USBFSH->BASE_CTRL = 0x00;
313 USBFSD->INT_EN = USBFS_UIE_SUSPEND | USBFS_UIE_BUS_RST | USBFS_UIE_TRANSFER;
314 USBFSD->BASE_CTRL = USBFS_UC_DEV_PU_EN | USBFS_UC_INT_BUSY | USBFS_UC_DMA_EN;
315 USBFSD->UDEV_CTRL = USBFS_UD_PD_DIS | USBFS_UD_PORT_EN;
316 NVIC_EnableIRQ(USBFS_IRQn);
319void CH32USBOtgFS::Stop(
bool)
321 USBFSH->BASE_CTRL = USBFS_UC_RESET_SIE | USBFS_UC_CLR_ALL;
322 USBFSD->BASE_CTRL = 0x00;
323 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
USB 标准请求 SETUP 包(固定8字节) Standard USB setup packet (8 bytes)