Add workaround for ADC errata from Chris Taglia
git-svn-id: svn://svn.code.sf.net/p/nuttx/code/trunk@5760 42af7a65-404d-4744-a932-0658087f49c3
This commit is contained in:
parent
ffd85ebe97
commit
1f3846afd5
@ -392,6 +392,35 @@ config ADC0_SPS
|
||||
depends on LPC17_ADC
|
||||
default 1000
|
||||
|
||||
config ADC_CHANLIST
|
||||
bool "Use ADC channel list"
|
||||
default n
|
||||
---help--
|
||||
The errata that states: "A/D Global Data register should not be used
|
||||
with burst mode or hardware triggering". If this option is selected,
|
||||
then the ADC driver will grab from the individual channel registers
|
||||
rather than from the global data register as this is the stated
|
||||
workaround in the errata.
|
||||
|
||||
The ADC interrupt will trigger on conversion complete on the last
|
||||
channel listed in the array g_adc_chanlist[] (as opposed to
|
||||
triggering interrupt from the global DONE flag).
|
||||
|
||||
If this option is enabled, then the platform specific code must do
|
||||
two things: (1) define ADC_NCHANNELS in the configuration file and
|
||||
(2) provide an array g_adc_chanlist[] with the channel numbers
|
||||
matching the ADC0_MASK within the board-specific library.
|
||||
|
||||
config ADC_NCHANNELS
|
||||
int "ADC0 number of channels"
|
||||
depends on LPC17_ADC
|
||||
default 0
|
||||
---help--
|
||||
If CONFIG_ADC_CHANLIST is enabled, then the platform specific code
|
||||
must do two things: (1) define ADC_NCHANNELS in the configuration
|
||||
file and (2) provide an array g_adc_chanlist[] with the channel
|
||||
numbers matching the ADC0_MASK within the board-specific library.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "CAN driver options"
|
||||
|
@ -4,7 +4,7 @@
|
||||
* Copyright (C) 2011 Li Zhuoyi. All rights reserved.
|
||||
* Author: Li Zhuoyi <lzyy.cn@gmail.com>
|
||||
* History: 0.1 2011-08-05 initial version
|
||||
*
|
||||
*
|
||||
* This file is a part of NuttX:
|
||||
*
|
||||
* Copyright (C) 2010, 2013 Gregory Nutt. All rights reserved.
|
||||
@ -202,7 +202,7 @@ static void adc_reset(FAR struct adc_dev_s *dev)
|
||||
{
|
||||
lpc17_configgpio(GPIO_AD0p7);
|
||||
}
|
||||
|
||||
|
||||
irqrestore(flags);
|
||||
}
|
||||
|
||||
@ -276,7 +276,18 @@ static void adc_rxint(FAR struct adc_dev_s *dev, bool enable)
|
||||
|
||||
if (enable)
|
||||
{
|
||||
#ifdef CONFIG_ADC_CHANLIST
|
||||
/* Trigger interrupt at the end of conversion on the last A/D channel
|
||||
* in the channel list.
|
||||
*/
|
||||
|
||||
putreg32(ADC_INTEN_CHAN(g_adc_chanlist[CONFIG_ADC_NCHANNELS - 1]),
|
||||
LPC17_ADC_INTEN);
|
||||
#else
|
||||
/* Trigger interrupt using the global DONE flag. */
|
||||
|
||||
putreg32(ADC_INTEN_GLOBAL, LPC17_ADC_INTEN);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -309,11 +320,45 @@ static int adc_ioctl(FAR struct adc_dev_s *dev, int cmd, unsigned long arg)
|
||||
|
||||
static int adc_interrupt(int irq, void *context)
|
||||
{
|
||||
#ifdef CONFIG_ADC_CHANLIST
|
||||
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
|
||||
uint32_t regval;
|
||||
unsigned char ch;
|
||||
int32_t value;
|
||||
|
||||
int i;
|
||||
|
||||
regval = getreg32(LPC17_ADC_GDR);
|
||||
for(i = 0; i < CONFIG_ADC_NCHANNELS; i++
|
||||
{
|
||||
ch = g_adc_chanlist[i];
|
||||
regval = getreg32(LPC17_ADC_DR(ch));
|
||||
|
||||
if(regval&ADC_DR_DONE)
|
||||
{
|
||||
priv->count[ch]++;
|
||||
priv->buf[ch] += regval & 0xfff0;
|
||||
|
||||
if (priv->count[ch] >= CONFIG_ADC0_AVERAGE)
|
||||
{
|
||||
value = priv->buf[ch] / priv->count[ch];
|
||||
value <<= 15;
|
||||
adc_receive(&g_adcdev,ch,value);
|
||||
priv->buf[ch] = 0;
|
||||
priv->count[ch] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
#else
|
||||
|
||||
FAR struct up_dev_s *priv = (FAR struct up_dev_s *)g_adcdev.ad_priv;
|
||||
uint32_t regval;
|
||||
unsigned char ch;
|
||||
int32_t value;
|
||||
|
||||
regval = getreg32(LPC17_ADC_GDR);
|
||||
ch = (regval >> 24) & 0x07;
|
||||
priv->buf[ch] += regval & 0xfff0;
|
||||
@ -329,6 +374,8 @@ static int adc_interrupt(int irq, void *context)
|
||||
}
|
||||
|
||||
return OK;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -46,6 +46,20 @@
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* If CONFIG_ADC_CHANLIST is enabled, then the platform specific code must do
|
||||
* two things: (1) define CONFIG_ADC_NCHANNELS in the configuration file and
|
||||
* (2) provide an array g_adc_chanlist[] with the channel numbers matching
|
||||
* the ADC0_MASK within the board-specific library.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ADC_CHANLIST
|
||||
# if !defined(CONFIG_ADC_NCHANNELS)
|
||||
# error "CONFIG_ADC_CHANLIST must defined in this configuration"
|
||||
# elif CONFIG_ADC_NCHANNELS < 1
|
||||
# error "The value of CONFIG_ADC_NCHANNELS is invalid"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@ -55,12 +69,33 @@
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef __cplusplus
|
||||
#undef EXTERN
|
||||
#if defined(__cplusplus)
|
||||
#define EXTERN extern "C"
|
||||
extern "C"
|
||||
{
|
||||
#else
|
||||
#define EXTERN extern
|
||||
#endif
|
||||
|
||||
|
||||
/* The errata that states: "A/D Global Data register should not be used with
|
||||
* burst mode or hardware triggering". The configuration option
|
||||
* CONFIG_ADC_CHANLIST is a workaround for this errata. If this option is
|
||||
* selected, then the ADC driver will grab from the individual channel
|
||||
* registers rather than from the global data register as this is the stated
|
||||
* workaround in the errata.
|
||||
*
|
||||
* If this option is enabled, then the platform specific code must do two
|
||||
* things: (1) define CONFIG_ADC_NCHANNELS in the configuration file and
|
||||
* (2) provide an array g_adc_chanlist[] with the channel numbers matching
|
||||
* the ADC0_MASK within the board-specific library.
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_ADC_CHANLIST
|
||||
EXTERN uint8_t g_adc_chanlist[CONFIG_ADC_NCHANNELS];
|
||||
#endiff
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@ -80,6 +115,7 @@ extern "C"
|
||||
FAR struct adc_dev_s *lpc17_adcinitialize(void);
|
||||
#endif
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -63,28 +63,35 @@
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* This driver does not support the SPI exchange method. */
|
||||
|
||||
/* Enables debug output from this file (needs CONFIG_DEBUG too) */
|
||||
#ifdef CONFIG_SPI_EXCHANGE
|
||||
# error "CONFIG_SPI_EXCHANGE must not be defined in the configuration"
|
||||
#endif
|
||||
|
||||
#undef SPI_DEBUG /* Define to enable debug */
|
||||
#undef SPI_VERBOSE /* Define to enable verbose debug */
|
||||
/* Debug ********************************************************************/
|
||||
/* The following enable debug output from this file:
|
||||
*
|
||||
* CONFIG_DEBUG - Define to enable general debug features
|
||||
* CONFIG_DEBUG_SPI - Define to enable basic SSP debug (needs CONFIG_DEBUG)
|
||||
* CONFIG_DEBUG_VERBOSE - Define to enable verbose SSP debug
|
||||
*/
|
||||
|
||||
#ifdef SPI_DEBUG
|
||||
#ifdef CONFIG_DEBUG_SPI
|
||||
# define spidbg lldbg
|
||||
# ifdef SPI_VERBOSE
|
||||
# ifdef CONFIG_DEBUG_VERBOSE
|
||||
# define spivdbg lldbg
|
||||
# else
|
||||
# define spivdbg(x...)
|
||||
# endif
|
||||
#else
|
||||
# undef SPI_VERBOSE
|
||||
# define spidbg(x...)
|
||||
# define spivdbg(x...)
|
||||
#endif
|
||||
|
||||
/* SPI Clocking.
|
||||
*
|
||||
* The CPU clock by 1, 2, 4, or 8 to get the SPI peripheral clock (SPI_CLOCK).
|
||||
/* SSP Clocking *************************************************************/
|
||||
/* The CPU clock by 1, 2, 4, or 8 to get the SPI peripheral clock (SPI_CLOCK).
|
||||
* SPI_CLOCK may be further divided by 8-254 to get the SPI clock. If we
|
||||
* want a usable range of 4KHz to 25MHz for the SPI, then:
|
||||
*
|
||||
|
@ -63,16 +63,24 @@
|
||||
/****************************************************************************
|
||||
* Definitions
|
||||
****************************************************************************/
|
||||
/* Configuration ************************************************************/
|
||||
/* This driver does not support the SPI exchange method. */
|
||||
|
||||
/* The following enable debug output from this file (needs CONFIG_DEBUG too).
|
||||
#ifdef CONFIG_SPI_EXCHANGE
|
||||
# error "CONFIG_SPI_EXCHANGE must not be defined in the configuration"
|
||||
#endif
|
||||
|
||||
/* Debug ********************************************************************/
|
||||
/* The following enable debug output from this file:
|
||||
*
|
||||
* CONFIG_SPI_DEBUG - Define to enable basic SSP debug
|
||||
* CONFIG_VERBOSE - Define to enable verbose SSP debug
|
||||
* CONFIG_DEBUG - Define to enable general debug features
|
||||
* CONFIG_DEBUG_SPI - Define to enable basic SSP debug (needs CONFIG_DEBUG)
|
||||
* CONFIG_DEBUG_VERBOSE - Define to enable verbose SSP debug
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SPI_DEBUG
|
||||
#ifdef CONFIG_DEBUG_SPI
|
||||
# define sspdbg lldbg
|
||||
# ifdef CONFIG_VERBOSE
|
||||
# ifdef CONFIG_DEBUG_VERBOSE
|
||||
# define spivdbg lldbg
|
||||
# else
|
||||
# define spivdbg(x...)
|
||||
@ -82,9 +90,8 @@
|
||||
# define spivdbg(x...)
|
||||
#endif
|
||||
|
||||
/* SSP Clocking.
|
||||
*
|
||||
* The CPU clock by 1, 2, 4, or 8 to get the SSP peripheral clock (SSP_CLOCK).
|
||||
/* SSP Clocking *************************************************************/
|
||||
/* The CPU clock by 1, 2, 4, or 8 to get the SSP peripheral clock (SSP_CLOCK).
|
||||
* SSP_CLOCK may be further divided by 2-254 to get the SSP clock. If we
|
||||
* want a usable range of 4KHz to 25MHz for the SSP, then:
|
||||
*
|
||||
|
Loading…
Reference in New Issue
Block a user