From 2f5221ed91cffb6492ab3c9fa3c2201f12a87f9a Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Thu, 26 May 2016 12:19:17 -0600 Subject: [PATCH] Add ADC bind method to the LPC43xx and SAMA5Dx ADC drivers --- arch/arm/src/lpc17xx/lpc17_adc.c | 1 - arch/arm/src/lpc43xx/lpc43_adc.c | 41 +++++++++++++++++++++++++-- arch/arm/src/sama5/sam_adc.c | 48 ++++++++++++++++++++++++++++++-- 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/arch/arm/src/lpc17xx/lpc17_adc.c b/arch/arm/src/lpc17xx/lpc17_adc.c index 011b0aada5..490b25bf80 100644 --- a/arch/arm/src/lpc17xx/lpc17_adc.c +++ b/arch/arm/src/lpc17xx/lpc17_adc.c @@ -644,7 +644,6 @@ static int adc_interrupt(int irq, void *context) FAR struct adc_dev_s *lpc17_adcinitialize(void) { - g_adcdev.cb = NULL; return &g_adcdev; } diff --git a/arch/arm/src/lpc43xx/lpc43_adc.c b/arch/arm/src/lpc43xx/lpc43_adc.c index 487c0b5cf3..4286451f11 100644 --- a/arch/arm/src/lpc43xx/lpc43_adc.c +++ b/arch/arm/src/lpc43xx/lpc43_adc.c @@ -7,8 +7,9 @@ * Ported from from the LPC17 version: * * Copyright(C) 2011 Li Zhuoyi. All rights reserved. + * Copyright(C) 2016 Gregory Nutt. All rights reserved. * Author: Li Zhuoyi - * History: 0.1 2011-08-05 initial version + * Gregory Nutt * * This file is a part of NuttX: * @@ -55,6 +56,7 @@ #include #include #include +#include #include #include @@ -112,6 +114,7 @@ struct up_dev_s { + FAR const struct adc_callback_s *cb; uint8_t mask; uint8_t mask_int; uint32_t freq; @@ -126,6 +129,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); @@ -139,6 +144,7 @@ static int adc_interrupt(int irq, void *context); static const struct adc_ops_s g_adcops = { + .ao_bind = adc_bind, .ao_reset = adc_reset, .ao_setup = adc_setup, .ao_shutdown = adc_shutdown, @@ -166,6 +172,25 @@ static struct adc_dev_s g_adcdev = * 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 up_dev_s *priv = (FAR struct up_dev_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + priv->cb = callback; + return OK; +} + /**************************************************************************** * Name: adc_reset * @@ -454,8 +479,20 @@ static int adc_interrupt(int irq, void *context) { if (priv->mask & (1 << i)) { + int32_t data; + regval = getreg32(LPC43_ADC0_DR(i)); - adc_receive(&g_adcdev, i,(regval&ADC_DR_VVREF_MASK)>>ADC_DR_VVREF_SHIFT); + data = (regval & ADC_DR_VVREF_MASK) >> ADC_DR_VVREF_SHIFT; + + /* 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, i, data); + } } } diff --git a/arch/arm/src/sama5/sam_adc.c b/arch/arm/src/sama5/sam_adc.c index 261434229e..68565bc502 100644 --- a/arch/arm/src/sama5/sam_adc.c +++ b/arch/arm/src/sama5/sam_adc.c @@ -57,6 +57,7 @@ #include #include #include +#include #include #include @@ -378,6 +379,7 @@ struct sam_adc_s { + FAR const struct adc_callback_s *cb; sem_t exclsem; /* Supports exclusive access to the ADC interface */ bool initialized; /* The ADC driver is already initialized */ uint32_t frequency; /* ADC clock frequency */ @@ -446,6 +448,8 @@ static int sam_adc_interrupt(int irq, void *context); /* ADC methods */ #ifdef SAMA5_ADC_HAVE_CHANNELS +static int sam_adc_bind(FAR struct adc_dev_s *dev, + FAR const struct adc_callback_s *callback); static void sam_adc_reset(struct adc_dev_s *dev); static int sam_adc_setup(struct adc_dev_s *dev); static void sam_adc_shutdown(struct adc_dev_s *dev); @@ -477,6 +481,7 @@ static void sam_adc_channels(struct sam_adc_s *priv); static const struct adc_ops_s g_adcops = { + .ao_bind = sam_adc_bind, .ao_reset = sam_adc_reset, .ao_setup = sam_adc_setup, .ao_shutdown = sam_adc_shutdown, @@ -664,9 +669,15 @@ static void sam_adc_dmadone(void *arg) chan = (int)((*buffer & ADC_LCDR_CHANB_MASK) >> ADC_LCDR_CHANB_SHIFT); sample = ((*buffer & ADC_LCDR_DATA_MASK) >> ADC_LCDR_DATA_SHIFT); - /* And give the sample data to the ADC upper half */ + /* Verify that the upper-half driver has bound its callback functions */ - (void)adc_receive(priv->dev, chan, sample); + if (priv->cb != NULL) + { + /* Give the sample data to the ADC upper half */ + + DEBUGASSERT(priv->cb->au_receive != NULL); + priv->cb->au_receive(priv->dev, chan, sample); + } } } @@ -858,7 +869,17 @@ static void sam_adc_endconversion(void *arg) /* Read the ADC sample and pass it to the upper half */ regval = sam_adc_getreg(priv, SAM_ADC_CDR(chan)); - (void)adc_receive(priv->dev, chan, regval & ADC_CDR_DATA_MASK); + + /* 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(priv->dev, chan, regval & ADC_CDR_DATA_MASK); + } + pending &= ~bit; } } @@ -954,6 +975,26 @@ static int sam_adc_interrupt(int irq, void *context) /**************************************************************************** * ADC methods ****************************************************************************/ + +/**************************************************************************** + * Name: sam_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 sam_adc_bind(FAR struct adc_dev_s *dev, + FAR const struct adc_callback_s *callback) +{ + struct sam_adc_s *priv = (struct sam_adc_s *)dev->ad_priv; + + DEBUGASSERT(priv != NULL); + priv->cb = callback; + return OK; +} + /**************************************************************************** * Name: sam_adc_reset * @@ -1980,6 +2021,7 @@ struct adc_dev_s *sam_adc_initialize(void) /* Initialize the private ADC device data structure */ sem_init(&priv->exclsem, 0, 1); + priv->cb = NULL; priv->dev = &g_adcdev; #ifdef CONFIG_SAMA5_ADC_DMA