summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--nuttx/ChangeLog5
-rw-r--r--nuttx/Documentation/NuttX.html4
-rw-r--r--nuttx/TODO25
-rwxr-xr-xnuttx/arch/arm/src/imx/imx_spi.c88
-rwxr-xr-xnuttx/arch/z80/src/ez80/ez80_spi.c1
-rw-r--r--nuttx/include/nuttx/spi.h68
6 files changed, 172 insertions, 19 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index 4464c8615..ba377d494 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -703,4 +703,7 @@
number of bits per word is greater an 8 (such as with many 9-bit display
interfaces). -- this might have broken a few things which will need to
be retested!
-
+ * arch/arm/src/imx: Added i.MX SPI driver
+ * SPI: Add a method to set the number of bits per word. Also add an
+ alternative interface for so that (eventually) I can phase the sndblock
+ and recvblock methods and replace them with a single exchange method
diff --git a/nuttx/Documentation/NuttX.html b/nuttx/Documentation/NuttX.html
index 15977d93d..b48a764ed 100644
--- a/nuttx/Documentation/NuttX.html
+++ b/nuttx/Documentation/NuttX.html
@@ -1389,6 +1389,10 @@ nuttx-0.4.6 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
number of bits per word is greater an 8 (such as with many 9-bit display
interfaces). -- this might have broken a few things which will need to
be retested!
+ * arch/arm/src/imx: Added i.MX SPI driver
+ * SPI: Add a method to set the number of bits per word. Also add an
+ alternative interface for so that (eventually) I can phase the sndblock
+ and recvblock methods and replace them with a single exchange method
pascal-0.1.3 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
diff --git a/nuttx/TODO b/nuttx/TODO
index ac208f540..1007989d1 100644
--- a/nuttx/TODO
+++ b/nuttx/TODO
@@ -21,9 +21,9 @@ NuttX TODO List (Last updated April 12, 2009)
(2) ARM (arch/arm/)
(1) ARM/C5471 (arch/arm/src/c5471/)
(3) ARM/DM320 (arch/arm/src/dm320/)
- (1) ARM/i.MX (arch/arm/src/imx/)
- (6) ARM/LPC214x (arch/arm/src/lpc214x/)
- (3) ARM/STR71x (arch/arm/src/str71x/)
+ (2) ARM/i.MX (arch/arm/src/imx/)
+ (3) ARM/LPC214x (arch/arm/src/lpc214x/)
+ (4) ARM/STR71x (arch/arm/src/str71x/)
(4) pjrc-8052 / MCS51 (arch/pjrc-8051/)
(2) Hitachi/Renesas SH-1 (arch/sh/src/sh1)
(4) Renesas M16C/26 (arch/sh/src/m16c)
@@ -483,6 +483,10 @@ o ARM/i.MX (arch/arm/src/imx/)
Status: Open (and in work)
Priority: Medium (high if you need i.MX1/L support)
+ Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy.
+ Status: Open
+ Priority: Medium -- Will be very high if you do SPI access from multiple threads.
+
o ARM/LPC214x (arch/arm/src/lpc214x/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -509,9 +513,16 @@ o ARM/LPC214x (arch/arm/src/lpc214x/)
Priority: High
Description: At present the SPI driver is polled. Should it be interrupt driven?
+ Look at arch/arm/src/imx/imx_spi.c -- that is a good example of an
+ interrupt driven SPI driver. Should be very easy to part that architecture
+ to the LPC.
Status: Open
Priority: Medium
+ Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy.
+ Status: Open
+ Priority: Medium -- Will be very high if you do SPI access from multiple threads.
+
Description: At present the SPI driver is polled -AND- there is a rather large, arbitrary,
delay in one of the block access routines. The purpose of the delay is to
avoid a race conditions. This begs for a re-design -OR- at a minimum, some
@@ -535,6 +546,10 @@ o ARM/STR71x (arch/arm/src/str71x/)
Status: Open
Priority: Medium
+ Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy.
+ Status: Open
+ Priority: Medium -- Will be very high if you do SPI access from multiple threads.
+
o pjrc-8052 / MCS51 (arch/pjrc-8051/)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -704,6 +719,10 @@ o z80/z8/ez80 (arch/z80)
Status: Open
Priority: Med
+ Description: SPI methods are not thread safe. Needs a semaphore to protect from re-entrancy.
+ Status: Open
+ Priority: Medium -- Will be very high if you do SPI access from multiple threads.
+
Description: A "generic" I2C driver has been coded for the eZ8Encore!
However, this remains untested since I have no I2C devices for
the board (yet).
diff --git a/nuttx/arch/arm/src/imx/imx_spi.c b/nuttx/arch/arm/src/imx/imx_spi.c
index 54fd5502e..437bd009d 100755
--- a/nuttx/arch/arm/src/imx/imx_spi.c
+++ b/nuttx/arch/arm/src/imx/imx_spi.c
@@ -166,9 +166,15 @@ static int spi_interrupt(int irq, void *context);
static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
+static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd);
-static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen);
-static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t buflen);
+#ifdef CONFIG_SPI_EXCHANGE
+static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
+ FAR void *rxbuffer, size_t nwords);
+#else
+static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords);
+static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords);
+#endif
/****************************************************************************
* Private Data
@@ -181,10 +187,15 @@ static const struct spi_ops_s g_spiops =
.select = imx_spiselect, /* Provided externally by board logic */
.setfrequency = spi_setfrequency,
.setmode = spi_setmode,
+ .setbits = spi_setbits,
.status = imx_spistatus, /* Provided externally by board logic */
.send = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = spi_exchange,
+#else
.sndblock = spi_sndblock,
.recvblock = spi_recvblock,
+#endif
};
/* This supports is up to two SPI busses/ports */
@@ -795,6 +806,34 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
}
/****************************************************************************
+ * Name: spi_setbits
+ *
+ * Description:
+ * Set the number if bits per word.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * nbits - The number of bits requests
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+
+static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
+{
+ struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
+ if (priv && nbits != priv->nbits && nbits > 0 && nbits <= 16)
+ {
+ uint32 regval = spi_getreg(priv, CSPI_CTRL_OFFSET);
+ regval &= ~CSPI_CTRL_BITCOUNT_MASK;
+ regval |= ((nbits - 1) << CSPI_CTRL_BITCOUNT_SHIFT);
+ spi_putreg(priv, CSPI_CTRL_OFFSET, regval);
+ priv->nbits = nbits;
+ }
+}
+
+/****************************************************************************
* Name: spi_send
*
* Description:
@@ -819,6 +858,35 @@ static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
return response;
}
+/****************************************************************************
+ * Name: SPI_EXCHANGE
+ *
+ * Description:
+ * Exahange a block of data from SPI. Required.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * buffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to the buffer in which to recieve data
+ * nwords - the length of data that to be exchanged in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into ubytes; if nbits >8, the data is packed into uint16's
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SPI_EXCHANGE
+static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
+ FAR void *rxbuffer, size_t nwords)
+{
+ struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
+ (void)spi_transfer(priv, txbuffer, rxbuffer, nwords);
+}
+#endif
+
/*************************************************************************
* Name: spi_sndblock
*
@@ -828,7 +896,7 @@ static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the buffer of data to be sent
- * buflen - the length of data to send from the buffer in number of words.
+ * nwords - the length of data to send from the buffer in number of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into ubytes; if nbits >8, the data is packed into uint16's
@@ -838,11 +906,13 @@ static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
*
****************************************************************************/
-static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen)
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords)
{
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
- (void)spi_transfer(priv, buffer, NULL, buflen);
+ (void)spi_transfer(priv, buffer, NULL, nwords);
}
+#endif
/****************************************************************************
* Name: spi_recvblock
@@ -853,7 +923,7 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the buffer in which to recieve data
- * buflen - the length of data that can be received in the buffer in number
+ * nwords - the length of data that can be received in the buffer in number
* of words. The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into ubytes; if nbits >8, the data is packed into uint16's
@@ -863,11 +933,13 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
*
****************************************************************************/
-static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t buflen)
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords)
{
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
- (void)spi_transfer(priv, NULL, buffer, buflen);
+ (void)spi_transfer(priv, NULL, buffer, nwords);
}
+#endif
/****************************************************************************
* Public Functions
diff --git a/nuttx/arch/z80/src/ez80/ez80_spi.c b/nuttx/arch/z80/src/ez80/ez80_spi.c
index 20db1035a..8e34de10e 100755
--- a/nuttx/arch/z80/src/ez80/ez80_spi.c
+++ b/nuttx/arch/z80/src/ez80/ez80_spi.c
@@ -80,6 +80,7 @@ static const struct spi_ops_s g_spiops =
ez80_spiselect, /* Provided externally by board logic */
spi_setfrequency,
spi_setmode,
+ NULL, /* Variable number of bits not implemented */
ez80_spistatus, /* Provided externally by board logic */
spi_send,
spi_sndblock,
diff --git a/nuttx/include/nuttx/spi.h b/nuttx/include/nuttx/spi.h
index 7e60a53b3..200232735 100644
--- a/nuttx/include/nuttx/spi.h
+++ b/nuttx/include/nuttx/spi.h
@@ -105,6 +105,23 @@
#define SPI_SETMODE(d,m) ((d)->ops->mode ? (d)->ops->mode(d,m) : (void))
/****************************************************************************
+ * Name: SPI_SETBITS
+ *
+ * Description:
+ * Set the number if bits per word.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * nbits - The number of bits requests
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+
+#define SPI_SETBITS(d,b) ((d)->ops->setbits ? (d)->ops->setbits(d,b) : (void))
+
+/****************************************************************************
* Name: SPI_STATUS
*
* Description:
@@ -156,7 +173,7 @@
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the buffer of data to be sent
- * buflen - the length of data to send from the buffer in number of words.
+ * nwords - the length of data to send from the buffer in number of words.
* The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into ubytes; if nbits >8, the data is packed into uint16's
@@ -166,18 +183,22 @@
*
****************************************************************************/
-#define SPI_SNDBLOCK(d,b,l) ((d)->ops->sndblock(d,b,l))
+#ifdef CONFIG_SPI_EXCHANGE
+# define SPI_SNDBLOCK(d,b,l) ((d)->ops->exchange(d,b,0,l))
+#else
+# define SPI_SNDBLOCK(d,b,l) ((d)->ops->sndblock(d,b,l))
+#endif
/****************************************************************************
* Name: SPI_RECVBLOCK
*
* Description:
- * Revice a block of data from SPI. Required.
+ * Receive a block of data from SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* buffer - A pointer to the buffer in which to recieve data
- * buflen - the length of data that can be received in the buffer in number
+ * nwords - the length of data that can be received in the buffer in number
* of words. The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is
* packed into ubytes; if nbits >8, the data is packed into uint16's
@@ -187,7 +208,35 @@
*
****************************************************************************/
-#define SPI_RECVBLOCK(d,b,l) ((d)->ops->recvblock(d,b,l))
+#ifdef CONFIG_SPI_EXCHANGE
+# define SPI_RECVBLOCK(d,b,l) ((d)->ops->exchange(d,0,b,l))
+#else
+# define SPI_RECVBLOCK(d,b,l) ((d)->ops->recvblock(d,b,l))
+#endif
+
+/****************************************************************************
+ * Name: SPI_EXCHANGE
+ *
+ * Description:
+ * Exahange a block of data from SPI. Required.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * buffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to the buffer in which to recieve data
+ * nwords - the length of data that to be exchanged in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into ubytes; if nbits >8, the data is packed into uint16's
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_SPI_EXCHANGE
+# define SPI_EXCHANGE(d,t,r,l) ((d)->ops->exchange(d,t,r,l))
+#endif
/****************************************************************************
* Name: SPI_REGISTERCALLBACK
@@ -247,10 +296,15 @@ struct spi_ops_s
void (*select)(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
uint32 (*setfrequency)(FAR struct spi_dev_s *dev, uint32 frequency);
void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
+ void (*setbits)(FAR struct spi_dev_s *dev, int nbits);
ubyte (*status)(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
uint16 (*send)(FAR struct spi_dev_s *dev, uint16 wd);
- void (*sndblock)(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen);
- void (*recvblock)(FAR struct spi_dev_s *dev, FAR void *buffer, size_t buflen);
+#ifdef CONFIG_SPI_EXCHANGE
+ void (*exchange)(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords);
+#else
+ void (*sndblock)(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords);
+ void (*recvblock)(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords);
+#endif
int (*registercallback)(FAR struct spi_dev_s *dev, mediachange_t callback, void *arg);
};