diff --git a/examples/host/cdc_msc_hid/src/tusb_config.h b/examples/host/cdc_msc_hid/src/tusb_config.h index abb75f068..7d621d466 100644 --- a/examples/host/cdc_msc_hid/src/tusb_config.h +++ b/examples/host/cdc_msc_hid/src/tusb_config.h @@ -35,9 +35,12 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_RP2040 -// change to 1 if using pico-pio-usb as host controller for raspberry rp2040 -#define CFG_TUH_RPI_PIO_USB 0 -#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB +#elif CFG_TUSB_MCU == OPT_MCU_NRF5X + // Use external USB controller (via SPI) MAX3421E (aka usb host shield) + #define CFG_TUH_MAX3421 1 #endif // RHPort number used for host can be defined by board.mk, default to port 0 diff --git a/examples/host/msc_file_explorer/src/tusb_config.h b/examples/host/msc_file_explorer/src/tusb_config.h index 1e0d067bf..bb2fd4cf5 100644 --- a/examples/host/msc_file_explorer/src/tusb_config.h +++ b/examples/host/msc_file_explorer/src/tusb_config.h @@ -35,11 +35,15 @@ //--------------------------------------------------------------------+ #if CFG_TUSB_MCU == OPT_MCU_RP2040 -// change to 1 if using pico-pio-usb as host controller for raspberry rp2040 -#define CFG_TUH_RPI_PIO_USB 0 -#define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_USB + // change to 1 if using pico-pio-usb as host controller for raspberry rp2040 + #define CFG_TUH_RPI_PIO_USB 0 + #define BOARD_TUH_RHPORT CFG_TUH_RPI_PIO_US +#elif CFG_TUSB_MCU == OPT_MCU_NRF5X + // Use external USB controller (via SPI) MAX3421E (aka usb host shield) + #define CFG_TUH_MAX3421 1 #endif + // RHPort number used for host can be defined by board.mk, default to port 0 #ifndef BOARD_TUH_RHPORT #define BOARD_TUH_RHPORT 0 diff --git a/src/common/tusb_mcu.h b/src/common/tusb_mcu.h index 35f94efbc..21939df7c 100644 --- a/src/common/tusb_mcu.h +++ b/src/common/tusb_mcu.h @@ -385,6 +385,18 @@ #define TUP_RHPORT_HIGHSPEED 1 #endif + +//--------------------------------------------------------------------+ +// External USB controller +//--------------------------------------------------------------------+ + +#if defined(CFG_TUH_MAX3421) & CFG_TUH_MAX3421 + #ifndef CFG_TUH_MAX3421_ENDPOINT_TOTAL + #define CFG_TUH_MAX3421_ENDPOINT_TOTAL (8 + 4*(CFG_TUH_DEVICE_MAX-1)) + #endif +#endif + + //--------------------------------------------------------------------+ // Default Values //--------------------------------------------------------------------+ diff --git a/src/host/hcd.h b/src/host/hcd.h index 1f01a1a2f..e25b20ea3 100644 --- a/src/host/hcd.h +++ b/src/host/hcd.h @@ -39,7 +39,7 @@ // Configuration //--------------------------------------------------------------------+ -// Max number of endpoints per device +// Max number of endpoints pair per device // TODO optimize memory usage #ifndef CFG_TUH_ENDPOINT_MAX #define CFG_TUH_ENDPOINT_MAX 16 @@ -167,7 +167,7 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr); //--------------------------------------------------------------------+ // Open an endpoint -bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc); +bool hcd_edpt_open(uint8_t rhport, uint8_t daddr, tusb_desc_endpoint_t const * ep_desc); // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen); diff --git a/src/host/usbh.c b/src/host/usbh.c index 7a09f5b6e..12a7f5839 100644 --- a/src/host/usbh.c +++ b/src/host/usbh.c @@ -919,6 +919,7 @@ TU_ATTR_FAST_FUNC void hcd_event_handler(hcd_event_t const* event, bool in_isr) switch (event->event_id) { // case HCD_EVENT_DEVICE_REMOVE: +// // FIXME device remove from a hub need an HCD API for hcd to free up endpoint // // mark device as removing to prevent further xfer before the event is processed in usbh task // break; diff --git a/src/portable/analog/max3421/hcd_max3421.c b/src/portable/analog/max3421/hcd_max3421.c index e546f99ce..574cca788 100644 --- a/src/portable/analog/max3421/hcd_max3421.c +++ b/src/portable/analog/max3421/hcd_max3421.c @@ -582,6 +582,7 @@ void xact_out(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { } uint8_t const xact_len = (uint8_t) tu_min16(ep->total_len - ep->xferred_len, ep->packet_size); + TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ, ); fifo_write(rhport, SNDFIFO_ADDR, ep->buf, xact_len, in_isr); sndbc_write(rhport, xact_len, in_isr); @@ -602,6 +603,28 @@ void xact_in(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { hxfr_write(rhport, hxfr, in_isr); } +TU_ATTR_ALWAYS_INLINE static inline void xact_inout(uint8_t rhport, max3421_ep_t *ep, bool switch_ep, bool in_isr) { + if (ep->ep_dir) { + xact_in(rhport, ep, switch_ep, in_isr); + }else { + xact_out(rhport, ep, switch_ep, in_isr); + } +} + +void xfer_complete_isr(uint8_t rhport, max3421_ep_t *ep, xfer_result_t result, uint8_t data_toggle) { + (void) rhport; + (void) result; + ep->xfer_pending = 0; + ep->data_toggle = data_toggle; + //uint8_t const ep_addr = tu_edpt_addr(ep->ep_num, ep->ep_dir); + //hcd_event_xfer_complete(rhport, ep_addr, ep->xferred_len, result, true); + +// max3421_ep_t *next_ep = find_next_pending_ep(ep); +// if (next_ep) { +// xact_inout(rhport, next_ep, true, true); +// } +} + // Submit a transfer, when complete hcd_event_xfer_complete() must be invoked bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { (void) rhport; @@ -612,6 +635,9 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf max3421_ep_t* ep = find_opened_ep(daddr, ep_num, ep_dir); TU_ASSERT(ep); + // control transfer can switch direction + ep->ep_dir = ep_dir; + ep->buf = buffer; ep->total_len = buflen; ep->xferred_len = 0; @@ -636,12 +662,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t daddr, uint8_t ep_addr, uint8_t * buf } } - if ( 0 == ep_dir ) { - TU_ASSERT(_hcd_data.hirq & HIRQ_SNDBAV_IRQ); - xact_out(rhport, ep, true, false); - } else { - xact_in(rhport, ep, true, false); - } + xact_inout(rhport, ep, true, false); } return true; @@ -662,6 +683,7 @@ bool hcd_setup_send(uint8_t rhport, uint8_t daddr, uint8_t const setup_packet[8] (void) rhport; max3421_ep_t* ep = find_opened_ep(daddr, 0, 0); + ep->ep_dir = 0; ep->total_len = 8; ep->xferred_len = 0; @@ -715,18 +737,13 @@ static void handle_xfer_done(uint8_t rhport) { }else { // NAK on non-control, find next pending to switch max3421_ep_t *next_ep = find_next_pending_ep(ep); - TU_ASSERT(next_ep, ); if (ep == next_ep) { // only one pending, retry immediately hxfr_write(rhport, _hcd_data.hxfr, true); - }else { + }else if (next_ep) { // switch to next pending TODO could have issue with double buffered if not clear previously out data - if ( ep_dir ) { - xact_in(rhport, next_ep, true, true); - } else { - xact_out(rhport, next_ep, true, true); - } + xact_inout(rhport, next_ep, true, true); } } return; @@ -744,8 +761,8 @@ static void handle_xfer_done(uint8_t rhport) { // short packet or all bytes transferred if ( ep->xfer_complete ) { - // save data toggle - ep->data_toggle = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; + uint8_t const dt = (hrsl & HRSL_RCVTOGRD) ? 1 : 0; // save data toggle + xfer_complete_isr(rhport, ep, xfer_result, dt); hcd_event_xfer_complete(_hcd_data.peraddr, TUSB_DIR_IN_MASK | ep_num, ep->xferred_len, xfer_result, true); }else { // more to transfer @@ -767,8 +784,8 @@ static void handle_xfer_done(uint8_t rhport) { ep->buf += xact_len; if (xact_len < ep->packet_size || ep->xferred_len >= ep->total_len) { - // save data toggle - ep->data_toggle = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; + uint8_t const dt = (hrsl & HRSL_SNDTOGRD) ? 1 : 0; // save data toggle + xfer_complete_isr(rhport, ep, xfer_result, dt); hcd_event_xfer_complete(_hcd_data.peraddr, ep_num, ep->xferred_len, xfer_result, true); } else { xact_out(rhport, ep, false, true);