2015-08-10 01:14 AM
Is there any way to cancel OUT transfer (receive) on STM32 using CubeF4 library?
I use USB in my device to communicate with PC (STM32 is ''device'', PC is ''host''). If client (PC side) program is ''crashed'' and my software protocol is not terminated correctly I have to send ''reset'' command to control (0) pipe of USB and handle it on STM32 side. The problem is that before the client application crashed last time, MCU firmware used USBD_LL_PrepareReceive function and device is waiting for data from PC! I _have_ to cancel that transfer without resetting whole USB device stack. Is there any way to do that with CubeF4 library?2015-08-10 04:00 AM
OK, I got it Edit: no, bad code!
PCD_HandleTypeDef *hpcd =hUsbDevice.pData; USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; USB_OTG_OUTEndpointTypeDef* outEp = GetOutEndpoint(&hUsbDevice, NDC_IF0_OUT_EP); USB_OTG_INEndpointTypeDef* inEp = GetInEndpoint(&hUsbDevice, NDC_IF0_IN_EP); //set global OUT NAK USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM; if((USBx->GINTSTS & USB_OTG_GINTMSK_GONAKEFFM) == 0){ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK; while((USBx->GINTSTS & USB_OTG_GINTMSK_GONAKEFFM) == 0){} } //begin disable EP USBx_DEVICE->DOEPMSK &= ~USB_OTG_DOEPMSK_EPDM; //Mask EP disabled interrupt for polling outEp->DOEPCTL |= USB_OTG_DOEPCTL_SNAK | USB_OTG_DOEPCTL_EPDIS; //Begin disable while((outEp->DOEPINT & USB_OTG_DOEPINT_EPDISD) == 0){} //Wait for disabled flag outEp->DOEPINT = USB_OTG_DOEPINT_EPDISD; //Clear endpoint disabled interrupt USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_EPDM;//Unmask EP disabled interrupt USBD_LL_FlushEP(&hUsbDevice, NDC_IF0_OUT_EP); //Flush EP FIFO outEp->DOEPTSIZ = 0; USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK; //Disable global OUT NAK //Disable IN endpoint //stop tramsmission USBx_DEVICE->DIEPMSK &= ~USB_OTG_DIEPMSK_INEPNEM; //mask NAK effective interrupt inEp->DIEPCTL |= USB_OTG_DIEPCTL_SNAK; while((inEp->DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0){} //wait 'till stopped //disable endpoint USBx_DEVICE->DIEPMSK &= ~USB_OTG_DIEPMSK_EPDM; //Mask EP disabled interrupt for polling inEp->DIEPCTL |= USB_OTG_DIEPCTL_SNAK | USB_OTG_DIEPCTL_EPDIS; //begin disable while((inEp->DIEPINT & USB_OTG_DIEPINT_EPDISD) == 0){}//wait for disable done inEp->DIEPINT = USB_OTG_DIEPINT_EPDISD; //Clear endpoint disabled interrupt USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_EPDM; //unmask; USBD_LL_FlushEP(&hUsbDevice, NDC_IF0_IN_EP); inEp->DIEPTSIZ = 0; //unmask NAK EFFECTIVE interrupt USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_INEPNEM; inEp->DIEPCTL |= USB_OTG_DIEPCTL_CNAK; while((inEp->DIEPCTL & USB_OTG_DIEPCTL_NAKSTS) != 0){} inEp->DIEPINT = USB_OTG_DIEPINT_INEPNE; //Clear NAK effective interrupt2015-09-23 07:45 AM
Code in my previous post is not working good if DMA mode enabled in USB.
Here is correct version: portENTER_CRITICAL(); PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)hUsbDevice.pData; USB_OTG_GlobalTypeDef *USBx = hpcd->Instance; USB_OTG_OUTEndpointTypeDef* outEp = USBx_OUTEP(hpcd->OUT_ep[NDC_IF0_OUT_EP & 0x7F].num); USB_OTG_INEndpointTypeDef* inEp = USBx_INEP(hpcd->IN_ep[NDC_IF0_IN_EP & 0x7F].num); //Disable OUT endpoint if((outEp->DOEPCTL & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA){ //set global OUT NAK USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM; if((USBx->GINTSTS & USB_OTG_GINTMSK_GONAKEFFM) == 0){ USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK; while((USBx->GINTSTS & USB_OTG_GINTMSK_GONAKEFFM) == 0){} } //begin disable OUT EP USBx_DEVICE->DOEPMSK &= ~USB_OTG_DOEPMSK_EPDM; //Mask EP disabled interrupt for polling outEp->DOEPCTL |= USB_OTG_DOEPCTL_SNAK | USB_OTG_DOEPCTL_EPDIS; //Begin disable while((outEp->DOEPINT & USB_OTG_DOEPINT_EPDISD) == 0){} //Wait for disabled flag outEp->DOEPINT = USB_OTG_DOEPINT_EPDISD; //Clear endpoint disabled interrupt USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_EPDM;//Unmask EP disabled interrupt USBD_LL_FlushEP(&hUsbDevice, NDC_IF0_OUT_EP); //Flush EP FIFO USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK; //Disable global OUT NAK USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM; } outEp->DOEPTSIZ = 0; //Disable IN endpoint if ((inEp->DIEPCTL & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA){ USBx_DEVICE->DIEPMSK &= ~USB_OTG_DIEPMSK_INEPNEM; //mask NAK effective interrupt USBx_DEVICE->DIEPMSK &= ~USB_OTG_DIEPMSK_EPDM; //Mask EP disabled interrupt for polling inEp->DIEPCTL |= USB_OTG_DIEPCTL_SNAK; while((inEp->DIEPINT & USB_OTG_DIEPINT_INEPNE) == 0){} //wait 'till stopped inEp->DIEPCTL |= (USB_OTG_DIEPCTL_EPDIS | USB_OTG_DIEPCTL_SNAK); while((inEp->DIEPINT & USB_OTG_DIEPINT_EPDISD) == 0){}//wait for disable done inEp->DIEPINT = USB_OTG_DIEPINT_EPDISD; //Clear endpoint disabled interrupt USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_EPDM; //unmask; USBD_LL_FlushEP(&hUsbDevice, NDC_IF0_IN_EP); inEp->DIEPCTL |= USB_OTG_DIEPCTL_CNAK; while((inEp->DIEPCTL & USB_OTG_DIEPCTL_NAKSTS) != 0){} inEp->DIEPINT = USB_OTG_DIEPINT_INEPNE; //Clear NAK effective interrupt //unmask NAK EFFECTIVE interrupt USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_INEPNEM; } inEp->DIEPTSIZ = 0; //can clear custom software RX/TX buffers here //... portEXIT_CRITICAL();2015-10-06 11:43 AM
Update: small bugfixes in interrupts handling, now forking perfect in any tested conditions!