diff options
Diffstat (limited to 'libmaple/usb/stm32f1/usb.c')
-rw-r--r-- | libmaple/usb/stm32f1/usb.c | 196 |
1 files changed, 101 insertions, 95 deletions
diff --git a/libmaple/usb/stm32f1/usb.c b/libmaple/usb/stm32f1/usb.c index c20cc71..f694f04 100644 --- a/libmaple/usb/stm32f1/usb.c +++ b/libmaple/usb/stm32f1/usb.c @@ -28,7 +28,7 @@ * @file libmaple/usb/stm32f1/usb.c * @brief USB support. * - * This is a mess. What we need almost amounts to a ground-up rewrite. + * This is a mess. */ #include <libmaple/usb.h> @@ -69,13 +69,14 @@ typedef enum { } RESUME_STATE; struct { - volatile RESUME_STATE eState; - volatile uint8 bESOFcnt; + volatile RESUME_STATE eState; + volatile uint8 bESOFcnt; } ResumeS; static usblib_dev usblib = { .irq_mask = USB_ISR_MSK, .state = USB_UNCONNECTED, + .prevState = USB_UNCONNECTED, .clk_id = RCC_USB, }; usblib_dev *USBLIB = &usblib; @@ -105,147 +106,151 @@ void usb_init_usblib(usblib_dev *dev, } static void usb_suspend(void) { - uint16 cntr; - - /* TODO decide if read/modify/write is really what we want - * (e.g. usb_resume_init() reconfigures CNTR). */ - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_FSUSP; - USB_BASE->CNTR = cntr; - cntr |= USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; - - USBLIB->state = USB_SUSPENDED; + uint16 cntr; + + /* TODO decide if read/modify/write is really what we want + * (e.g. usb_resume_init() reconfigures CNTR). */ + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_FSUSP; + USB_BASE->CNTR = cntr; + cntr |= USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; + + USBLIB->prevState = USBLIB->state; + USBLIB->state = USB_SUSPENDED; } static void usb_resume_init(void) { - uint16 cntr; + uint16 cntr; - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_LP_MODE; - USB_BASE->CNTR = cntr; + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_LP_MODE; + USB_BASE->CNTR = cntr; - /* Enable interrupt lines */ - USB_BASE->CNTR = USB_ISR_MSK; + /* Enable interrupt lines */ + USB_BASE->CNTR = USB_ISR_MSK; } static void usb_resume(RESUME_STATE eResumeSetVal) { - uint16 cntr; + uint16 cntr; - if (eResumeSetVal != RESUME_ESOF) - ResumeS.eState = eResumeSetVal; + if (eResumeSetVal != RESUME_ESOF) { + ResumeS.eState = eResumeSetVal; + } - switch (ResumeS.eState) - { + switch (ResumeS.eState) { case RESUME_EXTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_OFF; - break; + usb_resume_init(); + ResumeS.eState = RESUME_OFF; + USBLIB->state = USBLIB->prevState; + break; case RESUME_INTERNAL: - usb_resume_init(); - ResumeS.eState = RESUME_START; - break; + usb_resume_init(); + ResumeS.eState = RESUME_START; + break; case RESUME_LATER: - ResumeS.bESOFcnt = 2; - ResumeS.eState = RESUME_WAIT; - break; + ResumeS.bESOFcnt = 2; + ResumeS.eState = RESUME_WAIT; + break; case RESUME_WAIT: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) - ResumeS.eState = RESUME_START; - break; + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + ResumeS.eState = RESUME_START; + } + break; case RESUME_START: - cntr = USB_BASE->CNTR; - cntr |= USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_ON; - ResumeS.bESOFcnt = 10; - break; + cntr = USB_BASE->CNTR; + cntr |= USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + ResumeS.eState = RESUME_ON; + ResumeS.bESOFcnt = 10; + break; case RESUME_ON: - ResumeS.bESOFcnt--; - if (ResumeS.bESOFcnt == 0) { - cntr = USB_BASE->CNTR; - cntr &= ~USB_CNTR_RESUME; - USB_BASE->CNTR = cntr; - ResumeS.eState = RESUME_OFF; - } - break; + ResumeS.bESOFcnt--; + if (ResumeS.bESOFcnt == 0) { + cntr = USB_BASE->CNTR; + cntr &= ~USB_CNTR_RESUME; + USB_BASE->CNTR = cntr; + USBLIB->state = USBLIB->prevState; + ResumeS.eState = RESUME_OFF; + } + break; case RESUME_OFF: case RESUME_ESOF: default: - ResumeS.eState = RESUME_OFF; - break; + ResumeS.eState = RESUME_OFF; + break; } } #define SUSPEND_ENABLED 1 void __irq_usb_lp_can_rx0(void) { - uint16 istr = USB_BASE->ISTR; + uint16 istr = USB_BASE->ISTR; - /* Use USB_ISR_MSK to only include code for bits we care about. */ + /* Use USB_ISR_MSK to only include code for bits we care about. */ #if (USB_ISR_MSK & USB_ISTR_RESET) - if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_RESET; - pProperty->Reset(); - } + if (istr & USB_ISTR_RESET & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_RESET; + pProperty->Reset(); + } #endif #if (USB_ISR_MSK & USB_ISTR_PMAOVR) - if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_PMAOVR; - } + if (istr & ISTR_PMAOVR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_PMAOVR; + } #endif #if (USB_ISR_MSK & USB_ISTR_ERR) - if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ERR; - } + if (istr & USB_ISTR_ERR & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ERR; + } #endif #if (USB_ISR_MSK & USB_ISTR_WKUP) - if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_WKUP; - usb_resume(RESUME_EXTERNAL); - } + if (istr & USB_ISTR_WKUP & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_WKUP; + usb_resume(RESUME_EXTERNAL); + } #endif #if (USB_ISR_MSK & USB_ISTR_SUSP) - if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { - /* check if SUSPEND is possible */ - if (SUSPEND_ENABLED) { - usb_suspend(); - } else { - /* if not possible then resume after xx ms */ - usb_resume(RESUME_LATER); + if (istr & USB_ISTR_SUSP & USBLIB->irq_mask) { + /* check if SUSPEND is possible */ + if (SUSPEND_ENABLED) { + usb_suspend(); + } else { + /* if not possible then resume after xx ms */ + usb_resume(RESUME_LATER); + } + /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ + USB_BASE->ISTR = ~USB_ISTR_SUSP; } - /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */ - USB_BASE->ISTR = ~USB_ISTR_SUSP; -} #endif #if (USB_ISR_MSK & USB_ISTR_SOF) - if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_SOF; - } + if (istr & USB_ISTR_SOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_SOF; + } #endif #if (USB_ISR_MSK & USB_ISTR_ESOF) - if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { - USB_BASE->ISTR = ~USB_ISTR_ESOF; - /* resume handling timing is made with ESOFs */ - usb_resume(RESUME_ESOF); /* request without change of the machine state */ - } + if (istr & USB_ISTR_ESOF & USBLIB->irq_mask) { + USB_BASE->ISTR = ~USB_ISTR_ESOF; + /* resume handling timing is made with ESOFs */ + usb_resume(RESUME_ESOF); /* request without change of the machine state */ + } #endif - /* - * Service the correct transfer interrupt. - */ + /* + * Service the correct transfer interrupt. + */ #if (USB_ISR_MSK & USB_ISTR_CTR) - if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { - dispatch_ctr_lp(); - } + if (istr & USB_ISTR_CTR & USBLIB->irq_mask) { + dispatch_ctr_lp(); + } #endif } @@ -274,8 +279,9 @@ static void dispatch_ctr_lp() { * once we're done serving endpoint zero, but not okay if * there are multiple nonzero endpoint transfers to * handle. */ - if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) + if (dispatch_endpt_zero(istr & USB_ISTR_DIR)) { return; + } } else { dispatch_endpt(ep_id); } |