9
0
Fork 0

Extend SPI interface for word sizes >8bits

git-svn-id: https://nuttx.svn.sourceforge.net/svnroot/nuttx/trunk@1740 7fd9a85b-ad96-42d3-883c-3090e2eb8679
This commit is contained in:
patacongo 2009-04-26 16:06:29 +00:00
parent 80bb010aa6
commit e5fb54b7d2
9 changed files with 269 additions and 168 deletions

View File

@ -699,3 +699,8 @@
0.4.6 2009-xx-xx Gregory Nutt <spudmonkey@racsa.co.cr>
* Change SPI interface so that is can accomodate interfaces where the
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!

View File

@ -8,7 +8,7 @@
<tr align="center" bgcolor="#e4e4e4">
<td>
<h1><big><font color="#3c34ec"><i>NuttX RTOS</i></font></big></h1>
<p>Last Updated: April 25, 2009</p>
<p>Last Updated: April 26, 2009</p>
</td>
</tr>
</table>
@ -1385,6 +1385,11 @@ buildroot-0.1.5 2009-04-25 &lt;spudmonkey@racsa.co.cr&gt;
<pre><ul>
nuttx-0.4.6 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
* Change SPI interface so that is can accomodate interfaces where the
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!
pascal-0.1.3 2009-xx-xx Gregory Nutt &lt;spudmonkey@racsa.co.cr&gt;
buildroot-0.1.6 2009-xx-xx &lt;spudmonkey@racsa.co.cr&gt;

View File

@ -131,6 +131,8 @@
#define CSPI_INTCS_ROEN (1 << 14) /* BIT 14: RXFIFO Overflow Interrupt Enable */
#define CSPI_INTCS_BOEN (1 << 15) /* Bit 15: Bit Count Overflow Interrupt Enable */
#define CSPI_INTCS_ALLINTS 0x0000ff00
/* CSPI Sample Period Control Register */
#define CSPI_SPCR_WAIT_SHIFT 0

View File

