rp2040 add disconnection detection
- also use dcd_event_bus_reset() - Add TODO for suspend, resume later on (need to test with/without vbus detection).
This commit is contained in:
		@@ -992,11 +992,15 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
 | 
				
			|||||||
  switch (event->event_id)
 | 
					  switch (event->event_id)
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    case DCD_EVENT_UNPLUGGED:
 | 
					    case DCD_EVENT_UNPLUGGED:
 | 
				
			||||||
 | 
					      // UNPLUGGED event can be bouncing, only processing if we are currently connected
 | 
				
			||||||
 | 
					      if ( _usbd_dev.connected )
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
        _usbd_dev.connected  = 0;
 | 
					        _usbd_dev.connected  = 0;
 | 
				
			||||||
        _usbd_dev.addressed  = 0;
 | 
					        _usbd_dev.addressed  = 0;
 | 
				
			||||||
        _usbd_dev.cfg_num    = 0;
 | 
					        _usbd_dev.cfg_num    = 0;
 | 
				
			||||||
        _usbd_dev.suspended  = 0;
 | 
					        _usbd_dev.suspended  = 0;
 | 
				
			||||||
        osal_queue_send(_usbd_q, event, in_isr);
 | 
					        osal_queue_send(_usbd_q, event, in_isr);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    break;
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case DCD_EVENT_SOF:
 | 
					    case DCD_EVENT_SOF:
 | 
				
			||||||
@@ -1004,9 +1008,10 @@ void dcd_event_handler(dcd_event_t const * event, bool in_isr)
 | 
				
			|||||||
    break;
 | 
					    break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    case DCD_EVENT_SUSPEND:
 | 
					    case DCD_EVENT_SUSPEND:
 | 
				
			||||||
      // NOTE: When plugging/unplugging device, the D+/D- state are unstable and can accidentally meet the
 | 
					      // NOTE: When plugging/unplugging device, the D+/D- state are unstable and
 | 
				
			||||||
      // SUSPEND condition ( Idle for 3ms ). Some MCUs such as SAMD doesn't distinguish suspend vs disconnect as well.
 | 
					      // can accidentally meet the SUSPEND condition ( Bus Idle for 3ms ).
 | 
				
			||||||
      // We will skip handling SUSPEND/RESUME event if not currently connected
 | 
					      // In addition, some MCUs such as SAMD or boards that haven no VBUS detection cannot distinguish
 | 
				
			||||||
 | 
					      // suspended vs disconnected. We will skip handling SUSPEND/RESUME event if not currently connected
 | 
				
			||||||
      if ( _usbd_dev.connected )
 | 
					      if ( _usbd_dev.connected )
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        _usbd_dev.suspended = 1;
 | 
					        _usbd_dev.suspended = 1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -317,13 +317,45 @@ static void dcd_rp2040_irq(void)
 | 
				
			|||||||
        pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0);
 | 
					        pico_trace("BUS RESET (addr %d -> %d)\n", assigned_address, 0);
 | 
				
			||||||
        usb_hw->dev_addr_ctrl = 0;
 | 
					        usb_hw->dev_addr_ctrl = 0;
 | 
				
			||||||
        handled |= USB_INTS_BUS_RESET_BITS;
 | 
					        handled |= USB_INTS_BUS_RESET_BITS;
 | 
				
			||||||
        dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
 | 
					        dcd_event_bus_reset(0, TUSB_SPEED_FULL, true);
 | 
				
			||||||
        usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
 | 
					        usb_hw_clear->sie_status = USB_SIE_STATUS_BUS_RESET_BITS;
 | 
				
			||||||
