adc: support ADC on esp32c6 (driver/test/example)

This commit is contained in:
laokaiyao
2022-12-05 16:01:34 +08:00
parent e27f3e3128
commit 5333ac81bf
50 changed files with 363 additions and 331 deletions

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -20,6 +20,7 @@
#include "hal/adc_types.h"
#include "hal/adc_types_private.h"
#include "hal/regi2c_ctrl.h"
#include "hal/sar_ctrl_ll.h"
#include "soc/regi2c_saradc.h"
@@ -36,49 +37,30 @@ extern "C" {
#define ADC_LL_EVENT_ADC1_ONESHOT_DONE BIT(31)
#define ADC_LL_EVENT_ADC2_ONESHOT_DONE BIT(30)
#define ADC_LL_EVENT_THRES0_HIGH BIT(29)
#define ADC_LL_event_THRES1_HIGH BIT(28)
#define ADC_LL_event_THRES0_LOW BIT(27)
#define ADC_LL_EVENT_THRES1_HIGH BIT(28)
#define ADC_LL_EVENT_THRES0_LOW BIT(27)
#define ADC_LL_EVENT_THRES1_LOW BIT(26)
typedef enum {
ADC_POWER_BY_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */
ADC_POWER_SW_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */
ADC_POWER_SW_OFF, /*!< ADC XPD controlled by SW. power off. */
ADC_POWER_BY_FSM = SAR_CTRL_LL_POWER_FSM, /*!< ADC XPD controlled by FSM. Used for polling mode */
ADC_POWER_SW_ON = SAR_CTRL_LL_POWER_ON, /*!< ADC XPD controlled by SW. power on. Used for DMA mode */
ADC_POWER_SW_OFF = SAR_CTRL_LL_POWER_OFF, /*!< ADC XPD controlled by SW. power off. */
ADC_POWER_MAX, /*!< For parameter check. */
} adc_ll_power_t;
typedef enum {
ADC_RTC_DATA_OK = 0,
ADC_RTC_CTRL_UNSELECTED = 1,
ADC_RTC_CTRL_BREAK = 2,
ADC_RTC_DATA_FAIL = -1,
} adc_ll_rtc_raw_data_t;
typedef enum {
ADC_LL_CTRL_DIG = 0, ///< Only support ADC1, i.e. only digital controller available.
ADC_LL_CTRL_DIG = 0, ///< ADC digital controller
} adc_ll_controller_t;
/**
* @brief Clock source of ADC digital controller
* @note Not public as it always uses a default value for now
*/
typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t;
/**
* @brief Clock source of ADC digital controller
* @note Not public as it always uses a default value for now
*/
typedef soc_periph_adc_digi_clk_src_t adc_ll_digi_clk_src_t;
/**
* @brief ADC digital controller (DMA mode) work mode.
*
* @note The conversion mode affects the sampling frequency:
* ESP32C3 only support ALTER_UNIT mode
* ALTER_UNIT : When the measurement is triggered, ADC1 or ADC2 samples alternately.
* ESP32C6 only support ONLY_ADC1 mode
* SINGLE_UNIT_1: When the measurement is triggered, only ADC1 is sampled once.
*/
typedef enum {
ADC_LL_DIGI_CONV_ALTER_UNIT = 0, // Use both ADC1 and ADC2 for conversion by turn. e.g. ADC1 -> ADC2 -> ADC1 -> ADC2 .....
ADC_LL_DIGI_CONV_ONLY_ADC1 = 0, // Only use ADC1 for conversion
} adc_ll_digi_convert_mode_t;
typedef struct {
@@ -123,9 +105,7 @@ static inline void adc_ll_digi_set_fsm_time(uint32_t rst_wait, uint32_t start_wa
*/
static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
{
// TODO: [adc_c6] Maybe this REG I2C for peripheral needs a reference lock
/* Should be called before writing I2C registers. */
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
/* Peripheral reg i2c has powered up in rtc_init, write directly */
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_SAMPLE_CYCLE_ADDR, sample_cycle);
}
@@ -137,7 +117,7 @@ static inline void adc_ll_set_sample_cycle(uint32_t sample_cycle)
*/
static inline void adc_ll_digi_set_clk_div(uint32_t div)
{
/* ADC clock devided from digital controller clock clk */
/* ADC clock divided from digital controller clock clk */
HAL_FORCE_MODIFY_U32_REG_FIELD(APB_SARADC.saradc_ctrl, saradc_saradc_sar_clk_div, div);
}
@@ -166,18 +146,18 @@ static inline void adc_ll_digi_convert_limit_enable(bool enable)
/**
* Set adc conversion mode for digital controller.
*
* @note ESP32C3 only support ADC1 single mode.
* @note ESP32C6 only support ADC1 single mode.
*
* @param mode Conversion mode select.
*/
static inline void adc_ll_digi_set_convert_mode(adc_ll_digi_convert_mode_t mode)
{
//ESP32C3 only supports ADC_CONV_ALTER_UNIT mode
//ESP32C6 only supports ADC_LL_DIGI_CONV_ONLY_ADC1 mode
}
/**
* Set pattern table length for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 4 items, in which channel selection,
* and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself.
*
@@ -191,7 +171,7 @@ static inline void adc_ll_digi_set_pattern_table_len(adc_unit_t adc_n, uint32_t
/**
* Set pattern table for digital controller.
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 8 items, in which channel selection,
* The pattern table that defines the conversion rules for each SAR ADC. Each table has 4 items, in which channel selection,
* resolution and attenuation are stored. When the conversion is started, the controller reads conversion rules from the
* pattern table one by one. For each controller the scan sequence has at most 8 different rules before repeating itself.
*
@@ -208,15 +188,15 @@ static inline void adc_ll_digi_set_pattern_table(adc_unit_t adc_n, uint32_t patt
pattern.val = (table.atten & 0x3) | ((table.channel & 0x7) << 2) | ((table.unit & 0x1) << 5);
if (index == 0) {
tab = APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1; // Read old register value
tab &= (~(0xFC0000 >> offset)); // Clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = tab; // Write back
tab = APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1; // Read old register value
tab &= (~(0xFC0000 >> offset)); // Clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
APB_SARADC.saradc_sar_patt_tab1.saradc_saradc_sar_patt_tab1 = tab; // Write back
} else {
tab = APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2; // Read old register value
tab &= (~(0xFC0000 >> offset)); // Clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = tab; // Write back
tab = APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2; // Read old register value
tab &= (~(0xFC0000 >> offset)); // Clear old data
tab |= ((uint32_t)(pattern.val & 0x3F) << 18) >> offset; // Fill in the new data
APB_SARADC.saradc_sar_patt_tab2.saradc_saradc_sar_patt_tab2 = tab; // Write back
}
}
@@ -252,8 +232,6 @@ static inline void adc_ll_digi_output_invert(adc_unit_t adc_n, bool inv_en)
{
if (adc_n == ADC_UNIT_1) {
APB_SARADC.saradc_ctrl2.saradc_saradc_sar1_inv = inv_en; // Enable / Disable ADC data invert
} else { // adc_n == ADC_UNIT_2
APB_SARADC.saradc_ctrl2.saradc_saradc_sar2_inv = inv_en; // Enable / Disable ADC data invert
}
}
@@ -305,7 +283,7 @@ static inline void adc_ll_digi_controller_clk_div(uint32_t div_num, uint32_t div
*
* @param clk_src clock source for ADC digital controller.
*/
static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src)
static inline void adc_ll_digi_clk_sel(adc_continuous_clk_src_t clk_src)
{
switch (clk_src) {
case ADC_DIGI_CLK_SRC_XTAL:
@@ -318,10 +296,10 @@ static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src)
PCR.saradc_clkm_conf.saradc_clkm_sel = 2;
break;
default:
PCR.saradc_clkm_conf.saradc_clkm_sel = 1;
HAL_ASSERT(false && "unsupported clock");
}
// Enable ADC_CTRL_CLK (i.e. digital domain clock)
PCR.saradc_clkm_conf.saradc_clkm_en = 1;
APB_SARADC.saradc_ctrl.saradc_saradc_sar_clk_gated = 1;
}
/**
@@ -329,7 +307,7 @@ static inline void adc_ll_digi_clk_sel(adc_ll_digi_clk_src_t clk_src)
*/
static inline void adc_ll_digi_controller_clk_disable(void)
{
PCR.saradc_clkm_conf.saradc_clkm_en = 0;
APB_SARADC.saradc_ctrl.saradc_saradc_sar_clk_gated = 0;
}
/**
@@ -480,9 +458,7 @@ static inline void adc_ll_digi_reset(void)
*/
static inline void adc_ll_pwdet_set_cct(uint32_t cct)
{
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
// RTCCNTL.sensor_ctrl.sar2_pwdet_cct = cct;
// TODO: [adc_c6] check cct validation on C6
(void)cct;
}
/**
@@ -493,9 +469,6 @@ static inline void adc_ll_pwdet_set_cct(uint32_t cct)
*/
static inline uint32_t adc_ll_pwdet_get_cct(void)
{
/* Capacitor tuning of the PA power monitor. cct set to the same value with PHY. */
// return RTCCNTL.sensor_ctrl.sar2_pwdet_cct;
// TODO: [adc_c6] check cct validation on C6
return 0;
}
@@ -512,13 +485,13 @@ static inline void adc_ll_set_power_manage(adc_ll_power_t manage)
/* Bit1 0:Fsm 1: SW mode
Bit0 0:SW mode power down 1: SW mode power on */
if (manage == ADC_POWER_SW_ON) {
PCR.saradc_clkm_conf.saradc_clkm_en = 1;
APB_SARADC.saradc_ctrl.saradc_saradc_sar_clk_gated = 1;
APB_SARADC.saradc_ctrl.saradc_saradc_xpd_sar_force = 3;
} else if (manage == ADC_POWER_BY_FSM) {
PCR.saradc_clkm_conf.saradc_clkm_en = 1;
APB_SARADC.saradc_ctrl.saradc_saradc_sar_clk_gated = 1;
APB_SARADC.saradc_ctrl.saradc_saradc_xpd_sar_force = 0;
} else if (manage == ADC_POWER_SW_OFF) {
PCR.saradc_clkm_conf.saradc_clkm_en = 0;
APB_SARADC.saradc_ctrl.saradc_saradc_sar_clk_gated = 0;
APB_SARADC.saradc_ctrl.saradc_saradc_xpd_sar_force = 2;
}
}
@@ -536,11 +509,8 @@ static inline void adc_ll_set_controller(adc_unit_t adc_n, adc_ll_controller_t c
__attribute__((always_inline))
static inline void adc_ll_calibration_init(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 1);
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 1);
}
HAL_ASSERT(adc_n == ADC_UNIT_1);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 1);
}
/**
@@ -554,19 +524,12 @@ static inline void adc_ll_calibration_init(adc_unit_t adc_n)
*/
static inline void adc_ll_calibration_prepare(adc_unit_t adc_n, bool internal_gnd)
{
HAL_ASSERT(adc_n == ADC_UNIT_1);
/* Enable/disable internal connect GND (for calibration). */
if (adc_n == ADC_UNIT_1) {
if (internal_gnd) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1);
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0);
}
if (internal_gnd) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 1);
} else {
if (internal_gnd) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 1);
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0);
}
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0);
}
}
@@ -577,11 +540,8 @@ static inline void adc_ll_calibration_prepare(adc_unit_t adc_n, bool internal_gn
*/
static inline void adc_ll_calibration_finish(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0);
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_ENCAL_GND_ADDR, 0);
}
HAL_ASSERT(adc_n == ADC_UNIT_1);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_ENCAL_GND_ADDR, 0);
}
/**
@@ -594,17 +554,12 @@ static inline void adc_ll_calibration_finish(adc_unit_t adc_n)
__attribute__((always_inline))
static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param)
{
HAL_ASSERT(adc_n == ADC_UNIT_1);
uint8_t msb = param >> 8;
uint8_t lsb = param & 0xFF;
if (adc_n == ADC_UNIT_1) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb);
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_HIGH_ADDR, msb);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_INITIAL_CODE_LOW_ADDR, lsb);
}
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_HIGH_ADDR, msb);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_INITIAL_CODE_LOW_ADDR, lsb);
}
/* Temp code end. */
/*---------------------------------------------------------------
Oneshot Read
@@ -612,13 +567,13 @@ static inline void adc_ll_set_calibration_param(adc_unit_t adc_n, uint32_t param
/**
* Set adc output data format for oneshot mode
*
* @note ESP32C3 Oneshot mode only supports 12bit.
* @note ESP32C6 Oneshot mode only supports 12bit.
* @param adc_n ADC unit.
* @param bits Output data bits width option.
*/
static inline void adc_oneshot_ll_set_output_bits(adc_unit_t adc_n, adc_bitwidth_t bits)
{
//ESP32C3 only supports 12bit, leave here for compatibility
//ESP32C6 only supports 12bit, leave here for compatibility
HAL_ASSERT(bits == ADC_BITWIDTH_12 || bits == ADC_BITWIDTH_DEFAULT);
}
@@ -632,6 +587,7 @@ static inline void adc_oneshot_ll_set_output_bits(adc_unit_t adc_n, adc_bitwidth
*/
static inline void adc_oneshot_ll_set_channel(adc_unit_t adc_n, adc_channel_t channel)
{
HAL_ASSERT(adc_n == ADC_UNIT_1);
APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | channel);
}
@@ -644,11 +600,8 @@ static inline void adc_oneshot_ll_set_channel(adc_unit_t adc_n, adc_channel_t ch
*/
static inline void adc_oneshot_ll_disable_channel(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | 0xF);
} else { // adc_n == ADC_UNIT_2
APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | 0x1);
}
HAL_ASSERT(adc_n == ADC_UNIT_1);
APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_channel = ((adc_n << 3) | 0xF);
}
/**
@@ -688,7 +641,7 @@ static inline bool adc_oneshot_ll_get_event(uint32_t event_mask)
}
/**
* Get the converted value for each ADCn for RTC controller.
* Get the converted value for each ADCn for controller.
*
* @param adc_n ADC unit.
* @return
@@ -696,12 +649,9 @@ static inline bool adc_oneshot_ll_get_event(uint32_t event_mask)
*/
static inline uint32_t adc_oneshot_ll_get_raw_result(adc_unit_t adc_n)
{
HAL_ASSERT(adc_n == ADC_UNIT_1);
uint32_t ret_val = 0;
if (adc_n == ADC_UNIT_1) {
ret_val = APB_SARADC.saradc_sar1data_status.saradc_apb_saradc1_data & 0xfff;
} else { // adc_n == ADC_UNIT_2
ret_val = APB_SARADC.saradc_sar2data_status.saradc_apb_saradc2_data & 0xfff;
}
ret_val = APB_SARADC.saradc_sar1data_status.saradc_apb_saradc1_data & 0xfff;
return ret_val;
}
@@ -717,15 +667,7 @@ static inline uint32_t adc_oneshot_ll_get_raw_result(adc_unit_t adc_n)
*/
static inline bool adc_oneshot_ll_raw_check_valid(adc_unit_t adc_n, uint32_t raw_data)
{
if (adc_n == ADC_UNIT_1) {
return true;
}
//The raw data API returns value without channel information. Read value directly from the register
if (((APB_SARADC.saradc_sar2data_status.saradc_apb_saradc2_data >> 13) & 0xF) > 9) {
return false;
}
HAL_ASSERT(adc_n == ADC_UNIT_1);
return true;
}
@@ -737,7 +679,7 @@ static inline bool adc_oneshot_ll_raw_check_valid(adc_unit_t adc_n, uint32_t raw
*/
static inline void adc_oneshot_ll_output_invert(adc_unit_t adc_n, bool inv_en)
{
(void)adc_n;
HAL_ASSERT(adc_n == ADC_UNIT_1);
(void)inv_en;
//For compatibility
}
@@ -749,11 +691,8 @@ static inline void adc_oneshot_ll_output_invert(adc_unit_t adc_n, bool inv_en)
*/
static inline void adc_oneshot_ll_enable(adc_unit_t adc_n)
{
if (adc_n == ADC_UNIT_1) {
APB_SARADC.saradc_onetime_sample.saradc_saradc1_onetime_sample = 1;
} else {
APB_SARADC.saradc_onetime_sample.saradc_saradc2_onetime_sample = 1;
}
HAL_ASSERT(adc_n == ADC_UNIT_1);
APB_SARADC.saradc_onetime_sample.saradc_saradc1_onetime_sample = 1;
}
/**
@@ -776,7 +715,7 @@ static inline void adc_oneshot_ll_disable_all_unit(void)
*/
static inline void adc_oneshot_ll_set_atten(adc_unit_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
(void)adc_n;
HAL_ASSERT(adc_n == ADC_UNIT_1);
(void)channel;
// Attenuation is for all channels, unit and channel are for compatibility
APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_atten = atten;
@@ -792,7 +731,7 @@ static inline void adc_oneshot_ll_set_atten(adc_unit_t adc_n, adc_channel_t chan
__attribute__((always_inline))
static inline adc_atten_t adc_ll_get_atten(adc_unit_t adc_n, adc_channel_t channel)
{
(void)adc_n;
HAL_ASSERT(adc_n == ADC_UNIT_1);
(void)channel;
return (adc_atten_t)APB_SARADC.saradc_onetime_sample.saradc_saradc_onetime_atten;
}