summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2013-07-01 12:23:26 -0600
committerGregory Nutt <gnutt@nuttx.org>2013-07-01 12:23:26 -0600
commit47335ab4bab269c35774964642b823d0367f79ed (patch)
tree033d6a88a653b2610bae7a7a72d4653289740dd4
parent55f91130376b9580a9720a641e80d4049a19d639 (diff)
downloadnuttx-47335ab4bab269c35774964642b823d0367f79ed.tar.gz
nuttx-47335ab4bab269c35774964642b823d0367f79ed.tar.bz2
nuttx-47335ab4bab269c35774964642b823d0367f79ed.zip
Add a general bit-bang SPI upper-half driver
-rw-r--r--nuttx/ChangeLog3
-rw-r--r--nuttx/configs/arduino-due/Kconfig9
-rw-r--r--nuttx/configs/arduino-due/README.txt26
-rw-r--r--nuttx/configs/arduino-due/nsh/defconfig1
-rw-r--r--nuttx/configs/arduino-due/src/Makefile17
-rw-r--r--nuttx/configs/arduino-due/src/arduino-due.h157
-rw-r--r--nuttx/drivers/Makefile3
-rw-r--r--nuttx/drivers/input/Make.defs2
-rw-r--r--nuttx/drivers/spi/Kconfig19
-rwxr-xr-xnuttx/drivers/spi/spi_bitbang.c544
-rwxr-xr-xnuttx/include/nuttx/spi/spi_bitbang.h176
11 files changed, 934 insertions, 23 deletions
diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog
index d19bb86c8..dcc7d15cf 100644
--- a/nuttx/ChangeLog
+++ b/nuttx/ChangeLog
@@ -5096,4 +5096,7 @@
SPI-related files. includes/nuttx/spi.h moved to include/nuttx/spi/.;
SPI-related Kconfig info moved from drivers/Kconfig to drivers/spi/kconfig
(2013-7-1).
+ * drivers/spi/spi_bitbang.c and include/nuttx/spi/spi_bitbang.h: Add
+ support for a generic bit-bang SPI driver. This checkout is the
+ common upper-half logic. Still missing the lower half (2013-7-1).
diff --git a/nuttx/configs/arduino-due/Kconfig b/nuttx/configs/arduino-due/Kconfig
index 8a0550d91..5330ae2a4 100644
--- a/nuttx/configs/arduino-due/Kconfig
+++ b/nuttx/configs/arduino-due/Kconfig
@@ -4,4 +4,13 @@
#
if ARCH_BOARD_ARDUINO_DUE
+
+config ARDUINO_ITHEAD_TFT
+ bool "ITEAD 2.4 inch TFT w/Touch"
+ default n
+ ---help---
+ Select this option if you have the ITEAD 2.4" TFT module installed.
+ This will enable support for the peripherals on that module
+ including the SD card, TFT LCD, and touchscreen controller.
+
endif
diff --git a/nuttx/configs/arduino-due/README.txt b/nuttx/configs/arduino-due/README.txt
index 4e9a304d5..35b9b20f3 100644
--- a/nuttx/configs/arduino-due/README.txt
+++ b/nuttx/configs/arduino-due/README.txt
@@ -122,19 +122,22 @@ ITEAD 2.4" TFT with Touch
The Arduino 2.4" TFT Touch shield uses the S6D1121 controller , it
supports 8-bit data interface. The touch IC is TSC2046.
- Arduino ATSAM3X Due ITHEAD
- Due PIN GPIO FUNCTION SIGNAL PIN SIGNAL NOTES
+ ---------- --------------------------- ----------- ----- ---------- ------------------
+ Arduino ATSAM3X Due ITHEAD
+ Due PIN GPIO FUNCTION SIGNAL PIN SIGNAL NOTES
+ ---------- ---- ---------------------- ----------- ----- ---------- ------------------
PWMH
10 SCL1 PA18 TWCK0/A20/WKUP9 SCL1 --- --- SCL not available
9 SDA1 PA17 TWD0SPCK0 SDA1 --- --- SDA not available
8 Aref --- --- AREF Vref --- ---
7 GND --- --- GND GND --- ---
- 6 PWM13 PB27 SPI0_SPCK/A20/WKUP10 PWM13 D13 SD_SCK SCK, also LED "L"
+ 6 PWM13 PB27 SPI0_SPCK/A20/WKUP10 PWM13 D13 SD_SCK SCK, also LED "L", Pulled low on-board
5 PWM12 PD8 A21/NANDALE/TIOB8 PWM12 D12 SD_MISO MISO not available
- 4 PWM11 PD7 A17/BA1/TIOA8 PWM11 D11 SD_MOSI MOSI not available
- 3 PWM10 ??? ??? SS0/PWM10 D10 SD_CS ???
- 2 PWM9 PC21 A0/NBS0/PWML4 PWM9 D9 Touch_IRQ ---
- 1 PWM8 PC22 A1/PWML5 PWM8 D8 Touch_Dout ---
+ 4 PWM11 PD7 A17/BA1/TIOA8 PWM11 D11 SD_MOSI MOSI not available, Pulled low on-board
+ 3 PWM10 ??? ??? SS0/PWM10 D10 SD_CS Pulled low on-board
+ 2 PWM9 PC21 A0/NBS0/PWML4 PWM9 D9 Touch_Dout ---
+ 1 PWM8 PC22 A1/PWML5 PWM8 D8 Touch_IRQ ---
+
PWML
8 PWM7 PC23 A2/PWML6 PWM7 D7 DB15 ---
7 PWM6 PC24 A3/PWML7 PWM6 D6 DB14 ---
@@ -144,7 +147,7 @@ ITEAD 2.4" TFT with Touch
3 PWM2 PB25 RTS0/TIOA0 PWM2 D2 DB10 ---
2 PWM1 PA9 UTXD/PWMH3 TX D1 DB9 UART0 TX
1 PWM0 PA8 URXD/PWMH0/WKUP4 RX D0 DB8 UART0 RX
-
+ ---------- ---- ---------------------- ----------- ----- ---------- ------------------
POWER
1 --- --- --- --- --- --- ---
2 IOref --- --- IOREF +3V3 --- --- ---
@@ -163,14 +166,15 @@ ITEAD 2.4" TFT with Touch
6 A5 PA4 TCLK1/NWAIT/AD2 AD5 A5 TFT_RS ---
7 A6 PA3 TIOB1/PWMFI1/AD1/WKUP1 AD6 --- --- ---
8 A7 PA2 TIOA1/NANDRDY/AD0 AD7 --- --- ---
+ ---------- ---- ---------------------- ----------- ----- ---------- ------------------
- NOTE:
+ NOTES:
1. It is not possible to use any of the SPI devices on the Shield unless
a bit-bang SPI interface is used. This includes the touch controller
and the SD card.
- 2. UART0 cannot be used
- 3. Parallel data is not contiguous in any PIO register
+ 2. UART0 cannot be used. USARTs on the COMM connector should be available.
+ 3. Parallel data is not contiguous in the PIO register
4. 3.3V and 5V are reversed.
Development Environment
diff --git a/nuttx/configs/arduino-due/nsh/defconfig b/nuttx/configs/arduino-due/nsh/defconfig
index 2e0f4387b..01e2dfe16 100644
--- a/nuttx/configs/arduino-due/nsh/defconfig
+++ b/nuttx/configs/arduino-due/nsh/defconfig
@@ -245,6 +245,7 @@ CONFIG_NSH_MMCSDMINOR=0
#
# Board-Specific Options
#
+# CONFIG_ARDUINO_ITHEAD_TFT is not set
#
# RTOS Features
diff --git a/nuttx/configs/arduino-due/src/Makefile b/nuttx/configs/arduino-due/src/Makefile
index a3ad76c45..3e09e46af 100644
--- a/nuttx/configs/arduino-due/src/Makefile
+++ b/nuttx/configs/arduino-due/src/Makefile
@@ -52,6 +52,23 @@ else
CSRCS += sam_userleds.c
endif
+ifeq ($(CONFIG_ARDUINO_ITHEAD_TFT),y)
+
+ifeq ($(CONFIG_SPI_BITBANG),y)
+ifeq ($(CONFIG_MMC_SPI),y)
+CSRCS += sam_mmcsd.c
+endif
+
+ifeq ($(CONFIG_INPUT),y)
+CSRCS += sam_touchscreen.c
+endif
+endif
+
+ifeq ($(CONFIG_LCD),y)
+CSRCS += sam_lcd.c
+endif
+endif
+
COBJS = $(CSRCS:.c=$(OBJEXT))
SRCS = $(ASRCS) $(CSRCS)
diff --git a/nuttx/configs/arduino-due/src/arduino-due.h b/nuttx/configs/arduino-due/src/arduino-due.h
index 71a5d3c12..4be9a7963 100644
--- a/nuttx/configs/arduino-due/src/arduino-due.h
+++ b/nuttx/configs/arduino-due/src/arduino-due.h
@@ -97,6 +97,163 @@
#define GPIO_LED_TX (GPIO_OUTPUT | GPIO_CFG_PULLUP | GPIO_OUTPUT_SET | \
GPIO_PORT_PIOA | GPIO_PIN21)
+/* ITEAD 2.4" TFT with Touch
+ *
+ * The Arduino 2.4" TFT Touch Shield is designed for all the Arduino
+ * compatible boards. It works in 3.3V voltage level. It can be directly
+ * plugged on the Arduino and other compatible boards. It will offer
+ * display, touch and storage functions for the Arduino board
+ *
+ * Features:
+ *
+ * 1. Compatible with 3.3/5V operation voltage level
+ * 2. Compatible with UTFT library
+ * 3. With SD Card Socket
+ *
+ * The Arduino 2.4" TFT Touch shield uses the S6D1121 controller , it
+ * supports 8-bit data interface. The touch IC is TSC2046.
+ *
+ * ---------- --------------------------- ----------- ----- ---------- ------------------
+ * Arduino ATSAM3X Due ITHEAD
+ * Due PIN GPIO FUNCTION SIGNAL PIN SIGNAL NOTES
+ * ---------- ---- ---------------------- ----------- ----- ---------- ------------------
+ * PWMH
+ * 10 SCL1 PA18 TWCK0/A20/WKUP9 SCL1 --- --- SCL not available
+ * 9 SDA1 PA17 TWD0SPCK0 SDA1 --- --- SDA not available
+ * 8 Aref --- --- AREF Vref --- ---
+ * 7 GND --- --- GND GND --- ---
+ * 6 PWM13 PB27 SPI0_SPCK/A20/WKUP10 PWM13 D13 SD_SCK SCK, also LED "L", Pulled low on-board
+ * 5 PWM12 PD8 A21/NANDALE/TIOB8 PWM12 D12 SD_MISO MISO not available
+ * 4 PWM11 PD7 A17/BA1/TIOA8 PWM11 D11 SD_MOSI MOSI not available, Pulled low on-board
+ * 3 PWM10 ??? ??? SS0/PWM10 D10 SD_CS Pulled low on-board
+ * 2 PWM9 PC21 A0/NBS0/PWML4 PWM9 D9 Touch_Dout ---
+ * 1 PWM8 PC22 A1/PWML5 PWM8 D8 Touch_IRQ ---
+ * PWML
+ * 8 PWM7 PC23 A2/PWML6 PWM7 D7 DB15 ---
+ * 7 PWM6 PC24 A3/PWML7 PWM6 D6 DB14 ---
+ * 6 PWM5 PC25 A4/TIOA6 PWM5 D5 DB13 ---
+ * 5 PWM4 PC26 A5/TIOB6 SS1/PWM4 D4 DB12 ---
+ * 4 PWM3 PC28 A7/TIOA7 PWM3 D3 DB11 ---
+ * 3 PWM2 PB25 RTS0/TIOA0 PWM2 D2 DB10 ---
+ * 2 PWM1 PA9 UTXD/PWMH3 TX D1 DB9 UART0 TX
+ * 1 PWM0 PA8 URXD/PWMH0/WKUP4 RX D0 DB8 UART0 RX
+ * ---------- ---- ---------------------- ----------- ----- ---------- ------------------
+ * POWER
+ * 1 --- --- --- --- --- --- ---
+ * 2 IOref --- --- IOREF +3V3 --- --- ---
+ * 3 RESET --- --- MASTER_RESET RST --- ---
+ * 4 3.3V --- --- +3V3 5V --- ---
+ * 5 5V --- --- +5V 3.3V --- ---
+ * 6 GND --- --- GND GND --- ---
+ * 7 GND --- --- GND GND --- ---
+ * 8 Vin --- --- VIN Vin --- ---
+ * ADCL
+ * 1 A0 PA16 SPCK1/TD/AD7 AD0 A0 Touch_Din ---
+ * 2 A1 PA24 MCDA3/PCK1/AD6 AD1 A1 Touch_CLK ---
+ * 3 A2 PA23 MCDA2/TCLK4/AD5 AD2 A2 --- ---
+ * 4 A3 PA22 MCDA1/TCLK3/AD4 AD3 A3 TFT_CS ---
+ * 5 A4 PA6 TIOB2/NCS0/AD3 AD4 A4 TFT_WR ---
+ * 6 A5 PA4 TCLK1/NWAIT/AD2 AD5 A5 TFT_RS ---
+ * 7 A6 PA3 TIOB1/PWMFI1/AD1/WKUP1 AD6 --- --- ---
+ * 8 A7 PA2 TIOA1/NANDRDY/AD0 AD7 --- --- ---
+ * ---------- ---- ---------------------- ----------- ----- ---------- ------------------
+ *
+ * NOTES:
+ *
+ * 1. It is not possible to use any of the SPI devices on the Shield unless
+ * a bit-bang SPI interface is used. This includes the touch controller
+ * and the SD card.
+ * 2. UART0 cannot be used. USARTs on the COMM connector should be available.
+ * 3. Parallel data is not contiguous in the PIO register
+ * 4. 3.3V and 5V are reversed.
+ */
+
+#ifdef CONFIG_ARDUINO_ITHEAD_TFT
+ /* In order to use the SD card on the ITEAD shield, you must enable the
+ * SPI bit-bang driver as well as support for SPI-based MMC/SD cards.
+ */
+
+# if defined(CONFIG_SPI_BITBANG) && defined(CONFIG_MMC_SPI)
+
+ /* The SD slot shares the pin with LED "L" so LED support must be disabled
+ * to use the MMC/SD card on the ITEAD shield.
+ */
+
+# ifdef CONFIG_ARCH_LEDs
+# error LEDs may not be used with the ITEAD SD card
+# endif
+
+# define GPIO_SD_SCK (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOB | GPIO_PIN27)
+# define GPIO_SD_MISO (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOD | GPIO_PIN8)
+# define GPIO_SD_MOSI (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOD | GPIO_PIN7)
+# define GPIO_SD_CS (GPIO_OUTPUT | GPIO_CFG_PULLUP | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIO? | GPIO_PIN?)
+# endif
+
+ /* In order to use the touchscreen on the ITEAD shield, you must enable the
+ * SPI bit-bang driver and INPUT device support.
+ */
+
+# if defined(CONFIG_SPI_BITBANG) && defined(CONFIG_INPUT)
+# define GPIO_TSC_SCK (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN24)
+# define GPIO_TSC_MISO (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN21)
+# define GPIO_TSC_MOSI (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN16)
+# define GPIO_TSC_CS (GPIO_OUTPUT | GPIO_CFG_PULLUP | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIO? | GPIO_PIN?)
+# define GPIO_TSC_IRQ (GPIO_INPUT | GPIO_CFG_PULLUP | GPIO_INT_BOTHEDGES | \
+ GPIO_PORT_PIOC | GPIO_PIN22)
+# define SAM_TCS_IRQ SAM_IRQ_PC21
+# endif
+
+ /* Only CONFIG_LCD is expected to enable the TFT LCD */
+
+# ifdef CONFIG_LCD
+
+ /* UART0 cannot be used with the LCD because the UART0 pins are used
+ * by the LCD.
+ */
+
+# ifdef CONFIG_SAM34_UART0
+# error "UART0 cannot be used with the ITEAD LCD"
+# endif
+
+ /* Data pins are initially configured but may be switched dynamically to
+ * either inputs or outputs as needed.
+ */
+
+# define GPIO_LCD_D0IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN8)
+# define GPIO_LCD_D1IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN9)
+# define GPIO_LCD_D2IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOB | GPIO_PIN25)
+# define GPIO_LCD_D3IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN28)
+# define GPIO_LCD_D4IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN26)
+# define GPIO_LCD_D5IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN25)
+# define GPIO_LCD_D6IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN24)
+# define GPIO_LCD_D7IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN23)
+# define GPIO_LCD_D7IN (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOC | GPIO_PIN23)
+# define GPIO_LCD_CS (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN22)
+# define GPIO_LCD_WR (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN6)
+# define GPIO_LCD_RS (GPIO_OUTPUT | GPIO_CFG_DEFAULT | GPIO_OUTPUT_CLR | \
+ GPIO_PORT_PIOA | GPIO_PIN4)
+# endif
+#endif
+
/************************************************************************************
* Public Types
************************************************************************************/
diff --git a/nuttx/drivers/Makefile b/nuttx/drivers/Makefile
index c91870ec9..cce03cad0 100644
--- a/nuttx/drivers/Makefile
+++ b/nuttx/drivers/Makefile
@@ -1,7 +1,7 @@
############################################################################
# drivers/Makefile
#
-# Copyright (C) 2007-2012 Gregory Nutt. All rights reserved.
+# Copyright (C) 2007-2013 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org>
#
# Redistribution and use in source and binary forms, with or without
@@ -62,6 +62,7 @@ include power$(DELIM)Make.defs
include sensors$(DELIM)Make.defs
include sercomm$(DELIM)Make.defs
include serial$(DELIM)Make.defs
+include spi$(DELIM)Make.defs
include syslog$(DELIM)Make.defs
include usbdev$(DELIM)Make.defs
include usbhost$(DELIM)Make.defs
diff --git a/nuttx/drivers/input/Make.defs b/nuttx/drivers/input/Make.defs
index 10e6db62f..81cf2f696 100644
--- a/nuttx/drivers/input/Make.defs
+++ b/nuttx/drivers/input/Make.defs
@@ -33,7 +33,7 @@
#
############################################################################
-# Don't build anything if there is no NX support for input devices
+# Don't build anything if there is no support for input devices
ifeq ($(CONFIG_INPUT),y)
diff --git a/nuttx/drivers/spi/Kconfig b/nuttx/drivers/spi/Kconfig
index 645f4017b..fbba4e253 100644
--- a/nuttx/drivers/spi/Kconfig
+++ b/nuttx/drivers/spi/Kconfig
@@ -3,22 +3,15 @@
# see misc/tools/kconfig-language.txt.
#
-config SPI
- bool "SPI Driver Support"
- default n
- ---help---
- This selection enables selection of common SPI options. This option
- should be enabled by all platforms that support SPI interfaces.
- See include/nuttx/spi/spi.h for further SPI driver information.
-
if SPI
+
config SPI_OWNBUS
bool "SPI single device"
default n
---help---
Set if there is only one active device on the SPI bus. No locking or
SPI configuration will be performed. It is not necessary for clients to
- lock, re-configure, etc..
+ lock, re-configure, etc.
config SPI_EXCHANGE
bool "SPI exchange"
@@ -36,5 +29,11 @@ config SPI_CMDDATA
either 9-bit SPI (yech) or 8-bit SPI and a GPIO output that selects
between command and data.
-endif
+config SPI_BITBANG
+ bool "SPI bit-bang device"
+ default n
+ ---help---
+ Enable support for a generic SPI bit-bang device.
+ See include/nuttx/spi/spi_bitbang.h for further information.
+endif
diff --git a/nuttx/drivers/spi/spi_bitbang.c b/nuttx/drivers/spi/spi_bitbang.c
new file mode 100755
index 000000000..27022c375
--- /dev/null
+++ b/nuttx/drivers/spi/spi_bitbang.c
@@ -0,0 +1,544 @@
+/****************************************************************************
+ * drivers/spi/spi_bitbang.c
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdlib.h>
+#include <semaphore.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <nuttx/spi/spi.h>
+#include <nuttx/spi/spi_bitbang.h>
+
+#ifdef CONFIG_SPI_BITBANG
+
+ /****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* This file holds the static, device-independ portion of the generica SPI-
+ * bit-bang driver. The full driver consists of 5 files:
+ *
+ * 1. drivers/spi/spi_bitbang.c: This file. This file holds the basic
+ * SPI driver framework and not perform any direct bit-bang operations.
+ * Rather, it will could out to board-specific logic to perform the
+ * low level data transfers.
+ * 2. include/nuttx/spi/spi_bitbang.h: This header file provides the
+ * data types and function prototypes needed to utilize the logic in
+ * this file.
+ * 3. configs/<board>/src/<file>: The implementation of the low-level
+ * bit-bang logic resides in some file in the board source directory.
+ * This board-specific logic includes the bit-bang skeleton logic
+ * provided in include/nuttx/spi/spi_bitband.c.
+ * 4. include/nuttx/spi/spi_bitband.c. Despite the .c extension, this
+ * really an included file. It is used in this way: 1) The board-
+ * specific logic in configs/<board>/src/<file> provides some definitions
+ * then 2) includes include/nuttx/spi/spi_bitband.c. That file will
+ * then use those definitions to implement the low-level bit-bang
+ * logic. the board-specific logic then calls spi_create_bitbang()
+ * in this file to instantiate the complete SPI driver.
+ *
+ * See include/nuttx/spi/spi_bitband.c for more detailed usage
+ * information.
+ */
+
+/* Debug ********************************************************************/
+/* Check if SPI debut is enabled (non-standard.. no support in
+ * include/debug.h
+ */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_VERBOSE
+# undef CONFIG_DEBUG_SPI
+#endif
+
+#ifdef CONFIG_DEBUG_SPI
+# define spidbg lldbg
+# ifdef CONFIG_DEBUG_VERBOSE
+# define spivdbg lldbg
+# else
+# define spivdbg(x...)
+# endif
+#else
+# define spidbg(x...)
+# define spivdbg(x...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* SPI methods */
+
+#ifndef CONFIG_SPI_OWNBUS
+static int spi_lock(FAR struct spi_dev_s *dev, bool lock);
+#endif
+static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid,
+ bool selected);
+static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev,
+ uint32_t frequency);
+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 uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t ch);
+static void spi_exchange(FAR struct spi_dev_s *dev,
+ FAR const void *txbuffer, FAR void *rxbuffer,
+ size_t nwords);
+static uint8_t spi_status(FAR struct spi_dev_s *dev, enum spi_dev_e devid);
+#ifdef CONFIG_SPI_CMDDATA
+static int spi_cmddata(FAR struct spi_dev_s *dev, enum spi_dev_e devid,
+ bool cmd);
+#endif
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_sndblock(FAR struct spi_dev_s *dev,
+ FAR const void *buffer, size_t nwords);
+static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer,
+ size_t nwords);
+#endif
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* SPI driver operations */
+
+static const struct spi_ops_s g_spiops =
+{
+#ifndef CONFIG_SPI_OWNBUS
+ .lock = spi_lock,
+#endif
+ .select = spi_select,
+ .setfrequency = spi_setfrequency,
+ .setmode = spi_setmode,
+ .setbits = spi_setbits,
+ .status = spi_status,
+#ifdef CONFIG_SPI_CMDDATA
+ .cmddata = spi_cmddata,
+#endif
+ .send = spi_send,
+#ifdef CONFIG_SPI_EXCHANGE
+ .exchange = spi_exchange,
+#else
+ .sndblock = spi_sndblock,
+ .recvblock = spi_recvblock,
+#endif
+ .registercallback = 0, /* Not implemented */
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * 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
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_SPI_OWNBUS
+static int spi_lock(FAR struct spi_dev_s *dev, bool lock)
+{
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+
+ spivdbg("lock=%d\n", lock);
+ 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;
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_select
+ *
+ * Description:
+ * Set/clear the chip select line for the selected device.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * devid - Identifies the device to be selected
+ * selected - select or de-select device
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void spi_select(FAR struct spi_dev_s *dev, enum spi_dev_e devid,
+ bool selected)
+{
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+ DEBUGASSERT(priv && priv->low->select);
+ priv->low->select(priv, devid, selected);
+}
+
+/****************************************************************************
+ * Name: spi_setfrequency
+ *
+ * Description:
+ * Set the SPI frequency.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * frequency - The SPI frequency requested
+ *
+ * Returned Value:
+ * Returns the actual frequency selected
+ *
+ ****************************************************************************/
+
+static uint32_t spi_setfrequency(FAR struct spi_dev_s *dev, uint32_t frequency)
+{
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+
+ /* SPI frequency cannot be precisely controlled with a bit-bang interface.
+ * Freqency corresponds to delay in toggle the SPI clock line: Set high,
+ * wait, set low, wait, set high, wait, etc.
+ *
+ * Here we calcalute the half period of the frequency in nanoseconds (i.e.,
+ * the amount of time that the clock should remain in the high or low state).
+ *
+ * frequency = psec / 1 sec - psec = full period in seconds
+ * psec = 1 sec / frequency
+ * hpsec = 1 sec / (2 * frequency) - hpsec = half period in seconds
+ * hpnsec = 1000000000 / (2 * frequency) - hpnsec = half period in nanoseconds
+ */
+
+ priv->hpnsec = (1000000000ul + frequency) / (frequency << 2);
+ return frequency;
+}
+
+/****************************************************************************
+ * Name: spi_setmode
+ *
+ * Description:
+ * Set the SPI mode. Optional. See enum spi_mode_e for mode definitions
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * mode - The SPI mode requested
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+
+static void spi_setmode(FAR struct spi_dev_s *dev, enum spi_mode_e mode)
+{
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+ DEBUGASSERT(priv && priv->low->setmode);
+ priv->low->setmode(priv, mode);
+}
+
+/****************************************************************************
+ * Name: spi_setbits
+ *
+ * Description:
+ * Set the number if bits per word.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * nbits - The number of bits requests
+ *
+ * Returned Value:
+ * none
+ *
+ ****************************************************************************/
+
+static void spi_setbits(FAR struct spi_dev_s *dev, int nbits)
+{
+#ifdef CONFIG_SPI_BITBANG_VARWIDTH
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+
+ spivdbg("nbits=%d\n", nbits);
+ DEBUGASSERT(priv && nbits > 0);
+ priv->nbits = nbits;
+#else
+ spivdbg("nbits=%d\n", nbits);
+ DEBUGASSERT(nbits == 8);
+#endif
+}
+/****************************************************************************
+ * Name: spi_send
+ *
+ * Description:
+ * Exchange one word on SPI
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * wd - The word to send. the size of the data is determined by the
+ * number of bits selected for the SPI interface.
+ *
+ * Returned Value:
+ * response
+ *
+ ****************************************************************************/
+
+static uint16_t spi_send(FAR struct spi_dev_s *dev, uint16_t wd)
+{
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+ DEBUGASSERT(priv && priv->low && priv->low->exchange);
+
+ return priv->low->exchange(priv, wd);
+}
+
+/****************************************************************************
+ * Name: spi_exchange
+ *
+ * Description:
+ * Exahange a block of data from SPI. Required.
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * txbuffer - A pointer to the buffer of data to be sent
+ * rxbuffer - A pointer to the buffer in which to recieve data
+ * nwords - the length of data that to be exchanged in units of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into
+ * uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+static void spi_exchange(FAR struct spi_dev_s *dev,
+ FAR const void *txbuffer, FAR void *rxbuffer,
+ size_t nwords)
+{
+ FAR struct spi_bitbang_s *priv = (FAR struct spi_bitbang_s *)dev;
+ FAR const uint8_t *src = (FAR const uint8_t *)txbuffer;
+ FAR uint8_t *dest = (FAR uint8_t *)rxbuffer;
+ uint16_t dataout;
+ uint16_t datain;
+
+ DEBUGASSERT(priv && priv->low && priv->low->exchange);
+
+ /* If there is no data source, send 0xff */
+
+ if (!src)
+ {
+ dataout = 0xff;
+ }
+
+ /* Exchange each word */
+
+ while (nwords-- > 0)
+ {
+ /* If there is source data, get the next word from the source */
+
+ if (src)
+ {
+ dataout = (uint16_t)*src++;
+
+#ifdef CONFIG_SPI_BITBANG_VARWIDTH
+ if (priv->nbits > 8)
+ {
+#ifdef CONFIG_ENDIAN_BIG
+ dataout <<= 8;
+ dataout |= *src++;
+#else
+ dataout |= (uint16_t)(*src++) << 8;
+#endif
+ }
+#endif
+ }
+
+ /* Exchange the word of data */
+
+ datain = priv->low->exchange(priv, dataout);
+
+ /* If there is a data sink, transfer the data to the receive buffer */
+
+ if (dest)
+ {
+#ifdef CONFIG_SPI_BITBANG_VARWIDTH
+ if (priv->nbits > 8)
+ {
+#ifdef CONFIG_ENDIAN_BIG
+ *dest++ = (uint8_t)(datain >> 8);
+ *dest++ = (uint8_t)datain;
+#else
+ *dest++ = (uint8_t)datain;
+ *dest++ = (uint8_t)(datain >> 8);
+#endif
+ }
+#else
+ *dest++ = (uint8_t)datain;
+#endif
+ }
+ }
+}
+
+/***************************************************************************
+ * Name: spi_sndblock
+ *
+ * Description:
+ * Send a block of data on SPI
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * buffer - A pointer to the buffer of data to be sent
+ * nwords - the length of data to send from the buffer in number of words.
+ * The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_sndblock(FAR struct spi_dev_s *dev, FAR const void *buffer, size_t nwords)
+{
+ /* spi_exchange can do this. */
+
+ spi_exchange(dev, buffer, NULL, nwords);
+}
+#endif
+
+/****************************************************************************
+ * Name: spi_recvblock
+ *
+ * Description:
+ * Revice a block of data from SPI
+ *
+ * Input Parameters:
+ * dev - Device-specific state data
+ * buffer - A pointer to the buffer in which to recieve data
+ * nwords - the length of data that can be received in the buffer in number
+ * of words. The wordsize is determined by the number of bits-per-word
+ * selected for the SPI interface. If nbits <= 8, the data is
+ * packed into uint8_t's; if nbits >8, the data is packed into uint16_t's
+ *
+ * Returned Value:
+ * None
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_SPI_EXCHANGE
+static void spi_recvblock(FAR struct spi_dev_s *dev, FAR void *buffer, size_t nwords)
+{
+ /* spi_exchange can do this. */
+
+ spi_exchange(dev, NULL, buffer, nwords);
+}
+#endif
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spi_create_bitbang
+ *
+ * Descripton:
+ * Create an instance of the SPI bit-bang driver.
+ *
+ ****************************************************************************/
+
+FAR struct spi_dev_s *spi_create_bitbang(FAR const struct spi_bitbang_ops_s *low)
+{
+ FAR struct spi_bitbang_s *priv;
+
+ DEBUGASSERT(low);
+
+ /* Allocate an instance of the SPI bit bang structure */
+
+ priv = (FAR struct spi_bitbang_s *)zalloc(sizeof(struct spi_bitbang_s));
+ if (!priv)
+ {
+ spidbg("Failed to allocate the device structure\n");
+ return NULL;
+ }
+
+ /* Initialize the driver structure */
+
+ priv->dev.ops = &g_spiops;
+ priv->low = low;
+#ifdef CONFIG_SPI_BITBANG_VARWIDTH
+ priv->nbits = 8;
+#endif
+
+ /* Select an initial state of mode 0, 8-bits, and 400KHz */
+
+ low->setmode(priv, SPIDEV_MODE0);
+ spi_setfrequency(&priv->dev, 400000);
+
+ /* And return the initialized driver structure */
+
+ return &priv->dev;
+}
+
+#endif /* CONFIG_SPI_BITBANG */
diff --git a/nuttx/include/nuttx/spi/spi_bitbang.h b/nuttx/include/nuttx/spi/spi_bitbang.h
new file mode 100755
index 000000000..22a44494b
--- /dev/null
+++ b/nuttx/include/nuttx/spi/spi_bitbang.h
@@ -0,0 +1,176 @@
+/****************************************************************************
+ * include/nuttx/spi/spi_bitbang.h
+ *
+ * Copyright (C) 2013 Gregory Nutt. All rights reserved.
+ * Author: Gregory Nutt <gnutt@nuttx.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ * 3. Neither the name NuttX nor the names of its contributors may be
+ * used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ ****************************************************************************/
+
+#ifndef __INCLUDE_NUTTX_SPI_SPI_BITBANG_H
+#define __INCLUDE_NUTTX_SPI_SPI_BITBANG_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <nuttx/spi/spi.h>
+
+#ifdef CONFIG_SPI_BITBANG
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+/* Configuration ************************************************************/
+#ifndef SPI_BITBANG_MODE <<< NOOOO.. Needs to be programmable
+# define SPI_BITBANG_MODE SPI_MODE0
+#endif
+
+#ifndef CONFIG_SPI_BITBANG_FREQUENCY <<< NOOOO.. Needs to be programmable
+# define CONFIG_SPI_BITBANG_FREQUENCY 1000000
+#endif
+
+/* Debug ********************************************************************/
+/* Check if SPI debut is enabled (non-standard.. no support in
+ * include/debug.h
+ */
+
+#ifndef CONFIG_DEBUG
+# undef CONFIG_DEBUG_VERBOSE
+# undef CONFIG_DEBUG_SPI
+#endif
+
+#ifdef CONFIG_DEBUG_SPI
+# define spidbg lldbg
+# ifdef CONFIG_DEBUG_VERBOSE
+# define spivdbg lldbg
+# else
+# define spivdbg(x...)
+# endif
+#else
+# define spidbg(x...)
+# define spivdbg(x...)
+#endif
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+#ifndef __ASSEMBLY__
+
+/* These are the lower-half handlers that perform the level-level, platform-
+ * specific bit-bang operations.
+ */
+
+struct spi_bitbang_s; /* Forward reference */
+struct spi_bitbang_ops_s
+{
+ /* Platform specific chip select logic */
+
+ void (*select)(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid,
+ bool selected);
+
+ /* Platform-specific, SPI mode function */
+
+ void (*setmode)(FAR struct spi_bitbang_s *priv, enum spi_mode_e mode);
+
+ /* Platform-specific word exchange function */
+
+ uint16_t (*exchange)(FAR struct spi_bitbang_s *priv, uint16_t dataout);
+
+ /* Platform-specific word exchange function */
+
+ uint8_t (*status)(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid);
+
+#ifdef CONFIG_SPI_CMDDATA
+ /* Platform-specific CMD/DATA function */
+
+ int (*cmddata)(FAR struct spi_bitbang_s *priv, enum spi_dev_e devid,
+ bool cmd);
+#endif
+};
+
+/* This structure provides the state of the SPI bit-bang driver */
+
+struct spi_bitbang_s
+{
+ struct spi_dev_s dev; /* Publicly visible version of SPI driver */
+ FAR const struct spi_bitbang_ops_s *low; /* Low-level operations */
+ uint32_t hpnsec; /* Number of microseconds in a half cycle */
+#ifndef CONFIG_SPI_OWNBUS
+ sem_t exclsem; /* Supports mutually exclusive access to SPI */
+#endif
+#ifdef CONFIG_SPI_BITBANG_VARWIDTH
+ uint8_t nbits; /* Number of bits in the transfer */
+#endif
+ FAR void *priv; /* For use by the lower half driver */
+};
+
+/****************************************************************************
+ * Public Data
+ ****************************************************************************/
+
+#undef EXTERN
+#if defined(__cplusplus)
+#define EXTERN extern "C"
+extern "C"
+{
+#else
+#define EXTERN extern
+#endif
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: spi_create_bitbang
+ *
+ * Descripton:
+ * Create an instance of the SPI bit-bang driver.
+ *
+ * Input Parameters:
+ * low - Low-level, platform specific device operations.
+ *
+ * Returned Value:
+ * On success a non-NULL, initialized SPI driver instance is returned.
+ *
+ ****************************************************************************/
+
+FAR struct spi_dev_s *spi_create_bitbang(FAR const struct spi_bitbang_ops_s *low);
+
+#undef EXTERN
+#if defined(__cplusplus)
+}
+#endif
+
+#endif /* __ASSEMBLY__ */
+#endif /* CONFIG_SPI_BITBANG */
+#endif /* __INCLUDE_NUTTX_SPI_SPI_BITBANG_H */