@ -87,12 +87,17 @@
struct imx_spidev_s
{
const struct spi_ops_s *ops; /* Common SPI operations */
#ifndef CONFIG_SPI_POLLWAIT
sem_t sem; /* Wait for transfer to complete */
#endif
uint32 base; /* SPI register base address */
uint32 frequency; /* Current desired SCLK frequency */
uint32 actual; /* Current actual SCLK frequency */
ubyte mode; /* Current mode */
ubyte nbytes; /* Current number of bits per word */
#ifndef CONFIG_SPI_POLLWAIT
ubyte irq; /* SPI IRQ number */
#endif
};
/****************************************************************************
@ -103,16 +108,20 @@ struct imx_spidev_s
static inline uint32 spi_getreg(struct imx_spidev_s *priv, unsigned int offset);
static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32 value);
static ubyte spi_waitspif(struct imx_spidev_s *priv);
static ubyte spi_transfer(struct imx_spidev_s *priv, ubyte ch);
#ifndef CONFIG_SPI_POLLWAIT
static inline struct imx_spidev_s *spi_mapirq(int irq);
static int spi_interrupt(int irq, void *context);
#endif
static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
void *rxbuffer, unsigned int nwords);
/* SPI methods */
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 ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen);
static ubyte 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);
/****************************************************************************
* Private Data
@ -122,13 +131,13 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t
static const struct spi_ops_s g_spiops =
{
imx_spiselect, /* Provided externally by board logic */
spi_setfrequency,
spi_setmode,
imx_spistatus, /* Provided externally by board logic */
spi_sndbyte,
spi_sndblock,
spi_recvblock,
.select = imx_spiselect, /* Provided externally by board logic */
.frequency = spi_setfrequency,
.setmode = spi_setmode,
.status = imx_spistatus, /* Provided externally by board logic */
.send = spi_send,
.sndblock = spi_sndblock,
.recvblock = spi_recvblock,
};
/* This supports is up to two SPI busses/ports */
@ -139,14 +148,18 @@ static struct imx_spidev_s g_spidev[] =
{
.ops = &g_spiops,
.base = IMX_CSPI1_VBASE
#ifndef CONFIG_SPI_POLLWAIT
.irq = IMX_IRQ_CSPI1,
#endif
},
#endif
#ifndef CONFIG_SPI1_DISABLE
#ifndef CONFIG_SPI2_DISABLE
{
.ops = &g_spiops,
.base = IMX_CSPI2_VBASE
#ifndef CONFIG_SPI_POLLWAIT
.irq = IMX_IRQ_CSPI2,
#endif
},
#endif
};
@ -201,62 +214,93 @@ static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, ui
}
/****************************************************************************
* Name: spi_waitspif
* Name: spi_mapirq
*
* Description:
* Wait space available in the Tx FIFO.
* Map an IRQ number into the appropriate SPI device
*
* Input Parameters:
* priv - Device-specific state data
* irq - The IRQ number to be mapped
*
* Returned Value:
* Status register mode bits
* On success, a reference to the private data structgure for this IRQ.
* NULL on failrue.
*
****************************************************************************/
static uint32 spi_waitspif(struct imx_spidev_s *priv)
#ifndef CONFIG_SPI_POLLWAIT
static inline struct imx_spidev_s *spi_mapirq(int irq)
{
uint32 status;
/* Wait for the device to be ready to accept another byte (or for an error
* to be reported).
*/
#error "Missing logic"
return status;
switch (irq)
{
#ifndef CONFIG_SPI1_DISABLE
case IMX_IRQ_CSPI1:
return &g_spidev[SPI1_NDX];
#endif
#ifndef CONFIG_SPI2_DISABLE
case IMX_IRQ_CSPI2:
return &g_spidev[SPI2_NDX];
#endif
default:
return NULL;
}
}
#endif
/****************************************************************************
* Name: spi_transfer
*
* Description:
* Send one byte on SPI, return the response
* Exchange a block data with the SPI device
*
* Input Parameters:
* priv - Device-specific state data
* ch - the byte to send
* txbuffer - The buffer of data to send to the device (may be NULL).
* rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of ubytes;
* if the interface uses >8 bits per word, then this is the
* number of uint16's
*
* Returned Value:
* response
* 0: success, <0:Negated error number on failure
*
****************************************************************************/
static ubyte spi_transfer(struct imx_spidev_s *priv, ubyte ch)
#ifndef CONFIG_SPI_POLLWAIT
static int spi_interrupt(int irq, void *context)
{
ubyte status;
struct imx_spidev_s *priv = spi_mapirq(irq);
DBGASSERT(priv != NULL);
# error "Missing logic"
return OK;
}
#endif
/* Send the byte, repeating if some error occurs */
/****************************************************************************
* Name: spi_transfer
*
* Description:
* Exchange a block data with the SPI device
*
* Input Parameters:
* priv - Device-specific state data
* txbuffer - The buffer of data to send to the device (may be NULL).
* rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of ubytes;
* if the interface uses >8 bits per word, then this is the
* number of uint16's
*
* Returned Value:
* 0: success, <0:Negated error number on failure
*
****************************************************************************/
for(;;)
{
static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
void *rxbuffer, unsigned int nwords)
{
#error "Missing logic"
/* Wait for the device to be ready to accept another byte */
status = spi_waitspif(oriv);
/* Return the next byte from the Rx FIFO */
#error "Missing logic"
}
}
/****************************************************************************
@ -396,24 +440,28 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
}
/****************************************************************************
* Name: spi_sndbyte
* Name: spi_send
*
* Description:
* Send one byte on SPI
* Exchange one word on SPI
*
* Input Parameters:
* dev - Device-specific state data
* ch - The byte to send
* wd - The word to send. the size of the data is determined by the
* number of bits selected for the SPI interface.
*
* Returned Value:
* response
*
****************************************************************************/
static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
{
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
return spi_transfer(priv, ch);
struct imx_spidev_s *priv = (struct imx_spidev_s*)dev;
uint16 response = 0;
(void)spi_transfer(priv, &wd, &response, 1);
return response;
}
/*************************************************************************
@ -425,24 +473,20 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen)
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen)
{
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
uint32 response;
/* Loop while thre are bytes remaining to be sent */
while (buflen-- > 0)
{
response = spi_transfer(priv, *buffer++);
}
(void)spi_transfer(priv, buffer, NULL, buflen);
}
/****************************************************************************
@ -454,23 +498,20 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, siz
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen)
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t buflen)
{
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
/* Loop while thre are bytes remaining to be sent */
while (buflen-- > 0)
{
*buffer = (ubyte)spi_transfer(prive, 0xff);
}
(void)spi_transfer(priv, NULL, buffer, buflen);
}
/****************************************************************************
@ -584,7 +625,13 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
/* Disable SPI */
#error "Missing logic"
/* Initialize control rebistger: min frequency, ignore ready, master mode, mode=0, 8-bit */
/* Initialize the state structure */
ifndef CONFIG_SPI_POLLWAIT
sem_init(&priv->sem, 0, 0);
#endif
/* Initialize control register: min frequency, ignore ready, master mode, mode=0, 8-bit */
spi_putreg(priv, IMX_CSPI_CTRL_OFFSET,
CSPI_CTRL_DIV512 | /* Lowest frequency */
@ -603,10 +650,14 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
/* Enable interrupts on data ready (and certain error conditions */
ifndef CONFIG_SPI_POLLWAIT
spi_putreg(priv, CSPI_INTCS_OFFSET,
CSPI_INTCS_RREN | /* RXFIFO Data Ready Interrupt Enable */
CSPI_INTCS_ROEN | /* RXFIFO Overflow Interrupt Enable */
CSPI_INTCS_BOEN); /* Bit Count Overflow Interrupt Enable */
#else
spi_putreg(priv, CSPI_INTCS_OFFSET, 0); /* No interrupts */
#endif
/* Set the clock source=bit clock and number of clocks inserted between
* transactions = 2.
@ -620,7 +671,9 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
/* Attach the interrupt */
irq_attach(priv->irq, (xcpt_t)imx_spinterrupt);
ifndef CONFIG_SPI_POLLWAIT
irq_attach(priv->irq, (xcpt_t)spi_interrupt);
#endif
/* Enable SPI */
@ -630,7 +683,9 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
/* Enable SPI interrupts */
ifndef CONFIG_SPI_POLLWAIT
up_enable_irq(priv->irq);
#endif
return (FAR struct spi_dev_s *)priv;
}

