From 7da67bc80a0effac984445b362d4bfd545b81b5b Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Fri, 5 Aug 2016 10:23:04 -0600 Subject: [PATCH] drivers/spi: Add a helper function that encapsulates and manages a sequency of SPI transfers. --- configs/tm4c1294-launchpad/src/tm4c_bringup.c | 2 +- drivers/spi/Make.defs | 4 + drivers/spi/spi_transfer.c | 154 ++++++++++++++++++ include/nuttx/spi/spi.h | 3 +- include/nuttx/spi/spi_transfer.h | 147 +++++++++++++++++ 5 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 drivers/spi/spi_transfer.c create mode 100644 include/nuttx/spi/spi_transfer.h diff --git a/configs/tm4c1294-launchpad/src/tm4c_bringup.c b/configs/tm4c1294-launchpad/src/tm4c_bringup.c index 194b06938f..ee1a37e998 100644 --- a/configs/tm4c1294-launchpad/src/tm4c_bringup.c +++ b/configs/tm4c1294-launchpad/src/tm4c_bringup.c @@ -267,7 +267,7 @@ int tm4c_bringup(void) * Name: board_pwm_setup * * Description: - * No implementation for now, it's called by PWM tool via boardctl.h. + * No implementation for now, it's called by PWM tool via boardctl(). * See include/nuttx/board.h * * Input Parameters: diff --git a/drivers/spi/Make.defs b/drivers/spi/Make.defs index 43e5654faa..0b0539cc95 100644 --- a/drivers/spi/Make.defs +++ b/drivers/spi/Make.defs @@ -37,6 +37,10 @@ ifeq ($(CONFIG_SPI),y) +ifeq ($(CONFIG_SPI_EXCHANGE),y) + CSRCS += spi_transfer.c +endif + # Include the selected SPI drivers ifeq ($(CONFIG_SPI_BITBANG),y) diff --git a/drivers/spi/spi_transfer.c b/drivers/spi/spi_transfer.c new file mode 100644 index 0000000000..088be5f1c8 --- /dev/null +++ b/drivers/spi/spi_transfer.c @@ -0,0 +1,154 @@ +/**************************************************************************** + * drivers/spi/spi_transfer.c + * + * Copyright (C) 2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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 + +#include +#include +#include + +#include +#include + +#ifdef CONFIG_SPI_EXCHANGE + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_transfer + * + * Description: + * This is a helper function that can be used to encapsulate and manage + * a sequence of SPI transfers. + * + * Input Parameters: + * spi - An instance of the SPI device to use for the transfer + * seq - Describes the sequence of transfers. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int spi_transfer(FAR struct spi_dev_s *spi, FAR struct spi_sequence_s *seq) +{ + FAR struct spi_trans_s *trans; + int ret = OK; + int i; + + DEBUGASSERT(spi != NULL && seq != NULL && seq->trans != NULL); + + /* Get exclusive access to the SPI bus */ + + SPI_LOCK(spi, true); + + /* Establish the fixed SPI attributes for all transfers in the sequence */ + + (void)SPI_SETFREQUENCY(spi, seq->frequency); + +#ifdef CONFIG_SPI_CS_DELAY_CONTROL + ret = SPI_SETDELAY(spi, seq->a, seq->b, seq->c); + if (ret < 0) + { + spierr("ERROR: SPI_SETDELAY failed: %d\n", ret) + SPI_LOCK(spi, false); + return ret; + } +#endif + + SPI_SETMODE(spi, seq->mode); + SPI_SETBITS(spi, seq->nbits); + + /* Select the SPI device in preparation for the transfer */ + + SPI_SELECT(spi, seq->dev, true); + + /* Then perform each transfer is the sequence */ + + for (i = 0, trans = seq->trans; i < (int)seq->ntrans; i++, trans++) + { + /* Establish the fixed SPI attributes for unique to this transaction */ + +#ifdef CONFIG_SPI_HWFEATURES + ret = SPI_HWFEATURES(spi, trans->hwfeat); + if (ret < 0) + { + spierr("ERROR: SPI_HWFEATURES failed: %d\n", ret) + break; + } +#endif + +#ifdef CONFIG_SPI_CMDDATA + ret = SPI_CMDDATA(spi, seq->dev, trans->cmd); + if (ret < 0) + { + spierr("ERROR: SPI_CMDDATA failed: %d\n", ret) + break; + } +#endif + + /* Perform the transfer */ + + SPI_EXCHANGE(spi, trans->txbuffer, trans->rxbuffer, trans->nwords); + } + + SPI_SELECT(spi, seq->dev, false); + SPI_LOCK(spi, false); + return ret; +} + +#endif /* CONFIG_SPI_EXCHANGE */ diff --git a/include/nuttx/spi/spi.h b/include/nuttx/spi/spi.h index 45b041ffba..53046fcc73 100644 --- a/include/nuttx/spi/spi.h +++ b/include/nuttx/spi/spi.h @@ -140,7 +140,8 @@ * csdelay - The delay between CS inactive and CS active again * * Returned Value: - * Returns the actual frequency selected + * Returns zero (OK) on success; a negated errno value is return on any + * failure. * ****************************************************************************/ diff --git a/include/nuttx/spi/spi_transfer.h b/include/nuttx/spi/spi_transfer.h new file mode 100644 index 0000000000..b7d2cc0336 --- /dev/null +++ b/include/nuttx/spi/spi_transfer.h @@ -0,0 +1,147 @@ +/**************************************************************************** + * include/nuttx/spi/spi_transfer.h + * + * Copyright(C) 2015-2016 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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_TRANSFER_H +#define __INCLUDE_NUTTX_SPI_TRANSFER_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include + +#ifdef CONFIG_SPI_EXCHANGE + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* This describes one SPI transaction as handled by spi_transfer() */ + +struct spi_trans_s +{ + /* SPI attributes for unique to this transaction */ + +#ifdef CONFIG_SPI_CMDDATA + bool cmd; /* true=command; false=data */ +#endif +#ifdef CONFIG_SPI_HWFEATURES + spi_hwfeatures_t hwfeat; /* Hard features to enable on this transfer */ +#endif + + /* These describe the single data transfer */ + + size_t nwords; /* Number of words in transfer */ + FAR const void *txbuffer; /* Source buffer for TX transfer */ + FAR void *rxbuffer; /* Sink buffer for RX transfer */ +}; + +/* This describes a sequence of SPI transactions as handled by spi_transfer. + * + * Example usage: + * struct spi_trans_s mytrans[5]; + * struct spi_sequence_s myseq; + * ... + * myseq.ntrans = 5; + * myseq.trans = mytrans; + * ... + * int ret = spi_transfer(spi, myseq); + * ... + */ + +struct spi_sequence_s +{ + /* Properties that are fixed throughout the transfer */ + + uint8_t dev; /* See enum spi_dev_e */ + uint8_t mode; /* See enum spi_mode_e */ + uint8_t nbits; /* Number of bits */ + uint8_t ntrans; /* Number of transactions */ + uint32_t frequency; /* SPI frequency (Hz) */ +#ifdef CONFIG_SPI_CS_DELAY_CONTROL + uint32_t a; /* Arguments to setdelay() */ + uint32_t b; + uint32_t c; +#endif + + /* A pointer to the list of transfers to be be performed. */ + + FAR struct spi_trans_s *trans; +}; + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: spi_transfer + * + * Description: + * This is a helper function that can be used to encapsulate and manage + * a sequence of SPI transfers. + * + * Input Parameters: + * spi - An instance of the SPI device to use for the transfer + * seq - Describes the sequence of transfers. + * + * Returned Value: + * Zero (OK) on success; a negated errno value on failure. + * + ****************************************************************************/ + +int spi_transfer(FAR struct spi_dev_s *spi, FAR struct spi_sequence_s *seq); + +#undef EXTERN +#if defined(__cplusplus) +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +#undef EXTERN +#if defined(__cplusplus) +} +#endif + +#endif /* CONFIG_SPI_EXCHANGE */ +#endif /* __INCLUDE_NUTTX_SPI_TRANSFER_H */