Merge pull request #357 from hathach/fix-209

add disconnection detection for stm32 synopsys
This commit is contained in:
Ha Thach 2020-04-19 13:01:13 +07:00 committed by GitHub
commit c0047e376f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 69 additions and 23 deletions

View File

@ -179,7 +179,8 @@ void dcd_init(uint8_t rhport)
USB0.gintmsk = 0; //mask all USB0.gintmsk = 0; //mask all
USB0.gotgint = ~0U; //clear OTG ints USB0.gotgint = ~0U; //clear OTG ints
USB0.gintsts = ~0U; //clear pending ints USB0.gintsts = ~0U; //clear pending ints
USB0.gintmsk = USB_MODEMISMSK_M | USB0.gintmsk = USB_OTGINTMSK_M |
USB_MODEMISMSK_M |
#if USE_SOF #if USE_SOF
USB_SOFMSK_M | USB_SOFMSK_M |
#endif #endif
@ -189,7 +190,7 @@ void dcd_init(uint8_t rhport)
USB_USBRSTMSK_M | USB_USBRSTMSK_M |
USB_ENUMDONEMSK_M | USB_ENUMDONEMSK_M |
USB_RESETDETMSK_M | USB_RESETDETMSK_M |
USB_DISCONNINTMSK_M; USB_DISCONNINTMSK_M; // host most only
} }
void dcd_set_address(uint8_t rhport, uint8_t dev_addr) void dcd_set_address(uint8_t rhport, uint8_t dev_addr)
@ -638,12 +639,6 @@ static void _dcd_int_handler(void* arg)
const uint32_t int_status = USB0.gintsts; const uint32_t int_status = USB0.gintsts;
//const uint32_t int_msk = USB0.gintmsk; //const uint32_t int_msk = USB0.gintmsk;
if (int_status & USB_DISCONNINT_M) {
ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected");
USB0.gintsts = USB_DISCONNINT_M;
dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
}
if (int_status & USB_USBRST_M) { if (int_status & USB_USBRST_M) {
// start of reset // start of reset
ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset"); ESP_EARLY_LOGV(TAG, "dcd_int_handler - reset");
@ -666,6 +661,21 @@ static void _dcd_int_handler(void* arg)
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
} }
if (int_status & USB_OTGINT_M)
{
// OTG INT bit is read-only
ESP_EARLY_LOGV(TAG, "dcd_int_handler - disconnected");
uint32_t const otg_int = USB0.gotgint;
if (otg_int & USB_SESENDDET_M)
{
dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
}
USB0.gotgint = otg_int;
}
#if USE_SOF #if USE_SOF
if (int_status & USB_SOF_M) { if (int_status & USB_SOF_M) {
USB0.gintsts = USB_SOF_M; USB0.gintsts = USB_SOF_M;
@ -674,26 +684,25 @@ static void _dcd_int_handler(void* arg)
#endif #endif
if (int_status & USB_RXFLVI_M) { if (int_status & USB_RXFLVI_M) {
// RXFLVL bit is read-only
ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!"); ESP_EARLY_LOGV(TAG, "dcd_int_handler - rx!");
USB0.gintsts = USB_RXFLVI_M;
// disable RXFLVI interrupt until we read data from FIFO // Mask out RXFLVL while reading data from FIFO
USB0.gintmsk &= ~USB_RXFLVIMSK_M; USB0.gintmsk &= ~USB_RXFLVIMSK_M;
read_rx_fifo(); read_rx_fifo();
// re-enable RXFLVI
USB0.gintmsk |= USB_RXFLVIMSK_M; USB0.gintmsk |= USB_RXFLVIMSK_M;
} }
// OUT endpoint interrupt handling. // OUT endpoint interrupt handling.
if (int_status & USB_OEPINT_M) { if (int_status & USB_OEPINT_M) {
// OEPINT is read-only
ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!"); ESP_EARLY_LOGV(TAG, "dcd_int_handler - OUT endpoint!");
handle_epout_ints(); handle_epout_ints();
} }
// IN endpoint interrupt handling. // IN endpoint interrupt handling.
if (int_status & USB_IEPINT_M) { if (int_status & USB_IEPINT_M) {
// IEPINT bit read-only
ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!"); ESP_EARLY_LOGV(TAG, "dcd_int_handler - IN endpoint!");
handle_epin_ints(); handle_epin_ints();
} }

View File

@ -75,6 +75,11 @@
/*------------------------------------------------------------------*/ /*------------------------------------------------------------------*/
/* MACRO TYPEDEF CONSTANT ENUM /* MACRO TYPEDEF CONSTANT ENUM
*------------------------------------------------------------------*/ *------------------------------------------------------------------*/
// Since TinyUSB doesn't use SOF for now, and this interrupt too often (1ms interval)
// We disable SOF for now until needed later on
#define USE_SOF 0
#define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE) #define DEVICE_BASE (USB_OTG_DeviceTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_DEVICE_BASE)
#define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE) #define OUT_EP_BASE (USB_OTG_OUTEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_OUT_ENDPOINT_BASE)
#define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE) #define IN_EP_BASE (USB_OTG_INEndpointTypeDef *) (USB_OTG_FS_PERIPH_BASE + USB_OTG_IN_ENDPOINT_BASE)
@ -187,15 +192,13 @@ void dcd_init (uint8_t rhport)
// TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating? // TODO: PHYSEL is read-only on some cores (STM32F407). Worth gating?
USB_OTG_FS->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL; USB_OTG_FS->GUSBCFG |= (0x06 << USB_OTG_GUSBCFG_TRDT_Pos) | USB_OTG_GUSBCFG_PHYSEL;
// Clear all used interrupts // Clear all interrupts
USB_OTG_FS->GINTSTS |= USB_OTG_GINTSTS_OTGINT | USB_OTG_GINTSTS_MMIS | \ USB_OTG_FS->GINTSTS |= USB_OTG_FS->GINTSTS;
USB_OTG_GINTSTS_USBRST | USB_OTG_GINTSTS_ENUMDNE | \
USB_OTG_GINTSTS_ESUSP | USB_OTG_GINTSTS_USBSUSP | USB_OTG_GINTSTS_SOF;
// Required as part of core initialization. Disable OTGINT as we don't use // Required as part of core initialization.
// it right now. TODO: How should mode mismatch be handled? It will cause // TODO: How should mode mismatch be handled? It will cause
// the core to stop working/require reset. // the core to stop working/require reset.
USB_OTG_FS->GINTMSK |= /* USB_OTG_GINTMSK_OTGINT | */ USB_OTG_GINTMSK_MMISM; USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_OTGINT | USB_OTG_GINTMSK_MMISM;
USB_OTG_DeviceTypeDef * dev = DEVICE_BASE; USB_OTG_DeviceTypeDef * dev = DEVICE_BASE;
@ -203,9 +206,9 @@ void dcd_init (uint8_t rhport)
// (non zero-length packet), send STALL back and discard. Full speed. // (non zero-length packet), send STALL back and discard. Full speed.
dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos); dev->DCFG |= USB_OTG_DCFG_NZLSOHSK | (3 << USB_OTG_DCFG_DSPD_Pos);
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM | \ USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_USBRST | USB_OTG_GINTMSK_ENUMDNEM |
USB_OTG_GINTMSK_SOFM | USB_OTG_GINTMSK_RXFLVLM /* SB_OTG_GINTMSK_ESUSPM | \ USB_OTG_GINTMSK_USBSUSPM | USB_OTG_GINTMSK_WUIM |
USB_OTG_GINTMSK_USBSUSPM */; USB_OTG_GINTMSK_RXFLVLM | (USE_SOF ? USB_OTG_GINTMSK_SOFM : 0);
// Enable USB transceiver. // Enable USB transceiver.
USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN; USB_OTG_FS->GCCFG |= USB_OTG_GCCFG_PWRDWN;
@ -687,22 +690,56 @@ void dcd_int_handler(uint8_t rhport) {
dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true); dcd_event_bus_signal(0, DCD_EVENT_BUS_RESET, true);
} }
if(int_status & USB_OTG_GINTSTS_USBSUSP)
{
USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_USBSUSP;
dcd_event_bus_signal(0, DCD_EVENT_SUSPEND, true);
}
if(int_status & USB_OTG_GINTSTS_WKUINT)
{
USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_WKUINT;
dcd_event_bus_signal(0, DCD_EVENT_RESUME, true);
}
if(int_status & USB_OTG_GINTSTS_OTGINT)
{
// OTG INT bit is read-only
uint32_t const otg_int = USB_OTG_FS->GOTGINT;
if (otg_int & USB_OTG_GOTGINT_SEDET)
{
dcd_event_bus_signal(0, DCD_EVENT_UNPLUGGED, true);
}
USB_OTG_FS->GOTGINT = otg_int;
}
#if USE_SOF
if(int_status & USB_OTG_GINTSTS_SOF) { if(int_status & USB_OTG_GINTSTS_SOF) {
USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_SOF; USB_OTG_FS->GINTSTS = USB_OTG_GINTSTS_SOF;
dcd_event_bus_signal(0, DCD_EVENT_SOF, true); dcd_event_bus_signal(0, DCD_EVENT_SOF, true);
} }
#endif
if(int_status & USB_OTG_GINTSTS_RXFLVL) { if(int_status & USB_OTG_GINTSTS_RXFLVL) {
// RXFLVL bit is read-only
// Mask out RXFLVL while reading data from FIFO
USB_OTG_FS->GINTMSK &= ~USB_OTG_GINTMSK_RXFLVLM;
read_rx_fifo(out_ep); read_rx_fifo(out_ep);
USB_OTG_FS->GINTMSK |= USB_OTG_GINTMSK_RXFLVLM;
} }
// OUT endpoint interrupt handling. // OUT endpoint interrupt handling.
if(int_status & USB_OTG_GINTSTS_OEPINT) { if(int_status & USB_OTG_GINTSTS_OEPINT) {
// OEPINT is read-only
handle_epout_ints(dev, out_ep); handle_epout_ints(dev, out_ep);
} }
// IN endpoint interrupt handling. // IN endpoint interrupt handling.
if(int_status & USB_OTG_GINTSTS_IEPINT) { if(int_status & USB_OTG_GINTSTS_IEPINT) {
// IEPINT bit read-only
handle_epin_ints(dev, in_ep); handle_epin_ints(dev, in_ep);
} }
} }