Add ESP32-S3 ADC driver

This commit is contained in:
nuttxs 2024-05-06 10:41:12 +08:00 committed by Xiang Xiao
parent 9d6e2b97fb
commit 8d3d93e001
11 changed files with 1505 additions and 1 deletions

View File

@ -150,7 +150,7 @@ The following list indicates the state of peripherals' support in NuttX:
========== ======= =====
Peripheral Support NOTES
========== ======= =====
ADC No
ADC YES
AES YES
Bluetooth No
CAMERA No

View File

@ -288,6 +288,12 @@ menu "ESP32-S3 Peripheral Selection"
source "arch/xtensa/src/common/espressif/Kconfig"
config ESP32S3_ADC
bool "ADC"
default n
select ANALOG
select ADC
config ESP32S3_UART
bool
default n
@ -1285,6 +1291,73 @@ endif # ESP32S3_UART2
endmenu # UART Configuration
menu "ADC Configuration"
depends on ESP32S3_ADC
if ESP32S3_ADC
choice ESP32S3_ADC_VOL_RANGES
prompt "ADC voltage ranges"
default ESP32S3_ADC_VOL_3100
config ESP32S3_ADC_VOL_950
bool "0~950mV"
config ESP32S3_ADC_VOL_1250
bool "0~1250mV"
config ESP32S3_ADC_VOL_1750
bool "0~1750mV"
config ESP32S3_ADC_VOL_3100
bool "0~3100mV"
endchoice
config ESP32S3_ADC1_CHANNEL0
bool "ADC1 channel 0"
default n
config ESP32S3_ADC1_CHANNEL1
bool "ADC1 channel 1"
default n
config ESP32S3_ADC1_CHANNEL2
bool "ADC1 channel 2"
default n
config ESP32S3_ADC1_CHANNEL3
bool "ADC1 channel 3"
default n
config ESP32S3_ADC1_CHANNEL4
bool "ADC1 channel 4"
default n
config ESP32S3_ADC1_CHANNEL5
bool "ADC1 channel 5"
default n
config ESP32S3_ADC1_CHANNEL6
bool "ADC1 channel 6"
default n
config ESP32S3_ADC1_CHANNEL7
bool "ADC1 channel 7"
default n
config ESP32S3_ADC1_CHANNEL8
bool "ADC1 channel 8"
default n
config ESP32S3_ADC1_CHANNEL9
bool "ADC1 channel 9"
default n
endif # ESP32S3_ADC
endmenu # ADC Configuration
menu "I2C Configuration"
depends on ESP32S3_I2C

View File

@ -104,6 +104,10 @@ ifeq ($(CONFIG_ESP32S3_RT_TIMER),y)
CHIP_CSRCS += esp32s3_rt_timer.c
endif
ifeq ($(CONFIG_ESP32S3_ADC),y)
CHIP_CSRCS += esp32s3_adc.c
endif
ifeq ($(CONFIG_ESP32S3_I2C),y)
CHIP_CSRCS += esp32s3_i2c.c
endif

View File

