cancel
Showing results for 
Search instead for 
Did you mean: 

How to cancel transfer on OUT pipe of USB?

l-proger
Associate II
Posted on August 10, 2015 at 10:14

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?
3 REPLIES 3
l-proger
Associate II
Posted on August 10, 2015 at 13:00

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 interrupt

l-proger
Associate II
Posted on September 23, 2015 at 16:45

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();

l-proger
Associate II
Posted on October 06, 2015 at 20:43

Update: small bugfixes in interrupts handling, now forking perfect in any tested conditions!