diff --git a/drivers/analog/Kconfig b/drivers/analog/Kconfig index bc05480422..5c68f518e7 100644 --- a/drivers/analog/Kconfig +++ b/drivers/analog/Kconfig @@ -46,6 +46,7 @@ config ADC_ADS125X bool "TI ADS1255/ADS1256 support" default n select SPI + select SCHED_HPWORK if ADC_ADS125X diff --git a/drivers/analog/ads1255.c b/drivers/analog/ads1255.c index 8fbe3921ab..0f380a4058 100644 --- a/drivers/analog/ads1255.c +++ b/drivers/analog/ads1255.c @@ -39,6 +39,10 @@ * ************************************************************************************/ +/**************************************************************************** + * Included Files + ****************************************************************************/ + #include #include @@ -50,13 +54,17 @@ #include #include -#include #include +#include #include #include #if defined(CONFIG_ADC_ADS1255) +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + #define ADS125X_BUFON 0x02 #define ADS125X_BUFOFF 0x00 @@ -103,12 +111,14 @@ #endif /**************************************************************************** - * ad_private Types + * Private Types ****************************************************************************/ struct ads1255_dev_s { FAR const struct adc_callback_s *cb; + FAR struct spi_dev_s *spi; /* Cached SPI device reference */ + struct work_s work; uint8_t channel; uint32_t sps; uint8_t pga; @@ -116,11 +126,10 @@ struct ads1255_dev_s const uint8_t *mux; int irq; int devno; - FAR struct spi_dev_s *spi; /* Cached SPI device reference */ }; /**************************************************************************** - * ad_private Function Prototypes + * Private Function Prototypes ****************************************************************************/ /* ADC methods */ @@ -132,10 +141,14 @@ static int adc_setup(FAR struct adc_dev_s *dev); static void adc_shutdown(FAR struct adc_dev_s *dev); static void adc_rxint(FAR struct adc_dev_s *dev, bool enable); static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg); + +/* Interrupt handling */ + +static void adc_worker(FAR void *arg); static int adc_interrupt(int irq, void *context); /**************************************************************************** - * ad_private Data + * Private Data ****************************************************************************/ static const struct adc_ops_s g_adcops = @@ -351,16 +364,16 @@ static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg) } /**************************************************************************** - * Name: adc_interrupt + * Name: adc_worker * * Description: - * ADC interrupt handler + * ADC interrupt work * ****************************************************************************/ -static int adc_interrupt(int irq, void *context) +static void adc_worker(FAR void *arg) { - FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)g_adcdev.ad_priv; + FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)arg; FAR struct spi_dev_s *spi; unsigned char buf[4]; unsigned char ch; @@ -406,6 +419,34 @@ static int adc_interrupt(int irq, void *context) priv->cb->au_receive(&g_adcdev, priv->channel, *(int32_t *)buf); } + /* Re-enable ADC interrupts */ + + up_enable_irq(priv->irq); +} + +/**************************************************************************** + * Name: adc_interrupt + * + * Description: + * ADC interrupt handler + * + ****************************************************************************/ + +static int adc_interrupt(int irq, void *context) +{ + FAR struct ads1255_dev_s *priv = (FAR struct ads1255_dev_s *)g_adcdev.ad_priv; + + DEBUGASSERT(priv != NULL); + + /* Disable further ADC interrupts until the worker thread has executed. */ + + up_disable_irq(priv->irq); + + /* Schedule the ADC work for the worker thread. Whent he sample has been + * processed, the ADC interrupt will be re-enabled. + */ + + DEBUGVERIFY(work_queue(HPWORK, &priv->work, adc_worker, priv, 0)); return OK; }