adc: support adc efuse-based calibration on esp32s3

This commit is contained in:
Armando 2021-09-07 11:21:35 +08:00 committed by Armando (Dou Yiwen)
parent c54caa457e
commit c45c6f52f1
32 changed files with 1017 additions and 190 deletions

View File

@ -18,16 +18,18 @@
#include "driver/gpio.h"
#include "driver/adc.h"
#include "adc1_private.h"
#include "hal/adc_types.h"
#include "hal/adc_hal.h"
#include "hal/adc_hal_conf.h"
#if SOC_DAC_SUPPORTED
#include "driver/dac.h"
#include "hal/dac_hal.h"
#endif
#include "hal/adc_hal_conf.h"
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp_efuse_rtc_calib.h"
#endif
#define ADC_CHECK_RET(fun_ret) ({ \
if (fun_ret != ESP_OK) { \
@ -123,20 +125,10 @@ static esp_pm_lock_handle_t s_adc2_arbiter_lock;
#endif //CONFIG_PM_ENABLE
#endif // !CONFIG_IDF_TARGET_ESP32
/*---------------------------------------------------------------
ADC Common
---------------------------------------------------------------*/
#if CONFIG_IDF_TARGET_ESP32S2
static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan)
{
adc_atten_t atten = adc_hal_get_atten(adc_n, chan);
extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool no_cal);
return adc_get_calibration_offset(adc_n, chan, atten, false);
}
#endif
// ADC Power
// This gets incremented when adc_power_acquire() is called, and decremented when
@ -226,7 +218,56 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
//------------------------------------------------------------RTC Single Read----------------------------------------------//
#if SOC_ADC_RTC_CTRL_SUPPORTED
/*---------------------------------------------------------------
ADC Calibration
---------------------------------------------------------------*/
#if CONFIG_IDF_TARGET_ESP32S3
/**
* Temporarily put this function here. These are about ADC calibration and will be moved driver/adc.c in !14278.
* Reason for putting calibration functions in driver/adc.c:
* adc_common.c is far too confusing. Before a refactor is applied to adc_common.c, will put definite code in driver/adc.c
*/
static uint16_t s_adc_cali_param[ADC_UNIT_MAX][ADC_ATTEN_MAX] = {};
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
if (s_adc_cali_param[adc_n][atten]) {
//These value won't exceed UINT16_MAX
return s_adc_cali_param[adc_n][atten];
}
//Get the calibration version
int version = esp_efuse_rtc_calib_get_ver();
uint32_t init_code = 0;
if (version == 1) {
init_code = esp_efuse_rtc_calib_get_init_code(version, adc_n, atten);
s_adc_cali_param[adc_n][atten] = init_code;
} else {
ESP_LOGW(ADC_TAG, "Calibration eFuse is not configured, skip calibration");
}
return s_adc_cali_param[adc_n][atten];
}
#elif CONFIG_IDF_TARGET_ESP32S2
//Temporarily extern this from s2/adc.c. Will be modified in !14278.
extern uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten);
#endif //CONFIG_IDF_TARGET_ESP32S3
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
static uint32_t get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan)
{
adc_atten_t atten = adc_hal_get_atten(adc_n, chan);
return adc_get_calibration_offset(adc_n, chan, atten);
}
#endif //#if SOC_ADC_CALIBRATION_V1_SUPPORTED
esp_err_t adc_set_clk_div(uint8_t clk_div)
{
DIGI_CONTROLLER_ENTER();
@ -349,7 +390,7 @@ esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
adc_hal_set_atten(ADC_NUM_1, channel, atten);
SARADC1_EXIT();
#if SOC_ADC_HW_CALIBRATION_V1
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
adc_hal_calibration_init(ADC_NUM_1);
#endif
@ -427,11 +468,11 @@ int adc1_get_raw(adc1_channel_t channel)
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
adc1_rtc_mode_acquire();
#if CONFIG_IDF_TARGET_ESP32S2
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
// Get calibration value before going into critical section
uint32_t cal_val = get_calibration_offset(ADC_NUM_1, channel);
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
#endif
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
SARADC1_ENTER();
#ifdef CONFIG_IDF_TARGET_ESP32
@ -521,7 +562,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
SARADC2_RELEASE();
#if SOC_ADC_HW_CALIBRATION_V1
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
adc_hal_calibration_init(ADC_NUM_2);
#endif
@ -578,11 +619,11 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
ADC_CHECK(width_bit == ADC_WIDTH_MAX - 1, "WIDTH ERR: see `adc_bits_width_t` for supported bit width", ESP_ERR_INVALID_ARG);
#endif
#if CONFIG_IDF_TARGET_ESP32S2
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
// Get calibration value before going into critical section
uint32_t cal_val = get_calibration_offset(ADC_NUM_2, channel);
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
#endif
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
if ( SARADC2_TRY_ACQUIRE() == -1 ) {
//try the lock, return if failed (wifi using).
@ -679,4 +720,4 @@ esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
return ESP_OK;
}
#endif //CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#endif //SOC_ADC_RTC_CTRL_SUPPORTED

View File

@ -437,7 +437,7 @@ static uint16_t s_adc_cali_param[ADC_NUM_MAX][ADC_ATTEN_MAX] = { {0}, {0} };
// 1. Semaphore when reading efuse
// 2. Spinlock when actually doing ADC calibration
//This function shoudn't be called inside critical section or ISR
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool no_cal)
uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
#ifdef CONFIG_IDF_ENV_FPGA
return 0;
@ -448,10 +448,6 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a
return (uint32_t)s_adc_cali_param[adc_n][atten];
}
if (no_cal) {
return 0; //indicating failure
}
uint32_t dout = 0;
// check if we can fetch the values from eFuse.
int version = esp_efuse_rtc_table_read_calib_version();
@ -474,7 +470,7 @@ uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, a
esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
{
adc_hal_calibration_init(adc_n);
uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten, false);
uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten);
ADC_ENTER_CRITICAL();
adc_hal_set_calibration_param(adc_n, cal_val);
ADC_EXIT_CRITICAL();

View File

@ -33,7 +33,7 @@ uint8_t esp_efuse_get_chip_ver(void)
uint32_t esp_efuse_get_pkg_ver(void)
{
uint32_t pkg_ver = 0;
esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, 4);
esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, ESP_EFUSE_PKG_VERSION[0]->bit_count);
return pkg_ver;
}
@ -45,9 +45,9 @@ esp_err_t esp_efuse_disable_rom_download_mode(void)
esp_err_t esp_efuse_set_rom_log_scheme(esp_efuse_rom_log_scheme_t log_scheme)
{
int cur_log_scheme = 0;
esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, 2);
esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, ESP_EFUSE_UART_PRINT_CONTROL[0]->bit_count);
if (!cur_log_scheme) { // not burned yet
return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, 2);
return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, ESP_EFUSE_UART_PRINT_CONTROL[0]->bit_count);
} else {
return ESP_ERR_INVALID_STATE;
}

View File