View File

@ -67,7 +67,7 @@
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 ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch);
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen);
@ -81,7 +81,7 @@ static const struct spi_ops_s g_spiops =
spi_setfrequency,
spi_setmode,
ez80_spistatus, /* Provided externally by board logic */
spi_sndbyte,
spi_send,
spi_sndblock,
spi_recvblock,
};
@ -268,23 +268,24 @@ static ubyte spi_transfer(ubyte ch)
}
/****************************************************************************
* Name: spi_sndbyte
* Name: spi_send
*
* Description:
* Send one byte on SPI
* Exchange one word on SPI
*
* Input Parameters:
* dev - Device-specific state data
* ch - The byte to send
* wd - The word to send. the size of the data is determined by the
* number of bits selected for the SPI interface.
*
* Returned Value:
* response
*
****************************************************************************/
static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
{
return spi_transfer(ch);
return spi_transfer((ubyte)wd);
}
/*************************************************************************
@ -296,22 +297,26 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen)
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen)
{
FAR const ubyte *ptr = (FAR const ubyte*)buffer;
ubyte response;
/* Loop while thre are bytes remaining to be sent */
while (buflen-- > 0)
{
response = spi_transfer(*buffer++);
response = spi_transfer(*ptr++);
}
}
@ -324,22 +329,26 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, siz
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen)
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t buflen)
{
FAR ubyte *ptr = (FAR ubyte*)buffer;
ubyte response;
/* Loop while thre are bytes remaining to be sent */
while (buflen-- > 0)
{
*buffer = spi_transfer(0xff);
*ptr++ = spi_transfer(0xff);
}
}

