Merged in gnagflow/nuttx (pull request #105)

SAM3/4 USB and USBMSC fixes.
This commit is contained in:
Gregory Nutt
2016-07-24 07:37:35 -06:00
5 changed files with 76 additions and 27 deletions
+1 -1
View File
@@ -692,8 +692,8 @@ static void up_disableallints(struct up_dev_s *priv, uint32_t *imr)
static int up_setup(struct uart_dev_s *dev)
{
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
#ifndef CONFIG_SUPPRESS_UART_CONFIG
struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
uint32_t regval;
uint32_t imr;
+68 -21
View File
@@ -305,6 +305,7 @@ struct sam_ep_s
uint8_t zlpneeded:1; /* Zero length packet needed at end of transfer */
uint8_t zlpsent:1; /* Zero length packet has been sent */
uint8_t txbusy:1; /* Write request queue is busy (recursion avoidance kludge) */
uint8_t lastbank:1; /* Last bank we read data from */
};
struct sam_usbdev_s
@@ -1188,9 +1189,14 @@ static int sam_req_read(struct sam_usbdev_s *priv, struct sam_ep_s *privep,
/* We get here when an RXDATABK0/1 interrupt occurs. That interrupt
* cannot be cleared until all of the data has been taken from the RX
* FIFO. But we can
* FIFO.
*
* Also, we need to remember which bank we read last so the interrupt handler
* can determine the correct bank read sequence for future reads.
*/
privep->lastbank = bank;
sam_csr_clrbits(epno, bank ? UDPEP_CSR_RXDATABK1 : UDPEP_CSR_RXDATABK0);
/* Complete the transfer immediately and give the data to the class
@@ -1873,7 +1879,6 @@ static void sam_ep_bankinterrupt(struct sam_usbdev_s *priv,
* transferred from the FIFO.
*/
privep->epstate = UDP_EPSTATE_IDLE;
(void)sam_req_read(priv, privep, pktsize, bank);
}
@@ -2020,34 +2025,75 @@ static void sam_ep_interrupt(struct sam_usbdev_s *priv, int epno)
}
}
/* OUT packet received in data bank 0 */
if ((csr & UDPEP_CSR_RXDATABK0) != 0)
/* OUT packet received.
*
* OUT packets are received in two banks. The hardware does not provide
* information about which bank has been filled last. Therefore we need to
* keep track about which bank we read last to figure out which bank(s) we
* need to read next.
*
* When we get here either none, one or both banks can be filled with data.
* Depending on which bank we read last and which bank(s) contain data we
* need to correctly sequence the FIFO reads:
*
* case lastbank bk0 bk1 read sequence
* 1. 0 0 0 No data to read
* 2. 0 1 0 Only read bank 0
* 3. 0 0 1 Only read bank 1
* 4. 0 1 1 Read bank 1, then read bank 0
*
* 5. 1 0 0 No data to read
* 6. 1 1 0 Only read bank 0
* 7. 1 0 1 Only read bank 1 (should not happen)
* 8. 1 1 1 Read bank 0, then read bank 1
*
* lastbank will be updated in sam_req_read() after the FIFO has been read
* and clear RXDATABKx.
*/
bool bk0 = (csr & UDPEP_CSR_RXDATABK0) != 0;
bool bk1 = (csr & UDPEP_CSR_RXDATABK1) != 0;
/* 2. and 6. - Only read bank 0 */
if (bk0 && !bk1)
{
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_RXDATABK0), (uint16_t)csr);
/* Handle data received on Bank 0. sam_ep_bankinterrupt will
* clear the RXDATABK0 interrupt once that data has been
* transferred from the FIFO.
*/
sam_ep_bankinterrupt(priv, privep, csr, 0);
}
/* OUT packet received in data bank 1 */
else if ((csr & UDPEP_CSR_RXDATABK1) != 0)
/* 3. and 7. - Only read bank 1*/
else if (!bk0 && bk1)
{
#ifdef CONFIG_DEBUG
if (privep->lastbank == 1)
{
ulldbg("Unexpected USB RX case.\n");
}
#endif
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_RXDATABK1), (uint16_t)csr);
DEBUGASSERT(SAM_UDP_NBANKS(epno) > 1);
/* Handle data received on Bank 1. sam_ep_bankinterrupt will
* clear the RXDATABK1 interrupt once that data has been
* transferred from the FIFO.
*/
sam_ep_bankinterrupt(priv, privep, csr, 1);
}
else if (bk0 && bk1)
{
/* 4. - Read bank 1, then read bank 0 */
if (privep->lastbank == 0)
{
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_RXDATABK1), (uint16_t)csr);
sam_ep_bankinterrupt(priv, privep, csr, 1);
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_RXDATABK0), (uint16_t)csr);
sam_ep_bankinterrupt(priv, privep, csr, 0);
}
/* 8. - Read bank 0, then read bank 1 */
else
{
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_RXDATABK0), (uint16_t)csr);
sam_ep_bankinterrupt(priv, privep, csr, 0);
usbtrace(TRACE_INTDECODE(SAM_TRACEINTID_RXDATABK1), (uint16_t)csr);
sam_ep_bankinterrupt(priv, privep, csr, 1);
}
}
/* STALL sent */
@@ -2510,6 +2556,7 @@ static void sam_ep_reset(struct sam_usbdev_s *priv, uint8_t epno)
privep->zlpneeded = false;
privep->zlpsent = false;
privep->txbusy = false;
privep->lastbank = 1;
}
/****************************************************************************
+1 -1
View File
@@ -177,7 +177,7 @@ const struct trace_msg_t g_usb_trace_strings_clserror[] =
TRACE_STR(USBMSC_TRACEERR_CMDREADREADFAIL),
TRACE_STR(USBMSC_TRACEERR_CMDREADSUBMIT),
TRACE_STR(USBMSC_TRACEERR_CMDREADWRRQEMPTY),
TRACE_STR(USBMSC_TRACEERR_CMDSTATUSRDREQLISTEMPTY),
TRACE_STR(USBMSC_TRACEERR_CMDSTATUSWRREQLISTEMPTY),
TRACE_STR(USBMSC_TRACEERR_CMDUNEVIOLATION),
TRACE_STR(USBMSC_TRACEERR_CMDWRITERDSUBMIT),
TRACE_STR(USBMSC_TRACEERR_CMDWRITERDRQEMPTY),
+5 -3
View File
@@ -2263,7 +2263,9 @@ static int usbmsc_cmdwritestate(FAR struct usbmsc_dev_s *priv)
* data to be written.
*/
irqstate_t flags = enter_critical_section();
privreq = (FAR struct usbmsc_req_s *)sq_remfirst(&priv->rdreqlist);
leave_critical_section(flags);
/* If there no request data available, then just return an error.
* This will cause us to remain in the CMDWRITE state. When a filled request is
@@ -2537,7 +2539,7 @@ static int usbmsc_cmdstatusstate(FAR struct usbmsc_dev_s *priv)
if (!privreq)
{
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDSTATUSRDREQLISTEMPTY), 0);
usbtrace(TRACE_CLSERROR(USBMSC_TRACEERR_CMDSTATUSWRREQLISTEMPTY), 0);
return -ENOMEM;
}
@@ -2639,8 +2641,8 @@ int usbmsc_scsi_main(int argc, char *argv[])
uinfo("Waiting to be signalled\n");
usbmsc_scsi_lock(priv);
priv->thstate = USBMSC_STATE_STARTED;
while ((priv->theventset & USBMSC_EVENT_READY) != 0 &&
(priv->theventset & USBMSC_EVENT_TERMINATEREQUEST) != 0)
while ((priv->theventset & USBMSC_EVENT_READY) == 0 &&
(priv->theventset & USBMSC_EVENT_TERMINATEREQUEST) == 0)
{
usbmsc_scsi_wait(priv);
}
+1 -1
View File
@@ -295,7 +295,7 @@
#define USBMSC_TRACEERR_CMDREADREADFAIL 0x0094
#define USBMSC_TRACEERR_CMDREADSUBMIT 0x0095
#define USBMSC_TRACEERR_CMDREADWRRQEMPTY 0x0096
#define USBMSC_TRACEERR_CMDSTATUSRDREQLISTEMPTY 0x0097
#define USBMSC_TRACEERR_CMDSTATUSWRREQLISTEMPTY 0x0097
#define USBMSC_TRACEERR_CMDUNEVIOLATION 0x0098
#define USBMSC_TRACEERR_CMDWRITERDSUBMIT 0x0099
#define USBMSC_TRACEERR_CMDWRITERDRQEMPTY 0x009a