@ -0,0 +1,103 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_bit_defs.h>
#include "esp_err.h"
#include "esp_log.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
//Don't introduce new dependency of ADC, keep these macro same as ADC related definations
#define ADC_ATTEN_MAX 4
#define ADC_NUM_MAX 2
#define ADC_NUM_1 0
#define ADC_NUM_2 1
int esp_efuse_rtc_calib_get_ver(void)
{
uint32_t blk1_version = 0;
uint32_t blk2_version = 0;
ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_BLOCK1_VERSION, &blk1_version, ESP_EFUSE_BLOCK1_VERSION[0]->bit_count));
ESP_ERROR_CHECK(esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &blk2_version, ESP_EFUSE_BLOCK2_VERSION[0]->bit_count));
if (blk1_version == blk2_version) {
return blk1_version;
} else {
blk1_version = 0;
blk2_version = 0;
ESP_LOGW("eFuse", "calibration efuse version does not match, set default version: %d", 0);
}
return blk2_version;
}
uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten)
{
assert(version == 1);
assert(atten < 4);
assert(adc_unit < ADC_NUM_MAX);
const esp_efuse_desc_t **desc[8] = {ESP_EFUSE_ADC1_INIT_CODE_ATTEN0, ESP_EFUSE_ADC1_INIT_CODE_ATTEN1, ESP_EFUSE_ADC1_INIT_CODE_ATTEN2, ESP_EFUSE_ADC1_INIT_CODE_ATTEN3,
ESP_EFUSE_ADC2_INIT_CODE_ATTEN0, ESP_EFUSE_ADC2_INIT_CODE_ATTEN1, ESP_EFUSE_ADC2_INIT_CODE_ATTEN2, ESP_EFUSE_ADC2_INIT_CODE_ATTEN3};
int efuse_icode_bits = 0;
uint32_t adc_icode[4] = {};
uint32_t adc_icode_diff[4] = {};
uint8_t desc_index = (adc_unit == ADC_NUM_1) ? 0 : 4;
for (int diff_index = 0; diff_index < 4; diff_index++) {
efuse_icode_bits = esp_efuse_get_field_size(desc[desc_index]);
ESP_ERROR_CHECK(esp_efuse_read_field_blob(desc[desc_index], &adc_icode_diff[diff_index], efuse_icode_bits));
desc_index++;
}
//Version 1 logic for calculating ADC ICode based on EFUSE burnt value
if (adc_unit == ADC_NUM_1) {
adc_icode[0] = adc_icode_diff[0] + 1850;
adc_icode[1] = adc_icode_diff[1] + adc_icode[0] + 90;
adc_icode[2] = adc_icode_diff[2] + adc_icode[1];
adc_icode[3] = adc_icode_diff[3] + adc_icode[2] + 70;
} else {
adc_icode[0] = adc_icode_diff[0] + 2020;
adc_icode[1] = adc_icode_diff[1] + adc_icode[0];
adc_icode[2] = adc_icode_diff[2] + adc_icode[1];
adc_icode[3] = adc_icode_diff[3] + adc_icode[2];
}
return adc_icode[atten];
}
esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t *out_digi, uint32_t *out_vol_mv)
{
assert(version == 1);
assert(atten < 4);
assert(adc_unit < ADC_NUM_MAX);
int efuse_vol_bits = 0;
uint32_t adc_vol_diff[8] = {};
uint32_t adc1_vol[4] = {};
uint32_t adc2_vol[4] = {};
const esp_efuse_desc_t **desc[8] = {ESP_EFUSE_ADC1_CAL_VOL_ATTEN0, ESP_EFUSE_ADC1_CAL_VOL_ATTEN1, ESP_EFUSE_ADC1_CAL_VOL_ATTEN2, ESP_EFUSE_ADC1_CAL_VOL_ATTEN3,
ESP_EFUSE_ADC2_CAL_VOL_ATTEN0, ESP_EFUSE_ADC2_CAL_VOL_ATTEN1, ESP_EFUSE_ADC2_CAL_VOL_ATTEN2, ESP_EFUSE_ADC2_CAL_VOL_ATTEN3};
for (int i = 0; i < 8; i++) {
efuse_vol_bits = esp_efuse_get_field_size(desc[i]);
ESP_ERROR_CHECK(esp_efuse_read_field_blob(desc[i], &adc_vol_diff[i], efuse_vol_bits));
}
adc1_vol[3] = adc_vol_diff[3] + 900;
adc1_vol[2] = adc_vol_diff[2] + adc1_vol[3] + 800;
adc1_vol[1] = adc_vol_diff[1] + adc1_vol[2] + 700;
adc1_vol[0] = adc_vol_diff[0] + adc1_vol[1] + 800;
adc2_vol[3] = adc1_vol[3] - adc_vol_diff[7] + 15;
adc2_vol[2] = adc1_vol[2] - adc_vol_diff[6] + 20;
adc2_vol[1] = adc1_vol[1] - adc_vol_diff[5] + 10;
adc2_vol[0] = adc1_vol[0] - adc_vol_diff[4] + 40;
*out_digi = (adc_unit == ADC_NUM_1) ? adc1_vol[atten] : adc2_vol[atten];
*out_vol_mv = 850;
return ESP_OK;
}

View File

