summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorhathach <[email protected]>2021-06-17 01:55:35 +0700
committerhathach <[email protected]>2021-06-17 01:55:35 +0700
commit832d22d7addf9b1e4b88556c544f60bd9fa32dd6 (patch)
tree44fb76004a6b1557d17651ec87f49fcf03af726a /src
parent5c567129ea34ea78833cee2bf38e4e09cbdee389 (diff)
force single buffered for device mode, out endpoint
Diffstat (limited to 'src')
-rw-r--r--src/device/usbd.c3
-rw-r--r--src/portable/raspberrypi/rp2040/dcd_rp2040.c15
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.c52
-rw-r--r--src/portable/raspberrypi/rp2040/rp2040_usb.h4
4 files changed, 55 insertions, 19 deletions
diff --git a/src/device/usbd.c b/src/device/usbd.c
index 2935defd0..587d487dc 100644
--- a/src/device/usbd.c
+++ b/src/device/usbd.c
@@ -1254,14 +1254,13 @@ bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t
if ( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) )
{
- TU_LOG2("OK\r\n");
return true;
}else
{
// DCD error, mark endpoint as ready to allow next transfer
_usbd_dev.ep_status[epnum][dir].busy = false;
_usbd_dev.ep_status[epnum][dir].claimed = 0;
- TU_LOG2("failed\r\n");
+ TU_LOG2("FAILED\r\n");
TU_BREAKPOINT();
return false;
}
diff --git a/src/portable/raspberrypi/rp2040/dcd_rp2040.c b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
index b87951421..f78a932f1 100644
--- a/src/portable/raspberrypi/rp2040/dcd_rp2040.c
+++ b/src/portable/raspberrypi/rp2040/dcd_rp2040.c
@@ -145,6 +145,7 @@ static void _hw_endpoint_init(struct hw_endpoint *ep, uint8_t ep_addr, uint16_t
// Now if it hasn't already been done
//alloc a buffer and fill in endpoint control register
+ // TODO device may change configuration (dynamic), should clear and reallocate
if(!(ep->configured))
{
_hw_endpoint_alloc(ep);
@@ -194,9 +195,6 @@ static void hw_handle_buff_status(void)
{
if (remaining_buffers & bit)
{
- uint __unused which = (usb_hw->buf_cpu_should_handle & bit) ? 1 : 0;
- // Should be single buffered
- assert(which == 0);
// clear this in advance
usb_hw_clear->buf_status = bit;
// IN transfer for even i, OUT transfer for odd i
@@ -463,7 +461,7 @@ void dcd_edpt0_status_complete(uint8_t rhport, tusb_control_request_t const * re
bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * desc_edpt)
{
- pico_info("dcd_edpt_open %d %02x\n", rhport, desc_edpt->bEndpointAddress);
+ pico_info("dcd_edpt_open %02x\n", desc_edpt->bEndpointAddress);
assert(rhport == 0);
hw_endpoint_init(desc_edpt->bEndpointAddress, desc_edpt->wMaxPacketSize.size, desc_edpt->bmAttributes.xfer);
return true;
@@ -478,14 +476,14 @@ bool dcd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t t
void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr)
{
- pico_trace("dcd_edpt_stall %d %02x\n", rhport, ep_addr);
+ pico_trace("dcd_edpt_stall %02x\n", ep_addr);
assert(rhport == 0);
hw_endpoint_stall(ep_addr);
}
void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
{
- pico_trace("dcd_edpt_clear_stall %d %02x\n", rhport, ep_addr);
+ pico_trace("dcd_edpt_clear_stall %02x\n", ep_addr);
assert(rhport == 0);
hw_endpoint_clear_stall(ep_addr);
}
@@ -493,8 +491,11 @@ void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr)
void dcd_edpt_close (uint8_t rhport, uint8_t ep_addr)
{
+ (void) rhport;
+ (void) ep_addr;
+
// usbd.c says: In progress transfers on this EP may be delivered after this call
- pico_trace("dcd_edpt_close %d %02x\n", rhport, ep_addr);
+ pico_trace("dcd_edpt_close %02x\n", ep_addr);
}
void dcd_int_handler(uint8_t rhport)
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.c b/src/portable/raspberrypi/rp2040/rp2040_usb.c
index 5b2a5f5a0..dc12e6d82 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.c
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.c
@@ -148,10 +148,15 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
{
uint32_t ep_ctrl = *ep->endpoint_control;
- // always compute buffer 0
- uint32_t buf_ctrl = prepare_ep_buffer(ep, 0);
+ // always compute and start with buffer 0
+ uint32_t buf_ctrl = prepare_ep_buffer(ep, 0) | USB_BUF_CTRL_SEL;
- if(ep->remaining_len)
+ // For now: skip double buffered for Device mode, OUT endpoint since
+ // host could send < 64 bytes and cause short packet on buffer0
+ // NOTE this could happen to Host mode IN endpoint
+ bool const force_single = !(usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) && !tu_edpt_dir(ep->ep_addr);
+
+ if(ep->remaining_len && !force_single)
{
// Use buffer 1 (double buffered) if there is still data
// TODO: Isochronous for buffer1 bit-field is different than CBI (control bulk, interrupt)
@@ -181,8 +186,7 @@ static void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t total_len)
{
_hw_endpoint_lock_update(ep, 1);
- pico_trace("Start transfer of total len %d on ep %d %s\n", total_len, tu_edpt_number(ep->ep_addr),
- ep_dir_string[tu_edpt_dir(ep->ep_addr)]);
+
if ( ep->active )
{
// TODO: Is this acceptable for interrupt packets?
@@ -251,10 +255,42 @@ static void _hw_endpoint_xfer_sync (struct hw_endpoint *ep)
// always sync buffer 0
uint16_t buf0_bytes = sync_ep_buffer(ep, 0);
- // sync buffer 1 if double buffered and buffer 0 is not short packet
- if ( ((*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS) && (buf0_bytes == ep->wMaxPacketSize) )
+ // sync buffer 1 if double buffered
+ if ( (*ep->endpoint_control) & EP_CTRL_DOUBLE_BUFFERED_BITS )
{
- sync_ep_buffer(ep, 1);
+ if (buf0_bytes == ep->wMaxPacketSize)
+ {
+ // sync buffer 1 if not short packet
+ sync_ep_buffer(ep, 1);
+ }else
+ {
+ // short packet on buffer 0
+ // TODO couldn't figure out how to handle this case which happen with net_lwip_webserver example
+ // At this time (currently trigger per 2 buffer), the buffer1 is probably filled with data from
+ // the next transfer (not current one). For now we disable double buffered for device OUT
+ // NOTE this could happen to Host IN
+#if 0
+ uint8_t const ep_num = tu_edpt_number(ep->ep_addr);
+ uint8_t const dir = (uint8_t) tu_edpt_dir(ep->ep_addr);
+ uint8_t const ep_id = 2*ep_num + (dir ? 0 : 1);
+
+ // abort queued transfer on buffer 1
+ usb_hw->abort |= TU_BIT(ep_id);
+
+ while ( !(usb_hw->abort_done & TU_BIT(ep_id)) ) {}
+
+ uint32_t ep_ctrl = *ep->endpoint_control;
+ ep_ctrl &= ~(EP_CTRL_DOUBLE_BUFFERED_BITS | EP_CTRL_INTERRUPT_PER_DOUBLE_BUFFER);
+ ep_ctrl |= EP_CTRL_INTERRUPT_PER_BUFFER;
+
+ _hw_endpoint_buffer_control_set_value32(ep, 0);
+
+ usb_hw->abort &= ~TU_BIT(ep_id);
+
+ TU_LOG(3, "----SHORT PACKET buffer0 on EP %02X:\r\n", ep->ep_addr);
+ print_bufctrl32(buf_ctrl);
+#endif
+ }
}
}
diff --git a/src/portable/raspberrypi/rp2040/rp2040_usb.h b/src/portable/raspberrypi/rp2040/rp2040_usb.h
index 4c787f496..514152cd9 100644
--- a/src/portable/raspberrypi/rp2040/rp2040_usb.h
+++ b/src/portable/raspberrypi/rp2040/rp2040_usb.h
@@ -120,8 +120,8 @@ static inline void print_bufctrl16(uint32_t u16)
.u16 = u16
};
- TU_LOG(3, "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);
+ TU_LOG(3, "len = %u, available = %u, full = %u, last = %u, stall = %u, reset = %u, toggle = %u\r\n",
+ bufctrl.xfer_len, bufctrl.available, bufctrl.full, bufctrl.last_buf, bufctrl.stall, bufctrl.reset_bufsel, bufctrl.data_toggle);
}
static inline void print_bufctrl32(uint32_t u32)