summaryrefslogtreecommitdiff
path: root/nuttx/arch/arm/src
diff options
context:
space:
mode:
authorpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-19 14:45:26 +0000
committerpatacongo <patacongo@42af7a65-404d-4744-a932-0658087f49c3>2013-03-19 14:45:26 +0000
commitc79e92ceffd9665632b58a6fb884178a4f4c71a2 (patch)
tree3a9f58cf49adcd4cb4e19f29fa9de73dfd12cb16 /nuttx/arch/arm/src
parent18f9d0eaa3b20a4c3a11c9a3f4e60a150e11d69f (diff)
downloadpx4-nuttx-c79e92ceffd9665632b58a6fb884178a4f4c71a2.tar.gz
px4-nuttx-c79e92ceffd9665632b58a6fb884178a4f4c71a2.tar.bz2
px4-nuttx-c79e92ceffd9665632b58a6fb884178a4f4c71a2.zip
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
Diffstat (limited to 'nuttx/arch/arm/src')
-rw-r--r--nuttx/arch/arm/src/lpc17xx/Kconfig29
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_adc.c53
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_adc.h40
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_spi.c25
-rw-r--r--nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c23
5 files changed, 148 insertions, 22 deletions
diff --git a/nuttx/arch/arm/src/lpc17xx/Kconfig b/nuttx/arch/arm/src/lpc17xx/Kconfig
index db76eeb77..0b482540f 100644
--- a/nuttx/arch/arm/src/lpc17xx/Kconfig
+++ b/nuttx/arch/arm/src/lpc17xx/Kconfig
@@ -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"
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c b/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c
index a3d20d8eb..bcc42f153 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_adc.c
@@ -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
}
/****************************************************************************
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_adc.h b/nuttx/arch/arm/src/lpc17xx/lpc17_adc.h
index 5a1bef14a..ecca04446 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_adc.h
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_adc.h
@@ -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
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_spi.c b/nuttx/arch/arm/src/lpc17xx/lpc17_spi.c
index 05e791434..d87e6c1ec 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_spi.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_spi.c
@@ -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:
*
diff --git a/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c b/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c
index 96b66d7a1..151efbd89 100644
--- a/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c
+++ b/nuttx/arch/arm/src/lpc17xx/lpc17_ssp.c
@@ -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:
*