diff --git a/arch/arm/src/calypso/calypso_spi.c b/arch/arm/src/calypso/calypso_spi.c index b885953b068..f540985e1c3 100644 --- a/arch/arm/src/calypso/calypso_spi.c +++ b/arch/arm/src/calypso/calypso_spi.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include "up_arch.h" @@ -60,14 +61,34 @@ struct calypso_spidev_s { struct spi_dev_s spidev; /* External driver interface */ int nbits; /* Number of transfered bits */ - sem_t exclsem; /* Mutual exclusion of devices */ + sem_t exclsem; /* Supports mutually exclusive access */ }; /* STUBS! */ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) { - return -ENOSYS; + struct calypso_spidev_s *priv = (struct efm32_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; } static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, @@ -142,6 +163,12 @@ static struct calypso_spidev_s g_spidev = void spi_init(void) { +#if 0 + /* Initialize the SPI semaphore that enforces mutually exclusive access */ + + sem_init(&priv->exclsem, 0, 1); +#endif + putreg16(SPI_SET1_EN_CLK | SPI_SET1_WR_IRQ_DIS | SPI_SET1_RDWR_IRQ_DIS, SPI_REG(REG_SET1)); diff --git a/arch/arm/src/efm32/efm32_spi.c b/arch/arm/src/efm32/efm32_spi.c index 66e17eb3034..f0dd854b4c1 100644 --- a/arch/arm/src/efm32/efm32_spi.c +++ b/arch/arm/src/efm32/efm32_spi.c @@ -768,7 +768,7 @@ static int spi_lock(struct spi_dev_s *dev, bool lock) * was awakened by a signal. */ - ASSERT(errno == EINTR); + DEBUGASSERT(errno == EINTR); } } else diff --git a/arch/arm/src/imx/imx_spi.c b/arch/arm/src/imx/imx_spi.c index 58d0e79e081..3a9ccaa5e69 100644 --- a/arch/arm/src/imx/imx_spi.c +++ b/arch/arm/src/imx/imx_spi.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/arm/src/imx/imx_spi.c * - * Copyright (C) 2009-2010, 2013 Gregory Nutt. All rights reserved. + * Copyright (C) 2009-2010, 2013, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@ #include #include +#include +#include #include #include @@ -98,8 +100,9 @@ struct imx_spidev_s { const struct spi_ops_s *ops; /* Common SPI operations */ #ifndef CONFIG_SPI_POLLWAIT - sem_t sem; /* Wait for transfer to complete */ + sem_t waitsem; /* Wait for transfer to complete */ #endif + sem_t exclsem; /* Supports mutually exclusive access */ /* These following are the source and destination buffers of the transfer. * they are retained in this structure so that they will be accessible @@ -558,9 +561,10 @@ static int spi_transfer(struct imx_spidev_s *priv, const void *txbuffer, { /* Wait to be signaled from the interrupt handler */ - ret = sem_wait(&priv->sem); + ret = sem_wait(&priv->waitsem); } while (ret < 0 && errno == EINTR); + #else /* Perform the transfer using polling logic. This will totally * dominate the CPU until the transfer is complete. Only recommended @@ -673,8 +677,9 @@ static int spi_interrupt(int irq, void *context) { /* Yes, wake up the waiting thread */ - sem_post(&priv->sem); + sem_post(&priv->waitsem); } + return OK; } #endif @@ -702,9 +707,27 @@ static int spi_interrupt(int irq, void *context) static int spi_lock(FAR struct spi_dev_s *dev, bool lock) { - /* Not implemented */ + struct imx_spidev_s *priv = (struct imx_spidev_s *)dev; - return -ENOSYS; + 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. + */ + + DEBUGASSERT(errno == EINTR); + } + } + else + { + (void)sem_post(&priv->exclsem); + } + + return OK; } /**************************************************************************** @@ -1093,8 +1116,9 @@ FAR struct spi_dev_s *up_spiinitialize(int port) /* Initialize the state structure */ #ifndef CONFIG_SPI_POLLWAIT - sem_init(&priv->sem, 0, 0); + sem_init(&priv->waitsem, 0, 0); #endif + sem_init(&priv->exclsem, 0, 1); /* Initialize control register: min frequency, ignore ready, master mode, mode=0, 8-bit */ diff --git a/arch/z80/src/ez80/ez80_spi.c b/arch/z80/src/ez80/ez80_spi.c index 6caff8a9f7b..fa3c519497f 100644 --- a/arch/z80/src/ez80/ez80_spi.c +++ b/arch/z80/src/ez80/ez80_spi.c @@ -1,7 +1,7 @@ /**************************************************************************** * arch/z80/src/ez80/ez80_spi.c * - * Copyright (C) 2009-2010 Gregory Nutt. All rights reserved. + * Copyright (C) 2009-2010, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -41,6 +41,8 @@ #include #include +#include +#include #include #include @@ -85,33 +87,32 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR uint8_t *buffer, static const struct spi_ops_s g_spiops = { spi_lock, - ez80_spiselect, /* select: Provided externally by board logic */ + ez80_spiselect, /* select: Provided externally by board logic */ spi_setfrequency, spi_setmode, - NULL, /* setbits: Variable number of bits not implemented */ + NULL, /* setbits: Variable number of bits not implemented */ #ifdef CONFIG_SPI_HWFEATURES - NULL, /* hwfeatures: Not supported */ + NULL, /* hwfeatures: Not supported */ #endif - ez80_spistatus, /* status: Provided externally by board logic */ + ez80_spistatus, /* status: Provided externally by board logic */ #ifdef CONFIG_SPI_CMDDATA ez80_spicmddata, #endif spi_send, spi_sndblock, spi_recvblock, - 0 /* registercallback: Not yet implemented */ + 0 /* registercallback: Not yet implemented */ }; /* This supports is only a single SPI bus/port. If you port this to an - * architecture with multiple SPI busses/ports, then the following must - * become an array with one 'struct spi_dev_s' instance per bus. + * architecture with multiple SPI busses/ports, then (1) you must create + * a structure, say ez80_spidev_s, containing both struct spi_dev_s and + * the mutual exclusion semaphored, and (2) the following must become an + * array with one 'struct spi_dev_s' instance per bus. */ -static struct spi_dev_s g_spidev = { &g_spiops }; - -/**************************************************************************** - * Public Data - ****************************************************************************/ +static struct spi_dev_s g_spidev = {&g_spiops}; +static sem_t g_exclsem = SEM_INITIALIZER(1); /* For mutually exclusive access */ /**************************************************************************** * Private Functions @@ -140,9 +141,25 @@ static struct spi_dev_s g_spidev = { &g_spiops }; static int spi_lock(FAR struct spi_dev_s *dev, bool lock) { - /* Not implemented */ + if (lock) + { + /* Take the semaphore (perhaps waiting) */ - return -ENOSYS; + while (sem_wait(&g_exclsem) != 0) + { + /* The only case that an error should occur here is if the wait + * was awakened by a signal. + */ + + DEBUGASSERT(errno == EINTR); + } + } + else + { + (void)sem_post(&g_exclsem); + } + + return OK; } /****************************************************************************