mirror of
https://github.com/apache/nuttx.git
synced 2026-06-04 23:03:27 +08:00
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
This commit is contained in:
@@ -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;
|
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->cd_priv;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
canvdbg("CAN%d enable: %d\n", priv->port, enable);
|
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);
|
regval = can_getreg(priv, LPC17_CAN_IER_OFFSET);
|
||||||
if (enable)
|
if (enable)
|
||||||
{
|
{
|
||||||
@@ -514,6 +520,7 @@ static void can_rxint(FAR struct can_dev_s *dev, bool enable)
|
|||||||
regval &= ~CAN_IER_RIE;
|
regval &= ~CAN_IER_RIE;
|
||||||
}
|
}
|
||||||
can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
|
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;
|
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->cd_priv;
|
||||||
uint32_t regval;
|
uint32_t regval;
|
||||||
|
irqstate_t flags;
|
||||||
|
|
||||||
canvdbg("CAN%d enable: %d\n", priv->port, enable);
|
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)
|
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_getreg(priv, LPC17_CAN_IER_OFFSET);
|
||||||
regval &= ~(CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3);
|
regval &= ~(CAN_IER_TIE1 | CAN_IER_TIE2 | CAN_IER_TIE3);
|
||||||
can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
|
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)
|
else if ((regval & CAN_SR_TBS3) != 0)
|
||||||
{
|
{
|
||||||
/* We have no more buffers. We will make the caller wait. First, make
|
/* 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
|
* sure that all buffer 3 interrupts are enabled BEFORE sending the
|
||||||
* message. The TX interrupt is generated TBS3 bit in CANxSR goes from 0
|
* message. The TX interrupt is generated TBSn bit in CANxSR goes from 0
|
||||||
* to 1 when the TIE3 bit in CANxIER is 1. If we don't enable it now,
|
* to 1 when the TIEn bit in CANxIER is 1. If we don't enable it now,
|
||||||
* we will miss interrupts.
|
* 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
|
* NOTE: The IER is also modified from the interrupt handler, but the
|
||||||
* more likely to complete quicker than buffer 3.
|
* following is safe because interrupts are disabled here.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
regval = can_getreg(priv, LPC17_CAN_IER_OFFSET);
|
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);
|
can_putreg(priv, LPC17_CAN_IER_OFFSET, regval);
|
||||||
|
|
||||||
/* Set up the transfer */
|
/* 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);
|
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);
|
can_txdone(&g_can1dev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,6 +47,10 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.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 "up_internal.h"
|
||||||
#include "chip.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
|
#ifdef CONFIG_LPC17_SPI
|
||||||
EXTERN void lpc17_spiselect(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
|
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);
|
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);
|
EXTERN int lpc17_spicmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_LPC17_SSP0
|
#ifdef CONFIG_LPC17_SSP0
|
||||||
EXTERN void lpc17_ssp0select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
|
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);
|
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);
|
EXTERN int lpc17_ssp0cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool cmd);
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_LPC17_SSP1
|
#ifdef CONFIG_LPC17_SSP1
|
||||||
EXTERN void lpc17_ssp1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected);
|
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);
|
EXTERN uint8_t lpc17_ssp1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
|
||||||
@@ -624,14 +627,49 @@ EXTERN int lpc17_ssp1cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bo
|
|||||||
*
|
*
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
|
|
||||||
struct spi_dev_s;
|
|
||||||
#ifdef CONFIG_LPC17_SPI
|
#ifdef CONFIG_LPC17_SPI
|
||||||
EXTERN void spi_flush(FAR struct spi_dev_s *dev);
|
EXTERN void spi_flush(FAR struct spi_dev_s *dev);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONFIG_LPC17_SSP0) || defined(CONFIG_LPC17_SSP1)
|
#if defined(CONFIG_LPC17_SSP0) || defined(CONFIG_LPC17_SSP1)
|
||||||
EXTERN void ssp_flush(FAR struct spi_dev_s *dev);
|
EXTERN void ssp_flush(FAR struct spi_dev_s *dev);
|
||||||
#endif
|
#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
|
* Name: lpc17_dmainitialize
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -165,18 +165,22 @@ static const struct spi_ops_s g_spi0ops =
|
|||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.lock = ssp_lock,
|
.lock = ssp_lock,
|
||||||
#endif
|
#endif
|
||||||
.select = lpc17_ssp0select,
|
.select = lpc17_ssp0select, /* Provided externally */
|
||||||
.setfrequency = ssp_setfrequency,
|
.setfrequency = ssp_setfrequency,
|
||||||
.setmode = ssp_setmode,
|
.setmode = ssp_setmode,
|
||||||
.setbits = ssp_setbits,
|
.setbits = ssp_setbits,
|
||||||
.status = lpc17_ssp0status,
|
.status = lpc17_ssp0status, /* Provided externally */
|
||||||
#ifdef CONFIG_SPI_CMDDATA
|
#ifdef CONFIG_SPI_CMDDATA
|
||||||
.cmddata = lpc17_ssp0cmddata,
|
.cmddata = lpc17_ssp0cmddata, /* Provided externally */
|
||||||
#endif
|
#endif
|
||||||
.send = ssp_send,
|
.send = ssp_send,
|
||||||
.sndblock = ssp_sndblock,
|
.sndblock = ssp_sndblock,
|
||||||
.recvblock = ssp_recvblock,
|
.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 =
|
static struct lpc17_sspdev_s g_ssp0dev =
|
||||||
@@ -195,18 +199,22 @@ static const struct spi_ops_s g_spi1ops =
|
|||||||
#ifndef CONFIG_SPI_OWNBUS
|
#ifndef CONFIG_SPI_OWNBUS
|
||||||
.lock = ssp_lock,
|
.lock = ssp_lock,
|
||||||
#endif
|
#endif
|
||||||
.select = lpc17_ssp1select,
|
.select = lpc17_ssp1select, /* Provided externally */
|
||||||
.setfrequency = ssp_setfrequency,
|
.setfrequency = ssp_setfrequency,
|
||||||
.setmode = ssp_setmode,
|
.setmode = ssp_setmode,
|
||||||
.setbits = ssp_setbits,
|
.setbits = ssp_setbits,
|
||||||
.status = lpc17_ssp1status,
|
.status = lpc17_ssp1status, /* Provided externally */
|
||||||
#ifdef CONFIG_SPI_CMDDATA
|
#ifdef CONFIG_SPI_CMDDATA
|
||||||
.cmddata = lpc17_ssp1cmddata,
|
.cmddata = lpc17_ssp1cmddata, /* Provided externally */
|
||||||
#endif
|
#endif
|
||||||
.send = ssp_send,
|
.send = ssp_send,
|
||||||
.sndblock = ssp_sndblock,
|
.sndblock = ssp_sndblock,
|
||||||
.recvblock = ssp_recvblock,
|
.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 =
|
static struct lpc17_sspdev_s g_ssp1dev =
|
||||||
|
|||||||
Reference in New Issue
Block a user