@ -0,0 +1,944 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_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 <inttypes.h>
#include <stdint.h>
#include <sys/param.h>
#include <assert.h>
#include <debug.h>
#include <nuttx/mutex.h>
#include "esp32s3_gpio.h"
#include "esp32s3_dma.h"
#include "esp32s3_irq.h"
#include "esp32s3_adc.h"
#include "xtensa.h"
#include "hardware/esp32s3_system.h"
#include "hardware/esp32s3_efuse.h"
#include "hardware/esp32s3_sens.h"
#include "hardware/esp32s3_gpio_sigmap.h"
#include "hardware/regi2c_ctrl.h"
#include "hardware/regi2c_saradc.h"
#include "hardware/esp32s3_rtc_io.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/* ADC calibration max count */
#define ADC_CAL_CNT_MAX (32)
/* ADC calibration max value */
#define ADC_CAL_VAL_MAX (4096 - 1)
/* ADC calibration sampling channel */
#define ADC_CAL_CHANNEL (0xf)
/* ADC max value mask */
#define ADC_VAL_MASK (0xfff)
#define ADC_CAL_BASE_REG EFUSE_RD_SYS_PART1_DATA0_REG
#define ADC_CAL_VER_OFF (128)
#define ADC_CAL_VER_LEN (2)
#define ADC_CAL_DATA_COMP (1550)
#define ADC_CAL_VOL_LEN (8)
/* ADC input voltage attenuation, this affects measuring range */
#define ADC_ATTEN_DB_0 (0) /* Vmax = 950 mV */
#define ADC_ATTEN_DB_2_5 (1) /* Vmax = 1250 mV */
#define ADC_ATTEN_DB_6 (2) /* Vmax = 1750 mV */
#define ADC_ATTEN_DB_12 (3) /* Vmax = 3100 mV */
/* ADC attenuation */
#if defined(CONFIG_ESP32S3_ADC_VOL_950)
# define ADC_ATTEN_DEF ADC_ATTEN_DB_0
# define ADC_CAL_DATA_LEN (8)
# define ADC_CAL_DATA_OFF (149)
# define ADC_CAL_VOL_OFF (201)
# define ADC_CAL_VOL_DEF (488)
#elif defined(CONFIG_ESP32S3_ADC_VOL_1250)
# define ADC_ATTEN_DEF ADC_ATTEN_DB_2_5
# define ADC_CAL_DATA_LEN (6)
# define ADC_CAL_DATA_OFF (157)
# define ADC_CAL_VOL_OFF (209)
# define ADC_CAL_VOL_DEF (641)
#elif defined(CONFIG_ESP32S3_ADC_VOL_1750)
# define ADC_ATTEN_DEF ADC_ATTEN_DB_6
# define ADC_CAL_DATA_LEN (6)
# define ADC_CAL_DATA_OFF (163)
# define ADC_CAL_VOL_OFF (217)
# define ADC_CAL_VOL_DEF (892)
#elif defined(CONFIG_ESP32S3_ADC_VOL_3100)
# define ADC_ATTEN_DEF ADC_ATTEN_DB_12
# define ADC_CAL_DATA_LEN (6)
# define ADC_CAL_DATA_OFF (169)
# define ADC_CAL_VOL_OFF (225)
# define ADC_CAL_VOL_DEF (1592)
#endif
#define setbits(bs, a) modifyreg32(a, 0, bs)
#define resetbits(bs, a) modifyreg32(a, bs, 0)
/****************************************************************************
* Private Types
****************************************************************************/
/* ADC Private Data */
struct adc_chan_s
{
uint32_t ref; /* Reference count */
const uint8_t channel; /* Channel number */
const uint8_t pin; /* GPIO pin number */
const struct adc_callback_s *cb; /* Upper driver callback */
};
/****************************************************************************
* Private Function Prototypes
****************************************************************************/
static int adc_bind(struct adc_dev_s *dev,
const struct adc_callback_s *callback);
static void adc_reset(struct adc_dev_s *dev);
static int adc_setup(struct adc_dev_s *dev);
static void adc_shutdown(struct adc_dev_s *dev);
static void adc_rxint(struct adc_dev_s *dev, bool enable);
static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg);
/****************************************************************************
* Private Data
****************************************************************************/
/* ADC interface operations */
static const struct adc_ops_s g_adcops =
{
.ao_bind = adc_bind,
.ao_reset = adc_reset,
.ao_setup = adc_setup,
.ao_shutdown = adc_shutdown,
.ao_rxint = adc_rxint,
.ao_ioctl = adc_ioctl,
};
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL0
static struct adc_chan_s g_adc1_chan0 =
{
.channel = 0,
.pin = 1
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL1
static struct adc_chan_s g_adc1_chan1 =
{
.channel = 1,
.pin = 2
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL2
static struct adc_chan_s g_adc1_chan2 =
{
.channel = 2,
.pin = 3
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL3
static struct adc_chan_s g_adc1_chan3 =
{
.channel = 3,
.pin = 4
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL4
static struct adc_chan_s g_adc1_chan4 =
{
.channel = 4,
.pin = 5
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL5
static struct adc_chan_s g_adc1_chan5 =
{
.channel = 5,
.pin = 6
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL6
static struct adc_chan_s g_adc1_chan6 =
{
.channel = 6,
.pin = 7
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL7
static struct adc_chan_s g_adc1_chan7 =
{
.channel = 7,
.pin = 8
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL8
static struct adc_chan_s g_adc1_chan8 =
{
.channel = 8,
.pin = 9
};
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL9
static struct adc_chan_s g_adc1_chan9 =
{
.channel = 9,
.pin = 10
};
#endif
/* ADC calibration mark */
static bool g_adc_switch;
/* ADC calibration mark */
static bool g_calibrated;
/* ADC calibration digital parameter */
static uint16_t g_cal_digit;
/* ADC clock reference */
static uint32_t g_clk_ref;
static mutex_t g_lock = NXMUTEX_INITIALIZER;
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: read_efuse
*
* Description:
* Read Efuse data.
*
* Input Parameters:
* addr - register address
* b_off - bit offset
* b_size - bit size
*
* Returned Value:
* Efuse data.
*
****************************************************************************/
static uint32_t read_efuse(uint32_t addr, uint32_t b_off, uint32_t b_size)
{
uint32_t data;
uint32_t regval;
uint32_t shift = 32 - b_size;
uint32_t mask = UINT32_MAX >> shift;
uint32_t res = b_off % 32;
uint32_t regaddr = addr + (b_off / 32 * 4);
regval = getreg32(regaddr);
data = regval >> res;
if (res <= shift)
{
data &= mask;
}
else
{
shift = 32 - res;
regval = getreg32(regaddr + 4);
data |= (regval & (mask >> shift)) << shift;
}
return data;
}
/****************************************************************************
* Name: adc_enable_clk
*
* Description:
* Enable ADC clock.
*
* Input Parameters:
* NOne
*
* Returned Value:
* None.
*
****************************************************************************/
static void adc_enable_clk(void)
{
irqstate_t flags;
flags = enter_critical_section();
if (!g_clk_ref)
{
setbits(SENS_SARADC_CLK_EN, SENS_SAR_PERI_CLK_GATE_CONF_REG);
}
g_clk_ref++;
leave_critical_section(flags);
}
/****************************************************************************
* Name: adc_disable_clk
*
* Description:
* Disable ADC clock.
*
* Input Parameters:
* NOne
*
* Returned Value:
* None.
*
****************************************************************************/
static void adc_disable_clk(void)
{
irqstate_t flags;
flags = enter_critical_section();
g_clk_ref--;
if (!g_clk_ref)
{
resetbits(SENS_SARADC_CLK_EN, SENS_SAR_PERI_CLK_GATE_CONF_REG);
}
leave_critical_section(flags);
}
/****************************************************************************
* Name: adc_set_calibration
*
* Description:
* Set calibration parameter to ADC hardware.
*
* Input Parameters:
* data - Calibration parameter
*
* Returned Value:
* None.
*
****************************************************************************/
static void adc_set_calibration(uint16_t data)
{
uint8_t h_data = data >> 8;
uint8_t l_data = data & 0xff;
esp_rom_regi2c_write_mask(I2C_ADC, I2C_ADC_HOSTID,
I2C_ADC1_INITVAL_H,
I2C_ADC1_INITVAL_H_MSB,
I2C_ADC1_INITVAL_H_LSB, h_data);
esp_rom_regi2c_write_mask(I2C_ADC, I2C_ADC_HOSTID,
I2C_ADC1_INITVAL_L,
I2C_ADC1_INITVAL_L_MSB,
I2C_ADC1_INITVAL_L_LSB, l_data);
}
/****************************************************************************
* Name: adc_samplecfg
*
* Description:
* Set ADC sampling with given channel.
*
* Input Parameters:
* channel - Sampling channel number
*
* Returned Value:
* None.
*
****************************************************************************/
static inline void adc_samplecfg(int channel)
{
uint32_t regval;
/* set (Frequency division) (inversion adc) */
regval = getreg32(SENS_SAR_READER1_CTRL_REG);
regval &= ~(SENS_SAR1_CLK_DIV_M);
regval |= (1 << SENS_SAR1_CLK_DIV_S);
putreg32(regval, SENS_SAR_READER1_CTRL_REG);
/* Enable ADC1, its sampling attenuation */
regval = getreg32(SENS_SAR_ATTEN1_REG);
regval &= ~(ADC_ATTEN_DEF << (channel * 2));
regval |= ADC_ATTEN_DEF << (channel * 2);
putreg32(regval, SENS_SAR_ATTEN1_REG);
/* Enable ADC1, its sampling channel and attenuation */
regval = getreg32(SENS_SAR_MEAS1_CTRL2_REG);
regval &= ~(SENS_SAR1_EN_PAD_M | SENS_SAR1_EN_PAD_FORCE_M |
SENS_MEAS1_START_FORCE_M);
regval |= ((1 << channel) << SENS_SAR1_EN_PAD_S) |
SENS_SAR1_EN_PAD_FORCE | SENS_MEAS1_START_FORCE;
putreg32(regval, SENS_SAR_MEAS1_CTRL2_REG);
}
/****************************************************************************
* Name: adc_read
*
* Description:
* Start ADC sampling and read ADC value.
*
* Input Parameters:
* None
*
* Returned Value:
* Read ADC value.
*
****************************************************************************/
static uint16_t adc_read(void)
{
uint16_t adc;
uint32_t regval;
/* Trigger ADC1 sampling */
setbits(SENS_MEAS1_START_SAR, SENS_SAR_MEAS1_CTRL2_REG);
/* Wait until ADC1 sampling is done */
do
{
regval = getreg32(SENS_SAR_MEAS1_CTRL2_REG);
}
while (!(regval & SENS_MEAS1_DONE_SAR_M));
regval = getreg32(SENS_SAR_MEAS1_CTRL2_REG) & ADC_VAL_MASK;
ainfo("SENS_MEAS1_DATA_SAR adc_read: %d\n", regval);
/* Disable ADC sampling */
resetbits(SENS_MEAS1_START_SAR, SENS_SAR_MEAS1_CTRL2_REG);
return regval;
}
/****************************************************************************
* Name: adc_calibrate
*
* Description:
* ADC calibration.
*
* Input Parameters:
* None
*
* Returned Value:
* None.
*
****************************************************************************/
static void adc_calibrate(void)
{
uint16_t cali_val;
uint16_t adc;
uint16_t adc_max = 0;
uint16_t adc_min = UINT16_MAX;
uint32_t adc_sum = 0;
uint32_t regval;
regval = read_efuse(ADC_CAL_BASE_REG, ADC_CAL_VER_OFF, ADC_CAL_VER_LEN);
if (regval == 1)
{
ainfo("Calibrate based on efuse data\n");
regval = read_efuse(ADC_CAL_BASE_REG, ADC_CAL_DATA_OFF,
ADC_CAL_DATA_LEN);
cali_val = regval + ADC_CAL_DATA_COMP;
}
else
{
ainfo("Calibrate based on GND voltage\n");
/* Enable Vdef */
esp_rom_regi2c_write_mask(I2C_ADC, I2C_ADC_HOSTID,
I2C_ADC1_DEF, I2C_ADC1_DEF_MSB,
I2C_ADC1_DEF_LSB, 1);
/* Start sampling */
adc_samplecfg(ADC_CAL_CHANNEL);
/* Enable internal connect GND (for calibration). */
esp_rom_regi2c_write_mask(I2C_ADC, I2C_ADC_HOSTID,
I2C_ADC1_ENCAL_GND, I2C_ADC1_ENCAL_GND_MSB,
I2C_ADC1_ENCAL_GND_LSB, 1);
for (int i = 1; i < ADC_CAL_CNT_MAX ; i++)
{
adc_set_calibration(0);
adc = adc_read();
adc_sum += adc;
adc_max = MAX(adc, adc_max);
adc_min = MIN(adc, adc_min);
}
cali_val = (adc_sum - adc_max - adc_min) / (ADC_CAL_CNT_MAX - 2);
/* Disable internal connect GND (for calibration). */
esp_rom_regi2c_write_mask(I2C_ADC, I2C_ADC_HOSTID,
I2C_ADC1_ENCAL_GND,
I2C_ADC1_ENCAL_GND_MSB,
I2C_ADC1_ENCAL_GND_LSB, 0);
}
ainfo("calibration value: %" PRIu16 "\n", cali_val);
/* Set final calibration parameters */
adc_set_calibration(cali_val);
/* Set calibration digital parameters */
regval = read_efuse(ADC_CAL_BASE_REG, ADC_CAL_VOL_OFF, ADC_CAL_VOL_LEN);
if (regval & BIT(ADC_CAL_VOL_LEN - 1))
{
g_cal_digit = 2000 - (regval & ~(BIT(ADC_CAL_VOL_LEN - 1)));
}
else
{
g_cal_digit = 2000 + regval;
}
ainfo("calibration read_efuse g_cal_digit: %" PRIu16 "\n", g_cal_digit);
}
/****************************************************************************
* Name: adc_read_work
*
* Description:
* Read ADC value and pass it to up.
*
* Input Parameters:
* dev - ADC device pointer
*
* Returned Value:
* None.
*
****************************************************************************/
static void adc_read_work(struct adc_dev_s *dev)
{
int ret;
uint32_t value;
int32_t adc;
struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv;
ret = nxmutex_lock(&g_lock);
if (ret < 0)
{
aerr("Failed to lock ret=%d\n", ret);
return;
}
adc_samplecfg(priv->channel);
value = adc_read();
adc = (int32_t)(value * (UINT16_MAX * ADC_CAL_VOL_DEF / g_cal_digit) /
UINT16_MAX);
priv->cb->au_receive(dev, priv->channel, adc);
ainfo("channel: %" PRIu8 ", voltage: %" PRIu32 " mV\n", priv->channel,
adc);
nxmutex_unlock(&g_lock);
}
/****************************************************************************
* Name: 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 adc_bind(struct adc_dev_s *dev,
const struct adc_callback_s *callback)
{
struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv;
DEBUGASSERT(priv != NULL);
ainfo("channel: %" PRIu8 "\n", priv->channel);
priv->cb = callback;
return OK;
}
/****************************************************************************
* 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(struct adc_dev_s *dev)
{
irqstate_t flags;
struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv;
ainfo("channel: %" PRIu8 "\n", priv->channel);
flags = enter_critical_section();
/* Do nothing if ADC instance is currently in use */
if (priv->ref > 0)
{
goto out;
}
/* Reset ADC hardware */
adc_enable_clk();
adc_disable_clk();
out:
leave_critical_section(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.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static int adc_setup(struct adc_dev_s *dev)
{
int ret;
uint32_t regval;
struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv;
ainfo("channel: %" PRIu8 "\n", priv->channel);
/* Do nothing when the ADC device is already set up */
if (priv->ref > 0)
{
priv->ref++;
return OK;
}
/* Enable ADC clock */
adc_enable_clk();
/* Disable GPIO input and output */
ainfo("pin: %" PRIu8 "\n", priv->pin);
esp32s3_configgpio(priv->pin, INPUT | FUNCTION_1);
/* Start calibration only once */
ret = nxmutex_lock(&g_lock);
if (ret < 0)
{
adc_disable_clk();
aerr("Failed to lock ret=%d\n", ret);
return ret;
}
if (!g_calibrated)
{
adc_calibrate();
g_calibrated = true;
}
nxmutex_unlock(&g_lock);
/* The ADC device is ready */
priv->ref++;
return OK;
}
/****************************************************************************
* Name: adc_rxint
*
* Description:
* Call to enable or disable RX interrupts.
*
* Input Parameters:
*
* Returned Value:
*
****************************************************************************/
static void adc_rxint(struct adc_dev_s *dev, bool enable)
{
}
/****************************************************************************
* Name: adc_ioctl
*
* Description:
* All ioctl calls will be routed through this method.
*
* Input Parameters:
* dev - pointer to device structure used by the driver
* cmd - command
* arg - arguments passed with command
*
* Returned Value:
*
****************************************************************************/
static int adc_ioctl(struct adc_dev_s *dev, int cmd, unsigned long arg)
{
int ret;
struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv;
ainfo("channel: %" PRIu8 " cmd=%d\n", priv->channel, cmd);
switch (cmd)
{
case ANIOC_TRIGGER:
{
/* Start sampling and read ADC value here */
adc_read_work(dev);
ret = OK;
}
break;
case ANIOC_GET_NCHANNELS:
{
/* Return the number of configured channels */
ret = priv->channel;
}
break;
default:
{
aerr("ERROR: Unknown cmd: %d\n", cmd);
ret = -ENOTTY;
}
break;
}
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(struct adc_dev_s *dev)
{
struct adc_chan_s *priv = (struct adc_chan_s *)dev->ad_priv;
ainfo("channel: %" PRIu8 "\n", priv->channel);
/* Decrement count only when ADC device is in use */
if (priv->ref > 0)
{
priv->ref--;
/* Shutdown the ADC device only when not in use */
if (!priv->ref)
{
adc_rxint(dev, false);
/* Disable ADC clock */
adc_disable_clk();
}
}
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: esp32s3_adc_init
*
* Description:
* Initialize the ADC.
*
* Input Parameters:
* adc_index - ADC channel number
* dev - pointer to device structure used by the driver
*
* Returned Value:
*
****************************************************************************/
void esp32s3_adc_init(int adc_index, struct adc_dev_s *dev)
{
ainfo("ADC index: %" PRIu8 "\n", adc_index);
dev->ad_ops = &g_adcops;
switch (adc_index)
{
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL0)
case 0:
dev->ad_priv = &g_adc1_chan0;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL1)
case 1:
dev->ad_priv = &g_adc1_chan1;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL2)
case 2:
dev->ad_priv = &g_adc1_chan2;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL3)
case 3:
dev->ad_priv = &g_adc1_chan3;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL4)
case 4:
dev->ad_priv = &g_adc1_chan4;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL5)
case 5:
dev->ad_priv = &g_adc1_chan5;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL6)
case 6:
dev->ad_priv = &g_adc1_chan6;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL7)
case 7:
dev->ad_priv = &g_adc1_chan7;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL8)
case 8:
dev->ad_priv = &g_adc1_chan8;
break;
#endif
#if defined(CONFIG_ESP32S3_ADC1_CHANNEL9)
case 9:
dev->ad_priv = &g_adc1_chan9;
break;
#endif
default:
{
aerr("ERROR: No ADC interface defined\n");
}
}
}

View File

@ -0,0 +1,93 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/esp32s3_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_XTENSA_SRC_ESP32S3_ESP32S3_ADC_H
#define __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_ADC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <nuttx/arch.h>
#include <nuttx/analog/adc.h>
#include <nuttx/analog/ioctl.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Types
****************************************************************************/
#ifndef __ASSEMBLY__
#ifdef CONFIG_ESP32S3_ADC
# define ESP32S3_ADC1 1
# define ESP32S3_ADC1_CHANNEL0 0
# define ESP32S3_ADC1_CHANNEL1 1
# define ESP32S3_ADC1_CHANNEL2 2
# define ESP32S3_ADC1_CHANNEL3 3
# define ESP32S3_ADC1_CHANNEL4 4
# define ESP32S3_ADC1_CHANNEL5 5
# define ESP32S3_ADC1_CHANNEL6 6
# define ESP32S3_ADC1_CHANNEL7 7
# define ESP32S3_ADC1_CHANNEL8 8
# define ESP32S3_ADC1_CHANNEL9 9
#endif
/****************************************************************************
* Public Data
****************************************************************************/
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Name: esp32s3_adc_init
*
* Description:
* Initialize the ADC.
*
* Input Parameters:
* channel - ADC channel number
*
* Returned Value:
* ADC device structure reference on success; a NULL on failure
*
****************************************************************************/
void esp32s3_adc_init(int adc_index, struct adc_dev_s *dev);
#ifdef __cplusplus
}
#endif
#undef EXTERN
#endif /* __ASSEMBLY__ */
#endif /* __ARCH_XTENSA_SRC_ESP32S3_ESP32S3_ADC_H */

View File

@ -0,0 +1,52 @@
/****************************************************************************
* arch/xtensa/src/esp32s3/hardware/regi2c_saradc.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_XTENSA_SRC_ESP32S3_HARDWARE_REGI2C_SARADC_H
#define __ARCH_XTENSA_SRC_ESP32S3_HARDWARE_REGI2C_SARADC_H
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/**
* Register definitions for analog to calibrate initial code for getting a
* more precise voltage of SAR ADC.
*/
#define I2C_ADC (0x69)
#define I2C_ADC_HOSTID (1)
#define I2C_ADC1_ENCAL_GND (0x7)
#define I2C_ADC1_ENCAL_GND_MSB (0x5)
#define I2C_ADC1_ENCAL_GND_LSB (0x5)
#define I2C_ADC1_INITVAL_L (0x0)
#define I2C_ADC1_INITVAL_L_MSB (0x7)
#define I2C_ADC1_INITVAL_L_LSB (0x0)
#define I2C_ADC1_INITVAL_H (0x1)
#define I2C_ADC1_INITVAL_H_MSB (0x3)
#define I2C_ADC1_INITVAL_H_LSB (0x0)
#define I2C_ADC1_DEF (0x2)
#define I2C_ADC1_DEF_MSB (0x6)
#define I2C_ADC1_DEF_LSB (0x4)
#endif /* __ARCH_XTENSA_SRC_ESP32S3_HARDWARE_REGI2C_SARADC_H */

View File

@ -0,0 +1,74 @@
/****************************************************************************
* boards/xtensa/esp32s3/common/include/esp32s3_board_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 __BOARDS_XTENSA_ESP32S3_COMMON_INCLUDE_ESP32S3_BOARD_ADC_H
#define __BOARDS_XTENSA_ESP32S3_COMMON_INCLUDE_ESP32S3_BOARD_ADC_H
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#ifndef __ASSEMBLY__
#undef EXTERN
#if defined(__cplusplus)
#define EXTERN extern "C"
extern "C"
{
#else
#define EXTERN extern
#endif
/****************************************************************************
* Public Function Prototypes
****************************************************************************/
/****************************************************************************
* Name: board_adc_init
*
* Description:
* Configure the ADC driver.
*
* Input Parameters:
* None.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
* to indicate the nature of any failure.
*
****************************************************************************/
#ifdef CONFIG_ESP32S3_ADC
int board_adc_init(void);
#endif
#undef EXTERN
#if defined(__cplusplus)
}
#endif
#endif /* __ASSEMBLY__ */
#endif /* __BOARDS_XTENSA_ESP32S3_COMMON_INCLUDE_ESP32S3_BOARD_ADC_H */

