summaryrefslogtreecommitdiff
path: root/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c')
-rw-r--r--nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c150
1 files changed, 87 insertions, 63 deletions
diff --git a/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c b/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
index d84df0aac..c33a39ea6 100644
--- a/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
+++ b/nuttx/arch/mips/src/pic32mx/pic32mx-usbdev.c
@@ -118,7 +118,7 @@
/* Endpoint Definitions */
-#ifndef CONFIG_USB_PINGPONG
+#ifndef CONFIG_PIC32MX_USBDEV_PINGPONG
# define USB_NEXT_PINGPONG (0)
# define EP0_OUT_EVEN (0)
# define EP0_OUT_ODD (0)
@@ -221,20 +221,21 @@
#define PIC32MX_TRACEINTID_GETSTATUS 0x0013
#define PIC32MX_TRACEINTID_IFGETSTATUS 0x0014
#define PIC32MX_TRACEINTID_TRNC 0x0015
-#define PIC32MX_TRACEINTID_INTERRUPT 0x0016
-#define PIC32MX_TRACEINTID_NOSTDREQ 0x0017
-#define PIC32MX_TRACEINTID_RESET 0x0018
-#define PIC32MX_TRACEINTID_SETCONFIG 0x0019
-#define PIC32MX_TRACEINTID_SETFEATURE 0x001a
-#define PIC32MX_TRACEINTID_IDLE 0x001b
-#define PIC32MX_TRACEINTID_SYNCHFRAME 0x001c
-#define PIC32MX_TRACEINTID_WKUP 0x001d
-#define PIC32MX_TRACEINTID_T1MSEC 0x001e
-#define PIC32MX_TRACEINTID_OTGID 0x001f
-#define PIC32MX_TRACEINTID_STALL 0x0020
-#define PIC32MX_TRACEINTID_UERR 0x0021
-#define PIC32MX_TRACEINTID_SUSPENDED 0x0022
-#define PIC32MX_TRACEINTID_WAITRESET 0x0023
+#define PIC32MX_TRACEINTID_TRNCS 0x0016
+#define PIC32MX_TRACEINTID_INTERRUPT 0x0017
+#define PIC32MX_TRACEINTID_NOSTDREQ 0x0018
+#define PIC32MX_TRACEINTID_RESET 0x0019
+#define PIC32MX_TRACEINTID_SETCONFIG 0x001a
+#define PIC32MX_TRACEINTID_SETFEATURE 0x001b
+#define PIC32MX_TRACEINTID_IDLE 0x001c
+#define PIC32MX_TRACEINTID_SYNCHFRAME 0x001d
+#define PIC32MX_TRACEINTID_WKUP 0x001e
+#define PIC32MX_TRACEINTID_T1MSEC 0x001f
+#define PIC32MX_TRACEINTID_OTGID 0x0020
+#define PIC32MX_TRACEINTID_STALL 0x0021
+#define PIC32MX_TRACEINTID_UERR 0x0022
+#define PIC32MX_TRACEINTID_SUSPENDED 0x0023
+#define PIC32MX_TRACEINTID_WAITRESET 0x0024
/* Misc Helper Macros *******************************************************/
@@ -351,20 +352,17 @@ struct pic32mx_ep_s
* to struct pic32mx_ep_s.
*/
- struct usbdev_ep_s ep; /* Standard endpoint structure */
+ struct usbdev_ep_s ep; /* Standard endpoint structure */
/* PIC32MX-specific fields */
- struct pic32mx_usbdev_s *dev; /* Reference to private driver data */
- struct pic32mx_req_s *head; /* Request list for this endpoint */
- struct pic32mx_req_s *tail;
- uint8_t stalled:1; /* true: Endpoint is stalled */
- uint8_t halted:1; /* true: Endpoint feature halted */
- uint8_t txbusy:1; /* true: TX endpoint FIFO full */
- uint8_t txnullpkt:1; /* Null packet needed at end of transfer */
-#ifdef CONFIG_USB_PINGPONG
- uint8_t ep0ready:1 /* EP0 OUT already prepared */
-#endif
+ struct pic32mx_usbdev_s *dev; /* Reference to private driver data */
+ struct pic32mx_req_s *head; /* Request list for this endpoint */
+ struct pic32mx_req_s *tail;
+ uint8_t stalled:1; /* true: Endpoint is stalled */
+ uint8_t halted:1; /* true: Endpoint feature halted */
+ uint8_t txbusy:1; /* true: TX endpoint FIFO full */
+ uint8_t txnullpkt:1; /* Null packet needed at end of transfer */
volatile struct usbotg_bdtentry_s *bdtin; /* BDT entry for the IN transaction*/
volatile struct usbotg_bdtentry_s *bdtout; /* BDT entry for the OUT transaction */
};
@@ -389,6 +387,9 @@ struct pic32mx_usbdev_s
uint8_t ctrlstate; /* Control EP state (see enum pic32mx_ctrlstate_e) */
uint8_t selfpowered:1; /* 1: Device is self powered */
uint8_t rwakeup:1; /* 1: Device supports remote wakeup */
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
+ uint8_t ep0ready:1; /* EP0 OUT already prepared */
+#endif
uint16_t epavail; /* Bitset of available endpoints */
/* The endpoint list */
@@ -535,7 +536,7 @@ static const struct usbdev_ops_s g_devops =
/* Buffer Descriptor Table */
-#ifndef CONFIG_USB_PINGPONG
+#ifndef CONFIG_PIC32MX_USBDEV_PINGPONG
volatile struct usbotg_bdtentry_s
g_bdt[(PIC32MX_NENDPOINTS + 1) * 2] __attribute__ ((aligned(512)));
#else
@@ -747,7 +748,7 @@ static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
/* Clear status and toggle the DTS bit if required */
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
/* Clear all bits in the status but preserve the data toggle bit */
status = bdt->status & USB_BDT_DATA01;
@@ -779,7 +780,7 @@ static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
/* Point to the next ping pong buffer. */
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_NEXT_PINGPONG;
#endif
@@ -1044,7 +1045,9 @@ static int pic32mx_ep0rdsetup(struct pic32mx_usbdev_s *priv, uint8_t *dest,
* else.
*/
- status = bdt->status & ~(USB_BDT_UOWN|USB_BDT_BYTECOUNT_MASK|USB_BDT_DATA01);
+ status = bdt->status;
+ status &= ~(USB_BDT_BSTALL | USB_BDT_NINC | USB_BDT_KEEP| USB_BDT_UOWN |
+ USB_BDT_BYTECOUNT_MASK | USB_BDT_DATA01);
bdt->status = status;
/* Set the data pointer, data length, and enable the endpoint */
@@ -1091,7 +1094,7 @@ static int pic32mx_rdsetup(struct pic32mx_usbdev_s *priv,
/* Toggle the DATA01 bit if required for ping pong support */
-#ifndef CONFIG_USB_PINGPONG
+#ifndef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_BDT_DATA01;
#endif
@@ -1105,7 +1108,7 @@ static int pic32mx_rdsetup(struct pic32mx_usbdev_s *priv,
/* Point to the next ping pong buffer. */
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_NEXT_PINGPONG;
#endif
@@ -1332,7 +1335,7 @@ static void pic32mx_ep0nextsetup(struct pic32mx_usbdev_s *priv)
status = bdt->status & ~USB_BDT_UOWN;
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_NEXT_PINGPONG;
#endif
status &= ~USB_BDT_UOWN;
@@ -1351,7 +1354,7 @@ static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv,
{
struct pic32mx_ep_s *ep0 = &priv->eplist[EP0];
volatile struct usbotg_bdtentry_s *bdtout;
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
volatile struct usbotg_bdtentry_s *bdtnext;
#endif
uint16_t status;
@@ -1359,15 +1362,15 @@ static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv,
/* Which BDT are we working on new? Which one will be next */
bdtout = ep0->bdtout;
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
if (bdtout == &g_bdt[EP0_OUT_EVEN])
{
- btdnext = &g_bdt[EP0_OUT_ODD]
+ bdtnext = &g_bdt[EP0_OUT_ODD];
}
else
{
DEBUGASSERT(bdtout == &g_bdt[EP0_OUT_ODD]);
- btdnext = &g_bdt[EP0_OUT_EVEN]
+ bdtnext = &g_bdt[EP0_OUT_EVEN];
}
#endif
@@ -1384,26 +1387,34 @@ static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv,
* buffer address should be pointed to priv->ctrl.
*/
- status = bdtout->status & ~(USB_BDT_BYTECOUNT_MASK | USB_BDT_DTS);
+ status = bdtout->status;
+ status &= ~(USB_BDT_BSTALL | USB_BDT_NINC | USB_BDT_KEEP |
+ USB_BDT_BYTECOUNT_MASK | USB_BDT_DTS);
status |= (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
status |= USB_BDT_UOWN; /* Note: DTSEN is 0 */
bdtout->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
- bdtdbg("EP0 BDT OUT (Next) {%08x, %08x}\n", status, bdtout->addr);
+ bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, bdtout->addr);
bdtout->status = status;
-#ifdef CONFIG_USB_PINGPONG
- status = btdnext->status & ~USB_BDT_BYTECOUNT_MASK;
+ /* In ping-pong mode, force a STALL if there is any access to the
+ * other buffer.
+ */
+
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
+ status = bdtnext->status;
+ status &= ~USB_BDT_BYTECOUNT_MASK;
status |= (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
- status |= USB_BDT_UOWN | USB_BDT_BSTALL;
+ status |= (USB_BDT_UOWN | USB_BDT_BSTALL);
- btdnext->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
+ bdtnext->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
- bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, btdnext->addr);
+ bdtdbg("EP0 BDT OUT (Next) {%08x, %08x}\n", status, bdtnext->addr);
- btdnext->status = status;
+ bdtnext->status = status;
+ priv->ep0ready = 1;
#endif
}
@@ -1451,11 +1462,10 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
* ownership after a stall.
*/
+ bdtdbg("EP0 BDT IN {%08x, %08x}\n", ep0->bdtin->status, ep0->bdtin->addr);
ep0->bdtin->status &= ~USB_BDT_UOWN;
}
- bdtdbg("EP0 BDT IN {%08x, %08x}\n", ep0->bdtin->status, ep0->bdtin->addr);
-
/* Assume NOT stalled; no TX in progress */
ep0->stalled = 0;
@@ -1987,7 +1997,7 @@ static void pic32mx_ep0in(struct pic32mx_usbdev_s *priv)
/* Switch to the next ping pong buffer */
status = bdt->status;
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_NEXT_PINGPONG;
#endif
@@ -2085,7 +2095,9 @@ static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv)
{
/* Prepare EP0 OUT for the next SETUP transaction. */
- status = ep0->bdtout->status & ~(USB_BDT_BYTECOUNT_MASK|USB_BDT_DATA01);
+ status = ep0->bdtout->status;
+ status &= ~(USB_BDT_BSTALL | USB_BDT_NINC | USB_BDT_KEEP |
+ USB_BDT_BYTECOUNT_MASK | USB_BDT_DATA01);
ep0->bdtout->status = status;
ep0->bdtout->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
@@ -2122,11 +2134,13 @@ static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv)
pic32mx_ep0nextsetup(priv);
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
if (!priv->ep0ready)
#endif
{
- status = ep0->bdtout->status & ~(USB_BDT_BYTECOUNT_MASK|USB_BDT_DATA01);
+ status = ep0->bdtout->status;
+ status &= ~(USB_BDT_BSTALL | USB_BDT_NINC | USB_BDT_KEEP |
+ USB_BDT_BYTECOUNT_MASK | USB_BDT_DATA01);
ep0->bdtout->status = status;
ep0->bdtout->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
@@ -2140,8 +2154,8 @@ static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv)
ep0->bdtout->status = status;
}
-#ifdef CONFIG_USB_PINGPONG
- priv->ep0ready = 0;
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
+ priv->ep0ready = 0;
#endif
}
break;
@@ -2182,7 +2196,7 @@ static void pic32mx_ep0transfer(struct pic32mx_usbdev_s *priv, uint16_t status)
/* It was an EP0 OUT transaction. Get the index to the BDT. */
-#if CONFIG_USB_PINGPONG
+#if CONFIG_PIC32MX_USBDEV_PINGPONG
index = ((status & USB_STAT_PPBI) == 0 ? EP0_OUT_EVEN : EP0_OUT_ODD);
#else
index = EP0_OUT_EVEN;
@@ -2469,13 +2483,15 @@ static int pic32mx_interrupt(int irq, void *context)
{
uint8_t epno;
- /* Is token processing complete */
+ /* Check the pending interrupt register. Is token processing complete. */
if ((pic32mx_getreg(PIC32MX_USB_IR) & USB_INT_TRN) != 0)
{
regval = pic32mx_getreg(PIC32MX_USB_STAT);
pic32mx_putreg(USB_INT_TRN, PIC32MX_USB_IR);
+ usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_TRNCS), regval);
+
/* Handle the endpoint tranfer complete event. */
epno = (regval & USB_STAT_ENDPT_MASK) >> USB_STAT_ENDPT_SHIFT;
@@ -2759,7 +2775,7 @@ static int pic32mx_epconfigure(struct usbdev_ep_s *ep,
* The only difference is the we clear DATA1 (making it DATA0)
*/
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
bdt = &g_bdt[index+1];
status = bdt->status & ~USB_BDT_UOWN;
@@ -2793,7 +2809,7 @@ static int pic32mx_epconfigure(struct usbdev_ep_s *ep,
* The only difference is the we clear DATA1 (making it DATA0)
*/
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
bdt = &g_bdt[index+1];
status = bdt->status & ~USB_BDT_UOWN;
@@ -2863,7 +2879,7 @@ static int pic32mx_epdisable(struct usbdev_ep_s *ep)
/* Reset the BDTs */
ptr = (uint32_t*)&g_bdt[EP(epno, 0, 0)];
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
for (i = 0; i < (4 * sizeof(struct usbotg_bdtentry_s) / sizeof(uint32_t)); i++)
#else
for (i = 0; i < (2 * sizeof(struct usbotg_bdtentry_s) / sizeof(uint32_t)); i++)
@@ -3089,7 +3105,7 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
/* Toggle over the to the next buffer */
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_NEXT_PINGPONG;
#endif
status |= (USB_BDT_UOWN | USB_BDT_DATA1);
@@ -3117,7 +3133,7 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
/* Toggle over the to the next buffer */
-#ifdef CONFIG_USB_PINGPONG
+#ifdef CONFIG_PIC32MX_USBDEV_PINGPONG
status ^= USB_NEXT_PINGPONG;
#endif
status |= (USB_BDT_UOWN | USB_BDT_DATA1 | USB_BDT_DTS);
@@ -3561,6 +3577,7 @@ static void pic32mx_detach(struct pic32mx_usbdev_s *priv)
static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
{
+ uint32_t physaddr;
uint16_t regval;
int i;
@@ -3581,10 +3598,17 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
regval |= USB_PWRC_USBPWR;
pic32mx_putreg(regval, PIC32MX_USB_PWRC);
- /* Set the address of the buffer descriptor table (BDT) */
+ /* Set the address of the buffer descriptor table (BDT)
+ *
+ * BDTP1: Bit 1-7: Bits 9-15 of the BDT base address
+ * BDTP2: Bit 0-7: Bits 16-23 of the BDT base address
+ * BDTP3: Bit 0-7: Bits 24-31 of the BDT base address
+ */
- regval = (uint16_t)((PHYS_ADDR(g_bdt)) >> 8);
- pic32mx_putreg(regval, PIC32MX_USB_BDTP1);
+ physaddr = (PHYS_ADDR(g_bdt)) >> 8;
+ pic32mx_putreg((uint16_t)((regval >> 8) & USB_BDTP1_MASK), PIC32MX_USB_BDTP1);
+ pic32mx_putreg((uint16_t)((regval >> 16) & USB_BDTP2_MASK), PIC32MX_USB_BDTP2);
+ pic32mx_putreg((uint16_t)((regval >> 24) & USB_BDTP3_MASK), PIC32MX_USB_BDTP3);
/* Assert reset request to all of the Ping Pong buffer pointers */