Skip to content

Commit

Permalink
temp
Browse files Browse the repository at this point in the history
  • Loading branch information
sakumisu committed Jan 24, 2025
1 parent efbfc9d commit 33ab4b7
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 1 deletion.
2 changes: 2 additions & 0 deletions cherryusb.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ if(CONFIG_CHERRYUSB_HOST)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "kinetis_mcx")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_hc_kinetis.c)
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/kinetis/usb_glue_mcx.c)
elseif("${CONFIG_CHERRYUSB_HOST_HCD}" STREQUAL "rp2040")
list(APPEND cherryusb_srcs ${CMAKE_CURRENT_LIST_DIR}/port/rp2040/usb_hc_rp2040.c)
endif()
endif()

Expand Down
12 changes: 11 additions & 1 deletion port/rp2040/usb_dc_rp2040.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ struct rp2040_udc {
struct usb_setup_packet setup; /*!< Setup package that may be used in interrupt processing (outside the protocol stack) */
} g_rp2040_udc;

void rp2040_usbd_irq(void);

/**
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
*
Expand Down Expand Up @@ -144,6 +146,11 @@ int usb_dc_init(uint8_t busid)
next_buffer_ptr += 64;
}

// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);

irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbd_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);

// Reset usb controller
reset_unreset_block_num_wait_blocking(RESET_USBCTRL);

Expand Down Expand Up @@ -181,6 +188,9 @@ int usb_dc_init(uint8_t busid)
int usb_dc_deinit(uint8_t busid)
{
irq_set_enabled(USBCTRL_IRQ, false);
// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbd_irq);

usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
memset(&g_rp2040_udc, 0, sizeof(struct rp2040_udc));

Expand Down Expand Up @@ -571,7 +581,7 @@ void USBD_IRQHandler(uint8_t busid)
}
}

void isr_usbctrl(void)
void rp2040_usbd_irq(void)
{
USBD_IRQHandler(0);
}
313 changes: 313 additions & 0 deletions port/rp2040/usb_hc_rp2040.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,313 @@
/*
* Copyright (c) 2025, sakumisu
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "usbh_core.h"
#include "usbh_hub.h"
#include "hardware/resets.h"
#include "hardware/irq.h"
#include "hardware/structs/usb.h"

#define usb_hw_set hw_set_alias(usb_hw)
#define usb_hw_clear hw_clear_alias(usb_hw)

struct rp2040_pipe {
uint8_t chidx;
bool inuse;
volatile uint32_t *endpoint_control; /*!< Endpoint control register */
volatile uint32_t *buffer_control; /*!< Buffer control register */
uint8_t *data_buffer; /*!< Buffer pointer in usb dpram */
uint32_t buffer_size; /*!< Buffer size */
usb_osal_sem_t waitsem;
struct usbh_urb *urb;
};

struct rp2040_hcd {
volatile bool port_csc;
volatile bool port_pec;
volatile bool port_pe;
struct rp2040_pipe pipe_pool[1 + CONFIG_USBHOST_PIPE_NUM];
} g_rp2040_hcd[CONFIG_USBHOST_MAX_BUS];

void rp2040_usbh_irq(void);

/**
* @brief Take a buffer pointer located in the USB RAM and return as an offset of the RAM.
*
* @param buf
* @return uint32_t
*/
static inline uint32_t usb_buffer_offset(volatile uint8_t *buf)
{
return (uint32_t)buf ^ (uint32_t)usbh_dpram;
}

static inline uint8_t usbh_get_port_speed(void)
{
return (usb_hw->sie_status & USB_SIE_STATUS_SPEED_BITS) >> USB_SIE_STATUS_SPEED_LSB;
}

int usb_hc_init(struct usbh_bus *bus)
{
uint8_t *next_buffer_ptr;

memset(&g_rp2040_hcd[bus->hcd.hcd_id], 0, sizeof(struct rp2040_hcd));

for (uint8_t i = 0; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].waitsem = usb_osal_sem_create(0);
}

g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].endpoint_control = &usbh_dpram->epx_ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].buffer_control = &usbh_dpram->epx_buf_ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[0].data_buffer = &usbh_dpram->epx_data[0];

