mirror of
https://github.com/hathach/tinyusb.git
synced 2025-01-17 05:32:55 +08:00
Merge pull request #862 from hathach/host-rp2040
Fix host rp2040 with low speed device
This commit is contained in:
commit
a6b5e207b2
@ -307,25 +307,40 @@ void tu_print_var(uint8_t const* buf, uint32_t bufsize)
|
|||||||
for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]);
|
for(uint32_t i=0; i<bufsize; i++) tu_printf("%02X ", buf[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Log with debug level 1
|
// Log with Level
|
||||||
|
#define TU_LOG(n, ...) TU_LOG##n(__VA_ARGS__)
|
||||||
|
#define TU_LOG_MEM(n, ...) TU_LOG##n##_MEM(__VA_ARGS__)
|
||||||
|
#define TU_LOG_VAR(n, ...) TU_LOG##n##_VAR(__VA_ARGS__)
|
||||||
|
#define TU_LOG_INT(n, ...) TU_LOG##n##_INT(__VA_ARGS__)
|
||||||
|
#define TU_LOG_HEX(n, ...) TU_LOG##n##_HEX(__VA_ARGS__)
|
||||||
|
#define TU_LOG_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
|
||||||
|
#define TU_LOG_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
|
||||||
|
|
||||||
|
|
||||||
|
// Log Level 1: Error
|
||||||
#define TU_LOG1 tu_printf
|
#define TU_LOG1 tu_printf
|
||||||
#define TU_LOG1_MEM tu_print_mem
|
#define TU_LOG1_MEM tu_print_mem
|
||||||
#define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
|
#define TU_LOG1_VAR(_x) tu_print_var((uint8_t const*)(_x), sizeof(*(_x)))
|
||||||
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) )
|
#define TU_LOG1_INT(_x) tu_printf(#_x " = %ld\n", (uint32_t) (_x) )
|
||||||
#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) )
|
#define TU_LOG1_HEX(_x) tu_printf(#_x " = %lX\n", (uint32_t) (_x) )
|
||||||
#define TU_LOG1_LOCATION() tu_printf("%s: %d:\r\n", __PRETTY_FUNCTION__, __LINE__)
|
|
||||||
#define TU_LOG1_FAILED() tu_printf("%s: %d: Failed\r\n", __PRETTY_FUNCTION__, __LINE__)
|
|
||||||
|
|
||||||
// Log with debug level 2
|
// Log Level 2: Warn
|
||||||
#if CFG_TUSB_DEBUG > 1
|
#if CFG_TUSB_DEBUG >= 2
|
||||||
#define TU_LOG2 TU_LOG1
|
#define TU_LOG2 TU_LOG1
|
||||||
#define TU_LOG2_MEM TU_LOG1_MEM
|
#define TU_LOG2_MEM TU_LOG1_MEM
|
||||||
#define TU_LOG2_VAR TU_LOG1_VAR
|
#define TU_LOG2_VAR TU_LOG1_VAR
|
||||||
#define TU_LOG2_INT TU_LOG1_INT
|
#define TU_LOG2_INT TU_LOG1_INT
|
||||||
#define TU_LOG2_HEX TU_LOG1_HEX
|
#define TU_LOG2_HEX TU_LOG1_HEX
|
||||||
#define TU_LOG2_LOCATION() TU_LOG1_LOCATION()
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Log Level 3: Info
|
||||||
|
#if CFG_TUSB_DEBUG >= 3
|
||||||
|
#define TU_LOG3 TU_LOG1
|
||||||
|
#define TU_LOG3_MEM TU_LOG1_MEM
|
||||||
|
#define TU_LOG3_VAR TU_LOG1_VAR
|
||||||
|
#define TU_LOG3_INT TU_LOG1_INT
|
||||||
|
#define TU_LOG3_HEX TU_LOG1_HEX
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
@ -370,6 +385,15 @@ static inline const char* tu_lookup_find(tu_lookup_table_t const* p_table, uint3
|
|||||||
#define TU_LOG2_LOCATION()
|
#define TU_LOG2_LOCATION()
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef TU_LOG3
|
||||||
|
#define TU_LOG3(...)
|
||||||
|
#define TU_LOG3_MEM(...)
|
||||||
|
#define TU_LOG3_VAR(...)
|
||||||
|
#define TU_LOG3_INT(...)
|
||||||
|
#define TU_LOG3_HEX(...)
|
||||||
|
#define TU_LOG3_LOCATION()
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -212,6 +212,7 @@ static void hcd_rp2040_irq(void)
|
|||||||
if (status & USB_INTS_BUFF_STATUS_BITS)
|
if (status & USB_INTS_BUFF_STATUS_BITS)
|
||||||
{
|
{
|
||||||
handled |= USB_INTS_BUFF_STATUS_BITS;
|
handled |= USB_INTS_BUFF_STATUS_BITS;
|
||||||
|
// print_bufctrl32(*epx.buffer_control);
|
||||||
hw_handle_buff_status();
|
hw_handle_buff_status();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -233,6 +234,7 @@ static void hcd_rp2040_irq(void)
|
|||||||
if (status & USB_INTS_ERROR_DATA_SEQ_BITS)
|
if (status & USB_INTS_ERROR_DATA_SEQ_BITS)
|
||||||
{
|
{
|
||||||
usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
|
usb_hw_clear->sie_status = USB_SIE_STATUS_DATA_SEQ_ERROR_BITS;
|
||||||
|
// print_bufctrl32(*epx.buffer_control);
|
||||||
panic("Data Seq Error \n");
|
panic("Data Seq Error \n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -452,6 +454,7 @@ bool hcd_edpt_xfer(uint8_t rhport, uint8_t dev_addr, uint8_t ep_addr, uint8_t *
|
|||||||
if (ep_addr != ep->ep_addr)
|
if (ep_addr != ep->ep_addr)
|
||||||
{
|
{
|
||||||
// Direction has flipped so re init it but with same properties
|
// 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);
|
_hw_endpoint_init(ep, dev_addr, ep_addr, ep->wMaxPacketSize, ep->transfer_type, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,6 +534,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)
|
bool hcd_edpt_stalled(uint8_t dev_addr, uint8_t ep_addr)
|
||||||
{
|
{
|
||||||
panic("hcd_pipe_stalled");
|
panic("hcd_pipe_stalled");
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
|
bool hcd_edpt_clear_stall(uint8_t dev_addr, uint8_t ep_addr)
|
||||||
|
@ -46,7 +46,7 @@ static inline void _hw_endpoint_lock_update(struct hw_endpoint *ep, int delta) {
|
|||||||
#if TUSB_OPT_HOST_ENABLED
|
#if TUSB_OPT_HOST_ENABLED
|
||||||
static inline void _hw_endpoint_update_last_buf(struct hw_endpoint *ep)
|
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
|
#endif
|
||||||
|
|
||||||
@ -126,8 +126,30 @@ void _hw_endpoint_start_next_buffer(struct hw_endpoint *ep)
|
|||||||
|
|
||||||
// PID
|
// PID
|
||||||
val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
|
val |= ep->next_pid ? USB_BUF_CTRL_DATA1_PID : USB_BUF_CTRL_DATA0_PID;
|
||||||
|
|
||||||
|
#if TUSB_OPT_DEVICE_ENABLED
|
||||||
ep->next_pid ^= 1u;
|
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
|
#if TUSB_OPT_HOST_ENABLED
|
||||||
// Is this the last buffer? Only really matters for host mode. Will trigger
|
// 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
|
// 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
|
// the next time the controller polls this dpram address
|
||||||
_hw_endpoint_buffer_control_set_value32(ep, val);
|
_hw_endpoint_buffer_control_set_value32(ep, val);
|
||||||
pico_trace("buffer control (0x%p) <- 0x%x\n", ep->buffer_control, 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
|
// Fill in info now that we're kicking off the hw
|
||||||
ep->total_len = total_len;
|
ep->total_len = total_len;
|
||||||
ep->len = 0;
|
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->active = true;
|
||||||
ep->user_buf = buffer;
|
ep->user_buf = buffer;
|
||||||
#if TUSB_OPT_HOST_ENABLED
|
#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;
|
uint16_t transferred_bytes = buf_ctrl & USB_BUF_CTRL_LEN_MASK;
|
||||||
|
|
||||||
#if TUSB_OPT_HOST_ENABLED
|
#if TUSB_OPT_HOST_ENABLED
|
||||||
|
// RP2040-E4
|
||||||
// tag::host_buf_sel_fix[]
|
// tag::host_buf_sel_fix[]
|
||||||
|
// TODO need changes to support double buffering
|
||||||
if (ep->buf_sel == 1)
|
if (ep->buf_sel == 1)
|
||||||
{
|
{
|
||||||
// Host can erroneously write status to top half of buf_ctrl register
|
// Host can erroneously write status to top half of buf_ctrl register
|
||||||
buf_ctrl = buf_ctrl >> 16;
|
buf_ctrl = buf_ctrl >> 16;
|
||||||
|
|
||||||
|
// update buf1 -> buf0 to prevent panic with "already available"
|
||||||
|
*ep->buffer_control = buf_ctrl;
|
||||||
}
|
}
|
||||||
// Flip buf sel for host
|
// Flip buf sel for host
|
||||||
ep->buf_sel ^= 1u;
|
ep->buf_sel ^= 1u;
|
||||||
@ -240,8 +271,9 @@ bool _hw_endpoint_xfer_continue(struct hw_endpoint *ep)
|
|||||||
_hw_endpoint_xfer_sync(ep);
|
_hw_endpoint_xfer_sync(ep);
|
||||||
|
|
||||||
// Now we have synced our state with the hardware. Is there more data to transfer?
|
// 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;
|
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
|
#if TUSB_OPT_HOST_ENABLED
|
||||||
_hw_endpoint_update_last_buf(ep);
|
_hw_endpoint_update_last_buf(ep);
|
||||||
#endif
|
#endif
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX
|
#define TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX PICO_RP2040_USB_DEVICE_ENUMERATION_FIX
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// For memset
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#if false && !defined(NDEBUG)
|
#if false && !defined(NDEBUG)
|
||||||
#define pico_trace(format,args...) printf(format, ## args)
|
#define pico_trace(format,args...) printf(format, ## args)
|
||||||
@ -78,7 +76,7 @@ struct hw_endpoint
|
|||||||
#if TUSB_OPT_HOST_ENABLED
|
#if TUSB_OPT_HOST_ENABLED
|
||||||
// Only needed for host mode
|
// Only needed for host mode
|
||||||
bool last_buf;
|
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
|
// control register when doing transfers > 1 packet
|
||||||
uint8_t buf_sel;
|
uint8_t buf_sel;
|
||||||
// Only needed for host
|
// Only needed for host
|
||||||
@ -119,4 +117,44 @@ static inline uintptr_t hw_data_offset(uint8_t *buf)
|
|||||||
|
|
||||||
extern const char *ep_dir_string[];
|
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 u16)
|
||||||
|
{
|
||||||
|
rp2040_buffer_control_t bufctrl;
|
||||||
|
|
||||||
|
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
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user