Fixes to PIC32 USB driver and LPC17xx CAN driver

git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4316 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
patacongo
2012-01-20 02:40:56 +00:00
parent bc6ca2a294
commit 1800623e98
3 changed files with 137 additions and 60 deletions
+8 -8
View File
@@ -151,7 +151,7 @@
# define CONFIG_CAN_TSEG2 7 # define CONFIG_CAN_TSEG2 7
#endif #endif
#define CAN_BIT_QUANTA (CONFIG_CAN_TSEG1 + CONFIG_CAN_TSEG2 + 3) #define CAN_BIT_QUANTA (CONFIG_CAN_TSEG1 + CONFIG_CAN_TSEG2 + 1)
/* Debug ********************************************************************/ /* Debug ********************************************************************/
/* Non-standard debug that may be enabled just for testing CAN */ /* Non-standard debug that may be enabled just for testing CAN */
@@ -1070,7 +1070,7 @@ static int can12_interrupt(int irq, void *context)
* *
* |<----------------- NOMINAL BIT TIME ----------------->| * |<----------------- NOMINAL BIT TIME ----------------->|
* |<- SYNC_SEG ->|<------ BS1 ------>|<------ BS2 ------>| * |<- SYNC_SEG ->|<------ BS1 ------>|<------ BS2 ------>|
* |<--- 3*Tq --->|<----- Tbs1 ------>|<----- Tbs2 ------>| * |<---- Tq ---->|<----- Tbs1 ------>|<----- Tbs2 ------>|
* *
* Where * Where
* Tbs1 is the duration of the BS1 segment * Tbs1 is the duration of the BS1 segment
@@ -1080,7 +1080,7 @@ static int can12_interrupt(int irq, void *context)
* Relationships: * Relationships:
* *
* baud = 1 / bit_time * baud = 1 / bit_time
* bit_time = 3*Tq + Tbs1 + Tbs2 * bit_time = Tq + Tbs1 + Tbs2
* Tbs1 = Tq * ts1 * Tbs1 = Tq * ts1
* Tbs2 = Tq * ts2 * Tbs2 = Tq * ts2
* Tq = brp * Tcan * Tq = brp * Tcan
@@ -1108,14 +1108,14 @@ static int can_bittiming(struct up_dev_s *priv)
canllvdbg("CAN%d PCLK: %d baud: %d\n", priv->port, canllvdbg("CAN%d PCLK: %d baud: %d\n", priv->port,
CAN_CLOCK_FREQUENCY(priv->divisor), priv->baud); CAN_CLOCK_FREQUENCY(priv->divisor), priv->baud);
/* Try to get CAN_BIT_QUANTA quanta in one bit_time. /* Try to get CAN_BIT_QUANTA quanta in one bit_time.
* *
* bit_time = Tq*(3 + ts1 + ts2) * bit_time = Tq*(ts1 + ts2 + 1)
* nquanta = bit_time/Tq * nquanta = bit_time/Tq
* Tq = brp * Tcan * Tq = brp * Tcan
* nquanta = (3 + ts1 + ts2) * nquanta = (ts1 + ts2 + 1)
* *
* bit_time = brp * Tcan * (3 + ts1 + ts2) * bit_time = brp * Tcan * (ts1 + ts2 + 1)
* nquanta = bit_time / brp / Tcan * nquanta = bit_time / brp / Tcan
* brp = Fcan / baud / nquanta; * brp = Fcan / baud / nquanta;
* *
@@ -1135,7 +1135,7 @@ static int can_bittiming(struct up_dev_s *priv)
/* In this case, we have to guess a good value for ts1 and ts2 */ /* In this case, we have to guess a good value for ts1 and ts2 */
ts1 = (nclks - 1) >> 1; ts1 = (nclks - 1) >> 1;
ts2 = nclks - ts1 - 3; ts2 = nclks - ts1 - 1;
if (ts1 == ts2 && ts1 > 1 && ts2 < CAN_BTR_TSEG2_MAX) if (ts1 == ts2 && ts1 > 1 && ts2 < CAN_BTR_TSEG2_MAX)
{ {
ts1--; ts1--;
+129 -40
View File
@@ -338,6 +338,7 @@ union wb_u
struct pic32mx_req_s struct pic32mx_req_s
{ {
struct usbdev_req_s req; /* Standard USB request */ struct usbdev_req_s req; /* Standard USB request */
uint16_t inflight; /* The number of bytes "in-flight" */
struct pic32mx_req_s *flink; /* Supports a singly linked list */ struct pic32mx_req_s *flink; /* Supports a singly linked list */
}; };
@@ -422,7 +423,11 @@ 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); const uint8_t *src, uint32_t nbytes, bool toggle);
static void pic32mx_wrcomplete(struct pic32mx_usbdev_s *priv,
struct pic32mx_ep_s *privep);
static void pic32mx_wrrestart(struct pic32mx_usbdev_s *priv,
struct pic32mx_ep_s *privep);
static int pic32mx_wrrequest(struct pic32mx_usbdev_s *priv, static int pic32mx_wrrequest(struct pic32mx_usbdev_s *priv,
struct pic32mx_ep_s *privep); struct pic32mx_ep_s *privep);
static int pic32mx_rdcomplete(struct pic32mx_usbdev_s *priv, static int pic32mx_rdcomplete(struct pic32mx_usbdev_s *priv,
@@ -732,8 +737,8 @@ static void pic32mx_reqcomplete(struct pic32mx_ep_s *privep, int16_t result)
* Name: pic32mx_epwrite * Name: pic32mx_epwrite
****************************************************************************/ ****************************************************************************/
static void pic32mx_epwrite(struct pic32mx_ep_s *privep, static void pic32mx_epwrite(struct pic32mx_ep_s *privep, const uint8_t *src,
const uint8_t *src, uint32_t nbytes) uint32_t nbytes, bool toggle)
{ {
volatile struct usbotg_bdtentry_s *bdt = privep->bdtin; volatile struct usbotg_bdtentry_s *bdt = privep->bdtin;
uint32_t status; uint32_t status;
@@ -742,9 +747,23 @@ static void pic32mx_epwrite(struct pic32mx_ep_s *privep,
/* Clear status and toggle the DTS bit if required */ /* Clear status and toggle the DTS bit if required */
#ifdef CONFIG_USB_PINGPONG
/* Clear all bits in the status but preserve the data toggle bit */
status = bdt->status & USB_BDT_DATA01; status = bdt->status & USB_BDT_DATA01;
#ifndef CONFIG_USB_PINGPONG #else
status ^= USB_BDT_DATA01; if (toggle)
{
/* Clear all bits in the status but toggle DATA0/1 */
status = (bdt->status & USB_BDT_DATA01) ^ USB_BDT_DATA01;
}
else
{
/* Clear all bits in the status but set DATA1 */
status = USB_BDT_DATA1;
}
#endif #endif
bdt->status = status; bdt->status = status;
@@ -780,6 +799,85 @@ static void pic32mx_epwrite(struct pic32mx_ep_s *privep,
privep->txbusy = true; privep->txbusy = true;
} }
/****************************************************************************
* Name: pic32mx_wrcomplete
****************************************************************************/
static void pic32mx_wrcomplete(struct pic32mx_usbdev_s *priv,
struct pic32mx_ep_s *privep)
{
struct pic32mx_req_s *privreq;
int bytesleft;
/* Check the request from the head of the endpoint request queue. Since
* we got here from a write completion event, the request queue should
* be non-NULL.
*/
privreq = pic32mx_rqpeek(privep);
if (privreq != NULL)
{
/* An outgoing IN packet has completed. Update the number of bytes
* transferred.
*/
privreq->req.xfrd += privreq->inflight;
privreq->inflight = 0;
bytesleft = privreq->req.len - privreq->req.xfrd;
/* If all of the bytes were sent (bytesleft == 0) and no NULL packet is
* needed (!txnullpkt), then we are finished with the transfer
*/
if (bytesleft == 0 && !privep->txnullpkt)
{
/* The transfer is complete. Give the completed request back to
* the class driver.
*/
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
pic32mx_reqcomplete(privep, OK);
/* Special case writes to endpoint zero. If there is no transfer in
* progress, then we need to configure to received the next SETUP packet.
*/
if (USB_EPNO(privep->ep.eplog) == 0)
{
priv->ctrlstate = CTRLSTATE_WAITSETUP;
}
}
}
}
/****************************************************************************
* Name: pic32mx_wrrestart
****************************************************************************/
static void pic32mx_wrrestart(struct pic32mx_usbdev_s *priv,
struct pic32mx_ep_s *privep)
{
struct pic32mx_req_s *privreq;
/* Reset some endpoint state variables */
privep->txnullpkt = false;
privep->txbusy = false;
/* Check the request from the head of the endpoint request queue */
privreq = pic32mx_rqpeek(privep);
if (!privreq)
{
/* Restart transmission after we have recovered from a stall */
privreq->req.xfrd = 0;
privreq->inflight = 0;
(void)pic32mx_wrrequest(priv, privep);
}
}
/**************************************************************************** /****************************************************************************
* Name: pic32mx_wrrequest * Name: pic32mx_wrrequest
****************************************************************************/ ****************************************************************************/
@@ -829,8 +927,8 @@ static int pic32mx_wrrequest(struct pic32mx_usbdev_s *priv, struct pic32mx_ep_s
/* Get the number of bytes left to be sent in the packet */ /* Get the number of bytes left to be sent in the packet */
bytesleft = privreq->req.len - privreq->req.xfrd; bytesleft = privreq->req.len - privreq->req.xfrd;
nbytes = bytesleft; nbytes = bytesleft;
/* Send the next packet */ /* Send the next packet */
@@ -864,7 +962,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); pic32mx_epwrite(privep, buf, nbytes, privreq->req.xfrd > 0);
/* Special case endpoint 0 state information. The write request is in /* Special case endpoint 0 state information. The write request is in
* progress. * progress.
@@ -877,29 +975,7 @@ static int pic32mx_wrrequest(struct pic32mx_usbdev_s *priv, struct pic32mx_ep_s
/* Update for the next data IN interrupt */ /* Update for the next data IN interrupt */
privreq->req.xfrd += nbytes; privreq->inflight = nbytes;
bytesleft = privreq->req.len - privreq->req.xfrd;
/* If all of the bytes were sent (including any final null packet)
* then we are finished with the transfer
*/
if (bytesleft == 0 && !privep->txnullpkt)
{
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)), privreq->req.xfrd);
privep->txnullpkt = 0;
pic32mx_reqcomplete(privep, OK);
/* Special case writes to endpoint zero. If there is no transfer in
* progress, then we need to configure to received the next SETUP packet.
*/
if (epno == 0)
{
priv->ctrlstate = CTRLSTATE_WAITSETUP;
}
}
return OK; return OK;
} }
@@ -1225,7 +1301,13 @@ static void pic32mx_eptransfer(struct pic32mx_usbdev_s *priv, uint8_t epno,
usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_EPINDONE), status); usbtrace(TRACE_INTDECODE(PIC32MX_TRACEINTID_EPINDONE), status);
/* Handle write requests */ /* An outgoing IN packet has completed. Update the number of bytes transferred
* and check for completion of the transfer.
*/
pic32mx_wrcomplete(priv, privep);
/* Handle additional queued write requests */
pic32mx_wrrequest(priv, privep); pic32mx_wrrequest(priv, privep);
} }
@@ -1863,7 +1945,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); pic32mx_epwrite(&priv->eplist[EP0], response.b, nbytes, false);
priv->ctrlstate = CTRLSTATE_WAITSETUP; priv->ctrlstate = CTRLSTATE_WAITSETUP;
} }
@@ -1915,6 +1997,12 @@ static void pic32mx_ep0in(struct pic32mx_usbdev_s *priv)
if (priv->ctrlstate == CTRLSTATE_WRREQUEST) if (priv->ctrlstate == CTRLSTATE_WRREQUEST)
{ {
/* An outgoing EP0 transfer has completed. Update the byte count and
* check for the completion of the transfer.
*/
pic32mx_wrcomplete(priv, &priv->eplist[EP0]);
/* Handle the next queue IN transfer */ /* Handle the next queue IN transfer */
ret = pic32mx_wrrequest(priv, &priv->eplist[EP0]); ret = pic32mx_wrrequest(priv, &priv->eplist[EP0]);
@@ -2872,10 +2960,11 @@ static int pic32mx_epsubmit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
/* Handle the request from the class driver */ /* Handle the request from the class driver */
epno = USB_EPNO(ep->eplog); epno = USB_EPNO(ep->eplog);
req->result = -EINPROGRESS; req->result = -EINPROGRESS;
req->xfrd = 0; req->xfrd = 0;
flags = irqsave(); privreq->inflight = 0;
flags = irqsave();
/* If we are stalled, then drop all requests on the floor */ /* If we are stalled, then drop all requests on the floor */
@@ -2998,9 +3087,9 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
status = bdt->status; status = bdt->status;
#ifdef CONFIG_USB_PINGPONG
/* Toggle over the to the next buffer */ /* Toggle over the to the next buffer */
#ifdef CONFIG_USB_PINGPONG
status ^= USB_NEXT_PINGPONG; status ^= USB_NEXT_PINGPONG;
#endif #endif
status |= (USB_BDT_UOWN | USB_BDT_DATA1); status |= (USB_BDT_UOWN | USB_BDT_DATA1);
@@ -3013,7 +3102,7 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
/* Restart any queued write requests */ /* Restart any queued write requests */
(void)pic32mx_wrrequest(priv, privep); pic32mx_wrrestart(priv, privep);
} }
else else
{ {
@@ -3026,9 +3115,9 @@ static int pic32mx_epbdtstall(struct usbdev_ep_s *ep,
status = bdt->status; status = bdt->status;
#ifdef CONFIG_USB_PINGPONG
/* Toggle over the to the next buffer */ /* Toggle over the to the next buffer */
#ifdef CONFIG_USB_PINGPONG
status ^= USB_NEXT_PINGPONG; status ^= USB_NEXT_PINGPONG;
#endif #endif
status |= (USB_BDT_UOWN | USB_BDT_DATA1 | USB_BDT_DTS); status |= (USB_BDT_UOWN | USB_BDT_DATA1 | USB_BDT_DTS);
-12
View File
@@ -67,18 +67,6 @@
# relationship to interrupt vectors. In such cases, CONFIG_ARCH_VECNOTIRQ # relationship to interrupt vectors. In such cases, CONFIG_ARCH_VECNOTIRQ
# must defined so that the OS logic will know not to assume it can use # must defined so that the OS logic will know not to assume it can use
# a vector number to enable or disable interrupts. # a vector number to enable or disable interrupts.
# CONFIG_ARCH_NOINTC - define if the architecture does not
# support an interrupt controller or otherwise cannot support
# APIs like up_enable_irq() and up_disable_irq().
# CONFIG_ARCH_VECNOTIRQ - Usually the interrupt vector number provided
# to interfaces like irq_attach() and irq_detach are the same as IRQ
# numbers that are provied to IRQ management functions like
# up_enable_irq() and up_disable_irq(). But that is not true for all
# interrupt controller implementations. For example, the PIC32MX
# interrupt controller manages interrupt sources that have a many-to-one
# relationship to interrupt vectors. In such cases, CONFIG_ARCH_VECNOTIRQ
# must defined so that the OS logic will know not to assume it can use
# a vector number to enable or disable interrupts.
# CONFIG_ARCH_IRQPRIO - The PIC32MX supports interrupt prioritization # CONFIG_ARCH_IRQPRIO - The PIC32MX supports interrupt prioritization
# CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt # CONFIG_ARCH_INTERRUPTSTACK - This architecture supports an interrupt
# stack. If defined, this symbol is the size of the interrupt # stack. If defined, this symbol is the size of the interrupt