View File

@ -60,6 +60,10 @@ ifeq ($(CONFIG_ESP32S3_OTG),y)
CSRCS += esp32s3_board_usb.c
endif
ifeq ($(CONFIG_ESP32S3_ADC),y)
CSRCS += esp32s3_board_adc.c
endif
ifeq ($(CONFIG_NET_LAN9250),y)
CSRCS += esp32s3_lan9250.c
endif

View File

@ -0,0 +1,192 @@
/****************************************************************************
* boards/xtensa/esp32s3/common/src/esp32s3_board_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 <syslog.h>
#include <debug.h>
#include <sys/types.h>
#include "esp32s3_adc.h"
#include "esp32s3_board_adc.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: board_adc_register
*
* Description:
* Register the ADC driver.
*
* Input Parameters:
* channel - ADC channel number.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
* to indicate the nature of any failure.
*
****************************************************************************/
static int board_adc_register(int channel)
{
int ret;
char devname[12];
FAR struct adc_dev_s *adcdev;
adcdev = kmm_malloc(sizeof(struct adc_dev_s));
if (adcdev == NULL)
{
aerr("ERROR: Failed to allocate adc_dev_s instance\n");
return -ENOMEM;
}
memset(adcdev, 0, sizeof(struct adc_dev_s));
esp32s3_adc_init(channel, adcdev);
snprintf(devname, 12, "/dev/adc%d", channel);
/* Register the ADC driver at "/dev/adcx_x" */
ret = adc_register(devname, adcdev);
if (ret < 0)
{
kmm_free(adcdev);
syslog(LOG_ERR, "ERROR: adc_register %s failed: %d\n", devname, ret);
return ret;
}
return ret;
}
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: board_adc_init
*
* Description:
* Configure the ADC driver.
*
* Input Parameters:
* None.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned
* to indicate the nature of any failure.
*
****************************************************************************/
int board_adc_init(void)
{
int ret;
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL0
ret = board_adc_register(ESP32S3_ADC1_CHANNEL0);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL1
ret = board_adc_register(ESP32S3_ADC1_CHANNEL1);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL2
ret = board_adc_register(ESP32S3_ADC1_CHANNEL2);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL3
ret = board_adc_register(ESP32S3_ADC1_CHANNEL3);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL4
ret = board_adc_register(ESP32S3_ADC1_CHANNEL4);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL5
ret = board_adc_register(ESP32S3_ADC1_CHANNEL5);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL6
ret = board_adc_register(ESP32S3_ADC1_CHANNEL6);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL7
ret = board_adc_register(ESP32S3_ADC1_CHANNEL7);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL8
ret = board_adc_register(ESP32S3_ADC1_CHANNEL8);
if (ret != OK)
{
return ret;
}
#endif
#ifdef CONFIG_ESP32S3_ADC1_CHANNEL9
ret = board_adc_register(ESP32S3_ADC1_CHANNEL9);
if (ret != OK)
{
return ret;
}
#endif
return ret;
}