View File

@ -89,9 +89,9 @@
static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);
static ubyte spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen);
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 ch);
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);
/****************************************************************************
* Private Data
@ -102,7 +102,7 @@ static const struct spi_ops_s g_spiops =
.select = spi_select,
.setfrequency = spi_setfrequency,
.status = spi_status,
.sndbyte = spi_sndbyte,
.send = spi_send,
.sndblock = spi_sndblock,
.recvblock = spi_recvblock,
};
@ -232,21 +232,22 @@ static ubyte spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid)
}
/****************************************************************************
* Name: spi_sndbyte
* Name: spi_send
*
* Description:
* Send one byte on SPI
* Exchange one word on SPI
*
* Input Parameters:
* dev - Device-specific state data
* ch - The byte to send
* wd - The word to send. the size of the data is determined by the
* number of bits selected for the SPI interface.
*
* Returned Value:
* response
*
****************************************************************************/
static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
{
/* Wait while the TX FIFO is full */
@ -254,7 +255,7 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
/* Write the byte to the TX FIFO */
putreg16(ch, LPC214X_SPI1_DR);
putreg16((ubyte)wd, LPC214X_SPI1_DR);
/* Wait for the RX FIFO not empty */
@ -262,7 +263,7 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
/* Get the value from the RX FIFO and return it */
return (ubyte)getreg16(LPC214X_SPI1_DR);
return (uint16)getreg16(LPC214X_SPI1_DR);
}
/*************************************************************************
@ -274,15 +275,19 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen)
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen)
{
FAR const ubyte *ptr = (FAR const ubyte *)buffer;
ubyte sr;
/* Loop while thre are bytes remaining to be sent */
@ -295,8 +300,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, siz
{
/* Send the data */
putreg16((uint16)*buffer, LPC214X_SPI1_DR);
buffer++;
putreg16((uint16)*ptr, LPC214X_SPI1_DR);
ptr++;
buflen--;
}
}
@ -339,20 +344,24 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, siz
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen)
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR const *buffer, size_t buflen)
{
FAR ubyte *ptr = (FAR ubyte*)buffer;
uint32 fifobytes = 0;
/* While there is remaining to be sent (and no synchronization error has occurred) */
while (buflen || fifobytes)
while (ptr || fifobytes)
{
/* Fill the transmit FIFO with 0xff...
* Write 0xff to the data register while (1) the TX FIFO is
@ -372,7 +381,7 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t b
while (getreg8(LPC214X_SPI1_SR) & LPC214X_SPI1SR_RNE)
{
*buffer++ = (ubyte)getreg16(LPC214X_SPI1_DR);
*ptr++ = (ubyte)getreg16(LPC214X_SPI1_DR);
fifobytes--;
}
}

View File

@ -266,9 +266,9 @@ static inline void spi_putreg(FAR struct str71x_spidev_s *priv, ubyte offset,
static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);
static ubyte spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen);
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);
/****************************************************************************
* Private Data
@ -279,7 +279,7 @@ static const struct spi_ops_s g_spiops =
.select = spi_select,
.setfrequency = spi_setfrequency,
.status = spi_status,
.sndbyte = spi_sndbyte,
.send = spi_send,
.sndblock = spi_sndblock,
.recvblock = spi_recvblock,
};
@ -518,21 +518,22 @@ static ubyte spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid)
}
/****************************************************************************
* Name: spi_sndbyte
* Name: spi_send
*
* Description:
* Send one byte on SPI
* Exchange one word on SPI
*
* Input Parameters:
* dev - Device-specific state data
* ch - The byte to send
* wd - The word to send. the size of the data is determined by the
* number of bits selected for the SPI interface.
*
* Returned Value:
* response
*
****************************************************************************/
static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
static uint16 spi_send(FAR struct spi_dev_s *dev, uint16 wd)
{
FAR struct str71x_spidev_s *priv = (FAR struct str71x_spidev_s *)dev;
@ -550,7 +551,7 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
/* Write the byte to the TX FIFO */
spi_putreg(priv, STR71X_BSPI_TXR_OFFSET, (uint16)ch << 8);
spi_putreg(priv, STR71X_BSPI_TXR_OFFSET, wd << 8);
/* Wait for the RX FIFO not empty */
@ -570,16 +571,20 @@ static ubyte spi_sndbyte(FAR struct spi_dev_s *dev, ubyte ch)
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen)
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t buflen)
{
FAR struct str71x_spidev_s *priv = (FAR struct str71x_spidev_s *)dev;
FAR const ubyte *ptr = (FAR const ubyte *)buffer;
uint16 csr2;
DEBUGASSERT(priv && priv->spibase);
@ -594,8 +599,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, siz
{
/* Send the data */
spi_putreg(priv, STR71X_BSPI_TXR_OFFSET, ((uint16)*buffer) << 8);
buffer++;
spi_putreg(priv, STR71X_BSPI_TXR_OFFSET, ((uint16)*ptr) << 8);
ptr++;
buflen--;
}
}
@ -638,16 +643,20 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, siz
* 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
* buflen - 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
*
* Returned Value:
* None
*
****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen)
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR const *buffer, size_t buflen)
{
FAR struct str71x_spidev_s *priv = (FAR struct str71x_spidev_s *)dev;
FAR ubyte *ptr = (FAR ubyte*)buffer;
uint32 fifobytes = 0;
DEBUGASSERT(priv && priv->spibase);
@ -674,7 +683,7 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t b
while ((spi_getreg(priv, STR71X_BSPI_CSR2_OFFSET) & STR71X_BSPICSR2_RFNE) != 0)
{
*buffer++ = (ubyte)(spi_getreg(priv, STR71X_BSPI_RXR_OFFSET) >> 8);
*ptr++ = (ubyte)(spi_getreg(priv, STR71X_BSPI_RXR_OFFSET) >> 8);
fifobytes--;
}
}