@ -9,7 +9,7 @@
#include <assert.h>
#include "esp_efuse_table.h"
// md5_digest_table 2b4b79060b04576a3d189a54f42dd462
// md5_digest_table 0f3dc076304dac1cb56cea03c223d26d
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
// If you want to change some fields, you need to change esp_efuse_table.csv file
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
@ -417,15 +417,15 @@ static const esp_efuse_desc_t WAFER_VERSION[] = {
};
static const esp_efuse_desc_t PKG_VERSION[] = {
{EFUSE_BLK1, 117, 4}, // Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32,
{EFUSE_BLK1, 117, 3}, // Package version,
};
static const esp_efuse_desc_t BLOCK1_VERSION[] = {
{EFUSE_BLK1, 121, 3}, // BLOCK1 efuse version 0:No calibration 1:With calibration,
{EFUSE_BLK1, 120, 3}, // BLOCK1 efuse version 0:No calibration 1:With calibration,
};
static const esp_efuse_desc_t SYS_DATA_PART0[] = {
{EFUSE_BLK1, 126, 66}, // System configuration,
static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN3[] = {
{EFUSE_BLK1, 186, 6}, // ADC2 calibration voltage at atten3,
};
static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = {
@ -433,7 +433,75 @@ static const esp_efuse_desc_t OPTIONAL_UNIQUE_ID[] = {
};
static const esp_efuse_desc_t BLOCK2_VERSION[] = {
{EFUSE_BLK2, 132, 3}, // Version of BLOCK2,
{EFUSE_BLK2, 128, 4}, // Version of BLOCK2,
};
static const esp_efuse_desc_t TEMP_CALIB[] = {
{EFUSE_BLK2, 132, 9}, // Temperature calibration data,
};
static const esp_efuse_desc_t OCODE[] = {
{EFUSE_BLK2, 141, 8}, // ADC OCode,
};
static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN0[] = {
{EFUSE_BLK2, 149, 8}, // ADC1 init code at atten0,
};
static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN1[] = {
{EFUSE_BLK2, 157, 6}, // ADC1 init code at atten1,
};
static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN2[] = {
{EFUSE_BLK2, 163, 6}, // ADC1 init code at atten2,
};
static const esp_efuse_desc_t ADC1_INIT_CODE_ATTEN3[] = {
{EFUSE_BLK2, 169, 6}, // ADC1 init code at atten3,
};
static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN0[] = {
{EFUSE_BLK2, 175, 8}, // ADC2 init code at atten0,
};
static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN1[] = {
{EFUSE_BLK2, 183, 6}, // ADC2 init code at atten1,
};
static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN2[] = {
{EFUSE_BLK2, 189, 6}, // ADC2 init code at atten2,
};
static const esp_efuse_desc_t ADC2_INIT_CODE_ATTEN3[] = {
{EFUSE_BLK2, 195, 6}, // ADC2 init code at atten3,
};
static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN0[] = {
{EFUSE_BLK2, 201, 8}, // ADC1 calibration voltage at atten0,
};
static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN1[] = {
{EFUSE_BLK2, 209, 8}, // ADC1 calibration voltage at atten1,
};
static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN2[] = {
{EFUSE_BLK2, 217, 8}, // ADC1 calibration voltage at atten2,
};
static const esp_efuse_desc_t ADC1_CAL_VOL_ATTEN3[] = {
{EFUSE_BLK2, 225, 8}, // ADC1 calibration voltage at atten3,
};
static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN0[] = {
{EFUSE_BLK2, 233, 8}, // ADC2 calibration voltage at atten0,
};
static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN1[] = {
{EFUSE_BLK2, 241, 7}, // ADC2 calibration voltage at atten1,
};
static const esp_efuse_desc_t ADC2_CAL_VOL_ATTEN2[] = {
{EFUSE_BLK2, 248, 7}, // ADC2 calibration voltage at atten2,
};
static const esp_efuse_desc_t USER_DATA[] = {
@ -977,7 +1045,7 @@ const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[] = {
};
const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[] = {
&PKG_VERSION[0], // Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32
&PKG_VERSION[0], // Package version
NULL
};
@ -986,8 +1054,8 @@ const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[] = {
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[] = {
&SYS_DATA_PART0[0], // System configuration
const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN3[] = {
&ADC2_CAL_VOL_ATTEN3[0], // ADC2 calibration voltage at atten3
NULL
};
@ -1001,6 +1069,91 @@ const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[] = {
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[] = {
&TEMP_CALIB[0], // Temperature calibration data
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_OCODE[] = {
&OCODE[0], // ADC OCode
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[] = {
&ADC1_INIT_CODE_ATTEN0[0], // ADC1 init code at atten0
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[] = {
&ADC1_INIT_CODE_ATTEN1[0], // ADC1 init code at atten1
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[] = {
&ADC1_INIT_CODE_ATTEN2[0], // ADC1 init code at atten2
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[] = {
&ADC1_INIT_CODE_ATTEN3[0], // ADC1 init code at atten3
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN0[] = {
&ADC2_INIT_CODE_ATTEN0[0], // ADC2 init code at atten0
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN1[] = {
&ADC2_INIT_CODE_ATTEN1[0], // ADC2 init code at atten1
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN2[] = {
&ADC2_INIT_CODE_ATTEN2[0], // ADC2 init code at atten2
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN3[] = {
&ADC2_INIT_CODE_ATTEN3[0], // ADC2 init code at atten3
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[] = {
&ADC1_CAL_VOL_ATTEN0[0], // ADC1 calibration voltage at atten0
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[] = {
&ADC1_CAL_VOL_ATTEN1[0], // ADC1 calibration voltage at atten1
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[] = {
&ADC1_CAL_VOL_ATTEN2[0], // ADC1 calibration voltage at atten2
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[] = {
&ADC1_CAL_VOL_ATTEN3[0], // ADC1 calibration voltage at atten3
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN0[] = {
&ADC2_CAL_VOL_ATTEN0[0], // ADC2 calibration voltage at atten0
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN1[] = {
&ADC2_CAL_VOL_ATTEN1[0], // ADC2 calibration voltage at atten1
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN2[] = {
&ADC2_CAL_VOL_ATTEN2[0], // ADC2 calibration voltage at atten2
NULL
};
const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[] = {
&USER_DATA[0], // User data
NULL

View File

@ -130,14 +130,31 @@
SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, SPI_PAD_configure D6
SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, SPI_PAD_configure D7
WAFER_VERSION, EFUSE_BLK1, 114, 3, WAFER version 0:A
PKG_VERSION, EFUSE_BLK1, 117, 4, Package version 0:ESP32-S2 1:ESP32-S2FH16 2:ESP32-S2FH32
BLOCK1_VERSION, EFUSE_BLK1, 121, 3, BLOCK1 efuse version 0:No calibration 1:With calibration
SYS_DATA_PART0, EFUSE_BLK1, 126, 66, System configuration
PKG_VERSION, EFUSE_BLK1, 117, 3, Package version
BLOCK1_VERSION, EFUSE_BLK1, 120, 3, BLOCK1 efuse version 0:No calibration 1:With calibration
ADC2_CAL_VOL_ATTEN3, EFUSE_BLK1, 186, 6, ADC2 calibration voltage at atten3
# SYS_DATA_PART1 BLOCK# - System configuration
#######################
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, Optional unique 128-bit ID
BLOCK2_VERSION, EFUSE_BLK2, 132, 3, Version of BLOCK2
BLOCK2_VERSION, EFUSE_BLK2, 128, 4, Version of BLOCK2
TEMP_CALIB, EFUSE_BLK2, 132, 9, Temperature calibration data
OCODE, EFUSE_BLK2, 141, 8, ADC OCode
ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 149, 8, ADC1 init code at atten0
ADC1_INIT_CODE_ATTEN1, EFUSE_BLK2, 157, 6, ADC1 init code at atten1
ADC1_INIT_CODE_ATTEN2, EFUSE_BLK2, 163, 6, ADC1 init code at atten2
ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 169, 6, ADC1 init code at atten3
ADC2_INIT_CODE_ATTEN0, EFUSE_BLK2, 175, 8, ADC2 init code at atten0
ADC2_INIT_CODE_ATTEN1, EFUSE_BLK2, 183, 6, ADC2 init code at atten1
ADC2_INIT_CODE_ATTEN2, EFUSE_BLK2, 189, 6, ADC2 init code at atten2
ADC2_INIT_CODE_ATTEN3, EFUSE_BLK2, 195, 6, ADC2 init code at atten3
ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 201, 8, ADC1 calibration voltage at atten0
ADC1_CAL_VOL_ATTEN1, EFUSE_BLK2, 209, 8, ADC1 calibration voltage at atten1
ADC1_CAL_VOL_ATTEN2, EFUSE_BLK2, 217, 8, ADC1 calibration voltage at atten2
ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 225, 8, ADC1 calibration voltage at atten3
ADC2_CAL_VOL_ATTEN0, EFUSE_BLK2, 233, 8, ADC2 calibration voltage at atten0
ADC2_CAL_VOL_ATTEN1, EFUSE_BLK2, 241, 7, ADC2 calibration voltage at atten1
ADC2_CAL_VOL_ATTEN2, EFUSE_BLK2, 248, 7, ADC2 calibration voltage at atten2
################
USER_DATA, EFUSE_BLK3, 0, 256, User data

Can't render this file because it contains an unexpected character in line 8 and column 53.

View File

@ -0,0 +1,56 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <esp_types.h>
#include <esp_err.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Get the RTC calibration efuse version
*
* @return Version of the stored efuse
*/
int esp_efuse_rtc_calib_get_ver(void);
/**
* @brief Get the init code in the efuse, for the corresponding attenuation.
*
* @param version Version of the stored efuse
* @param adc_unit ADC unit
* @param atten Attenuation of the init code
* @return The init code stored in efuse
*/
uint16_t esp_efuse_rtc_calib_get_init_code(int version, uint32_t adc_unit, int atten);
/**
* @brief Get the calibration digits stored in the efuse, and the corresponding voltage.
*
* @param version Version of the stored efuse
* @param adc_unit ADC unit
* @param atten Attenuation to use
* @param out_digi Output buffer of the digits
* @param out_vol_mv Output of the voltage, in mV
* @return
* - ESP_ERR_INVALID_ARG: If efuse version or attenuation is invalid
* - ESP_OK: if success
*/
esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, uint32_t adc_unit, int atten, uint32_t* out_digi, uint32_t* out_vol_mv);
/**
* @brief Get the temperature sensor calibration number delta_T stored in the efuse.
*
* @param version Version of the stored efuse
*
* @return The specification of temperature sensor calibration number in efuse.
*/
float esp_efuse_rtc_calib_get_cal_temp(int version);
#ifdef __cplusplus
}
#endif

View File

@ -9,7 +9,7 @@ extern "C" {
#endif
// md5_digest_table 2b4b79060b04576a3d189a54f42dd462
// md5_digest_table 0f3dc076304dac1cb56cea03c223d26d
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
// If you want to change some fields, you need to change esp_efuse_table.csv file
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
@ -117,9 +117,26 @@ extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[];
extern const esp_efuse_desc_t* ESP_EFUSE_WAFER_VERSION[];
extern const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[];
extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[];
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN3[];
extern const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[];
extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[];
extern const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[];
extern const esp_efuse_desc_t* ESP_EFUSE_OCODE[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN0[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN1[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN2[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_INIT_CODE_ATTEN3[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN0[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN1[];
extern const esp_efuse_desc_t* ESP_EFUSE_ADC2_CAL_VOL_ATTEN2[];
extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[];
extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA_MAC_CUSTOM[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[];

View File

@ -1,3 +1,4 @@
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
"esp_efuse_fields.c"
"esp_efuse_rtc_calib.c"
"esp_efuse_utility.c")

View File

@ -15,6 +15,12 @@ elseif(${target} STREQUAL "esp32c3")
INCLUDE_DIRS "include"
REQUIRES driver efuse)
elseif(${target} STREQUAL "esp32s3")
idf_component_register(SRCS "esp_adc_cal_esp32s3.c"
INCLUDE_DIRS "include"
REQUIRES driver efuse)
elseif(${target} STREQUAL "esp32h2")
idf_component_register(SRCS "esp_adc_cal_esp32h2.c"
INCLUDE_DIRS "include"

View File

@ -3,4 +3,4 @@
#
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o esp_adc_cal_esp32h2.o
COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o esp_adc_cal_esp32h2.o esp_adc_cal_esp32s3.o

View File

@ -17,6 +17,7 @@
#include "driver/adc.h"
#include "soc/efuse_periph.h"
#include "esp_err.h"
#include "esp_check.h"
#include "assert.h"
#include "esp_adc_cal.h"
@ -82,11 +83,7 @@
#define LUT_HIGH_THRESH (LUT_LOW_THRESH + LUT_ADC_STEP_SIZE)
#define ADC_12_BIT_RES 4096
#define ADC_CAL_CHECK(cond, ret) ({ \
if(!(cond)){ \
return ret; \
} \
})
const static char LOG_TAG[] = "ADC_CALI";
/* ------------------------ Characterization Constants ---------------------- */
static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310};
@ -372,21 +369,20 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
uint32_t *voltage)
{
//Check parameters
ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG);
ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG);
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input");
ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer");
esp_err_t ret = ESP_OK;
int adc_reading;
if (chars->adc_num == ADC_UNIT_1) {
//Check channel is valid on ADC1
ADC_CAL_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, ESP_ERR_INVALID_ARG);
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
adc_reading = adc1_get_raw(channel);
} else {
//Check channel is valid on ADC2
ADC_CAL_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG);
if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) {
return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2
}
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
}
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
return ESP_OK;
return ret;
}

View File

@ -18,19 +18,12 @@
#include "esp_types.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "driver/adc.h"
#include "hal/adc_ll.h"
#include "esp_efuse_rtc_calib.h"
#include "esp_adc_cal.h"
#define ADC_CALIB_CHECK(cond, err_msg, ret) do {\
if (!(cond)) { \
ESP_LOGE(LOG_TAG, err_msg); \
return (ret); \
} \
} while(0)
const static char LOG_TAG[] = "adc_calib";
@ -110,13 +103,13 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
esp_err_t ret;
adc_calib_parsed_info efuse_parsed_data = {0};
// Check parameters
ADC_CALIB_CHECK(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, "Invalid unit num", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
ADC_CALIB_CHECK(chars != NULL, "Invalid characteristic", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
ADC_CALIB_CHECK(bit_width == ADC_WIDTH_BIT_12, "Invalid bit_width", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
ADC_CALIB_CHECK(atten < 4, "Invalid attenuation", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num");
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic");
ESP_RETURN_ON_FALSE(bit_width == ADC_WIDTH_BIT_12, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid bit_width");
ESP_RETURN_ON_FALSE(atten < 4, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation");
int version_num = esp_efuse_rtc_calib_get_ver();
ADC_CALIB_CHECK(version_num == 1, "No calibration efuse burnt", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt");
memset(chars, 0, sizeof(esp_adc_cal_characteristics_t));
@ -140,8 +133,7 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
{
ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG);
assert(chars != NULL);
return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
}
@ -150,21 +142,20 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
uint32_t *voltage)
{
// Check parameters
ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG);
ADC_CALIB_CHECK(voltage != NULL, "No output buffer.", ESP_ERR_INVALID_ARG);
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input");
ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer");
esp_err_t ret = ESP_OK;
int adc_reading;
if (chars->adc_num == ADC_UNIT_1) {
//Check if channel is valid on ADC1
ADC_CALIB_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG);
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
adc_reading = adc1_get_raw(channel);
} else {
//Check if channel is valid on ADC2
ADC_CALIB_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG);
if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) {
return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2
}
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
}
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
return ESP_OK;
return ret;
}

View File

@ -17,6 +17,7 @@
#include "driver/adc.h"
#include "soc/efuse_periph.h"
#include "esp_err.h"
#include "esp_check.h"
#include "assert.h"
#include "esp_adc_cal.h"
#include "esp_efuse.h"
@ -24,11 +25,6 @@
#include "esp_efuse_rtc_table.h"
#include "hal/adc_hal.h"
#define ADC_CAL_CHECK(cond, ret) ({ \
if(!(cond)){ \
return ret; \
} \
})
const static char LOG_TAG[] = "adc_calib";
/* ------------------------ Characterization Constants ---------------------- */
@ -207,8 +203,7 @@ esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
{
ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG);
assert(chars != NULL);
return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
}
@ -217,21 +212,20 @@ esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
uint32_t *voltage)
{
// Check parameters
ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG);
ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG);
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input");
ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer");
esp_err_t ret = ESP_OK;
int adc_reading;
if (chars->adc_num == ADC_UNIT_1) {
//Check if channel is valid on ADC1
ADC_CAL_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, ESP_ERR_INVALID_ARG);
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
adc_reading = adc1_get_raw(channel);
} else {
//Check if channel is valid on ADC2
ADC_CAL_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, ESP_ERR_INVALID_ARG);
if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) {
return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2
}
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
}
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
return ESP_OK;
return ret;
}

View File

@ -0,0 +1,237 @@
/*
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "esp_types.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_check.h"
#include "driver/adc.h"
#include "hal/adc_types.h"
#include "esp_efuse_rtc_calib.h"
#include "esp_adc_cal.h"
const static char LOG_TAG[] = "ADC_CALI";
/* ------------------------ Characterization Constants ---------------------- */
//coeff_a is actually a float number
//it is scaled to put them into uint32_t so that the headers do not have to be changed
static const int coeff_a_scaling = 1000000;
/**
* @note Error Calculation
* Coefficients for calculating the reading voltage error.
* Four sets of coefficients for atten0 ~ atten3 respectively.
*
* For each item, first element is the Coefficient, second element is the Multiple. (Coefficient / Multiple) is the real coefficient.
*
* @note {0,0} stands for unused item
* @note In case of the overflow, these coeffcients are recorded as Absolute Value
* @note For atten0 ~ 2, error = a1 * X^2 + a2 * X + a3; For atten3, error = a1 * X^4 + a2 * X^3 + a3 * X^2 + a4 * X + a5;
*/
const static uint64_t adc_error_coef_atten[4][10][2] = {
{{9798249589, 1e15}, {50871540569528, 1e16}, {3, 1}, {0, 0}, {0, 0}, //ADC1 atten0
{36615265189, 1e16}, {1353548869615, 1e16}, {3, 1}, {0, 0}, {0, 0}}, //ADC2 atten0
{{101379430548, 1e16}, {49393185868806, 1e16}, {3, 1}, {0, 0}, {0, 0}, //ADC1 atten1
{118964995959, 1e16}, {66319894226185, 1e16}, {2, 1}, {0, 0}, {0, 0}}, //ADC2 atten1
{{208385525314, 1e16}, {147640181047414, 1e16}, {2, 1}, {0, 0}, {0, 0}, //ADC1 atten2
{259011467956, 1e16}, {200996773954387, 1e16}, {1, 1}, {0, 0}, {0, 0}}, //ADC2 atten2
{{13515, 1e15}, {70769718, 1e15}, {1297891447611, 1e16}, {644334888647536, 1e16}, {1,1}, //ADC1 atten3
{15038, 1e15}, {79672528, 1e15}, {1478791187119, 1e16}, {755717904943462, 1e16}, {1,1}} //ADC2 atten3
};
const static int32_t adc_error_sign[4][10] = {
{1, -1, -1, 0, 0, //ADC1 atten0
1, 1, -1, 0, 0}, //ADC2 atten0
{1, -1, -1, 0, 0, //ADC1 atten1
1, -1, -1, 0, 0}, //ADC2 atten1
{1, -1, -1, 0, 0, //ADC1 atten2
1, -1, -1, 0, 0}, //ADC2 atten2
{1, -1, 1, -1, -1, //ADC1 atten3
1, -1, 1, -1, 1} //ADC2 atten3
};
/* -------------------- Characterization Helper Data Types ------------------ */
typedef struct {
uint32_t voltage;
uint32_t digi;
} adc_calib_data_ver1_t;
typedef struct {
char version_num;
adc_unit_t adc_num;
adc_atten_t atten_level;
union {
adc_calib_data_ver1_t ver1;
} ref_data;
} adc_calib_info_t;
//To get the reference point (Dout, Vin)
static esp_err_t get_reference_point(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_info_t *calib_info)
{
assert(version_num == 1);
esp_err_t ret;
calib_info->version_num = version_num;
calib_info->adc_num = adc_num;
calib_info->atten_level = atten;
uint32_t voltage = 0;
uint32_t digi = 0;
ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, ((adc_num == ADC_UNIT_1) ? 0 : 1), atten, &digi, &voltage);
assert(ret == ESP_OK);
calib_info->ref_data.ver1.voltage = voltage;
calib_info->ref_data.ver1.digi = digi;
return ret;
}
esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
{
if (source != ESP_ADC_CAL_VAL_EFUSE_TP_FIT) {
return ESP_ERR_NOT_SUPPORTED;
}
uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
if (adc_encoding_version != 1) {
// current version only accepts encoding ver 1.
return ESP_ERR_INVALID_VERSION;
}
return ESP_OK;
}
/*
* Get an expected linear relationship btwn Vin and Dout
*/
static void calculate_characterization_coefficients(const adc_calib_info_t *parsed_data, esp_adc_cal_characteristics_t *chars)
{
chars->coeff_a = coeff_a_scaling * parsed_data->ref_data.ver1.voltage / parsed_data->ref_data.ver1.digi;
chars->coeff_b = 0;
ESP_LOGV(LOG_TAG, "Calib V1, Cal Voltage = %d, Digi out = %d, Coef_a = %d\n", parsed_data->ref_data.ver1.voltage, parsed_data->ref_data.ver1.digi, chars->coeff_a);
}
esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
adc_atten_t atten,
adc_bits_width_t bit_width,
uint32_t default_vref,
esp_adc_cal_characteristics_t *chars)
{
(void) default_vref;
// Check parameters
ESP_RETURN_ON_FALSE(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid unit num");
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Ivalid characteristic");
ESP_RETURN_ON_FALSE(atten < ADC_ATTEN_MAX, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "Invalid attenuation");
int version_num = esp_efuse_rtc_calib_get_ver();
ESP_RETURN_ON_FALSE(version_num == 1, ESP_ADC_CAL_VAL_NOT_SUPPORTED, LOG_TAG, "No calibration efuse burnt");
memset(chars, 0, sizeof(esp_adc_cal_characteristics_t));
adc_calib_info_t calib_info = {0};
// make sure adc is calibrated.
get_reference_point(version_num, adc_num, atten, &calib_info);
calculate_characterization_coefficients(&calib_info, chars);
// Initialize remaining fields
chars->adc_num = adc_num;
chars->atten = atten;
chars->bit_width = bit_width;
return ESP_ADC_CAL_VAL_EFUSE_TP_FIT;
}
static int32_t get_reading_error(uint64_t v_cali_1, uint8_t adc_num, uint8_t atten)
{
if (v_cali_1 == 0) {
return 0;
}
uint8_t term_max = (atten == 3) ? 5 : 3;
int32_t error = 0;
uint64_t coeff = 0;
uint64_t term[5] = {0};
/**
* For atten0 ~ 2:
* error = a1 * X^2 + a2 * X + a3;
*
* For atten3:
* error = a1 * X^4 + a2 * X^3 + a3 * X^2 + a4 * X + a5;
*/
//Calculate all the power beforehand
term[term_max-1] = 1;
term[term_max-2] = v_cali_1;
for (int term_id = term_max - 3; term_id >= 0; term_id--) {
term[term_id] = term[term_id + 1] * v_cali_1;
}
//Calculate each term
uint8_t coef_id_start = (adc_num == ADC_UNIT_1) ? 0 : 5;
for (int i = 0; i < term_max; i++) {
coeff = adc_error_coef_atten[atten][coef_id_start + i][0];
term[i] = term[i] * coeff;
ESP_LOGV(LOG_TAG, "big coef is %llu, big term%d is %llu, coef_id is %d", coeff, i, term[i], coef_id_start + i);
term[i] = term[i] / adc_error_coef_atten[atten][coef_id_start + i][1];
error += (int32_t)term[i] * adc_error_sign[atten][i];
ESP_LOGV(LOG_TAG, "term%d is %llu, error is %d", i, term[i], error);
}
return error;
}
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
{
assert(chars != NULL);
//ADC reading won't exceed 4096. Otherwise the raw reading result is wrong, the next calculation will overflow.
assert(adc_reading < 4096);
uint32_t voltage = 0;
int32_t error = 0;
uint64_t v_cali_1 = 0;
//raw * gradient * 1000000
v_cali_1 = adc_reading * chars->coeff_a;
//convert to real number
v_cali_1 = v_cali_1 / coeff_a_scaling;
ESP_LOGV(LOG_TAG, "v_cali_1 is %llu", v_cali_1);
error = get_reading_error(v_cali_1, chars->adc_num, chars->atten);
voltage = (int32_t)v_cali_1 - error;
return voltage;
}
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
const esp_adc_cal_characteristics_t *chars,
uint32_t *voltage)
{
// Check parameters
ESP_RETURN_ON_FALSE(chars != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No characteristic input");
ESP_RETURN_ON_FALSE(voltage != NULL, ESP_ERR_INVALID_ARG, LOG_TAG, "No output buffer");
esp_err_t ret = ESP_OK;
int adc_reading;
if (chars->adc_num == ADC_UNIT_1) {
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(0), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
adc_reading = adc1_get_raw(channel);
} else {
ESP_RETURN_ON_FALSE(channel < SOC_ADC_CHANNEL_NUM(1), ESP_ERR_INVALID_ARG, LOG_TAG, "Invalid channel");
ret = adc2_get_raw(channel, chars->bit_width, &adc_reading);
}
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
return ret;
}

View File

@ -30,6 +30,7 @@ typedef enum {
ESP_ADC_CAL_VAL_EFUSE_VREF = 0, /**< Characterization based on reference voltage stored in eFuse*/
ESP_ADC_CAL_VAL_EFUSE_TP = 1, /**< Characterization based on Two Point values stored in eFuse*/
ESP_ADC_CAL_VAL_DEFAULT_VREF = 2, /**< Characterization based on default reference voltage*/
ESP_ADC_CAL_VAL_EFUSE_TP_FIT = 3, /**< Characterization based on Two Point values and fitting curve coefficients stored in eFuse */
ESP_ADC_CAL_VAL_MAX,
ESP_ADC_CAL_VAL_NOT_SUPPORTED = ESP_ADC_CAL_VAL_MAX,
} esp_adc_cal_value_t;
@ -48,6 +49,7 @@ typedef struct {
uint32_t vref; /**< Vref used by lookup table*/
const uint32_t *low_curve; /**< Pointer to low Vref curve of lookup table (NULL if unused)*/
const uint32_t *high_curve; /**< Pointer to high Vref curve of lookup table (NULL if unused)*/
uint8_t version; /**< ADC Calibration */
} esp_adc_cal_characteristics_t;
/**
@ -129,8 +131,8 @@ uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_char
*
* @return
* - ESP_OK: ADC read and converted to mV
* - ESP_ERR_TIMEOUT: Error, timed out attempting to read ADC
* - ESP_ERR_INVALID_ARG: Error due to invalid arguments
* - ESP_ERR_INVALID_STATE: Reading result is invalid. Try to read again.
*/
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, const esp_adc_cal_characteristics_t *chars, uint32_t *voltage);

View File

@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
/**
* @file regi2c_lp_bias.h
* @brief Register definitions for analog to calibrate o_code for getting a more precise voltage.
*/
#define I2C_ULP_IR_FORCE_CODE 5
#define I2C_ULP_IR_FORCE_CODE_MSB 6
#define I2C_ULP_IR_FORCE_CODE_LSB 6
//register for OCode
#define I2C_ULP_EXT_CODE 6
#define I2C_ULP_EXT_CODE_MSB 7
#define I2C_ULP_EXT_CODE_LSB 0

View File

@ -0,0 +1,47 @@
/*
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
/**
* @file regi2c_saradc.h
* @brief Register definitions for analog to calibrate initial code for getting a more precise voltage of SAR ADC.
*
* This file lists register fields of SAR, located on an internal configuration
* bus. These definitions are used via macros defined in regi2c_ctrl.h, by
* function in adc_ll.h.
*/
#define I2C_SAR_ADC 0X69
#define I2C_SAR_ADC_HOSTID 0
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define ADC_SAR1_INITIAL_CODE_LOW_ADDR 0x0
#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR 0x3
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0
#define ADC_SAR1_DREF_ADDR 0x2
#define ADC_SAR1_DREF_ADDR_MSB 0x6
#define ADC_SAR1_DREF_ADDR_LSB 0x4
#define ADC_SAR2_DREF_ADDR 0x5
#define ADC_SAR2_DREF_ADDR_MSB 0x6
#define ADC_SAR2_DREF_ADDR_LSB 0x4
#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2
#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0

View File

@ -9,6 +9,12 @@
#include <stdint.h>
#include "regi2c_bbpll.h"
#include "regi2c_dig_reg.h"
#include "regi2c_lp_bias.h"
#include "regi2c_saradc.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Analog function control register */
#define I2C_MST_ANA_CONF0_REG 0x6000E040
@ -73,3 +79,8 @@ void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add,
#define REGI2C_READ(block, reg_add) \
regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add)
#ifdef __cplusplus
}
#endif

View File

@ -17,11 +17,17 @@
#include "regi2c_ctrl.h"
#include "regi2c_ulp.h"
#include "soc_log.h"
#include "esp_err.h"
#include "esp_efuse.h"
#include "esp_efuse_table.h"
#define RTC_CNTL_MEM_FORCE_NOISO (RTC_CNTL_SLOWMEM_FORCE_NOISO | RTC_CNTL_FASTMEM_FORCE_NOISO)
static const char *TAG = "rtcinit";
static void set_ocode_by_efuse(int calib_version);
static void calibrate_ocode(void);
void rtc_init(rtc_config_t cfg)
{
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
@ -59,6 +65,31 @@ void rtc_init(rtc_config_t cfg)
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG_SLEEP, RTC_CNTL_DBIAS_1V10);
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_EXT_RTC_DREG, RTC_CNTL_DBIAS_1V10);
if (cfg.cali_ocode) {
uint32_t blk1_version = 0;
uint32_t blk2_version = 0;
esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_BLOCK1_VERSION, &blk1_version, 3);
if (err != ESP_OK) {
blk1_version = 0;
SOC_LOGW(TAG, "efuse read fail, set default blk1_version: %d\n", blk1_version);
}
err = esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &blk2_version, 4);
if (err != ESP_OK) {
blk2_version = 0;
SOC_LOGW(TAG, "efuse read fail, set default blk2_version: %d\n", blk2_version);
}
if (blk1_version != blk2_version) {
blk1_version = 0;
blk2_version = 0;
SOC_LOGW(TAG, "calibration efuse version does not match, set default version: %d\n", 0);
}
if (blk2_version == 1) {
set_ocode_by_efuse(blk2_version);
} else {
calibrate_ocode();
}
}
if (cfg.clkctl_init) {
//clear CMMU clock force on
CLEAR_PERI_REG_MASK(EXTMEM_CACHE_MMU_POWER_CTRL_REG, EXTMEM_CACHE_MMU_MEM_FORCE_ON);
@ -147,55 +178,6 @@ void rtc_init(rtc_config_t cfg)
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO);
}
if (cfg.cali_ocode) {
/*
Bangap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration(must close PLL).
Method:
1. read current cpu config, save in old_config;
2. switch cpu to xtal because PLL will be closed when o-code calibration;
3. begin o-code calibration;
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
5. set cpu to old-config.
*/
rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get();
rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL;
rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256;
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
if (slow_clk_freq == (rtc_slow_freq_x32k)) {
cal_clk = RTC_CAL_32K_XTAL;
} else if (slow_clk_freq == rtc_slow_freq_8MD256) {
cal_clk = RTC_CAL_8MD256;
}
uint64_t max_delay_time_us = 30000;
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
uint64_t cycle0 = rtc_time_get();
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
uint64_t cycle1 = 0;
rtc_cpu_freq_config_t old_config;
rtc_clk_cpu_freq_get_config(&old_config);
rtc_clk_cpu_freq_set_xtal();
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0);
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1);
bool odone_flag = 0;
bool bg_odone_flag = 0;
while (1) {
odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG);
bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG);
cycle1 = rtc_time_get();
if (odone_flag && bg_odone_flag) {
break;
}
if (cycle1 >= timeout_cycle) {
SOC_LOGW(TAG, "o_code calibration fail\n");
break;
}
}
rtc_clk_cpu_freq_set_config(&old_config);
}
REG_WRITE(RTC_CNTL_INT_ENA_REG, 0);
REG_WRITE(RTC_CNTL_INT_CLR_REG, UINT32_MAX);
@ -236,3 +218,66 @@ void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
val |= RTC_CNTL_SDIO_PD_EN;
REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val);
}
static void set_ocode_by_efuse(int calib_version)
{
assert(calib_version == 1);
// use efuse ocode.
uint32_t ocode;
esp_err_t err = esp_efuse_read_field_blob(ESP_EFUSE_OCODE, &ocode, 8);
assert(err == ESP_OK);
(void) err;
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_EXT_CODE, ocode);
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_CODE, 1);
}
static void calibrate_ocode(void)
{
/*
Bandgap output voltage is not precise when calibrate o-code by hardware sometimes, so need software o-code calibration (must turn off PLL).
Method:
1. read current cpu config, save in old_config;
2. switch cpu to xtal because PLL will be closed when o-code calibration;
3. begin o-code calibration;
4. wait o-code calibration done flag(odone_flag & bg_odone_flag) or timeout;
5. set cpu to old-config.
*/
rtc_slow_freq_t slow_clk_freq = rtc_clk_slow_freq_get();
rtc_slow_freq_t rtc_slow_freq_x32k = RTC_SLOW_FREQ_32K_XTAL;
rtc_slow_freq_t rtc_slow_freq_8MD256 = RTC_SLOW_FREQ_8MD256;
rtc_cal_sel_t cal_clk = RTC_CAL_RTC_MUX;
if (slow_clk_freq == (rtc_slow_freq_x32k)) {
cal_clk = RTC_CAL_32K_XTAL;
} else if (slow_clk_freq == rtc_slow_freq_8MD256) {
cal_clk = RTC_CAL_8MD256;
}
uint64_t max_delay_time_us = 10000;
uint32_t slow_clk_period = rtc_clk_cal(cal_clk, 100);
uint64_t max_delay_cycle = rtc_time_us_to_slowclk(max_delay_time_us, slow_clk_period);
uint64_t cycle0 = rtc_time_get();
uint64_t timeout_cycle = cycle0 + max_delay_cycle;
uint64_t cycle1 = 0;
rtc_cpu_freq_config_t old_config;
rtc_clk_cpu_freq_get_config(&old_config);
rtc_clk_cpu_freq_set_xtal();
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 0);
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_RESETB, 1);
bool odone_flag = 0;
bool bg_odone_flag = 0;
while (1) {
odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_O_DONE_FLAG);
bg_odone_flag = REGI2C_READ_MASK(I2C_ULP, I2C_ULP_BG_O_DONE_FLAG);
cycle1 = rtc_time_get();
if (odone_flag && bg_odone_flag) {
break;
}
if (cycle1 >= timeout_cycle) {
SOC_LOGW(TAG, "o_code calibration fail\n");
break;
}
}
rtc_clk_cpu_freq_set_config(&old_config);
}

