From be8207d493e20d85834e82a9c76709445ac37299 Mon Sep 17 00:00:00 2001 From: raiden00pl Date: Sat, 25 Mar 2017 16:50:11 +0100 Subject: [PATCH] drivers/analog: Add basic COMP driver --- drivers/analog/Kconfig | 7 + drivers/analog/Make.defs | 16 +++ drivers/analog/comp.c | 259 ++++++++++++++++++++++++++++++++++++ include/nuttx/analog/comp.h | 113 ++++++++++++++++ 4 files changed, 395 insertions(+) create mode 100644 drivers/analog/comp.c create mode 100644 include/nuttx/analog/comp.h diff --git a/drivers/analog/Kconfig b/drivers/analog/Kconfig index 20d99f8acb..99ff6b8fba 100644 --- a/drivers/analog/Kconfig +++ b/drivers/analog/Kconfig @@ -109,6 +109,13 @@ config PGA11X_MULTIPLE endif # if ADC_PGA11X endif # ADC +config COMP + bool "Analog Comparator" + default n + ---help--- + Select to enable support for Analog Comparators (COMPs). + + config DAC bool "Digital-to-Analog Conversion" default n diff --git a/drivers/analog/Make.defs b/drivers/analog/Make.defs index 2d12a1695d..580a44ae84 100644 --- a/drivers/analog/Make.defs +++ b/drivers/analog/Make.defs @@ -50,6 +50,16 @@ ifeq ($(CONFIG_DAC_AD5410),y) endif endif +# Check for COMP devices + +ifeq ($(CONFIG_COMP),y) + +# Include the common COMP character driver + +CSRCS += comp.c + +endif + # Check for ADC devices ifeq ($(CONFIG_ADC),y) @@ -86,6 +96,12 @@ ifeq ($(CONFIG_ADC),y) DEPPATH += --dep-path analog VPATH += :analog CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)analog} +else +ifeq ($(CONFIG_COMP),y) + DEPPATH += --dep-path analog + VPATH += :analog + CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" $(TOPDIR)$(DELIM)drivers$(DELIM)analog} +endif endif endif diff --git a/drivers/analog/comp.c b/drivers/analog/comp.c new file mode 100644 index 0000000000..5ebc2e87c2 --- /dev/null +++ b/drivers/analog/comp.c @@ -0,0 +1,259 @@ +/**************************************************************************** + * drivers/analog/comp.c + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Mateusz Szafoni + * + * 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 +#include +#include + +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int comp_open(FAR struct file *filep); +static int comp_close(FAR struct file *filep); +static ssize_t comp_read(FAR struct file *filep, FAR char *buffer, + size_t buflen); +static int comp_ioctl(FAR struct file *filep, int cmd, unsigned long arg); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const struct file_operations comp_fops = +{ + comp_open, /* open */ + comp_close, /* close */ + comp_read, /* read */ + NULL, /* write */ + NULL, /* seek */ + comp_ioctl /* ioctl */ +#ifndef CONFIG_DISABLE_POLL + , 0 +#endif +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ +/**************************************************************************** + * Name: comp_open + * + * Description: + * This function is called whenever the COMP device is opened. + * + ****************************************************************************/ + +static int comp_open(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct comp_dev_s *dev = inode->i_private; + uint8_t tmp; + int ret = OK; + + /* If the port is the middle of closing, wait until the close is finished */ + + if (sem_wait(&dev->ad_closesem) != OK) + { + ret = -errno; + } + else + { + /* Increment the count of references to the device. If this the first + * time that the driver has been opened for this device, then initialize + * the device. + */ + + tmp = dev->ad_ocount + 1; + if (tmp == 0) + { + /* More than 255 opens; uint8_t overflows to zero */ + + ret = -EMFILE; + } + else + { + /* Check if this is the first time that the driver has been opened. */ + + if (tmp == 1) + { + /* Yes.. perform one time hardware initialization. */ + + irqstate_t flags = enter_critical_section(); + ret = dev->ad_ops->ao_setup(dev); + if (ret == OK) + { + /* Save the new open count on success */ + + dev->ad_ocount = tmp; + } + + leave_critical_section(flags); + } + } + + sem_post(&dev->ad_closesem); + } + + return ret; +} + +/**************************************************************************** + * Name: comp_close + * + * Description: + * This routine is called when the COMP device is closed. + * It waits for the last remaining data to be sent. + * + ****************************************************************************/ + +static int comp_close(FAR struct file *filep) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct comp_dev_s *dev = inode->i_private; + irqstate_t flags; + int ret = OK; + + if (sem_wait(&dev->ad_closesem) != OK) + { + ret = -errno; + } + else + { + /* Decrement the references to the driver. If the reference count will + * decrement to 0, then uninitialize the driver. + */ + + if (dev->ad_ocount > 1) + { + dev->ad_ocount--; + sem_post(&dev->ad_closesem); + } + else + { + /* There are no more references to the port */ + + dev->ad_ocount = 0; + + /* Free the IRQ and disable the COMP device */ + + flags = enter_critical_section(); /* Disable interrupts */ + dev->ad_ops->ao_shutdown(dev); /* Disable the COMP */ + leave_critical_section(flags); + + sem_post(&dev->ad_closesem); + } + } + + return ret; +} + +/**************************************************************************** + * Name: comp_read + ****************************************************************************/ + +static ssize_t comp_read(FAR struct file *filep, FAR char *buffer, size_t buflen) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct comp_dev_s *dev = inode->i_private; + int ret; + + ret = dev->ad_ops->ao_read(dev); + + buffer[0] = (uint8_t)ret; + + return 1; +} + +/**************************************************************************** + * Name: comp_ioctl +****************************************************************************/ + +static int comp_ioctl(FAR struct file *filep, int cmd, unsigned long arg) +{ + FAR struct inode *inode = filep->f_inode; + FAR struct comp_dev_s *dev = inode->i_private; + int ret; + + ret = dev->ad_ops->ao_ioctl(dev, cmd, arg); + return ret; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: comp_register + ****************************************************************************/ + +int comp_register(FAR const char *path, FAR struct comp_dev_s *dev) +{ + int ret; + + /* Initialize the COMP device structure */ + + dev->ad_ocount = 0; + + /* Initialize semaphores */ + + sem_init(&dev->ad_closesem, 0, 1); + + /* Register the COMP character driver */ + + ret = register_driver(path, &comp_fops, 0444, dev); + if (ret < 0) + { + sem_destroy(&dev->ad_closesem); + } + + return ret; +} diff --git a/include/nuttx/analog/comp.h b/include/nuttx/analog/comp.h new file mode 100644 index 0000000000..9934d831ea --- /dev/null +++ b/include/nuttx/analog/comp.h @@ -0,0 +1,113 @@ +/************************************************************************************ + * include/nuttx/analog/comp.h + * + * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Author: Mateusz Szafoni + * + * 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_ANALOG_COMP_H +#define __INCLUDE_NUTTX_ANALOG_COMP_H + +/************************************************************************************ + * Included Files + ************************************************************************************/ + +#include +#include + +#include +#include +#include +#include +#include + +/************************************************************************************ + * Public Types + ************************************************************************************/ + +struct comp_dev_s; +struct comp_ops_s +{ + /* Configure the COMP. This method is called the first time that the COMP + * device is opened. This will occur when the port is first opened. + * This setup includes configuring and attaching COMP interrupts. Interrupts + * are all disabled upon return. + */ + + CODE int (*ao_setup)(FAR struct comp_dev_s *dev); + + /* Disable the COMP. This method is called when the COMP device is closed. + * This method reverses the operation the setup method. + * Works only if COMP device is not locked. + */ + + CODE void (*ao_shutdown)(FAR struct comp_dev_s *dev); + + /* Read COMP output state */ + + CODE int (*ao_read)(FAR struct comp_dev_s *dev); + + /* All ioctl calls will be routed through this method */ + + CODE int (*ao_ioctl)(FAR struct comp_dev_s *dev, int cmd, unsigned long arg); +}; + +struct comp_dev_s +{ +#ifdef CONFIG_COMP + /* Fields managed by common upper half COMP logic */ + + uint8_t ad_ocount; /* The number of times the device has been opened */ + sem_t ad_closesem; /* Locks out new opens while close is in progress */ +#endif + + /* Fields provided by lower half COMP logic */ + + FAR const struct comp_ops_s *ad_ops; /* Arch-specific operations */ + FAR void *ad_priv; /* Used by the arch-specific logic */ +}; + +/************************************************************************************ + * Public Functions + ************************************************************************************/ + +#if defined(__cplusplus) +extern "C" +{ +#endif + +int comp_register(FAR const char *path, FAR struct comp_dev_s *dev); + +#if defined(__cplusplus) +} +#endif + +#endif /* __INCLUDE_NUTTX_ANALOG_COMP_H */