Add bind method to the ADC lower-half interface
This commit is contained in:
parent
001715d57b
commit
b630d48175
@ -1,9 +1,10 @@
|
||||
/****************************************************************************
|
||||
* drivers/analog/adc.c
|
||||
*
|
||||
* Copyright (C) 2008-2009, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
|
||||
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
|
||||
* History: 0.1 2011-08-04 initial version
|
||||
* Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Derived from drivers/can.c
|
||||
*
|
||||
@ -70,12 +71,14 @@ static int adc_close(FAR struct file *filep);
|
||||
static ssize_t adc_read(FAR struct file *fielp, FAR char *buffer,
|
||||
size_t buflen);
|
||||
static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg);
|
||||
static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch,
|
||||
int32_t data);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct file_operations adc_fops =
|
||||
static const struct file_operations g_adc_fops =
|
||||
{
|
||||
adc_open, /* open */
|
||||
adc_close, /* close */
|
||||
@ -88,6 +91,11 @@ static const struct file_operations adc_fops =
|
||||
#endif
|
||||
};
|
||||
|
||||
static const struct adc_callback_s g_adc_callback =
|
||||
{
|
||||
adc_receive /* au_receive */
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
@ -361,15 +369,11 @@ static int adc_ioctl(FAR struct file *filep, int cmd, unsigned long arg)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: adc_receive
|
||||
****************************************************************************/
|
||||
|
||||
int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
|
||||
static int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
|
||||
{
|
||||
FAR struct adc_fifo_s *fifo = &dev->ad_recv;
|
||||
int nexttail;
|
||||
@ -408,12 +412,30 @@ int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data)
|
||||
return err;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: adc_register
|
||||
****************************************************************************/
|
||||
|
||||
int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(path != NULL && dev != NULL);
|
||||
|
||||
/* Bind the upper-half callbacks to the lower half ADC driver */
|
||||
|
||||
DEBUGASSERT(dev->ad_ops != NULL && dev->ad_ops->ao_bind != NULL);
|
||||
ret = dev->ad_ops->ao_bind(dev, &g_adc_callback);
|
||||
if (ret < 0)
|
||||
{
|
||||
adbg("ERROR: Failed to bind callbacks: %d\n", ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize the ADC device structure */
|
||||
|
||||
dev->ad_ocount = 0;
|
||||
@ -421,7 +443,19 @@ int adc_register(FAR const char *path, FAR struct adc_dev_s *dev)
|
||||
sem_init(&dev->ad_recv.af_sem, 0, 0);
|
||||
sem_init(&dev->ad_closesem, 0, 1);
|
||||
|
||||
/* Reset the ADC hardware */
|
||||
|
||||
DEBUGASSERT(dev->ad_ops->ao_reset != NULL);
|
||||
dev->ad_ops->ao_reset(dev);
|
||||
|
||||
return register_driver(path, &adc_fops, 0444, dev);
|
||||
/* Register the ADC character driver */
|
||||
|
||||
ret = register_driver(path, &g_adc_fops, 0444, dev);
|
||||
if (ret < 0)
|
||||
{
|
||||
sem_destroy(&dev->ad_recv.af_sem);
|
||||
sem_destroy(&dev->ad_closesem);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
/************************************************************************************
|
||||
* arch/drivers/analog/ads1255.c
|
||||
*
|
||||
* Copyright (C) 2010, 2016 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
|
||||
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
|
||||
* History: 0.1 2011-08-05 initial version
|
||||
* 0.2 2011-08-25 fix bug in g_adcdev (cd_ops -> ad_ops,cd_priv -> ad_priv)
|
||||
* Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* This file is a part of NuttX:
|
||||
*
|
||||
@ -47,6 +47,7 @@
|
||||
#include <stdbool.h>
|
||||
#include <semaphore.h>
|
||||
#include <errno.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <arch/board/board.h>
|
||||
@ -105,8 +106,9 @@
|
||||
* ad_private Types
|
||||
****************************************************************************/
|
||||
|
||||
struct up_dev_s
|
||||
struct ads1255_dev_s
|
||||
{
|
||||
FAR const struct adc_callback_s *cb;
|
||||
uint8_t channel;
|
||||
uint32_t sps;
|
||||
uint8_t pga;
|
||||
@ -123,6 +125,8 @@ struct up_dev_s
|
||||
|
||||
/* ADC methods */
|
||||
|
||||
static int adc_bind(FAR struct adc_dev_s *dev,
|
||||
FAR const struct adc_callback_s *callback);
|
||||
static void adc_reset(FAR struct adc_dev_s *dev);
|
||||
static int adc_setup(FAR struct adc_dev_s *dev);
|
||||
static void adc_shutdown(FAR struct adc_dev_s *dev);
|
||||
@ -143,7 +147,7 @@ static const struct adc_ops_s g_adcops =
|
||||
.ao_ioctl = adc_ioctl /* ao_read */
|
||||
};
|
||||
|
||||
static struct up_dev_s g_adcpriv =
|
||||
static struct ads1255_dev_s g_adcpriv =
|
||||
{
|
||||
.mux = (const uint8_t [])
|
||||
{
|
||||
@ -190,16 +194,44 @@ static uint8_t getspsreg(uint16_t sps)
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* ad_private Functions
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: adc_bind
|
||||
*
|
||||
* Description:
|
||||
* Bind the upper-half driver callbacks to the lower-half implementation. This
|
||||
* must be called early in order to receive ADC event notifications.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int adc_bind(FAR struct adc_dev_s *dev,
|
||||
FAR const struct adc_callback_s *callback)
|
||||
{
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
priv->cb = callback;
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: adc_reset
|
||||
*
|
||||
* Description:
|
||||
* Reset the ADC device. Called early to initialize the hardware. This
|
||||
* is called, before ao_setup() and on error conditions.
|
||||
*
|
||||
****************************************************************************/
|
||||
/* Reset the ADC device. Called early to initialize the hardware. This
|
||||
* is called, before ao_setup() and on error conditions.
|
||||
*/
|
||||
|
||||
static void adc_reset(FAR struct adc_dev_s *dev)
|
||||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
|
||||
FAR struct spi_dev_s *spi = priv->spi;
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
|
||||
FAR struct spi_dev_s *spi;
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->spi != NULL);
|
||||
spi = priv->spi;
|
||||
|
||||
SPI_SETMODE(spi, SPIDEV_MODE1);
|
||||
SPI_SETBITS(spi, 8);
|
||||
@ -213,18 +245,27 @@ static void adc_reset(FAR struct adc_dev_s *dev)
|
||||
SPI_SELECT(spi, priv->devno, false);
|
||||
}
|
||||
|
||||
/* Configure the ADC. This method is called the first time that the ADC
|
||||
* device is opened. This will occur when the port is first opened.
|
||||
* This setup includes configuring and attaching ADC interrupts. Interrupts
|
||||
* are all disabled upon return.
|
||||
*/
|
||||
/****************************************************************************
|
||||
* Name: adc_setup
|
||||
*
|
||||
* Description:
|
||||
* Configure the ADC. This method is called the first time that the ADC
|
||||
* device is opened. This will occur when the port is first opened.
|
||||
* This setup includes configuring and attaching ADC interrupts. Interrupts
|
||||
* are all disabled upon return.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int adc_setup(FAR struct adc_dev_s *dev)
|
||||
static int adc_setup(FAR struct adc_dev_s *dev)
|
||||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
|
||||
FAR struct spi_dev_s *spi = priv->spi;
|
||||
int ret = irq_attach(priv->irq, adc_interrupt);
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
|
||||
FAR struct spi_dev_s *spi;
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->spi != NULL);
|
||||
spi = priv->spi;
|
||||
|
||||
ret = irq_attach(priv->irq, adc_interrupt);
|
||||
if (ret == OK)
|
||||
{
|
||||
SPI_SELECT(spi, priv->devno, true);
|
||||
@ -251,22 +292,39 @@ static int adc_setup(FAR struct adc_dev_s *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Disable the ADC. This method is called when the ADC device is closed.
|
||||
* This method reverses the operation the setup method.
|
||||
*/
|
||||
/****************************************************************************
|
||||
* Name: adc_shutdown
|
||||
*
|
||||
* Description:
|
||||
* Disable the ADC. This method is called when the ADC device is closed.
|
||||
* This method reverses the operation the setup method.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void adc_shutdown(FAR struct adc_dev_s *dev)
|
||||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
up_disable_irq(priv->irq);
|
||||
irq_detach(priv->irq);
|
||||
}
|
||||
|
||||
/* Call to enable or disable RX interrupts */
|
||||
/****************************************************************************
|
||||
* Name: adc_rxint
|
||||
*
|
||||
* Description:
|
||||
* Call to enable or disable RX interrupts
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
|
||||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv;
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)dev->ad_priv;
|
||||
|
||||
DEBUGASSERT(priv != NULL);
|
||||
|
||||
if (enable)
|
||||
{
|
||||
up_enable_irq(priv->irq);
|
||||
@ -277,21 +335,42 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
|
||||
}
|
||||
}
|
||||
|
||||
/* All ioctl calls will be routed through this method */
|
||||
/****************************************************************************
|
||||
* Name: adc_ioctl
|
||||
*
|
||||
* Description:
|
||||
* All ioctl calls will be routed through this method
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
|
||||
static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
|
||||
{
|
||||
dbg("Fix me:Not Implemented\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: adc_interrupt
|
||||
*
|
||||
* Description:
|
||||
* ADC interrupt handler
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
static int adc_interrupt(int irq, void *context)
|
||||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
|
||||
FAR struct spi_dev_s *spi = priv->spi;
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)g_adcdev.ad_priv;
|
||||
FAR struct spi_dev_s *spi;
|
||||
unsigned char buf[4];
|
||||
unsigned char ch;
|
||||
|
||||
DEBUGASSERT(priv != NULL && priv->spi != NULL);
|
||||
spi = priv->spi;
|
||||
|
||||
/* REVISIT: Cannot perform SPI operations from an interrupt handler!
|
||||
* Need to use the high priority work queue.
|
||||
*/
|
||||
|
||||
SPI_SELECT(spi, priv->devno, true);
|
||||
SPI_SEND(spi, ADS125X_RDATA);
|
||||
up_udelay(10);
|
||||
@ -316,7 +395,16 @@ static int adc_interrupt(int irq, void *context)
|
||||
SPI_SEND(spi, ADS125X_WAKEUP);
|
||||
SPI_SELECT(spi, priv->devno, false);
|
||||
|
||||
adc_receive(&g_adcdev, priv->channel, *(int32_t *)buf);
|
||||
/* Verify that the upper-half driver has bound its callback functions */
|
||||
|
||||
if (priv->cb != NULL)
|
||||
{
|
||||
/* Perform the data received callback */
|
||||
|
||||
DEBUGASSERT(priv->cb->au_receive != NULL);
|
||||
priv->cb->au_receive(&g_adcdev, priv->channel, *(int32_t *)buf);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
@ -341,10 +429,13 @@ static int adc_interrupt(int irq, void *context)
|
||||
FAR struct adc_dev_s *up_ads1255initialize(FAR struct spi_dev_s *spi,
|
||||
unsigned int devno)
|
||||
{
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
|
||||
FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)g_adcdev.ad_priv;
|
||||
|
||||
DEBUGASSERT(spi != NULL);
|
||||
|
||||
/* Driver state data */
|
||||
|
||||
priv->cb = NULL;
|
||||
priv->spi = spi;
|
||||
priv->devno = devno;
|
||||
return &g_adcdev;
|
||||
|
@ -75,6 +75,27 @@
|
||||
/************************************************************************************
|
||||
* Public Types
|
||||
************************************************************************************/
|
||||
/* These are callbacks to notify the upper-half driver of ADC events */
|
||||
|
||||
struct adc_dev_s;
|
||||
struct adc_callback_s
|
||||
{
|
||||
/* This method is called from the lower half, platform-specific ADC logic when
|
||||
* new ADC sample data is available.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The ADC device structure that was previously registered by adc_register()
|
||||
* ch - And ID for the ADC channel number that generated the data
|
||||
* data - The actual converted data from the channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*/
|
||||
|
||||
CODE int (*au_receive)(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data);
|
||||
};
|
||||
|
||||
/* This describes on ADC message */
|
||||
|
||||
struct adc_msg_s
|
||||
{
|
||||
@ -82,6 +103,8 @@ struct adc_msg_s
|
||||
int32_t am_data; /* ADC convert result (4 bytes) */
|
||||
} packed_struct;
|
||||
|
||||
/* This describes a FIFO of ADC messages */
|
||||
|
||||
struct adc_fifo_s
|
||||
{
|
||||
sem_t af_sem; /* Counting semaphore */
|
||||
@ -99,6 +122,13 @@ struct adc_fifo_s
|
||||
struct adc_dev_s;
|
||||
struct adc_ops_s
|
||||
{
|
||||
/* Bind the upper-half driver callbacks to the lower-half implementation. This
|
||||
* must be called early in order to receive ADC event notifications.
|
||||
*/
|
||||
|
||||
CODE int (*ao_bind)(FAR struct adc_dev_s *dev,
|
||||
FAR const struct adc_callback_s *callback);
|
||||
|
||||
/* Reset the ADC device. Called early to initialize the hardware. This
|
||||
* is called, before ao_setup() and on error conditions.
|
||||
*/
|
||||
@ -188,25 +218,6 @@ extern "C"
|
||||
|
||||
int adc_register(FAR const char *path, FAR struct adc_dev_s *dev);
|
||||
|
||||
/************************************************************************************
|
||||
* Name: adc_receive
|
||||
*
|
||||
* Description:
|
||||
* This function is called from the lower half, platform-specific ADC logic when
|
||||
* new ADC sample data is available.
|
||||
*
|
||||
* Input Parameters:
|
||||
* dev - The ADC device structure that was previously registered by adc_register()
|
||||
* ch - And ID for the ADC channel number that generated the data
|
||||
* data - The actualy converted data from the channel.
|
||||
*
|
||||
* Returned Value:
|
||||
* Zero on success; a negated errno value on failure.
|
||||
*
|
||||
************************************************************************************/
|
||||
|
||||
int adc_receive(FAR struct adc_dev_s *dev, uint8_t ch, int32_t data);
|
||||
|
||||
/************************************************************************************
|
||||
* Platform-Independent "Lower Half" ADC Driver Interfaces
|
||||
************************************************************************************/
|
||||
|
Loading…
Reference in New Issue
Block a user