3#include "ch32_usb_dev.hpp"
4#include "ch32_usb_endpoint.hpp"
8using namespace LibXR::USB;
15static void ch32_usb_clock48m_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_usbhs_rcc_enable()
77 ch32_usb_clock48m_config();
79#if defined(RCC_HSBHSPLLCLKSource_HSE) && defined(RCC_USBPLL_Div2) && \
80 defined(RCC_USBHSPLLCKREFCLK_4M)
81 RCC_USBHSPLLCLKConfig(RCC_HSBHSPLLCLKSource_HSE);
82 RCC_USBHSConfig(RCC_USBPLL_Div2);
83 RCC_USBHSPLLCKREFCLKConfig(RCC_USBHSPLLCKREFCLK_4M);
84 RCC_USBHSPHYPLLALIVEcmd(ENABLE);
87#if defined(RCC_AHBPeriph_USBHS)
88 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBHS, ENABLE);
90#if defined(RCC_AHBPeriph_USBFS)
91 RCC_AHBPeriphClockCmd(RCC_AHBPeriph_USBFS, ENABLE);
98extern "C" __attribute__((interrupt))
void USBHS_IRQHandler(
void)
100 auto& map = LibXR::CH32EndpointOtgHs::map_otg_hs_;
107 const uint16_t INTFGST = *
reinterpret_cast<volatile uint16_t*
>(
108 reinterpret_cast<uintptr_t
>(&USBHSD->INT_FG));
110 const uint8_t INTFLAG =
static_cast<uint8_t
>(INTFGST & 0x00FFu);
111 const uint8_t INTST =
static_cast<uint8_t
>((INTFGST >> 8) & 0x00FFu);
118 uint8_t clear_mask = 0;
120 if (INTFLAG & USBHS_UIF_BUS_RST)
124 LibXR::CH32USBOtgHS::self_->Deinit(
true);
125 LibXR::CH32USBOtgHS::self_->Init(
true);
138 map[0][OUT_IDX]->tog0_ =
true;
139 map[0][OUT_IDX]->tog1_ =
false;
143 map[0][IN_IDX]->tog0_ =
true;
144 map[0][IN_IDX]->tog1_ =
false;
147 USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_NAK;
148 USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_NAK;
150 clear_mask |= USBHS_UIF_BUS_RST;
153 if (INTFLAG & USBHS_UIF_SUSPEND)
155 LibXR::CH32USBOtgHS::self_->Deinit(
true);
156 LibXR::CH32USBOtgHS::self_->Init(
true);
169 map[0][OUT_IDX]->tog0_ =
true;
170 map[0][OUT_IDX]->tog1_ =
false;
174 map[0][IN_IDX]->tog0_ =
true;
175 map[0][IN_IDX]->tog1_ =
false;
178 USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_NAK;
179 USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_NAK;
181 clear_mask |= USBHS_UIF_SUSPEND;
184 if (INTFLAG & USBHS_UIF_SETUP_ACT)
186 USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_TOG_DATA1 | USBHS_UEP_T_RES_NAK;
187 USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_TOG_DATA1 | USBHS_UEP_R_RES_NAK;
200 map[0][OUT_IDX]->tog0_ =
true;
201 map[0][OUT_IDX]->tog1_ =
false;
205 map[0][IN_IDX]->tog0_ =
true;
206 map[0][IN_IDX]->tog1_ =
false;
209 LibXR::CH32USBOtgHS::self_->OnSetupPacket(
211 map[0][OUT_IDX]->GetBuffer().addr_));
213 clear_mask |= USBHS_UIF_SETUP_ACT;
216 if (INTFLAG & USBHS_UIF_TRANSFER)
218 const uint8_t TOKEN = INTST & USBHS_UIS_TOKEN_MASK;
219 const uint8_t EPNUM = INTST & USBHS_UIS_ENDP_MASK;
221 auto& ep = map[EPNUM];
225 case USBHS_UIS_TOKEN_SETUP:
227 USBHSD->UEP0_TX_CTRL = USBHS_UEP_T_RES_NAK | USBHS_UEP_T_TOG_DATA1;
228 USBHSD->UEP0_RX_CTRL = USBHS_UEP_R_RES_NAK | USBHS_UEP_R_TOG_DATA1;
241 map[0][OUT_IDX]->tog0_ =
true;
242 map[0][OUT_IDX]->tog1_ =
false;
246 map[0][IN_IDX]->tog0_ =
true;
247 map[0][IN_IDX]->tog1_ =
false;
250 LibXR::CH32USBOtgHS::self_->OnSetupPacket(
252 map[0][OUT_IDX]->GetBuffer().addr_));
256 case USBHS_UIS_TOKEN_OUT:
259 if (((INTST & USBHS_UIS_IS_NAK) == 0) && ep[OUT_IDX])
261 const uint16_t LEN = USBHSD->RX_LEN;
262 ep[OUT_IDX]->TransferComplete(LEN);
267 case USBHS_UIS_TOKEN_IN:
270 if (((INTST & USBHS_UIS_IS_NAK) == 0) && ep[IN_IDX])
272 ep[IN_IDX]->TransferComplete(0);
281 clear_mask |= USBHS_UIF_TRANSFER;
284 clear_mask |=
static_cast<uint8_t
>(INTFLAG & ~(clear_mask));
285 USBHSD->INT_FG = clear_mask;
289CH32USBOtgHS::CH32USBOtgHS(
290 const std::initializer_list<CH32USBOtgHS::EPConfig> EP_CFGS, uint16_t vid,
291 uint16_t pid, uint16_t bcd,
292 const std::initializer_list<const USB::DescriptorStrings::LanguagePack*> LANG_LIST,
293 const std::initializer_list<
const std::initializer_list<USB::ConfigDescriptorItem*>>
297 USB::
DeviceCore(*this, USB::USBSpec::USB_2_1, USB::Speed::HIGH,
299 LANG_LIST, CONFIGS, uid)
302 ASSERT(EP_CFGS.size() > 0 && EP_CFGS.size() <= CH32EndpointOtgHs::EP_OTG_HS_MAX_SIZE);
304 auto cfgs_itr = EP_CFGS.begin();
306 ASSERT(cfgs_itr->buffer_tx.size_ == 64 && cfgs_itr->double_buffer ==
false);
309 new CH32EndpointOtgHs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::OUT,
310 cfgs_itr->buffer_rx,
false);
312 new CH32EndpointOtgHs(USB::Endpoint::EPNumber::EP0, USB::Endpoint::Direction::IN,
313 cfgs_itr->buffer_tx,
false);
319 for (++cfgs_itr, ep_index = USB::Endpoint::EPNumber::EP1; cfgs_itr != EP_CFGS.end();
322 if (!cfgs_itr->double_buffer)
324 auto ep_out =
new CH32EndpointOtgHs(ep_index, USB::Endpoint::Direction::OUT,
325 cfgs_itr->buffer_rx,
false);
326 USB::EndpointPool::Put(ep_out);
328 auto ep_in =
new CH32EndpointOtgHs(ep_index, USB::Endpoint::Direction::IN,
329 cfgs_itr->buffer_tx,
false);
330 USB::EndpointPool::Put(ep_in);
334 auto ep =
new CH32EndpointOtgHs(
336 cfgs_itr->is_in ? USB::Endpoint::Direction::IN : USB::Endpoint::Direction::OUT,
337 cfgs_itr->buffer_tx,
true);
338 USB::EndpointPool::Put(ep);
345 if (context == USB::DeviceCore::Context::STATUS_IN)
347 USBHSD->DEV_AD = address;
349 return ErrorCode::OK;
352void CH32USBOtgHS::Start(
bool)
354 ch32_usbhs_rcc_enable();
355 USBHSD->CONTROL = USBHS_UC_CLR_ALL | USBHS_UC_RESET_SIE;
356 USBHSD->CONTROL &= ~USBHS_UC_RESET_SIE;
357 USBHSD->HOST_CTRL = USBHS_UH_PHY_SUSPENDM;
358 USBHSD->CONTROL = USBHS_UC_DMA_EN | USBHS_UC_INT_BUSY | USBHS_UC_SPEED_HIGH;
359 USBHSD->INT_EN = USBHS_UIE_SETUP_ACT | USBHS_UIE_TRANSFER | USBHS_UIE_DETECT |
360 USBHS_UIE_SUSPEND | USBHS_UIE_ISO_ACT;
361 USBHSD->CONTROL |= USBHS_UC_DEV_PU_EN;
362 NVIC_EnableIRQ(USBHS_IRQn);
365void CH32USBOtgHS::Stop(
bool)
367 USBHSD->CONTROL = USBHS_UC_CLR_ALL | USBHS_UC_RESET_SIE;
369 NVIC_DisableIRQ(USBHS_IRQn);
常量原始数据封装类。 A class for encapsulating constant raw data.
USB 设备协议栈核心:EP0 控制传输、描述符、配置、标准/类/厂商请求 USB device core: EP0 control transfer, descriptors,...
Context
控制传输上下文 / Control transfer context
USB描述符基类 USB descriptor base class.
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)