next_buffer_ptr = &usb_dpram->epx_data[64 * 2];

for (uint8_t i = 1; i <= CONFIG_USBHOST_PIPE_NUM; i++) {
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].chidx = i;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].endpoint_control = &usbh_dpram->int_ep_ctrl[i].ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_control = &usbh_dpram->int_ep_buffer_ctrl[i].ctrl;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].data_buffer = next_buffer_ptr;
g_rp2040_hcd[bus->hcd.hcd_id].pipe_pool[i].buffer_size = (64 * 2);
next_buffer_ptr += (64 * 2);
}

// Reset usb controller
reset_unreset_block_num_wait_blocking(RESET_USBCTRL);

// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);

irq_add_shared_handler(USBCTRL_IRQ, rp2040_usbh_irq, PICO_SHARED_IRQ_HANDLER_HIGHEST_ORDER_PRIORITY);

/*!< Clear any previous state just in case */
memset(usb_hw, 0, sizeof(*usb_hw));
memset(usbh_dpram, 0, sizeof(*usbh_dpram));

/*!< Mux the controller to the onboard usb phy */
usb_hw->muxing = USB_USB_MUXING_TO_PHY_BITS | USB_USB_MUXING_SOFTCON_BITS;

// Force VBUS detect so the device thinks it is plugged into a host
usb_hw->pwr = USB_USB_PWR_VBUS_DETECT_BITS | USB_USB_PWR_VBUS_DETECT_OVERRIDE_EN_BITS;

// Enable the USB controller in device mode.
usb_hw->main_ctrl = USB_MAIN_CTRL_CONTROLLER_EN_BITS | USB_MAIN_CTRL_HOST_NDEVICE_BITS;

usb_hw->sie_ctrl = USB_SIE_CTRL_SOF_EN_BITS |
USB_SIE_CTRL_KEEP_ALIVE_EN_BITS |
USB_SIE_CTRL_PULLDOWN_EN_BITS |
USB_SIE_CTRL_EP0_INT_1BUF_BITS;

// Enable USB interrupt at processor
irq_set_enabled(USBCTRL_IRQ, true);

usb_hw->inte = USB_INTE_BUFF_STATUS_BITS |
USB_INTE_HOST_CONN_DIS_BITS |
USB_INTE_HOST_RESUME_BITS |
USB_INTE_STALL_BITS |
USB_INTE_TRANS_COMPLETE_BITS |
USB_INTE_ERROR_RX_TIMEOUT_BITS |
USB_INTE_ERROR_DATA_SEQ_BITS;
return 0;
}

int usb_hc_deinit(struct usbh_bus *bus)
{
// Enable USB interrupt at processor
irq_set_enabled(USBCTRL_IRQ, false);

// Remove shared irq if it was previously added so as not to fill up shared irq slots
irq_remove_handler(USBCTRL_IRQ, rp2040_usbh_irq);

return 0;
}

uint16_t usbh_get_frame_number(struct usbh_bus *bus)
{
return 0;
}

