You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by pk...@apache.org on 2023/03/25 16:37:59 UTC

[nuttx] branch master updated (c702223fab -> f48846676e)

This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git


    from c702223fab Documentation: Improve pages for ESP boards
     new 3571ff3c54 arch/nrf53: add SAADC support
     new f48846676e boards/nrf5340-dk: add ADC configuration

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 arch/arm/src/nrf53/Kconfig                         |  68 ++++-
 arch/arm/src/nrf53/Make.defs                       |   4 +
 .../src/{nrf52/nrf52_adc.c => nrf53/nrf53_adc.c}   | 322 ++++++++++-----------
 .../src/{nrf52/nrf52_adc.h => nrf53/nrf53_adc.h}   | 106 +++----
 .../configs/{timer_cpuapp => adc_cpuapp}/defconfig |   8 +-
 boards/arm/nrf53/nrf5340-dk/include/board.h        |  14 +
 boards/arm/nrf53/nrf5340-dk/src/Makefile           |   4 +
 boards/arm/nrf53/nrf5340-dk/src/nrf5340-dk.h       |  12 +
 .../nrf5340-dk/src/nrf53_adc.c}                    | 102 +++----
 boards/arm/nrf53/nrf5340-dk/src/nrf53_bringup.c    |  12 +
 10 files changed, 384 insertions(+), 268 deletions(-)
 copy arch/arm/src/{nrf52/nrf52_adc.c => nrf53/nrf53_adc.c} (68%)
 copy arch/arm/src/{nrf52/nrf52_adc.h => nrf53/nrf53_adc.h} (56%)
 copy boards/arm/nrf53/nrf5340-dk/configs/{timer_cpuapp => adc_cpuapp}/defconfig (90%)
 copy boards/arm/{nrf52/nrf52840-dk/src/nrf52_adc.c => nrf53/nrf5340-dk/src/nrf53_adc.c} (64%)


[nuttx] 01/02: arch/nrf53: add SAADC support

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit 3571ff3c54c8cd60b86cfbf100e821e838937715
Author: raiden00pl <ra...@railab.me>
AuthorDate: Mon Mar 13 12:32:56 2023 +0100

    arch/nrf53: add SAADC support
---
 arch/arm/src/nrf53/Kconfig     |  68 ++-
 arch/arm/src/nrf53/Make.defs   |   4 +
 arch/arm/src/nrf53/nrf53_adc.c | 964 +++++++++++++++++++++++++++++++++++++++++
 arch/arm/src/nrf53/nrf53_adc.h | 162 +++++++
 4 files changed, 1197 insertions(+), 1 deletion(-)

diff --git a/arch/arm/src/nrf53/Kconfig b/arch/arm/src/nrf53/Kconfig
index 7ed9deeb01..d9469c8d89 100644
--- a/arch/arm/src/nrf53/Kconfig
+++ b/arch/arm/src/nrf53/Kconfig
@@ -23,6 +23,7 @@ config NRF53_APPCORE
 	select ARM_HAVE_DSP
 	select ARCH_HAVE_FPU
 	select NRF53_HAVE_PWM
+	select NRF53_HAVE_SAADC
 
 config NRF53_NETCORE
 	bool
@@ -36,7 +37,6 @@ choice
 config ARCH_CHIP_NRF5340_CPUAPP
 	bool "NRF53 App core"
 	select NRF53_APPCORE
-	select ARCH_HAVE_FPU
 
 config ARCH_CHIP_NRF5340_CPUNET
 	bool "NRF53 Net core"
@@ -74,6 +74,10 @@ config NRF53_HAVE_PWM
 	bool
 	default n
 
+config NRF53_HAVE_SAADC
+	bool
+	default n
+
 # Peripheral Selection
 
 config NRF53_IPC
@@ -136,6 +140,10 @@ config NRF53_PWM2
 	select NRF53_PWM
 	default n
 
+config NRF53_SAADC
+	bool "SAADC"
+	default n
+
 endmenu # NRF53 Peripheral Selection
 
 menu "Clock Configuration"
@@ -332,6 +340,64 @@ endif # !NRF53_PWM_MULTICHAN
 
 endmenu # PWM configuration
 
+menu "SAADC Configuration"
+
+if NRF53_SAADC
+
+choice
+	prompt "SAADC trigger selection"
+	default NRF53_SAADC_TASK
+	---help---
+		Choose mode for sample rate control
+
+config NRF53_SAADC_TASK
+	bool "SAADC Task trigger"
+
+config NRF53_SAADC_TIMER
+	bool "SAADC Timer trigger"
+
+endchoice # SAADC trigger selection
+
+if NRF53_SAADC_TIMER
+
+config NRF53_SAADC_TIMER_CC
+	int "SAADC Timer CC"
+	default 0
+	range 80 2047
+
+endif #NRF53_SAADC_TIMER
+
+config NRF53_SAADC_OVERSAMPLE
+	int "SAADC oversample"
+	default 0
+	range 0 8
+	---help---
+		SAADC oversample control
+
+config NRF53_SAADC_RESOLUTION
+	int "SAADC resolution"
+	default 0
+	range 0 3
+	---help---
+		SAADC resolution 0 - 8 bits, 1 - 10 bits, 2 - 12 bits, 3 - 14 bits
+
+config NRF53_SAADC_CHANNELS
+	int "SAADC channels"
+	default 8
+	range 0 8
+	---help---
+		SAADC channels
+
+config NRF53_SAADC_LIMITS
+	bool "SAADC limits enable"
+	default n
+	---help---
+		SAADC limist enable
+
+endif # NRF53_SAADC
+
+endmenu # SAADC Configuration
+
 menuconfig NRF53_SOFTDEVICE_CONTROLLER
 	bool "SoftDevice Controller"
 	depends on ALLOW_BSDNORDIC_COMPONENTS
diff --git a/arch/arm/src/nrf53/Make.defs b/arch/arm/src/nrf53/Make.defs
index cef4be459b..ab2ee577a5 100644
--- a/arch/arm/src/nrf53/Make.defs
+++ b/arch/arm/src/nrf53/Make.defs
@@ -62,6 +62,10 @@ ifeq ($(CONFIG_NRF53_PWM),y)
 CHIP_CSRCS += nrf53_pwm.c
 endif
 
