mirror of
https://github.com/hathach/tinyusb.git
synced 2026-02-04 18:45:35 +00:00
fix rusb2 hcd_port_connect_status() using line state, add post root reset delay for stable speed detection
This commit is contained in:
@ -1405,12 +1405,13 @@ static void remove_device_tree(uint8_t rhport, uint8_t hub_addr, uint8_t hub_por
|
|||||||
// NOTE: due to the shared control buffer, we must complete enumerating
|
// NOTE: due to the shared control buffer, we must complete enumerating
|
||||||
// one device before enumerating another one.
|
// one device before enumerating another one.
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
enum { // USB 2.0 specs 7.1.7 for timing
|
enum { // USB 2.0 specs 7.1.7 for timing
|
||||||
ENUM_DEBOUNCING_DELAY_MS = 150, // T(ATTDB) minimum 100 ms for stable connection
|
ENUM_DEBOUNCING_DELAY_MS = 150, // T(ATTDB) minimum 100 ms for stable connection
|
||||||
ENUM_RESET_ROOT_DELAY_MS = 50, // T(DRSTr) minimum 50 ms for reset from root port
|
ENUM_RESET_ROOT_DELAY_MS = 50, // T(DRSTr) minimum 50 ms for reset from root port
|
||||||
ENUM_RESET_HUB_DELAY_MS = 20, // T(DRST) 10-20 ms for hub reset
|
ENUM_RESET_ROOT_POST_DELAY_MS = 2, // 2 ms delay after root port reset before getting speed/status
|
||||||
ENUM_RESET_RECOVERY_DELAY_MS = 10, // T(RSTRCY) minimum 10 ms for reset recovery
|
ENUM_RESET_HUB_DELAY_MS = 20, // T(DRST) 10-20 ms for hub reset
|
||||||
ENUM_SET_ADDRESS_RECOVERY_DELAY_MS = 2, // USB 2.0 Spec 9.2.6.3 min is 2 ms
|
ENUM_RESET_RECOVERY_DELAY_MS = 10, // T(RSTRCY) minimum 10 ms for reset recovery
|
||||||
|
ENUM_SET_ADDRESS_RECOVERY_DELAY_MS = 2, // USB 2.0 Spec 9.2.6.3 min is 2 ms
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@ -1469,6 +1470,7 @@ static bool enum_new_device(hcd_event_t* event) {
|
|||||||
hcd_port_reset(dev0_bus->rhport);
|
hcd_port_reset(dev0_bus->rhport);
|
||||||
tusb_time_delay_ms_api(ENUM_RESET_ROOT_DELAY_MS);
|
tusb_time_delay_ms_api(ENUM_RESET_ROOT_DELAY_MS);
|
||||||
hcd_port_reset_end(dev0_bus->rhport);
|
hcd_port_reset_end(dev0_bus->rhport);
|
||||||
|
tusb_time_delay_ms_api(ENUM_RESET_ROOT_POST_DELAY_MS);
|
||||||
|
|
||||||
if (!hcd_port_connect_status(dev0_bus->rhport)) {
|
if (!hcd_port_connect_status(dev0_bus->rhport)) {
|
||||||
// device unplugged while delaying
|
// device unplugged while delaying
|
||||||
|
|||||||
@ -76,12 +76,10 @@ typedef struct TU_ATTR_PACKED {
|
|||||||
TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain)
|
TU_ATTR_PACKED_END // End of definition of packed structs (used by the CCRX toolchain)
|
||||||
TU_ATTR_BIT_FIELD_ORDER_END
|
TU_ATTR_BIT_FIELD_ORDER_END
|
||||||
|
|
||||||
typedef struct
|
typedef struct {
|
||||||
{
|
|
||||||
bool need_reset; /* The device has not been reset after connection. */
|
|
||||||
pipe_state_t pipe[PIPE_COUNT];
|
pipe_state_t pipe[PIPE_COUNT];
|
||||||
uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */
|
uint8_t ep[4][2][15]; /* a lookup table for a pipe index from an endpoint address */
|
||||||
uint8_t ctl_mps[5]; /* EP0 max packet size for each device */
|
uint8_t ctl_mps[5]; /* EP0 max packet size for each device */
|
||||||
} hcd_data_t;
|
} hcd_data_t;
|
||||||
|
|
||||||
//--------------------------------------------------------------------+
|
//--------------------------------------------------------------------+
|
||||||
@ -535,13 +533,8 @@ void hcd_int_disable(uint8_t rhport) {
|
|||||||
rusb2_int_disable(rhport);
|
rusb2_int_disable(rhport);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t hcd_frame_number(uint8_t rhport)
|
uint32_t hcd_frame_number(uint8_t rhport) {
|
||||||
{
|
rusb2_reg_t *rusb = RUSB2_REG(rhport);
|
||||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
|
||||||
|
|
||||||
/* 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);
|
|
||||||
return rusb->FRMNUM_b.FRNM;
|
return rusb->FRMNUM_b.FRNM;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -550,32 +543,18 @@ uint32_t hcd_frame_number(uint8_t rhport)
|
|||||||
*--------------------------------------------------------------------+*/
|
*--------------------------------------------------------------------+*/
|
||||||
bool hcd_port_connect_status(uint8_t rhport) {
|
bool hcd_port_connect_status(uint8_t rhport) {
|
||||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||||
return rusb->INTSTS1_b.ATTCH ? true : false;
|
const uint16_t line_state = rusb->SYSSTS0 & RUSB2_SYSSTS0_LNST_Msk;
|
||||||
|
return line_state == RUSB2_SYSSTS0_LNST_FS_J || line_state == RUSB2_SYSSTS0_LNST_FS_K;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_port_reset(uint8_t rhport) {
|
void hcd_port_reset(uint8_t rhport) {
|
||||||
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
rusb2_reg_t* rusb = RUSB2_REG(rhport);
|
||||||
rusb->DCPCTR = RUSB2_PIPE_CTR_PID_NAK;
|
|
||||||
while (rusb->DCPCTR_b.PBUSY) {}
|
|
||||||
|
|
||||||
hcd_int_disable(rhport);
|
|
||||||
rusb->DVSTCTR0_b.UACT = 0;
|
|
||||||
if (rusb->DCPCTR_b.SUREQ) {
|
|
||||||
rusb->DCPCTR_b.SUREQCLR = 1;
|
|
||||||
}
|
|
||||||
hcd_int_enable(rhport);
|
|
||||||
|
|
||||||
/* Reset should be asserted 10-20ms. */
|
|
||||||
rusb->DVSTCTR0_b.USBRST = 1;
|
rusb->DVSTCTR0_b.USBRST = 1;
|
||||||
for (volatile int i = 0; i < 2400000; ++i) {}
|
|
||||||
rusb->DVSTCTR0_b.USBRST = 0;
|
|
||||||
|
|
||||||
rusb->DVSTCTR0_b.UACT = 1;
|
|
||||||
_hcd.need_reset = false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hcd_port_reset_end(uint8_t rhport) {
|
void hcd_port_reset_end(uint8_t rhport) {
|
||||||
(void) rhport;
|
rusb2_reg_t *rusb = RUSB2_REG(rhport);
|
||||||
|
rusb->DVSTCTR0_b.USBRST = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
|
tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
|
||||||
@ -584,7 +563,8 @@ tusb_speed_t hcd_port_speed_get(uint8_t rhport) {
|
|||||||
case RUSB2_DVSTCTR0_RHST_HS: return TUSB_SPEED_HIGH;
|
case RUSB2_DVSTCTR0_RHST_HS: return TUSB_SPEED_HIGH;
|
||||||
case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL;
|
case RUSB2_DVSTCTR0_RHST_FS: return TUSB_SPEED_FULL;
|
||||||
case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW;
|
case RUSB2_DVSTCTR0_RHST_LS: return TUSB_SPEED_LOW;
|
||||||
default: return TUSB_SPEED_INVALID;
|
default:
|
||||||
|
return TUSB_SPEED_INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -802,7 +782,6 @@ void hcd_int_handler(uint8_t rhport, bool in_isr) {
|
|||||||
|
|
||||||
if (is1 & RUSB2_INTSTS1_ATTCH_Msk) {
|
if (is1 & RUSB2_INTSTS1_ATTCH_Msk) {
|
||||||
rusb->DVSTCTR0_b.UACT = 1;
|
rusb->DVSTCTR0_b.UACT = 1;
|
||||||
_hcd.need_reset = true;
|
|
||||||
rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk;
|
rusb->INTENB1 = (rusb->INTENB1 & ~RUSB2_INTSTS1_ATTCH_Msk) | RUSB2_INTSTS1_DTCH_Msk;
|
||||||
hcd_event_device_attach(rhport, true);
|
hcd_event_device_attach(rhport, true);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1669,15 +1669,20 @@ TU_ATTR_BIT_FIELD_ORDER_END
|
|||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
/* Register Bit Utils */
|
/* Register Bit Utils */
|
||||||
/*--------------------------------------------------------------------*/
|
/*--------------------------------------------------------------------*/
|
||||||
#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */
|
#define RUSB2_SYSSTS0_LNST_SE0 (0)
|
||||||
#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */
|
#define RUSB2_SYSSTS0_LNST_FS_J (1u << RUSB2_SYSSTS0_LNST_Pos) /* Full-speed J state */
|
||||||
#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */
|
#define RUSB2_SYSSTS0_LNST_FS_K (2u << RUSB2_SYSSTS0_LNST_Pos) /* Full-speed K state */
|
||||||
#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */
|
#define RUSB2_SYSSTS0_LNST_LS_SE1 (3u << RUSB2_SYSSTS0_LNST_Pos) /* Low-speed SE1 state */
|
||||||
|
|
||||||
#define RUSB2_DVSTCTR0_RHST_LS (1U << RUSB2_DVSTCTR0_RHST_Pos) /* Low-speed connection */
|
#define RUSB2_DVSTCTR0_RHST_LS (1U << RUSB2_DVSTCTR0_RHST_Pos) /* Low-speed connection */
|
||||||
#define RUSB2_DVSTCTR0_RHST_FS (2U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */
|
#define RUSB2_DVSTCTR0_RHST_FS (2U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */
|
||||||
#define RUSB2_DVSTCTR0_RHST_HS (3U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */
|
#define RUSB2_DVSTCTR0_RHST_HS (3U << RUSB2_DVSTCTR0_RHST_Pos) /* Full-speed connection */
|
||||||
|
|
||||||
|
#define RUSB2_PIPE_CTR_PID_NAK (0U << RUSB2_PIPE_CTR_PID_Pos) /* NAK response */
|
||||||
|
#define RUSB2_PIPE_CTR_PID_BUF (1U << RUSB2_PIPE_CTR_PID_Pos) /* BUF response (depends buffer state) */
|
||||||
|
#define RUSB2_PIPE_CTR_PID_STALL (2U << RUSB2_PIPE_CTR_PID_Pos) /* STALL response */
|
||||||
|
#define RUSB2_PIPE_CTR_PID_STALL2 (3U << RUSB2_PIPE_CTR_PID_Pos) /* Also STALL response */
|
||||||
|
|
||||||
#define RUSB2_DEVADD_USBSPD_LS (1U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Low-speed */
|
#define RUSB2_DEVADD_USBSPD_LS (1U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Low-speed */
|
||||||
#define RUSB2_DEVADD_USBSPD_FS (2U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Full-speed */
|
#define RUSB2_DEVADD_USBSPD_FS (2U << RUSB2_DEVADD_USBSPD_Pos) /* Target Device Full-speed */
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user