Newer
Older
/****************************************************************************
* arch/arm/src/stm32/stm32_adc.c
*
* Copyright (C) 2011 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
* Diego Sanchez <dsanchez@nx-engineering.com>
*
* 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.
*
****************************************************************************/
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <stdio.h>
#include <sys/types.h>
#include <stdint.h>
#include <stdbool.h>
#include <semaphore.h>
#include <errno.h>
#include <debug.h>
#include <arch/board/board.h>
#include <nuttx/arch.h>
#include <nuttx/analog/adc.h>
#include "up_internal.h"
#include "up_arch.h"
#include "chip.h"
#include "stm32_internal.h"
#include "stm32_adc.h"
#ifdef CONFIG_ADC
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* Configuration ************************************************************/
/* Up to 3 ADC interfaces are supported */
#if STM32_NADC < 3
# undef CONFIG_STM32_ADC3
#endif
#if STM32_NADC < 2
# undef CONFIG_STM32_ADC2
#endif
#if STM32_NADC < 1
# undef CONFIG_STM32_ADC1
#endif
#if defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2) || defined(CONFIG_STM32_ADC3)
/* ADC interrupts */
#ifdef CONFIG_STM32_STM32F10XX
# define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC)
#else
# define ADC_SR_ALLINTS (ADC_SR_AWD | ADC_SR_EOC | ADC_SR_JEOC | ADC_SR_OVR)
#endif
#ifdef CONFIG_STM32_STM32F10XX
# define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE)
#else
# define ADC_CR1_ALLINTS (ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_JEOCIE | ADC_CR1_OVRIE)
#endif
/* The maximum number of samples */
#define ADC_MAX_SAMPLES 16
/****************************************************************************
* Private Types
****************************************************************************/
/* This structure describes the state of one ADC block */
uint8_t irq; /* Interrupt generated by this ADC block */
uint8_t nchannels; /* Number of channels */
uint8_t intf; /* ADC interface number */
xcpt_t isr; /* Interrupt handler for this ADC block */
uint32_t base; /* Base address of registers unique to this ADC block */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
/* ADC Register access */
static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset);
static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value);
static void adc_rccreset(int regaddr, bool reset);
static int adc_interrupt(FAR struct stm32_dev_s *priv);
#if defined(CONFIG_STM32_STM32F10XX) && (defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2))
static int adc12_interrupt(int irq, void *context);
#if defined(CONFIG_STM32_STM32F10XX) && defined (CONFIG_STM32_ADC3)
static int adc3_interrupt(int irq, void *context);
static int adc123_interrupt(int irq, void *context);
/* ADC Driver Methods */
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);
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);
static void adc_enable(FAR struct adc_dev_s *dev, bool enable);
/****************************************************************************
* Private Data
****************************************************************************/
static const struct adc_ops_s g_adcops =
{
.ao_reset = adc_reset,
.ao_setup = adc_setup,
.ao_shutdown = adc_shutdown,
.ao_rxint = adc_rxint,
.ao_ioctl = adc_ioctl,
};
#ifdef CONFIG_STM32_ADC1
static struct stm32_dev_s g_adcpriv1 =
{
#ifdef CONFIG_STM32_STM32F10XX
.irq = STM32_IRQ_ADC12,
.isr = adc12_interrupt,
.irq = STM32_IRQ_ADC,
.isr = adc123_interrupt,
};
static struct adc_dev_s g_adcdev1 =
{
.ad_ops = &g_adcops,
#ifdef CONFIG_STM32_ADC2
static struct stm32_dev_s g_adcpriv2 =
{
#ifdef CONFIG_STM32_STM32F10XX
.irq = STM32_IRQ_ADC12,
.isr = adc12_interrupt,
.irq = STM32_IRQ_ADC,
.isr = adc123_interrupt,
};
static struct adc_dev_s g_adcdev2 =
{
.ad_ops = &g_adcops,
.ad_priv= &g_adcpriv2,
#ifdef CONFIG_STM32_ADC3
static struct stm32_dev_s g_adcpriv3 =
{
#ifdef CONFIG_STM32_STM32F10XX
.irq = STM32_IRQ_ADC3,
.isr = adc3_interrupt,
.irq = STM32_IRQ_ADC,
.isr = adc123_interrupt,
};
static struct adc_dev_s g_adcdev3 =
{
.ad_ops = &g_adcops,
};
#endif
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* priv - A reference to the ADC block status
* offset - The offset to the register to read
*
* Returned Value:
*
****************************************************************************/
static uint32_t adc_getreg(struct stm32_dev_s *priv, int offset)
/****************************************************************************
* Name: adc_getreg
*
* Description:
* Read the value of an ADC register.
*
* Input Parameters:
* priv - A reference to the ADC block status
* offset - The offset to the register to read
*
* Returned Value:
*
****************************************************************************/
static void adc_putreg(struct stm32_dev_s *priv, int offset, uint32_t value)
{
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
/****************************************************************************
* Name: adc_rccreset
*
* Description:
* Deinitializes the ADCx peripheral registers to their default
* reset values. It could set all the ADCs configured.
*
* Input Parameters:
* regaddr - The register to read
* reset - Condition, set or reset
*
* Returned Value:
*
****************************************************************************/
static void adc_rccreset(struct stm32_dev_s *priv, bool reset)
{
uint32_t regval;
uint32_t adcbit;
/* Pick the appropriate bit in the APB2 reset register */
#ifdef CONFIG_STM32_STM32F10XX
/* For the STM32 F1, there is an individual bit to reset each ADC. */
switch (priv->intf)
{
#ifdef CONFIG_STM32_ADC1
case 1:
adcbit = RCC_APB2RSTR_ADC1RST;
break;
#endif
#ifdef CONFIG_STM32_ADC2
case 2:
adcbit = RCC_APB2RSTR_ADC2RST;
break;
#endif
#ifdef CONFIG_STM32_ADC3
case 3:
adcbit = RCC_APB2RSTR_ADC3RST;
break;
#endif
default:
return;
}
#else
/* For the STM32 F4, there is one common reset for all ADC block.
* THIS will probably cause some problems!
*/
adcbit = RCC_APB2RSTR_ADCRST;
#endif
/* Set or clear the selected bit in the APB2 reset register */
regval = getreg32(STM32_RCC_APB2RSTR);
if (reset)
{
/* Enable ADC reset state */
regval |= adcbit;
}
else
{
/* Release ADC from reset state */
regval &= ~adcbit;
}
putreg32(regval, STM32_RCC_APB2RSTR);
}
/*******************************************************************************
* Name: adc_enable
*
* Description : Enables or disables the specified ADC peripheral.
*
* Input Parameters:
*
* enable - true: enable ADC convertion
* false: disable ADC convertion
*
* Returned Value:
*
*******************************************************************************/
static void adc_enable(FAR struct adc_dev_s *dev, bool enable)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
uint32_t regval;
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
if (enable)
{
regval |= ADC_CR2_ADON;
}
else
{
regval &= ~ADC_CR2_ADON;
}
adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
}
/****************************************************************************
* Name: adc_reset
*
* Description:
* Reset the ADC device. Called early to initialize the hardware. This
* is called, before adc_setup() and on error conditions.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static void adc_reset(FAR struct adc_dev_s *dev)
{
adbg("Initializing the ADC to the reset values \n");
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
irqstate_t flags;
uint32_t regval;
uint32_t L = priv->nchannels;
uint32_t ch;
int offset = 0;
/* Enable ADC reset state */
adc_rccreset(priv, true);
/* Release ADC from reset state */
adc_rccreset(priv, false);
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
/* Initialize the watchdog high threshold register */
adc_putreg(priv, STM32_ADC_HTR_OFFSET, 0x00000fff);
/* Initialize the watchdog low threshold register */
adc_putreg(priv, STM32_ADC_LTR_OFFSET, 0x00000000);
#ifdef CONFIG_STM32_STM32F40XX
/* Initialize ADC Prescaler*/
regval = getreg32(STM32_ADC_CCR_OFFSET);
/* PCLK2 divided by 2 */
regval &= ~ADC_CCR_ADCPRE_MASK;
putreg32(regval,STM32_ADC_CCR_OFFSET);
#endif
/* Initialize the same sample time for each ADC 1.5 cycles
*
* During sample cycles channel selection bits must remain unchanged.
*
* 000: 1.5 cycles
* 001: 7.5 cycles
* 010: 13.5 cycles
* 011: 28.5 cycles
* 100: 41.5 cycles
* 101: 55.5 cycles
* 110: 71.5 cycles
* 111: 239.5 cycles
*/
adc_putreg(priv,STM32_ADC_SMPR1_OFFSET,0x00000000);
adc_putreg(priv,STM32_ADC_SMPR2_OFFSET,0x00000000);
/* ADC CR1 Configuration */
regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
regval &= ~ADC_CR1_DUALMOD_MASK;
regval &= ~ADC_CR1_SCAN; /* Clear DUALMODE and SCAN bits */
adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
/* Initialize the ADC_Mode (ADC_Mode_Independent) */
regval = adc_getreg(priv, STM32_ADC_CR1_OFFSET);
regval |= ADC_CR1_IND;
/* Initialize the ADC_CR1_SCAN member DISABLE */
regval &= ~ADC_CR1_SCAN;
adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
/* ADC1 CR2 Configuration */
/* Set the ADON bit to wake up the ADC from power down mode */
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
regval |= ADC_CR2_ADON;
/* Clear CONT, ALIGN and EXTTRIG bits */
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
regval &= ~ADC_CR2_CONT;
regval &= ~ADC_CR2_ALIGN;
regval &= ~ADC_CR2_EXTSEL_MASK;
adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
/* Set CONT, ALIGN and EXTTRIG bits */
/* Initialize the ALIGN: Data alignment Right */
regval = adc_getreg(priv, STM32_ADC_CR2_OFFSET);
regval &= ~ADC_CR2_ALIGN;
/* Initialize the External event select "Timer CC1 event" */
regval &= ~ADC_CR2_EXTSEL_MASK;
/* Initialize the ADC_ContinuousConvMode "Single conversion mode" */
regval &= ~ADC_CR2_CONT;
adc_putreg(priv, STM32_ADC_CR2_OFFSET, regval);
regval = adc_getreg(priv, STM32_ADC_SQR1_OFFSET);
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
regval &= ~ADC_SQR1_L_MASK; /* Clear L Mask */
regval |= L; /* SetL, # of convertions */
adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
/* Configuration of the channels convertions */
#warning "I can improve the ugly code below with a logic using offsets"
#warning "Or.. better yet, a loop"
regval = adc_getreg(priv, STM32_ADC_SQR3_OFFSET);
if (priv->nchannels >= 1)
{
ch = priv->chanlist[0];
ch <<= offset;
regval &= ~ADC_SQR3_SQ1_MASK; /* clear SQ1 */
regval |= ch; /* Set SQ1 */
adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 2)
{
ch = priv->chanlist[1];
ch <<= offset;
regval &= ~ADC_SQR3_SQ2_MASK; /* clear SQ2 */
regval |= ch; /* Set SQ2 */
adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 3)
{
ch = priv->chanlist[2];
ch <<= offset;
regval &= ~ADC_SQR3_SQ3_MASK; /* clear SQ3 */
regval |= ch; /* SetSQ3 */
adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 4)
{
ch = priv->chanlist[3];
ch <<= offset;
regval &= ~ADC_SQR3_SQ4_MASK; /* clear SQ4 */
regval |= ch; /* SetSQ4 */
adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 5)
{
ch = priv->chanlist[4];
ch <<= offset;
regval &= ~ADC_SQR3_SQ5_MASK; /* clear SQ5 */
regval |= ch; /* SetSQ5 */
adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 6)
{
ch = priv->chanlist[5];
ch <<= offset;
regval &= ~ADC_SQR3_SQ6_MASK; /* clear SQ6 */
regval |= ch; /* SetSQ6 */
adc_putreg(priv, STM32_ADC_SQR3_OFFSET, regval);
offset = 0;
}
if (priv->nchannels >= 7)
{
ch = priv->chanlist[6];
ch <<= offset;
regval &= ~ADC_SQR2_SQ7_MASK; /* clear SQ7 */
regval |= ch; /* SetSQ7 */
adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 8)
{
ch = priv->chanlist[7];
ch <<= offset;
regval &= ~ADC_SQR2_SQ8_MASK; /* clear SQ8 */
regval |= ch; /* SetSQ8 */
adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 9)
{
ch = priv->chanlist[8];
ch <<= offset;
regval &= ~ADC_SQR2_SQ9_MASK; /* clear SQ9 */
regval |= ch; /* SetSQ9 */
adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 10)
{
ch = priv->chanlist[9];
ch <<= offset;
regval &= ~ADC_SQR2_SQ10_MASK; /* clear SQ10 */
regval |= ch; /* SetSQ10 */
adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
offset += 5;
}
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
if (priv->nchannels >= 11)
{
ch = priv->chanlist[10];
ch <<= offset;
regval &= ~ADC_SQR2_SQ11_MASK; /* clear SQ11 */
regval |= ch; /* SetSQ11 */
adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 12)
{
ch = priv->chanlist[11];
ch <<= offset;
regval &= ~ADC_SQR2_SQ12_MASK; /* clear SQ12 */
regval |= ch; /* SetSQ12 */
adc_putreg(priv, STM32_ADC_SQR2_OFFSET, regval);
offset = 0;
}
if (priv->nchannels >= 13)
{
ch = priv->chanlist[12];
ch <<= offset;
regval &= ~ADC_SQR1_SQ13_MASK; /* clear SQ13 */
regval |= ch; /* SetSQ13 */
adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 14)
{
ch = priv->chanlist[13];
ch <<= offset;
regval &= ~ADC_SQR1_SQ14_MASK; /* clear SQ14 */
regval |= ch; /* SetSQ14 */
adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 15)
{
ch = priv->chanlist[14];
ch <<= offset;
regval &= ~ADC_SQR1_SQ15_MASK; /* clear SQ15 */
regval |= ch; /* SetSQ15 */
adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
offset += 5;
}
if (priv->nchannels >= 16)
{
ch = priv->chanlist[15];
ch <<= offset;
regval &= ~ADC_SQR1_SQ16_MASK; /* clear SQ16 */
regval |= ch; /* SetSQ16 */
adc_putreg(priv, STM32_ADC_SQR1_OFFSET, regval);
}
if (priv->nchannels >= 17)
{
adbg("ERROR: Number of channels exceeded\n");
}
irqrestore(flags);
}
/****************************************************************************
* 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.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static int adc_setup(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
int ret;
priv->buf[i] = 0;
priv->count[i] = 0;
/* Enable the ADC interrupt */
up_enable_irq(priv->irq);
}
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
return ret;
}
/****************************************************************************
* 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.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static void adc_shutdown(FAR struct adc_dev_s *dev)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
/* Disable ADC interrupts and detach the ADC interrupt handler */
up_disable_irq(priv->irq);
irq_detach(priv->irq);
/* Disable and reset the ADC module */
}
/****************************************************************************
* Name: adc_rxint
*
* Description:
* Call to enable or disable RX interrupts.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
{
FAR struct stm32_dev_s *priv = (FAR struct stm32_dev_s *)dev->ad_priv;
/* Enable the end-of-conversion ADC interrupt */
regval |= ADC_CR1_EOCIE;
/* Enable all ADC interrupts */
regval &= ~ADC_CR1_ALLINTS;
adc_putreg(priv, STM32_ADC_CR1_OFFSET, regval);
}
/****************************************************************************
* Name: adc_ioctl
*
* Description:
* All ioctl calls will be routed through this method.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
{
return -ENOTTY;
}
/****************************************************************************
* Name: adc_interrupt
*
* Description:
* Common ADC interrupt handler.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static int adc_interrupt(FAR struct stm32_dev_s *priv)
uint32_t adcsr;
int32_t value;
uint8_t ch;
int i;
/* Identifies the interruption AWD or EOC */
adcsr = adc_getreg(priv, STM32_ADC_SR_OFFSET);
if ((adcsr & ADC_SR_AWD) != 0)
{
adbg(" Analog Watchdog, Value converted out of range!\n");
}
/* EOC: End of conversion */
if ((adcsr & ADC_SR_EOC) != 0)
{
value = adc_getreg(priv, STM32_ADC_DR_OFFSET);
value &= ADC_DR_DATA_MASK;
#error "i is not assigned a value"
ch = priv->chanlist[i]; /* Channel converted */
/* Handle the ADC interrupt */
adc_receive(priv, ch, value);
priv->buf[ch] = 0;
priv->count[ch] = 0;
}
}
/****************************************************************************
* Name: adc12_interrupt
*
* Description:
* ADC12 interrupt handler for the STM32 F1 family.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
#if defined(CONFIG_STM32_STM32F10XX) && (defined(CONFIG_STM32_ADC1) || defined(CONFIG_STM32_ADC2))
static int adc12_interrupt(int irq, void *context)
{
uint32_t pending;
/* Check for pending ADC1 interrupts */
#ifdef CONFIG_STM32_ADC1
pending = regval & ADC_SR_ALLINTS;
if (pending != 0)
{
adc_interrupt(&g_adcpriv1);
regval &= ~pending;
putreg32(regval, STM32_ADC1_SR);
}
#endif
/* Check for pending ADC2 interrupts */
#ifdef CONFIG_STM32_ADC2
pending = regval & ADC_SR_ALLINTS;
if (pending != 0)
{
adc_interrupt(&g_adcpriv2);
regval &= ~pending;
putreg32(regval, STM32_ADC2_SR);
}
#endif
return OK;
}
#endif
/****************************************************************************
* Name: adc3_interrupt
*
* Description:
* ADC1/2 interrupt handler for the STM32 F1 family.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
#if defined (CONFIG_STM32_STM32F10XX) && defined (CONFIG_STM32_ADC3)
static int adc3_interrupt(int irq, void *context)
{
uint32_t regval;
uint32_t pending;
/* Check for pending ADC3 interrupts */
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
pending = regval & ADC_SR_ALLINTS;
if (pending != 0)
{
adc_interrupt(&g_adcpriv3);
regval &= ~pending;
putreg32(regval, STM32_ADC3_SR);
}
return OK;
}
#endif
/****************************************************************************
* Name: adc123_interrupt
*
* Description:
* ADC1/2/3 interrupt handler for the STM32 F4 family.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
#ifdef CONFIG_STM32_STM32F40XX
static int adc123_interrupt(int irq, void *context)
{
uint32_t regval;
uint32_t pending;
/* Check for pending ADC1 interrupts */
#ifdef CONFIG_STM32_ADC1
pending = regval & ADC_SR_ALLINTS;
if (pending != 0)
{
adc_interrupt(&g_adcpriv1);
regval &= ~pending;
putreg32(regval, STM32_ADC1_SR);
}
#endif
/* Check for pending ADC2 interrupts */
#ifdef CONFIG_STM32_ADC2
pending = regval & ADC_SR_ALLINTS;
if (pending != 0)
{
adc_interrupt(&g_adcpriv2);
regval &= ~pending;
putreg32(regval, STM32_ADC2_SR);
}
#endif
/* Check for pending ADC3 interrupts */
#ifdef CONFIG_STM32_ADC3
pending = regval & ADC_SR_ALLINTS;
if (pending != 0)
{
regval &= ~pending;
putreg32(regval, STM32_ADC3_SR);
}
#endif
return OK;
}
#endif
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Initialize the ADC. The logic is, save nchannels : # of channels
* (conversions) in ADC_SQR1_L
* Then, take the chanlist array and store it in the SQR Regs,
* chanlist[0] -> ADC_SQR3_SQ1
* chanlist[1] -> ADC_SQR3_SQ2
* chanlist[2] -> ADC_SQR3_SQ3
* chanlist[3] -> ADC_SQR3_SQ4
* chanlist[4] -> ADC_SQR3_SQ5
* chanlist[5] -> ADC_SQR3_SQ6
* ...
* chanlist[15]-> ADC_SQR1_SQ16
*
* up to
* chanlist[nchannels]