add e15 prefix or walkaround related functions, also minor refactor

This commit is contained in:
hathach
2023-01-31 14:48:11 +07:00
parent 0cce42fcc6
commit 19b6cbc616
3 changed files with 125 additions and 119 deletions

View File

@@ -254,25 +254,30 @@ static void __tusb_irq_path_func(dcd_rp2040_irq)(void)
handled |= USB_INTF_DEV_SOF_BITS; handled |= USB_INTF_DEV_SOF_BITS;
#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
last_sof = time_us_32(); // Errata 15 Walkaround for Device Bulk-In endpoint
e15_last_sof = time_us_32();
for ( uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++ ) for ( uint8_t i = 0; i < USB_MAX_ENDPOINTS; i++ )
{ {
struct hw_endpoint * ep = hw_endpoint_get_by_num(i, TUSB_DIR_IN); struct hw_endpoint * ep = hw_endpoint_get_by_num(i, TUSB_DIR_IN);
hw_endpoint_lock_update(ep, 1);
// Bulk IN endpoint in a transfer? // Active Bulk IN endpoint requires SOF
if (rp2040_ep_needs_sof(ep) && ep->active) keep_sof_alive = true; if ( (ep->transfer_type == TUSB_XFER_BULK) && ep->active )
{
keep_sof_alive = true;
hw_endpoint_lock_update(ep, 1);
// Deferred enable? // Deferred enable?
if ( ep->pending ) if ( ep->pending )
{ {
hw_endpoint_start_next_buffer(ep);
ep->pending = 0; ep->pending = 0;
hw_endpoint_start_next_buffer(ep);
} }
hw_endpoint_lock_update(ep, -1); hw_endpoint_lock_update(ep, -1);
} }
}
#endif #endif
// disable SOF interrupt if it is used for RESUME in remote wakeup // disable SOF interrupt if it is used for RESUME in remote wakeup

View File

@@ -51,37 +51,41 @@ TU_ATTR_ALWAYS_INLINE static inline bool is_host_mode(void)
//--------------------------------------------------------------------+ //--------------------------------------------------------------------+
#if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
volatile uint32_t last_sof = 0; // Errata 15 Walkaround for Device Bulk-In endpoint to avoid schedule an transfer
// within last 20% of an USB frame.
bool rp2040_critical_frame_period(struct hw_endpoint *ep) volatile uint32_t e15_last_sof = 0;
// check if Errata 15 walkround is needed for this endpoint
static bool __tusb_irq_path_func(e15_is_bulkin_ep) (struct hw_endpoint *ep)
{ {
uint32_t delta; return (!is_host_mode() && tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN &&
ep->transfer_type == TUSB_XFER_BULK);
if (usb_hw->main_ctrl & USB_MAIN_CTRL_HOST_NDEVICE_BITS) return false;
if (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_OUT ||
ep->transfer_type == TUSB_XFER_INTERRUPT ||
ep->transfer_type == TUSB_XFER_ISOCHRONOUS)
{
return false;
} }
// check if we need to apply Errata 15 workaround: ie.g
// Enpoint is BULK IN and is currently in critical frame period i.e 20% of last usb frame
static bool __tusb_irq_path_func(e15_is_critical_frame_period) (struct hw_endpoint *ep)
{
TU_VERIFY(e15_is_bulkin_ep(ep));
/* Avoid the last 200us (uframe 6.5-7) of a frame, up to the EOF2 point. /* Avoid the last 200us (uframe 6.5-7) of a frame, up to the EOF2 point.
* The device state machine cannot recover from receiving an incorrect PID * The device state machine cannot recover from receiving an incorrect PID
* when it is expecting an ACK. * when it is expecting an ACK.
*/ */
delta = time_us_32() - last_sof; uint32_t delta = time_us_32() - e15_last_sof;
if (delta < 800 || delta > 998) { if (delta < 800 || delta > 998) {
return false; return false;
} }
TU_LOG(3, "Avoiding sof %u now %lu last %lu\n", (usb_hw->sof_rd + 1) & USB_SOF_RD_BITS, now, last_sof); TU_LOG(3, "Avoiding sof %u now %lu last %lu\n", (usb_hw->sof_rd + 1) & USB_SOF_RD_BITS, time_us_32(), e15_last_sof);
return true; return true;
} }
bool rp2040_ep_needs_sof(struct hw_endpoint *ep) { #else
return (tu_edpt_dir(ep->ep_addr) == TUSB_DIR_IN &&
ep->transfer_type == TUSB_XFER_BULK); #define e15_is_bulkin_ep(x) false
} #define e15_is_critical_frame_period(x) false
#endif #endif
void rp2040_usb_init(void) void rp2040_usb_init(void)
@@ -249,17 +253,17 @@ void hw_endpoint_xfer_start(struct hw_endpoint *ep, uint8_t *buffer, uint16_t to
ep->active = true; ep->active = true;
ep->user_buf = buffer; ep->user_buf = buffer;
if (rp2040_ep_needs_sof(ep)) if ( e15_is_bulkin_ep(ep) )
{ {
usb_hw_set->inte = USB_INTS_DEV_SOF_BITS; usb_hw_set->inte = USB_INTS_DEV_SOF_BITS;
} }
if(!rp2040_critical_frame_period(ep)) if ( e15_is_critical_frame_period(ep) )
{
hw_endpoint_start_next_buffer(ep);
} else
{ {
ep->pending = 1; ep->pending = 1;
} else
{
hw_endpoint_start_next_buffer(ep);
} }
hw_endpoint_lock_update(ep, -1); hw_endpoint_lock_update(ep, -1);
@@ -356,6 +360,7 @@ static void __tusb_irq_path_func(_hw_endpoint_xfer_sync) (struct hw_endpoint *ep
bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep) bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep)
{ {
hw_endpoint_lock_update(ep, 1); hw_endpoint_lock_update(ep, 1);
// Part way through a transfer // Part way through a transfer
if (!ep->active) if (!ep->active)
{ {
@@ -377,10 +382,12 @@ bool __tusb_irq_path_func(hw_endpoint_xfer_continue)(struct hw_endpoint *ep)
} }
else else
{ {
if(!rp2040_critical_frame_period(ep)) { if ( e15_is_critical_frame_period(ep) )
hw_endpoint_start_next_buffer(ep); {
} else {
ep->pending = 1; ep->pending = 1;
} else
{
hw_endpoint_start_next_buffer(ep);
} }
} }

View File

@@ -93,14 +93,8 @@ typedef struct hw_endpoint
} hw_endpoint_t; } hw_endpoint_t;
#if !TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX #if TUD_OPT_RP2040_USB_DEVICE_UFRAME_FIX
#define rp2040_critical_frame_period(x) false extern volatile uint32_t e15_last_sof;
#define rp2040_ep_needs_sof(x) false
#else
extern volatile uint32_t last_sof;
bool rp2040_critical_frame_period(struct hw_endpoint *ep);
bool rp2040_ep_needs_sof(struct hw_endpoint *ep);
#endif #endif
void rp2040_usb_init(void); void rp2040_usb_init(void);