diff options
| author | Wini-Buh <[email protected]> | 2021-06-03 22:17:30 +0200 |
|---|---|---|
| committer | Wini-Buh <[email protected]> | 2021-06-03 22:17:30 +0200 |
| commit | 5a554508caba50bda2a82095a66a1896b960daaf (patch) | |
| tree | c2a1aaafb98689d8827061a37cdbc7788a0eb4ad /src/portable | |
| parent | e26cf6b26ca0d7c54f71332896d4bed9c418844a (diff) | |
| parent | ce30109b5bdb3ecd82f08c9dd48fe0f6f7f1713e (diff) | |
Merge remote-tracking branch 'upstream/master' into CCRX_Port
Diffstat (limited to 'src/portable')
| -rw-r--r-- | src/portable/ehci/ehci.c | 169 | ||||
| -rw-r--r-- | src/portable/ehci/ehci.h | 45 | ||||
| -rw-r--r-- | src/portable/espressif/esp32sx/dcd_esp32sx.c | 1 | ||||
| -rw-r--r-- | src/portable/microchip/samg/dcd_samg.c | 1 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc120/dcd_nuc120.c | 1 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc121/dcd_nuc121.c | 1 | ||||
| -rw-r--r-- | src/portable/nuvoton/nuc505/dcd_nuc505.c | 1 | ||||
| -rw-r--r-- | src/portable/ohci/ohci.c | 304 | ||||
| -rw-r--r-- | src/portable/ohci/ohci.h | 18 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/dcd_rp2040.c | 2 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/hcd_rp2040.c | 20 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/rp2040_usb.c | 38 | ||||
| -rw-r--r-- | src/portable/raspberrypi/rp2040/rp2040_usb.h | 44 | ||||
| -rw-r--r-- | src/portable/sony/cxd56/dcd_cxd56.c | 1 | ||||
| -rw-r--r-- | src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c | 1 | ||||
| -rw-r--r-- | src/portable/st/synopsys/dcd_synopsys.c | 2 | ||||
| -rw-r--r-- | src/portable/template/dcd_template.c | 1 | ||||
| -rw-r--r-- | src/portable/ti/msp430x5xx/dcd_msp430x5xx.c | 1 |
18 files changed, 308 insertions, 343 deletions
diff --git a/src/portable/ehci/ehci.c b/src/portable/ehci/ehci.c index eab1f8928..bcba360bb 100644 --- a/src/portable/ehci/ehci.c +++ b/src/portable/ehci/ehci.c @@ -44,6 +44,27 @@ // MACRO CONSTANT TYPEDEF //--------------------------------------------------------------------+ +typedef struct +{ + ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; + + // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) + // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms + ehci_qhd_t period_head_arr[4]; + + // Note control qhd of dev0 is used as head of async list + struct { + ehci_qhd_t qhd; + ehci_qtd_t qtd; + }control[CFG_TUSB_HOST_DEVICE_MAX+1]; + + ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; + ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); + + ehci_registers_t* regs; + + volatile uint32_t uframe_number; +}ehci_data_t; //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -67,7 +88,8 @@ static inline ehci_qhd_t* qhd_control(uint8_t dev_addr) static inline ehci_qhd_t* qhd_async_head(uint8_t rhport) { (void) rhport; - return qhd_control(0); // control qhd of dev0 is used as async head + // control qhd of dev0 is used as async head + return qhd_control(0); } static inline ehci_qtd_t* qtd_control(uint8_t dev_addr) @@ -102,10 +124,10 @@ static inline ehci_link_t* list_next (ehci_link_t *p_link_pointer); // HCD API //--------------------------------------------------------------------+ -uint32_t hcd_uframe_number(uint8_t rhport) +uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return ehci_data.uframe_number + ehci_data.regs->frame_index; + return (ehci_data.uframe_number + ehci_data.regs->frame_index) >> 3; } void hcd_port_reset(uint8_t rhport) @@ -293,81 +315,9 @@ static void ehci_stop(uint8_t rhport) #endif //--------------------------------------------------------------------+ -// CONTROL PIPE API +// Endpoint API //--------------------------------------------------------------------+ -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // FIXME control only for now - if ( epnum == 0 ) - { - ehci_qhd_t* qhd = qhd_control(dev_addr); - ehci_qtd_t* qtd = qtd_control(dev_addr); - - qtd_init(qtd, buffer, buflen); - - // first first data toggle is always 1 (data & setup stage) - qtd->data_toggle = 1; - qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; - qtd->int_on_complete = 1; - qtd->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = qtd; - qhd->p_qtd_list_tail = qtd; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) qtd; - }else - { - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); - TU_ASSERT(p_qtd); - - qtd_init(p_qtd, buffer, buflen); - p_qtd->pid = p_qhd->pid; - - // Insert TD to QH - qtd_insert_to_qhd(p_qhd, p_qtd); - - p_qhd->p_qtd_list_tail->int_on_complete = 1; - - // attach head QTD to QHD start transferring - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; - } - - return true; -} - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; - ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - - qtd_init(td, (void*) setup_packet, 8); - td->pid = EHCI_PID_SETUP; - td->int_on_complete = 1; - td->next.terminate = 1; - - // sw region - qhd->p_qtd_list_head = td; - qhd->p_qtd_list_tail = td; - - // attach TD - qhd->qtd_overlay.next.address = (uint32_t) td; - - return true; -} -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { (void) rhport; @@ -421,34 +371,71 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - //------------- set up QTD -------------// - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); - ehci_qtd_t *p_qtd = qtd_find_free(); + (void) rhport; - TU_ASSERT(p_qtd); + ehci_qhd_t* qhd = &ehci_data.control[dev_addr].qhd; + ehci_qtd_t* td = &ehci_data.control[dev_addr].qtd; - qtd_init(p_qtd, buffer, total_bytes); - p_qtd->pid = p_qhd->pid; + qtd_init(td, (void*) setup_packet, 8); + td->pid = EHCI_PID_SETUP; + td->int_on_complete = 1; + td->next.terminate = 1; + + // sw region + qhd->p_qtd_list_head = td; + qhd->p_qtd_list_tail = td; - //------------- insert TD to TD list -------------// - qtd_insert_to_qhd(p_qhd, p_qtd); + // attach TD + qhd->qtd_overlay.next.address = (uint32_t) td; return true; } -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { - TU_ASSERT ( hcd_pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes) ); + (void) rhport; - ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + if ( epnum == 0 ) + { + ehci_qhd_t* qhd = qhd_control(dev_addr); + ehci_qtd_t* qtd = qtd_control(dev_addr); + + qtd_init(qtd, buffer, buflen); + + // first first data toggle is always 1 (data & setup stage) + qtd->data_toggle = 1; + qtd->pid = dir ? EHCI_PID_IN : EHCI_PID_OUT; + qtd->int_on_complete = 1; + qtd->next.terminate = 1; + + // sw region + qhd->p_qtd_list_head = qtd; + qhd->p_qtd_list_tail = qtd; + + // attach TD + qhd->qtd_overlay.next.address = (uint32_t) qtd; + }else + { + ehci_qhd_t *p_qhd = qhd_get_from_addr(dev_addr, ep_addr); + ehci_qtd_t *p_qtd = qtd_find_free(); + TU_ASSERT(p_qtd); + + qtd_init(p_qtd, buffer, buflen); + p_qtd->pid = p_qhd->pid; + + // Insert TD to QH + qtd_insert_to_qhd(p_qhd, p_qtd); - if ( int_on_complete ) - { // the just added qtd is pointed by list_tail p_qhd->p_qtd_list_tail->int_on_complete = 1; + + // attach head QTD to QHD start transferring + p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; } - p_qhd->qtd_overlay.next.address = (uint32_t) p_qhd->p_qtd_list_head; // attach head QTD to QHD start transferring return true; } diff --git a/src/portable/ehci/ehci.h b/src/portable/ehci/ehci.h index 212f605b1..874195a0c 100644 --- a/src/portable/ehci/ehci.h +++ b/src/portable/ehci/ehci.h @@ -24,12 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_HCD - * @{ - * \defgroup EHCI - * \brief EHCI driver. All documents sources mentioned here (eg section 3.5) is referring to EHCI Specs unless state otherwise - * @{ */ - #ifndef _TUSB_EHCI_H_ #define _TUSB_EHCI_H_ @@ -309,12 +303,11 @@ enum ehci_usbcmd_pos_ { enum ehci_portsc_change_mask_{ EHCI_PORTSC_MASK_CURRENT_CONNECT_STATUS = TU_BIT(0), - EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), - EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), - EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), - EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), - - EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), + EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE = TU_BIT(1), + EHCI_PORTSC_MASK_PORT_EANBLED = TU_BIT(2), + EHCI_PORTSC_MASK_PORT_ENABLE_CHAGNE = TU_BIT(3), + EHCI_PORTSC_MASK_OVER_CURRENT_CHANGE = TU_BIT(5), + EHCI_PORTSC_MASK_PORT_RESET = TU_BIT(8), EHCI_PORTSC_MASK_ALL = EHCI_PORTSC_MASK_CONNECT_STATUS_CHANGE | @@ -425,36 +418,8 @@ typedef volatile struct }; }ehci_registers_t; -//--------------------------------------------------------------------+ -// EHCI Data Organization -//--------------------------------------------------------------------+ -typedef struct -{ - ehci_link_t period_framelist[EHCI_FRAMELIST_SIZE]; - - // for NXP ECHI, only implement 1 ms & 2 ms & 4 ms, 8 ms (framelist) - // [0] : 1ms, [1] : 2ms, [2] : 4ms, [3] : 8 ms - ehci_qhd_t period_head_arr[4]; - - // Note control qhd of dev0 is used as head of async list - struct { - ehci_qhd_t qhd; - ehci_qtd_t qtd; - }control[CFG_TUSB_HOST_DEVICE_MAX+1]; - - ehci_qhd_t qhd_pool[HCD_MAX_ENDPOINT]; - ehci_qtd_t qtd_pool[HCD_MAX_XFER] TU_ATTR_ALIGNED(32); - - ehci_registers_t* regs; - - volatile uint32_t uframe_number; -}ehci_data_t; - #ifdef __cplusplus } #endif #endif /* _TUSB_EHCI_H_ */ - -/** @} */ -/** @} */ diff --git a/src/portable/espressif/esp32sx/dcd_esp32sx.c b/src/portable/espressif/esp32sx/dcd_esp32sx.c index 502273a9b..d728487c2 100644 --- a/src/portable/espressif/esp32sx/dcd_esp32sx.c +++ b/src/portable/espressif/esp32sx/dcd_esp32sx.c @@ -40,7 +40,6 @@ #include "soc/gpio_sig_map.h" #include "soc/usb_periph.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" // Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval) diff --git a/src/portable/microchip/samg/dcd_samg.c b/src/portable/microchip/samg/dcd_samg.c index 9b6a1f9a5..d50621ce4 100644 --- a/src/portable/microchip/samg/dcd_samg.c +++ b/src/portable/microchip/samg/dcd_samg.c @@ -29,7 +29,6 @@ #if CFG_TUSB_MCU == OPT_MCU_SAMG #include "sam.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" // TODO should support (SAM3S || SAM4S || SAM4E || SAMG55) diff --git a/src/portable/nuvoton/nuc120/dcd_nuc120.c b/src/portable/nuvoton/nuc120/dcd_nuc120.c index 7aeb49f2a..047fa3fa6 100644 --- a/src/portable/nuvoton/nuc120/dcd_nuc120.c +++ b/src/portable/nuvoton/nuc120/dcd_nuc120.c @@ -37,7 +37,6 @@ #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC120) -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC100Series.h" diff --git a/src/portable/nuvoton/nuc121/dcd_nuc121.c b/src/portable/nuvoton/nuc121/dcd_nuc121.c index e76d7118c..37b7b0106 100644 --- a/src/portable/nuvoton/nuc121/dcd_nuc121.c +++ b/src/portable/nuvoton/nuc121/dcd_nuc121.c @@ -37,7 +37,6 @@ #if TUSB_OPT_DEVICE_ENABLED && ( (CFG_TUSB_MCU == OPT_MCU_NUC121) || (CFG_TUSB_MCU == OPT_MCU_NUC126) ) -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NuMicro.h" diff --git a/src/portable/nuvoton/nuc505/dcd_nuc505.c b/src/portable/nuvoton/nuc505/dcd_nuc505.c index 46081d4d0..4e633086d 100644 --- a/src/portable/nuvoton/nuc505/dcd_nuc505.c +++ b/src/portable/nuvoton/nuc505/dcd_nuc505.c @@ -37,7 +37,6 @@ #if TUSB_OPT_DEVICE_ENABLED && (CFG_TUSB_MCU == OPT_MCU_NUC505) -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "NUC505Series.h" diff --git a/src/portable/ohci/ohci.c b/src/portable/ohci/ohci.c index ee294856b..dbd2cc793 100644 --- a/src/portable/ohci/ohci.c +++ b/src/portable/ohci/ohci.c @@ -27,7 +27,7 @@ #include <common/tusb_common.h> #if TUSB_OPT_HOST_ENABLED && \ - (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) + (CFG_TUSB_MCU == OPT_MCU_LPC175X_6X || CFG_TUSB_MCU == OPT_MCU_LPC177X_8X || CFG_TUSB_MCU == OPT_MCU_LPC40XX) //--------------------------------------------------------------------+ // INCLUDE @@ -84,23 +84,23 @@ enum { }; enum { - OHCI_RHPORT_CURRENT_CONNECT_STATUS_MASK = TU_BIT(0), - OHCI_RHPORT_PORT_ENABLE_STATUS_MASK = TU_BIT(1), - OHCI_RHPORT_PORT_SUSPEND_STATUS_MASK = TU_BIT(2), - OHCI_RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3), - OHCI_RHPORT_PORT_RESET_STATUS_MASK = TU_BIT(4), ///< write '1' to reset port + RHPORT_CURRENT_CONNECT_STATUS_MASK = TU_BIT(0), + RHPORT_PORT_ENABLE_STATUS_MASK = TU_BIT(1), + RHPORT_PORT_SUSPEND_STATUS_MASK = TU_BIT(2), + RHPORT_PORT_OVER_CURRENT_INDICATOR_MASK = TU_BIT(3), + RHPORT_PORT_RESET_STATUS_MASK = TU_BIT(4), ///< write '1' to reset port - OHCI_RHPORT_PORT_POWER_STATUS_MASK = TU_BIT(8), - OHCI_RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = TU_BIT(9), + RHPORT_PORT_POWER_STATUS_MASK = TU_BIT(8), + RHPORT_LOW_SPEED_DEVICE_ATTACHED_MASK = TU_BIT(9), - OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK = TU_BIT(16), - OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK = TU_BIT(17), - OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK = TU_BIT(18), - OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK = TU_BIT(19), - OHCI_RHPORT_PORT_RESET_CHANGE_MASK = TU_BIT(20), + RHPORT_CONNECT_STATUS_CHANGE_MASK = TU_BIT(16), + RHPORT_PORT_ENABLE_CHANGE_MASK = TU_BIT(17), + RHPORT_PORT_SUSPEND_CHANGE_MASK = TU_BIT(18), + RHPORT_OVER_CURRENT_CHANGE_MASK = TU_BIT(19), + RHPORT_PORT_RESET_CHANGE_MASK = TU_BIT(20), - OHCI_RHPORT_ALL_CHANGE_MASK = OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK | OHCI_RHPORT_PORT_ENABLE_CHANGE_MASK | - OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK | OHCI_RHPORT_OVER_CURRENT_CHANGE_MASK | OHCI_RHPORT_PORT_RESET_CHANGE_MASK + RHPORT_ALL_CHANGE_MASK = RHPORT_CONNECT_STATUS_CHANGE_MASK | RHPORT_PORT_ENABLE_CHANGE_MASK | + RHPORT_PORT_SUSPEND_CHANGE_MASK | RHPORT_OVER_CURRENT_CHANGE_MASK | RHPORT_PORT_RESET_CHANGE_MASK }; enum { @@ -123,6 +123,23 @@ enum { OHCI_INT_ON_COMPLETE_YES = 0, OHCI_INT_ON_COMPLETE_NO = TU_BIN8(111) }; + +enum { + GTD_DT_TOGGLE_CARRY = 0, + GTD_DT_DATA0 = TU_BIT(1) | 0, + GTD_DT_DATA1 = TU_BIT(1) | 1, +}; + +enum { + PID_SETUP = 0, + PID_OUT, + PID_IN, +}; + +enum { + PID_FROM_TD = 0, +}; + //--------------------------------------------------------------------+ // INTERNAL OBJECT & FUNCTION DECLARATION //--------------------------------------------------------------------+ @@ -185,10 +202,10 @@ bool hcd_init(uint8_t rhport) return true; } -uint32_t hcd_uframe_number(uint8_t rhport) +uint32_t hcd_frame_number(uint8_t rhport) { (void) rhport; - return (ohci_data.frame_number_hi << 16 | OHCI_REG->frame_number) << 3; + return (ohci_data.frame_number_hi << 16) | OHCI_REG->frame_number; } @@ -198,7 +215,7 @@ uint32_t hcd_uframe_number(uint8_t rhport) void hcd_port_reset(uint8_t hostid) { (void) hostid; - OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; + OHCI_REG->rhport_status[0] = RHPORT_PORT_RESET_STATUS_MASK; } bool hcd_port_connect_status(uint8_t hostid) @@ -244,16 +261,16 @@ void hcd_device_close(uint8_t rhport, uint8_t dev_addr) //--------------------------------------------------------------------+ //--------------------------------------------------------------------+ -// CONTROL PIPE API +// List Helper //--------------------------------------------------------------------+ static inline tusb_xfer_type_t ed_get_xfer_type(ohci_ed_t const * const p_ed) { - return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : - (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : - (p_ed->is_interrupt_xfer ) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; + return (p_ed->ep_number == 0 ) ? TUSB_XFER_CONTROL : + (p_ed->is_iso ) ? TUSB_XFER_ISOCHRONOUS : + (p_ed->is_interrupt_xfer) ? TUSB_XFER_INTERRUPT : TUSB_XFER_BULK; } -static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, uint8_t endpoint_addr, uint8_t xfer_type, uint8_t interval) +static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t ep_size, uint8_t ep_addr, uint8_t xfer_type, uint8_t interval) { (void) interval; @@ -263,18 +280,18 @@ static void ed_init(ohci_ed_t *p_ed, uint8_t dev_addr, uint16_t max_packet_size, tu_memclr(p_ed, sizeof(ohci_ed_t)); } - p_ed->dev_addr = dev_addr; - p_ed->ep_number = endpoint_addr & 0x0F; - p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? OHCI_PID_SETUP : ( (endpoint_addr & TUSB_DIR_IN_MASK) ? OHCI_PID_IN : OHCI_PID_OUT ); + p_ed->dev_addr = dev_addr; + p_ed->ep_number = ep_addr & 0x0F; + p_ed->pid = (xfer_type == TUSB_XFER_CONTROL) ? PID_FROM_TD : (tu_edpt_dir(ep_addr) ? PID_IN : PID_OUT); p_ed->speed = _usbh_devices[dev_addr].speed; p_ed->is_iso = (xfer_type == TUSB_XFER_ISOCHRONOUS) ? 1 : 0; - p_ed->max_packet_size = max_packet_size; + p_ed->max_packet_size = ep_size; p_ed->used = 1; p_ed->is_interrupt_xfer = (xfer_type == TUSB_XFER_INTERRUPT ? 1 : 0); } -static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) +static void gtd_init(ohci_gtd_t* p_td, uint8_t* data_ptr, uint16_t total_bytes) { tu_memclr(p_td, sizeof(ohci_gtd_t)); @@ -286,81 +303,9 @@ static void gtd_init(ohci_gtd_t* p_td, void* data_ptr, uint16_t total_bytes) p_td->condition_code = OHCI_CCODE_NOT_ACCESSED; p_td->current_buffer_pointer = data_ptr; - p_td->buffer_end = total_bytes ? (((uint8_t*) data_ptr) + total_bytes-1) : NULL; -} - -bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) -{ - (void) rhport; - - ohci_ed_t* p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_setup = &ohci_data.control[dev_addr].gtd; - - gtd_init(p_setup, (void*) setup_packet, 8); - p_setup->index = dev_addr; - p_setup->pid = OHCI_PID_SETUP; - p_setup->data_toggle = TU_BIN8(10); // DATA0 - p_setup->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - //------------- Attach TDs list to Control Endpoint -------------// - p_ed->td_head.address = (uint32_t) p_setup; - - OHCI_REG->command_status_bit.control_list_filled = 1; - - return true; -} - -// TODO move around -static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr); -static ohci_gtd_t * gtd_find_free(void); -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd); - -bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) -{ - (void) rhport; - - uint8_t const epnum = tu_edpt_number(ep_addr); - uint8_t const dir = tu_edpt_dir(ep_addr); - - // FIXME control only for now - if ( epnum == 0 ) - { - ohci_ed_t* const p_ed = &ohci_data.control[dev_addr].ed; - ohci_gtd_t *p_data = &ohci_data.control[dev_addr].gtd; - - gtd_init(p_data, buffer, buflen); - - p_data->index = dev_addr; - p_data->pid = dir ? OHCI_PID_IN : OHCI_PID_OUT; - p_data->data_toggle = TU_BIN8(11); // DATA1 - p_data->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - p_ed->td_head.address = (uint32_t) p_data; - - OHCI_REG->command_status_bit.control_list_filled = 1; - }else - { - ohci_ed_t * p_ed = ed_from_addr(dev_addr, ep_addr); - ohci_gtd_t* p_gtd = gtd_find_free(); - - TU_ASSERT(p_gtd); - - gtd_init(p_gtd, buffer, buflen); - p_gtd->index = p_ed-ohci_data.ed_pool; - p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; - - td_insert_to_ed(p_ed, p_gtd); - - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; - } - - return true; + p_td->buffer_end = total_bytes ? (data_ptr + total_bytes-1) : data_ptr; } -//--------------------------------------------------------------------+ -// BULK/INT/ISO PIPE API -//--------------------------------------------------------------------+ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) { if ( tu_edpt_number(ep_addr) == 0 ) return &ohci_data.control[dev_addr].ed; @@ -370,7 +315,7 @@ static ohci_ed_t * ed_from_addr(uint8_t dev_addr, uint8_t ep_addr) for(uint32_t i=0; i<HCD_MAX_ENDPOINT; i++) { if ( (ed_pool[i].dev_addr == dev_addr) && - ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == OHCI_PID_IN) ) + ep_addr == tu_edpt_addr(ed_pool[i].ep_number, ed_pool[i].pid == PID_IN) ) { return &ed_pool[i]; } @@ -420,9 +365,36 @@ static void ed_list_remove_by_addr(ohci_ed_t * p_head, uint8_t dev_addr) } } +static ohci_gtd_t * gtd_find_free(void) +{ + for(uint8_t i=0; i < HCD_MAX_XFER; i++) + { + if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; + } + + return NULL; +} + +static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) +{ + // tail is always NULL + if ( tu_align16(p_ed->td_head.address) == 0 ) + { // TD queue is empty --> head = TD + p_ed->td_head.address |= (uint32_t) p_gtd; + } + else + { // TODO currently only support queue up to 2 TD each endpoint at a time + ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd; + } +} + +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) { - (void) rhport; + (void) rhport; // TODO iso support TU_ASSERT(ep_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); @@ -454,62 +426,65 @@ bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const return true; } -static ohci_gtd_t * gtd_find_free(void) +bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet[8]) { - for(uint8_t i=0; i < HCD_MAX_XFER; i++) - { - if ( !ohci_data.gtd_pool[i].used ) return &ohci_data.gtd_pool[i]; - } + (void) rhport; - return NULL; -} + ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_gtd_t *qtd = &ohci_data.control[dev_addr].gtd; -static void td_insert_to_ed(ohci_ed_t* p_ed, ohci_gtd_t * p_gtd) -{ - // tail is always NULL - if ( tu_align16(p_ed->td_head.address) == 0 ) - { // TD queue is empty --> head = TD - p_ed->td_head.address |= (uint32_t) p_gtd; - } - else - { // TODO currently only support queue up to 2 TD each endpoint at a time - ((ohci_gtd_t*) tu_align16(p_ed->td_head.address))->next = (uint32_t) p_gtd; - } + gtd_init(qtd, (uint8_t*) setup_packet, 8); + qtd->index = dev_addr; + qtd->pid = PID_SETUP; + qtd->data_toggle = GTD_DT_DATA0; + qtd->delay_interrupt = 0; + + //------------- Attach TDs list to Control Endpoint -------------// + ed->td_head.address = (uint32_t) qtd; + + OHCI_REG->command_status_bit.control_list_filled = 1; + + return true; } -static bool pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) +bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * buffer, uint16_t buflen) { - ohci_ed_t* const p_ed = ed_from_addr(dev_addr, ep_addr); + (void) rhport; - // not support ISO yet - TU_VERIFY ( !p_ed->is_iso ); + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); - ohci_gtd_t * const p_gtd = gtd_find_free(); - TU_ASSERT(p_gtd); // not enough gtd + if ( epnum == 0 ) + { + ohci_ed_t* ed = &ohci_data.control[dev_addr].ed; + ohci_gtd_t* gtd = &ohci_data.control[dev_addr].gtd; - gtd_init(p_gtd, buffer, total_bytes); - p_gtd->index = p_ed-ohci_data.ed_pool; + gtd_init(gtd, buffer, buflen); - if ( int_on_complete ) p_gtd->delay_interrupt = OHCI_INT_ON_COMPLETE_YES; + gtd->index = dev_addr; + gtd->pid = dir ? PID_IN : PID_OUT; + gtd->data_toggle = GTD_DT_DATA1; // Both Data and Ack stage start with DATA1 + gtd->delay_interrupt = 0; - td_insert_to_ed(p_ed, p_gtd); + ed->td_head.address = (uint32_t) gtd; - return true; -} + OHCI_REG->command_status_bit.control_list_filled = 1; + }else + { + ohci_ed_t * ed = ed_from_addr(dev_addr, ep_addr); + ohci_gtd_t* gtd = gtd_find_free(); -bool hcd_pipe_queue_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes) -{ - return pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, false); -} + TU_ASSERT(gtd); -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - (void) int_on_complete; - TU_ASSERT( pipe_queue_xfer(dev_addr, ep_addr, buffer, total_bytes, true) ); + gtd_init(gtd, buffer, buflen); + gtd->index = ed-ohci_data.ed_pool; + gtd->delay_interrupt = 0; - tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + td_insert_to_ed(ed, gtd); - if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + tusb_xfer_type_t xfer_type = ed_get_xfer_type( ed_from_addr(dev_addr, ep_addr) ); + if (TUSB_XFER_BULK == xfer_type) OHCI_REG->command_status_bit.bulk_list_filled = 1; + } return true; } @@ -580,7 +555,12 @@ static inline ohci_ed_t* gtd_get_ed(ohci_gtd_t const * const p_qtd) } static inline uint32_t gtd_xfer_byte_left(uint32_t buffer_end, uint32_t current_buffer) -{ // 5.2.9 OHCI sample code +{ + // 5.2.9 OHCI sample code + + // CBP is 0 mean all data is transferred + if (current_buffer == 0) return 0; + return (tu_align4k(buffer_end ^ current_buffer) ? 0x1000 : 0) + tu_offset4k(buffer_end) - tu_offset4k(current_buffer) + 1; } @@ -596,16 +576,16 @@ static void done_queue_isr(uint8_t hostid) { // TODO check if td_head is iso td //------------- Non ISO transfer -------------// - ohci_gtd_t * const p_qtd = (ohci_gtd_t *) td_head; - xfer_result_t const event = (p_qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : - (p_qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; + ohci_gtd_t * const qtd = (ohci_gtd_t *) td_head; + xfer_result_t const event = (qtd->condition_code == OHCI_CCODE_NO_ERROR) ? XFER_RESULT_SUCCESS : + (qtd->condition_code == OHCI_CCODE_STALL) ? XFER_RESULT_STALLED : XFER_RESULT_FAILED; - p_qtd->used = 0; // free TD - if ( (p_qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) + qtd->used = 0; // free TD + if ( (qtd->delay_interrupt == OHCI_INT_ON_COMPLETE_YES) || (event != XFER_RESULT_SUCCESS) ) { - ohci_ed_t * const p_ed = gtd_get_ed(p_qtd); + ohci_ed_t * const ed = gtd_get_ed(qtd); - uint32_t const xferred_bytes = p_qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) p_qtd->buffer_end, (uint32_t) p_qtd->current_buffer_pointer); + uint32_t const xferred_bytes = qtd->expected_bytes - gtd_xfer_byte_left((uint32_t) qtd->buffer_end, (uint32_t) qtd->current_buffer_pointer); // NOTE Assuming the current list is BULK and there is no other EDs in the list has queued TDs. // When there is a error resulting this ED is halted, and this EP still has other queued TD @@ -616,14 +596,14 @@ static void done_queue_isr(uint8_t hostid) // the TailP must be set back to NULL for processing remaining TDs if ((event != XFER_RESULT_SUCCESS)) { - p_ed->td_tail &= 0x0Ful; - p_ed->td_tail |= tu_align16(p_ed->td_head.address); // mark halted EP as empty queue - if ( event == XFER_RESULT_STALLED ) p_ed->is_stalled = 1; + ed->td_tail &= 0x0Ful; + ed->td_tail |= tu_align16(ed->td_head.address); // mark halted EP as empty queue + if ( event == XFER_RESULT_STALLED ) ed->is_stalled = 1; } - hcd_event_xfer_complete(p_ed->dev_addr, - tu_edpt_addr(p_ed->ep_number, p_ed->pid == OHCI_PID_IN), - xferred_bytes, event, true); + uint8_t dir = (ed->ep_number == 0) ? (qtd->pid == PID_IN) : (ed->pid == PID_IN); + + hcd_event_xfer_complete(ed->dev_addr, tu_edpt_addr(ed->ep_number, dir), xferred_bytes, event, true); } td_head = (ohci_td_item_t*) td_head->next; @@ -646,16 +626,16 @@ void hcd_int_handler(uint8_t hostid) //------------- RootHub status -------------// if ( int_status & OHCI_INT_RHPORT_STATUS_CHANGE_MASK ) { - uint32_t const rhport_status = OHCI_REG->rhport_status[0] & OHCI_RHPORT_ALL_CHANGE_MASK; + uint32_t const rhport_status = OHCI_REG->rhport_status[0] & RHPORT_ALL_CHANGE_MASK; // TODO dual port is not yet supported - if ( rhport_status & OHCI_RHPORT_CONNECT_STATUS_CHANGE_MASK ) + if ( rhport_status & RHPORT_CONNECT_STATUS_CHANGE_MASK ) { // TODO check if remote wake-up if ( OHCI_REG->rhport_status_bit[0].current_connect_status ) { // TODO reset port immediately, without this controller will got 2-3 (debouncing connection status change) - OHCI_REG->rhport_status[0] = OHCI_RHPORT_PORT_RESET_STATUS_MASK; + OHCI_REG->rhport_status[0] = RHPORT_PORT_RESET_STATUS_MASK; hcd_event_device_attach(hostid, true); }else { @@ -663,7 +643,7 @@ void hcd_int_handler(uint8_t hostid) } } - if ( rhport_status & OHCI_RHPORT_PORT_SUSPEND_CHANGE_MASK) + if ( rhport_status & RHPORT_PORT_SUSPEND_CHANGE_MASK) { } @@ -672,7 +652,7 @@ void hcd_int_handler(uint8_t hostid) } //------------- Transfer Complete -------------// - if ( int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) + if (int_status & OHCI_INT_WRITEBACK_DONEHEAD_MASK) { done_queue_isr(hostid); } diff --git a/src/portable/ohci/ohci.h b/src/portable/ohci/ohci.h index 7f9e55b21..6a634592a 100644 --- a/src/portable/ohci/ohci.h +++ b/src/portable/ohci/ohci.h @@ -24,12 +24,6 @@ * This file is part of the TinyUSB stack. */ -/** \ingroup Group_HCD - * @{ - * \defgroup OHCI - * \brief OHCI driver. All documents sources mentioned here (eg section 3.5) is referring to OHCI Specs unless state otherwise - * @{ */ - #ifndef _TUSB_OHCI_H_ #define _TUSB_OHCI_H_ @@ -48,12 +42,6 @@ enum { OHCI_MAX_ITD = 4 }; -enum { - OHCI_PID_SETUP = 0, - OHCI_PID_OUT, - OHCI_PID_IN, -}; - //--------------------------------------------------------------------+ // OHCI Data Structure //--------------------------------------------------------------------+ @@ -73,7 +61,6 @@ typedef struct { uint32_t reserved2; }ohci_td_item_t; - typedef struct TU_ATTR_ALIGNED(16) { // Word 0 @@ -105,7 +92,7 @@ typedef struct TU_ATTR_ALIGNED(16) // Word 0 uint32_t dev_addr : 7; uint32_t ep_number : 4; - uint32_t pid : 2; // 00b from TD, 01b Out, 10b In + uint32_t pid : 2; uint32_t speed : 1; uint32_t skip : 1; uint32_t is_iso : 1; @@ -286,6 +273,3 @@ TU_VERIFY_STATIC( sizeof(ohci_registers_t) == 0x5c, "size is not correct"); #endif #endif /* _TUSB_OHCI_H_ */ - -/** @} */ -/** @} */ diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c index 7731078b5..0048270a6 100644 --- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c @@ -35,8 +35,6 @@ #include "pico/fix/rp2040_usb_device_enumeration.h" #endif -#include "osal/osal.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ diff --git a/src/portable/raspberrypi/rp2040/hcd_rp2040.c b/src/portable/raspberrypi/rp2040/hcd_rp2040.c index 5201d1d4c..3c62b5732 100644 --- a/src/portable/raspberrypi/rp2040/hcd_rp2040.c +++ b/src/portable/raspberrypi/rp2040/hcd_rp2040.c @@ -212,6 +212,7 @@ static void hcd_rp2040_irq(void) if (status & USB_INTS_BUFF_STATUS_BITS) { handled |= USB_INTS_BUFF_STATUS_BITS; + // print_bufctrl32(*epx.buffer_control); hw_handle_buff_status(); } @@ -233,6 +234,7 @@ static void hcd_rp2040_irq(void) if (status & USB_INTS_ERROR_DATA_SEQ_BITS) { usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS; + // print_bufctrl32(*epx.buffer_control); panic("Data Seq Error \n"); } @@ -294,7 +296,6 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t dev_addr, uint8_t uint8_t const num = tu_edpt_number(ep_addr); tusb_dir_t const dir = tu_edpt_dir(ep_addr); - bool in = ep_addr & TUSB_DIR_IN_MASK; ep->ep_addr = ep_addr; ep->dev_addr = dev_addr; @@ -452,6 +453,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t * if (ep_addr != ep->ep_addr) { // Direction has flipped so re init it but with same properties + // TODO treat IN and OUT as invidual endpoints _hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0); } @@ -501,10 +503,9 @@ bool hcd_setup_send(uint8_t rhport, uint8_t dev_addr, uint8_t const setup_packet return true; } -uint32_t hcd_uframe_number(uint8_t rhport) +uint32_t hcd_frame_number(uint8_t rhport) { - // Microframe number is (125us) but we are max full speed so return miliseconds * 8 - return usb_hw->sof_rd * 8; + return usb_hw->sof_rd; } bool hcd_edpt_open(uint8_t rhport, uint8_t dev_addr, tusb_desc_endpoint_t const * ep_desc) @@ -531,6 +532,7 @@ bool hcd_edpt_busy(uint8_t dev_addr, uint8_t ep_addr) bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr) { panic("hcd_pipe_stalled"); + return false; } bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) @@ -539,14 +541,4 @@ bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr) return true; } -bool hcd_pipe_xfer(uint8_t dev_addr, uint8_t ep_addr, uint8_t buffer[], uint16_t total_bytes, bool int_on_complete) -{ - pico_trace("hcd_pipe_xfer dev_addr %d, ep_addr 0x%x, total_bytes %d, int_on_complete %d\n", - dev_addr, ep_addr, total_bytes, int_on_complete); - - // Same logic as hcd_edpt_xfer as far as I am concerned - hcd_edpt_xfer(0, dev_addr, ep_addr, buffer, total_bytes); - - return true; -} #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c index 98ffea9a3..a0263612f 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.c +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c @@ -46,7 +46,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) { #if TUSB_OPT_HOST_ENABLED static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep) { - ep->last_buf = ep->len + ep->transfer_size == ep->total_len; + ep->last_buf = (ep->len + ep->transfer_size == ep->total_len); } #endif @@ -126,8 +126,30 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) // PID val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID; + +#if TUSB_OPT_DEVICE_ENABLED ep->next_pid ^= 1u; +#else + // For Host (also device but since we dictate the endpoint size, following scenario does not occur) + // Next PID depends on the number of packet in case wMaxPacketSize < 64 (e.g Interrupt Endpoint 8, or 12) + // Special case with control status stage where PID is always DATA1 + if ( ep->transfer_size == 0 ) + { + // ZLP also toggle data + ep->next_pid ^= 1u; + }else + { + uint32_t packet_count = 1 + ((ep->transfer_size - 1) / ep->wMaxPacketSize); + + if ( packet_count & 0x01 ) + { + ep->next_pid ^= 1u; + } + } +#endif + + #if TUSB_OPT_HOST_ENABLED // Is this the last buffer? Only really matters for host mode. Will trigger // the trans complete irq but also stop it polling. We only really care about @@ -143,6 +165,7 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep) // the next time the controller polls this dpram address _hw_endpoint_buffer_control_set_value32(ep, val); pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, val); + //print_bufctrl16(val); } @@ -161,7 +184,10 @@ void _hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t t // Fill in info now that we're kicking off the hw ep->total_len = total_len; ep->len = 0; - ep->transfer_size = tu_min16(total_len, ep->wMaxPacketSize); + + // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0) + ep->transfer_size = tu_min16(total_len, tu_max16(64, ep->wMaxPacketSize)); + ep->active = true; ep->user_buf = buffer; #if TUSB_OPT_HOST_ENABLED @@ -185,11 +211,16 @@ void _hw_endpoint_xfer_sync(struct hw_endpoint *ep) uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK; #if TUSB_OPT_HOST_ENABLED + // RP2040-E4 // tag::host_buf_sel_fix[] + // TODO need changes to support double buffering if (ep->buf_sel == 1) { // Host can erroneously write status to top half of buf_ctrl register buf_ctrl = buf_ctrl >> 16; + + // update buf1 -> buf0 to prevent panic with "already available" + *ep->buffer_control = buf_ctrl; } // Flip buf sel for host ep->buf_sel ^= 1u; @@ -240,8 +271,9 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep) _hw_endpoint_xfer_sync(ep); // Now we have synced our state with the hardware. Is there more data to transfer? + // Limit by packet size but not less 64 (i.e low speed 8 bytes EP0) uint16_t remaining_bytes = ep->total_len - ep->len; - ep->transfer_size = tu_min16(remaining_bytes, ep->wMaxPacketSize); + ep->transfer_size = tu_min16(remaining_bytes, tu_max16(64, ep->wMaxPacketSize)); #if TUSB_OPT_HOST_ENABLED _hw_endpoint_update_last_buf(ep); #endif diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h index bb88d977f..33f3ecd41 100644 --- a/src/portable/raspberrypi/rp2040/rp2040_usb.h +++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h @@ -16,8 +16,6 @@ #define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX #endif -// For memset -#include <string.h> #if false && !defined(NDEBUG) #define pico_trace(format,args...) printf(format, ## args) @@ -78,7 +76,7 @@ struct hw_endpoint #if TUSB_OPT_HOST_ENABLED // Only needed for host mode bool last_buf; - // HOST BUG. Host will incorrect write status to top half of buffer + // RP2040-E4: HOST BUG. Host will incorrect write status to top half of buffer // control register when doing transfers > 1 packet uint8_t buf_sel; // Only needed for host @@ -119,4 +117,44 @@ static inline uintptr_t hw_data_offset(uint8_t *buf) extern const char *ep_dir_string[]; +typedef union TU_ATTR_PACKED +{ + uint16_t u16; + struct TU_ATTR_PACKED + { + uint16_t xfer_len : 10; + uint16_t available : 1; + uint16_t stall : 1; + uint16_t reset_bufsel : 1; + uint16_t data_toggle : 1; + uint16_t last_buf : 1; + uint16_t full : 1; + }; +} rp2040_buffer_control_t; + +TU_VERIFY_STATIC(sizeof(rp2040_buffer_control_t) == 2, "size is not correct"); + +static inline void print_bufctrl16(uint32_t __unused u16) +{ + rp2040_buffer_control_t __unused bufctrl = { + .u16 = u16 + }; + + TU_LOG(2, "len = %u, available = %u, stall = %u, reset = %u, toggle = %u, last = %u, full = %u\r\n", + bufctrl.xfer_len, bufctrl.available, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle, bufctrl.last_buf, bufctrl.full); +} + +static inline void print_bufctrl32(uint32_t u32) +{ + uint16_t u16; + + u16 = u32 >> 16; + TU_LOG(2, "Buffer Control 1 0x%x: ", u16); + print_bufctrl16(u16); + + u16 = u32 & 0x0000ffff; + TU_LOG(2, "Buffer Control 0 0x%x: ", u16); + print_bufctrl16(u16); +} + #endif diff --git a/src/portable/sony/cxd56/dcd_cxd56.c b/src/portable/sony/cxd56/dcd_cxd56.c index 54958182b..834976468 100644 --- a/src/portable/sony/cxd56/dcd_cxd56.c +++ b/src/portable/sony/cxd56/dcd_cxd56.c @@ -33,7 +33,6 @@ #include <nuttx/arch.h> #include "device/dcd.h" -#include "osal/osal.h" #define CXD56_EPNUM (7) #define CXD56_SETUP_QUEUE_DEPTH (4) diff --git a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c index 0b7605a73..74c144107 100644 --- a/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c +++ b/src/portable/st/stm32_fsdev/dcd_stm32_fsdev.c @@ -120,7 +120,6 @@ // Some definitions are copied to our private include file. #undef USE_HAL_DRIVER -#include "common/tusb_fifo.h" #include "device/dcd.h" #include "portable/st/stm32_fsdev/dcd_stm32_fsdev_pvt_st.h" diff --git a/src/portable/st/synopsys/dcd_synopsys.c b/src/portable/st/synopsys/dcd_synopsys.c index 76f5c6050..8a196e061 100644 --- a/src/portable/st/synopsys/dcd_synopsys.c +++ b/src/portable/st/synopsys/dcd_synopsys.c @@ -94,10 +94,8 @@ #else #error "Unsupported MCUs" - #endif -#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/template/dcd_template.c b/src/portable/template/dcd_template.c index 92a9f3144..12b9144bf 100644 --- a/src/portable/template/dcd_template.c +++ b/src/portable/template/dcd_template.c @@ -28,7 +28,6 @@ #if CFG_TUSB_MCU == OPT_MCU_NONE -#include "common/tusb_fifo.h" #include "device/dcd.h" //--------------------------------------------------------------------+ diff --git a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c index e13ee697e..027ed26c9 100644 --- a/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c +++ b/src/portable/ti/msp430x5xx/dcd_msp430x5xx.c @@ -30,7 +30,6 @@ #if TUSB_OPT_DEVICE_ENABLED && ( CFG_TUSB_MCU == OPT_MCU_MSP430x5xx ) #include "msp430.h" -#include "common/tusb_fifo.h" #include "device/dcd.h" /*------------------------------------------------------------------*/ |