#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
 | 
					#if TUD_OPT_RP2040_USB_DEVICE_ENUMERATION_FIX
 | 
				
			||||||
        rp2040_usb_device_enumeration_fix();
 | 
					        rp2040_usb_device_enumeration_fix();
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (status & USB_INTS_DEV_CONN_DIS_BITS)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        handled |= USB_INTS_DEV_CONN_DIS_BITS;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if ( usb_hw->sie_status & USB_SIE_STATUS_CONNECTED_BITS )
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          // Connected: nothing to do
 | 
				
			||||||
 | 
					        }else
 | 
				
			||||||
 | 
					        {
 | 
				
			||||||
 | 
					          // Disconnected
 | 
				
			||||||
 | 
					          dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        usb_hw_clear->sie_status = USB_SIE_STATUS_CONNECTED_BITS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#if 0 // TODO Enable SUSPEND & RESUME interrupt and test later on with/without VBUS detection
 | 
				
			||||||
 | 
					    if (status & USB_INTS_DEV_SUSPEND_BITS)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        handled |= USB_INTS_DEV_SUSPEND_BITS;
 | 
				
			||||||
 | 
					        dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
 | 
				
			||||||
 | 
					        usb_hw_clear->sie_status = USB_SIE_STATUS_SUSPENDED_BITS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (status & USB_INTS_DEV_RESUME_FROM_HOST_BITS)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					        handled |= USB_INTS_DEV_RESUME_FROM_HOST_BITS;
 | 
				
			||||||
 | 
					        dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
 | 
				
			||||||
 | 
					        usb_hw_clear->sie_status = USB_SIE_STATUS_RESUME_BITS;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (status ^ handled)
 | 
					    if (status ^ handled)
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
        panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled));
 | 
					        panic("Unhandled IRQ 0x%x\n", (uint) (status ^ handled));
 | 
				
			||||||
@@ -364,8 +396,10 @@ void dcd_init (uint8_t rhport)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    // Enable individual controller IRQS here. Processor interrupt enable will be used
 | 
					    // Enable individual controller IRQS here. Processor interrupt enable will be used
 | 
				
			||||||
    // for the global interrupt enable...
 | 
					    // for the global interrupt enable...
 | 
				
			||||||
 | 
					    // TODO Enable SUSPEND & RESUME interrupt
 | 
				
			||||||
    usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; 
 | 
					    usb_hw->sie_ctrl = USB_SIE_CTRL_EP0_INT_1BUF_BITS; 
 | 
				
			||||||
    usb_hw->inte     = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS;
 | 
					    usb_hw->inte     = USB_INTS_BUFF_STATUS_BITS | USB_INTS_BUS_RESET_BITS | USB_INTS_SETUP_REQ_BITS |
 | 
				
			||||||
 | 
					                       USB_INTS_DEV_CONN_DIS_BITS /* | USB_INTS_DEV_SUSPEND_BITS | USB_INTS_DEV_RESUME_FROM_HOST_BITS */  ;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    dcd_connect(rhport);
 | 
					    dcd_connect(rhport);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -393,8 +427,9 @@ void dcd_set_address (uint8_t rhport, uint8_t dev_addr)
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
void dcd_remote_wakeup(uint8_t rhport)
 | 
					void dcd_remote_wakeup(uint8_t rhport)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
    pico_info("dcd_remote_wakeup %d is not supported yet\n", rhport);
 | 
					    pico_info("dcd_remote_wakeup %d\n", rhport);
 | 
				
			||||||
    assert(rhport == 0);
 | 
					    assert(rhport == 0);
 | 
				
			||||||
 | 
					    usb_hw_set->sie_ctrl = USB_SIE_CTRL_RESUME_BITS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// disconnect by disabling internal pull-up resistor on D+/D-
 | 
					// disconnect by disabling internal pull-up resistor on D+/D-
 | 
				
			||||||
@@ -402,6 +437,7 @@ void dcd_disconnect(uint8_t rhport)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    pico_info("dcd_disconnect %d\n", rhport);
 | 
					    pico_info("dcd_disconnect %d\n", rhport);
 | 
				
			||||||
    assert(rhport == 0);
 | 
					    assert(rhport == 0);
 | 
				
			||||||
 | 
					    //TU_LOG2("dcd_disconnect\n");
 | 
				
			||||||
    usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
 | 
					    usb_hw_clear->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -410,6 +446,7 @@ void dcd_connect(uint8_t rhport)
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
    pico_info("dcd_connect %d\n", rhport);
 | 
					    pico_info("dcd_connect %d\n", rhport);
 | 
				
			||||||
    assert(rhport == 0);
 | 
					    assert(rhport == 0);
 | 
				
			||||||
 | 
					    //TU_LOG2("dcd_connect\n");
 | 
				
			||||||
    usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
 | 
					    usb_hw_set->sie_ctrl = USB_SIE_CTRL_PULLUP_EN_BITS;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user