From 71b4709004ce55e2fe546b5a3f77b7b76064c78b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sun, 16 Jun 2013 10:09:21 -0600 Subject: Re-architected SAM3/4 SPI interface; Change BUSY bit handling in the ADS7843E driver --- nuttx/ChangeLog | 12 ++ nuttx/arch/arm/src/sam34/chip/sam_spi.h | 3 + nuttx/arch/arm/src/sam34/sam_spi.c | 191 ++++++++++++++------------- nuttx/arch/arm/src/sam34/sam_spi.h | 38 +----- nuttx/configs/sam3u-ek/README.txt | 14 +- nuttx/configs/sam3u-ek/src/sam3u-ek.h | 18 +-- nuttx/configs/sam3u-ek/src/up_spi.c | 50 +------ nuttx/configs/sam3u-ek/src/up_touchscreen.c | 14 +- nuttx/configs/sam4l-xplained/README.txt | 11 +- nuttx/configs/sam4l-xplained/src/sam_mmcsd.c | 27 ++-- nuttx/configs/sam4l-xplained/src/sam_nsh.c | 5 +- nuttx/configs/sam4l-xplained/src/sam_spi.c | 50 +------ nuttx/drivers/input/ads7843e.c | 46 ++++++- 13 files changed, 226 insertions(+), 253 deletions(-) diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index f7d096e12..9f21e5769 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -4978,3 +4978,15 @@ configs/sam4l-xplained/README.txt, and configs/sam4l-xplained/include/board.h: Add support for the SPI- based SD card on the I/O1 module (2013-6-15). + * arch/arm/src/sam34/sam_spi.c: Re-architect the SAM3/4 SPI driver + so that is it compatible with the SPI drivers of other MCUs + (2013-6-16). + * configs/sam3u-ek/src/up_touchscreen.c and configs/sam4l-xplained/src/sam_mmcsd.c: + Changed needed because of the above change the the SAM3/4 SPI + interface (2013-6-16). + * drivers/input/ads7843e.c: Remove the wait for the touchscreen busy + bit. I don't see the busy bit changing on the SAM3U-EK board. But + maybe it is not supposed to. From my reading of the ADS7843 spec, it + would not be appropriate to wait for the BUSY bit to de-asserted + anyway (since it is only de-asserted when we read the data) + (2013-6-16). \ No newline at end of file diff --git a/nuttx/arch/arm/src/sam34/chip/sam_spi.h b/nuttx/arch/arm/src/sam34/chip/sam_spi.h index 887b7f656..a0344c6a8 100644 --- a/nuttx/arch/arm/src/sam34/chip/sam_spi.h +++ b/nuttx/arch/arm/src/sam34/chip/sam_spi.h @@ -49,6 +49,9 @@ /**************************************************************************************** * Pre-processor Definitions ****************************************************************************************/ +/* General definitions ******************************************************************/ + +#define SAM_SPI_NCS 4 /* Four chip selects */ /* SPI register offsets *****************************************************************/ diff --git a/nuttx/arch/arm/src/sam34/sam_spi.c b/nuttx/arch/arm/src/sam34/sam_spi.c index cf7518d0d..65ebfa922 100644 --- a/nuttx/arch/arm/src/sam34/sam_spi.c +++ b/nuttx/arch/arm/src/sam34/sam_spi.c @@ -43,6 +43,7 @@ #include #include #include +#include #include #include #include @@ -67,6 +68,7 @@ /**************************************************************************** * Definitions ****************************************************************************/ +/* Configuration ************************************************************/ /* Select MCU-specific settings * * For the SAM3U, SPI is driven by the main clock. @@ -81,6 +83,7 @@ # error Unrecognized SAM architecture #endif +/* Debug *******************************************************************/ /* Check if SPI debut is enabled (non-standard.. no support in * include/debug.h */ @@ -106,26 +109,16 @@ * Private Types ****************************************************************************/ -/* The state of one chip select */ +/* The state of the one chip select */ -#ifndef CONFIG_SPI_OWNBUS -struct sam_chipselect_s +struct sam_spidev_s { + struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ +#ifndef CONFIG_SPI_OWNBUS uint32_t frequency; /* Requested clock frequency */ uint32_t actual; /* Actual clock frequency */ uint8_t nbits; /* Width of word in bits (8 to 16) */ uint8_t mode; /* Mode 0,1,2,3 */ -}; -#endif - -/* The overall state of the SPI interface */ - -struct sam_spidev_s -{ - struct spi_dev_s spidev; /* Externally visible part of the SPI interface */ -#ifndef CONFIG_SPI_OWNBUS - sem_t exclsem; /* Held while chip is selected for mutual exclusion */ - struct sam_chipselect_s csstate[4]; #endif uint8_t cs; /* Chip select number */ }; @@ -194,12 +187,17 @@ static const struct spi_ops_s g_spiops = .registercallback = 0, /* Not implemented */ }; -/* SPI device structure */ +#ifdef CONFIG_SPI_OWNBUS +/* Single chip select device structure structure */ -static struct sam_spidev_s g_spidev = -{ - .spidev = { &g_spiops }, -}; +static struct sam_spidev_s g_spidev; + +#else +/* Held while chip is selected for mutual exclusion */ + +static sem_t g_spisem; +static bool g_spinitialized = false; +#endif /* This array maps chip select numbers (0-3) to CSR register addresses */ @@ -330,14 +328,12 @@ static inline uint32_t spi_cs2pcs(FAR struct sam_spidev_s *priv) #ifndef CONFIG_SPI_OWNBUS static int spi_lock(FAR struct spi_dev_s *dev, bool lock) { - FAR struct sam_spidev_s *priv = (FAR struct sam_spidev_s *)dev; - spivdbg("lock=%d\n", lock); if (lock) { /* Take the semaphore (perhaps waiting) */ - while (sem_wait(&priv->exclsem) != 0) + while (sem_wait(&g_spisem) != 0) { /* The only case that an error should occur here is if the wait was awakened * by a signal. @@ -348,8 +344,9 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) } else { - (void)sem_post(&priv->exclsem); + (void)sem_post(&g_spisem); } + return OK; } #endif @@ -381,15 +378,7 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) spivdbg("selected=%d\n", selected); if (selected) { - /* At this point, we expect no chip selected */ - - DEBUGASSERT(priv->cs == 0xff); - - /* Get the chip select number used with this SPI device */ - - priv->cs = sam_spicsnumber(devid); spivdbg("cs=%d\n", priv->cs); - DEBUGASSERT(priv->cs >= 0 && priv->cs <= 3); /* Before writing the TDR, the PCS field in the SPI_MR register must be set * in order to select a slave. @@ -400,19 +389,6 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) regval |= (spi_cs2pcs(priv) << SPI_MR_PCS_SHIFT); putreg32(regval, SAM_SPI_MR); } - else - { - /* At this point, we expect the chip to have already been selected */ - -#ifdef CONFIG_DEBUG - int cs = sam_spicsnumber(devid); - DEBUGASSERT(priv->cs == cs); -#endif - - /* Mark no chip selected */ - - priv->cs = 0xff; - } /* Perform any board-specific chip select operations. PIO chip select * pins may be programmed by the board specific logic in one of two @@ -429,7 +405,7 @@ static int spi_lock(FAR struct spi_dev_s *dev, bool lock) */ sam_spiselect(devid, selected); - } +} /**************************************************************************** * Name: spi_setfrequency @@ -457,16 +433,15 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) uint32_t regaddr; spivdbg("cs=%d frequency=%d\n", priv->cs, frequency); - DEBUGASSERT(priv->cs >= 0 && priv->cs <= 3); /* Check if the requested frequency is the same as the frequency selection */ #ifndef CONFIG_SPI_OWNBUS - if (priv->csstate[priv->cs].frequency == frequency) + if (priv->frequency == frequency) { /* We are already at this frequency. Return the actual. */ - return priv->csstate[priv->cs].actual; + return priv->actual; } #endif @@ -492,7 +467,7 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) regaddr = g_csraddr[priv->cs]; regval = getreg32(regaddr); - 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; /* DLYBS: Delay Before SPCK. This field defines the delay from NPCS valid to the @@ -534,8 +509,8 @@ static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency) /* Save the frequency setting */ #ifndef CONFIG_SPI_OWNBUS - priv->csstate[priv->cs].frequency = frequency; - priv->csstate[priv->cs].actual = actual; + priv->frequency = frequency; + priv->actual = actual; #endif spidbg("Frequency %d->%d\n", frequency, actual); @@ -564,19 +539,18 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) uint32_t regaddr; spivdbg("cs=%d mode=%d\n", priv->cs, mode); - DEBUGASSERT(priv->cs >= 0 && priv->cs <= 3); /* Has the mode changed? */ #ifndef CONFIG_SPI_OWNBUS - if (mode != priv->csstate[priv->cs].mode) + if (mode != priv->mode) { #endif /* Yes... Set the mode appropriately */ regaddr = g_csraddr[priv->cs]; regval = getreg32(regaddr); - regval &= ~(SPI_CSR_CPOL|SPI_CSR_NCPHA); + regval &= ~(SPI_CSR_CPOL | SPI_CSR_NCPHA); switch (mode) { @@ -606,7 +580,7 @@ static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode) /* Save the mode so that subsequent re-configurations will be faster */ #ifndef CONFIG_SPI_OWNBUS - priv->csstate[priv->cs].mode = mode; + priv->mode = mode; } #endif } @@ -634,7 +608,6 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) spivdbg("cs=%d nbits=%d\n", priv->cs, nbits); DEBUGASSERT(priv && nbits > 7 && nbits < 17); - DEBUGASSERT(priv->cs >= 0 && priv->cs <= 3); /* NOTE: The logic in spi_send and in spi_exchange only handles 8-bit * data at the present time. So the following extra assertion is a @@ -646,7 +619,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) /* Has the number of bits changed? */ #ifndef CONFIG_SPI_OWNBUS - if (nbits != priv->csstate[priv->cs].nbits) + if (nbits != priv->nbits) { #endif /* Yes... Set number of bits appropriately */ @@ -662,7 +635,7 @@ static void spi_setbits(FAR struct spi_dev_s *dev, int nbits) /* Save the selection so the subsequence re-configurations will be faster */ #ifndef CONFIG_SPI_OWNBUS - priv->csstate[priv->cs].nbits = nbits; + priv->nbits = nbits; } #endif } @@ -889,70 +862,106 @@ static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nw * Initialize the selected SPI port * * Input Parameter: - * Port number (for hardware that has mutiple SPI interfaces) + * cs - Chip select number (identifying the "logical" SPI port) * * Returned Value: * Valid SPI device structure reference on succcess; a NULL on failure * ****************************************************************************/ -FAR struct spi_dev_s *up_spiinitialize(int port) +FAR struct spi_dev_s *up_spiinitialize(int cs) { - FAR struct sam_spidev_s *priv = &g_spidev; + FAR struct sam_spidev_s *priv; irqstate_t flags; - /* The SAM3U has only a single SPI port */ + /* The support SAM parts have only a single SPI port */ - spivdbg("port=%d\n", port); - DEBUGASSERT(port == 0); + spivdbg("cs=%d\n", cs); + DEBUGASSERT(cs >= 0 && cs <= SAM_SPI_NCS); - /* Set up the initial state */ +#ifdef CONFIG_SPI_OWNBUS + /* There is only one device on the bus and, therefore, there is only one + * supported chip select. In this case, use the single, pre-allocated + * chip select structure. + */ - priv->cs = 0xff; + priv = &g_spidev; - /* Enable clocking to the SPI block */ +#else + /* Allocate a new state structure for this chip select. NOTE that there + * is no protection if the same chip select is used in two different + * chip select structures. + */ - flags = irqsave(); - sam_spi_enableclk(); + priv = (FAR struct sam_spidev_s *)zalloc(sizeof(struct sam_spidev_s)); + if (!priv) + { + spivdbg("ERROR: Failed to allocate a chip select structure\n", cs); + return NULL; + } +#endif - /* Configure multiplexed pins as connected on the board. Chip select pins - * must be configured by board-specific logic. + /* Set up the initial state for this chip select structure. Other fields + * were zeroed by zalloc(). */ - sam_configgpio(GPIO_SPI0_MISO); - sam_configgpio(GPIO_SPI0_MOSI); - sam_configgpio(GPIO_SPI0_SPCK); + priv->spidev.ops = &g_spiops; + priv->cs = cs; - /* Disable SPI clocking */ +#ifndef CONFIG_SPI_OWNBUS + /* Has the SPI hardware been initialized? */ + + if (!g_spinitialized) +#endif + { + /* Enable clocking to the SPI block */ + + flags = irqsave(); + sam_spi_enableclk(); + + /* Configure multiplexed pins as connected on the board. Chip select + * pins must be configured by board-specific logic. + */ + + sam_configgpio(GPIO_SPI0_MISO); + sam_configgpio(GPIO_SPI0_MOSI); + sam_configgpio(GPIO_SPI0_SPCK); - putreg32(SPI_CR_SPIDIS, SAM_SPI_CR); + /* Disable SPI clocking */ - /* Execute a software reset of the SPI (twice) */ + putreg32(SPI_CR_SPIDIS, SAM_SPI_CR); - putreg32(SPI_CR_SWRST, SAM_SPI_CR); - putreg32(SPI_CR_SWRST, SAM_SPI_CR); - irqrestore(flags); + /* Execute a software reset of the SPI (twice) */ - /* Configure the SPI mode register */ + putreg32(SPI_CR_SWRST, SAM_SPI_CR); + putreg32(SPI_CR_SWRST, SAM_SPI_CR); + irqrestore(flags); - putreg32(SPI_MR_MSTR | SPI_MR_MODFDIS, SAM_SPI_MR); + /* Configure the SPI mode register */ - /* And enable the SPI */ + putreg32(SPI_MR_MSTR | SPI_MR_MODFDIS, SAM_SPI_MR); - putreg32(SPI_CR_SPIEN, SAM_SPI_CR); - up_mdelay(20); + /* And enable the SPI */ - /* Flush any pending transfers */ + putreg32(SPI_CR_SPIEN, SAM_SPI_CR); + up_mdelay(20); - (void)getreg32(SAM_SPI_SR); - (void)getreg32(SAM_SPI_RDR); + /* Flush any pending transfers */ - /* Initialize the SPI semaphore that enforces mutually exclusive access */ + (void)getreg32(SAM_SPI_SR); + (void)getreg32(SAM_SPI_RDR); #ifndef CONFIG_SPI_OWNBUS - sem_init(&priv->exclsem, 0, 1); + /* Initialize the SPI semaphore that enforces mutually exclusive + * access to the SPI registers. + */ + + sem_init(&g_spisem, 0, 1); + g_spinitialized = true; #endif - spi_dumpregs("After initialization"); + spi_dumpregs("After initialization"); + } + return &priv->spidev; } #endif /* CONFIG_SAM34_SPI */ diff --git a/nuttx/arch/arm/src/sam34/sam_spi.h b/nuttx/arch/arm/src/sam34/sam_spi.h index 77e6e26f3..dfcfe20b3 100644 --- a/nuttx/arch/arm/src/sam34/sam_spi.h +++ b/nuttx/arch/arm/src/sam34/sam_spi.h @@ -79,15 +79,13 @@ extern "C" ************************************************************************************/ /**************************************************************************** - * Name: sam_spicsnumber, sam_spiselect, sam_spistatus, and sam_spicmddata + * Name: sam_spiselect, sam_spistatus, and sam_spicmddata * * Description: * These external functions must be provided by board-specific logic. They * include: * - * o sam_spicsnumber and sam_spiselect which are helper functions to - * manage the board-specific aspects of the unique SAM3/4 chip select - * architecture. + * o sam_spiselect is a functions tomanage the board-specific chip selects * o sam_spistatus and sam_spicmddata: Implementations of the status * and cmddata methods of the SPI interface defined by struct spi_ops_ * (see include/nuttx/spi.h). All other methods including @@ -97,10 +95,9 @@ extern "C" * * 1. Provide logic in sam_boardinitialize() to configure SPI chip select * pins. - * 2. Provide sam_spicsnumber(), sam_spiselect() and sam_spistatus() - * 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 sam_spiselect() and sam_spistatus() 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. If CONFIG_SPI_CMDDATA is defined in the NuttX configuration, provide * sam_spicmddata() functions in your board-specific logic. This * function will perform cmd/data selection operations using GPIOs in @@ -118,31 +115,6 @@ extern "C" struct spi_dev_s; enum spi_dev_e; -/**************************************************************************** - * Name: sam_spicsnumber - * - * Description: - * The SAM3/4 has 4 CS registers for controlling device features. This - * function must be provided by board-specific code. Given a logical device - * ID, this function returns a number from 0 to 3 that identifies one of - * these SAM3/4 CS resources. - * - * If CONFIG_SPI_OWNBUS is not defined and the GPIO is controlled by - * sam_spiselect, then the same CS register may be used to control - * multiple devices. - * - * Input Parameters: - * dev - SPI device info - * devid - Identifies the (logical) device - * - * Returned Values: - * On success, a CS number from 0 to 3 is returned; A negated errno may - * be returned on a failure. - * - ****************************************************************************/ - -int sam_spicsnumber(enum spi_dev_e devid); - /**************************************************************************** * Name: sam_spiselect * diff --git a/nuttx/configs/sam3u-ek/README.txt b/nuttx/configs/sam3u-ek/README.txt index 59aa65144..32d994329 100644 --- a/nuttx/configs/sam3u-ek/README.txt +++ b/nuttx/configs/sam3u-ek/README.txt @@ -572,20 +572,24 @@ Configuration sub-directories application. You can enable the touchscreen and test by modifying the default configuration in the following ways: - Drivers: + Device Drivers + CONFIG_SPI=y : Enable SPI support + CONFIG_SPI_EXCHANGE=y : The exchange() method is supported + CONFIG_SPI_OWNBUS=y : Smaller code if this is the only SPI device + CONFIG_INPUT=y : Enable support for input devices CONFIG_INPUT_ADS7843E=y : Enable support for the XPT2048 - CONFIG_ADS7843E_SPIDEV=0 : Use SPI for communication + CONFIG_ADS7843E_SPIDEV=2 : Use SPI CS 2 for communication CONFIG_ADS7843E_SPIMODE=0 : Use SPI mode 0 CONFIG_ADS7843E_THRESHX=39 : These will probably need to be tuned CONFIG_ADS7843E_THRESHY=51 - CONFIG_SPI=y : Enable SPI support - CONFIG_SPI_EXCHANGE=n : exchange() method is not supported + + System Type -> Peripherals: + CONFIG_SAM34_SPI=y : Enable support for SPI System Type: CONFIG_GPIO_IRQ=y : GPIO interrupt support CONFIG_GPIOA_IRQ=y : Enable GPIO interrupts from port A - CONFIG_SAM34_SPI=y : Enable support for SPI RTOS Features: CONFIG_DISABLE_SIGNALS=n : Signals are required diff --git a/nuttx/configs/sam3u-ek/src/sam3u-ek.h b/nuttx/configs/sam3u-ek/src/sam3u-ek.h index 909abc42a..af68df42a 100644 --- a/nuttx/configs/sam3u-ek/src/sam3u-ek.h +++ b/nuttx/configs/sam3u-ek/src/sam3u-ek.h @@ -190,6 +190,7 @@ #define GPIO_TSC_NPCS2 (GPIO_OUTPUT | GPIO_CFG_PULLUP | GPIO_OUTPUT_SET | \ GPIO_PORT_PIOC | GPIO_PIN14) +#define TSC_CSNUM 2 /************************************************************************************ * Public Types @@ -225,13 +226,13 @@ void weak_function sam_spiinitialize(void); void weak_function sam_usbinitialize(void); -/**************************************************************************** +/************************************************************************************ * Name: sam_hsmciinit * * Description: * Initialize HSMCI support * - ****************************************************************************/ + ************************************************************************************/ #ifdef CONFIG_SAM34_HSMCI int weak_function sam_hsmciinit(void); @@ -239,21 +240,21 @@ int weak_function sam_hsmciinit(void); # define sam_hsmciinit() #endif -/**************************************************************************** +/************************************************************************************ * Name: up_ledinit - ****************************************************************************/ + ************************************************************************************/ #ifdef CONFIG_ARCH_LEDS void up_ledinit(void); #endif -/**************************************************************************** +/************************************************************************************ * Name: sam_cardinserted * * Description: * Check if a card is inserted into the selected HSMCI slot * - ****************************************************************************/ + ************************************************************************************/ #ifdef CONFIG_SAM34_HSMCI bool sam_cardinserted(unsigned char slot); @@ -261,13 +262,13 @@ bool sam_cardinserted(unsigned char slot); # define sam_cardinserted(slot) (false) #endif -/**************************************************************************** +/************************************************************************************ * Name: sam_writeprotected * * Description: * Check if a card is inserted into the selected HSMCI slot * - ****************************************************************************/ + ************************************************************************************/ #ifdef CONFIG_SAM34_HSMCI bool sam_writeprotected(unsigned char slot); @@ -277,4 +278,3 @@ bool sam_writeprotected(unsigned char slot); #endif /* __ASSEMBLY__ */ #endif /* __CONFIGS_SAM3U_EK_SRC_SAM3U_EK_H */ - diff --git a/nuttx/configs/sam3u-ek/src/up_spi.c b/nuttx/configs/sam3u-ek/src/up_spi.c index b14029f5d..5d4073237 100644 --- a/nuttx/configs/sam3u-ek/src/up_spi.c +++ b/nuttx/configs/sam3u-ek/src/up_spi.c @@ -107,28 +107,25 @@ void weak_function sam_spiinitialize(void) } /**************************************************************************** - * Name: sam_spicsnumber, sam_spiselect, sam_spistatus, and sam_spicmddata + * Name: sam_spiselect, sam_spistatus, and sam_spicmddata * * Description: * These external functions must be provided by board-specific logic. They * include: * - * o sam_spicsnumber and sam_spiselect which are helper functions to - * manage the board-specific aspects of the unique SAM3U chip select - * architecture. + * o sam_spiselect is a functions tomanage the board-specific chip selects * o sam_spistatus and sam_spicmddata: Implementations of the status * and cmddata methods of the SPI interface defined by struct spi_ops_ * (see include/nuttx/spi.h). All other methods including - * up_spiinitialize()) are provided by common SAM3U logic. + * up_spiinitialize()) are provided by common SAM3/4 logic. * * To use this common SPI logic on your board: * * 1. Provide logic in sam_boardinitialize() to configure SPI chip select * pins. - * 2. Provide sam_spicsnumber(), sam_spiselect() and sam_spistatus() - * 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 sam_spiselect() and sam_spistatus() 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. If CONFIG_SPI_CMDDATA is defined in the NuttX configuration, provide * sam_spicmddata() functions in your board-specific logic. This * function will perform cmd/data selection operations using GPIOs in @@ -142,41 +139,6 @@ void weak_function sam_spiinitialize(void) * ****************************************************************************/ -/**************************************************************************** - * Name: sam_spicsnumber - * - * Description: - * The SAM3U has 4 CS registers for controlling device features. This - * function must be provided by board-specific code. Given a logical device - * ID, this function returns a number from 0 to 3 that identifies one of - * these SAM3U CS resources. - * - * Input Parameters: - * devid - Identifies the (logical) device - * - * Returned Values: - * On success, a CS number from 0 to 3 is returned; A negated errno may - * be returned on a failure. - * - ****************************************************************************/ - -int sam_spicsnumber(enum spi_dev_e devid) -{ - int cs = -EINVAL; - -#if defined(CONFIG_INPUT) && defined(CONFIG_INPUT_ADS7843E) - if (devid == SPIDEV_TOUCHSCREEN) - { - /* Assert the CS pin to the OLED display */ - - cs = 2; - } -#endif - - spidbg("devid: %d CS: %d\n", (int)devid, cs); - return cs; -} - /**************************************************************************** * Name: sam_spiselect * diff --git a/nuttx/configs/sam3u-ek/src/up_touchscreen.c b/nuttx/configs/sam3u-ek/src/up_touchscreen.c index ea2ad3d0a..46a814c6f 100644 --- a/nuttx/configs/sam3u-ek/src/up_touchscreen.c +++ b/nuttx/configs/sam3u-ek/src/up_touchscreen.c @@ -75,11 +75,11 @@ #endif #ifndef CONFIG_ADS7843E_SPIDEV -# define CONFIG_ADS7843E_SPIDEV 0 +# define CONFIG_ADS7843E_SPIDEV TSC_CSNUM #endif -#if CONFIG_ADS7843E_SPIDEV != 0 -# error "CONFIG_ADS7843E_SPIDEV must be zero" +#if CONFIG_ADS7843E_SPIDEV != TSC_CSNUM +# error "CONFIG_ADS7843E_SPIDEV must have the same value as TSC_CSNUM" #endif #ifndef CONFIG_ADS7843E_DEVMINOR @@ -247,12 +247,12 @@ int arch_tcinitialize(int minor) sam_gpioirq(GPIO_TCS_IRQ); - /* Get an instance of the SPI interface */ + /* Get an instance of the SPI interface for the touchscreen chip select */ - dev = up_spiinitialize(CONFIG_ADS7843E_SPIDEV); + dev = up_spiinitialize(TSC_CSNUM); if (!dev) { - idbg("Failed to initialize SPI bus %d\n", CONFIG_ADS7843E_SPIDEV); + idbg("Failed to initialize SPI chip select %d\n", TSC_CSNUM); return -ENODEV; } @@ -261,7 +261,7 @@ int arch_tcinitialize(int minor) ret = ads7843e_register(dev, &g_tscinfo, CONFIG_ADS7843E_DEVMINOR); if (ret < 0) { - idbg("Failed to initialize SPI bus %d\n", CONFIG_ADS7843E_SPIDEV); + idbg("Failed to initialize SPI chip select %d\n", TSC_CSNUM); /* up_spiuninitialize(dev); */ return -ENODEV; } diff --git a/nuttx/configs/sam4l-xplained/README.txt b/nuttx/configs/sam4l-xplained/README.txt index 79b6f5bc8..4b67f6513 100644 --- a/nuttx/configs/sam4l-xplained/README.txt +++ b/nuttx/configs/sam4l-xplained/README.txt @@ -698,8 +698,9 @@ Configuration sub-directories CONFIG_SAM34_SPI=y : Enable the SAM4L SPI peripheral Board Selection -> Common Board Options - CONFIG_NSH_MMCSDSLOTNO=0 : Only one slot, slot 0 - CONFIG_NSH_MMCSDSPIPORTNO=0 : Only one SPI port, port 0 + CONFIG_NSH_MMCSDSLOTNO=0 : Only one MMC/SD slot, slot 0 + CONFIG_NSH_MMCSDSPIPORTNO=0 : Use CS=0 if the I/O1 is in EXT1, OR + CONFIG_NSH_MMCSDSPIPORTNO=2 : Use CS=2 if the I/O1 is in EXT2 Board Selection -> SAM4L Xplained Pro Modules CONFIG_SAM4L_XPLAINED_IOMODULE=y : I/O1 module is connected @@ -708,7 +709,8 @@ Configuration sub-directories Device Drivers CONFIG_SPI=y : Enable SPI support - CONFIG_SPI_EXCHANGE=y : The exchang() method is supported + CONFIG_SPI_EXCHANGE=y : The exchange() method is supported + CONFIG_SPI_OWNBUS=y : Smaller code if this is the only SPI device CONFIG_MMCSD=y : Enable MMC/SD support CONFIG_MMCSD_NSLOTS=1 : Only one MMC/SD card slot @@ -725,3 +727,6 @@ Configuration sub-directories jumper. Otherwise, you have lookpack on USART0 and NSH will *not* behave very well (since its outgoing prompts also appear as incoming commands). + + STATUS: As of 2013-6-16, the SPI interface is not communicating with + the SD card. \ No newline at end of file diff --git a/nuttx/configs/sam4l-xplained/src/sam_mmcsd.c b/nuttx/configs/sam4l-xplained/src/sam_mmcsd.c index be4a334ec..c23adf324 100644 --- a/nuttx/configs/sam4l-xplained/src/sam_mmcsd.c +++ b/nuttx/configs/sam4l-xplained/src/sam_mmcsd.c @@ -46,6 +46,8 @@ #include #include +#include "sam4l-xplained.h" + #ifdef CONFIG_SAM4L_XPLAINED_IOMODULE /**************************************************************************** @@ -65,7 +67,6 @@ # error MMC/SD support is required (CONFIG_MMCSD) #endif -#define SAM34_MMCSDSPIPORTNO 0 /* Port is SPI (there is only one port) */ #define SAM34_MMCSDSLOTNO 0 /* There is only one slot */ /**************************************************************************** @@ -89,34 +90,34 @@ int sam_sdinitialize(int minor) FAR struct spi_dev_s *spi; int ret; - /* Get the SPI port */ + /* Get the SPI driver instance for the SD chip select */ - fvdbg("Initializing SPI port %d\n", SAM34_MMCSDSPIPORTNO); + fvdbg("Initializing SPI chip select %d\n", SD_CSNO); - spi = up_spiinitialize(SAM34_MMCSDSPIPORTNO); + spi = up_spiinitialize(SD_CSNO); if (!spi) { - fdbg("Failed to initialize SPI port %d\n", SAM34_MMCSDSPIPORTNO); + fdbg("Failed to initialize SPI chip select %d\n", SD_CSNO); return -ENODEV; } - fvdbg("Successfully initialized SPI port %d\n", SAM34_MMCSDSPIPORTNO); + fvdbg("Successfully initialized SPI chip select %d\n", SD_CSNO); - /* Bind the SPI port to the slot */ + /* Bind the SPI device for the chip select to the slot */ - fvdbg("Binding SPI port %d to MMC/SD slot %d\n", - SAM34_MMCSDSPIPORTNO, SAM34_MMCSDSLOTNO); + fvdbg("Binding SPI chip select %d to MMC/SD slot %d\n", + SD_CSNO, SAM34_MMCSDSLOTNO); ret = mmcsd_spislotinitialize(minor, SAM34_MMCSDSLOTNO, spi); if (ret < 0) { - fdbg("Failed to bind SPI port %d to MMC/SD slot %d: %d\n", - SAM34_MMCSDSPIPORTNO, SAM34_MMCSDSLOTNO, ret); + fdbg("Failed to bind SPI chip select %d to MMC/SD slot %d: %d\n", + SD_CSNO, SAM34_MMCSDSLOTNO, ret); return ret; } - fvdbg("Successfuly bound SPI port %d to MMC/SD slot %d\n", - SAM34_MMCSDSPIPORTNO, SAM34_MMCSDSLOTNO); + fvdbg("Successfuly bound SPI chip select %d to MMC/SD slot %d\n", + SD_CSNO, SAM34_MMCSDSLOTNO); return OK; } diff --git a/nuttx/configs/sam4l-xplained/src/sam_nsh.c b/nuttx/configs/sam4l-xplained/src/sam_nsh.c index e5c77a926..a2b8b8534 100644 --- a/nuttx/configs/sam4l-xplained/src/sam_nsh.c +++ b/nuttx/configs/sam4l-xplained/src/sam_nsh.c @@ -52,15 +52,14 @@ /* Support for the SD card slot on the I/O1 module */ /* Verify NSH PORT and SLOT settings */ -# define SAM34_MMCSDSPIPORTNO 0 /* Port is SPI (there is only one port) */ # define SAM34_MMCSDSLOTNO 0 /* There is only one slot */ # if defined(CONFIG_NSH_MMCSDSLOTNO) && CONFIG_NSH_MMCSDSLOTNO != SAM34_MMCSDSLOTNO # error Only one MMC/SD slot: Slot 0 (CONFIG_NSH_MMCSDSLOTNO) # endif -# if defined(CONFIG_NSH_MMCSDSPIPORTNO) && CONFIG_NSH_MMCSDSPIPORTNO != SAM34_MMCSDSPIPORTNO -# error Only one MMC/SD port: Port 0 (CONFIG_NSH_MMCSDSPIPORTNO) +# if defined(CONFIG_NSH_MMCSDSPIPORTNO) && CONFIG_NSH_MMCSDSPIPORTNO != SD_CSNO +# error CONFIG_NSH_MMCSDSPIPORTNO must have the same value as SD_CSNO # endif /* Default MMC/SD minor number */ diff --git a/nuttx/configs/sam4l-xplained/src/sam_spi.c b/nuttx/configs/sam4l-xplained/src/sam_spi.c index b977db246..465f59e61 100644 --- a/nuttx/configs/sam4l-xplained/src/sam_spi.c +++ b/nuttx/configs/sam4l-xplained/src/sam_spi.c @@ -104,28 +104,25 @@ void weak_function sam_spiinitialize(void) } /**************************************************************************** - * Name: sam_spicsnumber, sam_spiselect, sam_spistatus, and sam_spicmddata + * Name: sam_spiselect, sam_spistatus, and sam_spicmddata * * Description: * These external functions must be provided by board-specific logic. They * include: * - * o sam_spicsnumber and sam_spiselect which are helper functions to - * manage the board-specific aspects of the unique SAM3U chip select - * architecture. + * o sam_spiselect is a functions tomanage the board-specific chip selects * o sam_spistatus and sam_spicmddata: Implementations of the status * and cmddata methods of the SPI interface defined by struct spi_ops_ * (see include/nuttx/spi.h). All other methods including - * up_spiinitialize()) are provided by common SAM3U logic. + * up_spiinitialize()) are provided by common SAM3/4 logic. * * To use this common SPI logic on your board: * * 1. Provide logic in sam_boardinitialize() to configure SPI chip select * pins. - * 2. Provide sam_spicsnumber(), sam_spiselect() and sam_spistatus() - * 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 sam_spiselect() and sam_spistatus() 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. If CONFIG_SPI_CMDDATA is defined in the NuttX configuration, provide * sam_spicmddata() functions in your board-specific logic. This * function will perform cmd/data selection operations using GPIOs in @@ -139,41 +136,6 @@ void weak_function sam_spiinitialize(void) * ****************************************************************************/ -/**************************************************************************** - * Name: sam_spicsnumber - * - * Description: - * The SAM3U has 4 CS registers for controlling device features. This - * function must be provided by board-specific code. Given a logical device - * ID, this function returns a number from 0 to 3 that identifies one of - * these SAM3U CS resources. - * - * Input Parameters: - * devid - Identifies the (logical) device - * - * Returned Values: - * On success, a CS number from 0 to 3 is returned; A negated errno may - * be returned on a failure. - * - ****************************************************************************/ - -int sam_spicsnumber(enum spi_dev_e devid) -{ - int cs = -EINVAL; - -#ifdef CONFIG_SAM4L_XPLAINED_IOMODULE - if (devid == SPIDEV_MMCSD) - { - /* Return the chip select number */ - - cs = SD_CSNO; - } -#endif - - spidbg("devid: %d CS: %d\n", (int)devid, cs); - return cs; -} - /**************************************************************************** * Name: sam_spiselect * diff --git a/nuttx/drivers/input/ads7843e.c b/nuttx/drivers/input/ads7843e.c index 98893a2f6..7d1a0c3ea 100644 --- a/nuttx/drivers/input/ads7843e.c +++ b/nuttx/drivers/input/ads7843e.c @@ -104,7 +104,9 @@ static void ads7843e_lock(FAR struct spi_dev_s *spi); static void ads7843e_unlock(FAR struct spi_dev_s *spi); #endif +#if 0 static inline void ads7843e_waitbusy(FAR struct ads7843e_dev_s *priv); +#endif static uint16_t ads7843e_sendcmd(FAR struct ads7843e_dev_s *priv, uint8_t cmd); /* Interrupts and data sampling */ @@ -268,6 +270,7 @@ static inline void ads7843e_configspi(FAR struct spi_dev_s *spi) * Name: ads7843e_waitbusy ****************************************************************************/ +#if 0 /* Not used */ static inline void ads7843e_waitbusy(FAR struct ads7843e_dev_s *priv) { /* BUSY is high impedance when the ads7843e not selected. When the @@ -277,9 +280,41 @@ static inline void ads7843e_waitbusy(FAR struct ads7843e_dev_s *priv) while (priv->config->busy(priv->config)); } +#endif /**************************************************************************** * Name: ads7843e_sendcmd + * + * Description. + * The command/data sequences is as follows: + * + * DCLK + * 1 2 3 4 5 6 7 8 1 2 3 4 ... + * S A2 A1 A0 MODE SER PD1 PD0 + * DFR + * START CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC + * CMD + * Aquisition AAAAAAAAAAA + * TIME + * BUSY BBBBBBBB + * Reported + * 12-bit DDDDDDDDDDDD... + * response + * + * The BUSY output is high imedance when /CS is high. BUSY goes low when + * /CS goes low (within 200ns). BUSY goes high on the falling edge of the + * 8th clock (within 200ns); BUSY goes low again after the falling edge of + * first clock of the 12-bit data read, at the leading edge of the MS bit + * 11 of the 12-bit data response. + * + * The acquisition time is 3 clock cycles and so should be complete at the + * end of the command transfer. Other places say that this time is + * nominally 2 microseconds. + * + * So what good is this BUSY? Many boards do not even bother to bring it + * to the MCU. It looks like busy will stick high until we read the data + * so it does not really make any sense to wait on it. + * ****************************************************************************/ static uint16_t ads7843e_sendcmd(FAR struct ads7843e_dev_s *priv, uint8_t cmd) @@ -294,9 +329,18 @@ static uint16_t ads7843e_sendcmd(FAR struct ads7843e_dev_s *priv, uint8_t cmd) /* Send the command */ (void)SPI_SEND(priv->spi, cmd); + +#if 1 + /* Wait a tiny amount to make sure that the aquisition time is complete */ + + up_udelay(3); /* 3 microseconds */ +#else + /* Wait until busy is no longer asserted */ + ads7843e_waitbusy(priv); +#endif - /* Read the data */ + /* Read the 12-bit data (LS 4 bits will be padded with zero) */ SPI_RECVBLOCK(priv->spi, buffer, 2); SPI_SELECT(priv->spi, SPIDEV_TOUCHSCREEN, false); -- cgit v1.2.3