diff options
author | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-10-15 23:16:14 +0000 |
---|---|---|
committer | patacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3> | 2009-10-15 23:16:14 +0000 |
commit | 9328ea4048154b6e2392e0102cbbb33712fa0fe6 (patch) | |
tree | 47e4c87128d5218aa0d61bdb6d1bb7a34f12f250 | |
parent | c0b9d8a745841fb1d713a63182230b491369f219 (diff) | |
download | nuttx-9328ea4048154b6e2392e0102cbbb33712fa0fe6.tar.gz nuttx-9328ea4048154b6e2392e0102cbbb33712fa0fe6.tar.bz2 nuttx-9328ea4048154b6e2392e0102cbbb33712fa0fe6.zip |
Fix SPI compilation errors
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2139 42af7a65-404d-4744-a932-0658087f49c3
-rwxr-xr-x | nuttx/arch/arm/src/stm32/stm32_internal.h | 36 | ||||
-rwxr-xr-x | nuttx/arch/arm/src/stm32/stm32_spi.c | 117 | ||||
-rwxr-xr-x | nuttx/arch/arm/src/stm32/stm32_spi.h | 17 | ||||
-rwxr-xr-x | nuttx/configs/stm3210e-eval/src/up_spi.c | 123 |
4 files changed, 204 insertions, 89 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_internal.h b/nuttx/arch/arm/src/stm32/stm32_internal.h index 25cff135f..8cb46d824 100755 --- a/nuttx/arch/arm/src/stm32/stm32_internal.h +++ b/nuttx/arch/arm/src/stm32/stm32_internal.h @@ -498,18 +498,24 @@ EXTERN int stm32_ethinitialize(int intf); #endif /************************************************************************************ - * The external functions, stm32_spi1/2select and stm32_spi1/2status must be - * provided by board-specific logic. They are implementations of the select - * and status methods of the SPI interface defined by struct spi_ops_s (see - * include/nuttx/spi.h). All other methods (including up_spiinitialize()) - * are provided by common STM32 logic. To use this common SPI logic on your - * board: + * Name: stm32_spi1/2/3select and stm32_spi1/2/3status + * + * Description: + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be + * provided by board-specific logic. They are implementations of the select + * and status methods of the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi.h). All other methods (including up_spiinitialize()) + * are provided by common STM32 logic. To use this common SPI logic on your + * board: * * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select * pins. - * 2. Provide stm32_spi1/2select() and stm32_spi1/2status() 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 * 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 * initialization logic * 4. The handle returned by up_spiinitialize() may then be used to bind the @@ -525,6 +531,22 @@ EXTERN void stm32_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, b EXTERN ubyte stm32_spi1status(FAR struct spi_dev_s *dev, enum spi_dev_e devid); EXTERN void stm32_spi2select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected); 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 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 #if defined(__cplusplus) diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.c b/nuttx/arch/arm/src/stm32/stm32_spi.c index faa1511a7..6cd75a1f2 100755 --- a/nuttx/arch/arm/src/stm32/stm32_spi.c +++ b/nuttx/arch/arm/src/stm32/stm32_spi.c @@ -34,23 +34,25 @@ ************************************************************************************/ /************************************************************************************ - * The external functions, stm32_spi1/2/3select and stm32_spi1//3status must - * be provided by board-specific logic. They are implementations of the - * select and status methods of the SPI interface defined by struct spi_ops_s - * (see include/nuttx/spi.h). All other methods (including up_spiinitialize()) + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be + * provided by board-specific logic. They are implementations of the select + * and status methods of the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi.h). All other methods (including up_spiinitialize()) * are provided by common STM32 logic. To use this common SPI logic on your * board: * * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select * pins. - * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions - * in your board-specific logic. These functions will perform chip - * selection and status operations using GPIOs in the way your board - * is configured. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your + * board-specific logic. These functions will perform chip selection and + * 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 * initialization logic - * 4. The handle returned by up_spiinitialize() may then be used to bind - * the SPI driver to higher level logic (e.g., calling + * 4. The handle returned by up_spiinitialize() may then be used to bind the + * SPI driver to higher level logic (e.g., calling * mmcsd_spislotinitialize(), for example, will bind the SPI driver to * the SPI MMC/SD driver). * @@ -62,6 +64,10 @@ #include <nuttx/config.h> +#include <semaphore.h> +#include <errno.h> +#include <debug.h> + #include <arch/board/board.h> #include <nuttx/arch.h> #include <nuttx/spi.h> @@ -71,6 +77,7 @@ #include "chip.h" #include "stm32_internal.h" +#include "stm32_gpio.h" #include "stm32_spi.h" #if defined(CONFIG_STM32_SPI1) || defined(CONFIG_STM32_SPI2) || defined(CONFIG_STM32_SPI3) @@ -97,6 +104,7 @@ struct stm32_spidev_s #ifdef CONFIG_STM32_SPI_INTERRUPTS uint8 spiirq; /* SPI IRQ number */ #endif + sem_t spisem; }; /************************************************************************************ @@ -140,12 +148,12 @@ static const struct spi_ops_s g_sp1iops = { .select = stm32_spi1select, .setfrequency = spi_setfrequency, - .setmode = spi_setmode; - .setbits = spi_setbits; + .setmode = spi_setmode, + .setbits = spi_setbits, .status = stm32_spi1status, .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange; + .exchange = spi_exchange, #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -157,7 +165,7 @@ static struct stm32_spidev_s g_spi1dev = { .spidev = { &g_sp1iops }, .spibase = STM32_SPI1_BASE, - .spiclock = STM32_PCLK2_FREQUENCY; + .spiclock = STM32_PCLK2_FREQUENCY, #ifdef CONFIG_STM32_SPI_INTERRUPTS .spiirq = STM32_IRQ_SPI1, #endif @@ -169,12 +177,12 @@ static const struct spi_ops_s g_sp2iops = { .select = stm32_spi2select, .setfrequency = spi_setfrequency, - .setmode = spi_setmode; - .setbits = spi_setbits; + .setmode = spi_setmode, + .setbits = spi_setbits, .status = stm32_spi2status, .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange; + .exchange = spi_exchange, #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -186,7 +194,7 @@ static struct stm32_spidev_s g_spi2dev = { .spidev = { &g_sp2iops }, .spibase = STM32_SPI2_BASE, - .spiclock = STM32_PCLK1_FREQUENCY; + .spiclock = STM32_PCLK1_FREQUENCY, #ifdef CONFIG_STM32_SPI_INTERRUPTS .spiirq = STM32_IRQ_SPI2, #endif @@ -198,12 +206,12 @@ static const struct spi_ops_s g_sp3iops = { .select = stm32_spi3select, .setfrequency = spi_setfrequency, - .setmode = spi_setmode; - .setbits = spi_setbits; + .setmode = spi_setmode, + .setbits = spi_setbits, .status = stm32_spi3status, .send = spi_send, #ifdef CONFIG_SPI_EXCHANGE - .exchange = spi_exchange; + .exchange = spi_exchange, #else .sndblock = spi_sndblock, .recvblock = spi_recvblock, @@ -215,7 +223,7 @@ static struct stm32_spidev_s g_spi3dev = { .spidev = { &g_sp3iops }, .spibase = STM32_SPI2_BASE, - .spiclock = STM32_PCLK1_FREQUENCY; + .spiclock = STM32_PCLK1_FREQUENCY, #ifdef CONFIG_STM32_SPI_INTERRUPTS .spiirq = STM32_IRQ_SPI3, #endif @@ -289,11 +297,11 @@ static inline uint16 spi_readword(FAR struct stm32_spidev_s *priv) { /* Wait until the receive buffer is not empty */ - while (spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_RXNE) != 0); + while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_RXNE) != 0); /* Then return the received byte */ - return spi_regreg(priv, STM32_SPI_DR_OFFSET); + return spi_getreg(priv, STM32_SPI_DR_OFFSET); } /************************************************************************************ @@ -315,7 +323,7 @@ static inline void spi_writeword(FAR struct stm32_spidev_s *priv, uint16 word) { /* Wait until the transmit buffer is empty */ - while (spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_TXE) != 0); + while ((spi_getreg(priv, STM32_SPI_SR_OFFSET) & SPI_SR_TXE) != 0); /* Then send the byte */ @@ -395,7 +403,7 @@ static uint32 spi_setfrequency(FAR struct spi_dev_s *dev, uint32 frequency) { /* Between fPCLCK/8 and fPCLCK/16, pick the slower */ - setbits = SPI_CR1_FPCLCKd1; /* 011: fPCLK/16 */ + setbits = SPI_CR1_FPCLCKd16; /* 011: fPCLK/16 */ actual = priv->spiclock >> 4; } else if (frequency >= priv->spiclock >> 5) @@ -449,7 +457,6 @@ 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) { FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; - uint16 cr1; uint16 setbits; uint16 clrbits; @@ -500,11 +507,10 @@ 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) { FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; - uint16 cr1; uint16 setbits; uint16 clrbits; - switch (mode) + switch (nbits) { case 8: setbits = 0; @@ -575,6 +581,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, FAR struct stm32_spidev_s *priv = (FAR struct stm32_spidev_s *)dev; DEBUGASSERT(priv && priv->spibase); +# warning "TODO: Need to incorporate DMA to get good SPI performance" + /* 8- or 16-bit mode? */ if ((spi_getreg(priv, STM32_SPI_CR1_OFFSET) & SPI_CR1_DFF) != 0) @@ -611,8 +619,8 @@ static void spi_exchange(FAR struct spi_dev_s *dev, FAR const void *txbuffer, { /* 8-bit mode */ - const uint8 *src = (const uint16*)txbuffer;; - uint8 *dest = (uint16*)rxbuffer; + const uint8 *src = (const uint8*)txbuffer;; + uint8 *dest = (uint8*)rxbuffer; uint8 word; /* Get the next word to write. Is there a source buffer? */ @@ -720,7 +728,7 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv) */ clrbits = SPI_CR1_CPHA|SPI_CR1_CPOL|SPI_CR1_BR_MASK|SPI_CR1_LSBFIRST|SPI_CR1_SSI| - SPI_CR1_SSM|SPI_CR1_RXONLY|SPI_CR1_DFF|SPI_CR1_BIDIOE|SPI_CR1_BIDIMODE); + SPI_CR1_SSM|SPI_CR1_RXONLY|SPI_CR1_DFF|SPI_CR1_BIDIOE|SPI_CR1_BIDIMODE; setbits = SPI_CR1_MSTR; spi_modifycr1(priv, setbits, clrbits); @@ -732,6 +740,10 @@ static void spi_portinitialize(FAR struct stm32_spidev_s *priv) spi_putreg(priv, STM32_SPI_CRCPR_OFFSET, 7); + /* Enable the SPI semaphore that enforces mutually exclusive access */ + + sem_init(&priv->spisem, 0, 1); + /* Enable spi */ spi_modifycr1(priv, SPI_CR1_SPE, 0); @@ -787,7 +799,7 @@ FAR struct spi_dev_s *up_spiinitialize(int port) /* Set up default configuration: Master, 8-bit, etc. */ - spi_portinitialize(priv) + spi_portinitialize(priv); } else #endif @@ -800,7 +812,7 @@ FAR struct spi_dev_s *up_spiinitialize(int port) /* Set up default configuration: Master, 8-bit, etc. */ - spi_portinitialize(priv) + spi_portinitialize(priv); } else #endif @@ -817,7 +829,7 @@ FAR struct spi_dev_s *up_spiinitialize(int port) # error "Available only in connectivity devices" #endif - /* Configure SPI1 pins: SCK, MISO, and MOSI */ + /* Configure SPI3 pins: SCK, MISO, and MOSI */ stm32_configgpio(GPIO_SPI3_SCK); stm32_configgpio(GPIO_SPI3_MISO); @@ -825,7 +837,7 @@ FAR struct spi_dev_s *up_spiinitialize(int port) /* Set up default configuration: Master, 8-bit, etc. */ - spi_portinitialize(priv) + spi_portinitialize(priv); } #endif @@ -833,4 +845,37 @@ FAR struct spi_dev_s *up_spiinitialize(int port) 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->spisem) != 0) + { + /* The only case that an error should occur here is if the wait was awakened + * by a signal. + */ + + ASSERT(*get_errno_ptr() == 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->spisem); +} + #endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 || CONFIG_STM32_SPI3 */ diff --git a/nuttx/arch/arm/src/stm32/stm32_spi.h b/nuttx/arch/arm/src/stm32/stm32_spi.h index 5b9f047ea..21d95d01d 100755 --- a/nuttx/arch/arm/src/stm32/stm32_spi.h +++ b/nuttx/arch/arm/src/stm32/stm32_spi.h @@ -134,8 +134,25 @@ * Public Data ************************************************************************************/ +#ifndef __ASSEMBLY__ + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" { +#else +#define EXTERN extern +#endif + /************************************************************************************ * Public Functions ************************************************************************************/ +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* __ASSEMBLY__ */ + #endif /* __ARCH_ARM_STC_STM32_STM32_SPI_H */ diff --git a/nuttx/configs/stm3210e-eval/src/up_spi.c b/nuttx/configs/stm3210e-eval/src/up_spi.c index 058d43a29..bfad4c5ae 100755 --- a/nuttx/configs/stm3210e-eval/src/up_spi.c +++ b/nuttx/configs/stm3210e-eval/src/up_spi.c @@ -79,6 +79,36 @@ * Private Functions
************************************************************************************/
+static void stm32_chipselect(FAR struct spi_dev_s *dev, uint32 pinset, boolean pinval, boolean selected)
+{
+ spidbg("devid: %d CS: %s pinset: %08x pinval: %s\n", + (int)devid, selected ? "assert" : "de-assert", pinset, pinval ? "HIGH" : "LOW"); + + /* If we are selecting the chip, then we must call stm32_spitake to assure that we + * have mutually exclusive access to the SPI bus while the chip is selected. + */ + + if (selected) + { + stm32_spitake(dev); + } + + /* Then set the CHIP select. Usually the chip select is LOW to select and HIGH, but + * that can vary from part to part. + */ + + stm32_gpiowrite(pinset, pinval); + + /* If we just de-selected the chip, then we must call stm32_spigive to to relinquish + * our exclusive access to the SPI bus. Now, any waiting threads can have the SPI. + */ + + if (!selected) + { + stm32_spigive(dev); + } +} + /************************************************************************************
* Public Functions
************************************************************************************/
@@ -93,76 +123,65 @@ void weak_function stm32_spiinitialize(void)
{ - /* NOTE: Clocking for SPI1 and/or SPI2 was already provided in stm32_rcc.c */ + /* NOTE: Clocking for SPI1 and/or SPI2 was already provided in stm32_rcc.c. + * Configurations of SPI pins is performed in stm32_spi.c. + * Here, we only initialize chip select pins unique to the board + * architecture. + */ #ifdef CONFIG_STM32_SPI1 - /* Select SPI1 pin mapping */ - - uint32 mapr = getreg32(STM32_AFIO_MAPR); -#ifdef CONFIG_STM32_SPI1_REMAP - mapr |= AFIO_MAPR_SPI1_REMAP; -#else - mapr &= ~AFIO_MAPR_SPI1_REMAP; -#endif - putreg32(mapr, STM32_AFIO_MAPR); - - /* Configure SPI1 alternate function pins */
-
- stm32_configgpio(GPIO_SPI1_SCK);
- stm32_configgpio(GPIO_SPI1_MISO);
- stm32_configgpio(GPIO_SPI1_MOSI);
-
/* Configure the SPI-based microSD and FLASH CS GPIO */
stm32_configgpio(GPIO_MMCSD_CS);
stm32_configgpio(GPIO_FLASH_CS);
#endif - -#ifdef CONFIG_STM32_SPI2 - /* Configure SPI1 alternate function pins */
-
- stm32_configgpio(GPIO_SPI2_SCK);
- stm32_configgpio(GPIO_SPI2_MISO);
- stm32_configgpio(GPIO_SPI2_MOSI);
-
-#endif
}
/****************************************************************************
- * The external functions, stm32_spi1/2select and stm32_spi1/2status must be
- * provided by board-specific logic. These are implementations of the
- * select and status methods SPI interface defined by struct spi_ops_s (see
- * include/nuttx/spi.h). All other methods (including up_spiinitialize())
- * are provided by common logic. To use this common SPI logic on your board:
- *
- * 1. Provide stm32_spi1/2select() and stm32_spi1/2status() functions in your
- * board-specific logic. This function will perform chip selection and
- * status operations using GPIOs in the way your board is configured.
- * 2. Add a call to up_spiinitialize() in your low level initialization
- * logic
- * 3. The handle returned by up_spiinitialize() may then be used to bind the
- * SPI driver to higher level logic (e.g., calling
- * mmcsd_spislotinitialize(), for example, will bind the SPI driver to
- * the SPI MMC/SD driver).
- *
+ * Name: stm32_spi1/2/3select and stm32_spi1/2/3status + * + * Description: + * The external functions, stm32_spi1/2/3select and stm32_spi1/2/3status must be + * provided by board-specific logic. They are implementations of the select + * and status methods of the SPI interface defined by struct spi_ops_s (see + * include/nuttx/spi.h). All other methods (including up_spiinitialize()) + * are provided by common STM32 logic. To use this common SPI logic on your + * board: + * + * 1. Provide logic in stm32_boardinitialize() to configure SPI chip select + * pins. + * 2. Provide stm32_spi1/2/3select() and stm32_spi1/2/3status() functions in your + * board-specific logic. These functions will perform chip selection and + * 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 + * initialization logic + * 4. The handle returned by up_spiinitialize() may then be used to bind the + * SPI driver to higher level logic (e.g., calling + * mmcsd_spislotinitialize(), for example, will bind the SPI driver to + * the SPI MMC/SD driver). + * ****************************************************************************/
#ifdef CONFIG_STM32_SPI1
void stm32_spi1select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected)
{
- spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
+ spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert"); + uint32 pinset;
if (devid == SPIDEV_MMCSD)
{
/* Set the GPIO low to select and high to de-select */
-
- stm32_gpiowrite(GPIO_MMCSD_CS, !selected);
+ + stm32_chipselect(dev, GPIO_MMCSD_CS,!selected, selected);
}
else if (devid == SPIDEV_FLASH)
{
/* Set the GPIO low to select and high to de-select */
- stm32_gpiowrite(GPIO_FLASH_CS, !selected);
+ stm32_chipselect(dev, GPIO_FLASH_CS,!selected, selected);
}
}
@@ -184,4 +203,16 @@ ubyte stm32_spi2status(FAR struct spi_dev_s *dev, enum spi_dev_e devid) }
#endif
+#ifdef CONFIG_STM32_SPI3
+void stm32_spi3select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, boolean selected)
+{
+ spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
+}
+
+ubyte stm32_spi3status(FAR struct spi_dev_s *dev, enum spi_dev_e devid)
+{
+ return SPI_STATUS_PRESENT;
+}
+#endif
+
#endif /* CONFIG_STM32_SPI1 || CONFIG_STM32_SPI2 */
|