diff options
Diffstat (limited to 'src/portable/nxp')
| -rw-r--r-- | src/portable/nxp/khci/dcd_khci.c | 6 | ||||
| -rw-r--r-- | src/portable/nxp/khci/hcd_khci.c | 4 | ||||
| -rw-r--r-- | src/portable/nxp/lpc17_40/dcd_lpc17_40.c | 2 | ||||
| -rw-r--r-- | src/portable/nxp/lpc17_40/dcd_lpc17_40.h | 2 | ||||
| -rw-r--r-- | src/portable/nxp/lpc17_40/hcd_lpc17_40.c | 3 | ||||
| -rw-r--r-- | src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c | 134 | ||||
| -rw-r--r-- | src/portable/nxp/transdimension/common_transdimension.h | 2 | ||||
| -rw-r--r-- | src/portable/nxp/transdimension/dcd_transdimension.c | 2 | ||||
| -rw-r--r-- | src/portable/nxp/transdimension/hcd_transdimension.c | 2 |
9 files changed, 91 insertions, 66 deletions
diff --git a/src/portable/nxp/khci/dcd_khci.c b/src/portable/nxp/khci/dcd_khci.c index 13eb105cd..b6daec3de 100644 --- a/src/portable/nxp/khci/dcd_khci.c +++ b/src/portable/nxp/khci/dcd_khci.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2020 Koji Kitayama @@ -296,7 +296,7 @@ void dcd_int_disable(uint8_t rhport) void dcd_set_address(uint8_t rhport, uint8_t dev_addr) { - _dcd.addr = dev_addr & 0x7F; + _dcd.addr = dev_addr & 0x7F; /* Response with status first before changing device address */ dcd_edpt_xfer(rhport, tu_edpt_addr(0, TUSB_DIR_IN), NULL, 0); } @@ -528,7 +528,7 @@ void dcd_int_handler(uint8_t rhport) if (is & USB_ISTAT_SLEEP_MASK) { // TU_LOG2("Suspend: "); TU_LOG2_HEX(is); - // Note Host usually has extra delay after bus reset (without SOF), which could falsely + // Note Host usually has extra delay after bus reset (without SOF), which could falsely // detected as Sleep event. Though usbd has debouncing logic so we are good KHCI->ISTAT = USB_ISTAT_SLEEP_MASK; process_bus_sleep(rhport); diff --git a/src/portable/nxp/khci/hcd_khci.c b/src/portable/nxp/khci/hcd_khci.c index 0f5fa6275..35763f121 100644 --- a/src/portable/nxp/khci/hcd_khci.c +++ b/src/portable/nxp/khci/hcd_khci.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2021 Koji Kitayama @@ -414,7 +414,7 @@ void hcd_int_disable(uint8_t rhport) uint32_t hcd_frame_number(uint8_t rhport) { (void)rhport; - /* The device must be reset at least once after connection + /* The device must be reset at least once after connection * in order to start the frame counter. */ if (_hcd.need_reset) hcd_port_reset(rhport); uint32_t frmnum = KHCI->FRMNUML; diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c index 0894a5eeb..86149afd8 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h index 07daa32e4..654b80866 100644 --- a/src/portable/nxp/lpc17_40/dcd_lpc17_40.h +++ b/src/portable/nxp/lpc17_40/dcd_lpc17_40.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) diff --git a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c index ad9ed59b4..372dcf51f 100644 --- a/src/portable/nxp/lpc17_40/hcd_lpc17_40.c +++ b/src/portable/nxp/lpc17_40/hcd_lpc17_40.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019, Ha Thach (tinyusb.org) @@ -44,4 +44,3 @@ void hcd_int_disable(uint8_t rhport) } #endif - diff --git a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c index 09ebf3b0d..5368ef868 100644 --- a/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c +++ b/src/portable/nxp/lpc_ip3511/dcd_lpc_ip3511.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) @@ -78,8 +78,10 @@ typedef struct { // Max nbytes for each control/bulk/interrupt transfer enum { - NBYTES_CBI_FULLSPEED_MAX = 64, - NBYTES_CBI_HIGHSPEED_MAX = 32767 // can be up to all 15-bit, but only tested with 4096 + NBYTES_ISO_FS_MAX = 1023, // FS ISO + NBYTES_ISO_HS_MAX = 1024, // HS ISO + NBYTES_CBI_FS_MAX = 64, // FS control/bulk/interrupt + NBYTES_CBI_HS_MAX = 32767 // can be up to all 15-bit, but only tested with 4096 }; enum { @@ -112,6 +114,8 @@ enum { typedef union TU_ATTR_PACKED { // Full and High speed has different bit layout for buffer_offset and nbytes + // TODO FS/HS layout depends on the max speed of controller e.g + // lpc55s69 PORT0 is only FS but actually has the same layout as HS on port1 // Buffer (aligned 64) = DATABUFSTART [31:22] | buffer_offset [21:6] volatile struct { @@ -135,7 +139,7 @@ typedef union TU_ATTR_PACKED uint32_t stall : 1 ; uint32_t disable : 1 ; uint32_t active : 1 ; - }; + } cmd_sts; }ep_cmd_sts_t; TU_VERIFY_STATIC( sizeof(ep_cmd_sts_t) == 4, "size is not correct" ); @@ -175,6 +179,9 @@ typedef struct // Use CFG_TUSB_MEM_SECTION to place it accordingly. CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(256) static dcd_data_t _dcd; +// Dummy buffer to fix ZLPs overwriting the buffer (probably an USB/DMA controller bug) +CFG_TUSB_MEM_SECTION TU_ATTR_ALIGNED(64) static uint8_t dummy[8]; + //--------------------------------------------------------------------+ // Multiple Controllers //--------------------------------------------------------------------+ @@ -225,8 +232,36 @@ static inline uint8_t ep_addr2id(uint8_t ep_addr) //--------------------------------------------------------------------+ // CONTROLLER API //--------------------------------------------------------------------+ + +static void prepare_setup_packet(uint8_t rhport) +{ + if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) + { + _dcd.ep[0][1].buffer_fs.offset = get_buf_offset(_dcd.setup_packet); + }else + { + _dcd.ep[0][1].buffer_hs.offset = get_buf_offset(_dcd.setup_packet); + } +} + +static void edpt_reset(uint8_t rhport, uint8_t ep_id) +{ + (void) rhport; + tu_memclr(&_dcd.ep[ep_id], sizeof(_dcd.ep[ep_id])); +} + +static void edpt_reset_all(uint8_t rhport) +{ + for (uint8_t ep_id = 0; ep_id < 2*_dcd_controller[rhport].ep_pairs; ++ep_id) + { + edpt_reset(rhport, ep_id); + } + prepare_setup_packet(rhport); +} void dcd_init(uint8_t rhport) { + edpt_reset_all(rhport); + dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; dcd_reg->EPLISTSTART = (uint32_t) _dcd.ep; @@ -294,7 +329,7 @@ void dcd_edpt_stall(uint8_t rhport, uint8_t ep_addr) // TODO cannot able to STALL Control OUT endpoint !!!!! FIXME try some walk-around uint8_t const ep_id = ep_addr2id(ep_addr); - _dcd.ep[ep_id][0].stall = 1; + _dcd.ep[ep_id][0].cmd_sts.stall = 1; } void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) @@ -303,26 +338,21 @@ void dcd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) uint8_t const ep_id = ep_addr2id(ep_addr); - _dcd.ep[ep_id][0].stall = 0; - _dcd.ep[ep_id][0].toggle_reset = 1; - _dcd.ep[ep_id][0].toggle_mode = 0; + _dcd.ep[ep_id][0].cmd_sts.stall = 0; + _dcd.ep[ep_id][0].cmd_sts.toggle_reset = 1; + _dcd.ep[ep_id][0].cmd_sts.toggle_mode = 0; } bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) { - (void) rhport; - - // TODO not support ISO yet - TU_VERIFY(p_endpoint_desc->bmAttributes.xfer != TUSB_XFER_ISOCHRONOUS); - //------------- Prepare Queue Head -------------// uint8_t ep_id = ep_addr2id(p_endpoint_desc->bEndpointAddress); // Check if endpoint is available - TU_ASSERT( _dcd.ep[ep_id][0].disable && _dcd.ep[ep_id][1].disable ); + TU_ASSERT( _dcd.ep[ep_id][0].cmd_sts.disable && _dcd.ep[ep_id][1].cmd_sts.disable ); - tu_memclr(_dcd.ep[ep_id], 2*sizeof(ep_cmd_sts_t)); - _dcd.ep[ep_id][0].is_iso = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); + edpt_reset(rhport, ep_id); + _dcd.ep[ep_id][0].cmd_sts.is_iso = (p_endpoint_desc->bmAttributes.xfer == TUSB_XFER_ISOCHRONOUS); // Enable EP interrupt dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; @@ -333,19 +363,20 @@ bool dcd_edpt_open(uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc) void dcd_edpt_close_all (uint8_t rhport) { - (void) rhport; - // TODO implement dcd_edpt_close_all() + for (uint8_t ep_id = 0; ep_id < 2*_dcd_controller[rhport].ep_pairs; ++ep_id) + { + _dcd.ep[ep_id][0].cmd_sts.active = _dcd.ep[ep_id][0].cmd_sts.active = 0; // TODO proper way is to EPSKIP then wait ep[][].active then write ep[][].disable (see table 778 in LPC55S69 Use Manual) + _dcd.ep[ep_id][0].cmd_sts.disable = _dcd.ep[ep_id][1].cmd_sts.disable = 1; + } } -static void prepare_setup_packet(uint8_t rhport) +void dcd_edpt_close(uint8_t rhport, uint8_t ep_addr) { - if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) - { - _dcd.ep[0][1].buffer_fs.offset = get_buf_offset(_dcd.setup_packet);; - }else - { - _dcd.ep[0][1].buffer_hs.offset = get_buf_offset(_dcd.setup_packet);; - } + (void) rhport; + + uint8_t ep_id = ep_addr2id(ep_addr); + _dcd.ep[ep_id][0].cmd_sts.active = _dcd.ep[ep_id][0].cmd_sts.active = 0; // TODO proper way is to EPSKIP then wait ep[][].active then write ep[][].disable (see table 778 in LPC55S69 Use Manual) + _dcd.ep[ep_id][0].cmd_sts.disable = _dcd.ep[ep_id][1].cmd_sts.disable = 1; } static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, uint16_t total_bytes) @@ -354,31 +385,36 @@ static void prepare_ep_xfer(uint8_t rhport, uint8_t ep_id, uint16_t buf_offset, if (_dcd_controller[rhport].max_speed == TUSB_SPEED_FULL ) { - // TODO ISO FullSpeed can have up to 1023 bytes - nbytes = tu_min16(total_bytes, NBYTES_CBI_FULLSPEED_MAX); + nbytes = tu_min16(total_bytes, _dcd.ep[ep_id][0].cmd_sts.is_iso ? NBYTES_ISO_FS_MAX : NBYTES_CBI_FS_MAX); _dcd.ep[ep_id][0].buffer_fs.offset = buf_offset; _dcd.ep[ep_id][0].buffer_fs.nbytes = nbytes; }else { - nbytes = tu_min16(total_bytes, NBYTES_CBI_HIGHSPEED_MAX); + nbytes = tu_min16(total_bytes, NBYTES_CBI_HS_MAX); _dcd.ep[ep_id][0].buffer_hs.offset = buf_offset; _dcd.ep[ep_id][0].buffer_hs.nbytes = nbytes; } _dcd.dma[ep_id].nbytes = nbytes; - _dcd.ep[ep_id][0].active = 1; + _dcd.ep[ep_id][0].cmd_sts.active = 1; } bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t total_bytes) { - (void) rhport; - uint8_t const ep_id = ep_addr2id(ep_addr); tu_memclr(&_dcd.dma[ep_id], sizeof(xfer_dma_t)); _dcd.dma[ep_id].total_bytes = total_bytes; + if (!buffer) + { + // Although having no data, ZLPs can cause buffer overwritten to zeroes. + // Probably due to USB/DMA controller side effect/bug. + // Assigned buffer offset to (valid) dummy to prevent overwriting to DATABUFSTART + buffer = (uint8_t*)(uint32_t)dummy; + } + prepare_ep_xfer(rhport, ep_id, get_buf_offset(buffer), total_bytes); return true; @@ -390,15 +426,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t* buffer, uint16_t to static void bus_reset(uint8_t rhport) { tu_memclr(&_dcd, sizeof(dcd_data_t)); + edpt_reset_all(rhport); - // disable all non-control endpoints on bus reset - for(uint8_t ep_id = 2; ep_id < 2*MAX_EP_PAIRS; ep_id++) + // disable all endpoints as specified by LPC55S69 UM Table 778 + for(uint8_t ep_id = 0; ep_id < 2*MAX_EP_PAIRS; ep_id++) { - _dcd.ep[ep_id][0].disable = _dcd.ep[ep_id][1].disable = 1; + _dcd.ep[ep_id][0].cmd_sts.disable = _dcd.ep[ep_id][1].cmd_sts.disable = 1; } - prepare_setup_packet(rhport); - dcd_registers_t* dcd_reg = _dcd_controller[rhport].regs; dcd_reg->EPINUSE = 0; @@ -424,7 +459,7 @@ static void process_xfer_isr(uint8_t rhport, uint32_t int_status) if ( ep_id == 0 || ep_id == 1) { // For control endpoint, we need to manually clear Active bit - ep_cs->active = 0; + ep_cs->cmd_sts.active = 0; } uint16_t buf_offset; @@ -506,31 +541,23 @@ void dcd_int_handler(uint8_t rhport) } } - // TODO support suspend & resume if (cmd_stat & CMDSTAT_SUSPEND_CHANGE_MASK) { - if (cmd_stat & CMDSTAT_DEVICE_SUSPEND_MASK) - { // suspend signal, bus idle for more than 3ms - // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. - if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK) - { - dcd_event_bus_signal(rhport, DCD_EVENT_SUSPEND, true); - } + // suspend signal, bus idle for more than 3ms + // Note: Host may delay more than 3 ms before and/or after bus reset before doing enumeration. + if (cmd_stat & CMDSTAT_DEVICE_ADDR_MASK) + { + dcd_event_bus_signal(rhport, (cmd_stat & CMDSTAT_DEVICE_SUSPEND_MASK) ? DCD_EVENT_SUSPEND : DCD_EVENT_RESUME, true); } } -// else -// { // resume signal -// dcd_event_bus_signal(rhport, DCD_EVENT_RESUME, true); -// } -// } } // Setup Receive if ( tu_bit_test(int_status, 0) && (cmd_stat & CMDSTAT_SETUP_RECEIVED_MASK) ) { // Follow UM flowchart to clear Active & Stall on both Control IN/OUT endpoints - _dcd.ep[0][0].active = _dcd.ep[1][0].active = 0; - _dcd.ep[0][0].stall = _dcd.ep[1][0].stall = 0; + _dcd.ep[0][0].cmd_sts.active = _dcd.ep[1][0].cmd_sts.active = 0; + _dcd.ep[0][0].cmd_sts.stall = _dcd.ep[1][0].cmd_sts.stall = 0; dcd_reg->DEVCMDSTAT |= CMDSTAT_SETUP_RECEIVED_MASK; @@ -548,4 +575,3 @@ void dcd_int_handler(uint8_t rhport) } #endif - diff --git a/src/portable/nxp/transdimension/common_transdimension.h b/src/portable/nxp/transdimension/common_transdimension.h index 69074de41..95ae1903e 100644 --- a/src/portable/nxp/transdimension/common_transdimension.h +++ b/src/portable/nxp/transdimension/common_transdimension.h @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2021, Ha Thach (tinyusb.org) diff --git a/src/portable/nxp/transdimension/dcd_transdimension.c b/src/portable/nxp/transdimension/dcd_transdimension.c index 1f27a6872..983d7cfcf 100644 --- a/src/portable/nxp/transdimension/dcd_transdimension.c +++ b/src/portable/nxp/transdimension/dcd_transdimension.c @@ -569,7 +569,7 @@ static void process_edpt_complete_isr(uint8_t rhport, uint8_t epnum, uint8_t dir tu_fifo_advance_write_pointer(p_qhd->ff, xferred_bytes); } } - + // only number of bytes in the IOC qtd dcd_event_xfer_complete(rhport, tu_edpt_addr(epnum, dir), xferred_bytes, result, true); } diff --git a/src/portable/nxp/transdimension/hcd_transdimension.c b/src/portable/nxp/transdimension/hcd_transdimension.c index 392764ff6..0b3e9e4ef 100644 --- a/src/portable/nxp/transdimension/hcd_transdimension.c +++ b/src/portable/nxp/transdimension/hcd_transdimension.c @@ -1,4 +1,4 @@ -/* +/* * The MIT License (MIT) * * Copyright (c) 2019 Ha Thach (tinyusb.org) |
