SAMA5: Backport some USB device ZLP logic from the SAMV7

This commit is contained in:
Gregory Nutt 2015-12-08 17:36:46 -06:00
parent 9135afa8c1
commit c26a624a9f
2 changed files with 31 additions and 25 deletions

View File

@ -969,11 +969,20 @@ static void sam_dma_wrsetup(struct sam_usbdev_s *priv, struct sam_ep_s *privep,
if (remaining > DMA_MAX_FIFO_SIZE)
{
privreq->inflight = DMA_MAX_FIFO_SIZE;
privep->zlpneeded = false;
}
else
#endif
{
privreq->inflight = remaining;
/* If the size is an exact multple of full packets, then note if
* we need to send a zero length packet next.
*/
privep->zlpneeded =
((privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0 &&
(remaining % privep->ep.maxpacket) == 0);
}
/* And perform the single DMA transfer.
@ -1223,9 +1232,19 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv,
* the request.
*/
if (nbytes >= privep->ep.maxpacket)
privep->zlpneeded = false;
if (nbytes > privep->ep.maxpacket)
{
nbytes = privep->ep.maxpacket;
nbytes = privep->ep.maxpacket;
}
else if (nbytes == privep->ep.maxpacket)
{
/* If the size is exactly a full packet, then note if we need to
* send a zero length packet next.
*/
privep->zlpneeded =
((privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0);
}
/* This is the new number of bytes "in-flight" */
@ -1352,26 +1371,6 @@ static int sam_req_write(struct sam_usbdev_s *priv, struct sam_ep_s *privep)
bytesleft = privreq->req.len - privreq->req.xfrd;
if (bytesleft > 0)
{
/* If the size is exactly a full packet, then note if we need to
* send a zero length packet next.
*/
if (bytesleft == privep->ep.maxpacket &&
(privreq->req.flags & USBDEV_REQFLAGS_NULLPKT) != 0)
{
/* Next time we get here, bytesleft will be zero and zlpneeded
* will be set.
*/
privep->zlpneeded = true;
}
else
{
/* No zero packet is forthcoming (maybe later) */
privep->zlpneeded = false;
}
/* The way that we handle the transfer is going to depend on
* whether or not this endpoint supports DMA. In either case
* the endpoint state will transition to SENDING.
@ -2392,6 +2391,12 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
/* This is an IN endpoint. Continuing processing the write
* request. We must call sam_req_write in the IDLE state
* with the number of bytes transferred in 'inflight'
*
* REVISIT: On the SAMV7, I found that you really need to
* wait for the TX completion interrupt before calling
* sam_req_write(). For the SAMV7, the logic here just
* enables that TX completion interrupt. The symptom of
* the problem was occassional missing zero-length packets.
*/
DEBUGASSERT(USB_ISEPIN(privep->ep.eplog));
@ -2451,7 +2456,7 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
USB_ISEPOUT(privep->ep.eplog));
/* Get the number of bytes transferred from the DMA status.
*
*
* BUFF_COUNT holds the number of untransmitted bytes. In this case,
* BUFF_COUNT should not be zero. BUFF_COUNT was set to the
* 'inflight' count when the DMA started so the difference will

View File

@ -1027,7 +1027,7 @@ static void sam_dma_wrsetup(struct sam_usbdev_s *priv, struct sam_ep_s *privep,
{
privreq->inflight = remaining;
/* If the size is an exact multple of full packets, then note if that
/* If the size is an exact multple of full packets, then note if
* we need to send a zero length packet next.
*/
@ -1284,7 +1284,7 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv,
privep->zlpneeded = false;
if (nbytes > privep->ep.maxpacket)
{
nbytes = privep->ep.maxpacket;
nbytes = privep->ep.maxpacket;
}
else if (nbytes == privep->ep.maxpacket)
{
@ -2497,6 +2497,7 @@ static void sam_dma_interrupt(struct sam_usbdev_s *priv, int epno)
DEBUGASSERT(USB_ISEPIN(privep->ep.eplog));
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTICR(epno));
#if 1 /* Wait for TXINI */
sam_putreg(USBHS_DEVEPTINT_TXINI, SAM_USBHS_DEVEPTIER(epno));
#else