SAM4E-EK UDP: prevent some bad recursive behavior
This commit is contained in:
parent
266ef59280
commit
293b5d7723
@ -303,6 +303,7 @@ struct sam_ep_s
|
|||||||
uint8_t halted:1; /* true: Endpoint feature halted */
|
uint8_t halted:1; /* true: Endpoint feature halted */
|
||||||
uint8_t zlpneeded:1; /* Zero length packet needed at end of transfer */
|
uint8_t zlpneeded:1; /* Zero length packet needed at end of transfer */
|
||||||
uint8_t zlpsent:1; /* Zero length packet has been sent */
|
uint8_t zlpsent:1; /* Zero length packet has been sent */
|
||||||
|
uint8_t wqbusy:1; /* Write request queue is busy (recursion avoidance kludge) */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sam_usbdev_s
|
struct sam_usbdev_s
|
||||||
@ -851,7 +852,7 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv,
|
|||||||
|
|
||||||
/* Get the number of bytes remaining to be sent. */
|
/* Get the number of bytes remaining to be sent. */
|
||||||
|
|
||||||
DEBUGASSERT(privreq->req.xfrd <= privreq->req.len);
|
DEBUGASSERT(privreq->req.xfrd < privreq->req.len);
|
||||||
nbytes = privreq->req.len - privreq->req.xfrd;
|
nbytes = privreq->req.len - privreq->req.xfrd;
|
||||||
|
|
||||||
/* Either send the maxpacketsize or all of the remaining data in
|
/* Either send the maxpacketsize or all of the remaining data in
|
||||||
@ -868,24 +869,19 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv,
|
|||||||
privreq->inflight = nbytes;
|
privreq->inflight = nbytes;
|
||||||
usbtrace(TRACE_WRITE(USB_EPNO(privep->ep.eplog)), nbytes);
|
usbtrace(TRACE_WRITE(USB_EPNO(privep->ep.eplog)), nbytes);
|
||||||
|
|
||||||
/* Check if we are sending a zero length packet */
|
/* The new buffer pointer is the start of the buffer plus the number of
|
||||||
|
* bytes successfully transferred plus the number of bytes previously
|
||||||
|
* "in-flight".
|
||||||
|
*/
|
||||||
|
|
||||||
if (nbytes > 0)
|
buf = privreq->req.buf + privreq->req.xfrd;
|
||||||
|
|
||||||
|
/* Write packet in the FIFO buffer */
|
||||||
|
|
||||||
|
fifo = (volatile uint32_t *)SAM_UDPEP_FDR(epno);
|
||||||
|
for (; nbytes; nbytes--)
|
||||||
{
|
{
|
||||||
/* The new buffer pointer is the start of the buffer plus the number of
|
*fifo = (uint32_t)(*buf++);
|
||||||
* bytes successfully transferred plus the number of bytes previously
|
|
||||||
* "in-flight".
|
|
||||||
*/
|
|
||||||
|
|
||||||
buf = privreq->req.buf + privreq->req.xfrd;
|
|
||||||
|
|
||||||
/* Write packet in the FIFO buffer */
|
|
||||||
|
|
||||||
fifo = (volatile uint32_t *)SAM_UDPEP_FDR(epno);
|
|
||||||
for (; nbytes; nbytes--)
|
|
||||||
{
|
|
||||||
*fifo = (uint32_t)(*buf++);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Indicate that there we are in the sending state (even if this is a
|
/* Indicate that there we are in the sending state (even if this is a
|
||||||
@ -1044,20 +1040,27 @@ static int sam_req_write(struct sam_usbdev_s *priv, struct sam_ep_s *privep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If all of the bytes were sent (including any final zero length
|
/* If all of the bytes were sent (including any final zero length
|
||||||
* packet) then we are finished with the request buffer), then we can
|
* packet) then we are finished with the request buffer and we can
|
||||||
* return the request buffer to the class driver. The transfer may
|
* return the request buffer to the class driver. The state will
|
||||||
* not finished yet, however. There may still be bytes in flight.
|
* remain IDLE only if nothing else was put in flight.
|
||||||
* The transfer is truly finished when we are called again and the
|
*
|
||||||
* request buffer is empty.
|
* Note that we will then loop to check to check the next queued
|
||||||
|
* write request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (privreq->req.len >= privreq->req.xfrd &&
|
if (privep->epstate == UDP_EPSTATE_IDLE)
|
||||||
privep->epstate == UDP_EPSTATE_IDLE)
|
|
||||||
{
|
{
|
||||||
/* Return the write request to the class driver */
|
/* Return the write request to the class driver. Set the wqbusy
|
||||||
|
* bit to prevent being called recursively from any new submission
|
||||||
|
* generated by returning the write request.
|
||||||
|
*/
|
||||||
|
|
||||||
usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
|
usbtrace(TRACE_COMPLETE(epno), privreq->req.xfrd);
|
||||||
|
DEBUGASSERT(privreq->req.len == privreq->req.xfrd);
|
||||||
|
|
||||||
|
privep->wqbusy = true;
|
||||||
sam_req_complete(privep, OK);
|
sam_req_complete(privep, OK);
|
||||||
|
privep->wqbusy = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2472,6 +2475,7 @@ static void sam_ep_reset(struct sam_usbdev_s *priv, uint8_t epno)
|
|||||||
privep->halted = false;
|
privep->halted = false;
|
||||||
privep->zlpneeded = false;
|
privep->zlpneeded = false;
|
||||||
privep->zlpsent = false;
|
privep->zlpsent = false;
|
||||||
|
privep->wqbusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -3078,9 +3082,6 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
|||||||
epno = USB_EPNO(ep->eplog);
|
epno = USB_EPNO(ep->eplog);
|
||||||
req->result = -EINPROGRESS;
|
req->result = -EINPROGRESS;
|
||||||
req->xfrd = 0;
|
req->xfrd = 0;
|
||||||
privreq->inflight = 0;
|
|
||||||
privep->zlpneeded = false;
|
|
||||||
privep->zlpsent = false;
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
|
||||||
/* Handle IN (device-to-host) requests. NOTE: If the class device is
|
/* Handle IN (device-to-host) requests. NOTE: If the class device is
|
||||||
@ -3111,9 +3112,11 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
|||||||
sam_req_enqueue(&privep->reqq, privreq);
|
sam_req_enqueue(&privep->reqq, privreq);
|
||||||
usbtrace(TRACE_INREQQUEUED(epno), req->len);
|
usbtrace(TRACE_INREQQUEUED(epno), req->len);
|
||||||
|
|
||||||
/* If the IN endpoint is IDLE, then transfer the data now */
|
/* If the IN endpoint is IDLE and there is not write queue
|
||||||
|
* processing in progress, then transfer the data now.
|
||||||
|
*/
|
||||||
|
|
||||||
if (privep->epstate == UDP_EPSTATE_IDLE)
|
if (privep->epstate == UDP_EPSTATE_IDLE && !privep->wqbusy)
|
||||||
{
|
{
|
||||||
ret = sam_req_write(priv, privep);
|
ret = sam_req_write(priv, privep);
|
||||||
}
|
}
|
||||||
@ -3561,6 +3564,7 @@ static void sam_reset(struct sam_usbdev_s *priv)
|
|||||||
privep->halted = false;
|
privep->halted = false;
|
||||||
privep->zlpneeded = false;
|
privep->zlpneeded = false;
|
||||||
privep->zlpsent = false;
|
privep->zlpsent = false;
|
||||||
|
privep->wqbusy = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Re-configure the USB controller in its initial, unconnected state */
|
/* Re-configure the USB controller in its initial, unconnected state */
|
||||||
|
@ -276,10 +276,11 @@ Loading Code into SRAM with J-Link
|
|||||||
J-Link> setpc <address of __start>
|
J-Link> setpc <address of __start>
|
||||||
J-Link> ... start debugging ...
|
J-Link> ... start debugging ...
|
||||||
|
|
||||||
STATUS: As of this writing, I have no been successful writing to FLASH
|
STATUS: As of this writing, I have not been successful writing to FLASH
|
||||||
using the GDB server. I think that this is because of issues with GPNVM1
|
using the GDB server; the write succeeds with no complaints, but the contents
|
||||||
settings and flash lock bits. In any event, the GDB server works great for
|
of the FLASH memory remain unchanged. This may be because of issues with
|
||||||
debugging after writing the program to FLASH using SAM-BA.
|
GPNVM1 settings and flash lock bits? In any event, the GDB server works
|
||||||
|
great for debugging after writing the program to FLASH using SAM-BA.
|
||||||
|
|
||||||
Writing to FLASH using SAM-BA
|
Writing to FLASH using SAM-BA
|
||||||
=============================
|
=============================
|
||||||
@ -1153,6 +1154,9 @@ Configurations
|
|||||||
This is another NSH example. If differs from the 'nsh' configuration
|
This is another NSH example. If differs from the 'nsh' configuration
|
||||||
in that this configurations uses a USB serial device for console I/O.
|
in that this configurations uses a USB serial device for console I/O.
|
||||||
|
|
||||||
|
STATUS:
|
||||||
|
2014-3-22: Partially functional, but not yet reliable.
|
||||||
|
|
||||||
NOTES:
|
NOTES:
|
||||||
|
|
||||||
1. See the NOTES in the description of the nsh configuration. Those
|
1. See the NOTES in the description of the nsh configuration. Those
|
||||||
|
Loading…
Reference in New Issue
Block a user