View File

@ -10,7 +10,7 @@
#include "soc/soc_caps.h"
#include "soc/rtc.h"
#include "soc/rtc_periph.h"
#if SOC_ADC_SUPPORT_RTC_CTRL
#if SOC_ADC_RTC_CTRL_SUPPORTED
#include "soc/sens_periph.h"
#endif
#include "soc/gpio_periph.h"

View File

@ -76,6 +76,12 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk);
__attribute__((weak)) void esp_clk_init(void)
{
rtc_config_t cfg = RTC_CONFIG_DEFAULT();
soc_reset_reason_t rst_reas;
rst_reas = esp_rom_get_reset_reason(0);
//When power on, we need to set `cali_ocode` to 1, to do a OCode calibration, which will calibrate the rtc reference voltage to a tested value
if (rst_reas == RESET_REASON_CHIP_POWER_ON) {
cfg.cali_ocode = 1;
}
rtc_init(cfg);
assert(rtc_clk_xtal_freq_get() == RTC_XTAL_FREQ_40M);

View File

@ -55,7 +55,7 @@ void adc_hal_arbiter_config(adc_arbiter_t *config)
/*---------------------------------------------------------------
ADC calibration setting
---------------------------------------------------------------*/
#if SOC_ADC_HW_CALIBRATION_V1
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
void adc_hal_calibration_init(adc_ll_num_t adc_n)
{
adc_ll_calibration_init(adc_n);
@ -134,6 +134,7 @@ static uint32_t read_cal_channel(adc_ll_num_t adc_n, int channel)
#define ADC_HAL_CAL_TIMES (10)
#define ADC_HAL_CAL_OFFSET_RANGE (4096)
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd)
{
if (adc_n == ADC_NUM_2) {
@ -191,7 +192,8 @@ uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc
adc_ll_calibration_finish(adc_n);
return ret;
}
#endif //SOC_ADC_HW_CALIBRATION_V1
#endif //#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
//This feature is currently supported on ESP32C3, will be supported on other chips soon

View File

@ -15,6 +15,8 @@
#include <stdio.h>
#include <stdbool.h>
#include "regi2c_ctrl.h"
#include "soc/adc_periph.h"
#include "hal/adc_types.h"
#include "soc/apb_saradc_struct.h"
@ -703,6 +705,18 @@ static inline void adc_ll_disable_sleep_controller(void)
SENS.sar_meas2_mux.sar2_rtc_force = 0;
}
/**
* @brief Set common calibration configuration. Should be shared with other parts (PWDET).
*/
static inline void adc_ll_calibration_init(adc_ll_num_t adc_n)
{
if (adc_n == ADC_NUM_1) {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR1_DREF_ADDR, 4);
} else {
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SAR2_DREF_ADDR, 4);
}
}
/**
* Configure the registers for ADC calibration. You need to call the ``adc_ll_calibration_finish`` interface to resume after calibration.
*
@ -737,7 +751,15 @@ static inline void adc_ll_calibration_finish(adc_ll_num_t adc_n)
*/
static inline void adc_ll_set_calibration_param(adc_ll_num_t adc_n, uint32_t param)
{
abort();
uint8_t msb = param >> 8;
uint8_t lsb = param & 0xFF;
if (adc_n == ADC_NUM_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);
}
}
/**
@ -1015,6 +1037,22 @@ static inline void adc_ll_set_atten(adc_ll_num_t adc_n, adc_channel_t channel, a
}
}
/**
* Get the attenuation of a particular channel on ADCn.
*
* @param adc_n ADC unit.
* @param channel ADCn channel number.
* @return atten The attenuation option.
*/
static inline adc_atten_t adc_ll_get_atten(adc_ll_num_t adc_n, adc_channel_t channel)
{
if (adc_n == ADC_NUM_1) {
return (adc_atten_t)((SENS.sar_atten1 >> (channel * 2)) & 0x3);
} else {
return (adc_atten_t)((SENS.sar_atten2 >> (channel * 2)) & 0x3);
}
}
static inline uint32_t adc_ll_adc1_read(void)
{
//On ESP32S3, valid data width is 12-bit

View File

@ -276,7 +276,7 @@ esp_err_t adc_hal_convert(adc_ll_num_t adc_n, int channel, int *out_raw);
/*---------------------------------------------------------------
ADC calibration setting
---------------------------------------------------------------*/
#if SOC_ADC_HW_CALIBRATION_V1
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
// ESP32-S2, C3 and H2 support HW offset calibration.
/**
@ -312,7 +312,7 @@ void adc_hal_set_calibration_param(adc_ll_num_t adc_n, uint32_t param);
*/
uint32_t adc_hal_self_calibration(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten, bool internal_gnd);
#endif //SOC_ADC_HW_CALIBRATION_V1
#endif //SOC_ADC_CALIBRATION_V1_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
/*---------------------------------------------------------------

View File

@ -75,20 +75,33 @@
#define SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS 1
/*-------------------------- ADC CAPS ----------------------------------------*/
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 8: 10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
#define SOC_ADC_MAX_BITWIDTH (12)
/**
* TO BE REMOVED in !14278
* Check if adc support digital controller (DMA) mode.
* @value
* - 1 : support;
* - 0 : not support;
*/
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 0)
#define SOC_ADC_SUPPORT_RTC_CTRL 1
/*!< SAR ADC Module*/
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 8: 10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16) //Two pattern table, each contains 16 items. Each item takes 1 byte. But only support ADC1 using DMA mode
#define SOC_ADC_DIGI_MIN_BITWIDTH (9)
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (12)
/*-------------------------- BROWNOUT CAPS -----------------------------------*/
#if SOC_CAPS_ECO_VER >= 1

