Skip to content

Commit 33ab4b7

Browse files
committed
temp
1 parent efbfc9d commit 33ab4b7

File tree

3 files changed

+326
-1
lines changed

3 files changed

+326
-1
lines changed

cherryusb.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,8 @@ if(CONFIG_CHERRYUSB_HOST)
272272
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "kinetis_mcx")
273273
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
274274
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
275+
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "rp2040")
276+
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_hc_rp2040.c)
275277
endif()
276278
endif()
277279

port/rp2040/usb_dc_rp2040.c

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ struct rp2040_udc {
4848
struct usb_setup_packet setup; /*!< Setup package that may be used in interrupt processing (outside the protocol stack) */
4949
} g_rp2040_udc;
5050

51+
void rp2040_usbd_irq(void);
52+
5153
/**
5254
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
5355
*
@@ -144,6 +146,11 @@ int usb_dc_init(uint8_t busid)
144146
next_buffer_ptr += 64;
145147
}
146148

149+
// Remove shared irq if it was previously added so as not to fill up shared irq slots
150+
irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);
151+
152+
irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbd_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
153+
147154
// Reset usb controller
148155
reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
149156

@@ -181,6 +188,9 @@ int usb_dc_init(uint8_t busid)
181188
int usb_dc_deinit(uint8_t busid)
182189
{
183190
irq_set_enabled(USBCTRL_IRQ, false);
191+
// Remove shared irq if it was previously added so as not to fill up shared irq slots
192+
irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);
193+
184194
usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
185195
memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));
186196

@@ -571,7 +581,7 @@ void USBD_IRQHandler(uint8_t busid)
571581
}
572582
}
573583

574-
void isr_usbctrl(void)
584+
void rp2040_usbd_irq(void)
575585
{
576586
USBD_IRQHandler(0);
577587
}

port/rp2040/usb_hc_rp2040.c

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
/*
2+
* Copyright (c) 2025, sakumisu
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
#include "usbh_core.h"
7+
#include "usbh_hub.h"
8+
#include "hardware/resets.h"
9+
#include "hardware/irq.h"
10+
#include "hardware/structs/usb.h"
11+
12+
#define usb_hw_set hw_set_alias(usb_hw)
13+
#define usb_hw_clear hw_clear_alias(usb_hw)
14+
15+
struct rp2040_pipe {
16+
uint8_t chidx;
17+
bool inuse;
18+
volatile uint32_t *endpoint_control; /*!< Endpoint control register */
19+
volatile uint32_t *buffer_control; /*!< Buffer control register */
20+
uint8_t *data_buffer; /*!< Buffer pointer in usb dpram */
21+
uint32_t buffer_size; /*!< Buffer size */
22+
usb_osal_sem_t waitsem;
23+
struct usbh_urb *urb;
24+
};
25+
26+
struct rp2040_hcd {
27+
volatile bool port_csc;
28+
volatile bool port_pec;
29+
volatile bool port_pe;
30+
struct rp2040_pipe pipe_pool[1 + CONFIG_USBHOST_PIPE_NUM];
31+
} g_rp2040_hcd[CONFIG_USBHOST_MAX_BUS];
32+
33+
void rp2040_usbh_irq(void);
34+
35+
/**
36+
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
37+
*
38+
* @param buf
39+
* @return uint32_t
40+
*/
41+
static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
42+
{
43+
return (uint32_t)buf ^ (uint32_t)usbh_dpram;
44+
}
45+
46+
static inline uint8_t usbh_get_port_speed(void)
47+
{
48+
return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB;
49+
}
50+
51+
int usb_hc_init(struct usbh_bus *bus)
52+
{
53+
uint8_t *next_buffer_ptr;
54+
55+
memset(&g_rp2040_hcd[bus->hcd.hcd_id], 0, sizeof(struct rp2040_hcd));
56+
57+
for (uint8_t i = 0; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
58+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem = usb_osal_sem_create(0);
59+
}
60+
61+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].endpoint_control = &usbh_dpram->epx_ctrl;
62+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].buffer_control = &usbh_dpram->epx_buf_ctrl;
63+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].data_buffer = &usbh_dpram->epx_data[0];
64+
65+
next_buffer_ptr = &usb_dpram->epx_data[64 * 2];
66+
67+
for (uint8_t i = 1; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
68+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].chidx = i;
69+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].endpoint_control = &usbh_dpram->int_ep_ctrl[i].ctrl;
70+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_control = &usbh_dpram->int_ep_buffer_ctrl[i].ctrl;
71+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].data_buffer = next_buffer_ptr;
72+
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_size = (64 * 2);
73+
next_buffer_ptr += (64 * 2);
74+
}
75+
76+
// Reset usb controller
77+
reset_unreset_block_num_wait_blocking(RESET_USBCTRL);
78+
79+
// Remove shared irq if it was previously added so as not to fill up shared irq slots
80+
irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);
81+
82+
irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbh_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);
83+
84+
/*!< Clear any previous state just in case */
85+
memset(usb_hw, 0, sizeof(*usb_hw));
86+
memset(usbh_dpram, 0, sizeof(*usbh_dpram));
87+
88+
/*!< Mux the controller to the onboard usb phy */
89+
usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;
90+
91+
// Force VBUS detect so the device thinks it is plugged into a host
92+
usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;
93+
94+
// Enable the USB controller in device mode.
95+
usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS;
96+
97+
usb_hw->sie_ctrl = USB_SIE_CTRL_SOF_EN_BITS |
98+
USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
99+
USB_SIE_CTRL_PULLDOWN_EN_BITS |
100+
USB_SIE_CTRL_EP0_INT_1BUF_BITS;
101+
102+
// Enable USB interrupt at processor
103+
irq_set_enabled(USBCTRL_IRQ, true);
104+
105+
usb_hw->inte = USB_INTE_BUFF_STATUS_BITS |
106+
USB_INTE_HOST_CONN_DIS_BITS |
107+
USB_INTE_HOST_RESUME_BITS |
108+
USB_INTE_STALL_BITS |
109+
USB_INTE_TRANS_COMPLETE_BITS |
110+
USB_INTE_ERROR_RX_TIMEOUT_BITS |
111+
USB_INTE_ERROR_DATA_SEQ_BITS;
112+
return 0;
113+
}
114+
115+
int usb_hc_deinit(struct usbh_bus *bus)
116+
{
117+
// Enable USB interrupt at processor
118+
irq_set_enabled(USBCTRL_IRQ, false);
119+
120+
// Remove shared irq if it was previously added so as not to fill up shared irq slots
121+
irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);
122+
123+
return 0;
124+
}
125+
126+
uint16_t usbh_get_frame_number(struct usbh_bus *bus)
127+
{
128+
return 0;
129+
}
130+
131+
int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
132+
{
133+
uint8_t nports;
134+
uint8_t port;
135+
uint32_t status;
136+
137+
nports = CONFIG_USBHOST_MAX_RHPORTS;
138+
port = setup->wIndex;
139+
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
140+
switch (setup->bRequest) {
141+
case HUB_REQUEST_CLEAR_FEATURE:
142+
switch (setup->wValue) {
143+
case HUB_FEATURE_HUB_C_LOCALPOWER:
144+
break;
145+
case HUB_FEATURE_HUB_C_OVERCURRENT:
146+
break;
147+
default:
148+
return -USB_ERR_INVAL;
149+
}
150+
break;
151+
case HUB_REQUEST_SET_FEATURE:
152+
switch (setup->wValue) {
153+
case HUB_FEATURE_HUB_C_LOCALPOWER:
154+
break;
155+
case HUB_FEATURE_HUB_C_OVERCURRENT:
156+
break;
157+
default:
158+
return -USB_ERR_INVAL;
159+
}
160+
break;
161+
case HUB_REQUEST_GET_DESCRIPTOR:
162+
break;
163+
case HUB_REQUEST_GET_STATUS:
164+
memset(buf, 0, 4);
165+
break;
166+
default:
167+
break;
168+
}
169+
} else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
170+
switch (setup->bRequest) {
171+
case HUB_REQUEST_CLEAR_FEATURE:
172+
if (!port || port > nports) {
173+
return -USB_ERR_INVAL;
174+
}
175+
176+
switch (setup->wValue) {
177+
case HUB_PORT_FEATURE_ENABLE:
178+
break;
179+
case HUB_PORT_FEATURE_SUSPEND:
180+
case HUB_PORT_FEATURE_C_SUSPEND:
181+
break;
182+
case HUB_PORT_FEATURE_POWER:
183+
break;
184+
case HUB_PORT_FEATURE_C_CONNECTION:
185+
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 0;
186+
break;
187+
case HUB_PORT_FEATURE_C_ENABLE:
188+
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 0;
189+
break;
190+
case HUB_PORT_FEATURE_C_OVER_CURREN:
191+
break;
192+
case HUB_PORT_FEATURE_C_RESET:
193+
break;
194+
default:
195+
return -USB_ERR_INVAL;
196+
}
197+
break;
198+
case HUB_REQUEST_SET_FEATURE:
199+
if (!port || port > nports) {
200+
return -USB_ERR_INVAL;
201+
}
202+
203+
switch (setup->wValue) {
204+
case HUB_PORT_FEATURE_SUSPEND:
205+
break;
206+
case HUB_PORT_FEATURE_POWER:
207+
break;
208+
case HUB_PORT_FEATURE_RESET:
209+
break;
210+
211+
default:
212+
return -USB_ERR_INVAL;
213+
}
214+
break;
215+
case HUB_REQUEST_GET_STATUS:
216+
if (!port || port > nports) {
217+
return -USB_ERR_INVAL;
218+
}
219+
220+
status = 0;
221+
if (g_rp2040_hcd[bus->hcd.hcd_id].port_csc) {
222+
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
223+
}
224+
if (g_rp2040_hcd[bus->hcd.hcd_id].port_pec) {
225+
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
226+
}
227+
228+
if (g_rp2040_hcd[bus->hcd.hcd_id].port_pe) {
229+
status |= (1 << HUB_PORT_FEATURE_CONNECTION);
230+
status |= (1 << HUB_PORT_FEATURE_ENABLE);
231+
if (usbh_get_port_speed() == USB_SPEED_LOW) {
232+
status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
233+
}
234+
}
235+
236+
status |= (1 << HUB_PORT_FEATURE_POWER);
237+
memcpy(buf, &status, 4);
238+
break;
239+
default:
240+
break;
241+
}
242+
}
243+
return 0;
244+
}
245+
246+
int usbh_submit_urb(struct usbh_urb *urb)
247+
{
248+
return -USB_ERR_NOTSUPP;
249+
}
250+
251+
int usbh_kill_urb(struct usbh_urb *urb)
252+
{
253+
return -USB_ERR_NOTSUPP;
254+
}
255+
256+
void USBH_IRQHandler(uint8_t busid)
257+
{
258+
uint32_t status = usb_hw->ints;
259+
uint32_t handled = 0;
260+
struct usbh_bus *bus;
261+
262+
bus = &g_usbhost_bus[busid];
263+
264+
if (status & USB_INTS_HOST_CONN_DIS_BITS) {
265+
handled |= USB_INTS_HOST_CONN_DIS_BITS;
266+
usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS;
267+
if (usbh_get_port_speed()) {
268+
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
269+
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
270+
g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 1;
271+
bus->hcd.roothub.int_buffer[0] = (1 << 1);
272+
usbh_hub_thread_wakeup(&bus->hcd.roothub);
273+
} else {
274+
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
275+
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
276+
g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 0;
277+
bus->hcd.roothub.int_buffer[0] = (1 << 1);
278+
usbh_hub_thread_wakeup(&bus->hcd.roothub);
279+
}
280+
}
281+
282+
if (status & USB_INTS_STALL_BITS) {
283+
handled |= USB_INTS_STALL_BITS;
284+
usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS;
285+
}
286+
287+
if (status & USB_INTS_BUFF_STATUS_BITS) {
288+
handled |= USB_INTS_BUFF_STATUS_BITS;
289+
}
290+
291+
if (status & USB_INTS_TRANS_COMPLETE_BITS) {
292+
handled |= USB_INTS_TRANS_COMPLETE_BITS;
293+
usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
294+
}
295+
296+
if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) {
297+
handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS;
298+
usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS;
299+
}
300+
301+
if (status & USB_INTS_ERROR_DATA_SEQ_BITS) {
302+
usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
303+
}
304+
305+
if (status ^ handled) {
306+
USB_LOG_ERR("Unhandled IRQ 0x%x\n", (uint)(status ^ handled));
307+
}
308+
}
309+
310+
void rp2040_usbh_irq(void)
311+
{
312+
USBH_IRQHandler(0);
313+
}

0 commit comments

Comments
 (0)