summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-03 13:47:40 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2012-01-03 13:47:40 +0000
commitb748be7443a9b0a3077856a5a11ac12acbcefda9 (patch)
tree6b22f4ee9ebc41eb7a656398a7b565c5a4ad9015
parent048e0346039fad2af077a7ebe7fb815c9d98cfd2 (diff)
downloadnuttx-b748be7443a9b0a3077856a5a11ac12acbcefda9.tar.gz
nuttx-b748be7443a9b0a3077856a5a11ac12acbcefda9.tar.bz2
nuttx-b748be7443a9b0a3077856a5a11ac12acbcefda9.zip
Improve LPC17xx CAN interrupt handling; Additions to LPC17xx SPI driver
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@4255 42af7a65-404d-4744-a932-0658087f49c3
-rw-r--r--apps/examples/can/can_main.c6
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_can.c48
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_internal.h46
-rwxr-xr-xnuttx/arch/arm/src/lpc17xx/lpc17_ssp.c24
4 files changed, 102 insertions, 22 deletions
diff --git a/apps/examples/can/can_main.c b/apps/examples/can/can_main.c
index a3a2e916a..4e12fcd08 100644
--- a/apps/examples/can/can_main.c
+++ b/apps/examples/can/can_main.c
@@ -216,12 +216,16 @@ int MAIN_NAME(int argc, char *argv[])
message("ERROR: Data does not match. DLC=%d\n", msgdlc);
for (i = 0; i < msgdlc; i++)
{
- message(" %d: TX %02x RX %02x\n", txmsg.cm_data[i], rxmsg.cm_data[i]);
+ message(" %d: TX %02x RX %02x\n", i, txmsg.cm_data[i], rxmsg.cm_data[i]);
errval = 5;
goto errout_with_dev;
}
}
+ /* Report success */
+
+ message(" ID: %4d DLC: %d -- OK\n", msgid, msgdlc);
+
/* Set up for the next pass */
msgdata += msgdlc;
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_can.c b/nuttx/arch/arm/src/lpc17xx/lpc17_can.c
index 41f823459..00c00d918 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_can.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_can.c
@@ -501,9 +501,15 @@ static void can_rxint(FAR struct can_dev_s *dev, bool enable)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->cd_priv;
uint32_t regval;
+ irqstate_t flags;
canvdbg("CAN%d enable: %d\n", priv->port, enable);
+ /* The EIR register is also modifed from the interrupt handler, so we have
+ * to protect this code section.
+ */
+
+ flags = irqsave();
regval = can_getreg(priv, LPC17_CAN_IER_OFFSET);
if (enable)
{
@@ -514,6 +520,7 @@ static void can_rxint(FAR struct can_dev_s *dev, bool enable)
regval &= ~CAN_IER_RIE;
}
can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
+ irqrestore(flags);
}
/****************************************************************************
@@ -534,6 +541,7 @@ static void can_txint(FAR struct can_dev_s *dev, bool enable)
{
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->cd_priv;
uint32_t regval;
+ irqstate_t flags;
canvdbg("CAN%d enable: %d\n", priv->port, enable);
@@ -544,10 +552,20 @@ static void can_txint(FAR struct can_dev_s *dev, bool enable)
if (!enable)
{
+ /* TX interrupts are also disabled from the interrupt handler, so we have
+ * to protect this code section.
+ */
+
+ flags = irqsave();
+
+ /* Disable all TX interrupts */
+
regval = can_getreg(priv, LPC17_CAN_IER_OFFSET);
regval &= ~(CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3);
can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
+ irqrestore(flags);
}
+
}
/****************************************************************************
@@ -684,17 +702,19 @@ static int can_send(FAR struct can_dev_s *dev, FAR struct can_msg_s *msg)
else if ((regval & CAN_SR_TBS3) != 0)
{
/* We have no more buffers. We will make the caller wait. First, make
- * sure that the buffer 3 TX interrupt is enabled BEFORE sending the
- * message. The TX interrupt is generated TBS3 bit in CANxSR goes from 0
- * to 1 when the TIE3 bit in CANxIER is 1. If we don't enable it now,
- * we will miss interrupts.
+ * sure that all buffer 3 interrupts are enabled BEFORE sending the
+ * message. The TX interrupt is generated TBSn bit in CANxSR goes from 0
+ * to 1 when the TIEn bit in CANxIER is 1. If we don't enable it now,
+ * we will miss the TIE3 interrupt. We enable ALL TIE interrupts here
+ * because we don't care which one finishes: When first one finishes it
+ * means that a transmit buffer is again available.
*
- * Hmmm... we could probably do better than this. Buffer 1 or 2 is much
- * more likely to complete quicker than buffer 3.
+ * NOTE: The IER is also modified from the interrupt handler, but the
+ * following is safe because interrupts are disabled here.
*/
regval = can_getreg(priv, LPC17_CAN_IER_OFFSET);
- regval |= CAN_IER_TIE3;
+ regval |= (CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3);
can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
/* Set up the transfer */
@@ -803,10 +823,20 @@ static void can_interrupt(FAR struct can_dev_s *dev)
can_receive(dev, hdr, (uint8_t *)data);
}
- /* Check for a transmit interrupt from buffer 3 */
+ /* Check for a transmit interrupt from buffer 1, 2, or 3 meaning that at
+ * least one TX is complete and that at least one TX buffer is available.
+ */
- if ((regval & CAN_ICR_TI3) != 0)
+ if ((regval & (CAN_ICR_TI1 | CAN_ICR_TI2 |CAN_ICR_TI3)) != 0)
{
+ /* Disable all further TX interrupts */
+
+ regval = can_getreg(priv, LPC17_CAN_IER_OFFSET);
+ regval &= ~(CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3);
+ can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
+
+ /* Indicate that the TX is done and a new TX buffer is available */
+
can_txdone(&g_can1dev);
}
}
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h b/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h
index 06ac7b47a..fdb14b4d7 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_internal.h
@@ -47,6 +47,10 @@
#include <stdint.h>
#include <stdbool.h>
+#if defined(CONFIG_LPC17_SPI) || defined(CONFIG_LPC17_SSP0) || defined(CONFIG_LPC17_SSP1)
+# include <nuttx/spi.h>
+#endif
+
#include "up_internal.h"
#include "chip.h"
@@ -583,9 +587,6 @@ EXTERN void lpc17_clrpend(int irq);
*
************************************************************************************/
-struct spi_dev_s;
-enum spi_dev_e;
-
#ifdef CONFIG_LPC17_SPI
EXTERN void lpc17_spiselect(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
EXTERN uint8_t lpc17_spistatus(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
@@ -593,6 +594,7 @@ EXTERN uint8_t lpc17_spistatus(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
EXTERN int lpc17_spicmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
+
#ifdef CONFIG_LPC17_SSP0
EXTERN void lpc17_ssp0select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
EXTERN uint8_t lpc17_ssp0status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
@@ -600,6 +602,7 @@ EXTERN uint8_t lpc17_ssp0status(FAR struct spi_dev_s *dev, enum spi_dev_e devid)
EXTERN int lpc17_ssp0cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
#endif
#endif
+
#ifdef CONFIG_LPC17_SSP1
EXTERN void lpc17_ssp1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
EXTERN uint8_t lpc17_ssp1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
@@ -624,15 +627,50 @@ EXTERN int lpc17_ssp1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bo
*
****************************************************************************/
-struct spi_dev_s;
#ifdef CONFIG_LPC17_SPI
EXTERN void spi_flush(FAR struct spi_dev_s *dev);
#endif
+
#if defined(CONFIG_LPC17_SSP0) || defined(CONFIG_LPC17_SSP1)
EXTERN void ssp_flush(FAR struct spi_dev_s *dev);
#endif
/****************************************************************************
+ * Name: lpc17_spi/ssp0/1register
+ *
+ * Description:
+ * If the board supports a card detect callback to inform the SPI-based
+ * MMC/SD drvier when an SD card is inserted or removed, then
+ * CONFIG_SPI_CALLBACK should be defined and the following function(s) must
+ * must be implemented. These functiosn implements the registercallback
+ * method of the SPI interface (see include/nuttx/spi.h for details)
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * callback - The funtion to call on the media change
+ * arg - A caller provided value to return with the callback
+ *
+ * Returned Value:
+ * 0 on success; negated errno on failure.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_LPC17_SPI
+EXTERN int lpc17_spiregister(FAR struct spi_dev_s *dev,
+ spi_mediachange_t callback, void *arg);
+#endif
+
+#ifdef CONFIG_LPC17_SSP0
+EXTERN int lpc17_ssp0register(FAR struct spi_dev_s *dev,
+ spi_mediachange_t callback, void *arg);
+#endif
+
+#ifdef CONFIG_LPC17_SSP1
+EXTERN int lpc17_ssp1register(FAR struct spi_dev_s *dev,
+ spi_mediachange_t callback, void *arg);
+#endif
+
+/****************************************************************************
* Name: lpc17_dmainitialize
*
* Description:
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c b/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c
index 94f6427d0..e945ced40 100755
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c
@@ -165,18 +165,22 @@ static const struct spi_ops_s g_spi0ops =
#ifndef CONFIG_SPI_OWNBUS
.lock = ssp_lock,
#endif
- .select = lpc17_ssp0select,
+ .select = lpc17_ssp0select, /* Provided externally */
.setfrequency = ssp_setfrequency,
.setmode = ssp_setmode,
.setbits = ssp_setbits,
- .status = lpc17_ssp0status,
+ .status = lpc17_ssp0status, /* Provided externally */
#ifdef CONFIG_SPI_CMDDATA
- .cmddata = lpc17_ssp0cmddata,
+ .cmddata = lpc17_ssp0cmddata, /* Provided externally */
#endif
.send = ssp_send,
.sndblock = ssp_sndblock,
.recvblock = ssp_recvblock,
- .registercallback = 0, /* Not implemented */
+#ifdef CONFIG_SPI_CALLBACK
+ .registercallback = lpc17_ssp0register, /* Provided externally */
+#else
+ .registercallback = 0, /* Not implemented */
+#endif
};
static struct lpc17_sspdev_s g_ssp0dev =
@@ -195,18 +199,22 @@ static const struct spi_ops_s g_spi1ops =
#ifndef CONFIG_SPI_OWNBUS
.lock = ssp_lock,
#endif
- .select = lpc17_ssp1select,
+ .select = lpc17_ssp1select, /* Provided externally */
.setfrequency = ssp_setfrequency,
.setmode = ssp_setmode,
.setbits = ssp_setbits,
- .status = lpc17_ssp1status,
+ .status = lpc17_ssp1status, /* Provided externally */
#ifdef CONFIG_SPI_CMDDATA
- .cmddata = lpc17_ssp1cmddata,
+ .cmddata = lpc17_ssp1cmddata, /* Provided externally */
#endif
.send = ssp_send,
.sndblock = ssp_sndblock,
.recvblock = ssp_recvblock,
- .registercallback = 0, /* Not implemented */
+#ifdef CONFIG_SPI_CALLBACK
+ .registercallback = lpc17_ssp1register, /* Provided externally */
+#else
+ .registercallback = 0, /* Not implemented */
+#endif
};
static struct lpc17_sspdev_s g_ssp1dev =