View File

@ -34,19 +34,30 @@
#define SOC_AES_SUPPORT_AES_256 (1)
/*-------------------------- ADC CAPS -------------------------------*/
/*!< SAR ADC Module*/
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) ((PERIPH_NUM==0)? 5 : 1)
#define SOC_ADC_MAX_CHANNEL_NUM (5)
#define SOC_ADC_MAX_BITWIDTH (12)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (1)
#define SOC_ADC_PATT_LEN_MAX (8) /*!< One pattern table, each contains 8 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1
//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
#define SOC_ADC_ARBITER_SUPPORTED 1
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (12)
/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (1)

View File

@ -37,7 +37,7 @@
#define SOC_ADC_MAX_BITWIDTH (12)
#define SOC_ADC_DIGI_FILTER_NUM (2)
#define SOC_ADC_DIGI_MONITOR_NUM (2)
#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) 1
//F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333

View File

@ -62,23 +62,29 @@
#define SOC_XT_WDT_SUPPORTED 1
/*-------------------------- ADC CAPS ----------------------------------------*/
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (16)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
#define SOC_ADC_MAX_BITWIDTH (13)
#define SOC_ADC_HW_CALIBRATION_V1 (1) /*!< support HW offset calibration */
/*!< SAR ADC Module*/
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (32) /*!< Two pattern table, each contains 16 items. Each item takes 1 byte */
#define SOC_ADC_DIGI_MAX_BITWIDTH (12)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (13)
/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
/**
* Check if adc support digital controller (DMA) mode.
* @value
* - 1 : support;
* - 0 : not support;
*/
#define SOC_ADC_SUPPORT_DMA_MODE(PERIPH_NUM) ((PERIPH_NUM==0)? 1: 1)
#define SOC_ADC_SUPPORT_RTC_CTRL 1
#define SOC_ADC_ARBITER_SUPPORTED 1
/*-------------------------- BROWNOUT CAPS -----------------------------------*/
#define SOC_BROWNOUT_RESET_SUPPORTED 1