+ifeq ($(CONFIG_NRF53_SAADC),y)
+CHIP_CSRCS += nrf53_adc.c
+endif
+
 ifeq ($(CONFIG_PM),y)
 CHIP_CSRCS += nrf53_pminitialize.c
 endif
diff --git a/arch/arm/src/nrf53/nrf53_adc.c b/arch/arm/src/nrf53/nrf53_adc.c
new file mode 100644
index 0000000000..83d988229f
--- /dev/null
+++ b/arch/arm/src/nrf53/nrf53_adc.c
@@ -0,0 +1,964 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/nrf53_adc.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/irq.h>
+#include <nuttx/arch.h>
+#include <nuttx/analog/adc.h>
+#include <nuttx/analog/ioctl.h>
+
+#include "arm_internal.h"
+#include "nrf53_gpio.h"
+#include "nrf53_adc.h"
+
+#include "hardware/nrf53_saadc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Private Types
+ ****************************************************************************/
+
+struct nrf53_adc_s
+{
+  /* Upper-half callback */
+
+  const struct adc_callback_s *cb;
+
+  /* Channels configuration */
+
+  struct nrf53_adc_channel_s channels[CONFIG_NRF53_SAADC_CHANNELS];
+
+  /* Samples buffer */
+
+  int16_t                    buffer[CONFIG_NRF53_SAADC_CHANNELS];
+
+  uint8_t                    chan_len;   /* Configured channels */
+  uint32_t                   base;       /* Base address of ADC register */
+  uint32_t                   irq;        /* ADC interrupt */
+  uint8_t                    resolution; /* ADC resolution */
+};
+
+/****************************************************************************
+ * Private Function Prototypes
+ ****************************************************************************/
+
+/* ADC Register access */
+
+static inline void nrf53_adc_putreg(struct nrf53_adc_s *priv,
+                                    uint32_t offset,
+                                    uint32_t value);
+static inline uint32_t nrf53_adc_getreg(struct nrf53_adc_s *priv,
+                                        uint32_t offset);
+
+/* ADC helpers */
+
+static int nrf53_adc_configure(struct nrf53_adc_s *priv);
+static int nrf53_adc_calibrate(struct nrf53_adc_s *priv);
+static uint32_t nrf53_adc_ch_config(struct nrf53_adc_channel_s *cfg);
+static uint32_t nrf53_adc_chanpsel(int psel);
+static int nrf53_adc_chancfg(struct nrf53_adc_s *priv, uint8_t chan,
+                             struct nrf53_adc_channel_s *cfg);
+static int nrf53_adc_isr(int irq, void *context, void *arg);
+
+/* ADC Driver Methods */
+
+static int  nrf53_adc_bind(struct adc_dev_s *dev,
+                           const struct adc_callback_s *callback);
+static void nrf53_adc_reset(struct adc_dev_s *dev);
+static int  nrf53_adc_setup(struct adc_dev_s *dev);
+static void nrf53_adc_shutdown(struct adc_dev_s *dev);
+static void nrf53_adc_rxint(struct adc_dev_s *dev, bool enable);
+static int  nrf53_adc_ioctl(struct adc_dev_s *dev, int cmd,
+                            unsigned long arg);
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+/* ADC interface operations */
+
+static const struct adc_ops_s g_nrf53_adcops =
+{
+  .ao_bind        = nrf53_adc_bind,
+  .ao_reset       = nrf53_adc_reset,
+  .ao_setup       = nrf53_adc_setup,
+  .ao_shutdown    = nrf53_adc_shutdown,
+  .ao_rxint       = nrf53_adc_rxint,
+  .ao_ioctl       = nrf53_adc_ioctl,
+};
+
+/* SAADC device */
+
+struct nrf53_adc_s g_nrf53_adcpriv =
+{
+  .cb         = NULL,
+  .base       = NRF53_SAADC_BASE,
+  .irq        = NRF53_IRQ_SAADC,
+  .resolution = CONFIG_NRF53_SAADC_RESOLUTION
+};
+
+/* Upper-half ADC device */
+
+static struct adc_dev_s g_nrf53_adc =
+{
+  .ad_ops      = &g_nrf53_adcops,
+  .ad_priv     = &g_nrf53_adcpriv,
+};
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_adc_putreg
+ *
+ * Description:
+ *   Put a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline void nrf53_adc_putreg(struct nrf53_adc_s *priv,
+                                    uint32_t offset,
+                                    uint32_t value)
+{
+  DEBUGASSERT(priv);
+
+  putreg32(value, priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_getreg
+ *
+ * Description:
+ *   Get a 32-bit register value by offset
+ *
+ ****************************************************************************/
+
+static inline uint32_t nrf53_adc_getreg(struct nrf53_adc_s *priv,
+                                        uint32_t offset)
+{
+  DEBUGASSERT(priv);
+
+  return getreg32(priv->base + offset);
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_isr
+ *
+ * Description:
+ *   Common ADC interrupt service routine
+ *
+ ****************************************************************************/
+
+static int nrf53_adc_isr(int irq, void *context, void *arg)
+{
+  struct adc_dev_s   *dev  = (struct adc_dev_s *) arg;
+  struct nrf53_adc_s *priv = NULL;
+  int                 ret  = OK;
+  int                 i    = 0;
+
+  DEBUGASSERT(dev);
+
+  priv = (struct nrf53_adc_s *) dev->ad_priv;
+  DEBUGASSERT(priv);
+
+  ainfo("nrf53_adc_isr\n");
+
+  /* END event */
+
+  if (nrf53_adc_getreg(priv, NRF53_SAADC_EVENTS_END_OFFSET) == 1)
+    {
+      DEBUGASSERT(priv->cb != NULL);
+      DEBUGASSERT(priv->cb->au_receive != NULL);
+
+      /* Give the ADC data to the ADC driver */
+
+      for (i = 0; i < priv->chan_len; i += 1)
+        {
+          priv->cb->au_receive(dev, i, priv->buffer[i]);
+        }
+
+      /* Clear event */
+
+      nrf53_adc_putreg(priv, NRF53_SAADC_EVENTS_END_OFFSET, 0);
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_configure
+ *
+ * Description:
+ *   Configure ADC
+ *
+ ****************************************************************************/
+
+static int nrf53_adc_configure(struct nrf53_adc_s *priv)
+{
+  int regval = 0;
+
+  DEBUGASSERT(priv);
+
+  /* Configure ADC resolution */
+
+  regval = CONFIG_NRF53_SAADC_RESOLUTION;
+  nrf53_adc_putreg(priv, NRF53_SAADC_RESOLUTION_OFFSET, regval);
+
+  /* Configure oversampling */
+
+  regval = CONFIG_NRF53_SAADC_OVERSAMPLE;
+  nrf53_adc_putreg(priv, NRF53_SAADC_OVERSAMPLE_OFFSET, regval);
+
+  /* Configure sample rate */
+
+#if defined(CONFIG_NRF53_SAADC_TIMER)
+  /* Trigger from local timer */
+
+  regval = SAADC_SAMPLERATE_MODE_TIMERS;
+  regval |= ((CONFIG_NRF53_SAADC_TIMER_CC & SAADC_SAMPLERATE_CC_MASK)
+             << SAADC_SAMPLERATE_CC_SHIFT);
+#elif defined(CONFIG_NRF53_SAADC_TASK)
+  /* Trigger on SAMPLE tas */
+
+  regval = SAADC_SAMPLERATE_MODE_TASK;
+#else
+#  error SAADC trigger not selected
+#endif
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_SAMPLERATE_OFFSET, regval);
+
+  /* Configure ADC buffer */
+
+  regval = (uint32_t)&priv->buffer;
+  nrf53_adc_putreg(priv, NRF53_SAADC_PTR_OFFSET, regval);
+
+  regval = priv->chan_len;
+  nrf53_adc_putreg(priv, NRF53_SAADC_MAXCNT_OFFSET, regval);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_calibrate
+ *
+ * Description:
+ *   Calibrate ADC
+ *
+ ****************************************************************************/
+
+static int nrf53_adc_calibrate(struct nrf53_adc_s *priv)
+{
+  /* Clear Event */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_EVENTS_CALDONE_OFFSET, 0);
+
+  /* Start calibration */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_TASKS_CALOFFSET_OFFSET, 1);
+
+  /* Wait for calibration done */
+
+  while (nrf53_adc_getreg(priv, NRF53_SAADC_EVENTS_CALDONE_OFFSET) != 1);
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_ch_config
+ ****************************************************************************/
+
+static uint32_t nrf53_adc_ch_config(struct nrf53_adc_channel_s *cfg)
+{
+  uint32_t regval = 0;
+
+  /* Positive channel resistor control */
+
+  switch (cfg->resp)
+    {
+      case NRF53_ADC_RES_BYPASS:
+        {
+          regval |= SAADC_CONFIG_RESP_NONE;
+          break;
+        }
+
+      case NRF53_ADC_RES_PULLDOWN:
+        {
+          regval |= SAADC_CONFIG_RESP_PD;
+          break;
+        }
+
+      case NRF53_ADC_RES_PULLUP:
+        {
+          regval |= SAADC_CONFIG_RESP_PU;
+          break;
+        }
+
+      case NRF53_ADC_RES_VDD_2:
+        {
+          regval |= SAADC_CONFIG_RESP_VDD1P2;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->resp: %d\n", cfg->resp);
+        }
+    }
+
+  /* Negative channel resistor control */
+
+  switch (cfg->resn)
+    {
+      case NRF53_ADC_RES_BYPASS:
+        {
+          regval |= SAADC_CONFIG_RESN_NONE;
+          break;
+        }
+
+      case NRF53_ADC_RES_PULLDOWN:
+        {
+          regval |= SAADC_CONFIG_RESN_PD;
+          break;
+        }
+
+      case NRF53_ADC_RES_PULLUP:
+        {
+          regval |= SAADC_CONFIG_RESN_PU;
+          break;
+        }
+
+      case NRF53_ADC_RES_VDD_2:
+        {
+          regval |= SAADC_CONFIG_RESN_VDD1P2;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->resn: %d\n", cfg->resn);
+        }
+    }
+
+  /* Gain control */
+
+  switch (cfg->gain)
+    {
+      case NRF53_ADC_GAIN_1_6:
+        {
+          regval |= SAADC_CONFIG_GAIN_1P6;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_1_5:
+        {
+          regval |= SAADC_CONFIG_GAIN_1P5;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_1_4:
+        {
+          regval |= SAADC_CONFIG_GAIN_1P4;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_1_3:
+        {
+          regval |= SAADC_CONFIG_GAIN_1P3;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_1_2:
+        {
+          regval |= SAADC_CONFIG_GAIN_1P2;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_1:
+        {
+          regval |= SAADC_CONFIG_GAIN_1;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_2:
+        {
+          regval |= SAADC_CONFIG_GAIN_2;
+          break;
+        }
+
+      case NRF53_ADC_GAIN_4:
+        {
+          regval |= SAADC_CONFIG_GAIN_4;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->gain: %d\n", cfg->gain);
+        }
+    }
+
+  /* Reference control */
+
+  switch (cfg->refsel)
+    {
+      case NRF53_ADC_REFSEL_INTERNAL:
+        {
+          regval |= SAADC_CONFIG_REFSEL_INTERNAL;
+          break;
+        }
+
+      case NRF53_ADC_REFSEL_VDD_4:
+        {
+          regval |= SAADC_CONFIG_REFSEL_VDD1P4;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->refsel: %d\n", cfg->refsel);
+        }
+    }
+
+  /* Acquisition time */
+
+  switch (cfg->tacq)
+    {
+      case NRF53_ADC_TACQ_3US:
+        {
+          regval |= SAADC_CONFIG_TACQ_3US;
+          break;
+        }
+
+      case NRF53_ADC_TACQ_5US:
+        {
+          regval |= SAADC_CONFIG_TACQ_5US;
+          break;
+        }
+
+      case NRF53_ADC_TACQ_10US:
+        {
+          regval |= SAADC_CONFIG_TACQ_10US;
+          break;
+        }
+
+      case NRF53_ADC_TACQ_15US:
+        {
+          regval |= SAADC_CONFIG_TACQ_15US;
+          break;
+        }
+
+      case NRF53_ADC_TACQ_20US:
+        {
+          regval |= SAADC_CONFIG_TACQ_20US;
+          break;
+        }
+
+      case NRF53_ADC_TACQ_40US:
+        {
+          regval |= SAADC_CONFIG_TACQ_40US;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->tacq: %d\n", cfg->tacq);
+        }
+    }
+
+  /* Singe-ended or differential mode */
+
+  switch (cfg->mode)
+    {
+      case NRF53_ADC_MODE_SE:
+        {
+          regval |= SAADC_CONFIG_MODE_SE;
+          break;
+        }
+
+      case NRF53_ADC_MODE_DIFF:
+        {
+          regval |= SAADC_CONFIG_MODE_DIFF;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->mode: %d\n", cfg->mode);
+        }
+    }
+
+  /* Burst mode */
+
+  switch (cfg->burst)
+    {
+      case NRF53_ADC_BURST_DISABLE:
+        {
+          regval |= SAADC_CONFIG_BURS_DIS;
+          break;
+        }
+
+      case NRF53_ADC_BURST_ENABLE:
+        {
+          regval |= SAADC_CONFIG_BURS_EN;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid cfg->burst: %d\n", cfg->burst);
+        }
+    }
+
+  return regval;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_chanpsel
+ ****************************************************************************/
+
+static uint32_t nrf53_adc_chanpsel(int psel)
+{
+  uint32_t regval = 0;
+
+  switch (psel)
+    {
+      case NRF53_ADC_IN_NC:
+        {
+          regval = SAADC_CHPSEL_NC;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN0:
+        {
+          regval = SAADC_CHPSEL_IN0;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN1:
+        {
+          regval = SAADC_CHPSEL_IN1;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN2:
+        {
+          regval = SAADC_CHPSEL_IN2;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN3:
+        {
+          regval = SAADC_CHPSEL_IN3;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN4:
+        {
+          regval = SAADC_CHPSEL_IN4;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN5:
+        {
+          regval = SAADC_CHPSEL_IN5;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN6:
+        {
+          regval = SAADC_CHPSEL_IN6;
+          break;
+        }
+
+      case NRF53_ADC_IN_IN7:
+        {
+          regval = SAADC_CHPSEL_IN7;
+          break;
+        }
+
+      case NRF53_ADC_IN_VDD:
+        {
+          regval = SAADC_CHPSEL_VDD;
+          break;
+        }
+
+      case NRF53_ADC_IN_VDDHDIV5:
+        {
+          regval = SAADC_CHPSEL_VDDHDIV5;
+          break;
+        }
+
+      default:
+        {
+          aerr("ERROR: invalid psel: %d\n", psel);
+        }
+    }
+
+  return regval;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_chancfg
+ *
+ * Description:
+ *   Configure ADC channel
+ *
+ ****************************************************************************/
+
+static int nrf53_adc_chancfg(struct nrf53_adc_s *priv, uint8_t chan,
+                             struct nrf53_adc_channel_s *cfg)
+{
+  uint32_t regval = 0;
+  int      ret    = OK;
+
+  DEBUGASSERT(priv);
+
+  /* Configure positive input */
+
+  regval = nrf53_adc_chanpsel(cfg->p_psel);
+  nrf53_adc_putreg(priv, NRF53_SAADC_CHPSELP_OFFSET(chan), regval);
+
+  /* Configure negative input */
+
+  regval = nrf53_adc_chanpsel(cfg->n_psel);
+  nrf53_adc_putreg(priv, NRF53_SAADC_CHPSELN_OFFSET(chan), regval);
+
+  /* Get channel configuration */
+
+  regval = nrf53_adc_ch_config(cfg);
+
+  /* Write channel configuration */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_CHCONFIG_OFFSET(chan), regval);
+
+#ifdef CONFIG_NRF53_SAADC_LIMITS
+  /* Configure limits */
+
+  regval = (cfg->limith < 16) | (cfg->limith << 0);
+  nrf53_adc_putreg(priv, NRF53_SAADC_CHLIMIT_OFFSET(chan), regval);
+#endif
+
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_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 nrf53_adc_bind(struct adc_dev_s *dev,
+                          const struct adc_callback_s *callback)
+{
+  struct nrf53_adc_s *priv = (struct nrf53_adc_s *) dev->ad_priv;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(priv);
+
+  priv->cb = callback;
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_reset
+ *
+ * Description:
+ *   Reset the ADC device.  Called early to initialize the hardware.
+ *   This is called, before adc_setup() and on error conditions.
+ *
+ ****************************************************************************/
+
+static void nrf53_adc_reset(struct adc_dev_s *dev)
+{
+  struct nrf53_adc_s *priv = (struct nrf53_adc_s *) dev->ad_priv;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(priv);
+
+  /* TODO */
+
+  UNUSED(priv);
+}
+
+/****************************************************************************
+ * Name: nrf53_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.
+ *
+ ****************************************************************************/
+
+static int nrf53_adc_setup(struct adc_dev_s *dev)
+{
+  struct nrf53_adc_s *priv = (struct nrf53_adc_s *) dev->ad_priv;
+  int                 i    = 0;
+  int                 ret  = OK;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(priv);
+
+  /* Disable ADC */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_ENABLE_OFFSET, 0);
+
+  /* Configure ADC */
+
+  ret = nrf53_adc_configure(priv);
+  if (ret < 0)
+    {
+      aerr("ERROR: nrf53_adc_configure failed: %d\n", ret);
+      goto errout;
+    }
+
+  /* Configure ADC channels */
+
+  for (i = 0; i < priv->chan_len; i += 1)
+    {
+      ret = nrf53_adc_chancfg(priv, i, &priv->channels[i]);
+      if (ret < 0)
+        {
+          aerr("ERROR: chancfg failed: %d %d\n", i, ret);
+          goto errout;
+        }
+    }
+
+  /* Enable ADC */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_ENABLE_OFFSET, 1);
+
+  /* Calibrate ADC */
+
+  ret = nrf53_adc_calibrate(priv);
+  if (ret < 0)
+    {
+      aerr("ERROR: adc calibration failed: %d\n", ret);
+      goto errout;
+    }
+
+  /* Attach the ADC interrupt */
+
+  ret = irq_attach(priv->irq, nrf53_adc_isr, dev);
+  if (ret < 0)
+    {
+      aerr("ERROR: irq_attach failed: %d\n", ret);
+      goto errout;
+    }
+
+  /* Enable the ADC interrupt */
+
+  up_enable_irq(priv->irq);
+
+errout:
+  return ret;
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_shutdown
+ *
+ * Description:
+ *   Disable the ADC.  This method is called when the ADC device is closed.
+ *   This method reverses the operation the setup method.
+ *
+ ****************************************************************************/
+
+static void nrf53_adc_shutdown(struct adc_dev_s *dev)
+{
+  struct nrf53_adc_s *priv = (struct nrf53_adc_s *) dev->ad_priv;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(priv);
+
+  /* Stop SAADC */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_TASKS_STOP_OFFSET, 1);
+
+  /* Wait for SAADC stopped */
+
+  while (nrf53_adc_getreg(priv, NRF53_SAADC_EVENTS_STOPPED_OFFSET) != 1);
+
+  /* Disable SAADC */
+
+  nrf53_adc_putreg(priv, NRF53_SAADC_ENABLE_OFFSET, 0);
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts.
+ *
+ ****************************************************************************/
+
+static void nrf53_adc_rxint(struct adc_dev_s *dev, bool enable)
+{
+  struct nrf53_adc_s *priv   = (struct nrf53_adc_s *) dev->ad_priv;
+  uint32_t            regval = 0;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(priv);
+
+  ainfo("RXINT enable: %d\n", enable ? 1 : 0);
+
+  regval = SAADC_INT_END;
+
+  if (enable)
+    {
+      nrf53_adc_putreg(priv, NRF53_SAADC_INTENSET_OFFSET, regval);
+    }
+  else
+    {
+      nrf53_adc_putreg(priv, NRF53_SAADC_INTENCLR_OFFSET, regval);
+    }
+}
+
+/****************************************************************************
+ * Name: nrf53_adc_ioctl
+ *
+ * Description:
+ *   All ioctl calls will be routed through this method.
+ *
+ ****************************************************************************/
+
+static int nrf53_adc_ioctl(struct adc_dev_s *dev, int cmd,
+                           unsigned long arg)
+{
+  struct nrf53_adc_s *priv = (struct nrf53_adc_s *) dev->ad_priv;
+  int ret                  = OK;
+
+  DEBUGASSERT(dev);
+  DEBUGASSERT(priv);
+
+  switch (cmd)
+    {
+      case ANIOC_TRIGGER:
+        {
+          /* Start ADC */
+
+          nrf53_adc_putreg(priv, NRF53_SAADC_TASKS_START_OFFSET, 1);
+
+          /* Trigger first sample */
+
+          nrf53_adc_putreg(priv, NRF53_SAADC_TASKS_SAMPLE_OFFSET, 1);
+        }
+        break;
+
+      case ANIOC_GET_NCHANNELS:
+        {
+          /* Return the number of configured channels */
+
+          ret = priv->chan_len;
+        }
+        break;
+
+      default:
+        {
+          aerr("ERROR: Unknown cmd: %d\n", cmd);
+          ret = -ENOTTY;
+        }
+        break;
+    }
+
+  return ret;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_adcinitialize
+ *
+ * Description:
+ *   Initialize the ADC. See nrf53_adc.c for more details.
+ *
+ * Input Parameters:
+ *   chanlist  - channels configuration
+ *   nchannels - number of channels
+ *
+ * Returned Value:
+ *   Valid ADC device structure reference on success; a NULL on failure
+ *
+ ****************************************************************************/
+
+struct adc_dev_s *nrf53_adcinitialize(
+    const struct nrf53_adc_channel_s *chan, int channels)
+{
+  struct adc_dev_s   *dev  = NULL;
+  struct nrf53_adc_s *priv = NULL;
+  int                 i    = 0;
+
+  DEBUGASSERT(chan != NULL);
+  DEBUGASSERT(channels <= CONFIG_NRF53_SAADC_CHANNELS);
+
+#ifdef CONFIG_NRF53_SAADC_TIMER
+  if (channels > 1)
+    {
+      aerr("ERORR: timer trigger works only for 1 channel!\n");
+      goto errout;
+    }
+#endif
+
+  /* Get device */
+
+  dev = &g_nrf53_adc;
+
+  /* Get private data */
+
+  priv = (struct nrf53_adc_s *) dev->ad_priv;
+
+  /* Copy channels configuration */
+
+  ainfo("channels: %d\n", channels);
+
+  for (i = 0; i < channels; i += 1)
+    {
+      memcpy(&priv->channels[i], &chan[i],
+             sizeof(struct nrf53_adc_channel_s));
+    }
+
+  priv->chan_len = channels;
+
+#ifdef CONFIG_NRF53_SAADC_TIMER
+errout:
+#endif
+  return dev;
+}
diff --git a/arch/arm/src/nrf53/nrf53_adc.h b/arch/arm/src/nrf53/nrf53_adc.h
new file mode 100644
index 0000000000..3e31efc1ae
--- /dev/null
+++ b/arch/arm/src/nrf53/nrf53_adc.h
@@ -0,0 +1,162 @@
+/****************************************************************************
+ * arch/arm/src/nrf53/nrf53_adc.h
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+#ifndef __ARCH_ARM_SRC_NRF53_NRF53_ADC_H
+#define __ARCH_ARM_SRC_NRF53_NRF53_ADC_H
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include "chip.h"
+
+#include <nuttx/analog/adc.h>
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Public Types
+ ****************************************************************************/
+
+/* ADC input */
+
+enum nrf53_adc_ain_e
+{
+  NRF53_ADC_IN_NC       = 0,   /* Not connected */
+  NRF53_ADC_IN_IN0      = 1,   /* Analog input 0 */
+  NRF53_ADC_IN_IN1      = 2,   /* Analog input 1 */
+  NRF53_ADC_IN_IN2      = 3,   /* Analog input 2 */
+  NRF53_ADC_IN_IN3      = 4,   /* Analog input 3 */
+  NRF53_ADC_IN_IN4      = 5,   /* Analog input 4 */
+  NRF53_ADC_IN_IN5      = 6,   /* Analog input 5 */
+  NRF53_ADC_IN_IN6      = 7,   /* Analog input 6 */
+  NRF53_ADC_IN_IN7      = 8,   /* Analog input 7 */
+  NRF53_ADC_IN_VDD      = 9,   /* VDD */
+  NRF53_ADC_IN_VDDHDIV5 = 10,  /* VDDH/5 */
+};
+
+/* Resistor control */
+
+enum nrf53_adc_res_e
+{
+  NRF53_ADC_RES_BYPASS   = 0,   /* Bypass resistor ladder */
+  NRF53_ADC_RES_PULLDOWN = 1,   /* Pull-down to GND */
+  NRF53_ADC_RES_PULLUP   = 2,   /* Pull-up to VDD */
+  NRF53_ADC_RES_VDD_2    = 3    /* Set input at VDD/2 */
+};
+
+/* Gain control */
+
+enum nrf53_adc_gain_e
+{
+  NRF53_ADC_GAIN_1_6 = 0,       /* 1/6 */
+  NRF53_ADC_GAIN_1_5 = 1,       /* 1/5 */
+  NRF53_ADC_GAIN_1_4 = 2,       /* 1/4 */
+  NRF53_ADC_GAIN_1_3 = 3,       /* 1/3 */
+  NRF53_ADC_GAIN_1_2 = 4,       /* 1/2 */
+  NRF53_ADC_GAIN_1   = 5,       /* 1 */
+  NRF53_ADC_GAIN_2   = 6,       /* 2 */
+  NRF53_ADC_GAIN_4   = 7        /* 4 */
+};
+
+/* Reference control */
+
+enum nrf53_adc_refsel_e
+{
+  NRF53_ADC_REFSEL_INTERNAL = 0, /* Internal reference (0.6V) */
+  NRF53_ADC_REFSEL_VDD_4    = 1  /* VDD/4 as reference */
+};
+
+/* Acquisition time control */
+
+enum nrf53_adc_tacq_e
+{
+  NRF53_ADC_TACQ_3US  = 0,      /* 3 us */
+  NRF53_ADC_TACQ_5US  = 1,      /* 5 us */
+  NRF53_ADC_TACQ_10US = 2,      /* 10 us */
+  NRF53_ADC_TACQ_15US = 3,      /* 15 us */
+  NRF53_ADC_TACQ_20US = 4,      /* 20 us */
+  NRF53_ADC_TACQ_40US = 5       /* 40 us */
+};
+
+/* ADC mode control */
+
+enum nrf53_adc_mode_e
+{
+  NRF53_ADC_MODE_SE   = 0,      /* Single-ended mode */
+  NRF53_ADC_MODE_DIFF = 1       /* Differentail mode */
+};
+
+/* ADC burst control */
+
+enum nrf53_adc_burst_e
+{
+  NRF53_ADC_BURST_DISABLE = 0,  /* Disable burst mode */
+  NRF53_ADC_BURST_ENABLE  = 1   /* Enable burst mode */
+};
+
+/* NRF53 ADC channel configuration */
+
+struct nrf53_adc_channel_s
+{
+  uint32_t p_psel;              /* P pin */
+  uint32_t n_psel;              /* N pin */
+#ifdef CONFIG_NRF53_SAADC_LIMITS
+  uint16_t limith;              /* High limit */
+  uint16_t limitl;              /* Low limit */
+#endif
+  uint8_t resp:2;               /* Positive chan resistor */
+  uint8_t resn:2;               /* Negative chan resistor */
+  uint8_t gain:3;               /* Gain control */
+  uint8_t refsel:1;             /* Reference control */
+  uint8_t tacq:3;               /* Acquisition time */
+  uint8_t mode:1;               /* Singe-ended or differential mode */
+  uint8_t burst:1;              /* Burst mode */
+  uint8_t _res:3;               /* Reserved */
+};
+
+/****************************************************************************
+ * Public Function Prototypes
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_adcinitialize
+ *
+ * Description:
+ *   Initialize the ADC. See nrf53_adc.c for more details.
+ *
+ * Input Parameters:
+ *   chanlist  - channels configuration
+ *   nchannels - number of channels
+ *
+ * Returned Value:
+ *   Valid ADC device structure reference on success; a NULL on failure
+ *
+ ****************************************************************************/
+
+struct adc_dev_s *nrf53_adcinitialize(
+    const struct nrf53_adc_channel_s *chan,
+    int channels);
+
+#endif  /* __ARCH_ARM_SRC_NRF53_NRF53_ADC_H */


[nuttx] 02/02: boards/nrf5340-dk: add ADC configuration

Posted by pk...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

pkarashchenko pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git

commit f48846676e6ca7271e8b8cdd5270e12bbe905ed0
Author: raiden00pl <ra...@railab.me>
AuthorDate: Mon Mar 13 13:24:34 2023 +0100

    boards/nrf5340-dk: add ADC configuration
---
 .../nrf53/nrf5340-dk/configs/adc_cpuapp/defconfig  |  52 ++++++
 boards/arm/nrf53/nrf5340-dk/include/board.h        |  14 ++
 boards/arm/nrf53/nrf5340-dk/src/Makefile           |   4 +
 boards/arm/nrf53/nrf5340-dk/src/nrf5340-dk.h       |  12 ++
 boards/arm/nrf53/nrf5340-dk/src/nrf53_adc.c        | 200 +++++++++++++++++++++
 boards/arm/nrf53/nrf5340-dk/src/nrf53_bringup.c    |  12 ++
 6 files changed, 294 insertions(+)

diff --git a/boards/arm/nrf53/nrf5340-dk/configs/adc_cpuapp/defconfig b/boards/arm/nrf53/nrf5340-dk/configs/adc_cpuapp/defconfig
new file mode 100644
index 0000000000..6c1d5a9f86
--- /dev/null
+++ b/boards/arm/nrf53/nrf5340-dk/configs/adc_cpuapp/defconfig
@@ -0,0 +1,52 @@
+#
+# This file is autogenerated: PLEASE DO NOT EDIT IT.
+#
+# You can use "make menuconfig" to make any modifications to the installed .config file.
+# You can then do "make savedefconfig" to generate a new defconfig file that includes your
+# modifications.
+#
+# CONFIG_NSH_DISABLE_IFCONFIG is not set
+# CONFIG_NSH_DISABLE_PS is not set
+# CONFIG_STANDARD_SERIAL is not set
+CONFIG_ADC=y
+CONFIG_ANALOG=y
+CONFIG_ARCH="arm"
+CONFIG_ARCH_BOARD="nrf5340-dk"
+CONFIG_ARCH_BOARD_NRF5340_DK=y
+CONFIG_ARCH_CHIP="nrf53"
+CONFIG_ARCH_CHIP_NRF5340=y
+CONFIG_ARCH_CHIP_NRF5340_CPUAPP=y
+CONFIG_ARCH_CHIP_NRF53=y
+CONFIG_ARCH_STACKDUMP=y
+CONFIG_ARCH_STDARG_H=y
+CONFIG_BOARD_LOOPSPERMSEC=5500
+CONFIG_BUILTIN=y
+CONFIG_EXAMPLES_ADC=y
+CONFIG_EXAMPLES_ADC_NSAMPLES=4
+CONFIG_EXAMPLES_ADC_SWTRIG=y
+CONFIG_EXPERIMENTAL=y
+CONFIG_FAT_LCNAMES=y
+CONFIG_FAT_LFN=y
+CONFIG_FS_FAT=y
+CONFIG_INIT_ENTRYPOINT="nsh_main"
+CONFIG_INTELHEX_BINARY=y
+CONFIG_MM_REGIONS=2
+CONFIG_NRF53_SAADC=y
+CONFIG_NRF53_UART0=y
+CONFIG_NSH_ARCHINIT=y
+CONFIG_NSH_BUILTIN_APPS=y
+CONFIG_NSH_FILEIOSIZE=512
+CONFIG_NSH_LINELEN=64
+CONFIG_NSH_READLINE=y
+CONFIG_PREALLOC_TIMERS=4
+CONFIG_RAM_SIZE=524288
+CONFIG_RAM_START=0x20000000
+CONFIG_RAW_BINARY=y
+CONFIG_RR_INTERVAL=200
+CONFIG_SCHED_WAITPID=y
+CONFIG_START_DAY=26
+CONFIG_START_MONTH=3
+CONFIG_SYMTAB_ORDEREDBYNAME=y
+CONFIG_SYSTEM_NSH=y
+CONFIG_TASK_NAME_SIZE=0
+CONFIG_UART0_SERIAL_CONSOLE=y
diff --git a/boards/arm/nrf53/nrf5340-dk/include/board.h b/boards/arm/nrf53/nrf5340-dk/include/board.h
index 35a82ab941..5ee9b31916 100644
--- a/boards/arm/nrf53/nrf5340-dk/include/board.h
+++ b/boards/arm/nrf53/nrf5340-dk/include/board.h
@@ -141,4 +141,18 @@
 #define NRF53_PWM0_CH2_PIN (GPIO_MCUSEL_APP | GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN(12))
 #define NRF53_PWM0_CH3_PIN (GPIO_MCUSEL_APP | GPIO_OUTPUT | GPIO_PORT1 | GPIO_PIN(13))
 
+/* ADC Pins *****************************************************************/
+
+/* ADC
+ *   ADC CH0 - P0.04 - AIN1
+ *   ADC CH1 - P0.05 - AIN2
+ *   ADC CH2 - P0.06 - AIN4
+ *   ADC CH3 - P0.07 - AIN5
+ */
+
+#define NRF53_ADC_CH0_PIN (GPIO_MCUSEL_APP | GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(4))
+#define NRF53_ADC_CH1_PIN (GPIO_MCUSEL_APP | GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(5))
+#define NRF53_ADC_CH2_PIN (GPIO_MCUSEL_APP | GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(6))
+#define NRF53_ADC_CH3_PIN (GPIO_MCUSEL_APP | GPIO_INPUT | GPIO_PORT0 | GPIO_PIN(7))
+
 #endif /* __BOARDS_ARM_NRF53_NRF5340_DK_INCLUDE_BOARD_H */
diff --git a/boards/arm/nrf53/nrf5340-dk/src/Makefile b/boards/arm/nrf53/nrf5340-dk/src/Makefile
index 396959a90b..9c5313b9b7 100644
--- a/boards/arm/nrf53/nrf5340-dk/src/Makefile
+++ b/boards/arm/nrf53/nrf5340-dk/src/Makefile
@@ -46,4 +46,8 @@ ifeq ($(CONFIG_PWM),y)
 CSRCS += nrf53_pwm.c
 endif
 
+ifeq ($(CONFIG_ADC),y)
+CSRCS += nrf53_adc.c
+endif
+
 include $(TOPDIR)/boards/Board.mk
diff --git a/boards/arm/nrf53/nrf5340-dk/src/nrf5340-dk.h b/boards/arm/nrf53/nrf5340-dk/src/nrf5340-dk.h
index 5e211e7f39..34ce71e3aa 100644
--- a/boards/arm/nrf53/nrf5340-dk/src/nrf5340-dk.h
+++ b/boards/arm/nrf53/nrf5340-dk/src/nrf5340-dk.h
@@ -106,5 +106,17 @@ int nrf53_timer_driver_setup(const char *devpath, int timer);
 int nrf53_pwm_setup(void);
 #endif
 
+/****************************************************************************
+ * Name: nrf53_adc_setup
+ *
+ * Description:
+ *   Initialize ADC driver.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_ADC
+int nrf53_adc_setup(void);
+#endif
+
 #endif /* __ASSEMBLY__ */
 #endif /* __BOARDS_ARM_NRF53_NRF5340_DK_SRC_NRF53_NRF5340_DK_H */
diff --git a/boards/arm/nrf53/nrf5340-dk/src/nrf53_adc.c b/boards/arm/nrf53/nrf5340-dk/src/nrf53_adc.c
new file mode 100644
index 0000000000..d8cfd6c4b4
--- /dev/null
+++ b/boards/arm/nrf53/nrf5340-dk/src/nrf53_adc.c
@@ -0,0 +1,200 @@
+/****************************************************************************
+ * boards/arm/nrf53/nrf5340-dk/src/nrf53_adc.c
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <stdint.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/analog/adc.h>
+#include <arch/board/board.h>
+
+#include "nrf53_gpio.h"
+#include "nrf53_adc.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+/* Only one channel supported if TIMER triger enabled */
+
+#ifdef CONFIG_NRF53_SAADC_TIMER
+#  define ADC_NCHANNELS (1)
+#else
+#  define ADC_NCHANNELS (4)
+#endif
+
+/****************************************************************************
+ * Private data
+ ****************************************************************************/
+
+/* ADC pins configuration */
+
+static uint32_t g_adc_pins[ADC_NCHANNELS] =
+{
+  NRF53_ADC_CH0_PIN,            /* AIN1 */
+#if (ADC_NCHANNELS == 4)
+  NRF53_ADC_CH1_PIN,            /* AIN2 */
+  NRF53_ADC_CH2_PIN,            /* AIN4 */
+  NRF53_ADC_CH3_PIN,            /* AIN5 */
+#endif
+};
+
+/* ADC channels configuration */
+
+static struct nrf53_adc_channel_s g_adc_chanlist[ADC_NCHANNELS] =
+{
+  /* Channel 0 */
+
+  {
+    .p_psel  = NRF53_ADC_IN_IN1,
+    .n_psel  = 0,
+#ifdef CONFIG_NRF53_SAADC_LIMITS
+    .limith = 0,
+    .limitl = 0,
+#endif
+    .resp   = NRF53_ADC_RES_BYPASS,
+    .resn   = NRF53_ADC_RES_BYPASS,
+    .gain   = NRF53_ADC_GAIN_1,
+    .refsel = NRF53_ADC_REFSEL_INTERNAL,
+    .tacq   = NRF53_ADC_TACQ_40US,
+    .mode   = NRF53_ADC_MODE_SE,
+    .burst  = NRF53_ADC_BURST_DISABLE,
+  },
+
+#if (ADC_NCHANNELS == 4)
+  /* Channel 1 */
+
+  {
+    .p_psel  = NRF53_ADC_IN_IN2,
+    .n_psel  = 0,
+#ifdef CONFIG_NRF53_SAADC_LIMITS
+    .limith = 0,
+    .limitl = 0,
+#endif
+    .resp   = NRF53_ADC_RES_BYPASS,
+    .resn   = NRF53_ADC_RES_BYPASS,
+    .gain   = NRF53_ADC_GAIN_1,
+    .refsel = NRF53_ADC_REFSEL_INTERNAL,
+    .tacq   = NRF53_ADC_TACQ_40US,
+    .mode   = NRF53_ADC_MODE_SE,
+    .burst  = NRF53_ADC_BURST_DISABLE,
+  },
+
+  /* Channel 2 */
+
+  {
+    .p_psel  = NRF53_ADC_IN_IN4,
+    .n_psel  = 0,
+#ifdef CONFIG_NRF53_SAADC_LIMITS
+    .limith = 0,
+    .limitl = 0,
+#endif
+    .resp   = NRF53_ADC_RES_BYPASS,
+    .resn   = NRF53_ADC_RES_BYPASS,
+    .gain   = NRF53_ADC_GAIN_1,
+    .refsel = NRF53_ADC_REFSEL_INTERNAL,
+    .tacq   = NRF53_ADC_TACQ_40US,
+    .mode   = NRF53_ADC_MODE_SE,
+    .burst  = NRF53_ADC_BURST_DISABLE,
+  },
+
+  /* Channel 3 */
+
+  {
+    .p_psel  = NRF53_ADC_IN_IN5,
+    .n_psel  = 0,
+#ifdef CONFIG_NRF53_SAADC_LIMITS
+    .limith = 0,
+    .limitl = 0,
+#endif
+    .resp   = NRF53_ADC_RES_BYPASS,
+    .resn   = NRF53_ADC_RES_BYPASS,
+    .gain   = NRF53_ADC_GAIN_1,
+    .refsel = NRF53_ADC_REFSEL_INTERNAL,
+    .tacq   = NRF53_ADC_TACQ_40US,
+    .mode   = NRF53_ADC_MODE_SE,
+    .burst  = NRF53_ADC_BURST_DISABLE,
+  }
+#endif
+};
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: nrf53_adc_setup
+ *
+ * Description:
+ *   Initialize ADC and register the ADC device.
+ *
+ ****************************************************************************/
+
+int nrf53_adc_setup(void)
+{
+  static bool       initialized = false;
+  struct adc_dev_s *adc         = NULL;
+  int               ret         = OK;
+  int               i           = 0;
+
+  /* Have we already initialized? */
+
+  if (!initialized)
+    {
+      /* Configure ADC pins */
+
+      for (i = 0; i < ADC_NCHANNELS; i += 1)
+        {
+          nrf53_gpio_config(g_adc_pins[i]);
+        }
+
+      /* Call nrf53_adcinitialize() to get an instance of the ADC interface */
+
+      adc = nrf53_adcinitialize(g_adc_chanlist, ADC_NCHANNELS);
+      if (!adc)
+        {
+          aerr("ERROR: Failed to get the NRF53 ADC lower half\n");
+          ret = -ENODEV;
+          goto errout;
+        }
+
+      /* Register the ADC driver at "/dev/adc0" */
+
+      ret = adc_register("/dev/adc0", adc);
+      if (ret < 0)
+        {
+          aerr("ERROR: adc_register failed: %d\n", ret);
+          goto errout;
+        }
+
+      /* Now we are initialized */
+
+      initialized = true;
+    }
+
+errout:
+  return ret;
+}
diff --git a/boards/arm/nrf53/nrf5340-dk/src/nrf53_bringup.c b/boards/arm/nrf53/nrf5340-dk/src/nrf53_bringup.c
index d5ea34733f..3523706b0a 100644
--- a/boards/arm/nrf53/nrf5340-dk/src/nrf53_bringup.c
+++ b/boards/arm/nrf53/nrf5340-dk/src/nrf53_bringup.c
@@ -111,6 +111,18 @@ int nrf53_bringup(void)
     }
 #endif
 
+#ifdef CONFIG_ADC
+  /* Configure ADC driver */
+
+  ret = nrf53_adc_setup();
+  if (ret < 0)
+    {
+      syslog(LOG_ERR,
+             "ERROR: Failed to initialize ADC driver: %d\n",
+             ret);
+    }
+#endif
+
 #ifdef CONFIG_NRF53_SOFTDEVICE_CONTROLLER
   ret = nrf53_sdc_initialize();