int usbh_roothub_control(struct usbh_bus *bus, struct usb_setup_packet *setup, uint8_t *buf)
{
uint8_t nports;
uint8_t port;
uint32_t status;

nports = CONFIG_USBHOST_MAX_RHPORTS;
port = setup->wIndex;
if (setup->bmRequestType & USB_REQUEST_RECIPIENT_DEVICE) {
switch (setup->bRequest) {
case HUB_REQUEST_CLEAR_FEATURE:
switch (setup->wValue) {
case HUB_FEATURE_HUB_C_LOCALPOWER:
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_SET_FEATURE:
switch (setup->wValue) {
case HUB_FEATURE_HUB_C_LOCALPOWER:
break;
case HUB_FEATURE_HUB_C_OVERCURRENT:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_GET_DESCRIPTOR:
break;
case HUB_REQUEST_GET_STATUS:
memset(buf, 0, 4);
break;
default:
break;
}
} else if (setup->bmRequestType & USB_REQUEST_RECIPIENT_OTHER) {
switch (setup->bRequest) {
case HUB_REQUEST_CLEAR_FEATURE:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}

switch (setup->wValue) {
case HUB_PORT_FEATURE_ENABLE:
break;
case HUB_PORT_FEATURE_SUSPEND:
case HUB_PORT_FEATURE_C_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_C_CONNECTION:
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 0;
break;
case HUB_PORT_FEATURE_C_ENABLE:
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 0;
break;
case HUB_PORT_FEATURE_C_OVER_CURREN:
break;
case HUB_PORT_FEATURE_C_RESET:
break;
default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_SET_FEATURE:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}

switch (setup->wValue) {
case HUB_PORT_FEATURE_SUSPEND:
break;
case HUB_PORT_FEATURE_POWER:
break;
case HUB_PORT_FEATURE_RESET:
break;

default:
return -USB_ERR_INVAL;
}
break;
case HUB_REQUEST_GET_STATUS:
if (!port || port > nports) {
return -USB_ERR_INVAL;
}

status = 0;
if (g_rp2040_hcd[bus->hcd.hcd_id].port_csc) {
status |= (1 << HUB_PORT_FEATURE_C_CONNECTION);
}
if (g_rp2040_hcd[bus->hcd.hcd_id].port_pec) {
status |= (1 << HUB_PORT_FEATURE_C_ENABLE);
}

if (g_rp2040_hcd[bus->hcd.hcd_id].port_pe) {
status |= (1 << HUB_PORT_FEATURE_CONNECTION);
status |= (1 << HUB_PORT_FEATURE_ENABLE);
if (usbh_get_port_speed() == USB_SPEED_LOW) {
status |= (1 << HUB_PORT_FEATURE_LOWSPEED);
}
}

status |= (1 << HUB_PORT_FEATURE_POWER);
memcpy(buf, &status, 4);
break;
default:
break;
}
}
return 0;
}

int usbh_submit_urb(struct usbh_urb *urb)
{
return -USB_ERR_NOTSUPP;
}

int usbh_kill_urb(struct usbh_urb *urb)
{
return -USB_ERR_NOTSUPP;
}

void USBH_IRQHandler(uint8_t busid)
{
uint32_t status = usb_hw->ints;
uint32_t handled = 0;
struct usbh_bus *bus;

bus = &g_usbhost_bus[busid];

if (status & USB_INTS_HOST_CONN_DIS_BITS) {
handled |= USB_INTS_HOST_CONN_DIS_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_SPEED_BITS;
if (usbh_get_port_speed()) {
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 1;
bus->hcd.roothub.int_buffer[0] = (1 << 1);
usbh_hub_thread_wakeup(&bus->hcd.roothub);
} else {
g_rp2040_hcd[bus->hcd.hcd_id].port_csc = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pec = 1;
g_rp2040_hcd[bus->hcd.hcd_id].port_pe = 0;
bus->hcd.roothub.int_buffer[0] = (1 << 1);
usbh_hub_thread_wakeup(&bus->hcd.roothub);
}
}

if (status & USB_INTS_STALL_BITS) {
handled |= USB_INTS_STALL_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_STALL_REC_BITS;
}

if (status & USB_INTS_BUFF_STATUS_BITS) {
handled |= USB_INTS_BUFF_STATUS_BITS;
}

if (status & USB_INTS_TRANS_COMPLETE_BITS) {
handled |= USB_INTS_TRANS_COMPLETE_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_TRANS_COMPLETE_BITS;
}

if (status & USB_INTS_ERROR_RX_TIMEOUT_BITS) {
handled |= USB_INTS_ERROR_RX_TIMEOUT_BITS;
usb_hw_clear->sie_status = USB_SIE_STATUS_RX_TIMEOUT_BITS;
}

if (status & USB_INTS_ERROR_DATA_SEQ_BITS) {
usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
}

if (status ^ handled) {
USB_LOG_ERR("Unhandled IRQ 0x%x\n", (uint)(status ^ handled));
}
}

void rp2040_usbh_irq(void)
{
USBH_IRQHandler(0);
}

0 comments on commit 33ab4b7

Please sign in to comment.