Extend SPI interface to better handle multiple devices on same SPI bus
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2162 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
31c28b1f59
commit
5f08d86694
@ -184,6 +184,7 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t
|
|||||||
|
|
||||||
static const struct spi_ops_s g_spiops =
|
static const struct spi_ops_s g_spiops =
|
||||||
{
|
{
|
||||||
|
.lock = 0, /* Not yet implemented */
|
||||||
.select = imx_spiselect, /* Provided externally by board logic */
|
.select = imx_spiselect, /* Provided externally by board logic */
|
||||||
.setfrequency = spi_setfrequency,
|
.setfrequency = spi_setfrequency,
|
||||||
.setmode = spi_setmode,
|
.setmode = spi_setmode,
|
||||||
|
@ -251,6 +251,7 @@ static void ssi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t
|
|||||||
|
|
||||||
static const struct spi_ops_s g_spiops =
|
static const struct spi_ops_s g_spiops =
|
||||||
{
|
{
|
||||||
|
.lock = 0, /* Not yet implemented */
|
||||||
.select = lm3s_spiselect, /* Provided externally by board logic */
|
.select = lm3s_spiselect, /* Provided externally by board logic */
|
||||||
.setfrequency = ssi_setfrequency,
|
.setfrequency = ssi_setfrequency,
|
||||||
.setmode = ssi_setmode,
|
.setmode = ssi_setmode,
|
||||||
|
@ -610,9 +610,6 @@ EXTERN int stm32_ethinitialize(int intf);
|
|||||||
* 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
|
* 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
|
||||||
* board-specific logic. These functions will perform chip selection and
|
* board-specific logic. These functions will perform chip selection and
|
||||||
* status operations using GPIOs in the way your board is configured.
|
* status operations using GPIOs in the way your board is configured.
|
||||||
* The select() methods must call stm32_spitake() when the chip is selected
|
|
||||||
* and stm32_spigive() when the chip is deselected. This assures mutually
|
|
||||||
* exclusive access to the SPI for the duration while a chip is selected.
|
|
||||||
* 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 up_spiinitialize() may then be used to bind the
|
* 4. The handle returned by up_spiinitialize() may then be used to bind the
|
||||||
@ -631,20 +628,6 @@ EXTERN ubyte stm32_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
|
|||||||
EXTERN void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
|
EXTERN void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected);
|
||||||
EXTERN ubyte stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
|
EXTERN ubyte stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Name: stm32_spitake() and stm32_spigive()
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* The stm32_spi1/2/3select() and stm32_spi1/2/3status() methods must call
|
|
||||||
* stm32_spitake() when the chip is selected and stm32_spigive() when the chip is
|
|
||||||
* deselected. This assures mutually exclusive access to the SPI for the duration
|
|
||||||
* while a chip is selected.
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
EXTERN void stm32_spitake(FAR struct spi_dev_s *dev);
|
|
||||||
EXTERN void stm32_spigive(FAR struct spi_dev_s *dev);
|
|
||||||
|
|
||||||
#undef EXTERN
|
#undef EXTERN
|
||||||
#if defined(__cplusplus)
|
#if defined(__cplusplus)
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,6 @@
|
|||||||
* 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
|
* 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your
|
||||||
* board-specific logic. These functions will perform chip selection and
|
* board-specific logic. These functions will perform chip selection and
|
||||||
* status operations using GPIOs in the way your board is configured.
|
* status operations using GPIOs in the way your board is configured.
|
||||||
* The select() methods must call stm32_spitake() when the chip is selected
|
|
||||||
* and stm32_spigive() when the chip is deselected. This assures mutually
|
|
||||||
* exclusive access to the SPI for the duration while a chip is selected.
|
|
||||||
* 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 up_spiinitialize() may then be used to bind the
|
* 4. The handle returned by up_spiinitialize() may then be used to bind the
|
||||||
@ -119,6 +116,10 @@ struct stm32_spidev_s
|
|||||||
struct spi_dev_s spidev; /* Externally visible part of the SPI interface */
|
struct spi_dev_s spidev; /* Externally visible part of the SPI interface */
|
||||||
uint32 spibase; /* SPIn base address */
|
uint32 spibase; /* SPIn base address */
|
||||||
uint32 spiclock; /* Clocking for the SPI module */
|
uint32 spiclock; /* Clocking for the SPI module */
|
||||||
|
uint32 frequency; /* Requested clock frequency */
|
||||||
|
uint32 actual; /* Actual clock frequency */
|
||||||
|
ubyte nbits; /* Width of work in bits (8 or 16) */
|
||||||
|
ubyte mode; /* Mode 0,1,2,3 */
|
||||||
#ifdef CONFIG_STM32_SPI_INTERRUPTS
|
#ifdef CONFIG_STM32_SPI_INTERRUPTS
|
||||||
ubyte spiirq; /* SPI IRQ number */
|
ubyte spiirq; /* SPI IRQ number */
|
||||||
#endif
|
#endif
|
||||||
@ -167,6 +168,7 @@ static inline void spi_dmatxstart(FAR struct stm32_spidev_s *priv);
|
|||||||
|
|
||||||
/* SPI methods */
|
/* SPI methods */
|
||||||
|
|
||||||
|
static int spi_lock(FAR struct spi_dev_s *dev, boolean lock);
|
||||||
static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);
|
static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency);
|
||||||
static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode);
|
static void spi_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);
|
||||||
@ -191,6 +193,7 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv);
|
|||||||
#ifdef CONFIG_STM32_SPI1
|
#ifdef CONFIG_STM32_SPI1
|
||||||
static const struct spi_ops_s g_sp1iops =
|
static const struct spi_ops_s g_sp1iops =
|
||||||
{
|
{
|
||||||
|
.lock = spi_lock,
|
||||||
.select = stm32_spi1select,
|
.select = stm32_spi1select,
|
||||||
.setfrequency = spi_setfrequency,
|
.setfrequency = spi_setfrequency,
|
||||||
.setmode = spi_setmode,
|
.setmode = spi_setmode,
|
||||||
@ -224,6 +227,7 @@ static struct stm32_spidev_s g_spi1dev =
|
|||||||
#ifdef CONFIG_STM32_SPI2
|
#ifdef CONFIG_STM32_SPI2
|
||||||
static const struct spi_ops_s g_sp2iops =
|
static const struct spi_ops_s g_sp2iops =
|
||||||
{
|
{
|
||||||
|
.lock = spi_lock,
|
||||||
.select = stm32_spi2select,
|
.select = stm32_spi2select,
|
||||||
.setfrequency = spi_setfrequency,
|
.setfrequency = spi_setfrequency,
|
||||||
.setmode = spi_setmode,
|
.setmode = spi_setmode,
|
||||||
@ -257,6 +261,7 @@ static struct stm32_spidev_s g_spi2dev =
|
|||||||
#ifdef CONFIG_STM32_SPI3
|
#ifdef CONFIG_STM32_SPI3
|
||||||
static const struct spi_ops_s g_sp3iops =
|
static const struct spi_ops_s g_sp3iops =
|
||||||
{
|
{
|
||||||
|
.lock = spi_lock,
|
||||||
.select = stm32_spi3select,
|
.select = stm32_spi3select,
|
||||||
.setfrequency = spi_setfrequency,
|
.setfrequency = spi_setfrequency,
|
||||||
.setmode = spi_setmode,
|
.setmode = spi_setmode,
|
||||||
@ -664,6 +669,51 @@ static void spi_modifycr1(FAR struct stm32_spidev_s *priv, uint16 setbits, uint1
|
|||||||
spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1);
|
spi_putreg(priv, STM32_SPI_CR1_OFFSET, cr1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/****************************************************************************
|
||||||
|
* Name: spi_lock
|
||||||
|
*
|
||||||
|
* Description:
|
||||||
|
* On SPI busses where there are multiple devices, it will be necessary to
|
||||||
|
* lock SPI to have exclusive access to the busses for a sequence of
|
||||||
|
* transfers. The bus should be locked before the chip is selected. After
|
||||||
|
* locking the SPI bus, the caller should then also call the setfrequency,
|
||||||
|
* setbits, and setmode methods to make sure that the SPI is properly
|
||||||
|
* configured for the device. If the SPI buss is being shared, then it
|
||||||
|
* may have been left in an incompatible state.
|
||||||
|
*
|
||||||
|
* Input Parameters:
|
||||||
|
* dev - Device-specific state data
|
||||||
|
* lock - TRUE: Lock spi bus, FALSE: unlock SPI bus
|
||||||
|
*
|
||||||
|
* Returned Value:
|
||||||
|
* None
|
||||||
|
*
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
static int spi_lock(FAR struct spi_dev_s *dev, boolean lock)
|
||||||
|
{
|
||||||
|
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
|
||||||
|
|
||||||
|
if (lock)
|
||||||
|
{
|
||||||
|
/* Take the semaphore (perhaps waiting) */
|
||||||
|
|
||||||
|
while (sem_wait(&priv->exclsem) != 0)
|
||||||
|
{
|
||||||
|
/* The only case that an error should occur here is if the wait was awakened
|
||||||
|
* by a signal.
|
||||||
|
*/
|
||||||
|
|
||||||
|
ASSERT(errno == EINTR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
(void)sem_post(&priv->exclsem);
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
* Name: spi_setfrequency
|
* Name: spi_setfrequency
|
||||||
*
|
*
|
||||||
@ -685,67 +735,74 @@ static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency)
|
|||||||
uint16 setbits;
|
uint16 setbits;
|
||||||
uint32 actual;
|
uint32 actual;
|
||||||
|
|
||||||
/* Choices are limited by PCLK frequency with a set of divisors */
|
/* Has the frequency changed? */
|
||||||
|
|
||||||
if (frequency >= priv->spiclock >> 1)
|
if (frequency != priv->frequency)
|
||||||
{
|
{
|
||||||
/* More than fPCLK/2. This is as fast as we can go */
|
/* Choices are limited by PCLK frequency with a set of divisors */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */
|
if (frequency >= priv->spiclock >> 1)
|
||||||
actual = priv->spiclock >> 1;
|
{
|
||||||
}
|
/* More than fPCLK/2. This is as fast as we can go */
|
||||||
else if (frequency >= priv->spiclock >> 2)
|
|
||||||
{
|
|
||||||
/* Between fPCLCK/2 and fPCLCK/4, pick the slower */
|
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */
|
setbits = SPI_CR1_FPCLCKd2; /* 000: fPCLK/2 */
|
||||||
actual = priv->spiclock >> 2;
|
actual = priv->spiclock >> 1;
|
||||||
}
|
}
|
||||||
else if (frequency >= priv->spiclock >> 3)
|
else if (frequency >= priv->spiclock >> 2)
|
||||||
{
|
{
|
||||||
/* Between fPCLCK/4 and fPCLCK/8, pick the slower */
|
/* Between fPCLCK/2 and fPCLCK/4, pick the slower */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */
|
setbits = SPI_CR1_FPCLCKd4; /* 001: fPCLK/4 */
|
||||||
actual = priv->spiclock >> 3;
|
actual = priv->spiclock >> 2;
|
||||||
}
|
}
|
||||||
else if (frequency >= priv->spiclock >> 4)
|
else if (frequency >= priv->spiclock >> 3)
|
||||||
{
|
{
|
||||||
/* Between fPCLCK/8 and fPCLCK/16, pick the slower */
|
/* Between fPCLCK/4 and fPCLCK/8, pick the slower */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */
|
setbits = SPI_CR1_FPCLCKd8; /* 010: fPCLK/8 */
|
||||||
actual = priv->spiclock >> 4;
|
actual = priv->spiclock >> 3;
|
||||||
}
|
}
|
||||||
else if (frequency >= priv->spiclock >> 5)
|
else if (frequency >= priv->spiclock >> 4)
|
||||||
{
|
{
|
||||||
/* Between fPCLCK/16 and fPCLCK/32, pick the slower */
|
/* Between fPCLCK/8 and fPCLCK/16, pick the slower */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */
|
setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */
|
||||||
actual = priv->spiclock >> 5;
|
actual = priv->spiclock >> 4;
|
||||||
}
|
}
|
||||||
else if (frequency >= priv->spiclock >> 6)
|
else if (frequency >= priv->spiclock >> 5)
|
||||||
{
|
{
|
||||||
/* Between fPCLCK/32 and fPCLCK/64, pick the slower */
|
/* Between fPCLCK/16 and fPCLCK/32, pick the slower */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd64; /* 101: fPCLK/64 */
|
setbits = SPI_CR1_FPCLCKd32; /* 100: fPCLK/32 */
|
||||||
actual = priv->spiclock >> 6;
|
actual = priv->spiclock >> 5;
|
||||||
}
|
}
|
||||||
else if (frequency >= priv->spiclock >> 7)
|
else if (frequency >= priv->spiclock >> 6)
|
||||||
{
|
{
|
||||||
/* Between fPCLCK/64 and fPCLCK/128, pick the slower */
|
/* Between fPCLCK/32 and fPCLCK/64, pick the slower */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */
|
setbits = SPI_CR1_FPCLCKd64; /* 101: fPCLK/64 */
|
||||||
actual = priv->spiclock >> 7;
|
actual = priv->spiclock >> 6;
|
||||||
}
|
}
|
||||||
else
|
else if (frequency >= priv->spiclock >> 7)
|
||||||
{
|
{
|
||||||
/* Less than fPCLK/128. This is as slow as we can go */
|
/* Between fPCLCK/64 and fPCLCK/128, pick the slower */
|
||||||
|
|
||||||
|
setbits = SPI_CR1_FPCLCKd128; /* 110: fPCLK/128 */
|
||||||
|
actual = priv->spiclock >> 7;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Less than fPCLK/128. This is as slow as we can go */
|
||||||
|
|
||||||
setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
|
setbits = SPI_CR1_FPCLCKd256; /* 111: fPCLK/256 */
|
||||||
actual = priv->spiclock >> 8;
|
actual = priv->spiclock >> 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK);
|
spi_modifycr1(priv, setbits, SPI_CR1_BR_MASK);
|
||||||
return actual;
|
priv->frequency = frequency;
|
||||||
|
priv->actual = actual;
|
||||||
|
}
|
||||||
|
return priv->actual;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -769,33 +826,41 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
|
|||||||
uint16 setbits;
|
uint16 setbits;
|
||||||
uint16 clrbits;
|
uint16 clrbits;
|
||||||
|
|
||||||
switch (mode)
|
/* Has the mode changed? */
|
||||||
{
|
|
||||||
case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
|
|
||||||
setbits = 0;
|
|
||||||
clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
|
|
||||||
setbits = SPI_CR1_CPHA;
|
|
||||||
clrbits = SPI_CR1_CPOL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
|
|
||||||
setbits = SPI_CR1_CPOL;
|
|
||||||
clrbits = SPI_CR1_CPHA;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
|
|
||||||
setbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
|
|
||||||
clrbits = 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
spi_modifycr1(priv, setbits, clrbits);
|
if (mode != priv->mode)
|
||||||
|
{
|
||||||
|
/* Yes... Set CR1 appropriately */
|
||||||
|
|
||||||
|
switch (mode)
|
||||||
|
{
|
||||||
|
case SPIDEV_MODE0: /* CPOL=0; CPHA=0 */
|
||||||
|
setbits = 0;
|
||||||
|
clrbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPIDEV_MODE1: /* CPOL=0; CPHA=1 */
|
||||||
|
setbits = SPI_CR1_CPHA;
|
||||||
|
clrbits = SPI_CR1_CPOL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPIDEV_MODE2: /* CPOL=1; CPHA=0 */
|
||||||
|
setbits = SPI_CR1_CPOL;
|
||||||
|
clrbits = SPI_CR1_CPHA;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPIDEV_MODE3: /* CPOL=1; CPHA=1 */
|
||||||
|
setbits = SPI_CR1_CPOL|SPI_CR1_CPHA;
|
||||||
|
clrbits = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_modifycr1(priv, setbits, clrbits);
|
||||||
|
priv->mode = mode;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -819,23 +884,31 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
|
|||||||
uint16 setbits;
|
uint16 setbits;
|
||||||
uint16 clrbits;
|
uint16 clrbits;
|
||||||
|
|
||||||
switch (nbits)
|
/* Has the number of bits changed? */
|
||||||
|
|
||||||
|
if (nbits != priv->nbits)
|
||||||
{
|
{
|
||||||
case 8:
|
/* Yes... Set CR1 appropriately */
|
||||||
setbits = 0;
|
|
||||||
clrbits = SPI_CR1_DFF;
|
switch (nbits)
|
||||||
break;
|
{
|
||||||
|
case 8:
|
||||||
|
setbits = 0;
|
||||||
|
clrbits = SPI_CR1_DFF;
|
||||||
|
break;
|
||||||
|
|
||||||
case 16:
|
case 16:
|
||||||
setbits = SPI_CR1_DFF;
|
setbits = SPI_CR1_DFF;
|
||||||
clrbits = 0;
|
clrbits = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
spi_modifycr1(priv, setbits, clrbits);
|
||||||
|
priv->nbits = nbits;
|
||||||
}
|
}
|
||||||
|
|
||||||
spi_modifycr1(priv, setbits, clrbits);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
/************************************************************************************
|
||||||
@ -1094,8 +1167,12 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv)
|
|||||||
setbits = SPI_CR1_MSTR|SPI_CR1_SSI|SPI_CR1_SSM;
|
setbits = SPI_CR1_MSTR|SPI_CR1_SSI|SPI_CR1_SSM;
|
||||||
spi_modifycr1(priv, setbits, clrbits);
|
spi_modifycr1(priv, setbits, clrbits);
|
||||||
|
|
||||||
|
priv->nbits = 8;
|
||||||
|
priv->mode = SPIDEV_MODE0;
|
||||||
|
|
||||||
/* Select a default frequency of approx. 400KHz */
|
/* Select a default frequency of approx. 400KHz */
|
||||||
|
|
||||||
|
priv->frequency = 0;
|
||||||
spi_setfrequency((FAR struct spi_dev_s *)priv, 400000);
|
spi_setfrequency((FAR struct spi_dev_s *)priv, 400000);
|
||||||
|
|
||||||
/* CRCPOLY configuration */
|
/* CRCPOLY configuration */
|
||||||
@ -1227,37 +1304,4 @@ FAR struct spi_dev_s *up_spiinitialize(int port)
|
|||||||
return (FAR struct spi_dev_s *)priv;
|
return (FAR struct spi_dev_s *)priv;
|
||||||
}
|
}
|
||||||
|
|
||||||
/************************************************************************************
|
|
||||||
* Name: stm32_spitake() and stm32_spigive()
|
|
||||||
*
|
|
||||||
* Description:
|
|
||||||
* The stm32_spi1/2/3select() and stm32_spi1/2/3status() methods must call
|
|
||||||
* stm32_spitake() when the chip is selected and stm32_spigive() when the chip is
|
|
||||||
* deselected. This assures mutually exclusive access to the SPI for the duration
|
|
||||||
* while a chip is selected.
|
|
||||||
*
|
|
||||||
************************************************************************************/
|
|
||||||
|
|
||||||
void stm32_spitake(FAR struct spi_dev_s *dev)
|
|
||||||
{
|
|
||||||
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
|
|
||||||
|
|
||||||
/* Take the semaphore (perhaps waiting) */
|
|
||||||
|
|
||||||
while (sem_wait(&priv->exclsem) != 0)
|
|
||||||
{
|
|
||||||
/* The only case that an error should occur here is if the wait was awakened
|
|
||||||
* by a signal.
|
|
||||||
*/
|
|
||||||
|
|
||||||
ASSERT(errno == EINTR);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void stm32_spigive(FAR struct spi_dev_s *dev)
|
|
||||||
{
|
|
||||||
FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev;
|
|
||||||
(void)sem_post(&priv->exclsem);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */
|
#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */
|
||||||
|
@ -77,6 +77,7 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR ubyte *buffer, size_t
|
|||||||
|
|
||||||
static const struct spi_ops_s g_spiops =
|
static const struct spi_ops_s g_spiops =
|
||||||
{
|
{
|
||||||
|
0, /* lock() method not yet implemented */
|
||||||
ez80_spiselect, /* Provided externally by board logic */
|
ez80_spiselect, /* Provided externally by board logic */
|
||||||
spi_setfrequency,
|
spi_setfrequency,
|
||||||
spi_setmode,
|
spi_setmode,
|
||||||
@ -85,6 +86,7 @@ static const struct spi_ops_s g_spiops =
|
|||||||
spi_send,
|
spi_send,
|
||||||
spi_sndblock,
|
spi_sndblock,
|
||||||
spi_recvblock,
|
spi_recvblock,
|
||||||
|
0 /* registercallback not yet implemented */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* This supports is only a single SPI bus/port. If you port this to an
|
/* This supports is only a single SPI bus/port. If you port this to an
|
||||||
|
Loading…
Reference in New Issue
Block a user