From a0307bafdaa97628bb5e4d5e476db54cbc028d33 Mon Sep 17 00:00:00 2001 From: hathach Date: Wed, 29 May 2019 16:55:15 +0700 Subject: added usbd_edpt_xfer/usbd_edpt_busy to replace dcd_edpt_transfer/dcd_edpt_busy() - improve fifo write/read_n with only one lock - use usbd_edpt_xfer/usbd_edpt_busy for hid/cdc/msc class driver - replace cdc read's pending_read_from_host by usbd_edpt_busy() --- src/device/dcd.h | 23 +++++++++++++---------- src/device/usbd.c | 43 ++++++++++++++++++++++++++++++++++++------- src/device/usbd_pvt.h | 11 +++++++++-- 3 files changed, 58 insertions(+), 19 deletions(-) (limited to 'src/device') diff --git a/src/device/dcd.h b/src/device/dcd.h index 35164ac62..bd7088fe4 100644 --- a/src/device/dcd.h +++ b/src/device/dcd.h @@ -100,25 +100,28 @@ void dcd_set_config (uint8_t rhport, uint8_t config_num); // Wake up host void dcd_remote_wakeup(uint8_t rhport); -/*------------------------------------------------------------------*/ -/* Endpoint API - * - open : Configure endpoint's registers - * - xfer : Submit a transfer. When complete dcd_event_xfer_complete - * must be called to notify the stack - * - busy : Check if endpoint transferring is complete (TODO remove) - * - stall : stall endpoint - * - clear_stall : clear stall, data toggle is also reset to DATA0 - *------------------------------------------------------------------*/ +//--------------------------------------------------------------------+ +// Endpoint API +//--------------------------------------------------------------------+ + +// Configure endpoint's registers according to descriptor bool dcd_edpt_open (uint8_t rhport, tusb_desc_endpoint_t const * p_endpoint_desc); + +// Submit a transfer, When complete dcd_event_xfer_complete() is invoked to notify the stack bool dcd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Check if endpoint transferring is complete (TODO remove) bool dcd_edpt_busy (uint8_t rhport, uint8_t ep_addr); +// Stall endpoint void dcd_edpt_stall (uint8_t rhport, uint8_t ep_addr); + +// clear stall, data toggle is also reset to DATA0 void dcd_edpt_clear_stall (uint8_t rhport, uint8_t ep_addr); /*------------------------------------------------------------------*/ /* Event Function - * Called by DCD to notify USBD + * Called by DCD to notify device stack *------------------------------------------------------------------*/ void dcd_event_handler(dcd_event_t const * event, bool in_isr); diff --git a/src/device/usbd.c b/src/device/usbd.c index 56d895388..e22de4728 100644 --- a/src/device/usbd.c +++ b/src/device/usbd.c @@ -51,8 +51,8 @@ typedef struct { uint8_t self_powered : 1; // configuration descriptor's attribute }; -// uint8_t ep_busy_mask[2]; // bit mask for busy endpoint - uint8_t ep_stall_mask[2]; // bit mask for stalled endpoint + uint8_t ep_busy_map[2]; // bit mask for busy endpoint + uint8_t ep_stall_map[2]; // bit map for stalled endpoint uint8_t itf2drv[16]; // map interface number to driver (0xff is invalid) uint8_t ep2drv[8][2]; // map endpoint to driver ( 0xff is invalid ) @@ -287,6 +287,10 @@ void tud_task (void) { // Invoke the class callback associated with the endpoint address uint8_t const ep_addr = event.xfer_complete.ep_addr; + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + _usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_busy_map[dir], epnum); if ( 0 == tu_edpt_number(ep_addr) ) { @@ -621,7 +625,7 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) case DCD_EVENT_SUSPEND: // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the - // SUSPEND condition ( Idle for 3ms ). Some MCUs such as samd don't distinguish suspend vs disconnect as well. + // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well. // We will skip handling SUSPEND/RESUME event if not currently connected if ( _usbd_dev.connected ) { @@ -643,7 +647,8 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr) break; case DCD_EVENT_XFER_COMPLETE: - // skip zero-length control status complete event, should dcd notifies us. + // skip zero-length control status complete event, should DCD notify us. + // TODO could cause issue with actual zero length data used by class such as DFU if ( (0 == tu_edpt_number(event->xfer_complete.ep_addr)) && (event->xfer_complete.len == 0) ) break; osal_queue_send(_usbd_q, event, in_isr); @@ -733,13 +738,37 @@ void usbd_defer_func(osal_task_func_t func, void* param, bool in_isr) //--------------------------------------------------------------------+ // USBD Endpoint API //--------------------------------------------------------------------+ + +bool usbd_edpt_xfer(uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes) +{ + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + TU_VERIFY( dcd_edpt_xfer(rhport, ep_addr, buffer, total_bytes) ); + + _usbd_dev.ep_busy_map[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_busy_map[dir], epnum); + + return true; +} + +bool usbd_edpt_busy(uint8_t rhport, uint8_t ep_addr) +{ + (void) rhport; + + uint8_t const epnum = tu_edpt_number(ep_addr); + uint8_t const dir = tu_edpt_dir(ep_addr); + + return tu_bit_test(_usbd_dev.ep_busy_map[dir], epnum); +} + + void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr) { uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_stall(rhport, ep_addr); - _usbd_dev.ep_stall_mask[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_stall_mask[dir], epnum); + _usbd_dev.ep_stall_map[dir] = (uint8_t) tu_bit_set(_usbd_dev.ep_stall_map[dir], epnum); } void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) @@ -748,7 +777,7 @@ void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr) uint8_t const dir = tu_edpt_dir(ep_addr); dcd_edpt_clear_stall(rhport, ep_addr); - _usbd_dev.ep_stall_mask[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_stall_mask[dir], epnum); + _usbd_dev.ep_stall_map[dir] = (uint8_t) tu_bit_clear(_usbd_dev.ep_stall_map[dir], epnum); } bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) @@ -758,7 +787,7 @@ bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr) uint8_t const epnum = tu_edpt_number(ep_addr); uint8_t const dir = tu_edpt_dir(ep_addr); - return tu_bit_test(_usbd_dev.ep_stall_mask[dir], epnum); + return tu_bit_test(_usbd_dev.ep_stall_map[dir], epnum); } #endif diff --git a/src/device/usbd_pvt.h b/src/device/usbd_pvt.h index f20532627..706857d45 100644 --- a/src/device/usbd_pvt.h +++ b/src/device/usbd_pvt.h @@ -33,10 +33,11 @@ extern "C" { #endif +bool usbd_init (void); + //--------------------------------------------------------------------+ -// INTERNAL API for stack management +// USBD Endpoint API //--------------------------------------------------------------------+ -bool usbd_init (void); // Carry out Data and Status stage of control transfer // - If len = 0, it is equivalent to sending status only @@ -46,6 +47,12 @@ bool usbd_control_xfer(uint8_t rhport, tusb_control_request_t const * request, v // Send STATUS (zero length) packet bool usbd_control_status(uint8_t rhport, tusb_control_request_t const * request); +// Submit a usb transfer +bool usbd_edpt_xfer (uint8_t rhport, uint8_t ep_addr, uint8_t * buffer, uint16_t total_bytes); + +// Check if endpoint transferring is complete +bool usbd_edpt_busy (uint8_t rhport, uint8_t ep_addr); + void usbd_edpt_stall(uint8_t rhport, uint8_t ep_addr); void usbd_edpt_clear_stall(uint8_t rhport, uint8_t ep_addr); bool usbd_edpt_stalled(uint8_t rhport, uint8_t ep_addr); -- cgit v1.3.1