Fix PIC32 USB cloning errors -- There is not pbuffer toggle bit in the BDT status
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4442 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
39106cde3a
commit
e23d7b69df
arch/mips/src/pic32mx
configs
@ -116,18 +116,18 @@
|
|||||||
#define PIC32MX_ENDP_BIT(ep) (1 << (ep))
|
#define PIC32MX_ENDP_BIT(ep) (1 << (ep))
|
||||||
#define PIC32MX_ENDP_ALLSET 0xffff
|
#define PIC32MX_ENDP_ALLSET 0xffff
|
||||||
|
|
||||||
/* BDT Table Indexing. The BDT table is addressed in the hardware as
|
/* BDT Table Indexing. The BDT is addressed in the hardware as follows:
|
||||||
* follows:
|
|
||||||
*
|
*
|
||||||
* Bits 9-31: These come the BDT address bits written into the BDTP3, BDTP2
|
* Bits 9-31: These come the BDT address bits written into the BDTP3,
|
||||||
* and BDTP1 registers
|
* BDTP2, and BDTP1 registers
|
||||||
* Bits 5-8: The endpoint number
|
* Bits 5-8: The endpoint number
|
||||||
* Bit 4: Direction
|
* Bit 4: Direction:
|
||||||
* Bit 3: PPBI, the ping point buffer index bit.
|
* 1 = Transmit: SETUP/OUT for host, IN for function
|
||||||
|
* 0 = Receive: IN for host, SETUP/OUT for function
|
||||||
|
* Bit 3: PPBI, the ping point buffer index bit (0=EVEN, 1=ODD)
|
||||||
* Bits 0-2: Supports 8-byte BDT entries
|
* Bits 0-2: Supports 8-byte BDT entries
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define USB_NEXT_PINGPONG USB_BDT_DTS
|
|
||||||
#define EP0_OUT_EVEN (0)
|
#define EP0_OUT_EVEN (0)
|
||||||
#define EP0_OUT_ODD (1)
|
#define EP0_OUT_ODD (1)
|
||||||
#define EP0_IN_EVEN (2)
|
#define EP0_IN_EVEN (2)
|
||||||
@ -136,9 +136,14 @@
|
|||||||
#define EP_OUT_ODD(ep) (((ep) << 2) + 1)
|
#define EP_OUT_ODD(ep) (((ep) << 2) + 1)
|
||||||
#define EP_IN_EVEN(ep) (((ep) << 2) + 2)
|
#define EP_IN_EVEN(ep) (((ep) << 2) + 2)
|
||||||
#define EP_IN_ODD(ep) (((ep) << 2) + 3)
|
#define EP_IN_ODD(ep) (((ep) << 2) + 3)
|
||||||
#define EP(ep,dir,pp) (((ep) << 2) + ((dir) << 1) + (pp))
|
|
||||||
|
|
||||||
/* Packet sizes. We us a fixed 64 max packet size for all endpoint types */
|
#define EP(ep,dir,pp) (((ep) << 2) + ((dir) << 1) + (pp))
|
||||||
|
#define EP_DIR_OUT 0
|
||||||
|
#define EP_DIR_IN 1
|
||||||
|
#define EP_PP_EVEN 0
|
||||||
|
#define EP_PP_ODD 1
|
||||||
|
|
||||||
|
/* Packet sizes. We use a fixed 64 max packet size for all endpoint types */
|
||||||
|
|
||||||
#define PIC32MX_MAXPACKET_SHIFT (6)
|
#define PIC32MX_MAXPACKET_SHIFT (6)
|
||||||
#define PIC32MX_MAXPACKET_SIZE (1 << (PIC32MX_MAXPACKET_SHIFT))
|
#define PIC32MX_MAXPACKET_SIZE (1 << (PIC32MX_MAXPACKET_SHIFT))
|
||||||
@ -263,7 +268,7 @@
|
|||||||
#ifdef CONFIG_PIC32MX_USBDEV_REGDEBUG
|
#ifdef CONFIG_PIC32MX_USBDEV_REGDEBUG
|
||||||
|
|
||||||
# undef CONFIG_PIC32MX_USBDEV_BDTDEBUG
|
# undef CONFIG_PIC32MX_USBDEV_BDTDEBUG
|
||||||
# define CONFIG_PIC32MX_USBDEV_BDTDEBUG
|
# define CONFIG_PIC32MX_USBDEV_BDTDEBUG 1
|
||||||
|
|
||||||
# define regdbg lldbg
|
# define regdbg lldbg
|
||||||
# ifdef CONFIG_DEBUG_VERBOSE
|
# ifdef CONFIG_DEBUG_VERBOSE
|
||||||
@ -294,6 +299,7 @@
|
|||||||
|
|
||||||
# define bdtdbg(x...)
|
# define bdtdbg(x...)
|
||||||
# define bdtvdbg(x...)
|
# define bdtvdbg(x...)
|
||||||
|
# define pic32mx_ep0bdtdump(msg)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -359,8 +365,8 @@ struct pic32mx_ep_s
|
|||||||
uint8_t halted:1; /* true: Endpoint feature halted */
|
uint8_t halted:1; /* true: Endpoint feature halted */
|
||||||
uint8_t txbusy:1; /* true: TX endpoint FIFO full */
|
uint8_t txbusy:1; /* true: TX endpoint FIFO full */
|
||||||
uint8_t txnullpkt:1; /* Null packet needed at end of transfer */
|
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 *bdtin; /* BDT entry for the IN transaction*/
|
||||||
volatile struct usbotg_bdtentry_s *bdtout; /* BDT entry for the OUT transaction */
|
volatile struct usbotg_bdtentry_s *bdtout; /* BDT entry for the OUT transaction */
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pic32mx_usbdev_s
|
struct pic32mx_usbdev_s
|
||||||
@ -383,7 +389,8 @@ struct pic32mx_usbdev_s
|
|||||||
uint8_t ctrlstate; /* Control EP state (see enum pic32mx_ctrlstate_e) */
|
uint8_t ctrlstate; /* Control EP state (see enum pic32mx_ctrlstate_e) */
|
||||||
uint8_t selfpowered:1; /* 1: Device is self powered */
|
uint8_t selfpowered:1; /* 1: Device is self powered */
|
||||||
uint8_t rwakeup:1; /* 1: Device supports remote wakeup */
|
uint8_t rwakeup:1; /* 1: Device supports remote wakeup */
|
||||||
uint8_t ep0ready:1; /* EP0 OUT already prepared */
|
uint8_t attached:1; /* Device is attached to the host */
|
||||||
|
uint8_t ep0done:1; /* EP0 OUT already prepared */
|
||||||
uint16_t epavail; /* Bitset of available endpoints */
|
uint16_t epavail; /* Bitset of available endpoints */
|
||||||
|
|
||||||
/* The endpoint list */
|
/* The endpoint list */
|
||||||
@ -418,7 +425,7 @@ static inline void
|
|||||||
struct pic32mx_req_s *privreq, int16_t result);
|
struct pic32mx_req_s *privreq, int16_t result);
|
||||||
static void pic32mx_reqcomplete(struct pic32mx_ep_s *privep, int16_t result);
|
static void pic32mx_reqcomplete(struct pic32mx_ep_s *privep, int16_t result);
|
||||||
static void pic32mx_epwrite(struct pic32mx_ep_s *privep,
|
static void pic32mx_epwrite(struct pic32mx_ep_s *privep,
|
||||||
const uint8_t *src, uint32_t nbytes, bool toggle);
|
const uint8_t *src, uint32_t nbytes);
|
||||||
static void pic32mx_wrcomplete(struct pic32mx_usbdev_s *priv,
|
static void pic32mx_wrcomplete(struct pic32mx_usbdev_s *priv,
|
||||||
struct pic32mx_ep_s *privep);
|
struct pic32mx_ep_s *privep);
|
||||||
static void pic32mx_wrrestart(struct pic32mx_usbdev_s *priv,
|
static void pic32mx_wrrestart(struct pic32mx_usbdev_s *priv,
|
||||||
@ -442,8 +449,7 @@ static void pic32mx_ep0stall(struct pic32mx_usbdev_s *priv);
|
|||||||
static void pic32mx_eptransfer(struct pic32mx_usbdev_s *priv, uint8_t epno,
|
static void pic32mx_eptransfer(struct pic32mx_usbdev_s *priv, uint8_t epno,
|
||||||
uint16_t status);
|
uint16_t status);
|
||||||
static void pic32mx_ep0nextsetup(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_ep0nextsetup(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv,
|
static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv);
|
||||||
uint8_t *response, int nbytes);
|
|
||||||
static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_ep0in(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_ep0in(struct pic32mx_usbdev_s *priv);
|
||||||
@ -459,6 +465,10 @@ static inline void
|
|||||||
struct pic32mx_ep_s *privep);
|
struct pic32mx_ep_s *privep);
|
||||||
static inline bool
|
static inline bool
|
||||||
pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno);
|
pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno);
|
||||||
|
static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv);
|
||||||
|
#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG
|
||||||
|
static void pic32mx_ep0bdtdump(const char *msg);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Endpoint operations ******************************************************/
|
/* Endpoint operations ******************************************************/
|
||||||
|
|
||||||
@ -494,7 +504,7 @@ static void pic32mx_reset(struct pic32mx_usbdev_s *priv);
|
|||||||
static void pic32mx_attach(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_attach(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_detach(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_detach(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_hwsetup(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_stateinit(struct pic32mx_usbdev_s *priv);
|
||||||
static void pic32mx_hwshutdown(struct pic32mx_usbdev_s *priv);
|
static void pic32mx_hwshutdown(struct pic32mx_usbdev_s *priv);
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -528,20 +538,20 @@ static const struct usbdev_ops_s g_devops =
|
|||||||
.pullup = pic32mx_usbpullup,
|
.pullup = pic32mx_usbpullup,
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Buffer Descriptor Table.
|
/* Buffer Descriptor Table. Four BDT entries per
|
||||||
*
|
*
|
||||||
* The BDT table is addressed in the hardware as follows:
|
* The BDT is addressed in the hardware as follows:
|
||||||
*
|
*
|
||||||
* Bits 9-31: These come the BDT address bits written into the BDTP3, BDTP2
|
* Bits 9-31: These come the BDT address bits written into the BDTP3, BDTP2
|
||||||
* and BDTP1 registers
|
* and BDTP1 registers
|
||||||
* Bits 5-8: The endpoint number
|
* Bits 5-8: The endpoint number
|
||||||
* Bit 4: Direction
|
* Bit 4: Direction (0=IN/Tx, 1 = OUT/Rx)
|
||||||
* Bit 3: PPBI, the ping point buffer index bit.
|
* Bit 3: PPBI, the ping point buffer index bit.
|
||||||
* Bits 0-2: Supports 8-byte BDT entries
|
* Bits 0-2: Supports 8-byte BDT entries
|
||||||
*/
|
*/
|
||||||
|
|
||||||
volatile struct usbotg_bdtentry_s
|
static volatile struct usbotg_bdtentry_s g_bdt[4*PIC32MX_NENDPOINTS]
|
||||||
g_bdt[(PIC32MX_NENDPOINTS + 1) * 4] __attribute__ ((aligned(512)));
|
__attribute__ ((aligned(512)));
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Public Data
|
* Public Data
|
||||||
@ -738,7 +748,7 @@ static void pic32mx_reqcomplete(struct pic32mx_ep_s *privep, int16_t result)
|
|||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
|
static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
|
||||||
uint32_t nbytes, bool toggle)
|
uint32_t nbytes)
|
||||||
{
|
{
|
||||||
volatile struct usbotg_bdtentry_s *bdt = privep->bdtin;
|
volatile struct usbotg_bdtentry_s *bdt = privep->bdtin;
|
||||||
uint32_t status;
|
uint32_t status;
|
||||||
@ -761,10 +771,6 @@ static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
|
|||||||
|
|
||||||
status |= (nbytes << USB_BDT_BYTECOUNT_SHIFT) | USB_BDT_DTS;
|
status |= (nbytes << USB_BDT_BYTECOUNT_SHIFT) | USB_BDT_DTS;
|
||||||
|
|
||||||
/* Point to the next ping pong buffer. */
|
|
||||||
|
|
||||||
status ^= USB_NEXT_PINGPONG;
|
|
||||||
|
|
||||||
/* And, finally, give the BDT to the USB */
|
/* And, finally, give the BDT to the USB */
|
||||||
|
|
||||||
status |= USB_BDT_UOWN;
|
status |= USB_BDT_UOWN;
|
||||||
@ -944,7 +950,7 @@ static int pic32mx_wrrequest(struct pic32mx_usbdev_s *priv, struct pic32mx_ep_s
|
|||||||
|
|
||||||
/* Setup the writes to the endpoints */
|
/* Setup the writes to the endpoints */
|
||||||
|
|
||||||
pic32mx_epwrite(privep, buf, nbytes, privreq->req.xfrd > 0);
|
pic32mx_epwrite(privep, buf, nbytes);
|
||||||
|
|
||||||
/* Special case endpoint 0 state information. The write request is in
|
/* Special case endpoint 0 state information. The write request is in
|
||||||
* progress.
|
* progress.
|
||||||
@ -1049,7 +1055,7 @@ static int pic32mx_ep0rdsetup(struct pic32mx_usbdev_s *priv, uint8_t *dest,
|
|||||||
|
|
||||||
/* Then give the BDT to the USB */
|
/* Then give the BDT to the USB */
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, bdt->addr);
|
bdtdbg("EP0 BDT OUT [%p] {%08x, %08x}\n", bdt, status, bdt->addr);
|
||||||
|
|
||||||
bdt->status = status;
|
bdt->status = status;
|
||||||
priv->ctrlstate = CTRLSTATE_RDREQUEST;
|
priv->ctrlstate = CTRLSTATE_RDREQUEST;
|
||||||
@ -1081,10 +1087,6 @@ static int pic32mx_rdsetup(struct pic32mx_usbdev_s *priv,
|
|||||||
|
|
||||||
status |= (readlen << USB_BDT_BYTECOUNT_SHIFT) | USB_BDT_DTS;
|
status |= (readlen << USB_BDT_BYTECOUNT_SHIFT) | USB_BDT_DTS;
|
||||||
|
|
||||||
/* Point to the next ping pong buffer. */
|
|
||||||
|
|
||||||
status ^= USB_NEXT_PINGPONG;
|
|
||||||
|
|
||||||
/* Then give the BDT to the USB */
|
/* Then give the BDT to the USB */
|
||||||
|
|
||||||
status |= USB_BDT_UOWN;
|
status |= USB_BDT_UOWN;
|
||||||
@ -1219,7 +1221,8 @@ static void pic32mx_ep0stall(struct pic32mx_usbdev_s *priv)
|
|||||||
|
|
||||||
uint16_t status = (USB_BDT_UOWN| USB_BDT_DATA0 | USB_BDT_DTS | USB_BDT_BSTALL);
|
uint16_t status = (USB_BDT_UOWN| USB_BDT_DATA0 | USB_BDT_DTS | USB_BDT_BSTALL);
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, ep0->bdtout->addr);
|
bdtdbg("EP0 BDT OUT [%p] {%08x, %08x}\n",
|
||||||
|
ep0->bdtout, status, ep0->bdtout->addr);
|
||||||
|
|
||||||
ep0->bdtout->status = status;
|
ep0->bdtout->status = status;
|
||||||
}
|
}
|
||||||
@ -1306,12 +1309,10 @@ static void pic32mx_ep0nextsetup(struct pic32mx_usbdev_s *priv)
|
|||||||
* transaction.
|
* transaction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = bdt->status & ~USB_BDT_UOWN;
|
status = bdt->status & ~USB_BDT_UOWN;
|
||||||
|
|
||||||
status ^= USB_NEXT_PINGPONG;
|
|
||||||
status &= ~USB_BDT_UOWN;
|
status &= ~USB_BDT_UOWN;
|
||||||
|
|
||||||
bdtdbg("EP0 BDT IN {%08x, %08x}\n", status, bdt->addr);
|
bdtdbg("EP0 BDT IN [%p] {%08x, %08x}\n", bdt, status, bdt->addr);
|
||||||
|
|
||||||
bdt->status = status;
|
bdt->status = status;
|
||||||
}
|
}
|
||||||
@ -1320,24 +1321,25 @@ static void pic32mx_ep0nextsetup(struct pic32mx_usbdev_s *priv)
|
|||||||
* Name: pic32mx_ep0done
|
* Name: pic32mx_ep0done
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv,
|
static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv)
|
||||||
uint8_t *response, int nbytes)
|
|
||||||
{
|
{
|
||||||
struct pic32mx_ep_s *ep0 = &priv->eplist[EP0];
|
struct pic32mx_ep_s *ep0 = &priv->eplist[EP0];
|
||||||
volatile struct usbotg_bdtentry_s *bdtout;
|
volatile struct usbotg_bdtentry_s *bdtlast;
|
||||||
volatile struct usbotg_bdtentry_s *bdtnext;
|
volatile struct usbotg_bdtentry_s *bdtnext;
|
||||||
uint16_t status;
|
uint32_t status;
|
||||||
|
uint32_t bytecount;
|
||||||
|
uint32_t data01;
|
||||||
|
|
||||||
/* Which BDT are we working on new? Which one will be next */
|
/* Which BDT did we just finish working with? Which one will be next */
|
||||||
|
|
||||||
bdtout = ep0->bdtout;
|
bdtlast = ep0->bdtout;
|
||||||
if (bdtout == &g_bdt[EP0_OUT_EVEN])
|
if (bdtlast == &g_bdt[EP0_OUT_EVEN])
|
||||||
{
|
{
|
||||||
bdtnext = &g_bdt[EP0_OUT_ODD];
|
bdtnext = &g_bdt[EP0_OUT_ODD];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DEBUGASSERT(bdtout == &g_bdt[EP0_OUT_ODD]);
|
DEBUGASSERT(bdtlast == &g_bdt[EP0_OUT_ODD]);
|
||||||
bdtnext = &g_bdt[EP0_OUT_EVEN];
|
bdtnext = &g_bdt[EP0_OUT_EVEN];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1354,33 +1356,29 @@ static void pic32mx_ep0done(struct pic32mx_usbdev_s *priv,
|
|||||||
* buffer address should be pointed to priv->ctrl.
|
* buffer address should be pointed to priv->ctrl.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = bdtout->status;
|
bytecount = (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
|
||||||
status &= ~(USB_BDT_BSTALL | USB_BDT_NINC | USB_BDT_KEEP |
|
data01 = (bdtlast->status & USB_BDT_DATA01) ^ USB_BDT_DATA01;
|
||||||
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);
|
status = bdtnext->status;
|
||||||
|
status &= ~(USB_BDT_BSTALL | USB_BDT_NINC | USB_BDT_KEEP | USB_BDT_BYTECOUNT_MASK);
|
||||||
|
status = (USB_BDT_UOWN | USB_BDT_DTS | data01 | bytecount);
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, bdtout->addr);
|
bdtnext->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
|
||||||
|
bdtdbg("EP0 BDT OUT Next [%p] {%08x, %08x}\n", bdtnext, status, bdtnext->addr);
|
||||||
|
bdtnext->status = status;
|
||||||
|
priv->eplist[EP0].bdtout = bdtnext;
|
||||||
|
|
||||||
bdtout->status = status;
|
/* Force a STALL if there is any access to the other buffer. */
|
||||||
|
|
||||||
/* In ping-pong mode, force a STALL if there is any access to the
|
status = bdtlast->status;
|
||||||
* other buffer.
|
status &= ~(USB_BDT_UOWN | USB_BDT_BYTECOUNT_MASK);
|
||||||
*/
|
status |= (USB_BDT_BSTALL | bytecount);
|
||||||
|
|
||||||
status = bdtnext->status;
|
bdtlast->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
|
||||||
status &= ~USB_BDT_BYTECOUNT_MASK;
|
bdtdbg("EP0 BDT OUT Last [%p] {%08x, %08x}\n", bdtlast, status, bdtlast->addr);
|
||||||
status |= (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
|
bdtlast->status = status;
|
||||||
status |= (USB_BDT_UOWN | USB_BDT_BSTALL);
|
|
||||||
|
|
||||||
bdtnext->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
|
priv->ep0done = 1;
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT (Next) {%08x, %08x}\n", status, bdtnext->addr);
|
|
||||||
|
|
||||||
bdtnext->status = status;
|
|
||||||
priv->ep0ready = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
@ -1427,7 +1425,9 @@ static void pic32mx_ep0setup(struct pic32mx_usbdev_s *priv)
|
|||||||
* ownership after a stall.
|
* ownership after a stall.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bdtdbg("EP0 BDT IN {%08x, %08x}\n", ep0->bdtin->status, ep0->bdtin->addr);
|
bdtdbg("EP0 BDT IN [%p] {%08x, %08x}\n",
|
||||||
|
ep0->bdtin, ep0->bdtin->status, ep0->bdtin->addr);
|
||||||
|
|
||||||
ep0->bdtin->status &= ~USB_BDT_UOWN;
|
ep0->bdtin->status &= ~USB_BDT_UOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1920,7 +1920,7 @@ resume_packet_processing:
|
|||||||
|
|
||||||
/* Send the EP0 SETUP response (might be a zero-length packet) */
|
/* Send the EP0 SETUP response (might be a zero-length packet) */
|
||||||
|
|
||||||
pic32mx_epwrite(&priv->eplist[EP0], response.b, nbytes, false);
|
pic32mx_epwrite(&priv->eplist[EP0], response.b, nbytes);
|
||||||
priv->ctrlstate = CTRLSTATE_WAITSETUP;
|
priv->ctrlstate = CTRLSTATE_WAITSETUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1933,7 +1933,7 @@ resume_packet_processing:
|
|||||||
{
|
{
|
||||||
/* No.. Set up the BDTs to accept the next setup commend. */
|
/* No.. Set up the BDTs to accept the next setup commend. */
|
||||||
|
|
||||||
pic32mx_ep0done(priv, response.b, nbytes);
|
pic32mx_ep0done(priv);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1951,7 +1951,6 @@ static void pic32mx_ep0in(struct pic32mx_usbdev_s *priv)
|
|||||||
{
|
{
|
||||||
volatile struct usbotg_bdtentry_s *bdt;
|
volatile struct usbotg_bdtentry_s *bdt;
|
||||||
struct pic32mx_ep_s *ep0 = &priv->eplist[EP0];
|
struct pic32mx_ep_s *ep0 = &priv->eplist[EP0];
|
||||||
uint16_t status;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
/* There is no longer anything in the EP0 TX packet memory */
|
/* There is no longer anything in the EP0 TX packet memory */
|
||||||
@ -1959,11 +1958,6 @@ static void pic32mx_ep0in(struct pic32mx_usbdev_s *priv)
|
|||||||
ep0->txbusy = false;
|
ep0->txbusy = false;
|
||||||
bdt = ep0->bdtin;
|
bdt = ep0->bdtin;
|
||||||
|
|
||||||
/* Switch to the next ping pong buffer */
|
|
||||||
|
|
||||||
status = bdt->status;
|
|
||||||
status ^= USB_NEXT_PINGPONG;
|
|
||||||
|
|
||||||
/* Are we processing the completion of one packet of an outgoing request
|
/* Are we processing the completion of one packet of an outgoing request
|
||||||
* from the class driver?
|
* from the class driver?
|
||||||
*/
|
*/
|
||||||
@ -2058,26 +2052,7 @@ static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv)
|
|||||||
{
|
{
|
||||||
/* Prepare EP0 OUT for the next SETUP transaction. */
|
/* Prepare EP0 OUT for the next SETUP transaction. */
|
||||||
|
|
||||||
status = ep0->bdtout->status;
|
pic32mx_ep0done(priv);
|
||||||
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);
|
|
||||||
status |= (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
|
|
||||||
status |= (USB_BDT_DATA0 | USB_BDT_DTS | USB_BDT_BSTALL);
|
|
||||||
|
|
||||||
/* Set BSTALL in case the host tries to send more data than
|
|
||||||
* it claims it was going to send.
|
|
||||||
*/
|
|
||||||
|
|
||||||
status |= (USB_BDT_BSTALL | USB_BDT_UOWN);
|
|
||||||
|
|
||||||
/* Then give the BDT to the USB */
|
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, ep0->bdtout->addr);
|
|
||||||
|
|
||||||
ep0->bdtout->status = status;
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2088,34 +2063,22 @@ static void pic32mx_ep0out(struct pic32mx_usbdev_s *priv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* Prepare EP0 OUT for the next SETUP transaction. However,
|
/* Prepare EP0 OUT for the next SETUP transaction. However,
|
||||||
* EP0 may have already been prepared if ping-pong buffering
|
* EP0 may have already been prepared if the last control transfer
|
||||||
* was enabled on EP0 OUT, and the last control transfer was
|
* was of direction: device to host, see pic32mx_ep0done(). If
|
||||||
* of direction: device to host, see pic32mx_ep0done(). If
|
|
||||||
* it was already prepared, we do not want to do anything to
|
* it was already prepared, we do not want to do anything to
|
||||||
* the buffer descriptor table (BDT).
|
* the buffer descriptor table (BDT).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pic32mx_ep0nextsetup(priv);
|
pic32mx_ep0nextsetup(priv);
|
||||||
|
|
||||||
if (!priv->ep0ready)
|
if (!priv->ep0done)
|
||||||
{
|
{
|
||||||
status = ep0->bdtout->status;
|
/* Prepare EP0 OUT for the next SETUP transaction. */
|
||||||
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);
|
pic32mx_ep0done(priv);
|
||||||
status |= (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
|
|
||||||
status |= (USB_BDT_UOWN | USB_BDT_DATA0 | USB_BDT_DTS | USB_BDT_BSTALL);
|
|
||||||
|
|
||||||
/* Then give the BDT to the USB */
|
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT {%08x, %08x}\n", status, ep0->bdtout->addr);
|
|
||||||
|
|
||||||
ep0->bdtout->status = status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->ep0ready = 0;
|
priv->ep0done = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2140,13 +2103,15 @@ static void pic32mx_ep0transfer(struct pic32mx_usbdev_s *priv, uint16_t status)
|
|||||||
{
|
{
|
||||||
volatile struct usbotg_bdtentry_s *bdt;
|
volatile struct usbotg_bdtentry_s *bdt;
|
||||||
|
|
||||||
/* The following information is available in the tatus register :
|
/* The following information is available in the status register :
|
||||||
*
|
*
|
||||||
* ENDPT - The 4 bit endpoint number that cause the interrupt.
|
* ENDPT - The 4 bit endpoint number that cause the interrupt.
|
||||||
* DIR - The direction of the endpoint.
|
* DIR - The direction of the endpoint.
|
||||||
* PPBI - The ping-pong buffer used in the transaction.
|
* PPBI - The ping-pong buffer used in the transaction.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
priv->ep0done = 0;
|
||||||
|
|
||||||
/* Check if the last transaction was an EP0 OUT transaction */
|
/* Check if the last transaction was an EP0 OUT transaction */
|
||||||
|
|
||||||
if ((status & USB_STAT_DIR) == USB_STAT_DIR_OUT)
|
if ((status & USB_STAT_DIR) == USB_STAT_DIR_OUT)
|
||||||
@ -2159,11 +2124,7 @@ static void pic32mx_ep0transfer(struct pic32mx_usbdev_s *priv, uint16_t status)
|
|||||||
bdt = &g_bdt[index];
|
bdt = &g_bdt[index];
|
||||||
priv->eplist[0].bdtout = bdt;
|
priv->eplist[0].bdtout = bdt;
|
||||||
|
|
||||||
bdtdbg("EP0 BDT OUT {%08x, %08x}\n", bdt->status, bdt->addr);
|
bdtdbg("EP0 BDT OUT [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
|
||||||
|
|
||||||
/* Toggle it to the next ping pong buffer */
|
|
||||||
|
|
||||||
bdt->status ^= USB_NEXT_PINGPONG;
|
|
||||||
|
|
||||||
/* Check the current EP0 OUT buffer contains a SETUP packet */
|
/* Check the current EP0 OUT buffer contains a SETUP packet */
|
||||||
|
|
||||||
@ -2202,7 +2163,7 @@ static void pic32mx_ep0transfer(struct pic32mx_usbdev_s *priv, uint16_t status)
|
|||||||
{
|
{
|
||||||
usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_EP0INDONE), status);
|
usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_EP0INDONE), status);
|
||||||
|
|
||||||
/* Handle the IN transfer */
|
/* Handle the IN transfer complete */
|
||||||
|
|
||||||
pic32mx_ep0in(priv);
|
pic32mx_ep0in(priv);
|
||||||
}
|
}
|
||||||
@ -2336,18 +2297,13 @@ static int pic32mx_interrupt(int irq, void *context)
|
|||||||
|
|
||||||
/* Reset interrupt received. Restore our power-up state */
|
/* Reset interrupt received. Restore our power-up state */
|
||||||
|
|
||||||
|
#warning "Broken Logic"
|
||||||
|
#if 0 /* If there is no pull-up, then this will just cause another reset */
|
||||||
pic32mx_reset(priv);
|
pic32mx_reset(priv);
|
||||||
pic32mx_attach(priv);
|
pic32mx_attach(priv);
|
||||||
|
#endif
|
||||||
priv->devstate = DEVSTATE_DEFAULT;
|
priv->devstate = DEVSTATE_DEFAULT;
|
||||||
|
|
||||||
/* Re-initialize EP0 */
|
|
||||||
|
|
||||||
g_bdt[EP0_OUT_EVEN].addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
|
|
||||||
g_bdt[EP0_OUT_EVEN].status &= ~USB_BDT_BYTECOUNT_MASK;
|
|
||||||
g_bdt[EP0_OUT_EVEN].status |= (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
|
|
||||||
g_bdt[EP0_OUT_EVEN].status &= ~USB_BDT_STATUS_MASK;
|
|
||||||
g_bdt[EP0_OUT_EVEN].status |= USB_BDT_UOWN | USB_BDT_DATA0 | USB_BDT_DTS | USB_BDT_BSTALL;
|
|
||||||
|
|
||||||
#ifdef CONFIG_USBOTG
|
#ifdef CONFIG_USBOTG
|
||||||
/* Disable and deactivate HNP */
|
/* Disable and deactivate HNP */
|
||||||
#warning Missing Logic
|
#warning Missing Logic
|
||||||
@ -2634,6 +2590,71 @@ pic32mx_epreserved(struct pic32mx_usbdev_s *priv, int epno)
|
|||||||
return ((priv->epavail & PIC32MX_ENDP_BIT(epno)) == 0);
|
return ((priv->epavail & PIC32MX_ENDP_BIT(epno)) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pic32mx_ep0configure
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static void pic32mx_ep0configure(struct pic32mx_usbdev_s *priv)
|
||||||
|
{
|
||||||
|
volatile struct usbotg_bdtentry_s *bdt;
|
||||||
|
uint32_t bytecount;
|
||||||
|
|
||||||
|
/* Enable the EP0 endpoint */
|
||||||
|
|
||||||
|
pic32mx_putreg(PIC32MX_EP_CONTROL, PIC32MX_USB_EP0);
|
||||||
|
|
||||||
|
/* Configure the OUT BDTs. We expect to receive on the EVEN BDT first.
|
||||||
|
* If an OUT token is sent by the host before a SETUP token is sent, the
|
||||||
|
* firmware should respond with a STALL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
bytecount = (USB_SIZEOF_CTRLREQ << USB_BDT_BYTECOUNT_SHIFT);
|
||||||
|
|
||||||
|
bdt = &g_bdt[EP0_OUT_EVEN];
|
||||||
|
bdt->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
|
||||||
|
bdt->status = (USB_BDT_UOWN | USB_BDT_DATA0 | USB_BDT_DTS | bytecount);
|
||||||
|
priv->eplist[EP0].bdtout = bdt;
|
||||||
|
|
||||||
|
bdt = &g_bdt[EP0_OUT_ODD];
|
||||||
|
bdt->status = (USB_BDT_DATA1 | USB_BDT_BSTALL | USB_BDT_DTS | bytecount);
|
||||||
|
bdt->addr = (uint8_t *)PHYS_ADDR(&priv->ctrl);
|
||||||
|
|
||||||
|
/* Configure the IN BDTs. Set DATA1 to one in the EVEN BDT because the first
|
||||||
|
* thing we will do when transmitting is* toggle the bit
|
||||||
|
*/
|
||||||
|
|
||||||
|
bdt = &g_bdt[EP0_IN_EVEN];
|
||||||
|
bdt->status = (USB_BDT_DATA1 | USB_BDT_DTS | USB_BDT_BSTALL);
|
||||||
|
bdt->addr = 0;
|
||||||
|
priv->eplist[EP0].bdtin = bdt;
|
||||||
|
|
||||||
|
bdt = &g_bdt[EP0_IN_ODD];
|
||||||
|
bdt->status = (USB_BDT_DATA0 | USB_BDT_DTS | USB_BDT_BSTALL);
|
||||||
|
bdt->addr = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: pic32mx_ep0bdtdump
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifdef CONFIG_PIC32MX_USBDEV_BDTDEBUG
|
||||||
|
static void pic32mx_ep0bdtdump(const char *msg)
|
||||||
|
{
|
||||||
|
volatile struct usbotg_bdtentry_s *bdt;
|
||||||
|
|
||||||
|
bdtdbg("EP0 BDT: %s\n", msg);
|
||||||
|
|
||||||
|
bdt = &g_bdt[EP0_OUT_EVEN] ;
|
||||||
|
bdtdbg(" OUT EVEN [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
|
||||||
|
bdt = &g_bdt[EP0_OUT_ODD];
|
||||||
|
bdtdbg(" OUT ODD [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
|
||||||
|
bdt = &g_bdt[EP0_IN_EVEN];
|
||||||
|
bdtdbg(" IN EVEN [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
|
||||||
|
bdt = &g_bdt[EP0_IN_ODD];
|
||||||
|
bdtdbg(" IN ODD [%p] {%08x, %08x}\n", bdt, bdt->status, bdt->addr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Endpoint operations
|
* Endpoint operations
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
@ -2701,7 +2722,6 @@ static int pic32mx_epconfigure(struct usbdev_ep_s *ep,
|
|||||||
/* Enable the endpoint */
|
/* Enable the endpoint */
|
||||||
|
|
||||||
pic32mx_putreg(regval, PIC32MX_USB_EP(epno));
|
pic32mx_putreg(regval, PIC32MX_USB_EP(epno));
|
||||||
regdbg("PIC32MX_USB_EP%d: %04x\n", epno, getreg16(PIC32MX_USB_EP(epno)));
|
|
||||||
|
|
||||||
/* Setup up buffer descriptor table (BDT) entry/ies for this endpoint */
|
/* Setup up buffer descriptor table (BDT) entry/ies for this endpoint */
|
||||||
|
|
||||||
@ -2758,8 +2778,8 @@ static int pic32mx_epconfigure(struct usbdev_ep_s *ep,
|
|||||||
|
|
||||||
bdtdbg("EP%d BDT OUT {%08x, %08x}\n", epno, status, bdt->addr);
|
bdtdbg("EP%d BDT OUT {%08x, %08x}\n", epno, status, bdt->addr);
|
||||||
|
|
||||||
/* Now do the same for the other buffer (if ping pong mode is supported).
|
/* Now do the same for the other buffer. The only difference is the
|
||||||
* The only difference is the we clear DATA1 (making it DATA0)
|
* we clear DATA1 (making it DATA0)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bdt = &g_bdt[index+1];
|
bdt = &g_bdt[index+1];
|
||||||
@ -2827,10 +2847,12 @@ static int pic32mx_epdisable(struct usbdev_ep_s *ep)
|
|||||||
|
|
||||||
pic32mx_putreg(0, PIC32MX_USB_EP(epno));
|
pic32mx_putreg(0, PIC32MX_USB_EP(epno));
|
||||||
|
|
||||||
/* Reset the BDTs for the endpoint. Four BDT entries per endpoint. */
|
/* Reset the BDTs for the endpoint. Four BDT entries per endpoint; Two
|
||||||
|
* 32-bit words per BDT.
|
||||||
|
*/
|
||||||
|
|
||||||
ptr = (uint32_t*)&g_bdt[EP(epno, 0, 0)];
|
ptr = (uint32_t*)&g_bdt[EP(epno, 0, 0)];
|
||||||
for (i = 0; i < (4 * sizeof(struct usbotg_bdtentry_s) / sizeof(uint32_t)); i++)
|
for (i = 0; i < USB_BDT_WORD_SIZE * USB_NBDTS_PER_EP; i++)
|
||||||
{
|
{
|
||||||
*ptr++ = 0;
|
*ptr++ = 0;
|
||||||
}
|
}
|
||||||
@ -3048,11 +3070,7 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
|
|||||||
* is correct
|
* is correct
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = bdt->status;
|
status = bdt->status;
|
||||||
|
|
||||||
/* Toggle over the to the next buffer */
|
|
||||||
|
|
||||||
status ^= USB_NEXT_PINGPONG;
|
|
||||||
status |= (USB_BDT_UOWN | USB_BDT_DATA1);
|
status |= (USB_BDT_UOWN | USB_BDT_DATA1);
|
||||||
|
|
||||||
/* Then give the BDT to the USB */
|
/* Then give the BDT to the USB */
|
||||||
@ -3074,12 +3092,8 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
|
|||||||
* correct.
|
* correct.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
status = bdt->status;
|
status = bdt->status;
|
||||||
|
status |= (USB_BDT_UOWN | USB_BDT_DATA1 | USB_BDT_DTS);
|
||||||
/* Toggle over the to the next buffer */
|
|
||||||
|
|
||||||
status ^= USB_NEXT_PINGPONG;
|
|
||||||
status |= (USB_BDT_UOWN | USB_BDT_DATA1 | USB_BDT_DTS);
|
|
||||||
|
|
||||||
/* Then give the BDT to the USB */
|
/* Then give the BDT to the USB */
|
||||||
|
|
||||||
@ -3417,22 +3431,43 @@ static void pic32mx_attach(struct pic32mx_usbdev_s *priv)
|
|||||||
|
|
||||||
if (priv->devstate == DEVSTATE_DETACHED)
|
if (priv->devstate == DEVSTATE_DETACHED)
|
||||||
{
|
{
|
||||||
|
/* Disable USB interrupts at the interrupt controller */
|
||||||
|
|
||||||
|
up_disable_irq(PIC32MX_IRQSRC_USB);
|
||||||
|
|
||||||
/* Initialize registers to known states. */
|
/* Initialize registers to known states. */
|
||||||
|
|
||||||
pic32mx_putreg(0, PIC32MX_USB_CON);
|
pic32mx_putreg(0, PIC32MX_USB_CON);
|
||||||
|
|
||||||
/* Mask all USB interrupts */
|
|
||||||
|
|
||||||
pic32mx_putreg(0, PIC32MX_USB_IE);
|
|
||||||
|
|
||||||
/* Configure things like: pull ups, full/low-speed mode,
|
/* Configure things like: pull ups, full/low-speed mode,
|
||||||
* set the ping pong mode, and set internal transceiver
|
* set the ping pong mode, and set internal transceiver
|
||||||
*/
|
*/
|
||||||
|
|
||||||
pic32mx_putreg(0, PIC32MX_USB_CNFG1);
|
pic32mx_putreg(0, PIC32MX_USB_CNFG1);
|
||||||
|
|
||||||
|
/* Enable interrupts at the USB controller */
|
||||||
|
|
||||||
pic32mx_putreg(ERROR_INTERRUPTS, PIC32MX_USB_EIE);
|
pic32mx_putreg(ERROR_INTERRUPTS, PIC32MX_USB_EIE);
|
||||||
pic32mx_putreg(NORMAL_INTERRUPTS, PIC32MX_USB_IE);
|
pic32mx_putreg(NORMAL_INTERRUPTS, PIC32MX_USB_IE);
|
||||||
|
|
||||||
|
/* Configure EP0 */
|
||||||
|
|
||||||
|
pic32mx_ep0configure(priv);
|
||||||
|
pic32mx_ep0bdtdump("Attached");
|
||||||
|
|
||||||
|
/* Flush any pending transactions */
|
||||||
|
|
||||||
|
while ((pic32mx_getreg(PIC32MX_USB_IR) & USB_INT_TRN) != 0)
|
||||||
|
{
|
||||||
|
pic32mx_putreg(USB_INT_TRN, PIC32MX_USB_IR);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Make sure packet processing is enabled */
|
||||||
|
|
||||||
|
regval = pic32mx_getreg(PIC32MX_USB_CON);
|
||||||
|
regval &= ~USB_CON_PKTDIS;
|
||||||
|
pic32mx_putreg(regval, PIC32MX_USB_CON);
|
||||||
|
|
||||||
/* Enable the USB module and attach to bus */
|
/* Enable the USB module and attach to bus */
|
||||||
|
|
||||||
do
|
do
|
||||||
@ -3458,7 +3493,12 @@ static void pic32mx_attach(struct pic32mx_usbdev_s *priv)
|
|||||||
priv->devstate = DEVSTATE_ATTACHED;
|
priv->devstate = DEVSTATE_ATTACHED;
|
||||||
priv->usbdev.speed = USB_SPEED_FULL;
|
priv->usbdev.speed = USB_SPEED_FULL;
|
||||||
|
|
||||||
/* Enable USB interrupts */
|
/* Clear all pending USB interrupts */
|
||||||
|
|
||||||
|
pic32mx_putreg(USB_EINT_ALL, PIC32MX_USB_EIR);
|
||||||
|
pic32mx_putreg(USB_INT_ALL, PIC32MX_USB_IR);
|
||||||
|
|
||||||
|
/* Enable USB interrupts at the interrupt controller */
|
||||||
|
|
||||||
up_enable_irq(PIC32MX_IRQSRC_USB);
|
up_enable_irq(PIC32MX_IRQSRC_USB);
|
||||||
|
|
||||||
@ -3490,12 +3530,15 @@ static void pic32mx_detach(struct pic32mx_usbdev_s *priv)
|
|||||||
|
|
||||||
/* We are now in the detached state */
|
/* We are now in the detached state */
|
||||||
|
|
||||||
|
priv->attached = 0;
|
||||||
priv->devstate = DEVSTATE_DETACHED;
|
priv->devstate = DEVSTATE_DETACHED;
|
||||||
|
|
||||||
#ifdef CONFIG_USBOTG
|
#ifdef CONFIG_USBOTG
|
||||||
/* Disable the D+ Pullup */
|
/* Disable the D+ Pullup */
|
||||||
|
|
||||||
U1OTGCONbits.DPPULUP = 0;
|
regval = pic32mx_getreg(PIC32MX_USBOTG_CON);
|
||||||
|
regval &= ~USBOTG_CON_DPPULUP;
|
||||||
|
pic32mx_putreg(regval, PIC32MX_USBOTG_CON);
|
||||||
|
|
||||||
/* Disable and deactivate HNP */
|
/* Disable and deactivate HNP */
|
||||||
#warning Missing Logic
|
#warning Missing Logic
|
||||||
@ -3524,23 +3567,26 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
|
|||||||
uint16_t regval;
|
uint16_t regval;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/* Clear all pending USB interrupts */
|
/* Power down the USB module. This will reset all USB registers. */
|
||||||
|
|
||||||
pic32mx_putreg(USB_EINT_ALL, PIC32MX_USB_EIR);
|
regval = pic32mx_getreg(PIC32MX_USB_PWRC);
|
||||||
pic32mx_putreg(USB_INT_ALL, PIC32MX_USB_IR);
|
regval &= ~USB_PWRC_USBPWR;
|
||||||
|
|
||||||
/* Reset configuration and enable interrrupts */
|
/* Clear all of the buffer descriptor table (BDT) entries */
|
||||||
|
|
||||||
pic32mx_putreg(0, PIC32MX_USB_CNFG1);
|
memset((void*)g_bdt, 0, sizeof(g_bdt));
|
||||||
pic32mx_putreg(ERROR_INTERRUPTS, PIC32MX_USB_EIE);
|
|
||||||
pic32mx_putreg(NORMAL_INTERRUPTS, PIC32MX_USB_IE);
|
|
||||||
|
|
||||||
/* Power up the USB module */
|
/* Power up the USB module */
|
||||||
|
|
||||||
regval = pic32mx_getreg(PIC32MX_USB_PWRC);
|
|
||||||
regval |= USB_PWRC_USBPWR;
|
regval |= USB_PWRC_USBPWR;
|
||||||
pic32mx_putreg(regval, PIC32MX_USB_PWRC);
|
pic32mx_putreg(regval, PIC32MX_USB_PWRC);
|
||||||
|
|
||||||
|
/* Reset configuration and disable interrrupts at the USB controller */
|
||||||
|
|
||||||
|
pic32mx_putreg(0, PIC32MX_USB_CNFG1);
|
||||||
|
pic32mx_putreg(0, PIC32MX_USB_EIE);
|
||||||
|
pic32mx_putreg(0, PIC32MX_USB_IE);
|
||||||
|
|
||||||
/* 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
|
* BDTP1: Bit 1-7: Bits 9-15 of the BDT base address
|
||||||
@ -3549,17 +3595,11 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
physaddr = PHYS_ADDR(g_bdt);
|
physaddr = PHYS_ADDR(g_bdt);
|
||||||
pic32mx_putreg((uint16_t)((physaddr >> 8) & USB_BDTP1_MASK), PIC32MX_USB_BDTP1);
|
|
||||||
pic32mx_putreg((uint16_t)((physaddr >> 16) & USB_BDTP2_MASK), PIC32MX_USB_BDTP2);
|
|
||||||
pic32mx_putreg((uint16_t)((physaddr >> 24) & USB_BDTP3_MASK), PIC32MX_USB_BDTP3);
|
pic32mx_putreg((uint16_t)((physaddr >> 24) & USB_BDTP3_MASK), PIC32MX_USB_BDTP3);
|
||||||
|
pic32mx_putreg((uint16_t)((physaddr >> 16) & USB_BDTP2_MASK), PIC32MX_USB_BDTP2);
|
||||||
|
pic32mx_putreg((uint16_t)((physaddr >> 8) & USB_BDTP1_MASK), PIC32MX_USB_BDTP1);
|
||||||
|
|
||||||
/* Assert reset request to all of the Ping Pong buffer pointers */
|
/* Reset to then default address */
|
||||||
|
|
||||||
regval = pic32mx_getreg(PIC32MX_USB_CON);
|
|
||||||
regval |= USB_CON_PPBRST;
|
|
||||||
pic32mx_putreg(regval, PIC32MX_USB_CON);
|
|
||||||
|
|
||||||
/* Reset to default address */
|
|
||||||
|
|
||||||
pic32mx_putreg(0, PIC32MX_USB_ADDR);
|
pic32mx_putreg(0, PIC32MX_USB_ADDR);
|
||||||
|
|
||||||
@ -3570,47 +3610,30 @@ static void pic32mx_hwreset(struct pic32mx_usbdev_s *priv)
|
|||||||
pic32mx_putreg(0, PIC32MX_USB_EP(i));
|
pic32mx_putreg(0, PIC32MX_USB_EP(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Assert reset request to all of the Ping Pong buffer pointers. This
|
||||||
|
* will reset all Even/Odd buffer pointers to the EVEN BD banks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
regval = pic32mx_getreg(PIC32MX_USB_CON);
|
||||||
|
regval |= USB_CON_PPBRST;
|
||||||
|
pic32mx_putreg(regval, PIC32MX_USB_CON);
|
||||||
|
|
||||||
/* Bring the ping pong buffer pointers out of reset */
|
/* Bring the ping pong buffer pointers out of reset */
|
||||||
|
|
||||||
|
up_mdelay(5);
|
||||||
regval &= ~USB_CON_PPBRST;
|
regval &= ~USB_CON_PPBRST;
|
||||||
pic32mx_putreg(regval, PIC32MX_USB_CON);
|
pic32mx_putreg(regval, PIC32MX_USB_CON);
|
||||||
|
|
||||||
/* Clear all of the buffer descriptor table (BDT) entries */
|
|
||||||
|
|
||||||
memset((void*)g_bdt, 0, sizeof(g_bdt));
|
|
||||||
|
|
||||||
/* Initialize EP0 as a Ctrl EP */
|
|
||||||
|
|
||||||
pic32mx_putreg(PIC32MX_EP_CONTROL, PIC32MX_USB_EP0);
|
|
||||||
regdbg("PIC32MX_USB_EP0: %04x\n", getreg16(PIC32MX_USB_EP0));
|
|
||||||
|
|
||||||
/* Flush any pending transactions */
|
|
||||||
|
|
||||||
while ((pic32mx_getreg(PIC32MX_USB_IR) & USB_INT_TRN) != 0)
|
|
||||||
{
|
|
||||||
pic32mx_putreg(USB_INT_TRN, PIC32MX_USB_IR);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Make sure packet processing is enabled */
|
|
||||||
|
|
||||||
regval = pic32mx_getreg(PIC32MX_USB_CON);
|
|
||||||
regval &= ~USB_CON_PKTDIS;
|
|
||||||
pic32mx_putreg(regval, PIC32MX_USB_CON);
|
|
||||||
|
|
||||||
/* Get ready for the first packet */
|
|
||||||
|
|
||||||
priv->eplist[EP0].bdtin = &g_bdt[EP0_IN_EVEN];
|
|
||||||
|
|
||||||
/* Indicate that we are now in the detached state */
|
/* Indicate that we are now in the detached state */
|
||||||
|
|
||||||
priv->devstate = DEVSTATE_DETACHED;
|
priv->devstate = DEVSTATE_DETACHED;
|
||||||
}
|
}
|
||||||
|
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
* Name: pic32mx_hwsetup
|
* Name: pic32mx_stateinit
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
static void pic32mx_hwsetup(struct pic32mx_usbdev_s *priv)
|
static void pic32mx_stateinit(struct pic32mx_usbdev_s *priv)
|
||||||
{
|
{
|
||||||
int epno;
|
int epno;
|
||||||
|
|
||||||
@ -3724,9 +3747,9 @@ void up_usbinitialize(void)
|
|||||||
|
|
||||||
usbtrace(TRACE_DEVINIT, 0);
|
usbtrace(TRACE_DEVINIT, 0);
|
||||||
|
|
||||||
/* Power up the USB controller, but leave it in the reset state */
|
/* Initialize the driver state structure */
|
||||||
|
|
||||||
pic32mx_hwsetup(priv);
|
pic32mx_stateinit(priv);
|
||||||
|
|
||||||
/* Attach USB controller interrupt handler. The hardware will not be
|
/* Attach USB controller interrupt handler. The hardware will not be
|
||||||
* initialized and interrupts will not be enabled until the class device
|
* initialized and interrupts will not be enabled until the class device
|
||||||
@ -3788,8 +3811,8 @@ void up_usbuninitialize(void)
|
|||||||
* Name: usbdev_register
|
* Name: usbdev_register
|
||||||
*
|
*
|
||||||
* Description:
|
* Description:
|
||||||
* Register a USB device class driver. The class driver's bind() method will be
|
* Register a USB device class driver. The class driver's bind() method
|
||||||
* called to bind it to a USB device driver.
|
* will be called to bind it to a USB device driver.
|
||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
@ -3832,11 +3855,29 @@ int usbdev_register(struct usbdevclass_driver_s *driver)
|
|||||||
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BINDFAILED), (uint16_t)-ret);
|
usbtrace(TRACE_DEVERROR(PIC32MX_TRACEERR_BINDFAILED), (uint16_t)-ret);
|
||||||
priv->driver = NULL;
|
priv->driver = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The class driver has been successfully bound. */
|
||||||
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* Setup the USB controller in it initial unconnected state */
|
/* Setup the USB controller in it initial unconnected state */
|
||||||
|
|
||||||
|
DEBUGASSERT(priv->devstate == DEVSTATE_DETACHED);
|
||||||
pic32mx_hwreset(priv);
|
pic32mx_hwreset(priv);
|
||||||
|
|
||||||
|
/* We do not know the order in which the user will call APIs. If
|
||||||
|
* pic32mx_attach() were called before we got here, the the attach
|
||||||
|
* flag will be set and we should also attach to the USB bus.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->attached)
|
||||||
|
{
|
||||||
|
/* usbdev_attach() has already been called.. attach to the bus
|
||||||
|
* now
|
||||||
|
*/
|
||||||
|
|
||||||
|
pic32mx_attach(priv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -3893,7 +3934,7 @@ int usbdev_unregister(struct usbdevclass_driver_s *driver)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
pic32mx_hwshutdown(priv);
|
pic32mx_hwshutdown(priv);
|
||||||
pic32mx_hwsetup(priv);
|
pic32mx_stateinit(priv);
|
||||||
|
|
||||||
/* Unhook the driver */
|
/* Unhook the driver */
|
||||||
|
|
||||||
@ -3919,7 +3960,23 @@ void pic32mx_usbattach(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct pic32mx_usbdev_s *priv = &g_usbdev;
|
struct pic32mx_usbdev_s *priv = &g_usbdev;
|
||||||
pic32mx_attach(priv);
|
|
||||||
|
/* Mark that we are attached */
|
||||||
|
|
||||||
|
priv->attached = 1;
|
||||||
|
|
||||||
|
/* This API may be called asynchronously from other initialization
|
||||||
|
* interfaces. In particular, we may not want to attach the bus yet...
|
||||||
|
* that should only be done when the class driver is attached. Has
|
||||||
|
* the class driver been attached?
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (priv->driver)
|
||||||
|
{
|
||||||
|
/* Yes.. then attach to the bus */
|
||||||
|
|
||||||
|
pic32mx_attach(priv);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pic32mx_usbdetach(void)
|
void pic32mx_usbdetach(void)
|
||||||
@ -3930,6 +3987,9 @@ void pic32mx_usbdetach(void)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
struct pic32mx_usbdev_s *priv = &g_usbdev;
|
struct pic32mx_usbdev_s *priv = &g_usbdev;
|
||||||
|
|
||||||
|
/* Detach from the bus */
|
||||||
|
|
||||||
pic32mx_detach(priv);
|
pic32mx_detach(priv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +319,10 @@
|
|||||||
|
|
||||||
/* Offset 4: BUFFER_ADDRESS, 32-bit Buffer Address bits */
|
/* Offset 4: BUFFER_ADDRESS, 32-bit Buffer Address bits */
|
||||||
|
|
||||||
|
#define USB_BDT_BYTES_SIZE 8 /* Eight bytes per BDT */
|
||||||
|
#define USB_BDT_WORD_SIZE 2 /* Two 32-bit words per BDT */
|
||||||
|
#define USB_NBDTS_PER_EP 4 /* Number of BDTS per endpoint: IN/OUT and EVEN/ODD */
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Public Types
|
* Public Types
|
||||||
************************************************************************************/
|
************************************************************************************/
|
||||||
|
@ -283,7 +283,7 @@ USART6
|
|||||||
RX PC7*, PG9**
|
RX PC7*, PG9**
|
||||||
TX PC6, PG14**
|
TX PC6, PG14**
|
||||||
|
|
||||||
* Indicates pins that have other on-board functins and should be used only
|
* Indicates pins that have other on-board functions and should be used only
|
||||||
with care (See table 5 in the STM32F4Discovery User Guide). The rest are
|
with care (See table 5 in the STM32F4Discovery User Guide). The rest are
|
||||||
free I/O pins.
|
free I/O pins.
|
||||||
** Port G pins are not supported by the MCU
|
** Port G pins are not supported by the MCU
|
||||||
@ -342,7 +342,7 @@ TIM13
|
|||||||
TIM14
|
TIM14
|
||||||
CH1 PA7*, PF9
|
CH1 PA7*, PF9
|
||||||
|
|
||||||
* Indicates pins that have other on-board functins and should be used only
|
* Indicates pins that have other on-board functions and should be used only
|
||||||
with care (See table 5 in the STM32F4Discovery User Guide). The rest are
|
with care (See table 5 in the STM32F4Discovery User Guide). The rest are
|
||||||
free I/O pins.
|
free I/O pins.
|
||||||
** Port H pins are not supported by the MCU
|
** Port H pins are not supported by the MCU
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
* configs/sure-pic32mx/src/up_usbdev.c
|
* configs/sure-pic32mx/src/up_usbdev.c
|
||||||
* arch/arm/src/board/up_usbdev.c
|
* arch/arm/src/board/up_usbdev.c
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
|
* Copyright (C) 2011-2012 Gregory Nutt. All rights reserved.
|
||||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||||
*
|
*
|
||||||
* References:
|
* References:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user