From 9328ea4048154b6e2392e0102cbbb33712fa0fe6 Mon Sep 17 00:00:00 2001 From: patacongo Date: Thu, 15 Oct 2009 23:16:14 +0000 Subject: Fix SPI compilation errors git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@2139 42af7a65-404d-4744-a932-0658087f49c3 --- nuttx/arch/arm/src/stm32/stm32_internal.h | 36 +++++++-- nuttx/arch/arm/src/stm32/stm32_spi.c | 117 +++++++++++++++++++--------- nuttx/arch/arm/src/stm32/stm32_spi.h | 17 +++++ 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 +#include +#include +#include + #include #include #include @@ -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 */ -- cgit v1.2.3