View File

@ -35,12 +35,29 @@
#define SOC_APPCPU_HAS_CLOCK_GATING_BUG (1)
/*-------------------------- ADC CAPS ----------------------------------------*/
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
#define SOC_ADC_MAX_BITWIDTH (12)
#define SOC_ADC_SUPPORT_RTC_CTRL (1)
#define SOC_ADC_ARBITER_SUPPORTED (1)
/*!< SAR ADC Module*/
#define SOC_ADC_RTC_CTRL_SUPPORTED 1
#define SOC_ADC_ARBITER_SUPPORTED 1
#define SOC_ADC_FILTER_SUPPORTED 1
#define SOC_ADC_MONITOR_SUPPORTED 1
#define SOC_ADC_PERIPH_NUM (2)
#define SOC_ADC_CHANNEL_NUM(PERIPH_NUM) (10)
#define SOC_ADC_MAX_CHANNEL_NUM (10)
/*!< Digital */
#define SOC_ADC_DIGI_CONTROLLER_NUM (2)
#define SOC_ADC_PATT_LEN_MAX (24) //Two pattern table, each contains 12 items. Each item takes 1 byte
#define SOC_ADC_DIGI_MAX_BITWIDTH (13)
/*!< F_sample = F_digi_con / 2 / interval. F_digi_con = 5M for now. 30 <= interva <= 4095 */
#define SOC_ADC_SAMPLE_FREQ_THRES_HIGH 83333
#define SOC_ADC_SAMPLE_FREQ_THRES_LOW 611
/*!< RTC */
#define SOC_ADC_MAX_BITWIDTH (12)
/*!< Calibration */
#define SOC_ADC_CALIBRATION_V1_SUPPORTED (1) /*!< support HW offset calibration version 1*/
/*-------------------------- APB BACKUP DMA CAPS -------------------------------*/
#define SOC_APB_BACKUP_DMA (1)

View File

@ -18,7 +18,7 @@
#include "soc/soc_caps.h"
#include "soc/syscon_struct.h"
#if SOC_ADC_SUPPORT_RTC_CTRL
#if SOC_ADC_RTC_CTRL_SUPPORTED
#include "soc/sens_reg.h"
#include "soc/sens_struct.h"
#endif

View File

@ -27,7 +27,7 @@
#include "soc/rtc_cntl_reg.h"
#include "soc/rtc_cntl_struct.h"
#if SOC_ADC_SUPPORT_RTC_CTRL
#if SOC_ADC_RTC_CTRL_SUPPORTED
#include "soc/sens_struct.h"
#endif