SAMV7 USBHS Device: Reorder some interrupt handling logic to avoid losing an interrupt and to avoid a race condition
This commit is contained in:
parent
52d499ba33
commit
c75e594350
@ -2498,7 +2498,14 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
DEBUGASSERT(USB_ISEPIN(privep->ep.eplog));
|
DEBUGASSERT(USB_ISEPIN(privep->ep.eplog));
|
||||||
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTICR(epno));
|
|
||||||
|
/* Assume that will wait for the TXIN interrupt. Enable it
|
||||||
|
* now. We do this PRIOR to sampling the BYCT and BUSBK
|
||||||
|
* fields to avoid the race condition that would occur if
|
||||||
|
* the interrupt were enabled afterward.
|
||||||
|
*/
|
||||||
|
|
||||||
|
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTIER(epno));
|
||||||
|
|
||||||
/* Have all of the bytes in the FIFO been transmitted to the
|
/* Have all of the bytes in the FIFO been transmitted to the
|
||||||
* host?
|
* host?
|
||||||
@ -2521,23 +2528,21 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
|
|||||||
if (byct > 0 || nbusybk > 0)
|
if (byct > 0 || nbusybk > 0)
|
||||||
{
|
{
|
||||||
/* Not all of the data has been sent to the host. A TXIN
|
/* Not all of the data has been sent to the host. A TXIN
|
||||||
* interrupt will be generated later. Enable the TXIN
|
* interrupt will be generated later. We have already enabled
|
||||||
* interrupt now and wait for the transfer to complete.
|
* the TXIN interrupt. Now wait for the transfer to complete.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTIER(epno));
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* All bytes have been sent to the host. We must call
|
/* All bytes have been sent to the host. We must call
|
||||||
* sam_req_write() now in the IDLE state with the number of
|
* sam_req_write() now in the IDLE state with the number of
|
||||||
* bytes transferred in 'inflight'
|
* bytes transferred in 'inflight'. First disable and
|
||||||
*
|
* clear the TXIN interrupt.
|
||||||
* REVISIT: Isn't there a race condition here? Could TXIN
|
|
||||||
* have fired just before calculating byct? Could TXIN be
|
|
||||||
* pending here?
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTIDR(epno));
|
||||||
|
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTICR(epno));
|
||||||
|
|
||||||
privep->epstate = USBHS_EPSTATE_IDLE;
|
privep->epstate = USBHS_EPSTATE_IDLE;
|
||||||
(void)sam_req_write(priv, privep);
|
(void)sam_req_write(priv, privep);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user