View File

@ -1,7 +1,7 @@
/****************************************************************************
* drivers/mmcsd/mmcsd_spi.c
*
* Copyright (C) 2008 Gregory Nutt. All rights reserved.
* Copyright (C) 2008-2009 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <spudmonkey@racsa.co.cr>
*
* Redistribution and use in source and binary forms, with or without
@ -333,7 +333,7 @@ static int mmcsd_waitready(FAR struct mmcsd_slot_s *slot)
for (i = 0; i < slot->twrite; i++)
{
response = SPI_SNDBYTE(spi, 0xff);
response = SPI_SEND(spi, 0xff);
if (response == 0xff)
{
return OK;
@ -366,23 +366,23 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
/* Send command code */
SPI_SNDBYTE(spi, cmd->cmd);
SPI_SEND(spi, cmd->cmd);
/* Send command's arguments */
if (cmd->arg == MMCSD_CMDARG_NONE)
{
SPI_SNDBYTE(spi, 0x00);
SPI_SNDBYTE(spi, 0x00);
SPI_SNDBYTE(spi, 0x00);
SPI_SNDBYTE(spi, 0x00);
SPI_SEND(spi, 0x00);
SPI_SEND(spi, 0x00);
SPI_SEND(spi, 0x00);
SPI_SEND(spi, 0x00);
}
else
{
SPI_SNDBYTE(spi, arg >> 24);
SPI_SNDBYTE(spi, arg >> 16);
SPI_SNDBYTE(spi, arg >> 8);
SPI_SNDBYTE(spi, arg);
SPI_SEND(spi, arg >> 24);
SPI_SEND(spi, arg >> 16);
SPI_SEND(spi, arg >> 8);
SPI_SEND(spi, arg);
}
/* Send CRC if needed. The SPI interface is initialized in non-protected
@ -392,18 +392,18 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
if (cmd->cmd == 0x40)
{
SPI_SNDBYTE(spi, 0x95);
SPI_SEND(spi, 0x95);
}
else
{
SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
}
/* Get the response to the command */
for (i = 0; i < 9 && response == 0xff; i++)
{
response = SPI_SNDBYTE(spi, 0xff);
response = SPI_SEND(spi, 0xff);
}
if (i == 0)
@ -422,7 +422,7 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
uint32 busy = 0;
for (i = 0; i < slot->twrite && busy != 0xff; i++)
{
busy = SPI_SNDBYTE(spi, 0xff);
busy = SPI_SEND(spi, 0xff);
}
fvdbg("Return R1B=%02x\n", response);
}
@ -437,7 +437,7 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
case MMCSD_CMDRESP_R2:
{
result = ((uint32) response << 8) & 0x0000ff00;
result |= SPI_SNDBYTE(spi, 0xff) & 0xff;
result |= SPI_SEND(spi, 0xff) & 0xff;
fvdbg("Return R2=%04x\n", result);
}
return result;
@ -445,10 +445,10 @@ static uint32 mmcsd_sendcmd(FAR struct mmcsd_slot_s *slot,
case MMCSD_CMDRESP_R3:
default:
{
result = ((uint32) response << 24) & 0xff000000;
result |= ((uint32) SPI_SNDBYTE(spi, 0xff) << 16) & 0x00ff0000;
result |= ((uint32) SPI_SNDBYTE(spi, 0xff) << 8) & 0x0000ff00;
result |= SPI_SNDBYTE(spi, 0xff) & 0xff;
result = ((uint32)response << 24) & 0xff000000;
result |= ((uint32)SPI_SEND(spi, 0xff) << 16) & 0x00ff0000;
result |= ((uint32)SPI_SEND(spi, 0xff) << 8) & 0x0000ff00;
result |= SPI_SEND(spi, 0xff) & 0xff;
fvdbg("Return R3=%08x\n", result);
}
return result;
@ -605,7 +605,7 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
int i;
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
/* Send the CMD9 or CMD10 */
@ -620,8 +620,8 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
for (i = 0; i < 8; i++)
{
response = SPI_SNDBYTE(spi, 0xff);
fvdbg("%d. SPI sndbyte returned %02x\n", i, response);
response = SPI_SEND(spi, 0xff);
fvdbg("%d. SPI send returned %02x\n", i, response);
/* If a read operation fails and the card cannot provide the requested
* data, it will send a data error token instead. The 4 least
@ -637,13 +637,13 @@ static int mmcsd_getcardinfo(FAR struct mmcsd_slot_s *slot, ubyte *buffer,
{
for (i = 0; i < 16; ++i)
{
*buffer++ = SPI_SNDBYTE(spi, 0xff);
*buffer++ = SPI_SEND(spi, 0xff);
}
/* CRC receive */
(void)SPI_SNDBYTE(spi, 0xff);
(void)SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
SPI_SEND(spi, 0xff);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
return OK;
}
@ -791,7 +791,7 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
mmcsd_semtake(&slot->sem);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
(void)SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
/* Send CMD17: Reads a block of the size selected by the SET_BLOCKLEN
* command and verify that good R1 status is returned
@ -810,8 +810,8 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
{
/* Synchronize */
response = SPI_SNDBYTE(spi, 0xff);
fvdbg("(%d) SPI sndbyte returned %02x\n", i, response);
response = SPI_SEND(spi, 0xff);
fvdbg("(%d) SPI send returned %02x\n", i, response);
/* If a read operation fails and the card cannot provide the requested
* data, it will send a data error token instead. The 4 least
@ -831,8 +831,8 @@ static ssize_t mmcsd_read(FAR struct inode *inode, unsigned char *buffer,
/* Receive and ignore the two CRC bytes */
(void)SPI_SNDBYTE(spi, 0xff);
(void)SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
SPI_SEND(spi, 0xff);
/* On success, return the number of sectors transfer */
@ -933,7 +933,7 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
mmcsd_semtake(&slot->sem);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
(void)SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
/* Send CMD24 (WRITE_BLOCK) and verify that good R1 status is returned */
@ -952,20 +952,20 @@ static ssize_t mmcsd_write(FAR struct inode *inode, const unsigned char *buffer,
* 3. Followed by the block of data
*/
(void)SPI_SNDBYTE(spi, 0xff);
(void)SPI_SNDBYTE(spi, MMCSD_SPIDT_STARTBLKSNGL);
SPI_SEND(spi, 0xff);
SPI_SEND(spi, MMCSD_SPIDT_STARTBLKSNGL);
(void)SPI_SNDBLOCK(spi, buffer, nbytes);
/* Add the bogus CRC. By default, the SPI interface is initialized in
* non-protected mode. However, we still have to send bogus CRC values
*/
(void)SPI_SNDBYTE(spi, 0xff);
(void)SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
SPI_SEND(spi, 0xff);
/* Now get the data response */
response = SPI_SNDBYTE(spi, 0xff);
response = SPI_SEND(spi, 0xff);
if ((response & MMCSD_SPIDR_MASK) != MMCSD_SPIDR_ACCEPTED)
{
fdbg("Bad data response: %02x\n", response);
@ -1145,7 +1145,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
for (j = 10; j; j--)
{
SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
}
/* Send CMD0 (GO_TO_IDLE) to put MMC/SD in IDLE/SPI mode */
@ -1178,13 +1178,13 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
{
fvdbg("%d. Send CMD55\n", i);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
result = mmcsd_sendcmd(slot, &g_cmd55, 0);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
fvdbg("%d. Send ACMD41\n", i);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
result = mmcsd_sendcmd(slot, &g_acmd41, 0);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
@ -1199,7 +1199,7 @@ static int mmcsd_mediainitialize(FAR struct mmcsd_slot_s *slot)
{
fvdbg("%d. Send CMD1\n", i);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);
SPI_SNDBYTE(spi, 0xff);
SPI_SEND(spi, 0xff);
result = mmcsd_sendcmd(slot, &g_cmd1, 0);
SPI_SELECT(spi, SPIDEV_MMCSD, FALSE);

View File

@ -130,21 +130,22 @@
#define SPI_STATUS_WRPROTECTED 0x02 /* Bit 1=1: MMC/SD card write protected */
/****************************************************************************
* Name: SPI_SNDBYTE
* Name: SPI_SEND
*
* Description:
* Send one byte on SPI. Required.
* Exchange one word on SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* ch - The byte to send
* wd - The word to send. the size of the data is determined by the
* number of bits selected for the SPI interface.
*
* Returned Value:
* None
* Received value
*
****************************************************************************/
#define SPI_SNDBYTE(d,ch) ((d)->ops->sndbyte(d,ch))
#define SPI_SEND(d,wd) ((d)->ops->send(d,(uint16)wd))
/****************************************************************************
* Name: SPI_SNDBLOCK
@ -153,9 +154,12 @@
* Send a block of data on SPI. Required.
*
* Input Parameters:
* dev - Device-specific state data
* 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
* buflen - 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
*
* Returned Value:
* None
@ -173,7 +177,10 @@
* 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
* buflen - 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
*
* Returned Value:
* None
@ -241,9 +248,9 @@ struct spi_ops_s
uint32 (*setfrequency)(FAR struct spi_dev_s *dev, uint32 frequency);
void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
ubyte (*status)(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
ubyte (*sndbyte)(FAR struct spi_dev_s *dev, ubyte ch);
void (*sndblock)(FAR struct spi_dev_s *dev, FAR const ubyte *buffer, size_t buflen);
void (*recvblock)(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t buflen);
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);
int (*registercallback)(FAR struct spi_dev_s *dev, mediachange_t callback, void *arg);
};