Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 61 additions & 9 deletions os/hal/ports/KINETIS/LLD/USBHSv1/hal_usb_lld.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,26 @@ void usb_packet_receive(USBDriver *usbp, usbep_t ep, size_t n)
*/
OSAL_IRQ_HANDLER(KINETIS_USB_IRQ_VECTOR) {
USBDriver *usbp = &USBD1;

/* Bail out if driver is stopped or being torn down */
if (usbp->state == USB_UNINIT || usbp->state == USB_STOP) {
uint8_t enabled =
#if KINETIS_USB0_IS_USBOTG
(SIM->SCGC4 & SIM_SCGC4_USBOTG);
#else
(SIM->SCGC4 & SIM_SCGC4_USBFS);
#endif

if (enabled) {
/* Clear all pending USB IRQ flags */
USB0->ISTAT = 0xFF;
USB0->ERRSTAT = 0xFF;
}
OSAL_IRQ_EPILOGUE();
return;
}


uint8_t istat = USB0->ISTAT;

OSAL_IRQ_PROLOGUE();
Expand Down Expand Up @@ -527,18 +547,50 @@ void usb_lld_start(USBDriver *usbp) {
* @notapi
*/
void usb_lld_stop(USBDriver *usbp) {
/* TODO: If in ready state then disables the USB clock.*/
if (usbp->state == USB_STOP) {
#if KINETIS_USB_USE_USB0
if (&USBD1 == usbp) {
if (&USBD1 != usbp) return;

/* If the driver was never started, bail out */
if (usbp->state == USB_UNINIT || usbp->state == USB_STOP) {
return;
}

/* Mask all peripheral interrupts */
USB0->INTEN = 0;
USB0->ERREN = 0;

uint8_t enabled =
#if KINETIS_USB0_IS_USBOTG
nvicDisableVector(USB_OTG_IRQn);
#else /* KINETIS_USB0_IS_USBOTG */
nvicDisableVector(USB_IRQn);
#endif /* KINETIS_USB0_IS_USBOTG */
(SIM->SCGC4 & SIM_SCGC4_USBOTG);
#else
(SIM->SCGC4 & SIM_SCGC4_USBFS);
#endif
if (enabled) {
/* Disconnect pull-up while clock is still on */
usb_lld_disconnect_bus(usbp);

/* Only disable USB engine if the clock is enabled */
USB0->CTL = 0;
USB0->CTL = USBx_CTL_ODDRST; /* reset odd/even PID */
USB0->ISTAT = 0xFF;
USB0->ERRSTAT = 0xFF;
}
#endif /* KINETIS_USB_USE_USB0 */
}

/* Disable NVIC IRQ */
#if KINETIS_USB0_IS_USBOTG
nvicDisableVector(USB_OTG_IRQn);
#else
nvicDisableVector(USB_IRQn);
#endif

/* Gate the USB clock */
#if KINETIS_USB0_IS_USBOTG
SIM->SCGC4 &= ~SIM_SCGC4_USBOTG;
#else
SIM->SCGC4 &= ~SIM_SCGC4_USBFS;
#endif

#endif
}

/**
Expand Down
20 changes: 17 additions & 3 deletions os/hal/ports/KINETIS/LLD/USBHSv1/hal_usb_lld.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,14 +397,28 @@ struct USBDriver {
* @api
*/
#if !defined(usb_lld_disconnect_bus)
/* Writing to USB0->CONTROL causes an unhandled exception when USB module is not clocked. */

/* Writing USB0->CONTROL with clock off causes hard fault on MK20 */
#if KINETIS_USB0_IS_USBOTG
#define usb_lld_disconnect_bus(usbp) if(SIM->SCGC4 & SIM_SCGC4_USBOTG) {USB0->CONTROL &= ~USBx_CONTROL_DPPULLUPNONOTG;} else {}
#define usb_lld_disconnect_bus(usbp) \
do { \
(void)(usbp); \
if (SIM->SCGC4 & SIM_SCGC4_USBOTG) { \
USB0->CONTROL &= ~USBx_CONTROL_DPPULLUPNONOTG; \
} \
} while (false)
#else /* KINETIS_USB0_IS_USBOTG */
#define usb_lld_disconnect_bus(usbp) if(SIM->SCGC4 & SIM_SCGC4_USBFS) {USB0->CONTROL &= ~USBx_CONTROL_DPPULLUPNONOTG;} else {}
#define usb_lld_disconnect_bus(usbp) \
do { \
(void)(usbp); \
if (SIM->SCGC4 & SIM_SCGC4_USBFS) { \
USB0->CONTROL &= ~USBx_CONTROL_DPPULLUPNONOTG; \
} \
} while (false)
#endif /* KINETIS_USB0_IS_USBOTG */
#endif


/**
* @brief Start of host wake-up procedure.
*
Expand Down
Loading