View File

@ -0,0 +1,54 @@
#
# 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_ARCH_LEDS is not set
# CONFIG_NSH_ARGCAT is not set
# CONFIG_NSH_CMDOPT_HEXDUMP is not set
CONFIG_ARCH="xtensa"
CONFIG_ARCH_BOARD="esp32s3-devkit"
CONFIG_ARCH_BOARD_COMMON=y
CONFIG_ARCH_BOARD_ESP32S3_DEVKIT=y
CONFIG_ARCH_CHIP="esp32s3"
CONFIG_ARCH_CHIP_ESP32S3=y
CONFIG_ARCH_CHIP_ESP32S3WROOM1=y
CONFIG_ARCH_INTERRUPTSTACK=2048
CONFIG_ARCH_STACKDUMP=y
CONFIG_ARCH_XTENSA=y
CONFIG_BOARD_LOOPSPERMSEC=16717
CONFIG_BUILTIN=y
CONFIG_DEBUG_FULLOPT=y
CONFIG_DEBUG_SYMBOLS=y
CONFIG_ESP32S3_ADC1_CHANNEL0=y
CONFIG_ESP32S3_ADC1_CHANNEL1=y
CONFIG_ESP32S3_ADC1_CHANNEL2=y
CONFIG_ESP32S3_ADC=y
CONFIG_ESP32S3_APP_FORMAT_LEGACY=y
CONFIG_ESP32S3_UART0=y
CONFIG_EXAMPLES_ADC=y
CONFIG_EXAMPLES_ADC_SWTRIG=y
CONFIG_FS_PROCFS=y
CONFIG_HAVE_CXX=y
CONFIG_HAVE_CXXINITIALIZE=y
CONFIG_IDLETHREAD_STACKSIZE=3072
CONFIG_INIT_ENTRYPOINT="nsh_main"
CONFIG_INTELHEX_BINARY=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=114688
CONFIG_RAM_START=0x20000000
CONFIG_RR_INTERVAL=200
CONFIG_SCHED_WAITPID=y
CONFIG_START_DAY=6
CONFIG_START_MONTH=12
CONFIG_START_YEAR=2011
CONFIG_SYSLOG_BUFFER=y
CONFIG_SYSTEM_NSH=y
CONFIG_UART0_SERIAL_CONSOLE=y

View File

@ -109,6 +109,10 @@
# include "esp32s3_aes.h"
#endif
#ifdef CONFIG_ESP32S3_ADC
#include "esp32s3_board_adc.h"
#endif
#include "esp32s3-devkit.h"
/****************************************************************************
@ -456,6 +460,16 @@ int esp32s3_bringup(void)
#endif
#endif
#ifdef CONFIG_ESP32S3_ADC
/* Configure ADC */
ret = board_adc_init();
if (ret)
{
syslog(LOG_ERR, "ERROR: board_adc_init() failed: %d\n", ret);
}
#endif
/* If we got here then perhaps not all initialization was successful, but
* at least enough succeeded to bring-up NSH with perhaps reduced
* capabilities.