spi: change spi_send() interface to support of 32-bit word transfer

Signed-off-by: Petro Karashchenko <petro.karashchenko@gmail.com>
This commit is contained in:
Petro Karashchenko
2020-03-09 01:26:19 +02:00
committed by patacongo
parent 29be471f58
commit 3fa6baec98
47 changed files with 2154 additions and 1673 deletions
+2 -2
View File
@@ -1751,7 +1751,7 @@ The specific environmental definitions are unique for each board but should incl
The definitions in that header file provide the common interface between NuttX and the architecture-specific implementation in <code>arch/</code>. The definitions in that header file provide the common interface between NuttX and the architecture-specific implementation in <code>arch/</code>.
</p> </p>
<blockquote><small> <blockquote><small>
<code>up_</code> is supposed to stand for microprocessor; the <code>u</code> is like the Greek letter micron: <i>µ</i>. So it would be <code>µP</code> which is a common shortening of the word microprocessor. I don't like that name very much. I wish I would have used a more obvious prefix like <code>arch_</code> instead -- then I would not have to answer this question so often. <code>up_</code> is supposed to stand for microprocessor; the <code>u</code> is like the Greek letter micron: <i>ľ</i>. So it would be <code>ľP</code> which is a common shortening of the word microprocessor. I don't like that name very much. I wish I would have used a more obvious prefix like <code>arch_</code> instead -- then I would not have to answer this question so often.
</small></blockquote> </small></blockquote>
</li> </li>
<li> <li>
@@ -5865,7 +5865,7 @@ int kbd_decode(FAR struct lib_instream_s *stream, FAR struct kbd_getstate_s *sta
<code>void setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);</code><br> <code>void setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);</code><br>
<code>void setbits(FAR struct spi_dev_s *dev, int nbits);</code><br> <code>void setbits(FAR struct spi_dev_s *dev, int nbits);</code><br>
<code>uint8_t status(FAR struct spi_dev_s *dev, uint32_t devid);</code><br> <code>uint8_t status(FAR struct spi_dev_s *dev, uint32_t devid);</code><br>
<code>uint16_t send(FAR struct spi_dev_s *dev, uint16_t wd);</code><br> <code>uint32_t send(FAR struct spi_dev_s *dev, uint32_t wd);</code><br>
<code>void exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords);</code><br> <code>void exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords);</code><br>
<p><code>int registercallback(FAR struct spi_dev_s *dev, mediachange_t callback, void *arg);</code></p> <p><code>int registercallback(FAR struct spi_dev_s *dev, mediachange_t callback, void *arg);</code></p>
</ul> </ul>
+5 -4
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arm/arm/src/armv7-m/up_ramvec_initialize.c * arch/arm/src/armv7-m/up_ramvec_initialize.c
* *
* Copyright (C) 2013 Gregory Nutt. All rights reserved. * Copyright (C) 2013 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
@@ -81,14 +81,15 @@
#endif #endif
/* Alignment ****************************************************************/ /* Alignment ****************************************************************/
/* Per the ARMv7M Architecture reference manual, the NVIC vector table /* Per the ARMv7M Architecture reference manual, the NVIC vector table
* requires 7-bit address alignment (i.e, bits 0-6 of the address of the * requires 7-bit address alignment (i.e, bits 0-6 of the address of the
* vector table must be zero). In this case alignment to a 128 byte address * vector table must be zero). In this case alignment to a 128 byte address
* boundary is sufficient. * boundary is sufficient.
* *
* Some parts, such as the LPC17xx/LPC40xx family, require alignment to a 256 byte * Some parts, such as the LPC17xx/LPC40xx family, require alignment to a 256
* address boundary. Any other unusual alignment requirements for the vector * byte address boundary. Any other unusual alignment requirements for the
* can be specified for a given architecture be redefining * vector can be specified for a given architecture be redefining
* NVIC_VECTAB_TBLOFF_MASK in the chip-specific chip.h header file for the * NVIC_VECTAB_TBLOFF_MASK in the chip-specific chip.h header file for the
* appropriate mask. * appropriate mask.
*/ */
+18 -17
View File
@@ -117,8 +117,8 @@ struct cxd56_spidev_s
static inline uint32_t spi_getreg(FAR struct cxd56_spidev_s *priv, static inline uint32_t spi_getreg(FAR struct cxd56_spidev_s *priv,
uint8_t offset); uint8_t offset);
static inline void spi_putreg(FAR struct cxd56_spidev_s *priv, uint8_t offset, static inline void spi_putreg(FAR struct cxd56_spidev_s *priv,
uint32_t value); uint8_t offset, uint32_t value);
/* DMA support */ /* DMA support */
@@ -136,8 +136,8 @@ static void spi_dmatxsetup(FAR struct cxd56_spidev_s *priv,
static void spi_dmarxsetup(FAR struct cxd56_spidev_s *priv, static void spi_dmarxsetup(FAR struct cxd56_spidev_s *priv,
FAR const void *rxbuffer, size_t nwords); FAR const void *rxbuffer, size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_dmasndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, static void spi_dmasndblock(FAR struct spi_dev_s *dev,
size_t nwords); FAR const void *buffer, size_t nwords);
#endif #endif
#endif #endif
@@ -148,7 +148,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency); uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void __unused spi_exchange(FAR struct spi_dev_s *dev, static void __unused spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR const void *txbuffer,
FAR void *rxbuffer, FAR void *rxbuffer,
@@ -389,8 +389,8 @@ static inline uint32_t spi_getreg(FAR struct cxd56_spidev_s *priv,
* *
****************************************************************************/ ****************************************************************************/
static inline void spi_putreg(FAR struct cxd56_spidev_s *priv, uint8_t offset, static inline void spi_putreg(FAR struct cxd56_spidev_s *priv,
uint32_t value) uint8_t offset, uint32_t value)
{ {
putreg32(value, priv->spibase + (uint32_t)offset); putreg32(value, priv->spibase + (uint32_t)offset);
} }
@@ -654,7 +654,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev; FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev;
register uint32_t regval; register uint32_t regval;
@@ -678,7 +678,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Write the byte to the TX FIFO */ /* Write the byte to the TX FIFO */
spi_putreg(priv, CXD56_SPI_DR_OFFSET, (uint32_t)wd); spi_putreg(priv, CXD56_SPI_DR_OFFSET, wd);
/* Wait for the RX FIFO not empty */ /* Wait for the RX FIFO not empty */
@@ -700,7 +700,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
cxd56_spi_clock_gate_enable(priv->port); cxd56_spi_clock_gate_enable(priv->port);
return (uint16_t)regval; return regval;
} }
/**************************************************************************** /****************************************************************************
@@ -724,8 +724,9 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* *
****************************************************************************/ ****************************************************************************/
static void spi_do_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_do_exchange(FAR struct spi_dev_s *dev,
FAR void *rxbuffer, size_t nwords) FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords)
{ {
FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev; FAR struct cxd56_spidev_s *priv = (FAR struct cxd56_spidev_s *)dev;
uint32_t regval = 0; uint32_t regval = 0;
@@ -793,7 +794,8 @@ static void spi_do_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
rxpending++; rxpending++;
} }
/* Now, read the RX data from the RX FIFO while the RX FIFO is not empty /* Now, read the RX data from the RX FIFO
* while the RX FIFO is not empty
*/ */
spiinfo("RX: rxpending: %d\n", rxpending); spiinfo("RX: rxpending: %d\n", rxpending);
@@ -1495,8 +1497,8 @@ static void spi_dmaexchange(FAR struct spi_dev_s *dev,
* *
****************************************************************************/ ****************************************************************************/
static void spi_dmasndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, static void spi_dmasndblock(FAR struct spi_dev_s *dev,
size_t nwords) FAR const void *buffer, size_t nwords)
{ {
spi_dmaexchange(dev, buffer, NULL, nwords); spi_dmaexchange(dev, buffer, NULL, nwords);
} }
@@ -1510,8 +1512,7 @@ static void spi_dmasndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
****************************************************************************/ ****************************************************************************/
static void spi_dmarecvblock(FAR struct spi_dev_s *dev, static void spi_dmarecvblock(FAR struct spi_dev_s *dev,
FAR const void *buffer, FAR const void *buffer, size_t nwords)
size_t nwords)
{ {
spi_dmaexchange(dev, NULL, buffer, nwords); spi_dmaexchange(dev, NULL, buffer, nwords);
} }
+46 -30
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arm/arm/src/efm32/efm32_spi.c * arch/arm/src/efm32/efm32_spi.c
* *
* Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2014, 2016-2017 Gregory Nutt. All rights reserved.
* Copyright (C) 2014 Bouteville Pierre-Noel. All rights reserved. * Copyright (C) 2014 Bouteville Pierre-Noel. All rights reserved.
@@ -73,7 +73,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* SPI DMA */ /* SPI DMA */
#ifndef CONFIG_EFM32_SPI_DMA_TIMEO_NSEC #ifndef CONFIG_EFM32_SPI_DMA_TIMEO_NSEC
@@ -145,6 +147,7 @@ struct efm32_spidev_s
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
/* Low level SPI access */ /* Low level SPI access */
static uint32_t spi_getreg(const struct efm32_spiconfig_s *config, static uint32_t spi_getreg(const struct efm32_spiconfig_s *config,
@@ -194,7 +197,7 @@ static uint8_t spi_status(struct spi_dev_s *dev, uint32_t devid);
static int spi_cmddata(struct spi_dev_s *dev, uint32_t devid, static int spi_cmddata(struct spi_dev_s *dev, uint32_t devid,
bool cmd); bool cmd);
#endif #endif
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
void *rxbuffer, size_t nwords); void *rxbuffer, size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
@@ -372,7 +375,8 @@ static void spi_rxflush(const struct efm32_spiconfig_s *config)
{ {
/* Loop while data is available */ /* Loop while data is available */
while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_RXDATAV) != 0) while ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) &
USART_STATUS_RXDATAV) != 0)
{ {
/* Read and discard the data */ /* Read and discard the data */
@@ -409,7 +413,8 @@ static void spi_dma_timeout(int argc, uint32_t arg1, ...)
/* Mark DMA timeout error and wakeup form RX and TX waiters */ /* Mark DMA timeout error and wakeup form RX and TX waiters */
DEBUGASSERT(priv->rxresult == EINPROGRESS || priv->txresult == EINPROGRESS); DEBUGASSERT(priv->rxresult == EINPROGRESS ||
priv->txresult == EINPROGRESS);
if (priv->rxresult == EINPROGRESS) if (priv->rxresult == EINPROGRESS)
{ {
priv->rxresult = ETIMEDOUT; priv->rxresult = ETIMEDOUT;
@@ -815,7 +820,9 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
* *
* CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1) * CLKDIV = 256 * (fHFPERCLK/(2 * br) - 1)
* or * or
* CLKDIV = (256 * fHFPERCLK)/(2 * br) - 256 = (128 * fHFPERCLK)/br - 256 * CLKDIV = (256 * fHFPERCLK)/(2 * br) - 256
* or
* CLKDIV = (128 * fHFPERCLK)/br - 256
* *
* The basic problem with integer division in the above formula is that * The basic problem with integer division in the above formula is that
* the dividend (128 * fHFPERCLK) may become higher than max 32 bit * the dividend (128 * fHFPERCLK) may become higher than max 32 bit
@@ -907,19 +914,23 @@ static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode)
switch (mode) switch (mode)
{ {
case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */ case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
setting = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLELEADING; setting = USART_CTRL_CLKPOL_IDLELOW |
USART_CTRL_CLKPHA_SAMPLELEADING;
break; break;
case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */ case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
setting = USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLETRAILING; setting = USART_CTRL_CLKPOL_IDLELOW |
USART_CTRL_CLKPHA_SAMPLETRAILING;
break; break;
case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */ case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
setting = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLELEADING; setting = USART_CTRL_CLKPOL_IDLEHIGH |
USART_CTRL_CLKPHA_SAMPLELEADING;
break; break;
case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */ case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
setting = USART_CTRL_CLKPOL_IDLEHIGH | USART_CTRL_CLKPHA_SAMPLETRAILING; setting = USART_CTRL_CLKPOL_IDLEHIGH |
USART_CTRL_CLKPHA_SAMPLETRAILING;
break; break;
default: default:
@@ -1058,7 +1069,8 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_SPI_HWFEATURES #ifdef CONFIG_SPI_HWFEATURES
static int spi_hwfeatures(FAR struct spi_dev_s *dev, spi_hwfeatures_t features) static int spi_hwfeatures(FAR struct spi_dev_s *dev,
spi_hwfeatures_t features)
{ {
#ifdef CONFIG_SPI_BITORDER #ifdef CONFIG_SPI_BITORDER
struct efm32_spidev_s *priv = (struct efm32_spidev_s *)dev; struct efm32_spidev_s *priv = (struct efm32_spidev_s *)dev;
@@ -1194,11 +1206,11 @@ static int spi_cmddata(struct spi_dev_s *dev, uint32_t devid,
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
struct efm32_spidev_s *priv = (struct efm32_spidev_s *)dev; struct efm32_spidev_s *priv = (struct efm32_spidev_s *)dev;
const struct efm32_spiconfig_s *config; const struct efm32_spiconfig_s *config;
uint16_t ret; uint32_t ret;
DEBUGASSERT(priv && priv->config); DEBUGASSERT(priv && priv->config);
config = priv->config; config = priv->config;
@@ -1213,12 +1225,12 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
/* Write the data */ /* Write the data */
spi_putreg(config, EFM32_USART_TXDATA_OFFSET, (uint32_t)wd); spi_putreg(config, EFM32_USART_TXDATA_OFFSET, wd);
/* Wait for receive data to be available */ /* Wait for receive data to be available */
spi_wait_status(config, _USART_STATUS_RXDATAV_MASK, USART_STATUS_RXDATAV); spi_wait_status(config, _USART_STATUS_RXDATAV_MASK, USART_STATUS_RXDATAV);
ret = (uint16_t)spi_getreg(config, EFM32_USART_RXDATA_OFFSET); ret = spi_getreg(config, EFM32_USART_RXDATA_OFFSET);
spiinfo("Sent: %04x Return: %04x \n", wd, ret); spiinfo("Sent: %04x Return: %04x \n", wd, ret);
return ret; return ret;
@@ -1282,10 +1294,11 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
while (unrecvd > 0) while (unrecvd > 0)
{ {
/* REVISIT: Could this cause RX data overruns??? */ /* REVISIT: Could this cause RX data overruns??? */
/* Send data if there is space in the TX buffer. */ /* Send data if there is space in the TX buffer. */
if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_TXBL) != 0 && if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) &
unsent > 0) USART_STATUS_TXBL) != 0 && unsent > 0)
{ {
/* Get the next word to write. Is there a source buffer? */ /* Get the next word to write. Is there a source buffer? */
@@ -1306,8 +1319,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
/* Receive data if there is data available */ /* Receive data if there is data available */
if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_RXDATAV) != 0 && if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) &
unrecvd > 0) USART_STATUS_RXDATAV) != 0 && unrecvd > 0)
{ {
/* Receive the data */ /* Receive the data */
@@ -1336,10 +1349,11 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
while (unrecvd > 0) while (unrecvd > 0)
{ {
/* REVISIT: Could this cause RX data overruns??? */ /* REVISIT: Could this cause RX data overruns??? */
/* Send data if there is space in the TX buffer. */ /* Send data if there is space in the TX buffer. */
if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_TXBL) != 0 && if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) &
unsent > 0) USART_STATUS_TXBL) != 0 && unsent > 0)
{ {
/* Get the next word to write. Is there a source buffer? */ /* Get the next word to write. Is there a source buffer? */
@@ -1360,8 +1374,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
/* Receive data if there is data available */ /* Receive data if there is data available */
if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) & USART_STATUS_RXDATAV) != 0 && if ((spi_getreg(config, EFM32_USART_STATUS_OFFSET) &
unrecvd > 0) USART_STATUS_RXDATAV) != 0 && unrecvd > 0)
{ {
/* Receive the data */ /* Receive the data */
@@ -1451,7 +1465,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
* when both RX and TX transfers complete. * when both RX and TX transfers complete.
*/ */
ret = wd_start(priv->wdog, (int)ticks, spi_dma_timeout, 1, (uint32_t)priv); ret = wd_start(priv->wdog, (int)ticks, spi_dma_timeout, 1,
(uint32_t)priv);
if (ret < 0) if (ret < 0)
{ {
spierr("ERROR: Failed to start timeout: %d\n", ret); spierr("ERROR: Failed to start timeout: %d\n", ret);
@@ -1558,8 +1573,8 @@ static int spi_portinitialize(struct efm32_spidev_s *priv)
/* Set bits for synchronous mode */ /* Set bits for synchronous mode */
regval = _USART_CTRL_RESETVALUE | USART_CTRL_SYNC | USART_CTRL_CLKPOL_IDLELOW | regval = _USART_CTRL_RESETVALUE | USART_CTRL_SYNC |
USART_CTRL_CLKPHA_SAMPLELEADING; USART_CTRL_CLKPOL_IDLELOW | USART_CTRL_CLKPHA_SAMPLELEADING;
/* MSB First, 8 bits */ /* MSB First, 8 bits */
@@ -1592,7 +1607,7 @@ static int spi_portinitialize(struct efm32_spidev_s *priv)
priv->rxdmach = efm32_dmachannel(); priv->rxdmach = efm32_dmachannel();
if (!priv->rxdmach) if (!priv->rxdmach)
{ {
spierr("ERROR: Failed to allocate the RX DMA channel for SPI port: %d\n", spierr("ERROR: Failed to allocate RX DMA channel for SPI port: %d\n",
port); port);
goto errout; goto errout;
} }
@@ -1600,7 +1615,7 @@ static int spi_portinitialize(struct efm32_spidev_s *priv)
priv->txdmach = efm32_dmachannel(); priv->txdmach = efm32_dmachannel();
if (!priv->txdmach) if (!priv->txdmach)
{ {
spierr("ERROR: Failed to allocate the TX DMA channel for SPI port: %d\n", spierr("ERROR: Failed to allocate TX DMA channel for SPI port: %d\n",
port); port);
goto errout_with_rxdmach; goto errout_with_rxdmach;
} }
@@ -1623,13 +1638,14 @@ static int spi_portinitialize(struct efm32_spidev_s *priv)
* priority inheritance enabled. * priority inheritance enabled.
*/ */
nxsem_setprotocol(&priv->rxdmasem, SEM_PRIO_NONE); nxsem_setprotocol(&priv->rxdmasem, SEM_PRIO_NONE);
nxsem_setprotocol(&priv->txdmasem, SEM_PRIO_NONE); nxsem_setprotocol(&priv->txdmasem, SEM_PRIO_NONE);
#endif #endif
/* Enable SPI */ /* Enable SPI */
spi_putreg(config, EFM32_USART_CMD_OFFSET, USART_CMD_RXEN | USART_CMD_TXEN); spi_putreg(config, EFM32_USART_CMD_OFFSET,
USART_CMD_RXEN | USART_CMD_TXEN);
return OK; return OK;
#ifdef CONFIG_EFM32_SPI_DMA #ifdef CONFIG_EFM32_SPI_DMA
+7 -7
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arm/arm/src/efm32/efm32_spi.h * arch/arm/src/efm32/efm32_spi.h
* *
* Copyright (C) 2009-2013 Bouteville Pierre-Noel. All rights reserved. * Copyright (C) 2009-2013 Bouteville Pierre-Noel. All rights reserved.
* Author: Bouteville Pierre-Noel <pnb990@gmail.com> * Author: Bouteville Pierre-Noel <pnb990@gmail.com>
@@ -77,8 +77,8 @@ struct spi_dev_s *efm32_spibus_initialize(int port);
* efm32_spi[n]_cmddata must be provided by board-specific logic. These * efm32_spi[n]_cmddata must be provided by board-specific logic. These
* are implementations of the select, status, and cmddata methods of the * are implementations of the select, status, and cmddata methods of the
* SPI interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h). * SPI interface defined by struct spi_ops_s (see include/nuttx/spi/spi.h).
* All other methods (including efm32_spibus_initialize()) are provided by common * All other methods (including efm32_spibus_initialize()) are provided by
* EFM32 logic. To use this common SPI logic on your board: * common EFM32 logic. To use this common SPI logic on your board:
* *
* 1. Provide logic in efm32_boardinitialize() to configure SPI chip select * 1. Provide logic in efm32_boardinitialize() to configure SPI chip select
* pins. * pins.
@@ -90,10 +90,10 @@ struct spi_dev_s *efm32_spibus_initialize(int port);
* then provide efm32_spi[n]_cmddata() functions in your board-specific * then provide efm32_spi[n]_cmddata() functions in your board-specific
* logic. These functions will perform cmd/data selection operations * logic. These functions will perform cmd/data selection operations
* using GPIOs in the way your board is configured. * using GPIOs in the way your board is configured.
* 4. Add a calls to efm32_spibus_initialize() in your low level application * 4. Add a calls to efm32_spibus_initialize() in your low level
* initialization logic * application initialization logic
* 5. The handle returned by efm32_spibus_initialize() may then be used to bind * 5. The handle returned by efm32_spibus_initialize() may then be used to
* the SPI driver to higher level logic (e.g., calling * bind the SPI driver to higher level logic (e.g., calling
* mmcsd_spislotinitialize(), for example, will bind the SPI driver to * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
* the SPI MMC/SD driver). * the SPI MMC/SD driver).
* *
+59 -40
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/imx1/imx_spi.c * arch/arm/src/imx1/imx_spi.c
* *
* Copyright (C) 2009-2010, 2013, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2009-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -144,8 +144,10 @@ struct imx_spidev_s
/* SPI register access */ /* SPI register access */
static inline uint32_t spi_getreg(struct imx_spidev_s *priv, unsigned int offset); static inline uint32_t spi_getreg(struct imx_spidev_s *priv,
static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32_t value); unsigned int offset);
static inline void spi_putreg(struct imx_spidev_s *priv,
unsigned int offset, uint32_t value);
/* SPI data transfer */ /* SPI data transfer */
@@ -164,22 +166,26 @@ static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer,
#ifndef CONFIG_SPI_POLLWAIT #ifndef CONFIG_SPI_POLLWAIT
static inline struct imx_spidev_s *spi_mapirq(int irq); static inline struct imx_spidev_s *spi_mapirq(int irq);
static int spi_interrupt(int irq, void *context, FAR void *arg, FAR void *arg); static int spi_interrupt(int irq, void *context,
FAR void *arg, FAR void *arg);
#endif #endif
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords); FAR void *rxbuffer, size_t nwords);
#else #else
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
#endif #endif
/**************************************************************************** /****************************************************************************
@@ -258,7 +264,8 @@ static struct imx_spidev_s g_spidev[] =
* *
****************************************************************************/ ****************************************************************************/
static inline uint32_t spi_getreg(struct imx_spidev_s *priv, unsigned int offset) static inline uint32_t spi_getreg(struct imx_spidev_s *priv,
unsigned int offset)
{ {
return getreg32(priv->base + offset); return getreg32(priv->base + offset);
} }
@@ -279,7 +286,8 @@ static inline uint32_t spi_getreg(struct imx_spidev_s *priv, unsigned int offset
* *
****************************************************************************/ ****************************************************************************/
static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32_t value) static inline void spi_putreg(struct imx_spidev_s *priv,
unsigned int offset, uint32_t value)
{ {
putreg32(value, priv->base + offset); putreg32(value, priv->base + offset);
} }
@@ -288,10 +296,10 @@ static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, ui
* Name: spi_txnull, spi_txuint16, and spi_txuint8 * Name: spi_txnull, spi_txuint16, and spi_txuint8
* *
* Description: * Description:
* Transfer all ones, a uint8_t, or uint16_t to Tx FIFO and update the txbuffer * Transfer all ones, a uint8_t, or uint16_t to Tx FIFO and update
* pointer appropriately. The selected function dependes on (1) if there * the txbuffer pointer appropriately. The selected function depends
* is a source txbuffer provided, and (2) if the number of bits per * on (1) if there is a source txbuffer provided, and (2) if the
* word is <=8 or >8. * number of bits per word is <=8 or >8.
* *
* Input Parameters: * Input Parameters:
* priv - Device-specific state data * priv - Device-specific state data
@@ -407,6 +415,7 @@ static int spi_performtx(struct imx_spidev_s *priv)
spi_putreg(priv, CSPI_INTCS_OFFSET, regval); spi_putreg(priv, CSPI_INTCS_OFFSET, regval);
} }
} }
return ntxd; return ntxd;
} }
@@ -488,9 +497,9 @@ static void spi_startxfr(struct imx_spidev_s *priv, int ntxd)
* txbuffer - The buffer of data to send to the device (may be NULL). * 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). * rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface * nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of uint8_t's; * uses <= 8 bits per word, then this is the number of
* if the interface uses >8 bits per word, then this is the * uint8_t's; if the interface uses >8 bits per word, then this
* number of uint16_t's * is the number of uint16_t's
* *
* Returned Value: * Returned Value:
* 0: success, <0:Negated error number on failure * 0: success, <0:Negated error number on failure
@@ -637,9 +646,9 @@ static inline struct imx_spidev_s *spi_mapirq(int irq)
* txbuffer - The buffer of data to send to the device (may be NULL). * 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). * rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface * nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of uint8_t's; * uses <= 8 bits per word, then this is the number of
* if the interface uses >8 bits per word, then this is the * uint8_t's; if the interface uses >8 bits per word, then this
* number of uint16_t's * is the number of uint16_t's
* *
* Returned Value: * Returned Value:
* 0: success, <0:Negated error number on failure * 0: success, <0:Negated error number on failure
@@ -647,7 +656,8 @@ static inline struct imx_spidev_s *spi_mapirq(int irq)
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_POLLWAIT #ifndef CONFIG_SPI_POLLWAIT
static int spi_interrupt(int irq, void *context, FAR void *arg, FAR void *arg) static int spi_interrupt(int irq, void *context,
FAR void *arg, FAR void *arg)
{ {
struct imx_spidev_s *priv = spi_mapirq(irq); struct imx_spidev_s *priv = spi_mapirq(irq);
int ntxd; int ntxd;
@@ -732,7 +742,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
uint32_t actual; uint32_t actual;
@@ -900,10 +911,10 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
uint16_t response = 0; uint32_t response = 0;
spi_transfer(priv, &wd, &response, 1); spi_transfer(priv, &wd, &response, 1);
return response; return response;
@@ -922,7 +933,8 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - the length of data that to be exchanged in units of words. * nwords - the length of data that to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -950,7 +962,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -958,7 +971,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) 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; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
spi_transfer(priv, buffer, NULL, nwords); spi_transfer(priv, buffer, NULL, nwords);
@@ -975,9 +989,10 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -985,7 +1000,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) 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; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
spi_transfer(priv, NULL, buffer, nwords); spi_transfer(priv, NULL, buffer, nwords);
@@ -1005,10 +1021,10 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw
* prior to calling this function. Specifically: GPIOs should have * prior to calling this function. Specifically: GPIOs should have
* been configured for output, and all chip selects disabled. * been configured for output, and all chip selects disabled.
* *
* One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select. However, * One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select.
* If multiple devices on on the bus, then multiple chip selects will be * However, If multiple devices on on the bus, then multiple chip selects
* required. Therefore, all GPIO chip management is deferred to board- * will be required. Therefore, all GPIO chip management is deferred
* specific logic. * to board-specific logic.
* *
* Input Parameters: * Input Parameters:
* Port number (for hardware that has multiple SPI interfaces) * Port number (for hardware that has multiple SPI interfaces)
@@ -1029,6 +1045,7 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
{ {
#ifdef CONFIG_IMX1_SPI1 #ifdef CONFIG_IMX1_SPI1
case 1: case 1:
/* Select SPI1 */ /* Select SPI1 */
priv = &g_spidev[SPI1_NDX]; priv = &g_spidev[SPI1_NDX];
@@ -1046,11 +1063,13 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
#ifdef CONFIG_IMX1_SPI2 #ifdef CONFIG_IMX1_SPI2
case 2: case 2:
/* Select SPI2 */ /* Select SPI2 */
priv = &g_spidev[SPI2_NDX]; priv = &g_spidev[SPI2_NDX];
/* Configure SPI2 GPIOs */ /* Configure SPI2 GPIOs */
/* SCLK: AIN of Port A, pin 0 -OR- AIN of Port D, pin 7 */ /* SCLK: AIN of Port A, pin 0 -OR- AIN of Port D, pin 7 */
#if 1 #if 1
@@ -1108,10 +1127,10 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
* signaling and, hence, should not have priority inheritance enabled. * signaling and, hence, should not have priority inheritance enabled.
*/ */
nxsem_init(&priv->waitsem, 0, 0); nxsem_init(&priv->waitsem, 0, 0);
nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE); nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);
#endif #endif
nxsem_init(&priv->exclsem, 0, 1); nxsem_init(&priv->exclsem, 0, 1);
/* Initialize control register: min frequency, ignore ready, master mode, mode=0, 8-bit */ /* Initialize control register: min frequency, ignore ready, master mode, mode=0, 8-bit */
+53 -38
View File
@@ -134,7 +134,7 @@
* Private Type Definitions * Private Type Definitions
****************************************************************************/ ****************************************************************************/
/* Per SPI callouts to board-specific logic */ /* Per SPI callouts to board-specific logic */
typedef CODE void (*imx_select_t)(FAR struct spi_dev_s *dev, typedef CODE void (*imx_select_t)(FAR struct spi_dev_s *dev,
uint32_t devid, bool selected); uint32_t devid, bool selected);
@@ -202,8 +202,10 @@ struct imx_spidev_s
/* SPI register access */ /* SPI register access */
static inline uint32_t spi_getreg(struct imx_spidev_s *priv, unsigned int offset); static inline uint32_t spi_getreg(struct imx_spidev_s *priv,
static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32_t value); unsigned int offset);
static inline void spi_putreg(struct imx_spidev_s *priv,
unsigned int offset, uint32_t value);
/* SPI data transfer */ /* SPI data transfer */
@@ -233,7 +235,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency); uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static uint8_t spi_status(FAR struct spi_dev_s *dev, uint32_t devid); static uint8_t spi_status(FAR struct spi_dev_s *dev, uint32_t devid);
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
static int spi_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, static int spi_cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
@@ -296,11 +298,11 @@ static struct imx_spidev_s g_spidev[] =
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
.cmddata = imx_spi1cmddata, .cmddata = imx_spi1cmddata,
#endif #endif
} },
#endif #endif
#ifdef CONFIG_IMX6_ECSPI2 #ifdef CONFIG_IMX6_ECSPI2
, { {
.ops = &g_spiops, .ops = &g_spiops,
.base = IMX_ECSPI2_VBASE, .base = IMX_ECSPI2_VBASE,
.spindx = SPI2_NDX, .spindx = SPI2_NDX,
@@ -312,11 +314,11 @@ static struct imx_spidev_s g_spidev[] =
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
.cmddata = imx_spi2cmddata, .cmddata = imx_spi2cmddata,
#endif #endif
} },
#endif #endif
#ifdef CONFIG_IMX6_ECSPI3 #ifdef CONFIG_IMX6_ECSPI3
, { {
.ops = &g_spiops, .ops = &g_spiops,
.base = IMX_ECSPI3_VBASE, .base = IMX_ECSPI3_VBASE,
.spindx = SPI3_NDX, .spindx = SPI3_NDX,
@@ -328,11 +330,11 @@ static struct imx_spidev_s g_spidev[] =
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
.cmddata = imx_spi3cmddata, .cmddata = imx_spi3cmddata,
#endif #endif
} },
#endif #endif
#ifdef CONFIG_IMX6_ECSPI4 #ifdef CONFIG_IMX6_ECSPI4
, { {
.ops = &g_spiops, .ops = &g_spiops,
.base = IMX_ECSPI4_VBASE, .base = IMX_ECSPI4_VBASE,
.spindx = SPI4_NDX, .spindx = SPI4_NDX,
@@ -344,11 +346,11 @@ static struct imx_spidev_s g_spidev[] =
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
.cmddata = imx_spi4cmddata, .cmddata = imx_spi4cmddata,
#endif #endif
} },
#endif #endif
#ifdef CONFIG_IMX6_ECSPI5 #ifdef CONFIG_IMX6_ECSPI5
, { {
.ops = &g_spiops, .ops = &g_spiops,
.base = IMX_ECSPI5_VBASE, .base = IMX_ECSPI5_VBASE,
.spindx = SPI5_NDX, .spindx = SPI5_NDX,
@@ -383,7 +385,8 @@ static struct imx_spidev_s g_spidev[] =
* *
****************************************************************************/ ****************************************************************************/
static inline uint32_t spi_getreg(struct imx_spidev_s *priv, unsigned int offset) static inline uint32_t spi_getreg(struct imx_spidev_s *priv,
unsigned int offset)
{ {
return getreg32(priv->base + offset); return getreg32(priv->base + offset);
} }
@@ -404,7 +407,8 @@ static inline uint32_t spi_getreg(struct imx_spidev_s *priv, unsigned int offset
* *
****************************************************************************/ ****************************************************************************/
static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, uint32_t value) static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset,
uint32_t value)
{ {
putreg32(value, priv->base + offset); putreg32(value, priv->base + offset);
} }
@@ -413,10 +417,10 @@ static inline void spi_putreg(struct imx_spidev_s *priv, unsigned int offset, ui
* Name: spi_txnull, spi_txuint16, and spi_txuint8 * Name: spi_txnull, spi_txuint16, and spi_txuint8
* *
* Description: * Description:
* Transfer all ones, a uint8_t, or uint16_t to Tx FIFO and update the txbuffer * Transfer all ones, a uint8_t, or uint16_t to Tx FIFO and update the
* pointer appropriately. The selected function dependes on (1) if there * txbuffer pointer appropriately. The selected function dependes on
* is a source txbuffer provided, and (2) if the number of bits per * (1) if there is a source txbuffer provided, and (2) if the number of
* word is <=8 or >8. * bits per word is <=8 or >8.
* *
* Input Parameters: * Input Parameters:
* priv - Device-specific state data * priv - Device-specific state data
@@ -532,6 +536,7 @@ static int spi_performtx(struct imx_spidev_s *priv)
spi_putreg(priv, ECSPI_INTREG_OFFSET, regval); spi_putreg(priv, ECSPI_INTREG_OFFSET, regval);
} }
} }
return ntxd; return ntxd;
} }
@@ -613,9 +618,9 @@ static void spi_startxfr(struct imx_spidev_s *priv, int ntxd)
* txbuffer - The buffer of data to send to the device (may be NULL). * 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). * rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface * nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of uint8_t's; * uses <= 8 bits per word, then this is the number of
* if the interface uses >8 bits per word, then this is the * uint8_t's; if the interface uses >8 bits per word, then this
* number of uint16_t's * is the number of uint16_t's
* *
* Returned Value: * Returned Value:
* 0: success, <0:Negated error number on failure * 0: success, <0:Negated error number on failure
@@ -845,7 +850,8 @@ static void spi_select(FAR struct spi_dev_s *dev, uint32_t devid,
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
uint32_t actual; uint32_t actual;
@@ -1013,10 +1019,10 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
uint16_t response = 0; uint32_t response = 0;
spi_transfer(priv, &wd, &response, 1); spi_transfer(priv, &wd, &response, 1);
return response; return response;
@@ -1107,7 +1113,8 @@ static int spi_cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
* nwords - the length of data that to be exchanged in units of words. * nwords - the length of data that to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1135,7 +1142,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1143,7 +1151,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) 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; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
spi_transfer(priv, buffer, NULL, nwords); spi_transfer(priv, buffer, NULL, nwords);
@@ -1160,9 +1169,10 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1170,7 +1180,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) 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; struct imx_spidev_s *priv = (struct imx_spidev_s *)dev;
spi_transfer(priv, NULL, buffer, nwords); spi_transfer(priv, NULL, buffer, nwords);
@@ -1190,10 +1201,10 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw
* prior to calling this function. Specifically: GPIOs should have * prior to calling this function. Specifically: GPIOs should have
* been configured for output, and all chip selects disabled. * been configured for output, and all chip selects disabled.
* *
* One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select. However, * One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select.
* If multiple devices on on the bus, then multiple chip selects will be * However, If multiple devices on on the bus, then multiple chip selects
* required. Theregore, all GPIO chip management is deferred to board- * will be required. Therefore, all GPIO chip management is deferred to
* specific logic. * board-specific logic.
* *
* Input Parameters: * Input Parameters:
* Port number (for hardware that has multiple SPI interfaces) * Port number (for hardware that has multiple SPI interfaces)
@@ -1214,6 +1225,7 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
{ {
#ifdef CONFIG_IMX6_ECSPI1 #ifdef CONFIG_IMX6_ECSPI1
case 1: case 1:
/* Select SPI1 */ /* Select SPI1 */
priv = &g_spidev[SPI1_NDX]; priv = &g_spidev[SPI1_NDX];
@@ -1231,11 +1243,13 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
#ifdef CONFIG_IMX6_ECSPI2 #ifdef CONFIG_IMX6_ECSPI2
case 2: case 2:
/* Select SPI2 */ /* Select SPI2 */
priv = &g_spidev[SPI2_NDX]; priv = &g_spidev[SPI2_NDX];
/* Configure SPI2 GPIOs */ /* Configure SPI2 GPIOs */
/* SCLK: AIN of Port A, pin 0 -OR- AIN of Port D, pin 7 */ /* SCLK: AIN of Port A, pin 0 -OR- AIN of Port D, pin 7 */
#if 1 #if 1
@@ -1286,6 +1300,7 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
} }
/* Initialize the state structure */ /* Initialize the state structure */
/* Initialize Semaphores */ /* Initialize Semaphores */
#ifndef CONFIG_SPI_POLLWAIT #ifndef CONFIG_SPI_POLLWAIT
@@ -1294,10 +1309,10 @@ FAR struct spi_dev_s *imx_spibus_initialize(int port)
* signaling and, hence, should not have priority inheritance enabled. * signaling and, hence, should not have priority inheritance enabled.
*/ */
nxsem_init(&priv->waitsem, 0, 0); nxsem_init(&priv->waitsem, 0, 0);
nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE); nxsem_setprotocol(&priv->waitsem, SEM_PRIO_NONE);
#endif #endif
nxsem_init(&priv->exclsem, 0, 1); nxsem_init(&priv->exclsem, 0, 1);
/* Initialize control register: min frequency, ignore ready, master mode, mode=0, 8-bit */ /* Initialize control register: min frequency, ignore ready, master mode, mode=0, 8-bit */
+13 -13
View File
@@ -1,5 +1,5 @@
/***************************************************************************** /*****************************************************************************
* arm/arm/src/imxrt/imxrt_lpspi.c * arch/arm/src/imxrt/imxrt_lpspi.c
* *
* Copyright (C) 2018 Gregory Nutt. All rights reserved. * Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Authors: Teodora Kireva * Authors: Teodora Kireva
@@ -151,7 +151,7 @@ static inline uint32_t imxrt_lpspi_getreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset); uint8_t offset);
static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv, static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
uint8_t offset, uint32_t value); uint8_t offset, uint32_t value);
static inline uint16_t imxrt_lpspi_readword( static inline uint32_t imxrt_lpspi_readword(
FAR struct imxrt_lpspidev_s *priv); FAR struct imxrt_lpspidev_s *priv);
static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv, static inline void imxrt_lpspi_writeword(FAR struct imxrt_lpspidev_s *priv,
uint16_t byte); uint16_t byte);
@@ -177,7 +177,7 @@ static void imxrt_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits);
static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s *dev, static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s *dev,
imxrt_lpspi_hwfeatures_t features); imxrt_lpspi_hwfeatures_t features);
#endif #endif
static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void imxrt_lpspi_exchange(FAR struct spi_dev_s *dev, static void imxrt_lpspi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords); size_t nwords);
@@ -482,7 +482,7 @@ static inline void imxrt_lpspi_putreg32(FAR struct imxrt_lpspidev_s *priv,
* *
*****************************************************************************/ *****************************************************************************/
static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv) static inline uint32_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv)
{ {
/* Wait until the receive buffer is not empty */ /* Wait until the receive buffer is not empty */
@@ -491,7 +491,7 @@ static inline uint16_t imxrt_lpspi_readword(FAR struct imxrt_lpspidev_s *priv)
/* Then return the received byte */ /* Then return the received byte */
return (uint16_t) imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_RDR_OFFSET); return imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_RDR_OFFSET);
} }
/***************************************************************************** /*****************************************************************************
@@ -1233,15 +1233,15 @@ static int imxrt_lpspi_hwfeatures(FAR struct spi_dev_s *dev,
* *
*****************************************************************************/ *****************************************************************************/
static uint16_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t imxrt_lpspi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)dev; FAR struct imxrt_lpspidev_s *priv = (FAR struct imxrt_lpspidev_s *)dev;
uint32_t regval; uint32_t regval;
uint16_t ret; uint32_t ret;
DEBUGASSERT(priv && priv->spibase); DEBUGASSERT(priv && priv->spibase);
imxrt_lpspi_writeword(priv, (uint32_t) wd); imxrt_lpspi_writeword(priv, wd);
while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) != while ((imxrt_lpspi_getreg32(priv, IMXRT_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) !=
LPSPI_SR_RDF); LPSPI_SR_RDF);
@@ -1322,7 +1322,7 @@ static void imxrt_lpspi_exchange_nodma(FAR struct spi_dev_s *dev,
/* Exchange one word */ /* Exchange one word */
word = imxrt_lpspi_send(dev, word); word = (uint16_t) imxrt_lpspi_send(dev, (uint32_t) word);
/* Is there a buffer to receive the return value? */ /* Is there a buffer to receive the return value? */
@@ -1355,7 +1355,7 @@ static void imxrt_lpspi_exchange_nodma(FAR struct spi_dev_s *dev,
/* Exchange one word */ /* Exchange one word */
word = (uint8_t) imxrt_lpspi_send(dev, (uint16_t) word); word = (uint8_t) imxrt_lpspi_send(dev, (uint32_t) word);
/* Is there a buffer to receive the return value? */ /* Is there a buffer to receive the return value? */
@@ -1408,9 +1408,9 @@ static void imxrt_lpspi_sndblock(FAR struct spi_dev_s *dev,
* rxbuffer - A pointer to the buffer in which to receive data * rxbuffer - A pointer to the buffer in which to receive data
* nwords - the length of data that can be received in the buffer in * nwords - the length of data that can be received in the buffer in
* number of words. The wordsize is determined by the number of * number of words. The wordsize is determined by the number of
* bits-per-word selected for the SPI interface. If * bits-per-word selected for the SPI interface. If nbits <= 8,
* nbits <= 8, the data is packed into uint8_t's; * the data is packed into uint8_t's; if nbits >8, the data is
* if nbits >8, the data is packed into uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
+3 -3
View File
@@ -157,7 +157,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static int spi_hwfeatures(FAR struct spi_dev_s *dev, static int spi_hwfeatures(FAR struct spi_dev_s *dev,
spi_hwfeatures_t features); spi_hwfeatures_t features);
#endif #endif
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(FAR struct spi_dev_s *dev, static void spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords); FAR void *rxbuffer, size_t nwords);
@@ -937,11 +937,11 @@ static uint16_t spi_send_data(FAR struct kinetis_spidev_s *priv, uint16_t wd,
* *
************************************************************************************/ ************************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct kinetis_spidev_s *priv = (FAR struct kinetis_spidev_s *)dev; FAR struct kinetis_spidev_s *priv = (FAR struct kinetis_spidev_s *)dev;
return spi_send_data(priv, wd, true); return (uint32_t)spi_send_data(priv, (uint16_t)wd, true);
} }
/************************************************************************************ /************************************************************************************
+82 -62
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/kl/kl_spi.c * arch/arm/src/kl/kl_spi.c
* *
* Copyright (C) 2013, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2013-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -75,35 +75,38 @@ struct kl_spidev_s
uint8_t mode; /* Mode 0,1,2,3 */ uint8_t mode; /* Mode 0,1,2,3 */
}; };
/************************************************************************************ /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
************************************************************************************/ ****************************************************************************/
/* Helpers */ /* Helpers */
static inline uint8_t spi_getreg(FAR struct kl_spidev_s *priv, uint8_t offset); static inline uint8_t spi_getreg(FAR struct kl_spidev_s *priv,
uint8_t offset);
static inline void spi_putreg(FAR struct kl_spidev_s *priv, uint8_t offset, static inline void spi_putreg(FAR struct kl_spidev_s *priv, uint8_t offset,
uint8_t value); uint8_t value);
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); uint32_t frequency);
static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
FAR void *rxbuffer, size_t nwords); static void spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_sndblock(FAR struct spi_dev_s *dev,
size_t nwords); FAR const void *txbuffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
size_t nwords); size_t nwords);
#endif #endif
/************************************************************************************ /****************************************************************************
* Private Data * Private Data
************************************************************************************/ ****************************************************************************/
#ifdef CONFIG_KL_SPI0 #ifdef CONFIG_KL_SPI0
static const struct spi_ops_s g_spi0ops = static const struct spi_ops_s g_spi0ops =
@@ -132,7 +135,10 @@ static const struct spi_ops_s g_spi0ops =
static struct kl_spidev_s g_spi0dev = static struct kl_spidev_s g_spi0dev =
{ {
.spidev = { &g_spi0ops }, .spidev =
{
&g_spi0ops
},
.spibase = KL_SPI0_BASE, .spibase = KL_SPI0_BASE,
}; };
#endif #endif
@@ -161,7 +167,10 @@ static const struct spi_ops_s g_spi1ops =
static struct kl_spidev_s g_spi1dev = static struct kl_spidev_s g_spi1dev =
{ {
.spidev = { &g_spi1ops }, .spidev =
{
&g_spi1ops
},
.spibase = KL_SPI1_BASE, .spibase = KL_SPI1_BASE,
}; };
#endif #endif
@@ -170,7 +179,7 @@ static struct kl_spidev_s g_spi1dev =
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/************************************************************************************ /****************************************************************************
* Name: spi_getreg * Name: spi_getreg
* *
* Description: * Description:
@@ -183,14 +192,15 @@ static struct kl_spidev_s g_spi1dev =
* Returned Value: * Returned Value:
* The contents of the 16-bit register * The contents of the 16-bit register
* *
************************************************************************************/ ****************************************************************************/
static inline uint8_t spi_getreg(FAR struct kl_spidev_s *priv, uint8_t offset) static inline uint8_t spi_getreg(FAR struct kl_spidev_s *priv,
uint8_t offset)
{ {
return getreg8(priv->spibase + offset); return getreg8(priv->spibase + offset);
} }
/************************************************************************************ /****************************************************************************
* Name: spi_putreg * Name: spi_putreg
* *
* Description: * Description:
@@ -204,7 +214,7 @@ static inline uint8_t spi_getreg(FAR struct kl_spidev_s *priv, uint8_t offset)
* Returned Value: * Returned Value:
* The contents of the 16-bit register * The contents of the 16-bit register
* *
************************************************************************************/ ****************************************************************************/
static inline void spi_putreg(FAR struct kl_spidev_s *priv, uint8_t offset, static inline void spi_putreg(FAR struct kl_spidev_s *priv, uint8_t offset,
uint8_t value) uint8_t value)
@@ -212,7 +222,7 @@ static inline void spi_putreg(FAR struct kl_spidev_s *priv, uint8_t offset,
putreg8(value, priv->spibase + offset); putreg8(value, priv->spibase + offset);
} }
/************************************************************************************ /****************************************************************************
* Name: spi_lock * Name: spi_lock
* *
* Description: * Description:
@@ -231,7 +241,7 @@ static inline void spi_putreg(FAR struct kl_spidev_s *priv, uint8_t offset,
* Returned Value: * Returned Value:
* None * None
* *
************************************************************************************/ ****************************************************************************/
static int spi_lock(FAR struct spi_dev_s *dev, bool lock) static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
{ {
@@ -250,7 +260,7 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
return ret; return ret;
} }
/************************************************************************************ /****************************************************************************
* Name: spi_setfrequency * Name: spi_setfrequency
* *
* Description: * Description:
@@ -263,9 +273,10 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* Returned Value: * Returned Value:
* Returns the actual frequency selected * Returns the actual frequency selected
* *
************************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct kl_spidev_s *priv = (FAR struct kl_spidev_s *)dev; FAR struct kl_spidev_s *priv = (FAR struct kl_spidev_s *)dev;
uint32_t divisor; uint32_t divisor;
@@ -287,19 +298,23 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
* divisor in the range {2, 4, 8, 16, 32, 64, 128, 256, or 512). * divisor in the range {2, 4, 8, 16, 32, 64, 128, 256, or 512).
* *
* *
* BaudRateDivisor = (SPPR + 1) × 2^(SPR + 1) * BaudRateDivisor = (SPPR + 1) × 2^(SPR + 1)
* BaudRate = BusClock / BaudRateDivisor * BaudRate = BusClock / BaudRateDivisor
* *
* The strategy is to pick the smallest divisor that yields an in-range * The strategy is to pick the smallest divisor that yields an in-range
* solution. I am not sure if this *always* results in an optimal solution. * solution. I am not sure if this *always* results in an optimal
* But consider, for example, with a 24Mhz bus clock and a target of 400KHz * solution. But consider, for example, with a 24Mhz bus clock and a
* target of 400KHz
* *
* target divisor is 24,000,000 / 400,000 = 60 * target divisor is 24,000,000 / 400,000 = 60
* spr = 1 -> sppr = 60 / (1 << 1) = 30 -> out of range * spr = 1 -> sppr = 60 / (1 << 1) = 30 -> out of range
* spr = 2 -> sppr = 60 / (1 << 2) = 15 -> out of range * spr = 2 -> sppr = 60 / (1 << 2) = 15 -> out of range
* spr = 3 -> sppr = 60 / (1 << 3) = 7 -> actual = 24000000 / 7 * 8 = 428571 * spr = 3 -> sppr = 60 / (1 << 3) = 7 -> actual = 24000000 / 7 * 8
* spr = 4 -> sppr = 60 / (1 << 4) = 3 -> actual = 24000000 / 3 * 16 = 500000 * = 428571
* spr = 5 -> sppr = 60 / (1 << 5) = 1 -> actual = 24000000 / 1 * 32 = 750000 * spr = 4 -> sppr = 60 / (1 << 4) = 3 -> actual = 24000000 / 3 * 16
* = 500000
* spr = 5 -> sppr = 60 / (1 << 5) = 1 -> actual = 24000000 / 1 * 32
* = 750000
*/ */
divisor = BOARD_BUSCLK_FREQ / frequency; divisor = BOARD_BUSCLK_FREQ / frequency;
@@ -323,7 +338,8 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
/* Write the new dividers to the BR register */ /* Write the new dividers to the BR register */
spi_putreg(priv, KL_SPI_BR_OFFSET, SPI_BR_SPR_DIV(spr) | SPI_BR_SPPR(sppr)); spi_putreg(priv, KL_SPI_BR_OFFSET, SPI_BR_SPR_DIV(spr) |
SPI_BR_SPPR(sppr));
/* Calculate the actual divisor and frequency */ /* Calculate the actual divisor and frequency */
@@ -339,7 +355,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
return actual; return actual;
} }
/************************************************************************************ /****************************************************************************
* Name: spi_setmode * Name: spi_setmode
* *
* Description: * Description:
@@ -352,7 +368,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
* Returned Value: * Returned Value:
* Returns the actual frequency selected * Returns the actual frequency selected
* *
************************************************************************************/ ****************************************************************************/
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
{ {
@@ -400,7 +416,7 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
} }
} }
/************************************************************************************ /****************************************************************************
* Name: spi_setbits * Name: spi_setbits
* *
* Description: * Description:
@@ -413,7 +429,7 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
* Returned Value: * Returned Value:
* None * None
* *
************************************************************************************/ ****************************************************************************/
static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
{ {
@@ -422,7 +438,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
DEBUGASSERT(nbits == 8); DEBUGASSERT(nbits == 8);
} }
/************************************************************************************ /****************************************************************************
* Name: spi_send * Name: spi_send
* *
* Description: * Description:
@@ -436,9 +452,9 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* Returned Value: * Returned Value:
* response * response
* *
************************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct kl_spidev_s *priv = (FAR struct kl_spidev_s *)dev; FAR struct kl_spidev_s *priv = (FAR struct kl_spidev_s *)dev;
@@ -450,19 +466,19 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
spi_putreg(priv, KL_SPI_D_OFFSET, (uint8_t)wd); spi_putreg(priv, KL_SPI_D_OFFSET, (uint8_t)wd);
/* Wait for the SPRF bit in the SPI Status Register to be set to 1. SPRF is set /* Wait for the SPRF bit in the SPI Status Register to be set to 1. SPRF
* at the completion of an SPI transfer to indicate that received data may be read * is set at the completion of an SPI transfer to indicate that received
* from the SPI data registr * data may be read from the SPI data register
*/ */
while ((spi_getreg(priv, KL_SPI_S_OFFSET) & SPI_S_SPRF) == 0); while ((spi_getreg(priv, KL_SPI_S_OFFSET) & SPI_S_SPRF) == 0);
/* Return the data */ /* Return the data */
return (uint16_t)spi_getreg(priv, KL_SPI_D_OFFSET); return (uint32_t)spi_getreg(priv, KL_SPI_D_OFFSET);
} }
/************************************************************************************ /****************************************************************************
* Name: spi_exchange * Name: spi_exchange
* *
* Description: * Description:
@@ -475,12 +491,13 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - the length of data to be exchaned in units of words. * nwords - the length of data to be exchaned in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
************************************************************************************/ ****************************************************************************/
static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords) FAR void *rxbuffer, size_t nwords)
@@ -542,15 +559,16 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* txbuffer - A pointer to the buffer of data to be sent * txbuffer - A pointer to the buffer of data to be sent
* nwords - 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
* The wordsize is determined by the number of bits-per-word * words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
************************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
@@ -561,7 +579,7 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
} }
#endif #endif
/************************************************************************************ /****************************************************************************
* Name: spi_recvblock * Name: spi_recvblock
* *
* Description: * Description:
@@ -570,18 +588,20 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* rxbuffer - A pointer to the buffer in which to receive data * rxbuffer - A pointer to the buffer in which to receive data
* nwords - 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
* of words. The wordsize is determined by the number of bits-per-word * number of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
************************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, size_t nwords) static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
size_t nwords)
{ {
spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords); spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords);
return spi_exchange(dev, NULL, rxbuffer, nwords); return spi_exchange(dev, NULL, rxbuffer, nwords);
+33 -24
View File
@@ -101,13 +101,16 @@ struct lc823450_spidev_s
#ifndef CONFIG_SPI_OWNBUS #ifndef CONFIG_SPI_OWNBUS
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
#endif #endif
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void spi_sndblock(FAR struct spi_dev_s *dev,
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
#endif #endif
/**************************************************************************** /****************************************************************************
@@ -138,7 +141,10 @@ static const struct spi_ops_s g_spiops =
static struct lc823450_spidev_s g_spidev = static struct lc823450_spidev_s g_spidev =
{ {
.spidev = { &g_spiops }, .spidev =
{
&g_spiops
},
}; };
/**************************************************************************** /****************************************************************************
@@ -179,7 +185,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev;
unsigned long sysclk = lc823450_get_systemfreq(); unsigned long sysclk = lc823450_get_systemfreq();
@@ -193,7 +200,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
} }
#endif #endif
for (div = 0xFE; div >= 0; div--) for (div = 0xfe; div >= 0; div--)
{ {
if (frequency >= sysclk / (4 * (256 - div))) if (frequency >= sysclk / (4 * (256 - div)))
{ {
@@ -333,15 +340,15 @@ static void spi_dma_callback(DMA_HANDLE hdma, void *arg, int result)
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_LC823450_SPI_DMA #ifdef CONFIG_LC823450_SPI_DMA
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
spi_sndblock(dev, &wd, 1); spi_sndblock(dev, &wd, 1);
return 0; return 0;
} }
#else /* CONFIG_LC823450_SPI_DMA */ #else /* CONFIG_LC823450_SPI_DMA */
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
putreg16(wd, LC823450_SPI_STR); putreg16((uint16_t)wd, LC823450_SPI_STR);
modifyreg32(LC823450_SPI_ISR, 0, SPI_ISR_SPIF); modifyreg32(LC823450_SPI_ISR, 0, SPI_ISR_SPIF);
@@ -352,11 +359,11 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
while ((getreg32(LC823450_SPI_ISR) & SPI_ISR_SPIF) == 0) while ((getreg32(LC823450_SPI_ISR) & SPI_ISR_SPIF) == 0)
; ;
return getreg16(LC823450_SPI_SRR); return (uint32_t)getreg16(LC823450_SPI_SRR);
} }
#endif #endif
/************************************************************************* /****************************************************************************
* Name: spi_sndblock * Name: spi_sndblock
* *
* Description: * Description:
@@ -395,7 +402,7 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
LC823450_DMA_DSTWIDTH_BYTE | LC823450_DMA_DSTWIDTH_BYTE |
LC823450_DMA_SRCINC, LC823450_DMA_SRCINC,
(uint32_t)buffer, /* LC823450_SPI_STR */ (uint32_t)buffer, /* LC823450_SPI_STR */
LC823450_SPI_TxFF, len); LC823450_SPI_TXFF, len);
lc823450_dmastart(priv->hdma, spi_dma_callback, &priv->dma_wait); lc823450_dmastart(priv->hdma, spi_dma_callback, &priv->dma_wait);
@@ -408,8 +415,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
/* Wait for FIFO empty */ /* Wait for FIFO empty */
putreg32(SPI_ISR_TxEMP, LC823450_SPI_ISR); putreg32(SPI_ISR_TXEMP, LC823450_SPI_ISR);
while ((getreg32(LC823450_SPI_ISR) & SPI_ISR_TxEMP) != 0) while ((getreg32(LC823450_SPI_ISR) & SPI_ISR_TXEMP) != 0)
; ;
/* Wait for Tx reg empty */ /* Wait for Tx reg empty */
@@ -431,14 +438,14 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
{ {
for (i = 0; i < nwords; i++) for (i = 0; i < nwords; i++)
{ {
spi_send(dev, *buf16++); spi_send(dev, (uint32_t)*buf16++);
} }
} }
else else
{ {
for (i = 0; i < nwords; i++) for (i = 0; i < nwords; i++)
{ {
spi_send(dev, *buf++); spi_send(dev, (uint32_t)*buf++);
} }
} }
#endif /* CONFIG_LC823450_SPI_DMA */ #endif /* CONFIG_LC823450_SPI_DMA */
@@ -455,9 +462,10 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -465,7 +473,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords)
{ {
FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev; FAR struct lc823450_spidev_s *priv = (FAR struct lc823450_spidev_s *)dev;
int i; int i;
@@ -476,14 +485,14 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw
{ {
for (i = 0; i < nwords; i++) for (i = 0; i < nwords; i++)
{ {
*buf16++ = spi_send(dev, 0xffff); *buf16++ = (uint16_t)spi_send(dev, 0xffff);
} }
} }
else else
{ {
for (i = 0; i < nwords; i++) for (i = 0; i < nwords; i++)
{ {
*buf++ = spi_send(dev, 0xffff); *buf++ = (uint8_t)spi_send(dev, 0xffff);
} }
} }
} }
@@ -558,7 +567,7 @@ FAR struct spi_dev_s *lc823450_spibus_initialize(int port)
/* use FIFO */ /* use FIFO */
putreg32(SPI_TxFF_EN | SPI_TxFF_WL8, LC823450_SPI_FFCTL); putreg32(SPI_TXFF_EN | SPI_TXFF_WL8, LC823450_SPI_FFCTL);
#endif /* CONFIG_LC823450_SPI_DMA */ #endif /* CONFIG_LC823450_SPI_DMA */
} }
+19 -22
View File
@@ -58,7 +58,7 @@
#define LC823450_SPI_BRG (LC823450_SPI_REGBASE + 0x10) /* Baudrate Generator */ #define LC823450_SPI_BRG (LC823450_SPI_REGBASE + 0x10) /* Baudrate Generator */
#define LC823450_SPI_ISR (LC823450_SPI_REGBASE + 0x14) /* Interrupt Factor */ #define LC823450_SPI_ISR (LC823450_SPI_REGBASE + 0x14) /* Interrupt Factor */
#define LC823450_SPI_DREQ (LC823450_SPI_REGBASE + 0x18) /* DMA Request */ #define LC823450_SPI_DREQ (LC823450_SPI_REGBASE + 0x18) /* DMA Request */
#define LC823450_SPI_TxFF (LC823450_SPI_REGBASE + 0x1C) /* Transfer FIFO */ #define LC823450_SPI_TXFF (LC823450_SPI_REGBASE + 0x1C) /* Transfer FIFO */
#define LC823450_SPI_RxFF (LC823450_SPI_REGBASE + 0x20) /* Receive FIFO */ #define LC823450_SPI_RxFF (LC823450_SPI_REGBASE + 0x20) /* Receive FIFO */
#define LC823450_SPI_FFCTL (LC823450_SPI_REGBASE + 0x24) /* FIFO Control */ #define LC823450_SPI_FFCTL (LC823450_SPI_REGBASE + 0x24) /* FIFO Control */
#define LC823450_SPI_MSK (LC823450_SPI_REGBASE + 0x28) /* Interrupt Mask */ #define LC823450_SPI_MSK (LC823450_SPI_REGBASE + 0x28) /* Interrupt Mask */
@@ -93,28 +93,28 @@
#define SPI_ISR_CS_END (1 << 14) /* Bit 14: CS completion (not supported) */ #define SPI_ISR_CS_END (1 << 14) /* Bit 14: CS completion (not supported) */
#define SPI_ISR_BURST_END (1 << 13) /* Bit 13: Burst transfer completion */ #define SPI_ISR_BURST_END (1 << 13) /* Bit 13: Burst transfer completion */
#define SPI_ISR_RxORE (1 << 12) /* Bit 12: Rx FIFO overread */ #define SPI_ISR_RXORE (1 << 12) /* Bit 12: Rx FIFO overread */
#define SPI_ISR_TxORE (1 << 11) /* Bit 11: Tx FIFO overread */ #define SPI_ISR_TXORE (1 << 11) /* Bit 11: Tx FIFO overread */
#define SPI_ISR_RxOWE (1 << 10) /* Bit 10: Rx FIFO overwrite */ #define SPI_ISR_RXOWE (1 << 10) /* Bit 10: Rx FIFO overwrite */
#define SPI_ISR_TxOWE (1 << 9) /* Bit 9: Tx FIFO overwrite */ #define SPI_ISR_TXOWE (1 << 9) /* Bit 9: Tx FIFO overwrite */
#define SPI_ISR_RxFULL (1 << 8) /* Bit 8: Rx FIFO full */ #define SPI_ISR_RXFULL (1 << 8) /* Bit 8: Rx FIFO full */
#define SPI_ISR_TxFULL (1 << 7) /* Bit 7: Tx FIFO full */ #define SPI_ISR_TXFULL (1 << 7) /* Bit 7: Tx FIFO full */
#define SPI_ISR_RxEMP (1 << 6) /* Bit 6: Rx FIFO empty */ #define SPI_ISR_RXEMP (1 << 6) /* Bit 6: Rx FIFO empty */
#define SPI_ISR_TxEMP (1 << 5) /* Bit 5: Tx FIFO empty */ #define SPI_ISR_TXEMP (1 << 5) /* Bit 5: Tx FIFO empty */
#define SPI_ISR_RxWLM (1 << 4) /* Bit 4: Rx FIFO water level match */ #define SPI_ISR_RXWLM (1 << 4) /* Bit 4: Rx FIFO water level match */
#define SPI_ISR_TxWLM (1 << 3) /* Bit 3: Tx FIFO water level match */ #define SPI_ISR_TXWLM (1 << 3) /* Bit 3: Tx FIFO water level match */
#define SPI_ISR_ROWE (1 << 2) /* Bit 2: SRR register overwrite */ #define SPI_ISR_ROWE (1 << 2) /* Bit 2: SRR register overwrite */
#define SPI_ISR_OVE (1 << 1) /* Bit 1: overrun */ #define SPI_ISR_OVE (1 << 1) /* Bit 1: overrun */
#define SPI_ISR_SPIF (1 << 0) /* Bit 0: Frame transfer completion */ #define SPI_ISR_SPIF (1 << 0) /* Bit 0: Frame transfer completion */
/* SPI FIFO contorl Register */ /* SPI FIFO contorl Register */
#define SPI_TxFF_EN (1 << 0) #define SPI_TXFF_EN (1 << 0)
#define SPI_TxFF_WL2 (0 << 4) #define SPI_TXFF_WL2 (0 << 4)
#define SPI_TxFF_WL4 (1 << 4) #define SPI_TXFF_WL4 (1 << 4)
#define SPI_TxFF_WL8 (2 << 4) #define SPI_TXFF_WL8 (2 << 4)
#define SPI_TxFF_WL12 (3 << 4) #define SPI_TXFF_WL12 (3 << 4)
#define SPI_TxFF_WL14 (4 << 4) #define SPI_TXFF_WL14 (4 << 4)
/* SPI Interrupt Mask Register */ /* SPI Interrupt Mask Register */
@@ -166,13 +166,10 @@ extern "C"
#define EXTERN extern #define EXTERN extern
#endif #endif
/****************************************************************************
* Public Functions
****************************************************************************/
FAR struct spi_dev_s *lc823450_spibus_initialize(int bus); FAR struct spi_dev_s *lc823450_spibus_initialize(int bus);
void lc823450_spiinitialize(void); void lc823450_spiinitialize(void);
void lc823450_spiselect(FAR struct spi_dev_s *dev, uint32_t devid, bool selected); void lc823450_spiselect(FAR struct spi_dev_s *dev, uint32_t devid,
bool selected);
uint8_t lc823450_spistatus(FAR struct spi_dev_s *dev, uint32_t devid); uint8_t lc823450_spistatus(FAR struct spi_dev_s *dev, uint32_t devid);
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
+34 -20
View File
@@ -65,7 +65,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* This driver does not support the SPI exchange method. */ /* This driver does not support the SPI exchange method. */
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
@@ -73,12 +75,13 @@
#endif #endif
/* SSP Clocking *************************************************************/ /* SSP Clocking *************************************************************/
/* The CPU clock by 1, 2, 4, or 8 to get the SPI peripheral clock (SPI_CLOCK).
* SPI_CLOCK may be further divided by 8-254 to get the SPI clock. If we /* The CPU clock by 1, 2, 4, or 8 to get the SPI peripheral clock
* want a usable range of 4KHz to 25MHz for the SPI, then: * (SPI_CLOCK). SPI_CLOCK may be further divided by 8-254 to get the SPI
* clock. If we want a usable range of 4KHz to 25MHz for the SPI, then:
* *
* 1. SPICLK must be greater than (8*25MHz) = 200MHz (so we can't reach 25MHz), * 1. SPICLK must be greater than (8*25MHz) = 200MHz (so we can't reach
* and * 25MHz), and
* 2. SPICLK must be less than (254*40Khz) = 101.6MHz. * 2. SPICLK must be less than (254*40Khz) = 101.6MHz.
* *
* If we assume that CCLK less than or equal to 100MHz, we can just * If we assume that CCLK less than or equal to 100MHz, we can just
@@ -111,12 +114,15 @@ struct lpc17_40_spidev_s
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void spi_sndblock(FAR struct spi_dev_s *dev,
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@@ -148,7 +154,10 @@ static const struct spi_ops_s g_spiops =
static struct lpc17_40_spidev_s g_spidev = static struct lpc17_40_spidev_s g_spidev =
{ {
.spidev = { &g_spiops }, .spidev =
{
&g_spiops
},
}; };
/**************************************************************************** /****************************************************************************
@@ -212,7 +221,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct lpc17_40_spidev_s *priv = (FAR struct lpc17_40_spidev_s *)dev; FAR struct lpc17_40_spidev_s *priv = (FAR struct lpc17_40_spidev_s *)dev;
uint32_t divisor; uint32_t divisor;
@@ -380,11 +390,11 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
/* Write the data to transmitted to the SPI Data Register */ /* Write the data to transmitted to the SPI Data Register */
putreg32((uint32_t)wd, LPC17_40_SPI_DR); putreg32(wd, LPC17_40_SPI_DR);
/* Wait for the SPIF bit in the SPI Status Register to be set to 1. The /* Wait for the SPIF bit in the SPI Status Register to be set to 1. The
* SPIF bit will be set after the last sampling clock edge of the SPI * SPIF bit will be set after the last sampling clock edge of the SPI
@@ -396,7 +406,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Read the SPI Status Register again to clear the status bit */ /* Read the SPI Status Register again to clear the status bit */
getreg32(LPC17_40_SPI_SR); getreg32(LPC17_40_SPI_SR);
return (uint16_t)getreg32(LPC17_40_SPI_DR); return getreg32(LPC17_40_SPI_DR);
} }
/**************************************************************************** /****************************************************************************
@@ -411,14 +421,16 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) static void spi_sndblock(FAR struct spi_dev_s *dev,
FAR const void *buffer, size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
uint8_t data; uint8_t data;
@@ -455,16 +467,18 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
+59 -32
View File
@@ -65,7 +65,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* This driver does not support the SPI exchange method. */ /* This driver does not support the SPI exchange method. */
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
@@ -75,9 +77,9 @@
/* SSP Clocking *************************************************************/ /* SSP Clocking *************************************************************/
#if defined(LPC176x) #if defined(LPC176x)
/* The CPU clock by 1, 2, 4, or 8 to get the SSP peripheral clock (SSP_CLOCK). /* The CPU clock by 1, 2, 4, or 8 to get the SSP peripheral clock
* SSP_CLOCK may be further divided by 2-254 to get the SSP clock. If we * (SSP_CLOCK). SSP_CLOCK may be further divided by 2-254 to get the SSP
* want a usable range of 4KHz to 25MHz for the SSP, then: * clock. If we want a usable range of 4KHz to 25MHz for the SSP, then:
* *
* 1. SSPCLK must be greater than (2*25MHz) = 50MHz, and * 1. SSPCLK must be greater than (2*25MHz) = 50MHz, and
* 2. SSPCLK must be less than (254*40Khz) = 101.6MHz. * 2. SSPCLK must be less than (254*40Khz) = 101.6MHz.
@@ -94,8 +96,8 @@
# define SSP_CLOCK LPC17_40_CCLK # define SSP_CLOCK LPC17_40_CCLK
#elif defined(LPC178x_40xx) #elif defined(LPC178x_40xx)
/* All peripherals are clocked by the same peripheral clock in the LPC178x/40xx /* All peripherals are clocked by the same peripheral clock in the
* family. * LPC178x/40xx family.
*/ */
# define SSP_CLOCK BOARD_PCLK_FREQUENCY # define SSP_CLOCK BOARD_PCLK_FREQUENCY
@@ -128,19 +130,23 @@ struct lpc17_40_sspdev_s
/* Helpers */ /* Helpers */
static inline uint32_t ssp_getreg(FAR struct lpc17_40_sspdev_s *priv, uint8_t offset); static inline uint32_t ssp_getreg(FAR struct lpc17_40_sspdev_s *priv,
static inline void ssp_putreg(FAR struct lpc17_40_sspdev_s *priv, uint8_t offset, uint8_t offset);
uint32_t value); static inline void ssp_putreg(FAR struct lpc17_40_sspdev_s *priv,
uint8_t offset, uint32_t value);
/* SPI methods */ /* SPI methods */
static int ssp_lock(FAR struct spi_dev_s *dev, bool lock); static int ssp_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void ssp_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void ssp_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits); static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t ssp_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void ssp_sndblock(FAR struct spi_dev_s *dev,
static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
/* Initialization */ /* Initialization */
@@ -185,7 +191,10 @@ static const struct spi_ops_s g_spi0ops =
static struct lpc17_40_sspdev_s g_ssp0dev = static struct lpc17_40_sspdev_s g_ssp0dev =
{ {
.spidev = { &g_spi0ops }, .spidev =
{
&g_spi0ops
},
.sspbase = LPC17_40_SSP0_BASE, .sspbase = LPC17_40_SSP0_BASE,
#ifdef CONFIG_LPC17_40_SSP_INTERRUPTS #ifdef CONFIG_LPC17_40_SSP_INTERRUPTS
.sspirq = LPC17_40_IRQ_SSP0, .sspirq = LPC17_40_IRQ_SSP0,
@@ -217,7 +226,10 @@ static const struct spi_ops_s g_spi1ops =
static struct lpc17_40_sspdev_s g_ssp1dev = static struct lpc17_40_sspdev_s g_ssp1dev =
{ {
.spidev = { &g_spi1ops }, .spidev =
{
&g_spi1ops
},
.sspbase = LPC17_40_SSP1_BASE, .sspbase = LPC17_40_SSP1_BASE,
#ifdef CONFIG_LPC17_40_SSP_INTERRUPTS #ifdef CONFIG_LPC17_40_SSP_INTERRUPTS
.sspirq = LPC17_40_IRQ_SSP1, .sspirq = LPC17_40_IRQ_SSP1,
@@ -249,7 +261,10 @@ static const struct spi_ops_s g_spi2ops =
static struct lpc17_40_sspdev_s g_ssp2dev = static struct lpc17_40_sspdev_s g_ssp2dev =
{ {
.spidev = { &g_spi2ops }, .spidev =
{
&g_spi2ops
},
.sspbase = LPC17_40_SSP2_BASE, .sspbase = LPC17_40_SSP2_BASE,
#ifdef CONFIG_LPC17_40_SSP_INTERRUPTS #ifdef CONFIG_LPC17_40_SSP_INTERRUPTS
.sspirq = LPC17_40_IRQ_SSP2, .sspirq = LPC17_40_IRQ_SSP2,
@@ -280,7 +295,8 @@ static struct lpc17_40_sspdev_s g_ssp2dev =
* *
****************************************************************************/ ****************************************************************************/
static inline uint32_t ssp_getreg(FAR struct lpc17_40_sspdev_s *priv, uint8_t offset) static inline uint32_t ssp_getreg(FAR struct lpc17_40_sspdev_s *priv,
uint8_t offset)
{ {
return getreg32(priv->sspbase + (uint32_t)offset); return getreg32(priv->sspbase + (uint32_t)offset);
} }
@@ -301,7 +317,8 @@ static inline uint32_t ssp_getreg(FAR struct lpc17_40_sspdev_s *priv, uint8_t of
* *
****************************************************************************/ ****************************************************************************/
static inline void ssp_putreg(FAR struct lpc17_40_sspdev_s *priv, uint8_t offset, uint32_t value) static inline void ssp_putreg(FAR struct lpc17_40_sspdev_s *priv,
uint8_t offset, uint32_t value)
{ {
putreg32(value, priv->sspbase + (uint32_t)offset); putreg32(value, priv->sspbase + (uint32_t)offset);
} }
@@ -359,7 +376,8 @@ static int ssp_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev; FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev;
uint32_t cpsdvsr; uint32_t cpsdvsr;
@@ -562,7 +580,7 @@ static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t ssp_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev; FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev;
register uint32_t regval; register uint32_t regval;
@@ -573,7 +591,7 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Write the byte to the TX FIFO */ /* Write the byte to the TX FIFO */
ssp_putreg(priv, LPC17_40_SSP_DR_OFFSET, (uint32_t)wd); ssp_putreg(priv, LPC17_40_SSP_DR_OFFSET, wd);
/* Wait for the RX FIFO not empty */ /* Wait for the RX FIFO not empty */
@@ -583,7 +601,7 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
regval = ssp_getreg(priv, LPC17_40_SSP_DR_OFFSET); regval = ssp_getreg(priv, LPC17_40_SSP_DR_OFFSET);
spiinfo("%04x->%04x\n", wd, regval); spiinfo("%04x->%04x\n", wd, regval);
return (uint16_t)regval; return regval;
} }
/**************************************************************************** /****************************************************************************
@@ -598,14 +616,16 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
size_t nwords)
{ {
FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev; FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev;
union union
@@ -614,6 +634,7 @@ static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
FAR const uint16_t *p16; FAR const uint16_t *p16;
FAR const void *pv; FAR const void *pv;
} u; } u;
uint32_t data; uint32_t data;
uint32_t sr; uint32_t sr;
@@ -625,7 +646,8 @@ static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
{ {
/* While the TX FIFO is not full and there are bytes left to send */ /* While the TX FIFO is not full and there are bytes left to send */
while ((ssp_getreg(priv, LPC17_40_SSP_SR_OFFSET) & SSP_SR_TNF) && nwords) while ((ssp_getreg(priv, LPC17_40_SSP_SR_OFFSET) & SSP_SR_TNF) &&
nwords)
{ {
/* Fetch the data to send */ /* Fetch the data to send */
@@ -661,9 +683,9 @@ static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
} }
/* There is a race condition where TFE may go true just before /* There is a race condition where TFE may go true just before
* RNE goes true and this loop terminates prematurely. The nasty little * RNE goes true and this loop terminates prematurely. The nasty
* delay in the following solves that (it could probably be tuned * little delay in the following solves that (it could probably be
* to improve performance). * tuned to improve performance).
*/ */
else if ((sr & SSP_SR_TFE) != 0) else if ((sr & SSP_SR_TFE) != 0)
@@ -685,16 +707,18 @@ static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords)
{ {
FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev; FAR struct lpc17_40_sspdev_s *priv = (FAR struct lpc17_40_sspdev_s *)dev;
union union
@@ -703,6 +727,7 @@ static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw
FAR uint16_t *p16; FAR uint16_t *p16;
FAR void *pv; FAR void *pv;
} u; } u;
uint32_t data; uint32_t data;
uint32_t rxpending = 0; uint32_t rxpending = 0;
@@ -741,6 +766,7 @@ static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw
{ {
*u.p8++ = (uint8_t)data; *u.p8++ = (uint8_t)data;
} }
rxpending--; rxpending--;
} }
} }
@@ -956,7 +982,8 @@ FAR struct spi_dev_s *lpc17_40_sspbus_initialize(int port)
/* Configure 8-bit SPI mode */ /* Configure 8-bit SPI mode */
ssp_putreg(priv, LPC17_40_SSP_CR0_OFFSET, SSP_CR0_DSS_8BIT | SSP_CR0_FRF_SPI); ssp_putreg(priv, LPC17_40_SSP_CR0_OFFSET,
SSP_CR0_DSS_8BIT | SSP_CR0_FRF_SPI);
/* Disable the SSP and all interrupts (we'll poll for all data) */ /* Disable the SSP and all interrupts (we'll poll for all data) */
+35 -23
View File
@@ -6,7 +6,7 @@
* *
* Derived from arch/arm/src/lpc17xx_40xx/lpc17_40_spi.c * Derived from arch/arm/src/lpc17xx_40xx/lpc17_40_spi.c
* *
* Copyright (C) 2010, 2012, 2014, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2010-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -69,6 +69,7 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
@@ -81,8 +82,8 @@
* clock (SPI_CLOCK). SPI_CLOCK may be further divided by 8-254 to get the * clock (SPI_CLOCK). SPI_CLOCK may be further divided by 8-254 to get the
* SPI clock. If we want a usable range of 4KHz to 25MHz for the SPI, then: * SPI clock. If we want a usable range of 4KHz to 25MHz for the SPI, then:
* *
* 1. SPICLK must be greater than (8*25MHz) = 200MHz (so we can't reach 25MHz), * 1. SPICLK must be greater than (8*25MHz) = 200MHz (so we can't reach
* and * 25MHz), and
* 2. SPICLK must be less than (254*40Khz) = 101.6MHz. * 2. SPICLK must be less than (254*40Khz) = 101.6MHz.
* *
* If we assume that CCLK less than or equal to 100MHz, we can just * If we assume that CCLK less than or equal to 100MHz, we can just
@@ -117,12 +118,15 @@ struct lpc23xx_spidev_s
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void spi_sndblock(FAR struct spi_dev_s *dev,
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@@ -154,7 +158,10 @@ static const struct spi_ops_s g_spiops =
static struct lpc23xx_spidev_s g_spidev = static struct lpc23xx_spidev_s g_spidev =
{ {
.spidev = { &g_spiops }, .spidev =
{
&g_spiops
},
}; };
/**************************************************************************** /****************************************************************************
@@ -218,7 +225,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct lpc23xx_spidev_s *priv = (FAR struct lpc23xx_spidev_s *)dev; FAR struct lpc23xx_spidev_s *priv = (FAR struct lpc23xx_spidev_s *)dev;
uint32_t divisor; uint32_t divisor;
@@ -292,7 +300,7 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
/* Has the mode changed? */ /* Has the mode changed? */
DEBUGASSERT(priv != NULL); DEBUGASSERT(priv != NULL);
if (mode != priv->mode) if (mode != priv->mode)
{ {
/* Yes... Set CR appropriately */ /* Yes... Set CR appropriately */
@@ -387,11 +395,11 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
/* Write the data to transmitted to the SPI Data Register */ /* Write the data to transmitted to the SPI Data Register */
putreg32((uint32_t)wd, SPI_DR); putreg32(wd, SPI_DR);
/* Wait for the SPIF bit in the SPI Status Register to be set to 1. The /* Wait for the SPIF bit in the SPI Status Register to be set to 1. The
* SPIF bit will be set after the last sampling clock edge of the SPI * SPIF bit will be set after the last sampling clock edge of the SPI
@@ -403,7 +411,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Read the SPI Status Register again to clear the status bit */ /* Read the SPI Status Register again to clear the status bit */
getreg32(SPI_SR); getreg32(SPI_SR);
return (uint16_t)getreg32(SPI_DR); return getreg32(SPI_DR);
} }
/**************************************************************************** /****************************************************************************
@@ -418,14 +426,16 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) static void spi_sndblock(FAR struct spi_dev_s *dev,
FAR const void *buffer, size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
uint8_t data; uint8_t data;
@@ -462,16 +472,18 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
@@ -537,14 +549,14 @@ FAR struct spi_dev_s *lpc23_spibus_initialize(int port)
flags = enter_critical_section(); flags = enter_critical_section();
regval = getreg32(LPC23XX_SCB_BASE+SCB_PCONP_OFFSET); regval = getreg32(LPC23XX_SCB_BASE + SCB_PCONP_OFFSET);
regval |= PCSPI; regval |= PCSPI;
putreg32(regval, LPC23XX_SCB_BASE+SCB_PCONP_OFFSET); putreg32(regval, LPC23XX_SCB_BASE + SCB_PCONP_OFFSET);
regval = getreg32(LPC23XX_SCB_BASE+SCB_PCLKSEL0_OFFSET); regval = getreg32(LPC23XX_SCB_BASE + SCB_PCLKSEL0_OFFSET);
regval &= ~SPI_PCLKSEL_MASK; regval &= ~SPI_PCLKSEL_MASK;
regval |= SPI_PCLKSEL; regval |= SPI_PCLKSEL;
putreg32(regval, LPC23XX_SCB_BASE+SCB_PCLKSEL0_OFFSET); putreg32(regval, LPC23XX_SCB_BASE + SCB_PCLKSEL0_OFFSET);
regval = getreg32(LPC23XX_PINSEL0); regval = getreg32(LPC23XX_PINSEL0);
regval &= ~SPI_PINSEL0_MASK ; regval &= ~SPI_PINSEL0_MASK ;
File diff suppressed because it is too large Load Diff
+33 -21
View File
@@ -66,12 +66,12 @@
/* SPI Clocking. /* SPI Clocking.
* *
* The CPU clock by 1, 2, 4, or 8 to get the SPI peripheral clock (SPI_CLOCK). * The CPU clock by 1, 2, 4, or 8 to get the SPI peripheral clock
* SPI_CLOCK may be further divided by 8-254 to get the SPI clock. If we * (SPI_CLOCK). SPI_CLOCK may be further divided by 8-254 to get the SPI
* want a usable range of 4KHz to 25MHz for the SPI, then: * clock. If we want a usable range of 4KHz to 25MHz for the SPI, then:
* *
* 1. SPICLK must be greater than (8*25MHz) = 200MHz (so we can't reach 25MHz), * 1. SPICLK must be greater than (8*25MHz) = 200MHz (so we can't reach
* and * 25MHz), and
* 2. SPICLK must be less than (254*40Khz) = 101.6MHz. * 2. SPICLK must be less than (254*40Khz) = 101.6MHz.
* *
* If we assume that CCLK less than or equal to 100MHz, we can just * If we assume that CCLK less than or equal to 100MHz, we can just
@@ -103,13 +103,17 @@ struct lpc43_spidev_s
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static void spi_select(FAR struct spi_dev_s *dev, uint32_t devid, bool selected); static void spi_select(FAR struct spi_dev_s *dev, uint32_t devid,
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); bool selected);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void spi_sndblock(FAR struct spi_dev_s *dev,
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@@ -141,7 +145,10 @@ static const struct spi_ops_s g_spiops =
static struct lpc43_spidev_s g_spidev = static struct lpc43_spidev_s g_spidev =
{ {
.spidev = { &g_spiops }, .spidev =
{
&g_spiops
},
}; };
/**************************************************************************** /****************************************************************************
@@ -205,7 +212,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct lpc43_spidev_s *priv = (FAR struct lpc43_spidev_s *)dev; FAR struct lpc43_spidev_s *priv = (FAR struct lpc43_spidev_s *)dev;
uint32_t divisor; uint32_t divisor;
@@ -371,11 +379,11 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
/* Write the data to transmitted to the SPI Data Register */ /* Write the data to transmitted to the SPI Data Register */
putreg32((uint32_t)wd, LPC43_SPI_DR); putreg32(wd, LPC43_SPI_DR);
/* Wait for the SPIF bit in the SPI Status Register to be set to 1. The /* Wait for the SPIF bit in the SPI Status Register to be set to 1. The
* SPIF bit will be set after the last sampling clock edge of the SPI * SPIF bit will be set after the last sampling clock edge of the SPI
@@ -387,7 +395,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Read the SPI Status Register again to clear the status bit */ /* Read the SPI Status Register again to clear the status bit */
getreg32(LPC43_SPI_SR); getreg32(LPC43_SPI_SR);
return (uint16_t)getreg32(LPC43_SPI_DR); return getreg32(LPC43_SPI_DR);
} }
/**************************************************************************** /****************************************************************************
@@ -402,14 +410,16 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
uint8_t data; uint8_t data;
@@ -446,16 +456,18 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
* *
****************************************************************************/ ****************************************************************************/
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords) static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
+39 -22
View File
@@ -91,22 +91,27 @@ struct lpc43_sspdev_s
/* Helpers */ /* Helpers */
static inline uint32_t ssp_getreg(FAR struct lpc43_sspdev_s *priv, uint8_t offset); static inline uint32_t ssp_getreg(FAR struct lpc43_sspdev_s *priv,
static inline void ssp_putreg(FAR struct lpc43_sspdev_s *priv, uint8_t offset, uint8_t offset);
uint32_t value); static inline void ssp_putreg(FAR struct lpc43_sspdev_s *priv,
uint8_t offset, uint32_t value);
/* SPI methods */ /* SPI methods */
static int ssp_lock(FAR struct spi_dev_s *dev, bool lock); static int ssp_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void ssp_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void ssp_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits); static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t ssp_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void ssp_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void ssp_exchange(FAR struct spi_dev_s *dev,
FAR void *rxbuffer, size_t nwords); FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void ssp_sndblock(FAR struct spi_dev_s *dev,
static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void ssp_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
#endif #endif
/* Initialization */ /* Initialization */
@@ -153,7 +158,10 @@ static const struct spi_ops_s g_spi0ops =
static struct lpc43_sspdev_s g_ssp0dev = static struct lpc43_sspdev_s g_ssp0dev =
{ {
.spidev = { &g_spi0ops }, .spidev =
{
&g_spi0ops
},
.sspbase = LPC43_SSP0_BASE, .sspbase = LPC43_SSP0_BASE,
.sspbasefreq = BOARD_SSP0_BASEFREQ .sspbasefreq = BOARD_SSP0_BASEFREQ
#ifdef CONFIG_LPC43_SSP_INTERRUPTS #ifdef CONFIG_LPC43_SSP_INTERRUPTS
@@ -190,7 +198,10 @@ static const struct spi_ops_s g_spi1ops =
static struct lpc43_sspdev_s g_ssp1dev = static struct lpc43_sspdev_s g_ssp1dev =
{ {
.spidev = { &g_spi1ops }, .spidev =
{
&g_spi1ops
},
.sspbase = LPC43_SSP1_BASE, .sspbase = LPC43_SSP1_BASE,
.sspbasefreq = BOARD_SSP1_BASEFREQ .sspbasefreq = BOARD_SSP1_BASEFREQ
#ifdef CONFIG_LPC43_SSP_INTERRUPTS #ifdef CONFIG_LPC43_SSP_INTERRUPTS
@@ -222,7 +233,8 @@ static struct lpc43_sspdev_s g_ssp1dev =
* *
****************************************************************************/ ****************************************************************************/
static inline uint32_t ssp_getreg(FAR struct lpc43_sspdev_s *priv, uint8_t offset) static inline uint32_t ssp_getreg(FAR struct lpc43_sspdev_s *priv,
uint8_t offset)
{ {
return getreg32(priv->sspbase + (uint32_t)offset); return getreg32(priv->sspbase + (uint32_t)offset);
} }
@@ -243,7 +255,8 @@ static inline uint32_t ssp_getreg(FAR struct lpc43_sspdev_s *priv, uint8_t offse
* *
****************************************************************************/ ****************************************************************************/
static inline void ssp_putreg(FAR struct lpc43_sspdev_s *priv, uint8_t offset, uint32_t value) static inline void ssp_putreg(FAR struct lpc43_sspdev_s *priv,
uint8_t offset, uint32_t value)
{ {
putreg32(value, priv->sspbase + (uint32_t)offset); putreg32(value, priv->sspbase + (uint32_t)offset);
} }
@@ -301,7 +314,8 @@ static int ssp_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t ssp_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev; FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev;
uint32_t divisor; uint32_t divisor;
@@ -444,7 +458,8 @@ static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits)
regval &= ~SSP_CR0_DSS_MASK; regval &= ~SSP_CR0_DSS_MASK;
regval |= ((nbits - 1) << SSP_CR0_DSS_SHIFT); regval |= ((nbits - 1) << SSP_CR0_DSS_SHIFT);
ssp_putreg(priv, LPC43_SSP_CR0_OFFSET, regval); ssp_putreg(priv, LPC43_SSP_CR0_OFFSET, regval);
spiinfo("SSP Control Register 0 (CR0) after setting DSS: 0x%08X.\n", regval); spiinfo("SSP Control Register 0 (CR0) after setting"
"DSS: 0x%08X.\n", regval);
/* Save the selection so the subsequence re-configurations will be faster */ /* Save the selection so the subsequence re-configurations will be faster */
@@ -468,7 +483,7 @@ static void ssp_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t ssp_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev; FAR struct lpc43_sspdev_s *priv = (FAR struct lpc43_sspdev_s *)dev;
register uint32_t regval; register uint32_t regval;
@@ -479,7 +494,7 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Write the byte to the TX FIFO */ /* Write the byte to the TX FIFO */
ssp_putreg(priv, LPC43_SSP_DR_OFFSET, (uint32_t)wd); ssp_putreg(priv, LPC43_SSP_DR_OFFSET, wd);
/* Wait for the RX FIFO not empty */ /* Wait for the RX FIFO not empty */
@@ -489,7 +504,7 @@ static uint16_t ssp_send(FAR struct spi_dev_s *dev, uint16_t wd)
regval = ssp_getreg(priv, LPC43_SSP_DR_OFFSET); regval = ssp_getreg(priv, LPC43_SSP_DR_OFFSET);
spiinfo("%04x->%04x\n", wd, regval); spiinfo("%04x->%04x\n", wd, regval);
return (uint16_t)regval; return regval;
} }
/**************************************************************************** /****************************************************************************
@@ -523,12 +538,14 @@ static void ssp_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR const uint16_t *p16; FAR const uint16_t *p16;
FAR const void *pv; FAR const void *pv;
} tx; } tx;
union union
{ {
FAR uint8_t *p8; FAR uint8_t *p8;
FAR uint16_t *p16; FAR uint16_t *p16;
FAR void *pv; FAR void *pv;
} rx; } rx;
uint32_t data; uint32_t data;
uint32_t datadummy = (priv->nbits > 8) ? 0xffff : 0xff; uint32_t datadummy = (priv->nbits > 8) ? 0xffff : 0xff;
uint32_t rxpending = 0; uint32_t rxpending = 0;
@@ -628,10 +645,10 @@ static void ssp_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
+31 -27
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/lpc54xx/lpc54_spi.c * arch/arm/src/lpc54xx/lpc54_spi_master.c
* *
* Copyright (C) 2017-2018 Gregory Nutt. All rights reserved. * Copyright (C) 2017-2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
@@ -159,7 +159,7 @@ struct lpc54_txdummy_s
/* Transfer helpers */ /* Transfer helpers */
static inline unsigned int lpc54_spi_fifodepth(FAR struct lpc54_spidev_s *priv); static inline size_t lpc54_spi_fifodepth(FAR struct lpc54_spidev_s *priv);
static inline bool lpc54_spi_txavailable(FAR struct lpc54_spidev_s *priv); static inline bool lpc54_spi_txavailable(FAR struct lpc54_spidev_s *priv);
static inline bool lpc54_spi_rxavailable(FAR struct lpc54_spidev_s *priv); static inline bool lpc54_spi_rxavailable(FAR struct lpc54_spidev_s *priv);
@@ -182,7 +182,7 @@ static bool lpc54_spi_txdummy(FAR struct lpc54_spidev_s *priv,
static void lpc54_spi_exchange8(FAR struct lpc54_spidev_s *priv, static void lpc54_spi_exchange8(FAR struct lpc54_spidev_s *priv,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords); size_t nwords);
#ifdefCONFIG_LPC54_SPI_WIDEDATA #ifdef CONFIG_LPC54_SPI_WIDEDATA
static void lpc54_spi_exchange16(FAR struct lpc54_spidev_s *priv, static void lpc54_spi_exchange16(FAR struct lpc54_spidev_s *priv,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords); size_t nwords);
@@ -209,7 +209,7 @@ static uint32_t lpc54_spi_setfrequency(FAR struct spi_dev_s *dev,
static void lpc54_spi_setmode(FAR struct spi_dev_s *dev, static void lpc54_spi_setmode(FAR struct spi_dev_s *dev,
enum spi_mode_e mode); enum spi_mode_e mode);
static void lpc54_spi_setbits(FAR struct spi_dev_s *dev, int nbits); static void lpc54_spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t lpc54_spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t lpc54_spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
static void lpc54_spi_exchange(FAR struct spi_dev_s *dev, static void lpc54_spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
@@ -591,7 +591,7 @@ static inline uint32_t lpc54_spi_getreg(struct lpc54_spidev_s *priv,
* *
****************************************************************************/ ****************************************************************************/
static inline unsigned int lpc54_spi_fifodepth(FAR struct lpc54_spidev_s *priv) static inline size_t lpc54_spi_fifodepth(FAR struct lpc54_spidev_s *priv)
{ {
uint32_t regval = lpc54_spi_getreg(priv, LPC54_SPI_FIFOCFG_OFFSET); uint32_t regval = lpc54_spi_getreg(priv, LPC54_SPI_FIFOCFG_OFFSET);
return ((regval & SPI_FIFOCFG_SIZE_MASK) >> SPI_FIFOCFG_SIZE_SHIFT) << 3; return ((regval & SPI_FIFOCFG_SIZE_MASK) >> SPI_FIFOCFG_SIZE_SHIFT) << 3;
@@ -692,7 +692,7 @@ static void lpc54_spi_resetfifos(FAR struct lpc54_spidev_s *priv)
* Name: lpc54_spi_rxtransfer8 and lpc54_spi_rxtransfer16 * Name: lpc54_spi_rxtransfer8 and lpc54_spi_rxtransfer16
* *
* Description: * Description:
* Receive one 8- or 16-bit value from the selected SPI device. * Receive one 8-bit or 16-bit value from the selected SPI device.
* *
* Input Parameters: * Input Parameters:
* priv - Device-specific state data * priv - Device-specific state data
@@ -887,7 +887,8 @@ static bool lpc54_spi_txdummy(FAR struct lpc54_spidev_s *priv,
* Name: lpc54_spi_exchange8 and lpc54_spi_exchange16 * Name: lpc54_spi_exchange8 and lpc54_spi_exchange16
* *
* Description: * Description:
* Implements the SPI exchange method for the case of 8- and 16-bit transfers. * Implements the SPI exchange method for the case of 8-bit and 16-bit
* transfers.
* *
* Input Parameters: * Input Parameters:
* priv - Device-specific state data * priv - Device-specific state data
@@ -911,7 +912,7 @@ static void lpc54_spi_exchange8(FAR struct lpc54_spidev_s *priv,
{ {
struct lpc54_rxtransfer8_s rxtransfer; struct lpc54_rxtransfer8_s rxtransfer;
struct lpc54_txtransfer8_s txtransfer; struct lpc54_txtransfer8_s txtransfer;
unsigned int depth; size_t depth;
DEBUGASSERT(rxbuffer != NULL && txbuffer != NULL); DEBUGASSERT(rxbuffer != NULL && txbuffer != NULL);
@@ -921,12 +922,12 @@ static void lpc54_spi_exchange8(FAR struct lpc54_spidev_s *priv,
/* Set up the transfer data */ /* Set up the transfer data */
txtransfer.txctrl = SPI_FIFOWR_LEN(priv->nbits) | SPI_FIFOWR_TXSSELN_ALL; txtransfer.txctrl = SPI_FIFOWR_LEN(priv->nbits) | SPI_FIFOWR_TXSSELN_ALL;
txtransfer.txptr = (FAR uint8_t *)txbuffer; txtransfer.txptr = (FAR uint8_t *)txbuffer;
txtransfer.remaining = nwords; txtransfer.remaining = nwords;
rxtransfer.rxptr = (FAR uint8_t *)rxbuffer; rxtransfer.rxptr = (FAR uint8_t *)rxbuffer;
rxtransfer.remaining = nwords; rxtransfer.remaining = nwords;
rxtransfer.expected = 0; rxtransfer.expected = 0;
/* Clear Tx/Rx errors and empty FIFOs */ /* Clear Tx/Rx errors and empty FIFOs */
@@ -965,13 +966,14 @@ static void lpc54_spi_exchange8(FAR struct lpc54_spidev_s *priv,
#if defined(CONFIG_SPI_EXCHANGE) && defined(CONFIG_LPC54_SPI_WIDEDATA) #if defined(CONFIG_SPI_EXCHANGE) && defined(CONFIG_LPC54_SPI_WIDEDATA)
static void lpc54_spi_exchange16(FAR struct lpc54_spidev_s *priv, static void lpc54_spi_exchange16(FAR struct lpc54_spidev_s *priv,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer,
FAR void *rxbuffer,
size_t nwords) size_t nwords)
{ {
struct lpc54_rxtransfer16_s rxtransfer; struct lpc54_rxtransfer16_s rxtransfer;
struct lpc54_txtransfer16_s txtransfer; struct lpc54_txtransfer16_s txtransfer;
uint32_t regval; uint32_t regval;
unsigned int depth; size_t depth;
DEBUGASSERT(rxbuffer != NULL && ((uintptr_t)rxbuffer & 1) == 0); DEBUGASSERT(rxbuffer != NULL && ((uintptr_t)rxbuffer & 1) == 0);
DEBUGASSERT(txbuffer != NULL && ((uintptr_t)txbuffer & 1) == 0); DEBUGASSERT(txbuffer != NULL && ((uintptr_t)txbuffer & 1) == 0);
@@ -982,12 +984,12 @@ static void lpc54_spi_exchange16(FAR struct lpc54_spidev_s *priv,
/* Set up the transfer data */ /* Set up the transfer data */
txtransfer.txctrl = SPI_FIFOWR_LEN(priv->nbits) | SPI_FIFOWR_TXSSELN_ALL; txtransfer.txctrl = SPI_FIFOWR_LEN(priv->nbits) | SPI_FIFOWR_TXSSELN_ALL;
txtransfer.txptr = (FAR uint16_t *)txbuffer; txtransfer.txptr = (FAR uint16_t *)txbuffer;
txtransfer.remaining = nwords; txtransfer.remaining = nwords;
rxtransfer.rxptr = (FAR uint16_t *)rxbuffer; rxtransfer.rxptr = (FAR uint16_t *)rxbuffer;
rxtransfer.remaining = nwords; rxtransfer.remaining = nwords;
rxtransfer.expected = 0; rxtransfer.expected = 0;
/* Clear Tx/Rx errors and empty FIFOs */ /* Clear Tx/Rx errors and empty FIFOs */
@@ -1105,7 +1107,7 @@ static void lpc54_spi_sndblock16(FAR struct lpc54_spidev_s *priv,
lpc54_spi_txtransfer16(priv, &txtransfer); lpc54_spi_txtransfer16(priv, &txtransfer);
} }
} }
#endif /*CONFIG_LPC54_SPI_WIDEDATA */ #endif /* CONFIG_LPC54_SPI_WIDEDATA */
/**************************************************************************** /****************************************************************************
* Name: lpc54_spi_recvblock8 and lpc54_spi_recvblock16 * Name: lpc54_spi_recvblock8 and lpc54_spi_recvblock16
@@ -1133,7 +1135,7 @@ static void lpc54_spi_recvblock8(FAR struct lpc54_spidev_s *priv,
{ {
struct lpc54_rxtransfer8_s rxtransfer; struct lpc54_rxtransfer8_s rxtransfer;
struct lpc54_txdummy_s txtransfer; struct lpc54_txdummy_s txtransfer;
unsigned int depth; size_t depth;
DEBUGASSERT(buffer != NULL); DEBUGASSERT(buffer != NULL);
@@ -1158,7 +1160,7 @@ static void lpc54_spi_recvblock8(FAR struct lpc54_spidev_s *priv,
* received. * received.
*/ */
while (txtransfer.remaining != 0|| rxtransfer.remaining != 0) while (txtransfer.remaining != 0 || rxtransfer.remaining != 0)
{ {
/* Transfer one byte from the Rx FIFO to the caller's Rx buffer */ /* Transfer one byte from the Rx FIFO to the caller's Rx buffer */
@@ -1188,7 +1190,7 @@ static void lpc54_spi_recvblock16(FAR struct lpc54_spidev_s *priv,
{ {
struct lpc54_rxtransfer16_s rxtransfer; struct lpc54_rxtransfer16_s rxtransfer;
struct lpc54_txdummy_s txtransfer; struct lpc54_txdummy_s txtransfer;
unsigned int depth; size_t depth;
DEBUGASSERT(buffer != NULL); DEBUGASSERT(buffer != NULL);
@@ -1419,7 +1421,8 @@ static void lpc54_spi_setbits(FAR struct spi_dev_s *dev, int nbits)
/* The valid range of bit selections is SPI_MINWIDTH through SPI_MAXWIDTH */ /* The valid range of bit selections is SPI_MINWIDTH through SPI_MAXWIDTH */
DEBUGASSERT(priv != NULL && nbits >= SPI_MINWIDTH && nbits <= SPI_MAXWIDTH); DEBUGASSERT(priv != NULL && nbits >= SPI_MINWIDTH &&
nbits <= SPI_MAXWIDTH);
if (nbits >= SPI_MINWIDTH && nbits <= SPI_MAXWIDTH) if (nbits >= SPI_MINWIDTH && nbits <= SPI_MAXWIDTH)
{ {
@@ -1445,7 +1448,7 @@ static void lpc54_spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t lpc54_spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t lpc54_spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct lpc54_spidev_s *priv = (FAR struct lpc54_spidev_s *)dev; FAR struct lpc54_spidev_s *priv = (FAR struct lpc54_spidev_s *)dev;
uint32_t regval; uint32_t regval;
@@ -1473,7 +1476,7 @@ static uint16_t lpc54_spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Then read and return the value from the Rx FIFO */ /* Then read and return the value from the Rx FIFO */
return (uint16_t)lpc54_spi_getreg(priv, LPC54_SPI_FIFORD_OFFSET); return lpc54_spi_getreg(priv, LPC54_SPI_FIFORD_OFFSET);
} }
/**************************************************************************** /****************************************************************************
@@ -1669,6 +1672,7 @@ FAR struct spi_dev_s *lpc54_spibus_initialize(int port)
flags = enter_critical_section(); flags = enter_critical_section();
/* Configure the requested SPI peripheral */ /* Configure the requested SPI peripheral */
/* NOTE: The basic FLEXCOMM initialization was performed in /* NOTE: The basic FLEXCOMM initialization was performed in
* lpc54_lowputc.c. * lpc54_lowputc.c.
*/ */
@@ -2068,8 +2072,8 @@ FAR struct spi_dev_s *lpc54_spibus_initialize(int port)
/* Set the delay configuration (not used) */ /* Set the delay configuration (not used) */
regval = (SPI_DLY_PRE_DELAY(0) | SPI_DLY_POST_DELAY(0) | SPI_DLY_FRAME_DELAY(0) | regval = (SPI_DLY_PRE_DELAY(0) | SPI_DLY_POST_DELAY(0) |
SPI_DLY_TRANSFER_DELAY(0)); SPI_DLY_FRAME_DELAY(0) | SPI_DLY_TRANSFER_DELAY(0));
lpc54_spi_putreg(priv, LPC54_SPI_DLY_OFFSET, regval); lpc54_spi_putreg(priv, LPC54_SPI_DLY_OFFSET, regval);
/* Select a default frequency of approx. 400KHz */ /* Select a default frequency of approx. 400KHz */
+40 -29
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/max326/max326_spi.c * arch/arm/src/max326xx/max32660/max32660_spim.c
* *
* Copyright (C) 2018 Gregory Nutt. All rights reserved. * Copyright (C) 2018 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
@@ -193,7 +193,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits);
static int spi_hwfeatures(struct spi_dev_s *dev, static int spi_hwfeatures(struct spi_dev_s *dev,
spi_hwfeatures_t features); spi_hwfeatures_t features);
#endif #endif
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
void *rxbuffer, size_t nwords); void *rxbuffer, size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
@@ -247,7 +247,10 @@ static const struct spi_ops_s g_sp0iops =
static struct max326_spidev_s g_spi0dev = static struct max326_spidev_s g_spi0dev =
{ {
.dev = { &g_sp0iops }, .dev =
{
&g_sp0iops
},
.base = MAX326_SPI0_BASE, .base = MAX326_SPI0_BASE,
#ifdef CONFIG_MAX326_SPI_INTERRUPTS #ifdef CONFIG_MAX326_SPI_INTERRUPTS
.irq = MAX326_IRQ_SPI, .irq = MAX326_IRQ_SPI,
@@ -624,7 +627,8 @@ static int spi_poll(struct max326_spidev_s *priv)
/* Break out if we've transmitted all the bytes and not receiving */ /* Break out if we've transmitted all the bytes and not receiving */
if ((priv->rxbuffer == NULL) && priv->txbytes == length && if ((priv->rxbuffer == NULL) && priv->txbytes == length &&
(spi_getreg(priv, MAX326_SPI_DMA_OFFSET) & SPI_DMA_TXFIFOCNT_MASK) == 0) (spi_getreg(priv, MAX326_SPI_DMA_OFFSET) &
SPI_DMA_TXFIFOCNT_MASK) == 0)
{ {
goto done; goto done;
} }
@@ -790,8 +794,10 @@ static int spi_interrupt(int irq, void *context, void *arg)
/* Check if there is more Rx data to be read */ /* Check if there is more Rx data to be read */
regval = spi_getreg(priv, MAX326_SPI_DMA_OFFSET); regval = spi_getreg(priv, MAX326_SPI_DMA_OFFSET);
rxavail = (regval & SPI_DMA_TXFIFOCNT_MASK) >> SPI_DMA_TXFIFOCNT_SHIFT; rxavail = (regval & SPI_DMA_TXFIFOCNT_MASK) >>
rxlevel = (regval & SPI_DMA_RXFIFOLVL_MASK) >> SPI_DMA_RXFIFOLVL_SHIFT; SPI_DMA_TXFIFOCNT_SHIFT;
rxlevel = (regval & SPI_DMA_RXFIFOLVL_MASK) >>
SPI_DMA_RXFIFOLVL_SHIFT;
} }
while (/* RX buffer != NULL && */ rxavail > rxlevel); while (/* RX buffer != NULL && */ rxavail > rxlevel);
} }
@@ -998,12 +1004,14 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
} }
regval = spi_getreg(priv, MAX326_SPI_CLKCFG_OFFSET); regval = spi_getreg(priv, MAX326_SPI_CLKCFG_OFFSET);
regval &= ~(SPI_CLKCFG_LO_MASK | SPI_CLKCFG_HI_MASK | SPI_CLKCFG_SCALE_MASK); regval &= ~(SPI_CLKCFG_LO_MASK | SPI_CLKCFG_HI_MASK |
regval |= (SPI_CLKCFG_LO(high) | SPI_CLKCFG_HI(high) | SPI_CLKCFG_SCALE(scale)); SPI_CLKCFG_SCALE_MASK);
regval |= (SPI_CLKCFG_LO(high) | SPI_CLKCFG_HI(high) |
SPI_CLKCFG_SCALE(scale));
spi_putreg(priv, MAX326_SPI_CLKCFG_OFFSET, regval); spi_putreg(priv, MAX326_SPI_CLKCFG_OFFSET, regval);
/* Save the frequency selection so that subsequent reconfigurations will be /* Save the frequency selection so that subsequent reconfigurations
* faster. * will be faster.
*/ */
spiinfo("Frequency %d->%d\n", frequency, actual); spiinfo("Frequency %d->%d\n", frequency, actual);
@@ -1160,9 +1168,9 @@ static int spi_hwfeatures(struct spi_dev_s *dev, spi_hwfeatures_t features)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint16_t ret; uint32_t ret;
spiinfo("wd=%04u\n", wd); spiinfo("wd=%04u\n", wd);
spi_exchange(dev, &wd, &ret, 1); spi_exchange(dev, &wd, &ret, 1);
@@ -1190,8 +1198,8 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
* *
****************************************************************************/ ****************************************************************************/
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, void *rxbuffer, static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
size_t nwords) void *rxbuffer, size_t nwords)
{ {
struct max326_spidev_s *priv = (struct max326_spidev_s *)dev; struct max326_spidev_s *priv = (struct max326_spidev_s *)dev;
#ifndef CONFIG_MAX326_SPI_INTERRUPTS #ifndef CONFIG_MAX326_SPI_INTERRUPTS
@@ -1331,11 +1339,11 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, void *rxbu
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* txbuffer - A pointer to the buffer of data to be sent * txbuffer - A pointer to the buffer of data to be sent
* nwords - 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
* The wordsize is determined by the number of bits-per-word * words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1343,7 +1351,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, void *rxbu
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(struct spi_dev_s *dev, const void *txbuffer, size_t nwords) static void spi_sndblock(struct spi_dev_s *dev, const void *txbuffer,
size_t nwords)
{ {
spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords); spiinfo("txbuffer=%p nwords=%d\n", txbuffer, nwords);
spi_exchange(dev, txbuffer, NULL, nwords); spi_exchange(dev, txbuffer, NULL, nwords);
@@ -1359,11 +1368,11 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *txbuffer, size_t nwo
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* rxbuffer - A pointer to the buffer in which to receive data * rxbuffer - A pointer to the buffer in which to receive data
* nwords - 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
* of words. The wordsize is determined by the number of bits-per-word * number of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1371,7 +1380,8 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *txbuffer, size_t nwo
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_recvblock(struct spi_dev_s *dev, void *rxbuffer, size_t nwords) static void spi_recvblock(struct spi_dev_s *dev, void *rxbuffer,
size_t nwords)
{ {
spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords); spiinfo("rxbuffer=%p nwords=%d\n", rxbuffer, nwords);
spi_exchange(dev, NULL, rxbuffer, nwords); spi_exchange(dev, NULL, rxbuffer, nwords);
@@ -1382,8 +1392,8 @@ static void spi_recvblock(struct spi_dev_s *dev, void *rxbuffer, size_t nwords)
* Name: spi_bus_initialize * Name: spi_bus_initialize
* *
* Description: * Description:
* Initialize the selected SPI bus in its default state (Master, 8-bit, mode 0, * Initialize the selected SPI bus in its default state (Master, 8-bit,
* etc.) * mode 0, etc.)
* *
* Input Parameters: * Input Parameters:
* priv - private SPI device structure * priv - private SPI device structure
@@ -1405,7 +1415,8 @@ static void spi_bus_initialize(struct max326_spidev_s *priv)
/* Setup slaved select timing (even in Master mode?) */ /* Setup slaved select timing (even in Master mode?) */
regval = (SPI_SSTIME_SSACT1(1) | SPI_SSTIME_SSACT2(1) | SPI_SSTIME_SSINACT(1)); regval = (SPI_SSTIME_SSACT1(1) | SPI_SSTIME_SSACT2(1) |
SPI_SSTIME_SSINACT(1));
spi_putreg(priv, MAX326_SPI_SSTIME_OFFSET, regval); spi_putreg(priv, MAX326_SPI_SSTIME_OFFSET, regval);
/* Configure CTRL0. Default configuration: /* Configure CTRL0. Default configuration:
+8 -7
View File
@@ -112,7 +112,7 @@ static void nrf52_spi_setbits(FAR struct spi_dev_s *priv, int nbits);
static int nrf52_spi_hwfeatures(FAR struct spi_dev_s *dev, static int nrf52_spi_hwfeatures(FAR struct spi_dev_s *dev,
spi_hwfeatures_t features); spi_hwfeatures_t features);
#endif #endif
static uint16_t nrf52_spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t nrf52_spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void nrf52_spi_exchange(FAR struct spi_dev_s *dev, static void nrf52_spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords); FAR void *rxbuffer, size_t nwords);
@@ -600,7 +600,8 @@ errout:
* *
****************************************************************************/ ****************************************************************************/
static void nrf52_spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) static void nrf52_spi_setmode(FAR struct spi_dev_s *dev,
enum spi_mode_e mode)
{ {
FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev; FAR struct nrf52_spidev_s *priv = (FAR struct nrf52_spidev_s *)dev;
uint32_t regval = 0; uint32_t regval = 0;
@@ -757,9 +758,9 @@ static int nrf52_spi_hwfeatures(FAR struct spi_dev_s *dev,
* *
****************************************************************************/ ****************************************************************************/
static uint16_t nrf52_spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t nrf52_spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
uint16_t ret = 0; uint32_t ret = 0;
/* Exchange one word on SPI */ /* Exchange one word on SPI */
@@ -869,9 +870,9 @@ static void nrf52_spi_exchange(FAR struct spi_dev_s *dev,
* Input Parameters: * Input Parameters:
* dev - Device-specific state data * dev - Device-specific state data
* txbuffer - A pointer to the buffer of data to be sent * txbuffer - A pointer to the buffer of data to be sent
* nwords - 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
* The wordsize is determined by the number of bits-per-word * words. The wordsize is determined by the number of
* selected for the SPI interface. * bits-per-word selected for the SPI interface.
* *
* Returned Value: * Returned Value:
* None * None
+30 -26
View File
@@ -1,5 +1,5 @@
/************************************************************************************ /************************************************************************************
* arm/arm/src/s32k1xx/s32k1xx_lpspi.c * arch/arm/src/s32k1xx/s32k1xx_lpspi.c
* *
* Copyright (C) 2019 Gregory Nutt. All rights reserved. * Copyright (C) 2019 Gregory Nutt. All rights reserved.
* Authors: Teodora Kireva * Authors: Teodora Kireva
@@ -149,14 +149,14 @@ static inline uint32_t s32k1xx_lpspi_getreg32(FAR struct s32k1xx_lpspidev_s *pri
uint8_t offset); uint8_t offset);
static inline void s32k1xx_lpspi_putreg32(FAR struct s32k1xx_lpspidev_s *priv, static inline void s32k1xx_lpspi_putreg32(FAR struct s32k1xx_lpspidev_s *priv,
uint8_t offset, uint32_t value); uint8_t offset, uint32_t value);
static inline uint16_t s32k1xx_lpspi_readword(FAR struct s32k1xx_lpspidev_s *priv); static inline uint32_t s32k1xx_lpspi_readword(FAR struct s32k1xx_lpspidev_s *priv);
static inline void s32k1xx_lpspi_writeword(FAR struct s32k1xx_lpspidev_s *priv, static inline void s32k1xx_lpspi_writeword(FAR struct s32k1xx_lpspidev_s *priv,
uint16_t byte); uint16_t byte);
static inline bool s32k1xx_lpspi_9to16bitmode(FAR struct s32k1xx_lpspidev_s *priv); static inline bool s32k1xx_lpspi_9to16bitmode(FAR struct s32k1xx_lpspidev_s *priv);
static uint32_t s32k1xx_lpspi_pckfreq(uintptr_t base); static uint32_t s32k1xx_lpspi_pckfreq(uintptr_t base);
static inline void s32k1xx_lpspi_master_set_delays(FAR struct s32k1xx_lpspidev_s static inline void s32k1xx_lpspi_set_delays(FAR struct s32k1xx_lpspidev_s
*priv, uint32_t delay_ns, enum s32k1xx_delay_e type); *priv, uint32_t delay_ns, enum s32k1xx_delay_e type);
static inline void s32k1xx_lpspi_master_set_delay_scaler(FAR struct static inline void s32k1xx_lpspi_set_delay_scaler(FAR struct
s32k1xx_lpspidev_s *priv, uint32_t scaler, enum s32k1xx_delay_e type); s32k1xx_lpspidev_s *priv, uint32_t scaler, enum s32k1xx_delay_e type);
/* SPI methods */ /* SPI methods */
@@ -171,7 +171,7 @@ static void s32k1xx_lpspi_setbits(FAR struct spi_dev_s *dev, int nbits);
static int s32k1xx_lpspi_hwfeatures(FAR struct spi_dev_s *dev, static int s32k1xx_lpspi_hwfeatures(FAR struct spi_dev_s *dev,
s32k1xx_lpspi_hwfeatures_t features); s32k1xx_lpspi_hwfeatures_t features);
#endif #endif
static uint16_t s32k1xx_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t s32k1xx_lpspi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void s32k1xx_lpspi_exchange(FAR struct spi_dev_s *dev, static void s32k1xx_lpspi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords); FAR const void *txbuffer, FAR void *rxbuffer, size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
@@ -428,7 +428,7 @@ static inline void s32k1xx_lpspi_putreg32(FAR struct s32k1xx_lpspidev_s *priv,
* *
************************************************************************************/ ************************************************************************************/
static inline uint16_t s32k1xx_lpspi_readword(FAR struct s32k1xx_lpspidev_s *priv) static inline uint32_t s32k1xx_lpspi_readword(FAR struct s32k1xx_lpspidev_s *priv)
{ {
/* Wait until the receive buffer is not empty */ /* Wait until the receive buffer is not empty */
@@ -438,7 +438,7 @@ static inline uint16_t s32k1xx_lpspi_readword(FAR struct s32k1xx_lpspidev_s *pri
/* Then return the received byte */ /* Then return the received byte */
return (uint16_t) s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_RDR_OFFSET); return (uint32_t) s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_RDR_OFFSET);
} }
/************************************************************************************ /************************************************************************************
@@ -640,7 +640,7 @@ static uint32_t s32k1xx_lpspi_pckfreq(uintptr_t base)
} }
/************************************************************************************ /************************************************************************************
* Name: s32k1xx_lpspi_master_set_delays * Name: s32k1xx_lpspi_set_delays
* *
* Description: * Description:
* SET LPSPI Delay times * SET LPSPI Delay times
@@ -655,9 +655,10 @@ static uint32_t s32k1xx_lpspi_pckfreq(uintptr_t base)
* *
************************************************************************************/ ************************************************************************************/
static inline void s32k1xx_lpspi_master_set_delay_scaler(FAR struct s32k1xx_lpspidev_s *priv, static inline void s32k1xx_lpspi_set_delay_scaler(FAR struct
uint32_t scaler, s32k1xx_lpspidev_s *priv,
enum s32k1xx_delay_e type) uint32_t scaler,
enum s32k1xx_delay_e type)
{ {
switch (type) switch (type)
{ {
@@ -685,7 +686,7 @@ static inline void s32k1xx_lpspi_master_set_delay_scaler(FAR struct s32k1xx_lpsp
} }
/************************************************************************************ /************************************************************************************
* Name: s32k1xx_lpspi_master_set_delays * Name: s32k1xx_lpspi_set_delays
* *
* Description: * Description:
* SET LPSPI Delay times * SET LPSPI Delay times
@@ -700,7 +701,7 @@ static inline void s32k1xx_lpspi_master_set_delay_scaler(FAR struct s32k1xx_lpsp
* *
************************************************************************************/ ************************************************************************************/
static inline void s32k1xx_lpspi_master_set_delays(FAR struct s32k1xx_lpspidev_s *priv, static inline void s32k1xx_lpspi_set_delays(FAR struct s32k1xx_lpspidev_s *priv,
uint32_t delay_ns, uint32_t delay_ns,
enum s32k1xx_delay_e type) enum s32k1xx_delay_e type)
{ {
@@ -785,7 +786,7 @@ static inline void s32k1xx_lpspi_master_set_delays(FAR struct s32k1xx_lpspidev_s
if (initial_delay_ns >= delay_ns) if (initial_delay_ns >= delay_ns)
{ {
s32k1xx_lpspi_master_set_delay_scaler(priv, 0, type); s32k1xx_lpspi_set_delay_scaler(priv, 0, type);
} }
else else
{ {
@@ -822,7 +823,7 @@ static inline void s32k1xx_lpspi_master_set_delays(FAR struct s32k1xx_lpspidev_s
} }
} }
s32k1xx_lpspi_master_set_delay_scaler(priv, best_scaler, type); s32k1xx_lpspi_set_delay_scaler(priv, best_scaler, type);
} }
} }
@@ -959,11 +960,11 @@ static uint32_t s32k1xx_lpspi_setfrequency(FAR struct spi_dev_s *dev,
priv->frequency = frequency; priv->frequency = frequency;
priv->actual = best_frequency; priv->actual = best_frequency;
s32k1xx_lpspi_master_set_delays(priv, 1000000000 / best_frequency, s32k1xx_lpspi_set_delays(priv, 1000000000 / best_frequency,
LPSPI_PCS_TO_SCK); LPSPI_PCS_TO_SCK);
s32k1xx_lpspi_master_set_delays(priv, 1000000000 / best_frequency, s32k1xx_lpspi_set_delays(priv, 1000000000 / best_frequency,
LPSPI_LAST_SCK_TO_PCS); LPSPI_LAST_SCK_TO_PCS);
s32k1xx_lpspi_master_set_delays(priv, 1000000000 / best_frequency, s32k1xx_lpspi_set_delays(priv, 1000000000 / best_frequency,
LPSPI_BETWEEN_TRANSFER); LPSPI_BETWEEN_TRANSFER);
/* Re-enable LPSPI if it was enabled previously */ /* Re-enable LPSPI if it was enabled previously */
@@ -1192,15 +1193,15 @@ static int s32k1xx_lpspi_hwfeatures(FAR struct spi_dev_s *dev,
* *
************************************************************************************/ ************************************************************************************/
static uint16_t s32k1xx_lpspi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t s32k1xx_lpspi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct s32k1xx_lpspidev_s *priv = (FAR struct s32k1xx_lpspidev_s *)dev; FAR struct s32k1xx_lpspidev_s *priv = (FAR struct s32k1xx_lpspidev_s *)dev;
uint32_t regval; uint32_t regval;
uint16_t ret; uint32_t ret;
DEBUGASSERT(priv && priv->spibase); DEBUGASSERT(priv && priv->spibase);
s32k1xx_lpspi_writeword(priv, (uint32_t) wd); s32k1xx_lpspi_writeword(priv, wd);
while ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) != while ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_SR_OFFSET) & LPSPI_SR_RDF) !=
LPSPI_SR_RDF); LPSPI_SR_RDF);
@@ -1281,7 +1282,7 @@ static void s32k1xx_lpspi_exchange_nodma(FAR struct spi_dev_s *dev,
/* Exchange one word */ /* Exchange one word */
word = s32k1xx_lpspi_send(dev, word); word = (uint16_t) s32k1xx_lpspi_send(dev, (uint32_t) word);
/* Is there a buffer to receive the return value? */ /* Is there a buffer to receive the return value? */
@@ -1314,7 +1315,7 @@ static void s32k1xx_lpspi_exchange_nodma(FAR struct spi_dev_s *dev,
/* Exchange one word */ /* Exchange one word */
word = (uint8_t) s32k1xx_lpspi_send(dev, (uint16_t) word); word = (uint8_t) s32k1xx_lpspi_send(dev, (uint32_t) word);
/* Is there a buffer to receive the return value? */ /* Is there a buffer to receive the return value? */
@@ -1488,7 +1489,8 @@ FAR struct spi_dev_s *s32k1xx_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */ /* Only configure if the bus is not already configured */
if ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0) if ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_CR_OFFSET) &
LPSPI_CR_MEN) == 0)
{ {
/* Configure SPI0 pins: SCK, MISO, and MOSI */ /* Configure SPI0 pins: SCK, MISO, and MOSI */
@@ -1512,7 +1514,8 @@ FAR struct spi_dev_s *s32k1xx_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */ /* Only configure if the bus is not already configured */
if ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0) if ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_CR_OFFSET) &
LPSPI_CR_MEN) == 0)
{ {
/* Configure SPI1 pins: SCK, MISO, and MOSI */ /* Configure SPI1 pins: SCK, MISO, and MOSI */
@@ -1536,7 +1539,8 @@ FAR struct spi_dev_s *s32k1xx_lpspibus_initialize(int bus)
/* Only configure if the bus is not already configured */ /* Only configure if the bus is not already configured */
if ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_CR_OFFSET) & LPSPI_CR_MEN) == 0) if ((s32k1xx_lpspi_getreg32(priv, S32K1XX_LPSPI_CR_OFFSET) &
LPSPI_CR_MEN) == 0)
{ {
/* Configure SPI2 pins: SCK, MISO, and MOSI */ /* Configure SPI2 pins: SCK, MISO, and MOSI */
+32 -26
View File
@@ -80,6 +80,7 @@
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* When SPI DMA is enabled, small DMA transfers will still be performed by /* When SPI DMA is enabled, small DMA transfers will still be performed by
* polling logic. But we need a threshold value to determine what is small. * polling logic. But we need a threshold value to determine what is small.
* That value is provided by CONFIG_SAM34_SPI_DMATHRESHOLD. * That value is provided by CONFIG_SAM34_SPI_DMATHRESHOLD.
@@ -113,6 +114,7 @@
#endif #endif
/* Clocking *****************************************************************/ /* Clocking *****************************************************************/
/* Select MCU-specific settings /* Select MCU-specific settings
* *
* For the SAM3U, SAM3A, SAM3X, SAM4E and SAM4S SPI is driven by the main * For the SAM3U, SAM3A, SAM3X, SAM4E and SAM4S SPI is driven by the main
@@ -137,7 +139,8 @@
#define DMA_TIMEOUT_MS (800) #define DMA_TIMEOUT_MS (800)
#define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS) #define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS)
/* Debug *******************************************************************/ /* Debug ********************************************************************/
/* Check if SPI debut is enabled */ /* Check if SPI debut is enabled */
#ifndef CONFIG_DEBUG_DMA_INFO #ifndef CONFIG_DEBUG_DMA_INFO
@@ -211,10 +214,10 @@ struct sam_spidev_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_SAM34_SPI_REGDEBUG #ifdef CONFIG_SAM34_SPI_REGDEBUG
bool wrlast; /* Last was a write */ bool wrlast; /* Last was a write */
uint32_t addresslast; /* Last address */ uint32_t addresslast; /* Last address */
uint32_t valuelast; /* Last value */ uint32_t valuelast; /* Last value */
int ntimes; /* Number of times */ int ntimes; /* Number of times */
#endif #endif
}; };
@@ -278,7 +281,7 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency);
static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(struct spi_dev_s *dev, int nbits); static void spi_setbits(struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SAM34_SPI_DMA #ifdef CONFIG_SAM34_SPI_DMA
static void spi_exchange_nodma(struct spi_dev_s *dev, static void spi_exchange_nodma(struct spi_dev_s *dev,
const void *txbuffer, void *rxbuffer, size_t nwords); const void *txbuffer, void *rxbuffer, size_t nwords);
@@ -624,8 +627,10 @@ static void spi_dma_sampleinit(struct sam_spics_s *spics)
{ {
/* Put contents of register samples into a known state */ /* Put contents of register samples into a known state */
memset(spics->rxdmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); memset(spics->rxdmaregs, 0xff,
memset(spics->txdmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); DMA_NSAMPLES * sizeof(struct sam_dmaregs_s));
memset(spics->txdmaregs, 0xff,
DMA_NSAMPLES * sizeof(struct sam_dmaregs_s));
/* Then get the initial samples */ /* Then get the initial samples */
@@ -657,6 +662,7 @@ static void spi_dma_sampledone(struct sam_spics_s *spics)
sam_dmasample(spics->txdma, &spics->txdmaregs[DMA_END_TRANSFER]); sam_dmasample(spics->txdma, &spics->txdmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */ /* Then dump the sampled DMA registers */
/* Initial register values */ /* Initial register values */
sam_dmadump(spics->txdma, &spics->txdmaregs[DMA_INITIAL], sam_dmadump(spics->txdma, &spics->txdmaregs[DMA_INITIAL],
@@ -780,8 +786,8 @@ static void spi_rxcallback(DMA_HANDLE handle, void *arg, int result)
spi_rxdma_sample(spics, DMA_CALLBACK); spi_rxdma_sample(spics, DMA_CALLBACK);
/* Report the result of the transfer only if the TX callback has not already /* Report the result of the transfer only if the TX callback has not
* reported an error. * already reported an error.
*/ */
if (spics->result == -EBUSY) if (spics->result == -EBUSY)
@@ -923,8 +929,8 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
{ {
spiinfo("cs=%d\n", spics->cs); spiinfo("cs=%d\n", spics->cs);
/* Before writing the TDR, the PCS field in the SPI_MR register must be set /* Before writing the TDR, the PCS field in the SPI_MR register must
* in order to select a slave. * be set in order to select a slave.
*/ */
regval = spi_getreg(spi, SAM_SPI_MR_OFFSET); regval = spi_getreg(spi, SAM_SPI_MR_OFFSET);
@@ -1013,10 +1019,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK); regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK);
regval |= scbr << SPI_CSR_SCBR_SHIFT; regval |= scbr << SPI_CSR_SCBR_SHIFT;
/* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid to the /* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid
* first valid SPCK transition. When DLYBS equals zero, the NPCS valid to SPCK * to the first valid SPCK transition. When DLYBS equals zero, the NPCS
* transition is 1/2 the SPCK clock period. Otherwise, the following equations * valid to SPCK transition is 1/2 the SPCK clock period. Otherwise, the
* determine the delay: * following equations determine the delay:
* *
* Delay Before SPCK = DLYBS / SPI_CLK * Delay Before SPCK = DLYBS / SPI_CLK
* *
@@ -1028,10 +1034,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
dlybs = SAM_SPI_CLOCK / 500000; dlybs = SAM_SPI_CLOCK / 500000;
regval |= dlybs << SPI_CSR_DLYBS_SHIFT; regval |= dlybs << SPI_CSR_DLYBS_SHIFT;
/* DLYBCT: Delay Between Consecutive Transfers. This field defines the delay /* DLYBCT: Delay Between Consecutive Transfers. This field defines the
* between two consecutive transfers with the same peripheral without removing * delay between two consecutive transfers with the same peripheral without
* the chip select. The delay is always inserted after each transfer and * removing the chip select. The delay is always inserted after each
* before removing the chip select if needed. * transfer and before removing the chip select if needed.
* *
* Delay Between Consecutive Transfers = (32 x DLYBCT) / SPI_CLK * Delay Between Consecutive Transfers = (32 x DLYBCT) / SPI_CLK
* *
@@ -1194,7 +1200,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -1209,7 +1215,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -1670,10 +1676,10 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
+43 -31
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/sama5/sam_spi.c * arch/arm/src/sama5/sam_spi.c
* *
* Copyright (C) 2013-2014, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2013-2017 Gregory Nutt. All rights reserved.
* Authors: Gregory Nutt <gnutt@nuttx.org> * Authors: Gregory Nutt <gnutt@nuttx.org>
* *
* This derives from SAM3/4 SPI driver: * This derives from SAM3/4 SPI driver:
@@ -80,7 +80,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* When SPI DMA is enabled, small DMA transfers will still be performed by /* When SPI DMA is enabled, small DMA transfers will still be performed by
* polling logic. But we need a threshold value to determine what is small. * polling logic. But we need a threshold value to determine what is small.
* That value is provided by CONFIG_SAMA5_SPI_DMATHRESHOLD. * That value is provided by CONFIG_SAMA5_SPI_DMATHRESHOLD.
@@ -114,6 +116,7 @@
#endif #endif
/* Clocking *****************************************************************/ /* Clocking *****************************************************************/
/* Select MCU-specific settings /* Select MCU-specific settings
* *
* SPI is driven by the main clock. * SPI is driven by the main clock.
@@ -128,7 +131,8 @@
#define DMA_TIMEOUT_MS (800) #define DMA_TIMEOUT_MS (800)
#define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS) #define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS)
/* Debug *******************************************************************/ /* Debug ********************************************************************/
/* Check if SPI debug is enabled */ /* Check if SPI debug is enabled */
#ifndef CONFIG_DEBUG_DMA #ifndef CONFIG_DEBUG_DMA
@@ -200,10 +204,10 @@ struct sam_spidev_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_SAMA5_SPI_REGDEBUG #ifdef CONFIG_SAMA5_SPI_REGDEBUG
bool wrlast; /* Last was a write */ bool wrlast; /* Last was a write */
uint32_t addresslast; /* Last address */ uint32_t addresslast; /* Last address */
uint32_t valuelast; /* Last value */ uint32_t valuelast; /* Last value */
int ntimes; /* Number of times */ int ntimes; /* Number of times */
#endif #endif
}; };
@@ -267,7 +271,7 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency);
static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(struct spi_dev_s *dev, int nbits); static void spi_setbits(struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SAMA5_SPI_DMA #ifdef CONFIG_SAMA5_SPI_DMA
static void spi_exchange_nodma(struct spi_dev_s *dev, static void spi_exchange_nodma(struct spi_dev_s *dev,
const void *txbuffer, void *rxbuffer, size_t nwords); const void *txbuffer, void *rxbuffer, size_t nwords);
@@ -611,8 +615,10 @@ static void spi_dma_sampleinit(struct sam_spics_s *spics)
{ {
/* Put contents of register samples into a known state */ /* Put contents of register samples into a known state */
memset(spics->rxdmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); memset(spics->rxdmaregs, 0xff,
memset(spics->txdmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); DMA_NSAMPLES * sizeof(struct sam_dmaregs_s));
memset(spics->txdmaregs, 0xff,
DMA_NSAMPLES * sizeof(struct sam_dmaregs_s));
/* Then get the initial samples */ /* Then get the initial samples */
@@ -644,6 +650,7 @@ static void spi_dma_sampledone(struct sam_spics_s *spics)
sam_dmasample(spics->txdma, &spics->txdmaregs[DMA_END_TRANSFER]); sam_dmasample(spics->txdma, &spics->txdmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */ /* Then dump the sampled DMA registers */
/* Initial register values */ /* Initial register values */
sam_dmadump(spics->txdma, &spics->txdmaregs[DMA_INITIAL], sam_dmadump(spics->txdma, &spics->txdmaregs[DMA_INITIAL],
@@ -767,13 +774,13 @@ static void spi_rxcallback(DMA_HANDLE handle, void *arg, int result)
spi_rxdma_sample(spics, DMA_CALLBACK); spi_rxdma_sample(spics, DMA_CALLBACK);
/* Report the result of the transfer only if the TX callback has not already /* Report the result of the transfer only if the TX callback has not
* reported an error. * already reported an error.
*/ */
if (spics->result == -EBUSY) if (spics->result == -EBUSY)
{ {
/* Save the result of the transfer if no error was previuosly reported */ /* Save the result of the transfer if no error was previously reported */
spics->result = result; spics->result = result;
} }
@@ -910,8 +917,8 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
{ {
spiinfo("cs=%d\n", spics->cs); spiinfo("cs=%d\n", spics->cs);
/* Before writing the TDR, the PCS field in the SPI_MR register must be set /* Before writing the TDR, the PCS field in the SPI_MR register must be
* in order to select a slave. * set in order to select a slave.
*/ */
regval = spi_getreg(spi, SAM_SPI_MR_OFFSET); regval = spi_getreg(spi, SAM_SPI_MR_OFFSET);
@@ -974,7 +981,8 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
return spics->actual; return spics->actual;
} }
/* Configure SPI to a frequency as close as possible to the requested frequency. /* Configure SPI to a frequency as close as possible to the requested
* frequency.
* *
* SPCK frequency = SPI_CLK / SCBR, or SCBR = SPI_CLK / frequency * SPCK frequency = SPI_CLK / SCBR, or SCBR = SPI_CLK / frequency
*/ */
@@ -999,10 +1007,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK); regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK);
regval |= scbr << SPI_CSR_SCBR_SHIFT; regval |= scbr << SPI_CSR_SCBR_SHIFT;
/* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid to the /* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid
* first valid SPCK transition. When DLYBS equals zero, the NPCS valid to SPCK * to the first valid SPCK transition. When DLYBS equals zero, the NPCS
* transition is 1/2 the SPCK clock period. Otherwise, the following equations * valid to SPCK transition is 1/2 the SPCK clock period. Otherwise, the
* determine the delay: * following equations determine the delay:
* *
* Delay Before SPCK = DLYBS / SPI_CLK * Delay Before SPCK = DLYBS / SPI_CLK
* *
@@ -1014,10 +1022,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
dlybs = SAM_SPI_CLOCK / 500000; dlybs = SAM_SPI_CLOCK / 500000;
regval |= dlybs << SPI_CSR_DLYBS_SHIFT; regval |= dlybs << SPI_CSR_DLYBS_SHIFT;
/* DLYBCT: Delay Between Consecutive Transfers. This field defines the delay /* DLYBCT: Delay Between Consecutive Transfers. This field defines the
* between two consecutive transfers with the same peripheral without removing * delay between two consecutive transfers with the same peripheral without
* the chip select. The delay is always inserted after each transfer and * removing the chip select. The delay is always inserted after each
* before removing the chip select if needed. * transfer and before removing the chip select if needed.
* *
* Delay Between Consecutive Transfers = (32 x DLYBCT) / SPI_CLK * Delay Between Consecutive Transfers = (32 x DLYBCT) / SPI_CLK
* *
@@ -1185,7 +1193,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -1200,7 +1208,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -1566,7 +1574,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1574,7 +1583,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nwords) static void spi_sndblock(struct spi_dev_s *dev, const void *buffer,
size_t nwords)
{ {
/* spi_exchange can do this. */ /* spi_exchange can do this. */
@@ -1592,9 +1602,10 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nword
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1602,7 +1613,8 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nword
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_recvblock(struct spi_dev_s *dev, void *buffer, size_t nwords) static void spi_recvblock(struct spi_dev_s *dev, void *buffer,
size_t nwords)
{ {
/* spi_exchange can do this. */ /* spi_exchange can do this. */
+19 -15
View File
@@ -135,10 +135,10 @@ struct sam_spidev_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_SAMD2L2_SPI_REGDEBUG #ifdef CONFIG_SAMD2L2_SPI_REGDEBUG
bool wr; /* Last was a write */ bool wr; /* Last was a write */
uint32_t regaddr; /* Last address */ uint32_t regaddr; /* Last address */
uint32_t regval; /* Last value */ uint32_t regval; /* Last value */
int ntimes; /* Number of times */ int ntimes; /* Number of times */
#endif #endif
}; };
@@ -190,7 +190,7 @@ static int spi_lock(struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency);
static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(struct spi_dev_s *dev, int nbits); static void spi_setbits(struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
void *rxbuffer, size_t nwords); void *rxbuffer, size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
@@ -1072,7 +1072,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -1087,7 +1087,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -1322,7 +1322,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1330,7 +1331,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nwords) static void spi_sndblock(struct spi_dev_s *dev, const void *buffer,
size_t nwords)
{ {
/* spi_exchange can do this. */ /* spi_exchange can do this. */
@@ -1348,9 +1350,10 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nword
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1376,11 +1379,12 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer, size_t nwords)
static void spi_wait_synchronization(struct sam_spidev_s *priv) static void spi_wait_synchronization(struct sam_spidev_s *priv)
{ {
#if defined(CONFIG_ARCH_FAMILY_SAMD20) #if defined(CONFIG_ARCH_FAMILY_SAMD20)
while ((spi_getreg16(priv, SAM_SPI_STATUS_OFFSET) & SPI_STATUS_SYNCBUSY) != 0); while ((spi_getreg16(priv, SAM_SPI_STATUS_OFFSET) &
SPI_STATUS_SYNCBUSY) != 0);
#elif defined(CONFIG_ARCH_FAMILY_SAMD21) || defined(CONFIG_ARCH_FAMILY_SAML21) #elif defined(CONFIG_ARCH_FAMILY_SAMD21) || defined(CONFIG_ARCH_FAMILY_SAML21)
while ((spi_getreg16(priv, SAM_SPI_SYNCBUSY_OFFSET) & SPI_SYNCBUSY_ALL) != 0); while ((spi_getreg16(priv, SAM_SPI_SYNCBUSY_OFFSET) &
SPI_SYNCBUSY_ALL) != 0);
#endif #endif
} }
+17 -13
View File
@@ -130,10 +130,10 @@ struct sam_spidev_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_SAMD5E5SPI_REGDEBUG #ifdef CONFIG_SAMD5E5SPI_REGDEBUG
bool wr; /* Last was a write */ bool wr; /* Last was a write */
uint32_t regaddr; /* Last address */ uint32_t regaddr; /* Last address */
uint32_t regval; /* Last value */ uint32_t regval; /* Last value */
int ntimes; /* Number of times */ int ntimes; /* Number of times */
#endif #endif
}; };
@@ -185,7 +185,7 @@ static int spi_lock(struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency);
static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(struct spi_dev_s *dev, int nbits); static void spi_setbits(struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t ch);
static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer, static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
void *rxbuffer, size_t nwords); void *rxbuffer, size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
@@ -1167,7 +1167,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -1182,7 +1182,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -1417,7 +1417,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1425,7 +1426,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
****************************************************************************/ ****************************************************************************/
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nwords) static void spi_sndblock(struct spi_dev_s *dev, const void *buffer,
size_t nwords)
{ {
/* spi_exchange can do this. */ /* spi_exchange can do this. */
@@ -1443,9 +1445,10 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer, size_t nword
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1471,7 +1474,8 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer, size_t nwords)
static void spi_wait_synchronization(struct sam_spidev_s *priv) static void spi_wait_synchronization(struct sam_spidev_s *priv)
{ {
while ((spi_getreg16(priv, SAM_SPI_SYNCBUSY_OFFSET) & SPI_SYNCBUSY_ALL) != 0); while ((spi_getreg16(priv, SAM_SPI_SYNCBUSY_OFFSET) &
SPI_SYNCBUSY_ALL) != 0);
} }
/**************************************************************************** /****************************************************************************
+63 -51
View File
@@ -75,7 +75,9 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* When SPI DMA is enabled, small DMA transfers will still be performed by /* When SPI DMA is enabled, small DMA transfers will still be performed by
* polling logic. But we need a threshold value to determine what is small. * polling logic. But we need a threshold value to determine what is small.
* That value is provided by CONFIG_SAMV7_SPI_DMATHRESHOLD. * That value is provided by CONFIG_SAMV7_SPI_DMATHRESHOLD.
@@ -113,6 +115,7 @@
#endif #endif
/* Clocking *****************************************************************/ /* Clocking *****************************************************************/
/* The SPI Baud rate clock is generated by dividing the peripheral clock by /* The SPI Baud rate clock is generated by dividing the peripheral clock by
* a value between 1 and 255 * a value between 1 and 255
*/ */
@@ -126,7 +129,8 @@
#define DMA_TIMEOUT_MS (800) #define DMA_TIMEOUT_MS (800)
#define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS) #define DMA_TIMEOUT_TICKS MSEC2TICK(DMA_TIMEOUT_MS)
/* Debug *******************************************************************/ /* Debug ********************************************************************/
/* Check if SPI debug is enabled */ /* Check if SPI debug is enabled */
#ifndef CONFIG_DEBUG_DMA #ifndef CONFIG_DEBUG_DMA
@@ -199,10 +203,10 @@ struct sam_spidev_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_SAMV7_SPI_REGDEBUG #ifdef CONFIG_SAMV7_SPI_REGDEBUG
bool wrlast; /* Last was a write */ bool wrlast; /* Last was a write */
uint32_t addresslast; /* Last address */ uint32_t addresslast; /* Last address */
uint32_t valuelast; /* Last value */ uint32_t valuelast; /* Last value */
int ntimes; /* Number of times */ int ntimes; /* Number of times */
#endif #endif
}; };
@@ -265,14 +269,15 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
bool selected); bool selected);
static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency);
#ifdef CONFIG_SPI_CS_DELAY_CONTROL #ifdef CONFIG_SPI_CS_DELAY_CONTROL
static int spi_setdelay(struct spi_dev_s *dev, uint32_t a, uint32_t b, uint32_t c); static int spi_setdelay(struct spi_dev_s *dev, uint32_t a, uint32_t b,
uint32_t c);
#endif #endif
#ifdef CONFIG_SPI_HWFEATURES #ifdef CONFIG_SPI_HWFEATURES
static int spi_hwfeatures(struct spi_dev_s *dev, uint8_t features); static int spi_hwfeatures(struct spi_dev_s *dev, uint8_t features);
#endif #endif
static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(struct spi_dev_s *dev, int nbits); static void spi_setbits(struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SAMV7_SPI_DMA #ifdef CONFIG_SAMV7_SPI_DMA
static void spi_exchange_nodma(struct spi_dev_s *dev, static void spi_exchange_nodma(struct spi_dev_s *dev,
const void *txbuffer, void *rxbuffer, size_t nwords); const void *txbuffer, void *rxbuffer, size_t nwords);
@@ -296,9 +301,10 @@ static void spi_recvblock(struct spi_dev_s *dev, void *buffer,
static const uint8_t g_csroffset[16] = static const uint8_t g_csroffset[16] =
{ {
0, /* the CS counts from 1 to 15 */ 0, /* the CS counts from 1 to 15 */
SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR0_OFFSET,
SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR0_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET,
SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR1_OFFSET, SAM_SPI_CSR2_OFFSET,
SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET, SAM_SPI_CSR2_OFFSET,
SAM_SPI_CSR3_OFFSET, SAM_SPI_CSR3_OFFSET, SAM_SPI_CSR3_OFFSET SAM_SPI_CSR3_OFFSET, SAM_SPI_CSR3_OFFSET, SAM_SPI_CSR3_OFFSET
}; };
#else #else
@@ -605,18 +611,18 @@ static inline void spi_flush(struct sam_spidev_s *spi)
* 2 0011 x011 1011 * 2 0011 x011 1011
* 3 0111 0111 0111 * 3 0111 0111 0111
* *
* The second mode, activated via CONFIG_SAMV7_SPI_CS_DECODING uses the four * The second mode, activated via CONFIG_SAMV7_SPI_CS_DECODING uses the
* chip select pins in "encoded mode" which means, that up to 15 slaves can * four chip select pins in "encoded mode" which means, that up to 15
* be selected via an additional multiplex electronic to decode the values * slaves can be selected via an additional multiplex electronic to decode
* represented by the four lines. In that mode this function returns the * the values represented by the four lines. In that mode this function
* Bitmask the chip select number represents itself. * returns the Bitmask the chip select number represents itself.
* *
* Input Parameters: * Input Parameters:
* spics - Device-specific state data * spics - Device-specific state data
* *
* Returned Value: * Returned Value:
* Bitmask the pcs part of the SPI data transfer register should be switched * Bitmask the pcs part of the SPI data transfer register should be
* to for the chip select used. * switched to for the chip select used.
* *
****************************************************************************/ ****************************************************************************/
@@ -648,8 +654,10 @@ static void spi_dma_sampleinit(struct sam_spics_s *spics)
{ {
/* Put contents of register samples into a known state */ /* Put contents of register samples into a known state */
memset(spics->rxdmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); memset(spics->rxdmaregs, 0xff,
memset(spics->txdmaregs, 0xff, DMA_NSAMPLES * sizeof(struct sam_dmaregs_s)); DMA_NSAMPLES * sizeof(struct sam_dmaregs_s));
memset(spics->txdmaregs, 0xff,
DMA_NSAMPLES * sizeof(struct sam_dmaregs_s));
/* Then get the initial samples */ /* Then get the initial samples */
@@ -681,6 +689,7 @@ static void spi_dma_sampledone(struct sam_spics_s *spics)
sam_dmasample(spics->txdma, &spics->txdmaregs[DMA_END_TRANSFER]); sam_dmasample(spics->txdma, &spics->txdmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */ /* Then dump the sampled DMA registers */
/* Initial register values */ /* Initial register values */
sam_dmadump(spics->txdma, &spics->txdmaregs[DMA_INITIAL], sam_dmadump(spics->txdma, &spics->txdmaregs[DMA_INITIAL],
@@ -804,8 +813,8 @@ static void spi_rxcallback(DMA_HANDLE handle, void *arg, int result)
spi_rxdma_sample(spics, DMA_CALLBACK); spi_rxdma_sample(spics, DMA_CALLBACK);
/* Report the result of the transfer only if the TX callback has not already /* Report the result of the transfer only if the TX callback has not
* reported an error. * already reported an error.
*/ */
if (spics->result == -EBUSY) if (spics->result == -EBUSY)
@@ -947,18 +956,18 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
{ {
spiinfo("cs=%d\n", spics->cs); spiinfo("cs=%d\n", spics->cs);
/* Before writing the TDR, the PCS field in the SPI_MR register must be set /* Before writing the TDR, the PCS field in the SPI_MR register must be
* in order to select a slave. * set in order to select a slave.
*/ */
regval = spi_getreg(spi, SAM_SPI_MR_OFFSET); regval = spi_getreg(spi, SAM_SPI_MR_OFFSET);
regval &= ~SPI_MR_PCS_MASK; regval &= ~SPI_MR_PCS_MASK;
/* SPI_VARSELECT means, that the ChipSelect for each device is set within /* SPI_VARSELECT means, that the ChipSelect for each device is set
* the transferred data (SAM_SPI_TDR) instead inside the mode register * within the transferred data (SAM_SPI_TDR) instead inside the mode
* (SAM_SPI_MR). * register (SAM_SPI_MR).
* In addition, the LASTXFER flag is also set within the transferred data * In addition, the LASTXFER flag is also set within the transferred
* (SAM_SPI_TDR) instead inside the control register (SAM_SPI_CR). * data (SAM_SPI_TDR) instead inside the control register (SAM_SPI_CR).
* (see spi_exchange) * (see spi_exchange)
*/ */
@@ -1022,7 +1031,8 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
return spics->actual; return spics->actual;
} }
/* Configure SPI to a frequency as close as possible to the requested frequency. /* Configure SPI to a frequency as close as possible to the requested
* frequency.
* *
* SPCK frequency = SPI_CLK / SCBR, or SCBR = SPI_CLK / frequency * SPCK frequency = SPI_CLK / SCBR, or SCBR = SPI_CLK / frequency
*/ */
@@ -1047,10 +1057,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK); regval &= ~(SPI_CSR_SCBR_MASK | SPI_CSR_DLYBS_MASK | SPI_CSR_DLYBCT_MASK);
regval |= scbr << SPI_CSR_SCBR_SHIFT; regval |= scbr << SPI_CSR_SCBR_SHIFT;
/* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid to the /* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid
* first valid SPCK transition. When DLYBS equals zero, the NPCS valid to SPCK * to the first valid SPCK transition. When DLYBS equals zero, the NPCS
* transition is 1/2 the SPCK clock period. Otherwise, the following equations * valid to SPCK transition is 1/2 the SPCK clock period. Otherwise, the
* determine the delay: * following equations determine the delay:
* *
* Delay Before SPCK = DLYBS / SPI_CLK * Delay Before SPCK = DLYBS / SPI_CLK
* *
@@ -1062,10 +1072,10 @@ static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency)
dlybs = SAM_SPI_CLOCK / 500000; dlybs = SAM_SPI_CLOCK / 500000;
regval |= dlybs << SPI_CSR_DLYBS_SHIFT; regval |= dlybs << SPI_CSR_DLYBS_SHIFT;
/* DLYBCT: Delay Between Consecutive Transfers. This field defines the delay /* DLYBCT: Delay Between Consecutive Transfers. This field defines the
* between two consecutive transfers with the same peripheral without removing * delay between two consecutive transfers with the same peripheral without
* the chip select. The delay is always inserted after each transfer and * removing the chip select. The delay is always inserted after each
* before removing the chip select if needed. * transfer and before removing the chip select if needed.
* *
* Delay Between Consecutive Transfers = (32 x DLYBCT) / SPI_CLK * Delay Between Consecutive Transfers = (32 x DLYBCT) / SPI_CLK
* *
@@ -1183,6 +1193,7 @@ static int spi_setdelay(struct spi_dev_s *dev, uint32_t startdelay,
* *
* DLYBCS = SPI_CLK * Delay * DLYBCS = SPI_CLK * Delay
*/ */
dlybcs = SAM_SPI_CLOCK; dlybcs = SAM_SPI_CLOCK;
dlybcs *= csdelay; dlybcs *= csdelay;
dlybcs /= 1000000000; dlybcs /= 1000000000;
@@ -1239,8 +1250,8 @@ static int spi_hwfeatures(struct spi_dev_s *dev, uint8_t features)
spi_putreg(spi, regval, offset); spi_putreg(spi, regval, offset);
} }
/* CS does not rise automatically after a transmission, also if the spi runs /* CS does not rise automatically after a transmission, also if the spi
* out of data (for a long time) * runs out of data (for a long time)
*/ */
if ((features & HWFEAT_FORCE_CS_ACTIVE_AFTER_TRANSFER) != 0) if ((features & HWFEAT_FORCE_CS_ACTIVE_AFTER_TRANSFER) != 0)
@@ -1416,7 +1427,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -1431,7 +1442,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -1554,11 +1565,11 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
data = 0xffff; data = 0xffff;
} }
/* SPI_VARSELECT means, that the ChipSelect for each device is set within /* SPI_VARSELECT means, that the ChipSelect for each device is set
* the transferred data (SAM_SPI_TDR) instead inside the mode register * within the transferred data (SAM_SPI_TDR) instead inside the mode
* (SAM_SPI_MR). * register (SAM_SPI_MR).
* In addition, the LASTXFER flag is also set within the transferred data * In addition, the LASTXFER flag is also set within the transferred
* (SAM_SPI_TDR) instead inside the control register (SAM_SPI_CR). * data (SAM_SPI_TDR) instead inside the control register (SAM_SPI_CR).
*/ */
#ifdef CONFIG_SAMV7_SPI_VARSELECT #ifdef CONFIG_SAMV7_SPI_VARSELECT
@@ -1743,7 +1754,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
* the DMA completes * the DMA completes
*/ */
up_invalidate_dcache((uintptr_t)rxbuffer, (uintptr_t)rxbuffer + nbytes); up_invalidate_dcache((uintptr_t)rxbuffer,
(uintptr_t)rxbuffer + nbytes);
/* Use normal RX memory incrementing. */ /* Use normal RX memory incrementing. */
@@ -1937,10 +1949,10 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
+94 -68
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arm/arm/src/stm32/stm32_i2s.c * arch/arm/src/stm32/stm32_i2s.c
* *
* Copyright (C) 2017 Gregory Nutt. All rights reserved. * Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Taras Drozdovskiy <t.drozdovskiy@gmail.com> * Author: Taras Drozdovskiy <t.drozdovskiy@gmail.com>
@@ -41,11 +41,12 @@
* up_spiinitialize()) are provided by common STM32 logic. To use this * up_spiinitialize()) are provided by common STM32 logic. To use this
* common SPI logic on your board: * common SPI logic on your board:
* *
* 1. Provide logic in stm32_boardinitialize() to configure I2S chip select * 1. Provide logic in stm32_boardinitialize() to configure I2S chip
* pins. * select pins.
* 2. Provide stm32_i2s2/3select() and stm32_i2s2/3status() functions in your * 2. Provide stm32_i2s2/3select() and stm32_i2s2/3status() functions in
* board-specific logic. These functions will perform chip selection and * your board-specific logic. These functions will perform chip
* status operations using GPIOs in the way your board is configured. * selection and status operations using GPIOs in the way your board
* is configured.
* 3. Add a calls to up_spiinitialize() in your low level application * 3. Add a calls to up_spiinitialize() in your low level application
* initialization logic * initialization logic
* 4. The handle returned by stm32_i2sdev_initialize() may then be used to * 4. The handle returned by stm32_i2sdev_initialize() may then be used to
@@ -136,7 +137,8 @@
# endif # endif
/* Configuration ********************************************************************/ /* Configuration ************************************************************/
/* I2S interrupts */ /* I2S interrupts */
#ifdef CONFIG_STM32_SPI_INTERRUPTS #ifdef CONFIG_STM32_SPI_INTERRUPTS
@@ -202,7 +204,8 @@
# error "Unknown STM32 DMA" # error "Unknown STM32 DMA"
#endif #endif
/* Debug *******************************************************************/ /* Debug ********************************************************************/
/* Check if SSC debug is enabled (non-standard.. no support in /* Check if SSC debug is enabled (non-standard.. no support in
* include/debug.h * include/debug.h
*/ */
@@ -316,10 +319,10 @@ struct stm32_i2s_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_STM32_I2S_REGDEBUG #ifdef CONFIG_STM32_I2S_REGDEBUG
bool wr; /* Last was a write */ bool wr; /* Last was a write */
uint32_t regaddr; /* Last address */ uint32_t regaddr; /* Last address */
uint16_t regval; /* Last value */ uint16_t regval; /* Last value */
int count; /* Number of times */ int count; /* Number of times */
#endif /* CONFIG_STM32_I2S_REGDEBUG */ #endif /* CONFIG_STM32_I2S_REGDEBUG */
}; };
@@ -330,8 +333,8 @@ struct stm32_i2s_s
/* Register helpers */ /* Register helpers */
#ifdef CONFIG_STM32_I2S_REGDEBUG #ifdef CONFIG_STM32_I2S_REGDEBUG
static bool i2s_checkreg(struct stm32_i2s_s *priv, bool wr, uint16_t regval, static bool i2s_checkreg(struct stm32_i2s_s *priv, bool wr,
uint32_t regaddr); uint16_t regval, uint32_t regaddr);
#else #else
# define i2s_checkreg(priv,wr,regval,regaddr) (false) # define i2s_checkreg(priv,wr,regval,regaddr) (false)
#endif #endif
@@ -406,14 +409,16 @@ static void i2s_rxdma_timeout(int argc, uint32_t arg);
static int i2s_rxdma_setup(struct stm32_i2s_s *priv); static int i2s_rxdma_setup(struct stm32_i2s_s *priv);
static void i2s_rx_worker(void *arg); static void i2s_rx_worker(void *arg);
static void i2s_rx_schedule(struct stm32_i2s_s *priv, int result); static void i2s_rx_schedule(struct stm32_i2s_s *priv, int result);
static void i2s_rxdma_callback(DMA_HANDLE handle, uint8_t result, void *arg); static void i2s_rxdma_callback(DMA_HANDLE handle, uint8_t result,
void *arg);
#endif #endif
#ifdef I2S_HAVE_TX #ifdef I2S_HAVE_TX
static void i2s_txdma_timeout(int argc, uint32_t arg); static void i2s_txdma_timeout(int argc, uint32_t arg);
static int i2s_txdma_setup(struct stm32_i2s_s *priv); static int i2s_txdma_setup(struct stm32_i2s_s *priv);
static void i2s_tx_worker(void *arg); static void i2s_tx_worker(void *arg);
static void i2s_tx_schedule(struct stm32_i2s_s *priv, int result); static void i2s_tx_schedule(struct stm32_i2s_s *priv, int result);
static void i2s_txdma_callback(DMA_HANDLE handle, uint8_t result, void *arg); static void i2s_txdma_callback(DMA_HANDLE handle, uint8_t result,
void *arg);
#endif #endif
/* I2S methods (and close friends) */ /* I2S methods (and close friends) */
@@ -422,13 +427,16 @@ static int i2s_checkwidth(struct stm32_i2s_s *priv, int bits);
static uint32_t stm32_i2s_rxsamplerate(struct i2s_dev_s *dev, uint32_t rate); static uint32_t stm32_i2s_rxsamplerate(struct i2s_dev_s *dev, uint32_t rate);
static uint32_t stm32_i2s_rxdatawidth(struct i2s_dev_s *dev, int bits); static uint32_t stm32_i2s_rxdatawidth(struct i2s_dev_s *dev, int bits);
static int stm32_i2s_receive(struct i2s_dev_s *dev, struct ap_buffer_s *apb, static int stm32_i2s_receive(struct i2s_dev_s *dev,
i2s_callback_t callback, void *arg, uint32_t timeout); struct ap_buffer_s *apb,
i2s_callback_t callback,
void *arg, uint32_t timeout);
static uint32_t stm32_i2s_txsamplerate(struct i2s_dev_s *dev, uint32_t rate); static uint32_t stm32_i2s_txsamplerate(struct i2s_dev_s *dev, uint32_t rate);
static uint32_t stm32_i2s_txdatawidth(struct i2s_dev_s *dev, int bits); static uint32_t stm32_i2s_txdatawidth(struct i2s_dev_s *dev, int bits);
static int stm32_i2s_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb, static int stm32_i2s_send(struct i2s_dev_s *dev,
i2s_callback_t callback, void *arg, struct ap_buffer_s *apb,
uint32_t timeout); i2s_callback_t callback, void *arg,
uint32_t timeout);
/* Initialization */ /* Initialization */
@@ -714,7 +722,8 @@ static struct stm32_buffer_s *i2s_buf_allocate(struct stm32_i2s_s *priv)
* *
****************************************************************************/ ****************************************************************************/
static void i2s_buf_free(struct stm32_i2s_s *priv, struct stm32_buffer_s *bfcontainer) static void i2s_buf_free(struct stm32_i2s_s *priv,
struct stm32_buffer_s *bfcontainer)
{ {
irqstate_t flags; irqstate_t flags;
@@ -814,6 +823,7 @@ static void i2s_rxdma_sampledone(struct stm32_i2s_s *priv, int result)
stm32_dmasample(priv->rx.dma, &priv->rx.dmaregs[DMA_END_TRANSFER]); stm32_dmasample(priv->rx.dma, &priv->rx.dmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */ /* Then dump the sampled DMA registers */
/* Initial register values */ /* Initial register values */
stm32_dmadump(priv->rx.dma, &priv->rx.dmaregs[DMA_INITIAL], stm32_dmadump(priv->rx.dma, &priv->rx.dmaregs[DMA_INITIAL],
@@ -879,6 +889,7 @@ static void i2s_txdma_sampledone(struct stm32_i2s_s *priv, int result)
stm32_dmasample(priv->tx.dma, &priv->tx.dmaregs[DMA_END_TRANSFER]); stm32_dmasample(priv->tx.dma, &priv->tx.dmaregs[DMA_END_TRANSFER]);
/* Then dump the sampled DMA registers */ /* Then dump the sampled DMA registers */
/* Initial register values */ /* Initial register values */
stm32_dmadump(priv->tx.dma, &priv->tx.dmaregs[DMA_INITIAL], stm32_dmadump(priv->tx.dma, &priv->tx.dmaregs[DMA_INITIAL],
@@ -1115,9 +1126,9 @@ static void i2s_rx_worker(void *arg)
DEBUGASSERT(priv); DEBUGASSERT(priv);
/* When the transfer was started, the active buffer containers were removed /* When the transfer was started, the active buffer containers were removed
* from the rx.pend queue and saved in the rx.act queue. We get here when the * from the rx.pend queue and saved in the rx.act queue. We get here when
* DMA is finished... either successfully, with a DMA error, or with a DMA * the DMA is finished... either successfully, with a DMA error, or with a
* timeout. * DMA timeout.
* *
* In any case, the buffer containers in rx.act will be moved to the end * In any case, the buffer containers in rx.act will be moved to the end
* of the rx.done queue and rx.act queue will be emptied before this worker * of the rx.done queue and rx.act queue will be emptied before this worker
@@ -1302,7 +1313,8 @@ static void i2s_rxdma_callback(DMA_HANDLE handle, uint8_t result, void *arg)
/* REVISIT: We would like to the next DMA started here so that we do not /* REVISIT: We would like to the next DMA started here so that we do not
* get audio glitches at the boundaries between DMA transfers. * get audio glitches at the boundaries between DMA transfers.
* Unfortunately, we cannot call stm32_dmasetup() from an interrupt handler! * Unfortunately, we cannot call stm32_dmasetup() from an interrupt
* handler!
*/ */
/* Then schedule completion of the transfer to occur on the worker thread */ /* Then schedule completion of the transfer to occur on the worker thread */
@@ -1424,9 +1436,10 @@ static int i2s_txdma_setup(struct stm32_i2s_s *priv)
/* Configure DMA stream */ /* Configure DMA stream */
stm32_dmasetup(priv->tx.dma, priv->base + STM32_SPI_DR_OFFSET, stm32_dmasetup(priv->tx.dma, priv->base + STM32_SPI_DR_OFFSET,
(uint32_t)samp, nbytes/2, priv->txccr); (uint32_t)samp, nbytes / 2, priv->txccr);
/* Increment the DMA timeout */ /* Increment the DMA timeout */
if (bfcontainer->timeout > 0) if (bfcontainer->timeout > 0)
{ {
timeout += bfcontainer->timeout; timeout += bfcontainer->timeout;
@@ -1458,7 +1471,8 @@ static int i2s_txdma_setup(struct stm32_i2s_s *priv)
/* Enable the transmitter */ /* Enable the transmitter */
i2s_putreg(priv, STM32_SPI_CR2_OFFSET, i2s_getreg(priv, STM32_SPI_CR2_OFFSET) | SPI_CR2_TXDMAEN); i2s_putreg(priv, STM32_SPI_CR2_OFFSET,
i2s_getreg(priv, STM32_SPI_CR2_OFFSET) | SPI_CR2_TXDMAEN);
/* Start a watchdog to catch DMA timeouts */ /* Start a watchdog to catch DMA timeouts */
@@ -1507,9 +1521,9 @@ static void i2s_tx_worker(void *arg)
DEBUGASSERT(priv); DEBUGASSERT(priv);
/* When the transfer was started, the active buffer containers were removed /* When the transfer was started, the active buffer containers were removed
* from the tx.pend queue and saved in the tx.act queue. We get here when the * from the tx.pend queue and saved in the tx.act queue. We get here when
* DMA is finished... either successfully, with a DMA error, or with a DMA * the DMA is finished... either successfully, with a DMA error, or with a
* timeout. * DMA timeout.
* *
* In any case, the buffer containers in tx.act will be moved to the end * In any case, the buffer containers in tx.act will be moved to the end
* of the tx.done queue and tx.act will be emptied before this worker is * of the tx.done queue and tx.act will be emptied before this worker is
@@ -1682,7 +1696,8 @@ static void i2s_txdma_callback(DMA_HANDLE handle, uint8_t result, void *arg)
/* REVISIT: We would like to the next DMA started here so that we do not /* REVISIT: We would like to the next DMA started here so that we do not
* get audio glitches at the boundaries between DMA transfers. * get audio glitches at the boundaries between DMA transfers.
* Unfortunately, we cannot call stm32_dmasetup() from an interrupt handler! * Unfortunately, we cannot call stm32_dmasetup() from an interrupt
* handler!
*/ */
/* Then schedule completion of the transfer to occur on the worker thread */ /* Then schedule completion of the transfer to occur on the worker thread */
@@ -1906,8 +1921,8 @@ static int stm32_i2s_receive(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
flags = enter_critical_section(); flags = enter_critical_section();
sq_addlast((sq_entry_t *)bfcontainer, &priv->rx.pend); sq_addlast((sq_entry_t *)bfcontainer, &priv->rx.pend);
/* Then start the next transfer. If there is already a transfer in progress, /* Then start the next transfer. If there is already a transfer in
* then this will do nothing. * progress, then this will do nothing.
*/ */
ret = i2s_rxdma_setup(priv); ret = i2s_rxdma_setup(priv);
@@ -1930,12 +1945,12 @@ errout_with_exclsem:
static int roundf(float num) static int roundf(float num)
{ {
if (((int)(num + 0.5f)) > num) if (((int)(num + 0.5f)) > num)
{ {
return num + 1; return num + 1;
} }
return num; return num;
} }
/**************************************************************************** /****************************************************************************
@@ -1999,7 +2014,7 @@ static uint32_t stm32_i2s_txdatawidth(struct i2s_dev_s *dev, int bits)
struct stm32_i2s_s *priv = (struct stm32_i2s_s *)dev; struct stm32_i2s_s *priv = (struct stm32_i2s_s *)dev;
int ret; int ret;
i2sinfo("Data width bits of tx = %d\n",bits); i2sinfo("Data width bits of tx = %d\n", bits);
DEBUGASSERT(priv && bits > 1); DEBUGASSERT(priv && bits > 1);
/* Check if this is a bit width that we are configured to handle */ /* Check if this is a bit width that we are configured to handle */
@@ -2112,8 +2127,8 @@ static int stm32_i2s_send(struct i2s_dev_s *dev, struct ap_buffer_s *apb,
flags = enter_critical_section(); flags = enter_critical_section();
sq_addlast((sq_entry_t *)bfcontainer, &priv->tx.pend); sq_addlast((sq_entry_t *)bfcontainer, &priv->tx.pend);
/* Then start the next transfer. If there is already a transfer in progress, /* Then start the next transfer. If there is already a transfer in
* then this will do nothing. * progress, then this will do nothing.
*/ */
ret = i2s_txdma_setup(priv); ret = i2s_txdma_setup(priv);
@@ -2156,7 +2171,10 @@ static uint32_t i2s_mckdivider(struct stm32_i2s_s *priv)
uint32_t bitrate; uint32_t bitrate;
uint32_t regval; uint32_t regval;
uint16_t pllr = 5, plln = 256, div = 12, odd = 1; uint16_t pllr = 5;
uint16_t plln = 256;
uint16_t div = 12;
uint16_t odd = 1;
DEBUGASSERT(priv && priv->samplerate >= 0 && priv->datalen > 0); DEBUGASSERT(priv && priv->samplerate >= 0 && priv->datalen > 0);
@@ -2169,39 +2187,43 @@ static uint32_t i2s_mckdivider(struct stm32_i2s_s *priv)
} }
else else
{ {
int R, n, Od; int R;
int Napprox; int n;
int od;
int napprox;
int diff; int diff;
int diff_min = 500000000; int diff_min = 500000000;
for (Od = 0; Od <= 1; ++Od) for (od = 0; od <= 1; ++od)
{ {
for (R = 2; R <= 7; ++R) for (R = 2; R <= 7; ++R)
{ {
for (n = 2; n <= 256; ++n) for (n = 2; n <= 256; ++n)
{ {
Napprox = roundf(priv->samplerate / 1000000.0f * (8 * 32 * R * (2 * n + Od))); napprox = roundf(priv->samplerate / 1000000.0f *
if ((Napprox > 432) || (Napprox < 50)) (8 * 32 * R * (2 * n + od)));
{ if ((napprox > 432) || (napprox < 50))
continue; {
} continue;
}
diff = abs(priv->samplerate - 1000000 * Napprox / (8 * 32 * R * (2 * n + Od))); diff = abs(priv->samplerate - 1000000 * napprox /
if (diff_min > diff) (8 * 32 * R * (2 * n + od)));
{ if (diff_min > diff)
diff_min = diff; {
plln = Napprox; diff_min = diff;
pllr = R; plln = napprox;
div = n; pllr = R;
odd = Od; div = n;
} odd = od;
}
} }
} }
} }
/* Calculate the new bitrate in Hz */ /* Calculate the new bitrate in Hz */
bitrate = priv->samplerate * priv->datalen; bitrate = priv->samplerate * priv->datalen;
} }
/* Configure MCK divider */ /* Configure MCK divider */
@@ -2216,7 +2238,8 @@ static uint32_t i2s_mckdivider(struct stm32_i2s_s *priv)
/* PLLI2S clock used as I2S clock source */ /* PLLI2S clock used as I2S clock source */
putreg32(((getreg32(STM32_RCC_CFGR)) & (~RCC_CFGR_I2SSRC)), STM32_RCC_CFGR); putreg32(((getreg32(STM32_RCC_CFGR)) & (~RCC_CFGR_I2SSRC)),
STM32_RCC_CFGR);
regval = (pllr << 28) | (plln << 6); regval = (pllr << 28) | (plln << 6);
putreg32(regval, STM32_RCC_PLLI2SCFGR); putreg32(regval, STM32_RCC_PLLI2SCFGR);
@@ -2230,8 +2253,9 @@ static uint32_t i2s_mckdivider(struct stm32_i2s_s *priv)
i2s_putreg(priv, STM32_SPI_I2SCFGR_OFFSET, i2s_putreg(priv, STM32_SPI_I2SCFGR_OFFSET,
SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SCFG_MTX | SPI_I2SCFGR_I2SE); SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SCFG_MTX | SPI_I2SCFGR_I2SE);
putreg32(((getreg32(STM32_DMA1_HIFCR)) | 0x80000000 /* DMA_HIFCR_CTCIF7 */), /* putreg32((getreg32(STM32_DMA1_HIFCR) | DMA_HIFCR_CTCIF7), STM32_DMA1_HIFCR); */
STM32_DMA1_HIFCR);
putreg32((getreg32(STM32_DMA1_HIFCR) | 0x80000000), STM32_DMA1_HIFCR);
return bitrate; return bitrate;
#else #else
@@ -2258,7 +2282,9 @@ static int i2s_dma_flags(struct stm32_i2s_s *priv)
switch (priv->datalen) switch (priv->datalen)
{ {
case 8: case 8:
/* Reconfigure the RX DMA (and TX DMA if applicable) */ /* Reconfigure the RX DMA (and TX DMA if applicable) */
priv->rxccr = SPI_RXDMA8_CONFIG; priv->rxccr = SPI_RXDMA8_CONFIG;
priv->txccr = SPI_TXDMA8_CONFIG; priv->txccr = SPI_TXDMA8_CONFIG;
break; break;
@@ -2429,7 +2455,7 @@ static void i2s2_configure(struct stm32_i2s_s *priv)
* select pins must be selected by board-specific logic. * select pins must be selected by board-specific logic.
*/ */
priv->base = STM32_I2S2_BASE; priv->base = STM32_I2S2_BASE;
#ifdef CONFIG_STM32_I2S2_RX #ifdef CONFIG_STM32_I2S2_RX
priv->rxenab = true; priv->rxenab = true;
@@ -2541,7 +2567,7 @@ static void i2s3_configure(struct stm32_i2s_s *priv)
* Public Functions * Public Functions
****************************************************************************/ ****************************************************************************/
/************************************************************************************ /****************************************************************************
* Name: stm32_i2sdev_initialize * Name: stm32_i2sdev_initialize
* *
* Description: * Description:
@@ -2553,7 +2579,7 @@ static void i2s3_configure(struct stm32_i2s_s *priv)
* Returned Value: * Returned Value:
* Valid I2S device structure reference on success; a NULL on failure * Valid I2S device structure reference on success; a NULL on failure
* *
************************************************************************************/ ****************************************************************************/
FAR struct i2s_dev_s *stm32_i2sdev_initialize(int port) FAR struct i2s_dev_s *stm32_i2sdev_initialize(int port)
{ {
+15 -11
View File
@@ -232,7 +232,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static int spi_hwfeatures(FAR struct spi_dev_s *dev, static int spi_hwfeatures(FAR struct spi_dev_s *dev,
spi_hwfeatures_t features); spi_hwfeatures_t features);
#endif #endif
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords); FAR void *rxbuffer, size_t nwords);
#ifdef CONFIG_SPI_TRIGGER #ifdef CONFIG_SPI_TRIGGER
@@ -1508,16 +1508,16 @@ static int spi_hwfeatures(FAR struct spi_dev_s *dev, spi_hwfeatures_t features)
* *
************************************************************************************/ ************************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
uint32_t regval; uint32_t regval;
uint16_t ret; uint32_t ret;
DEBUGASSERT(priv && priv->spibase); DEBUGASSERT(priv && priv->spibase);
spi_writeword(priv, wd); spi_writeword(priv, (uint32_t)(wd & 0xffff));
ret = spi_readword(priv); ret = (uint32_t)spi_readword(priv);
/* Check and clear any error flags (Reading from the SR clears the error flags) */ /* Check and clear any error flags (Reading from the SR clears the error flags) */
@@ -1545,7 +1545,8 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - the length of data to be exchaned in units of words. * nwords - the length of data to be exchaned in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1592,7 +1593,7 @@ static void spi_exchange_nodma(FAR struct spi_dev_s *dev, FAR const void *txbuff
/* Exchange one word */ /* Exchange one word */
word = spi_send(dev, word); word = (uint16_t)spi_send(dev, (uint32_t)word);
/* Is there a buffer to receive the return value? */ /* Is there a buffer to receive the return value? */
@@ -1625,7 +1626,7 @@ static void spi_exchange_nodma(FAR struct spi_dev_s *dev, FAR const void *txbuff
/* Exchange one word */ /* Exchange one word */
word = (uint8_t)spi_send(dev, (uint16_t)word); word = (uint8_t)spi_send(dev, (uint32_t)word);
/* Is there a buffer to receive the return value? */ /* Is there a buffer to receive the return value? */
@@ -1651,7 +1652,8 @@ static void spi_exchange_nodma(FAR struct spi_dev_s *dev, FAR const void *txbuff
* nwords - the length of data to be exchanged in units of words. * nwords - the length of data to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1797,7 +1799,8 @@ static int spi_trigger(FAR struct spi_dev_s *dev)
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1826,7 +1829,8 @@ static void spi_sndblock(FAR struct spi_dev_s *dev,
* nwords - 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 * of words. The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+5 -1
View File
@@ -1,5 +1,5 @@
/************************************************************************************ /************************************************************************************
* arm/arm/src/stm32f7/stm32_tim.c * arch/arm/src/stm32f7/stm32_tim.c
* *
* Copyright (C) 2011 Uros Platise. All rights reserved. * Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu> * Author: Uros Platise <uros.platise@isotel.eu>
@@ -712,6 +712,7 @@ static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t m
break; break;
case STM32_TIM_MODE_UPDOWN: case STM32_TIM_MODE_UPDOWN:
/* Our default: Interrupts are generated on compare, when counting down */ /* Our default: Interrupts are generated on compare, when counting down */
val |= ATIM_CR1_CENTER1; val |= ATIM_CR1_CENTER1;
@@ -1165,6 +1166,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel
break; break;
#endif #endif
} }
return OK; return OK;
} }
@@ -1190,6 +1192,7 @@ static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev, uint8_t channel
default: default:
return -EINVAL; return -EINVAL;
} }
return OK; return OK;
} }
@@ -1248,6 +1251,7 @@ struct stm32_tim_priv_s stm32_tim1_priv =
.base = STM32_TIM1_BASE, .base = STM32_TIM1_BASE,
}; };
#endif #endif
#ifdef CONFIG_STM32F7_TIM2 #ifdef CONFIG_STM32F7_TIM2
struct stm32_tim_priv_s stm32_tim2_priv = struct stm32_tim_priv_s stm32_tim2_priv =
{ {
File diff suppressed because it is too large Load Diff
+17 -12
View File
@@ -1,5 +1,5 @@
/*************************************************************************** /****************************************************************************
* arm/arm/src/stm32h7/stm32_tim.c * arch/arm/src/stm32h7/stm32_tim.c
* *
* Copyright (C) 2011 Uros Platise. All rights reserved. * Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu> * Author: Uros Platise <uros.platise@isotel.eu>
@@ -64,9 +64,9 @@
#include "stm32_gpio.h" #include "stm32_gpio.h"
#include "stm32_tim.h" #include "stm32_tim.h"
/*************************************************************************** /****************************************************************************
* Private Types * Private Types
***************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
@@ -274,19 +274,23 @@ struct stm32_tim_priv_s
/* Timer methods */ /* Timer methods */
static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev, stm32_tim_mode_t mode); static int stm32_tim_setmode(FAR struct stm32_tim_dev_s *dev,
static int stm32_tim_setclock(FAR struct stm32_tim_dev_s *dev, uint32_t freq); stm32_tim_mode_t mode);
static int stm32_tim_setclock(FAR struct stm32_tim_dev_s *dev,
uint32_t freq);
static void stm32_tim_setperiod(FAR struct stm32_tim_dev_s *dev, static void stm32_tim_setperiod(FAR struct stm32_tim_dev_s *dev,
uint32_t period); uint32_t period);
static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev, uint8_t channel, static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev,
stm32_tim_channel_t mode); uint8_t channel, stm32_tim_channel_t mode);
static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev, uint8_t channel, static int stm32_tim_setcompare(FAR struct stm32_tim_dev_s *dev,
uint32_t compare); uint8_t channel, uint32_t compare);
static int stm32_tim_getcapture(FAR struct stm32_tim_dev_s *dev, uint8_t channel); static int stm32_tim_getcapture(FAR struct stm32_tim_dev_s *dev,
uint8_t channel);
static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, xcpt_t handler, static int stm32_tim_setisr(FAR struct stm32_tim_dev_s *dev, xcpt_t handler,
void *arg, int source); void *arg, int source);
static void stm32_tim_enableint(FAR struct stm32_tim_dev_s *dev, int source); static void stm32_tim_enableint(FAR struct stm32_tim_dev_s *dev, int source);
static void stm32_tim_disableint(FAR struct stm32_tim_dev_s *dev, int source); static void stm32_tim_disableint(FAR struct stm32_tim_dev_s *dev,
int source);
static void stm32_tim_ackint(FAR struct stm32_tim_dev_s *dev, int source); static void stm32_tim_ackint(FAR struct stm32_tim_dev_s *dev, int source);
/**************************************************************************** /****************************************************************************
@@ -1219,6 +1223,7 @@ static int stm32_tim_setchannel(FAR struct stm32_tim_dev_s *dev,
break; break;
#endif #endif
} }
return OK; return OK;
} }
+1 -1
View File
@@ -1,5 +1,5 @@
/************************************************************************************ /************************************************************************************
* arm/arm/src/stm3l42/stm32l4_lptim.c * arch/arm/src/stm3l42/stm32l4_lptim.c
* *
* Copyright (C) 2011 Uros Platise. All rights reserved. * Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu> * Author: Uros Platise <uros.platise@isotel.eu>
File diff suppressed because it is too large Load Diff
+11 -7
View File
@@ -1,5 +1,5 @@
/************************************************************************************ /************************************************************************************
* arm/arm/src/stm32l4/stm32l4_tim.c * arch/arm/src/stm32l4/stm32l4_tim.c
* *
* Copyright (C) 2011 Uros Platise. All rights reserved. * Copyright (C) 2011 Uros Platise. All rights reserved.
* Author: Uros Platise <uros.platise@isotel.eu> * Author: Uros Platise <uros.platise@isotel.eu>
@@ -68,6 +68,7 @@
************************************************************************************/ ************************************************************************************/
/* Configuration ********************************************************************/ /* Configuration ********************************************************************/
/* Timer devices may be used for different purposes. Such special purposes include: /* Timer devices may be used for different purposes. Such special purposes include:
* *
* - To generate modulated outputs for such things as motor control. If * - To generate modulated outputs for such things as motor control. If
@@ -208,8 +209,8 @@
#endif #endif
#endif #endif
/* This module then only compiles if there are enabled timers that are not intended for /* This module then only compiles if there are enabled timers that are not
* some other purpose. * intended for some other purpose.
*/ */
#if defined(CONFIG_STM32L4_TIM1) || defined(CONFIG_STM32L4_TIM2) || \ #if defined(CONFIG_STM32L4_TIM1) || defined(CONFIG_STM32L4_TIM2) || \
@@ -604,7 +605,9 @@ static int stm32l4_tim_setmode(FAR struct stm32l4_tim_dev_s *dev,
case STM32L4_TIM_MODE_UPDOWN: case STM32L4_TIM_MODE_UPDOWN:
val |= ATIM_CR1_CENTER1; val |= ATIM_CR1_CENTER1;
// Our default: Interrupts are generated on compare, when counting down
/* Our default: Interrupts are generated on compare, when counting down */
break; break;
case STM32L4_TIM_MODE_PULSE: case STM32L4_TIM_MODE_PULSE:
@@ -892,10 +895,10 @@ static uint32_t stm32l4_tim_getcounter(FAR struct stm32l4_tim_dev_s *dev)
return counter; return counter;
default: default:
return counter & 0x0000FFFF; return counter & 0x0000ffff;
} }
#else #else
return counter & 0x0000FFFF; return counter & 0x0000ffff;
#endif #endif
} }
@@ -951,7 +954,8 @@ static int stm32l4_tim_setchannel(FAR struct stm32l4_tim_dev_s *dev,
break; break;
case STM32L4_TIM_CH_OUTPWM: case STM32L4_TIM_CH_OUTPWM:
ccmr_val = (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) + ATIM_CCMR1_OC1PE; ccmr_val = (ATIM_CCMR_MODE_PWM1 << ATIM_CCMR1_OC1M_SHIFT) +
ATIM_CCMR1_OC1PE;
ccer_val |= ATIM_CCER_CC1E << (channel << 2); ccer_val |= ATIM_CCER_CC1E << (channel << 2);
break; break;
+65 -50
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/tiva/common/tiva_ssi.c * arch/arm/src/tiva/common/tiva_ssi.c
* *
* Copyright (C) 2009-2010, 2014, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2009-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -75,8 +75,8 @@
#endif #endif
/* How many SSI modules does this chip support? The LM3S6918 supports 2 SSI /* How many SSI modules does this chip support? The LM3S6918 supports 2 SSI
* modules, the LM3S6965 and LM3S8962 support 1 module (others may support more than 2-- in * modules, the LM3S6965 and LM3S8962 support 1 module (others may support
* such case, the following must be expanded). * more than 2-- in such case, the following must be expanded).
*/ */
#if TIVA_NSSI < 1 #if TIVA_NSSI < 1
@@ -229,9 +229,9 @@ struct tiva_ssidev_s
/* SSI register access */ /* SSI register access */
static inline uint32_t ssi_getreg(struct tiva_ssidev_s *priv, static inline uint32_t ssi_getreg(struct tiva_ssidev_s *priv,
unsigned int offset); unsigned int offset);
static inline void ssi_putreg(struct tiva_ssidev_s *priv, unsigned int offset, static inline void ssi_putreg(struct tiva_ssidev_s *priv,
uint32_t value); unsigned int offset, uint32_t value);
/* Misc helpers */ /* Misc helpers */
@@ -281,7 +281,7 @@ static void ssi_setmodeinternal(struct tiva_ssidev_s *priv,
static void ssi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void ssi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static void ssi_setbitsinternal(struct tiva_ssidev_s *priv, int nbits); static void ssi_setbitsinternal(struct tiva_ssidev_s *priv, int nbits);
static void ssi_setbits(FAR struct spi_dev_s *dev, int nbits); static void ssi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t ssi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t ssi_send(FAR struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
static void ssi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void ssi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
FAR void *rxbuffer, size_t nwords); FAR void *rxbuffer, size_t nwords);
@@ -434,8 +434,8 @@ static inline void ssi_putreg(struct tiva_ssidev_s *priv,
* Name: ssi_disable * Name: ssi_disable
* *
* Description: * Description:
* Disable SSI operation. NOTE: The SSI must be disabled before any control * Disable SSI operation. NOTE: The SSI must be disabled before any
* registers can be re-programmed. * control registers can be re-programmed.
* *
* Input Parameters: * Input Parameters:
* priv - Device-specific state data * priv - Device-specific state data
@@ -511,10 +511,10 @@ static void ssi_semtake(sem_t *sem)
* Name: ssi_txnull, ssi_txuint16, and ssi_txuint8 * Name: ssi_txnull, ssi_txuint16, and ssi_txuint8
* *
* Description: * Description:
* Transfer all ones, a uint8_t, or uint16_t to Tx FIFO and update the txbuffer * Transfer all ones, a uint8_t, or uint16_t to Tx FIFO and update the
* pointer appropriately. The selected function dependes on (1) if there * txbuffer pointer appropriately. The selected function dependes on (1)
* is a source txbuffer provided, and (2) if the number of bits per * if there is a source txbuffer provided, and (2) if the number of bits
* word is <=8 or >8. * per word is <=8 or >8.
* *
* Input Parameters: * Input Parameters:
* priv - Device-specific state data * priv - Device-specific state data
@@ -656,6 +656,7 @@ static inline int ssi_performtx(struct tiva_ssidev_s *priv)
priv->ntxwords--; priv->ntxwords--;
return 1; return 1;
} }
return 0; return 0;
} }
@@ -684,7 +685,9 @@ static int ssi_performtx(struct tiva_ssidev_s *priv)
* FIFO to CONFIG_SSI_TXLIMIT. Otherwise, we could * FIFO to CONFIG_SSI_TXLIMIT. Otherwise, we could
* overrun the Rx FIFO on a very fast SSI bus. * overrun the Rx FIFO on a very fast SSI bus.
*/ */
for (; ntxd < priv->ntxwords && ntxd < CONFIG_SSI_TXLIMIT && !ssi_txfifofull(priv); ntxd++)
for (; ntxd < priv->ntxwords && ntxd < CONFIG_SSI_TXLIMIT &&
!ssi_txfifofull(priv); ntxd++)
#else #else
for (; ntxd < priv->ntxwords && !ssi_txfifofull(priv); ntxd++) for (; ntxd < priv->ntxwords && !ssi_txfifofull(priv); ntxd++)
#endif #endif
@@ -721,9 +724,11 @@ static int ssi_performtx(struct tiva_ssidev_s *priv)
regval &= ~(SSI_IM_TX | SSI_RIS_ROR); regval &= ~(SSI_IM_TX | SSI_RIS_ROR);
} }
ssi_putreg(priv, TIVA_SSI_IM_OFFSET, regval); ssi_putreg(priv, TIVA_SSI_IM_OFFSET, regval);
#endif /* CONFIG_SSI_POLLWAIT */ #endif /* CONFIG_SSI_POLLWAIT */
} }
return ntxd; return ntxd;
} }
@@ -794,6 +799,7 @@ static inline void ssi_performrx(struct tiva_ssidev_s *priv)
regval &= ~(SSI_IM_RX | SSI_IM_RT); regval &= ~(SSI_IM_RX | SSI_IM_RT);
} }
ssi_putreg(priv, TIVA_SSI_IM_OFFSET, regval); ssi_putreg(priv, TIVA_SSI_IM_OFFSET, regval);
#endif /* CONFIG_SSI_POLLWAIT */ #endif /* CONFIG_SSI_POLLWAIT */
} }
@@ -809,9 +815,9 @@ static inline void ssi_performrx(struct tiva_ssidev_s *priv)
* txbuffer - The buffer of data to send to the device (may be NULL). * 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). * rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface * nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of uint8_t's; * uses <= 8 bits per word, then this is the number of
* if the interface uses >8 bits per word, then this is the * uint8_t's; if the interface uses >8 bits per word, then this
* number of uint16_t's * is the number of uint16_t's
* *
* Returned Value: * Returned Value:
* 0: success, <0:Negated error number on failure * 0: success, <0:Negated error number on failure
@@ -987,9 +993,9 @@ static inline struct tiva_ssidev_s *ssi_mapirq(int irq)
* txbuffer - The buffer of data to send to the device (may be NULL). * 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). * rxbuffer - The buffer to receive data from the device (may be NULL).
* nwords - The total number of words to be exchanged. If the interface * nwords - The total number of words to be exchanged. If the interface
* uses <= 8 bits per word, then this is the number of uint8_t's; * uses <= 8 bits per word, then this is the number of
* if the interface uses >8 bits per word, then this is the * uint8_t's; if the interface uses >8 bits per word, then this
* number of uint16_t's * is the number of uint16_t's
* *
* Returned Value: * Returned Value:
* 0: success, <0:Negated error number on failure * 0: success, <0:Negated error number on failure
@@ -1127,25 +1133,25 @@ static uint32_t ssi_setfrequencyinternal(struct tiva_ssidev_s *priv,
{ {
/* "The serial bit rate is derived by dividing down the input clock /* "The serial bit rate is derived by dividing down the input clock
* (FSysClk). The clock is first divided by an even prescale value * (FSysClk). The clock is first divided by an even prescale value
* CPSDVSR from 2 to 254, which is programmed in the SSI Clock Prescale * CPSDVSR from 2 to 254, which is programmed in the SSI Clock
* (SSI_CPSR) register ... The clock is further divided by a value * Prescale (SSI_CPSR) register ... The clock is further divided by
* from 1 to 256, which is 1 + SCR, where SCR is the value programmed * a value from 1 to 256, which is 1 + SCR, where SCR is the value
* i n the SSI Control0 (SSICR0) register ... * programmed in the SSI Control0 (SSICR0) register ...
* *
* "The frequency of the output clock SSIClk is defined by: * "The frequency of the output clock SSIClk is defined by:
* *
* "SSIClk = FSysClk / (CPSDVSR * (1 + SCR)) * "SSIClk = FSysClk / (CPSDVSR * (1 + SCR))
* *
* "Note: Although the SSIClk transmit clock can theoretically be 25 MHz, * "Note: Although the SSIClk transmit clock can theoretically be
* the module may not be able to operate at that speed. For master mode, * 25 MHz, the module may not be able to operate at that speed. For
* the system clock must be at least two times faster than the SSIClk. * master mode, the system clock must be at least two times faster
* For slave mode, the system clock must be at least 12 times faster * than the SSIClk. For slave mode, the system clock must be at
* than the SSIClk." * least 12 times faster than the SSIClk."
*/ */
if (frequency > SYSCLK_FREQUENCY/2) if (frequency > SYSCLK_FREQUENCY / 2)
{ {
frequency = SYSCLK_FREQUENCY/2; frequency = SYSCLK_FREQUENCY / 2;
} }
/* Find optimal values for CPSDVSR and SCR. This loop is inefficient, /* Find optimal values for CPSDVSR and SCR. This loop is inefficient,
@@ -1194,8 +1200,8 @@ static uint32_t ssi_setfrequencyinternal(struct tiva_ssidev_s *priv,
actual = SYSCLK_FREQUENCY / (cpsdvsr * (scr + 1)); actual = SYSCLK_FREQUENCY / (cpsdvsr * (scr + 1));
/* Save the frequency selection so that subsequent reconfigurations will be /* Save the frequency selection so that subsequent reconfigurations
* faster. * will be faster.
*/ */
priv->frequency = frequency; priv->frequency = frequency;
@@ -1205,7 +1211,8 @@ static uint32_t ssi_setfrequencyinternal(struct tiva_ssidev_s *priv,
return priv->actual; return priv->actual;
} }
static uint32_t ssi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t ssi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
struct tiva_ssidev_s *priv = (struct tiva_ssidev_s *)dev; struct tiva_ssidev_s *priv = (struct tiva_ssidev_s *)dev;
uint32_t enable; uint32_t enable;
@@ -1237,7 +1244,8 @@ static uint32_t ssi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
* *
****************************************************************************/ ****************************************************************************/
static void ssi_setmodeinternal(struct tiva_ssidev_s *priv, enum spi_mode_e mode) static void ssi_setmodeinternal(struct tiva_ssidev_s *priv,
enum spi_mode_e mode)
{ {
uint32_t modebits; uint32_t modebits;
uint32_t regval; uint32_t regval;
@@ -1363,10 +1371,10 @@ static void ssi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t ssi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t ssi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
struct tiva_ssidev_s *priv = (struct tiva_ssidev_s *)dev; struct tiva_ssidev_s *priv = (struct tiva_ssidev_s *)dev;
uint16_t response = 0; uint32_t response = 0;
ssi_transfer(priv, &wd, &response, 1); ssi_transfer(priv, &wd, &response, 1);
return response; return response;
@@ -1385,7 +1393,8 @@ static uint16_t ssi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* nwords - the length of data that to be exchanged in units of words. * nwords - the length of data that to be exchanged in units of words.
* The wordsize is determined by the number of bits-per-word * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1413,7 +1422,8 @@ static void ssi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
* nwords - 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 * The wordsize is determined by the number of bits-per-word
* selected for the SPI interface. If nbits <= 8, the data is * selected for the SPI interface. If nbits <= 8, the data is
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * packed into uint8_t's; if nbits >8, the data is packed into
* uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1439,9 +1449,10 @@ static void ssi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into uint16_t's * the data is packed into uint8_t's; if nbits >8, the data is
* packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1470,10 +1481,10 @@ static void ssi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
* prior to calling this function. Specifically: GPIOs should have * prior to calling this function. Specifically: GPIOs should have
* been configured for output, and all chip selects disabled. * been configured for output, and all chip selects disabled.
* *
* One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select. However, * One GPIO, SS (PB2 on the eZ8F091) is reserved as a chip select.
* If multiple devices on on the bus, then multiple chip selects will be * However, if multiple devices on on the bus, then multiple chip selects
* required. Therefore, all GPIO chip management is deferred to board- * will be required. Therefore, all GPIO chip management is deferred to
* specific logic. * board-specific logic.
* *
* Input Parameters: * Input Parameters:
* Port number (for hardware that has multiple SSI interfaces) * Port number (for hardware that has multiple SSI interfaces)
@@ -1497,6 +1508,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
{ {
#ifdef CONFIG_TIVA_SSI0 #ifdef CONFIG_TIVA_SSI0
case 0: case 0:
/* Select SSI0 */ /* Select SSI0 */
priv = &g_ssidev[SSI0_NDX]; priv = &g_ssidev[SSI0_NDX];
@@ -1520,7 +1532,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
*/ */
tiva_configgpio(GPIO_SSI0_CLK); /* PA2: SSI0 clock (SSI0Clk) */ tiva_configgpio(GPIO_SSI0_CLK); /* PA2: SSI0 clock (SSI0Clk) */
/* tiva_configgpio(GPIO_SSI0_FSS); PA3: SSI0 frame (SSI0Fss) */ /* tiva_configgpio(GPIO_SSI0_FSS); PA3: SSI0 frame (SSI0Fss) */
tiva_configgpio(GPIO_SSI0_RX); /* PA4: SSI0 receive (SSI0Rx) */ tiva_configgpio(GPIO_SSI0_RX); /* PA4: SSI0 receive (SSI0Rx) */
tiva_configgpio(GPIO_SSI0_TX); /* PA5: SSI0 transmit (SSI0Tx) */ tiva_configgpio(GPIO_SSI0_TX); /* PA5: SSI0 transmit (SSI0Tx) */
break; break;
@@ -1528,6 +1540,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
#ifdef CONFIG_TIVA_SSI1 #ifdef CONFIG_TIVA_SSI1
case 1: case 1:
/* Select SSI1 */ /* Select SSI1 */
priv = &g_ssidev[SSI1_NDX]; priv = &g_ssidev[SSI1_NDX];
@@ -1549,7 +1562,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
/* Configure SSI1 GPIOs */ /* Configure SSI1 GPIOs */
tiva_configgpio(GPIO_SSI1_CLK); /* PE0: SSI1 clock (SSI1Clk) */ tiva_configgpio(GPIO_SSI1_CLK); /* PE0: SSI1 clock (SSI1Clk) */
/* tiva_configgpio(GPIO_SSI1_FSS); PE1: SSI1 frame (SSI1Fss) */ /* tiva_configgpio(GPIO_SSI1_FSS); PE1: SSI1 frame (SSI1Fss) */
tiva_configgpio(GPIO_SSI1_RX); /* PE2: SSI1 receive (SSI1Rx) */ tiva_configgpio(GPIO_SSI1_RX); /* PE2: SSI1 receive (SSI1Rx) */
tiva_configgpio(GPIO_SSI1_TX); /* PE3: SSI1 transmit (SSI1Tx) */ tiva_configgpio(GPIO_SSI1_TX); /* PE3: SSI1 transmit (SSI1Tx) */
break; break;
@@ -1557,6 +1570,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
#ifdef CONFIG_TIVA_SSI2 #ifdef CONFIG_TIVA_SSI2
case 2: case 2:
/* Select SSI2 */ /* Select SSI2 */
priv = &g_ssidev[SSI2_NDX]; priv = &g_ssidev[SSI2_NDX];
@@ -1578,7 +1592,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
/* Configure SSI2 GPIOs */ /* Configure SSI2 GPIOs */
tiva_configgpio(GPIO_SSI2_CLK); /* PE0: SSI2 clock (SSI2Clk) */ tiva_configgpio(GPIO_SSI2_CLK); /* PE0: SSI2 clock (SSI2Clk) */
/* tiva_configgpio(GPIO_SSI2_FSS); PE1: SSI2 frame (SSI2Fss) */ /* tiva_configgpio(GPIO_SSI2_FSS); PE1: SSI2 frame (SSI2Fss) */
tiva_configgpio(GPIO_SSI2_RX); /* PE2: SSI2 receive (SSI2Rx) */ tiva_configgpio(GPIO_SSI2_RX); /* PE2: SSI2 receive (SSI2Rx) */
tiva_configgpio(GPIO_SSI2_TX); /* PE3: SSI2 transmit (SSI2Tx) */ tiva_configgpio(GPIO_SSI2_TX); /* PE3: SSI2 transmit (SSI2Tx) */
break; break;
@@ -1586,6 +1600,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
#ifdef CONFIG_TIVA_SSI3 #ifdef CONFIG_TIVA_SSI3
case 3: case 3:
/* Select SSI3 */ /* Select SSI3 */
priv = &g_ssidev[SSI3_NDX]; priv = &g_ssidev[SSI3_NDX];
@@ -1607,7 +1622,7 @@ FAR struct spi_dev_s *tiva_ssibus_initialize(int port)
/* Configure SSI3 GPIOs */ /* Configure SSI3 GPIOs */
tiva_configgpio(GPIO_SSI3_CLK); /* PE0: SSI3 clock (SSI3Clk) */ tiva_configgpio(GPIO_SSI3_CLK); /* PE0: SSI3 clock (SSI3Clk) */
/* tiva_configgpio(GPIO_SSI3_FSS); PE1: SSI3 frame (SSI3Fss) */ /* tiva_configgpio(GPIO_SSI3_FSS); PE1: SSI3 frame (SSI3Fss) */
tiva_configgpio(GPIO_SSI3_RX); /* PE2: SSI3 receive (SSI3Rx) */ tiva_configgpio(GPIO_SSI3_RX); /* PE2: SSI3 receive (SSI3Rx) */
tiva_configgpio(GPIO_SSI3_TX); /* PE3: SSI3 transmit (SSI3Tx) */ tiva_configgpio(GPIO_SSI3_TX); /* PE3: SSI3 transmit (SSI3Tx) */
break; break;
+22 -16
View File
@@ -78,6 +78,7 @@
****************************************************************************/ ****************************************************************************/
/* Configuration ************************************************************/ /* Configuration ************************************************************/
/* When SPI DMA is enabled, small DMA transfers will still be performed by /* When SPI DMA is enabled, small DMA transfers will still be performed by
* polling logic. But we need a threshold value to determine what is small. * polling logic. But we need a threshold value to determine what is small.
* That value is provided by CONFIG_XMC4_SPI_DMATHRESHOLD. * That value is provided by CONFIG_XMC4_SPI_DMATHRESHOLD.
@@ -129,6 +130,7 @@
#endif #endif
/* Clocking *****************************************************************/ /* Clocking *****************************************************************/
/* Select MCU-specific settings */ /* Select MCU-specific settings */
#if defined(CONFIG_ARCH_CHIP_XMC4) #if defined(CONFIG_ARCH_CHIP_XMC4)
@@ -287,7 +289,7 @@ static void spi_select(struct spi_dev_s *dev, uint32_t devid,
static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(struct spi_dev_s *dev, uint32_t frequency);
static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(struct spi_dev_s *dev, enum spi_mode_e mode);
static void spi_setbits(struct spi_dev_s *dev, int nbits); static void spi_setbits(struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_XMC4_SPI_DMA #ifdef CONFIG_XMC4_SPI_DMA
static void spi_exchange_nodma(struct spi_dev_s *dev, static void spi_exchange_nodma(struct spi_dev_s *dev,
@@ -1300,7 +1302,7 @@ static void spi_setbits(struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -1315,7 +1317,7 @@ static uint16_t spi_send(struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -1395,7 +1397,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
/* Loop, sending each word in the user-provided data buffer. /* Loop, sending each word in the user-provided data buffer.
* *
* Note: Good SPI performance would require that we implement DMA transfers! * Note: Good SPI performance would require that we implement
* DMA transfers!
*/ */
for (; nwords > 0; nwords--) for (; nwords > 0; nwords--)
@@ -1435,7 +1438,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
{ {
} }
spi_putreg(spi, (USIC_PSCR_CRIF | USIC_PSCR_CAIF), XMC4_USIC_PSCR_OFFSET); spi_putreg(spi, (USIC_PSCR_CRIF | USIC_PSCR_CAIF),
XMC4_USIC_PSCR_OFFSET);
/* Read the received data from the SPI Data Register. */ /* Read the received data from the SPI Data Register. */
@@ -1551,7 +1555,8 @@ static void spi_exchange(struct spi_dev_s *dev, const void *txbuffer,
* the DMA completes * the DMA completes
*/ */
xmc4_cmcc_invalidate((uintptr_t)rxbuffer, (uintptr_t)rxbuffer + nbytes); xmc4_cmcc_invalidate((uintptr_t)rxbuffer,
(uintptr_t)rxbuffer + nbytes);
/* Use normal RX memory incrementing. */ /* Use normal RX memory incrementing. */
@@ -1747,10 +1752,10 @@ static void spi_sndblock(struct spi_dev_s *dev, const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -1890,13 +1895,14 @@ struct spi_dev_s *xmc4_spibus_initialize(int channel)
} }
else else
#endif #endif
{ {
spierr("ERROR: spino invalid: %d\n", spino); spierr("ERROR: spino invalid: %d\n", spino);
} }
/* Save the chip select and SPI controller numbers */ /* Save the chip select and SPI controller numbers */
/*spics->cs = csno; */ /* spics->cs = csno; */
spics->cs = 0; spics->cs = 0;
spics->spino = spino; spics->spino = spino;
@@ -2005,9 +2011,9 @@ struct spi_dev_s *xmc4_spibus_initialize(int channel)
} }
else else
#endif #endif
{ {
spierr("ERROR: spino invalid: %d\n", spino); spierr("ERROR: spino invalid: %d\n", spino);
} }
/* Leave critical section */ /* Leave critical section */
@@ -2063,7 +2069,7 @@ struct spi_dev_s *xmc4_spibus_initialize(int channel)
/* Clear protocol status */ /* Clear protocol status */
spi_putreg(spi, 0xffffffffUL, XMC4_USIC_PSCR_OFFSET); spi_putreg(spi, 0xfffffffful, XMC4_USIC_PSCR_OFFSET);
/* Disable the parity */ /* Disable the parity */
+23 -12
View File
@@ -1,5 +1,5 @@
/**************************************************************************** /****************************************************************************
* arch/arm/src/avr/up_spi.c * arch/avr/src/avr/up_spi.c
* *
* Copyright (C) 2011, 2016-2017 Gregory Nutt. All rights reserved. * Copyright (C) 2011, 2016-2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
@@ -82,12 +82,16 @@ struct avr_spidev_s
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); uint32_t 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords); static void spi_sndblock(FAR struct spi_dev_s *dev,
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords);
/**************************************************************************** /****************************************************************************
* Private Data * Private Data
@@ -115,7 +119,10 @@ static const struct spi_ops_s g_spiops =
static struct avr_spidev_s g_spidev = static struct avr_spidev_s g_spidev =
{ {
.spidev = { &g_spiops }, .spidev =
{
&g_spiops
},
}; };
/**************************************************************************** /****************************************************************************
@@ -175,7 +182,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct avr_spidev_s *priv = (FAR struct avr_spidev_s *)dev; FAR struct avr_spidev_s *priv = (FAR struct avr_spidev_s *)dev;
uint32_t actual; uint32_t actual;
@@ -340,7 +348,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
/* Write the data to transmitted to the SPI Data Register */ /* Write the data to transmitted to the SPI Data Register */
@@ -352,7 +360,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Then return the received value */ /* Then return the received value */
return (uint16_t)SPDR; return (uint32_t)SPDR;
} }
/**************************************************************************** /****************************************************************************
@@ -375,7 +383,8 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
* *
****************************************************************************/ ****************************************************************************/
static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords) static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
@@ -406,7 +415,8 @@ 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 nwords) static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords)
{ {
FAR uint8_t *ptr = (FAR uint8_t *)buffer; FAR uint8_t *ptr = (FAR uint8_t *)buffer;
@@ -465,6 +475,7 @@ FAR struct spi_dev_s *avr_spibus_initialize(int port)
SPCR = (1 << SPE) | (1 << MSTR); SPCR = (1 << SPE) | (1 << MSTR);
/* Set clock rate to f(osc)/8 */ /* Set clock rate to f(osc)/8 */
/* SPSR |= (1 << 0); */ /* SPSR |= (1 << 0); */
/* Clear status flags by reading them */ /* Clear status flags by reading them */
+16 -14
View File
@@ -64,6 +64,7 @@
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
****************************************************************************/ ****************************************************************************/
/* Configuration */ /* Configuration */
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
@@ -98,6 +99,7 @@ struct pic32mx_dev_s
/**************************************************************************** /****************************************************************************
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
/* Low-level register access */ /* Low-level register access */
static uint32_t spi_getreg(FAR struct pic32mx_dev_s *priv, static uint32_t spi_getreg(FAR struct pic32mx_dev_s *priv,
@@ -112,7 +114,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency); uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_sndblock(FAR struct spi_dev_s *dev, static void spi_sndblock(FAR struct spi_dev_s *dev,
FAR const void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
@@ -565,10 +567,10 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
* *
* CPOL=0: The inactive value of the clock is zero * CPOL=0: The inactive value of the clock is zero
* CPOL=1: The inactive value of the clock is one * CPOL=1: The inactive value of the clock is one
* CPHA=0: Data is captured on the clock's inactive-to-active edge and * CPHA=0: Data is captured on the clock's inactive-to-active edge
* data is propagated on a active-to-inactive edge. * and data is propagated on a active-to-inactive edge.
* CPHA=1: Data is captured on the clock's active-to-inactive edge and * CPHA=1: Data is captured on the clock's active-to-inactive edge
* data is propagated on a active-to-inactive edge. * and data is propagated on a active-to-inactive edge.
* *
* CON Register mapping: * CON Register mapping:
* CPOL=0 corresponds to CON:CKP=0; CPOL=1 corresponds to CON:CKP=1 * CPOL=0 corresponds to CON:CKP=0; CPOL=1 corresponds to CON:CKP=1
@@ -694,7 +696,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct pic32mx_dev_s *priv = (FAR struct pic32mx_dev_s *)dev; FAR struct pic32mx_dev_s *priv = (FAR struct pic32mx_dev_s *)dev;
@@ -702,7 +704,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Write the data to transmitted to the SPI Data Register */ /* Write the data to transmitted to the SPI Data Register */
spi_putreg(priv, PIC32MX_SPI_BUF_OFFSET, (uint32_t)wd); spi_putreg(priv, PIC32MX_SPI_BUF_OFFSET, wd);
#ifdef CONFIG_PIC32MX_SPI_ENHBUF #ifdef CONFIG_PIC32MX_SPI_ENHBUF
/* Wait for the SPIRBE bit in the SPI Status Register to be set to 0. In /* Wait for the SPIRBE bit in the SPI Status Register to be set to 0. In
@@ -722,7 +724,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
/* Return the SPI data */ /* Return the SPI data */
return (uint16_t)spi_getreg(priv, PIC32MX_SPI_BUF_OFFSET); return spi_getreg(priv, PIC32MX_SPI_BUF_OFFSET);
} }
/**************************************************************************** /****************************************************************************
@@ -762,9 +764,9 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
spi_putreg(priv, PIC32MX_SPI_BUF_OFFSET, (uint32_t)data); spi_putreg(priv, PIC32MX_SPI_BUF_OFFSET, (uint32_t)data);
#ifdef CONFIG_PIC32MX_SPI_ENHBUF #ifdef CONFIG_PIC32MX_SPI_ENHBUF
/* Wait for the SPIRBE bit in the SPI Status Register to be set to 0. In /* Wait for the SPIRBE bit in the SPI Status Register to be set to 0.
* enhanced buffer mode, the SPIRBE bit will be cleared in when the * In enhanced buffer mode, the SPIRBE bit will be cleared in when
* receive buffer is not empty. * the receive buffer is not empty.
*/ */
while ((spi_getreg(priv, PIC32MX_SPI_STAT_OFFSET) & while ((spi_getreg(priv, PIC32MX_SPI_STAT_OFFSET) &
@@ -823,9 +825,9 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
spi_putreg(priv, PIC32MX_SPI_BUF_OFFSET, 0xff); spi_putreg(priv, PIC32MX_SPI_BUF_OFFSET, 0xff);
#ifdef CONFIG_PIC32MX_SPI_ENHBUF #ifdef CONFIG_PIC32MX_SPI_ENHBUF
/* Wait for the SPIRBE bit in the SPI Status Register to be set to 0. In /* Wait for the SPIRBE bit in the SPI Status Register to be set to 0.
* enhanced buffer mode, the SPIRBE bit will be cleared in when the * In enhanced buffer mode, the SPIRBE bit will be cleared in when
* receive buffer is not empty. * the receive buffer is not empty.
*/ */
while ((spi_getreg(priv, PIC32MX_SPI_STAT_OFFSET) & while ((spi_getreg(priv, PIC32MX_SPI_STAT_OFFSET) &
+14 -14
View File
@@ -228,7 +228,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency); uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(FAR struct spi_dev_s *dev, static void spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords); size_t nwords);
@@ -1058,8 +1058,8 @@ static void spi_exchange8(FAR struct pic32mz_dev_s *priv,
spi_putreg(priv, PIC32MZ_SPI_BUF_OFFSET, (uint32_t)data); spi_putreg(priv, PIC32MZ_SPI_BUF_OFFSET, (uint32_t)data);
#ifdef CONFIG_PIC32MZ_SPI_ENHBUF #ifdef CONFIG_PIC32MZ_SPI_ENHBUF
/* Wait for the SPIRBE bit in the SPI Status Register to be set to 0. In /* Wait for the SPIRBE bit in the SPI Status Register to be set to 0.
* enhanced buffer mode, the SPIRBE bit will be cleared in when the * In enhanced buffer mode, the SPIRBE bit will be cleared in when the
* receive buffer is not empty. * receive buffer is not empty.
*/ */
@@ -1132,8 +1132,8 @@ static void spi_exchange16(FAR struct pic32mz_dev_s *priv,
spi_putreg(priv, PIC32MZ_SPI_BUF_OFFSET, (uint32_t)data); spi_putreg(priv, PIC32MZ_SPI_BUF_OFFSET, (uint32_t)data);
#ifdef CONFIG_PIC32MZ_SPI_ENHBUF #ifdef CONFIG_PIC32MZ_SPI_ENHBUF
/* Wait for the SPIRBE bit in the SPI Status Register to be set to 0. In /* Wait for the SPIRBE bit in the SPI Status Register to be set to 0.
* enhanced buffer mode, the SPIRBE bit will be cleared in when the * In enhanced buffer mode, the SPIRBE bit will be cleared in when the
* receive buffer is not empty. * receive buffer is not empty.
*/ */
@@ -1308,10 +1308,10 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
* *
* CPOL=0: The inactive value of the clock is zero * CPOL=0: The inactive value of the clock is zero
* CPOL=1: The inactive value of the clock is one * CPOL=1: The inactive value of the clock is one
* CPHA=0: Data is captured on the clock's inactive-to-active edge and * CPHA=0: Data is captured on the clock's inactive-to-active edge
* data is propagated on a active-to-inactive edge. * and data is propagated on a active-to-inactive edge.
* CPHA=1: Data is captured on the clock's active-to-inactive edge and * CPHA=1: Data is captured on the clock's active-to-inactive edge
* data is propagated on a active-to-inactive edge. * and data is propagated on a active-to-inactive edge.
* *
* CON Register mapping: * CON Register mapping:
* CPOL=0 corresponds to CON:CKP=0; CPOL=1 corresponds to CON:CKP=1 * CPOL=0 corresponds to CON:CKP=0; CPOL=1 corresponds to CON:CKP=1
@@ -1434,7 +1434,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct pic32mz_dev_s *priv = (FAR struct pic32mz_dev_s *)dev; FAR struct pic32mz_dev_s *priv = (FAR struct pic32mz_dev_s *)dev;
@@ -1456,7 +1456,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
spi_exchange16(priv, &txword, &rxword, 1); spi_exchange16(priv, &txword, &rxword, 1);
spiinfo("Sent %04x received %04x\n", txword, rxword); spiinfo("Sent %04x received %04x\n", txword, rxword);
return rxword; return (uint32_t)rxword;
} }
else else
{ {
@@ -1470,7 +1470,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
spi_exchange8(priv, &txbyte, &rxbyte, 1); spi_exchange8(priv, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
} }
@@ -1837,8 +1837,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
} }
else else
{ {
up_invalidate_dcache((uintptr_t)dummy, up_invalidate_dcache((uintptr_t)dummy, (uintptr_t)dummy +
(uintptr_t)dummy + CONFIG_PIC32MZ_SPI_DMABUFFSIZE); CONFIG_PIC32MZ_SPI_DMABUFFSIZE);
} }
} }
#endif /* CONFIG_PIC32MZ_SPI_DMA */ #endif /* CONFIG_PIC32MZ_SPI_DMA */
+17 -14
View File
@@ -178,7 +178,7 @@ struct sim_spiflashdev_s
FAR char * name; /* Name of the flash type (m25p, w25, etc.) */ FAR char * name; /* Name of the flash type (m25p, w25, etc.) */
int wren; int wren;
int state; int state;
uint16_t read_data; uint32_t read_data;
uint8_t last_cmd; uint8_t last_cmd;
uint8_t capacity; uint8_t capacity;
uint8_t manuf; uint8_t manuf;
@@ -194,27 +194,30 @@ struct sim_spiflashdev_s
/* SPI methods */ /* SPI methods */
static int spiflash_lock(FAR struct spi_dev_s *dev, bool lock); static int spiflash_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spiflash_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spiflash_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spiflash_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spiflash_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static void spiflash_setbits(FAR struct spi_dev_s *dev, int nbits); static void spiflash_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spiflash_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spiflash_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spiflash_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spiflash_exchange(FAR struct spi_dev_s *dev,
FAR void *rxbuffer, size_t nwords); FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords);
static void spiflash_select(FAR struct spi_dev_s *dev, uint32_t devid, static void spiflash_select(FAR struct spi_dev_s *dev, uint32_t devid,
bool selected); bool selected);
static uint8_t spiflash_status(FAR struct spi_dev_s *dev, uint32_t devid); static uint8_t spiflash_status(FAR struct spi_dev_s *dev, uint32_t devid);
#ifdef CONFIG_SPI_CMDDATA #ifdef CONFIG_SPI_CMDDATA
static int spiflash_cmddata(FAR struct spi_dev_s *dev, uint32_t devid, bool cmd); static int spiflash_cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
bool cmd);
#endif #endif
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spiflash_sndblock(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spiflash_sndblock(FAR struct spi_dev_s *dev,
size_t nwords); FAR const void *txbuffer, size_t nwords);
static void spiflash_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer, static void spiflash_recvblock(FAR struct spi_dev_s *dev, FAR void *rxbuffer,
size_t nwords); size_t nwords);
#endif #endif
static void spiflash_writeword(FAR struct sim_spiflashdev_s *priv, uint16_t data); static void spiflash_writeword(FAR struct sim_spiflashdev_s *priv, uint16_t data);
static uint16_t spiflash_readword(FAR struct sim_spiflashdev_s *priv); static uint32_t spiflash_readword(FAR struct sim_spiflashdev_s *priv);
/************************************************************************************ /************************************************************************************
* Private Data * Private Data
@@ -500,10 +503,10 @@ static uint8_t spiflash_status(FAR struct spi_dev_s *dev, uint32_t devid)
* *
************************************************************************************/ ************************************************************************************/
static uint16_t spiflash_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spiflash_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct sim_spiflashdev_s *priv = (FAR struct sim_spiflashdev_s *)dev; FAR struct sim_spiflashdev_s *priv = (FAR struct sim_spiflashdev_s *)dev;
uint16_t ret; uint32_t ret;
if (priv->selected) if (priv->selected)
{ {
@@ -897,7 +900,7 @@ static void spiflash_writeword(FAR struct sim_spiflashdev_s *priv, uint16_t data
* *
************************************************************************************/ ************************************************************************************/
static uint16_t spiflash_readword(FAR struct sim_spiflashdev_s *priv) static uint32_t spiflash_readword(FAR struct sim_spiflashdev_s *priv)
{ {
return priv->read_data; return priv->read_data;
} }
+31 -26
View File
@@ -74,10 +74,10 @@ struct z16f_spi_s
/* Debug stuff */ /* Debug stuff */
#ifdef CONFIG_Z16F_ESPI_REGDEBUG #ifdef CONFIG_Z16F_ESPI_REGDEBUG
bool wr; /* Last was a write */ bool wr; /* Last was a write */
uint16_t regval; /* Last value */ uint16_t regval; /* Last value */
int ntimes; /* Number of times */ int ntimes; /* Number of times */
uintptr_t regaddr; /* Last address */ uintptr_t regaddr; /* Last address */
#endif #endif
}; };
@@ -112,17 +112,19 @@ static void spi_flush(FAR struct z16f_spi_s *priv);
/* SPI methods */ /* SPI methods */
static int spi_lock(FAR struct spi_dev_s *dev, bool lock); static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency); static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); 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 void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, static void spi_exchange(FAR struct spi_dev_s *dev,
FAR void *rxbuffer, size_t nwords); FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords);
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
static void spi_sndblock(FAR struct spi_dev_s *dev, static void spi_sndblock(FAR struct spi_dev_s *dev,
FAR const void *buffer, size_t nwords); FAR const void *buffer, size_t nwords);
static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
size_t nwords); size_t nwords);
#endif #endif
/**************************************************************************** /****************************************************************************
@@ -185,8 +187,8 @@ static struct z16f_spi_s g_espi;
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_Z16F_ESPI_REGDEBUG #ifdef CONFIG_Z16F_ESPI_REGDEBUG
static bool spi_checkreg(FAR struct z16f_spi_s *priv, bool wr, uint16_t regval, static bool spi_checkreg(FAR struct z16f_spi_s *priv, bool wr,
uintptr_t regaddr) uint16_t regval, uintptr_t regaddr)
{ {
if (wr == priv->wr && /* Same kind of access? */ if (wr == priv->wr && /* Same kind of access? */
regval == priv->regval && /* Same value? */ regval == priv->regval && /* Same value? */
@@ -398,7 +400,8 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
* *
****************************************************************************/ ****************************************************************************/
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency)
{ {
FAR struct z16f_spi_s *priv = (FAR struct z16f_spi_s *)dev; FAR struct z16f_spi_s *priv = (FAR struct z16f_spi_s *)dev;
uint32_t actual; uint32_t actual;
@@ -580,7 +583,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t txbyte; uint8_t txbyte;
uint8_t rxbyte; uint8_t rxbyte;
@@ -595,7 +598,7 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
spi_exchange(dev, &txbyte, &rxbyte, 1); spi_exchange(dev, &txbyte, &rxbyte, 1);
spiinfo("Sent %02x received %02x\n", txbyte, rxbyte); spiinfo("Sent %02x received %02x\n", txbyte, rxbyte);
return (uint16_t)rxbyte; return (uint32_t)rxbyte;
} }
/**************************************************************************** /****************************************************************************
@@ -663,7 +666,7 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer,
* Save the final byte. * Save the final byte.
*/ */
for ( ; nwords > 0; nwords--) for (; nwords > 0; nwords--)
{ {
/* Get the data to send (0xff if there is no data source). */ /* Get the data to send (0xff if there is no data source). */
@@ -745,10 +748,10 @@ static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer,
* dev - Device-specific state data * dev - Device-specific state data
* buffer - A pointer to the buffer in which to receive data * buffer - A pointer to the buffer in which to receive data
* nwords - 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 * of words. The wordsize is determined by the number of
* selected for the SPI interface. If nbits <= 8, the data is * bits-per-word selected for the SPI interface. If nbits <= 8,
* packed into uint8_t's; if nbits >8, the data is packed into * the data is packed into uint8_t's; if nbits >8, the data is
* uint16_t's * packed into uint16_t's
* *
* Returned Value: * Returned Value:
* None * None
@@ -803,8 +806,8 @@ FAR struct spi_dev_s *z16_spibus_initialize(int port)
priv->spi.ops = &g_epsiops; priv->spi.ops = &g_epsiops;
nxsem_init(&priv->exclsem, 0, 1); nxsem_init(&priv->exclsem, 0, 1);
/* Set up the SPI pin configuration (board-specific logic is required to /* Set up the SPI pin configuration (board-specific logic is required
* configure and manage all chip selects). * to configure and manage all chip selects).
* *
* SCK - PC3, Alternate function 1 * SCK - PC3, Alternate function 1
* MOSI - PC4, Alternate function 1 * MOSI - PC4, Alternate function 1
@@ -824,14 +827,16 @@ FAR struct spi_dev_s *z16_spibus_initialize(int port)
spi_putreg8(priv, 0x00, Z16F_ESPI_CTL); /* Disabled the ESPI */ spi_putreg8(priv, 0x00, Z16F_ESPI_CTL); /* Disabled the ESPI */
spi_putreg8(priv, 0x00, Z16F_ESPI_DCR); /* Disabled slave select; clear TEOF */ spi_putreg8(priv, 0x00, Z16F_ESPI_DCR); /* Disabled slave select; clear TEOF */
regval = Z16F_ESPI_MODE_SSIO | Z16F_ESPI_MODE_NUMBITS_8BITS | Z16F_ESPI_MODE_SSMD_SPI; regval = Z16F_ESPI_MODE_SSIO | Z16F_ESPI_MODE_NUMBITS_8BITS |
Z16F_ESPI_MODE_SSMD_SPI;
spi_putreg8(priv, regval, Z16F_ESPI_MODE); /* SPI mode, 8-bit */ spi_putreg8(priv, regval, Z16F_ESPI_MODE); /* SPI mode, 8-bit */
regval = Z16F_ESPI_CTL_ESPIEN0 | Z16F_ESPI_CTL_MMEN | Z16F_ESPI_CTL_ESPIEN1; regval = Z16F_ESPI_CTL_ESPIEN0 | Z16F_ESPI_CTL_MMEN |
Z16F_ESPI_CTL_ESPIEN1;
spi_putreg8(priv, 0x00, Z16F_ESPI_CTL); /* TX/RX mode, Master mode */ spi_putreg8(priv, 0x00, Z16F_ESPI_CTL); /* TX/RX mode, Master mode */
/* Make sure that we are all in agreement about the configuration and set /* Make sure that we are all in agreement about the configuration and
* the BRG for 400KHz operation. * set the BRG for 400KHz operation.
*/ */
spi_setfrequency(&priv->spi, 400000); spi_setfrequency(&priv->spi, 400000);
+4 -4
View File
@@ -74,7 +74,7 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
uint32_t frequency); uint32_t frequency);
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode); static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
static void spi_exchange(FAR struct spi_dev_s *dev, static void spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
@@ -405,7 +405,7 @@ static int spi_transfer(uint8_t chout, FAR uint8_t *chin)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
uint8_t response; uint8_t response;
int ret; int ret;
@@ -414,11 +414,11 @@ static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
if (ret < 0) if (ret < 0)
{ {
spierr("ERROR: spi_transfer returned %d\n", ret); spierr("ERROR: spi_transfer returned %d\n", ret);
return (uint16_t)0xff; return (uint32_t)0xff;
} }
spiinfo("cmd: %04x resp: %02x\n", wd, response); spiinfo("cmd: %04x resp: %02x\n", wd, response);
return (uint16_t)response; return (uint32_t)response;
} }
/**************************************************************************** /****************************************************************************
+5 -4
View File
@@ -96,7 +96,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
static void spi_setmode(FAR struct spi_dev_s *dev, static void spi_setmode(FAR struct spi_dev_s *dev,
enum spi_mode_e mode); enum spi_mode_e mode);
static void spi_setbits(FAR struct spi_dev_s *dev, int nbits); static void spi_setbits(FAR struct spi_dev_s *dev, int nbits);
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch); static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd);
static void spi_exchange(FAR struct spi_dev_s *dev, static void spi_exchange(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
size_t nwords); size_t nwords);
@@ -308,12 +308,12 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
* *
****************************************************************************/ ****************************************************************************/
static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd) static uint32_t spi_send(FAR struct spi_dev_s *dev, uint32_t wd)
{ {
FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev; FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
DEBUGASSERT(priv && priv->low && priv->low->exchange); DEBUGASSERT(priv && priv->low && priv->low->exchange);
return priv->low->exchange(priv, wd); return priv->low->exchange(priv, (uint16_t)wd);
} }
/**************************************************************************** /****************************************************************************
@@ -528,7 +528,8 @@ static int spi_cmddata(FAR struct spi_dev_s *dev, uint32_t devid,
* *
****************************************************************************/ ****************************************************************************/
FAR struct spi_dev_s *spi_create_bitbang(FAR const struct spi_bitbang_ops_s *low) FAR struct spi_dev_s *spi_create_bitbang(FAR const struct
spi_bitbang_ops_s *low)
{ {
FAR struct spi_bitbang_s *priv; FAR struct spi_bitbang_s *priv;
+5 -8
View File
@@ -557,10 +557,11 @@ struct spi_ops_s
CODE int (*lock)(FAR struct spi_dev_s *dev, bool lock); CODE int (*lock)(FAR struct spi_dev_s *dev, bool lock);
CODE void (*select)(FAR struct spi_dev_s *dev, uint32_t devid, CODE void (*select)(FAR struct spi_dev_s *dev, uint32_t devid,
bool selected); bool selected);
CODE uint32_t (*setfrequency)(FAR struct spi_dev_s *dev, uint32_t frequency); CODE uint32_t (*setfrequency)(FAR struct spi_dev_s *dev,
uint32_t frequency);
#ifdef CONFIG_SPI_CS_DELAY_CONTROL #ifdef CONFIG_SPI_CS_DELAY_CONTROL
CODE int (*setdelay)(FAR struct spi_dev_s *dev, uint32_t a, uint32_t b, CODE int (*setdelay)(FAR struct spi_dev_s *dev, uint32_t a,
uint32_t c); uint32_t b, uint32_t c);
#endif #endif
CODE void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode); CODE void (*setmode)(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
CODE void (*setbits)(FAR struct spi_dev_s *dev, int nbits); CODE void (*setbits)(FAR struct spi_dev_s *dev, int nbits);
@@ -573,7 +574,7 @@ struct spi_ops_s
CODE int (*cmddata)(FAR struct spi_dev_s *dev, uint32_t devid, CODE int (*cmddata)(FAR struct spi_dev_s *dev, uint32_t devid,
bool cmd); bool cmd);
#endif #endif
CODE uint16_t (*send)(FAR struct spi_dev_s *dev, uint16_t wd); CODE uint32_t (*send)(FAR struct spi_dev_s *dev, uint32_t wd);
#ifdef CONFIG_SPI_EXCHANGE #ifdef CONFIG_SPI_EXCHANGE
CODE void (*exchange)(FAR struct spi_dev_s *dev, CODE void (*exchange)(FAR struct spi_dev_s *dev,
FAR const void *txbuffer, FAR void *rxbuffer, FAR const void *txbuffer, FAR void *rxbuffer,
@@ -601,10 +602,6 @@ struct spi_dev_s
FAR const struct spi_ops_s *ops; FAR const struct spi_ops_s *ops;
}; };
/****************************************************************************
* Public Functions
****************************************************************************/
#undef EXTERN #undef EXTERN
#if defined(__cplusplus) #if defined(__cplusplus)
#define EXTERN extern "C" #define EXTERN extern "C"