From 67f38169b237743551b713dd34cc98c4db6e4931 Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 26 Jan 2016 09:58:18 -0600 Subject: [PATCH] drivers/i2c: Move wrapper that implements I2C_WRITEREAD using I2C_transfer from pc9555.c to a new, comon i2c directory --- ChangeLog | 3 + drivers/Kconfig | 34 +----------- drivers/Makefile | 1 + drivers/README.txt | 5 +- drivers/i2c/Kconfig | 38 +++++++++++++ drivers/i2c/Make.defs | 50 +++++++++++++++++ drivers/i2c/i2c_writeread.c | 103 +++++++++++++++++++++++++++++++++++ drivers/ioexpander/pca9555.c | 40 +++----------- drivers/spi/Kconfig | 4 +- include/nuttx/i2c.h | 39 +++++++++++-- 10 files changed, 245 insertions(+), 72 deletions(-) create mode 100644 drivers/i2c/Kconfig create mode 100644 drivers/i2c/Make.defs create mode 100644 drivers/i2c/i2c_writeread.c diff --git a/ChangeLog b/ChangeLog index cd94d5c3ef..4f4a34eb31 100755 --- a/ChangeLog +++ b/ChangeLog @@ -11369,3 +11369,6 @@ ioexpander and not the I2C address. From Stefan Kolb (2016-01-26). * drivers/ioexpander/pca9555: Convert to use I2C_TRANSFER vs. I2C_WRITEREAD, the former is thread safe while the latter is deprecated (2016-01-26). + * drivers/i2c/i2c_writeread.c: Create a wrapper that uses I2C_TRANSFER + to implement I2C_WRITEREAD functionalit (2016-01-26). + diff --git a/drivers/Kconfig b/drivers/Kconfig index a51ac4549f..c836f5a8c4 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -271,38 +271,8 @@ menuconfig I2C See include/nuttx/i2c.h for further I2C driver information. if I2C - -config I2C_SLAVE - bool "I2C Slave" - default n - -config I2C_TRANSFER - bool "Support the I2C transfer() method" - default n - -config I2C_WRITEREAD - bool "Support the I2C writeread() method" - default n - -config I2C_POLLED - bool "Polled I2C (no interrupts)" - default n - -config I2C_TRACE - bool "Enable I2C trace debug" - default n - -config I2C_NTRACE - int "Number of I2C trace records" - default 32 - depends on I2C_TRACE - -config I2C_RESET - bool "Support up_i2creset" - default n - depends on ARCH_HAVE_I2CRESET - -endif # I2C +source drivers/i2c/Kconfig +endif menuconfig SPI bool "SPI Driver Support" diff --git a/drivers/Makefile b/drivers/Makefile index c508b353dd..c642b91877 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -52,6 +52,7 @@ VPATH = . include analog$(DELIM)Make.defs include audio$(DELIM)Make.defs include bch$(DELIM)Make.defs +include i2c$(DELIM)Make.defs include input$(DELIM)Make.defs include ioexpander$(DELIM)Make.defs include lcd$(DELIM)Make.defs diff --git a/drivers/README.txt b/drivers/README.txt index 82334c923c..6f731a153f 100644 --- a/drivers/README.txt +++ b/drivers/README.txt @@ -68,6 +68,9 @@ eeprom/ interface but instead use the simple character interface provided by the EEPROM drivers. +i2c/ + I2C drivers and support logic. See include/nuttx/i2c.h + input/ This directory holds implementations of human input device (HID) drivers. This includes such things as mouse, touchscreen, joystick, @@ -144,7 +147,7 @@ serial/ the NuttX system console. See also include/nuttx/serial/serial.h spi/ - SPI drivers. See include/nuttx/spi.h + SPI drivers and support logic. See include/nuttx/spi/spi.h syslog/ System logging devices. See include/syslog.h and include/nuttx/syslog/syslog.h diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig new file mode 100644 index 0000000000..664b105920 --- /dev/null +++ b/drivers/i2c/Kconfig @@ -0,0 +1,38 @@ +# +# For a description of the syntax of this configuration file, +# see the file kconfig-language.txt in the NuttX tools repository. +# + +if I2C + +config I2C_SLAVE + bool "I2C Slave" + default n + +config I2C_TRANSFER + bool "Support the I2C transfer() method" + default n + +config I2C_WRITEREAD + bool "Support the I2C writeread() method" + default n + +config I2C_POLLED + bool "Polled I2C (no interrupts)" + default n + +config I2C_TRACE + bool "Enable I2C trace debug" + default n + +config I2C_NTRACE + int "Number of I2C trace records" + default 32 + depends on I2C_TRACE + +config I2C_RESET + bool "Support up_i2creset" + default n + depends on ARCH_HAVE_I2CRESET + +endif # I2C diff --git a/drivers/i2c/Make.defs b/drivers/i2c/Make.defs new file mode 100644 index 0000000000..5354db1bfe --- /dev/null +++ b/drivers/i2c/Make.defs @@ -0,0 +1,50 @@ +############################################################################ +# drivers/i2c/Make.defs +# +# 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. +# +############################################################################ + +# Don't build anything if there is no I2C support + +ifeq ($(CONFIG_I2C),y) + +ifeq ($(CONFIG_I2C_TRANSFER),y) + CSRCS += i2c_writeread.c +endif + +# Include I2C device driver build support + +DEPPATH += --dep-path i2c +VPATH += :i2c +CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)i2c} +endif + diff --git a/drivers/i2c/i2c_writeread.c b/drivers/i2c/i2c_writeread.c new file mode 100644 index 0000000000..49753277b9 --- /dev/null +++ b/drivers/i2c/i2c_writeread.c @@ -0,0 +1,103 @@ +/**************************************************************************** + * drivers/i2c/i2c_writeread.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 + +#if defined(CONFIG_I2C_TRANSFER) + +/**************************************************************************** + * Name: pca9555_writeread + * + * Description: + * Write to then read from the I2C device. + * + ****************************************************************************/ + +int i2c_writeread(FAR struct i2c_dev_s *dev, FAR const struct i2c_config_s *config, + FAR const uint8_t *wbuffer, int wbuflen, + FAR uint8_t *rbuffer, int rbuflen) +{ + struct i2c_msg_s msg[2]; + unsigned int flags; + + /* 7- or 10-bit address? */ + + DEBUGASSERT(config->addrlen == 10 || config->addrlen == 7); + flags = (config->addrlen == 10) ? I2C_M_TEN : 0; + + /* Format two messages: The first is a write */ + + msg[0].addr = config->address; + msg[0].flags = flags; + msg[0].buffer = (FAR uint8_t *)wbuffer; /* Override const */ + msg[0].length = wbuflen; + + /* The second is either a read (rbuflen > 0) or a write (rbuflen < 0) with + * no restart. + */ + + if (rbuflen > 0) + { + msg[1].flags = (flags | I2C_M_READ); + } + else + { + msg[1].flags = (flags | I2C_M_NORESTART); + rbuflen = -rbuflen; + } + + msg[1].addr = config->address; + msg[1].buffer = rbuffer; + msg[1].length = rbuflen; + + /* Then perform the transfer + * + * REVISIT: The following two operations must become atomic in order to + * assure thread safety. + */ + + I2C_SETFREQUENCY(dev, config->frequency); + return I2C_TRANSFER(dev, msg, 2); +} + +#endif /* CONFIG_I2C_TRANSFER */ \ No newline at end of file diff --git a/drivers/ioexpander/pca9555.c b/drivers/ioexpander/pca9555.c index c267f38308..5d3843d7ea 100644 --- a/drivers/ioexpander/pca9555.c +++ b/drivers/ioexpander/pca9555.c @@ -137,41 +137,19 @@ static const struct ioexpander_ops_s g_pca9555_ops = * ****************************************************************************/ -static int pca9555_writeread(FAR struct pca9555_dev_s *pca, - FAR const uint8_t *wbuffer, int wbuflen, - FAR uint8_t *rbuffer, int rbuflen) +static inline int pca9555_writeread(FAR struct pca9555_dev_s *pca, + FAR const uint8_t *wbuffer, int wbuflen, + FAR uint8_t *rbuffer, int rbuflen) { - struct i2c_msg_s msg[2]; + struct i2c_config_s config; - /* Format two messages: The first is a write */ + /* Set up the configuration and perform the write-read operation */ - msg[0].addr = pca->config->address; - msg[0].flags = 0; - msg[0].buffer = (uint8_t *)wbuffer; /* Override const */ - msg[0].length = wbuflen; + config.frequency = pca->config->frequency; + config.address = pca->config->address; + config.addrlen = 7; - /* The second is either a read (rbuflen > 0) or a write (rbuflen < 0) with - * no restart. - */ - - if (rbuflen > 0) - { - msg[1].flags = I2C_M_READ; - } - else - { - msg[1].flags = I2C_M_NORESTART; - rbuflen = -rbuflen; - } - - msg[1].addr = pca->config->address; - msg[1].buffer = rbuffer; - msg[1].length = rbuflen; - - /* Then perform the transfer */ - - I2C_SETFREQUENCY(pca->i2c, pca->config->frequency); - return I2C_TRANSFER(pca->i2c, msg, 2); + return i2c_writeread(pca->i2c, &config, wbuffer, wbuflen, rbuffer, rbuflen); } /**************************************************************************** diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 4d0b72741c..b4c8e93bbc 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -80,5 +80,5 @@ config SPI_BITBANG_VARWIDTH Enable support for a variable data width transfers. Default: 8-bit only. -endif -endif +endif # SPI_BITBANG +endif # SPI diff --git a/include/nuttx/i2c.h b/include/nuttx/i2c.h index 6395fde925..264c0beeb4 100644 --- a/include/nuttx/i2c.h +++ b/include/nuttx/i2c.h @@ -1,7 +1,7 @@ /**************************************************************************** * include/nuttx/i2c.h * - * Copyright(C) 2009-2012 Gregory Nutt. All rights reserved. + * Copyright(C) 2009-2012, 2016 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -251,23 +251,36 @@ struct i2c_ops_s uint32_t (*setfrequency)(FAR struct i2c_dev_s *dev, uint32_t frequency); int (*setaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); int (*write)(FAR struct i2c_dev_s *dev, const uint8_t *buffer, - int buflen); + int buflen); int (*read)(FAR struct i2c_dev_s *dev, uint8_t *buffer, int buflen); #ifdef CONFIG_I2C_WRITEREAD - int (*writeread)(FAR struct i2c_dev_s *inst, const uint8_t *wbuffer, - int wbuflen, uint8_t *rbuffer, int rbuflen); + int (*writeread)(FAR struct i2c_dev_s *dev, + FAR const uint8_t *wbuffer, int wbuflen, + FAR uint8_t *rbuffer, int rbuflen); #endif #ifdef CONFIG_I2C_TRANSFER int (*transfer)(FAR struct i2c_dev_s *dev, FAR struct i2c_msg_s *msgs, - int count); + int count); #endif #ifdef CONFIG_I2C_SLAVE int (*setownaddress)(FAR struct i2c_dev_s *dev, int addr, int nbits); int (*registercallback)(FAR struct i2c_dev_s *dev, - int (*callback)(FAR void *arg), FAR void *arg); + int (*callback)(FAR void *arg), FAR void *arg); #endif }; +/* This structure contains the full state of I2C as needed for a specific + * transfer. It is passed to I2C methods so that I2C transfer may be + * performed in a thread safe manner. + */ + +struct i2c_config_s +{ + uint32_t frequency; /* I2C frequency */ + uint16_t address; /* I2C address (7 or 10 bit) */ + uint8_t addrlen; /* I2C address length (7 or 10 bits) */ +}; + /* I2C transaction segment beginning with a START. A number of these can * be transferred together to form an arbitrary sequence of write/read transfer * to an I2C slave device. @@ -352,6 +365,20 @@ int up_i2cuninitialize(FAR struct i2c_dev_s *dev); int up_i2creset(FAR struct i2c_dev_s *dev); #endif +/************************************************************************************ + * Name: i2c_writeread + * + * Description: + * Write to then read from the I2C device. + * + ************************************************************************************/ + +#ifdef CONFIG_I2C_TRANSFER +int i2c_writeread(FAR struct i2c_dev_s *dev, FAR const struct i2c_config_s *config, + FAR const uint8_t *wbuffer, int wbuflen, + FAR uint8_t *rbuffer, int rbuflen); +#endif + #undef EXTERN #if defined(__cplusplus) }