Merge remote-tracking branch 'espressif/master'

This commit is contained in:
Mark Webb-Johnson 2018-03-01 08:49:43 +08:00
commit 0f978bcb45
29 changed files with 898 additions and 419 deletions

View file

@ -224,6 +224,24 @@ esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num);
*/
esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num);
/**
* @brief Helper function to disconnect internal circuits from an RTC IO
* This function disables input, output, pullup, pulldown, and enables
* hold feature for an RTC IO.
* Use this function if an RTC IO needs to be disconnected from internal
* circuits in deep sleep, to minimize leakage current.
*
* In particular, for ESP32-WROVER module, call
* rtc_gpio_isolate(GPIO_NUM_12) before entering deep sleep, to reduce
* deep sleep current.
*
* @param gpio_num GPIO number (e.g. GPIO_NUM_12).
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if GPIO is not an RTC IO
*/
esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num);
/**
* @brief Disable force hold signal for all RTC IOs
*

View file

@ -381,6 +381,19 @@ esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num)
return ESP_OK;
}
esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num)
{
if (rtc_gpio_desc[gpio_num].reg == 0) {
return ESP_ERR_INVALID_ARG;
}
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_pulldown_dis(gpio_num);
rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
rtc_gpio_hold_en(gpio_num);
return ESP_OK;
}
void rtc_gpio_force_hold_dis_all()
{

View file

@ -45,6 +45,15 @@ config SPIRAM_BOOT_INIT
have specific requirements, you'll want to leave this enabled so memory allocated
during boot-up can also be placed in SPI RAM.
config SPIRAM_IGNORE_NOTFOUND
bool "Ignore PSRAM when not found"
default "n"
depends on SPIRAM_BOOT_INIT
help
Normally, if psram initialization is enabled during compile time but not found at runtime, it
is seen as an error making the ESP32 panic. If this is enabled, the ESP32 will keep on
running but will not add the (non-existing) RAM to any allocator.
choice SPIRAM_USE
prompt "SPI RAM access method"
default SPIRAM_USE_MALLOC
@ -100,6 +109,7 @@ endchoice
config SPIRAM_MEMTEST
bool "Run memory test on SPI RAM initialization"
default "y"
depends on SPIRAM_BOOT_INIT
help
Runs a rudimentary memory test on initialization. Aborts when memory test fails. Disable this for
slightly faster startop.

View file

@ -102,6 +102,9 @@ struct object { long placeholder[ 10 ]; };
void __register_frame_info (const void *begin, struct object *ob);
extern char __eh_frame[];
//If CONFIG_SPIRAM_IGNORE_NOTFOUND is set and external RAM is not found or errors out on testing, this is set to false.
static bool s_spiram_okay=true;
/*
* We arrive here after the bootloader finished loading the program from flash. The hardware is mostly uninitialized,
* and the app CPU is in reset. We do have a stack, so we can do the initialization in C.
@ -147,8 +150,13 @@ void IRAM_ATTR call_start_cpu0()
#if CONFIG_SPIRAM_BOOT_INIT
esp_spiram_init_cache();
if (esp_spiram_init() != ESP_OK) {
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
ESP_EARLY_LOGI(TAG, "Failed to init external RAM; continuing without it.");
s_spiram_okay = false;
#else
ESP_EARLY_LOGE(TAG, "Failed to init external RAM!");
abort();
#endif
}
#endif
@ -182,10 +190,12 @@ void IRAM_ATTR call_start_cpu0()
#if CONFIG_SPIRAM_MEMTEST
bool ext_ram_ok=esp_spiram_test();
if (!ext_ram_ok) {
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
abort();
if (s_spiram_okay) {
bool ext_ram_ok=esp_spiram_test();
if (!ext_ram_ok) {
ESP_EARLY_LOGE(TAG, "External RAM failed memory test!");
abort();
}
}
#endif
@ -252,23 +262,25 @@ void start_cpu0_default(void)
esp_err_t err;
esp_setup_syscall_table();
if (s_spiram_okay) {
#if CONFIG_SPIRAM_BOOT_INIT && (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
esp_err_t r=esp_spiram_add_to_heapalloc();
if (r != ESP_OK) {
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
abort();
}
esp_err_t r=esp_spiram_add_to_heapalloc();
if (r != ESP_OK) {
ESP_EARLY_LOGE(TAG, "External RAM could not be added to heap!");
abort();
}
#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
r=esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
if (r != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool!");
abort();
}
r=esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
if (r != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool!");
abort();
}
#endif
#if CONFIG_SPIRAM_USE_MALLOC
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
#endif
#endif
}
//Enable trace memory and immediately start trace.
#if CONFIG_ESP32_TRAX

View file

@ -108,7 +108,9 @@ esp_err_t esp_spiram_init()
esp_err_t r;
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
if (r != ESP_OK) {
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
#endif
return r;
}

View file

@ -0,0 +1,27 @@
menu "ADC-Calibration"
config ADC_CAL_EFUSE_TP_ENABLE
bool "Use Two Point Values"
default "y"
help
Some ESP32s have Two Point calibration values burned into eFuse BLOCK3.
This option will allow the ADC calibration component to characterize the
ADC-Voltage curve using Two Point values if they are available.
config ADC_CAL_EFUSE_VREF_ENABLE
bool "Use eFuse Vref"
default "y"
help
Some ESP32s have Vref burned into eFuse BLOCK0. This option will allow
the ADC calibration component to characterize the ADC-Voltage curve using
eFuse Vref if it is available.
config ADC_CAL_LUT_ENABLE
bool "Use Lookup Tables"
default "y"
help
This option will allow the ADC calibration component to use Lookup Tables
to correct for non-linear behavior in 11db attenuation. Other attenuations
do not exhibit non-linear behavior hence will not be affected by this option.
endmenu # ADC-Calibration

View file

@ -13,99 +13,410 @@
// limitations under the License.
#include <stdint.h>
#include "esp_types.h"
#include "driver/adc.h"
#include "soc/efuse_reg.h"
#include "esp_err.h"
#include "assert.h"
#include "esp_adc_cal.h"
static const esp_adc_cal_lookup_table_t *table_ptrs[4] = {&esp_adc_cal_table_atten_0,
&esp_adc_cal_table_atten_1,
&esp_adc_cal_table_atten_2,
&esp_adc_cal_table_atten_3};
/* ----------------------------- Configuration ------------------------------ */
uint32_t get_adc_vref_from_efuse()
#ifdef CONFIG_ADC_CAL_EFUSE_TP_ENABLE
#define EFUSE_TP_ENABLED 1
#else
#define EFUSE_TP_ENABLED 0
#endif
#ifdef CONFIG_ADC_CAL_EFUSE_VREF_ENABLE
#define EFUSE_VREF_ENABLED 1
#else
#define EFUSE_VREF_ENABLED 0
#endif
#ifdef CONFIG_ADC_CAL_LUT_ENABLE
#define LUT_ENABLED 1
#else
#define LUT_ENABLED 0
#endif
/*
* By default, ESP32s that have Two Point values burned to BLOCK3 will also
* set the EFUSE_BLK3_PART_RESERVE flag to indicate this. However, some ESP32s
* with Two Point values do not set this flag. Set the following definition
* to 0 if this is the case.
*/
#define CHECK_BLK3_FLAG 1
/*
* By default, Vref is burned into eFuse of ESP32s in Sign-Magnitude format.
* However some chips have Vref burned in two's complement format. Set the following
* definition to 1 if this is the case.
*/
#define VREF_FORMAT 0
/* ------------------------------ eFuse Access ----------------------------- */
#define BLK3_RESERVED_REG EFUSE_BLK0_RDATA4_REG
#define VREF_REG EFUSE_BLK0_RDATA4_REG
#define VREF_MASK 0x1F
#define VREF_STEP_SIZE 7
#define VREF_OFFSET 1100
#define TP_REG EFUSE_BLK3_RDATA3_REG
#define TP_LOW1_OFFSET 278
#define TP_LOW2_OFFSET 421
#define TP_LOW_MASK 0x7F
#define TP_LOW_VOLTAGE 150
#define TP_HIGH1_OFFSET 3265
#define TP_HIGH2_OFFSET 3406
#define TP_HIGH_MASK 0x1FF
#define TP_HIGH_VOLTAGE 850
#define TP_STEP_SIZE 4
/* ----------------------- Raw to Voltage Constants ------------------------- */
#define LIN_COEFF_A_SCALE 65536
#define LIN_COEFF_A_ROUND (LIN_COEFF_A_SCALE/2)
#define LUT_VREF_LOW 1000
#define LUT_VREF_HIGH 1200
#define LUT_ADC_STEP_SIZE 64
#define LUT_POINTS 20
#define LUT_LOW_THRESH 2880
#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; \
} \
})
/* ------------------------ Characterization Constants ---------------------- */
static const uint32_t adc1_tp_atten_scale[4] = {65504, 86975, 120389, 224310};
static const uint32_t adc2_tp_atten_scale[4] = {65467, 86861, 120416, 224708};
static const uint32_t adc1_tp_atten_offset[4] = {0, 1, 27, 54};
static const uint32_t adc2_tp_atten_offset[4] = {0, 9, 26, 66};
static const uint32_t adc1_vref_atten_scale[4] = {57431, 76236, 105481, 196602};
static const uint32_t adc2_vref_atten_scale[4] = {57236, 76175, 105678, 197170};
static const uint32_t adc1_vref_atten_offset[4] = {75, 78, 107, 142};
static const uint32_t adc2_vref_atten_offset[4] = {63, 66, 89, 128};
//20 Point lookup tables, covering ADC readings from 2880 to 4096, step size of 64
static const uint32_t lut_adc1_low[LUT_POINTS] = {2240, 2297, 2352, 2405, 2457, 2512, 2564, 2616, 2664, 2709,
2754, 2795, 2832, 2868, 2903, 2937, 2969, 3000, 3030, 3060};
static const uint32_t lut_adc1_high[LUT_POINTS] = {2667, 2706, 2745, 2780, 2813, 2844, 2873, 2901, 2928, 2956,
2982, 3006, 3032, 3059, 3084, 3110, 3135, 3160, 3184, 3209};
static const uint32_t lut_adc2_low[LUT_POINTS] = {2238, 2293, 2347, 2399, 2451, 2507, 2561, 2613, 2662, 2710,
2754, 2792, 2831, 2869, 2904, 2937, 2968, 2999, 3029, 3059};
static const uint32_t lut_adc2_high[LUT_POINTS] = {2657, 2698, 2738, 2774, 2807, 2838, 2867, 2894, 2921, 2946,
2971, 2996, 3020, 3043, 3067, 3092, 3116, 3139, 3162, 3185};
/* ----------------------- EFuse Access Functions --------------------------- */
static bool check_efuse_vref()
{
//TODO: Replaced with read to eFuse once ATE confirms location of 5 bits
return 0;
//Check if Vref is burned in eFuse
return (REG_GET_FIELD(VREF_REG, EFUSE_RD_ADC_VREF) != 0) ? true : false;
}
void esp_adc_cal_get_characteristics(uint32_t v_ref,
static bool check_efuse_tp()
{
//Check if Two Point values are burned in eFuse
if (CHECK_BLK3_FLAG && (REG_GET_FIELD(BLK3_RESERVED_REG, EFUSE_RD_BLK3_PART_RESERVE) == 0)) {
return false;
}
//All TP cal values must be non zero
if ((REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_LOW) != 0) &&
(REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_LOW) != 0) &&
(REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_HIGH) != 0) &&
(REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_HIGH) != 0)) {
return true;
} else {
return false;
}
}
static inline int decode_bits(uint32_t bits, uint32_t mask, bool is_twos_compl)
{
int ret;
if (bits & (~(mask >> 1) & mask)) { //Check sign bit (MSB of mask)
//Negative
if (is_twos_compl) {
ret = -(((~bits) + 1) & (mask >> 1)); //2's complement
} else {
ret = -(bits & (mask >> 1)); //Sign-magnitude
}
} else {
//Positive
ret = bits & (mask >> 1);
}
return ret;
}
static uint32_t read_efuse_vref()
{
//eFuse stores deviation from ideal reference voltage
uint32_t ret = VREF_OFFSET; //Ideal vref
uint32_t bits = REG_GET_FIELD(VREF_REG, EFUSE_ADC_VREF);
ret += decode_bits(bits, VREF_MASK, VREF_FORMAT) * VREF_STEP_SIZE;
return ret; //ADC Vref in mV
}
static uint32_t read_efuse_tp_low(adc_unit_t adc_num)
{
//ADC reading at 150mV stored in two's complement format
uint32_t ret;
uint32_t bits;
if (adc_num == ADC_UNIT_1) {
ret = TP_LOW1_OFFSET;
bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_LOW);
} else {
ret = TP_LOW2_OFFSET;
bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_LOW);
}
ret += decode_bits(bits, TP_LOW_MASK, true) * TP_STEP_SIZE;
return ret; //Reading of ADC at 150mV
}
static uint32_t read_efuse_tp_high(adc_unit_t adc_num)
{
//ADC reading at 850mV stored in two's complement format
uint32_t ret;
uint32_t bits;
if (adc_num == ADC_UNIT_1) {
ret = TP_HIGH1_OFFSET;
bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC1_TP_HIGH);
} else {
ret = TP_HIGH2_OFFSET;
bits = REG_GET_FIELD(TP_REG, EFUSE_RD_ADC2_TP_HIGH);
}
ret += decode_bits(bits, TP_HIGH_MASK, true) * TP_STEP_SIZE;
return ret; //Reading of ADC at 850mV
}
/* ----------------------- Characterization Functions ----------------------- */
static void characterize_using_two_point(adc_unit_t adc_num,
adc_atten_t atten,
uint32_t high,
uint32_t low,
uint32_t *coeff_a,
uint32_t *coeff_b)
{
const uint32_t *atten_scales;
const uint32_t *atten_offsets;
if (adc_num == ADC_UNIT_1) { //Using ADC 1
atten_scales = adc1_tp_atten_scale;
atten_offsets = adc1_tp_atten_offset;
} else { //Using ADC 2
atten_scales = adc2_tp_atten_scale;
atten_offsets = adc2_tp_atten_offset;
}
//Characterize ADC-Voltage curve as y = (coeff_a * x) + coeff_b
uint32_t delta_x = high - low;
uint32_t delta_v = TP_HIGH_VOLTAGE - TP_LOW_VOLTAGE;
//Where coeff_a = (delta_v/delta_x) * atten_scale
*coeff_a = (delta_v * atten_scales[atten] + (delta_x / 2)) / delta_x; //+(delta_x/2) for rounding
//Where coeff_b = high_v - ((delta_v/delta_x) * high_x) + atten_offset
*coeff_b = TP_HIGH_VOLTAGE - ((delta_v * high + (delta_x / 2)) / delta_x) + atten_offsets[atten];
}
static void characterize_using_vref(adc_unit_t adc_num,
adc_atten_t atten,
uint32_t vref,
uint32_t *coeff_a,
uint32_t *coeff_b)
{
const uint32_t *atten_scales;
const uint32_t *atten_offsets;
if (adc_num == ADC_UNIT_1) { //Using ADC 1
atten_scales = adc1_vref_atten_scale;
atten_offsets = adc1_vref_atten_offset;
} else { //Using ADC 2
atten_scales = adc2_vref_atten_scale;
atten_offsets = adc2_vref_atten_offset;
}
//Characterize ADC-Voltage curve as y = (coeff_a * x) + coeff_b
//Where coeff_a = (vref/4096) * atten_scale
*coeff_a = (vref * atten_scales[atten]) / (ADC_12_BIT_RES);
*coeff_b = atten_offsets[atten];
}
/* ------------------------ Conversion Functions --------------------------- */
static uint32_t calculate_voltage_linear(uint32_t adc_reading, uint32_t coeff_a, uint32_t coeff_b)
{
//Where voltage = coeff_a * adc_reading + coeff_b
return (((coeff_a * adc_reading) + LIN_COEFF_A_ROUND) / LIN_COEFF_A_SCALE) + coeff_b;
}
//Only call when ADC reading is above threshold
static uint32_t calculate_voltage_lut(uint32_t adc, uint32_t vref, const uint32_t *low_vref_curve, const uint32_t *high_vref_curve)
{
//Get index of lower bound points of LUT
uint32_t i = (adc - LUT_LOW_THRESH) / LUT_ADC_STEP_SIZE;
//Let the X Axis be Vref, Y axis be ADC reading, and Z be voltage
int x2dist = LUT_VREF_HIGH - vref; //(x2 - x)
int x1dist = vref - LUT_VREF_LOW; //(x - x1)
int y2dist = ((i + 1) * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH - adc; //(y2 - y)
int y1dist = adc - ((i * LUT_ADC_STEP_SIZE) + LUT_LOW_THRESH); //(y - y1)
//For points for bilinear interpolation
int q11 = low_vref_curve[i]; //Lower bound point of low_vref_curve
int q12 = low_vref_curve[i + 1]; //Upper bound point of low_vref_curve
int q21 = high_vref_curve[i]; //Lower bound point of high_vref_curve
int q22 = high_vref_curve[i + 1]; //Upper bound point of high_vref_curve
//Bilinear interpolation
//Where z = 1/((x2-x1)*(y2-y1)) * ( (q11*x2dist*y2dist) + (q21*x1dist*y2dist) + (q12*x2dist*y1dist) + (q22*x1dist*y1dist) )
int voltage = (q11 * x2dist * y2dist) + (q21 * x1dist * y2dist) + (q12 * x2dist * y1dist) + (q22 * x1dist * y1dist);
voltage += ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE) / 2; //Integer division rounding
voltage /= ((LUT_VREF_HIGH - LUT_VREF_LOW) * LUT_ADC_STEP_SIZE); //Divide by ((x2-x1)*(y2-y1))
return (uint32_t)voltage;
}
static inline uint32_t interpolate_two_points(uint32_t y1, uint32_t y2, uint32_t x_step, uint32_t x)
{
//Interpolate between two points (x1,y1) (x2,y2) between 'lower' and 'upper' separated by 'step'
return ((y1 * x_step) + (y2 * x) - (y1 * x) + (x_step / 2)) / x_step;
}
/* ------------------------- Public API ------------------------------------- */
esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
{
if (source == ESP_ADC_CAL_VAL_EFUSE_TP) {
return (check_efuse_tp()) ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
} else if (source == ESP_ADC_CAL_VAL_EFUSE_VREF) {
return (check_efuse_vref()) ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
} else {
return ESP_ERR_INVALID_ARG;
}
}
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)
{
//Check parameters
assert((adc_num == ADC_UNIT_1) || (adc_num == ADC_UNIT_2));
assert(chars != NULL);
assert(bit_width < ADC_WIDTH_MAX);
//Check eFuse if enabled to do so
bool efuse_tp_present = check_efuse_tp();
bool efuse_vref_present = check_efuse_vref();
esp_adc_cal_value_t ret;
if (efuse_tp_present && EFUSE_TP_ENABLED) {
//Characterize based on Two Point values
uint32_t high = read_efuse_tp_high(adc_num);
uint32_t low = read_efuse_tp_low(adc_num);
characterize_using_two_point(adc_num, atten, high, low, &chars->coeff_a, &chars->coeff_b);
ret = ESP_ADC_CAL_VAL_EFUSE_TP;
} else if (efuse_vref_present && EFUSE_VREF_ENABLED) {
//Characterize based on eFuse Vref
uint32_t vref = read_efuse_vref();
characterize_using_vref(adc_num, atten, vref, &chars->coeff_a, &chars->coeff_b);
ret = ESP_ADC_CAL_VAL_EFUSE_VREF;
} else {
//Characterized based on default Vref
characterize_using_vref(adc_num, atten, default_vref, &chars->coeff_a, &chars->coeff_b);
ret = ESP_ADC_CAL_VAL_DEFAULT_VREF;
}
//Initialized remaining fields
chars->adc_num = adc_num;
chars->atten = atten;
chars->bit_width = bit_width;
chars->vref = (efuse_vref_present) ? read_efuse_vref() : default_vref;
//Initialize fields for lookup table if necessary
if (LUT_ENABLED && atten == ADC_ATTEN_DB_11) {
chars->low_curve = (adc_num == ADC_UNIT_1) ? lut_adc1_low : lut_adc2_low;
chars->high_curve = (adc_num == ADC_UNIT_1) ? lut_adc1_high : lut_adc2_high;
} else {
chars->low_curve = NULL;
chars->high_curve = NULL;
}
return ret;
}
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
{
assert(chars != NULL);
//Scale adc_rading if not 12 bits wide
adc_reading = (adc_reading << (ADC_WIDTH_BIT_12 - chars->bit_width));
if (adc_reading > ADC_12_BIT_RES - 1) {
adc_reading = ADC_12_BIT_RES - 1; //Set to 12bit res max
}
if (LUT_ENABLED && (chars->atten == ADC_ATTEN_DB_11) && (adc_reading >= LUT_LOW_THRESH)) { //Check if in non-linear region
//Use lookup table to get voltage in non linear portion of ADC_ATTEN_DB_11
uint32_t lut_voltage = calculate_voltage_lut(adc_reading, chars->vref, chars->low_curve, chars->high_curve);
if (adc_reading <= LUT_HIGH_THRESH) { //If ADC is transitioning from linear region to non-linear region
//Linearly interpolate between linear voltage and lut voltage
uint32_t linear_voltage = calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
return interpolate_two_points(linear_voltage, lut_voltage, LUT_ADC_STEP_SIZE, (adc_reading - LUT_LOW_THRESH));
} else {
return lut_voltage;
}
} else {
return calculate_voltage_linear(adc_reading, chars->coeff_a, chars->coeff_b);
}
}
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
const esp_adc_cal_characteristics_t *chars,
uint32_t *voltage)
{
//Check parameters
ADC_CAL_CHECK(chars != NULL, ESP_ERR_INVALID_ARG);
ADC_CAL_CHECK(voltage != NULL, ESP_ERR_INVALID_ARG);
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);
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
}
}
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
return ESP_OK;
}
/* ------------------------ Deprecated API --------------------------------- */
void esp_adc_cal_get_characteristics(uint32_t vref,
adc_atten_t atten,
adc_bits_width_t bit_width,
esp_adc_cal_characteristics_t *chars)
{
chars->v_ref = v_ref;
chars->table = table_ptrs[atten];
chars->bit_width = bit_width;
if (v_ref >= ADC_CAL_LOW_V_REF) {
chars->gain = ((chars->v_ref - ADC_CAL_LOW_V_REF)
* chars->table->gain_m)
+ chars->table->gain_c;
chars->offset = (((chars->v_ref - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ chars->table->offset_c
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2))
>> ADC_CAL_OFFSET_SCALE; //Bit shift to cancel 2^10 multiplier
chars->ideal_offset = (((ADC_CAL_IDEAL_V_REF - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ chars->table->offset_c
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
>> ADC_CAL_OFFSET_SCALE;
} else { //For case where v_ref is smaller than low bound resulting in negative
chars->gain = chars->table->gain_c
- ((ADC_CAL_LOW_V_REF - chars->v_ref)
* chars->table->gain_m);
chars->offset = (chars->table->offset_c
- ((chars->v_ref - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
>> ADC_CAL_OFFSET_SCALE; //Bit shift to cancel 2^10 multiplier
chars->ideal_offset = (chars->table->offset_c
- ((ADC_CAL_IDEAL_V_REF - ADC_CAL_LOW_V_REF)
* chars->table->offset_m)
+ ((1 << ADC_CAL_OFFSET_SCALE) / 2)) //Rounding
>> ADC_CAL_OFFSET_SCALE;
}
}
static uint32_t esp_adc_cal_interpolate_round(uint32_t lower, uint32_t upper,
uint32_t step, uint32_t point)
{
//Interpolate 'point' between 'lower' and 'upper' seperated by 'step'
return ((lower * step) - (lower * point) + (upper * point) + (step / 2)) / step;
}
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc,
const esp_adc_cal_characteristics_t *chars)
{
//Scale ADC to 12 bit width (0 to 4095)
adc <<= (ADC_WIDTH_BIT_12 - chars->bit_width);
uint32_t i = (adc >> chars->table->bit_shift); //find index for lut voltages
//Refernce LUT to obtain voltage using index
uint32_t voltage = esp_adc_cal_interpolate_round(chars->table->voltage[i],
chars->table->voltage[i + 1],
(1 << chars->table->bit_shift),
adc - (i << chars->table->bit_shift));
/*
* Apply Gain, scaling(bit shift) and offset to interpolated voltage
* v_true = (((v_id - off_id)*gain)*scaling) + off_true
*/
if (voltage > chars->ideal_offset) {
voltage = (voltage - chars->ideal_offset) * chars->gain;
voltage += (1 << ADC_CAL_GAIN_SCALE) / 2; //For rounding when scaled
voltage >>= ADC_CAL_GAIN_SCALE;
voltage += chars->offset;
} else { //For case where voltage is less than ideal offset leading to negative value
voltage = ((chars->ideal_offset - voltage) * chars->gain);
voltage += (1 << ADC_CAL_GAIN_SCALE) / 2; //For rounding when scaled
voltage >>= ADC_CAL_GAIN_SCALE;
voltage = chars->offset - voltage;
}
return voltage;
assert(chars != NULL);
esp_adc_cal_characterize(ADC_UNIT_1, atten, bit_width, vref, chars);
}
uint32_t adc1_to_voltage(adc1_channel_t channel, const esp_adc_cal_characteristics_t *chars)
{
return esp_adc_cal_raw_to_voltage((uint32_t)adc1_get_raw(channel), chars);
assert(chars != NULL);
uint32_t voltage = 0;
esp_adc_cal_get_voltage((adc_channel_t)channel, chars, &voltage);
return voltage;
}

View file

@ -1,96 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed 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.
#include "esp_adc_cal.h"
/**
* Mean error of 219 modules: 3.756418mV
* Max error of 219 modules: 26.314087mV
* Mean of max errors of 219 modules: 7.387282mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_0 = {
.gain_m = 56,
.gain_c = 59928,
.offset_m = 91,
.offset_c = 52798,
.bit_shift = 7,
.voltage = {
54, 90, 120, 150, 180, 209, 241, 271,
301, 330, 360, 391, 421, 450, 480, 511,
541, 571, 601, 630, 660, 690, 720, 750,
780, 809, 839, 870, 900, 929, 959, 988,
1018
}
};
/**
* Mean error of 219 modules: 4.952441mV
* Max error of 219 modules: 38.235321mV
* Mean of max errors of 219 modules: 9.718749mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_1 = {
.gain_m = 57,
.gain_c = 59834,
.offset_m = 108,
.offset_c = 54733,
.bit_shift = 7,
.voltage = {
60, 102, 143, 184, 223, 262, 303, 343,
383, 423, 463, 503, 543, 583, 623, 663,
703, 742, 782, 823, 862, 901, 942, 981,
1022, 1060, 1101, 1141, 1180, 1219, 1259, 1298,
1338
}
};
/**
* Mean error of 219 modules: 6.793558mV
* Max error of 219 modules: 51.435440mV
* Mean of max errors of 219 modules: 13.083121mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_2 = {
.gain_m = 56,
.gain_c = 59927,
.offset_m = 154,
.offset_c = 71995,
.bit_shift = 7,
.voltage = {
82, 138, 194, 250, 305, 360, 417, 473,
529, 584, 639, 696, 751, 806, 861, 917,
971, 1026, 1081, 1136, 1192, 1246, 1301, 1356,
1411, 1466, 1522, 1577, 1632, 1687, 1743, 1799,
1855
}
};
/**
* Mean error of 219 modules: 13.149460mV
* Max error of 219 modules: 97.102951mV
* Mean of max errors of 219 modules: 35.538924mV
*/
const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_3 = {
.gain_m = 33,
.gain_c = 62214,
.offset_m = 610,
.offset_c = 108422,
.bit_shift = 7,
.voltage = {
110, 221, 325, 430, 534, 637, 741, 845,
947, 1049, 1153, 1256, 1358, 1461, 1565, 1670,
1774, 1878, 1983, 2088, 2192, 2293, 2393, 2490,
2580, 2665, 2746, 2820, 2885, 2947, 3007, 3060,
3107
}
};

View file

@ -20,131 +20,130 @@ extern "C" {
#endif
#include <stdint.h>
#include "esp_err.h"
#include "driver/adc.h"
/** @cond */
#define ADC_CAL_GAIN_SCALE 16
#define ADC_CAL_OFFSET_SCALE 10
#define ADC_CAL_IDEAL_V_REF 1100 //In mV
#define ADC_CAL_LOW_V_REF 1000
#define ADC_CAL_HIGH_V_REF 1200
#define ADC_CAL_MIN 0
#define ADC_CAL_MAX 4095
/** @endcond */
/**
* @brief Type of calibration value used in characterization
*/
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_value_t;
/**
* @brief Structure storing Lookup Table
* @brief Structure storing characteristics of an ADC
*
* The Lookup Tables (LUT) of a given attenuation contains 33 equally spaced
* points. The Gain and Offset curves are used to find the appopriate gain and
* offset factor given a reference voltage v_ref.
*
* @note A seperate LUT is provided for each attenuation and are defined in
* esp_adc_cal_lookup_tables.c
* @note Call esp_adc_cal_characterize() to initialize the structure
*/
typedef struct {
uint32_t gain_m; /**<Gradient of Gain Curve */
uint32_t gain_c; /**<Offset of Gain Curve */
uint32_t offset_m; /**<Gradient of Offset Curve */
uint32_t offset_c; /**<Offset of Offset Curve */
uint32_t bit_shift; /**<Bit shift used find corresponding LUT points
given an ADC reading*/
uint32_t voltage[]; /**<Array of voltages in mV representing the
ADC-Voltage curve */
} esp_adc_cal_lookup_table_t;
/**
* @brief Structure storing ADC characteristics of given v_ref
*
* The ADC Characteristics structure stores the gain and offset factors of an
* ESP32 module's ADC. These factors are calculated using the reference voltage,
* and the Gain and Offset curves provided in the lookup tables.
*
* @note Call esp_adc_cal_get_characteristics() to initialize the structure
*
*/
typedef struct {
uint32_t v_ref; /**<Reference Voltage of current ESP32 Module in mV*/
uint32_t gain; /**<Scaling factor used to correct LUT voltages to
current v_ref. Bit shifted by << ADC_CAL_GAIN_SCALE
for uint32 arithmetic */
uint32_t offset; /**<Offset in mV used to correct LUT Voltages to current v_ref */
uint32_t ideal_offset; /**<Offset in mV at the ideal reference voltage */
adc_bits_width_t bit_width; /**<Bit width of ADC e.g. ADC_WIDTH_BIT_12 */
const esp_adc_cal_lookup_table_t *table; /**<Pointer to LUT */
adc_unit_t adc_num; /**< ADC number*/
adc_atten_t atten; /**< ADC attenuation*/
adc_bits_width_t bit_width; /**< ADC bit width */
uint32_t coeff_a; /**< Gradient of ADC-Voltage curve*/
uint32_t coeff_b; /**< Offset of ADC-Voltage curve*/
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)*/
} esp_adc_cal_characteristics_t;
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_0; /**<LUT for atten0 */
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_1; /**<LUT for atten1 */
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_2; /**<LUT for atten2 */
extern const esp_adc_cal_lookup_table_t esp_adc_cal_table_atten_3; /**<LUT for atten3 */
/**
* @brief Checks if ADC calibration values are burned into eFuse
*
* This function checks if ADC reference voltage or Two Point values have been
* burned to the eFuse of the current ESP32
*
* @param value_type Type of calibration value (ESP_ADC_CAL_VAL_EFUSE_VREF or ESP_ADC_CAL_VAL_EFUSE_TP)
*
* @return
* - ESP_OK: The calibration mode is supported in eFuse
* - ESP_ERR_NOT_SUPPORTED: Error, eFuse values are not burned
* - ESP_ERR_INVALID_ARG: Error, invalid argument (ESP_ADC_CAL_VAL_DEFAULT_VREF)
*/
esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t value_type);
/**
* @brief Calculate characteristics of ADC
* @brief Characterize an ADC at a particular attenuation
*
* This function will calculate the gain and offset factors based on the
* reference voltage parameter and the Gain and Offset curve provided in the LUT.
* This function will characterize the ADC at a particular attenuation and generate
* the ADC-Voltage curve in the form of [y = coeff_a * x + coeff_b].
* Characterization can be based on Two Point values, eFuse Vref, or default Vref
* and the calibration values will be prioritized in that order.
*
* @note reference voltage of the ADCs can be routed to GPIO using
* adc2_vref_to_gpio() from the ADC driver
* @note Two Point values and eFuse Vref can be enabled/disabled using menuconfig.
*
* @note The LUT members have been bit shifted by ADC_CAL_GAIN_SCALE or
* ADC_CAL_OFFSET_SCALE to make them uint32_t compatible. This bit shifting will
* accounted for in this function
* @param[in] adc_num ADC to characterize (ADC_UNIT_1 or ADC_UNIT_2)
* @param[in] atten Attenuation to characterize
* @param[in] bit_width Bit width configuration of ADC
* @param[in] default_vref Default ADC reference voltage in mV (used if eFuse values is not available)
* @param[out] chars Pointer to empty structure used to store ADC characteristics
*
* @param[in] v_ref true reference voltage of the ADC in mV (1000 to 1200mV). Nominal
* value for reference voltage is 1100mV.
* @param[in] atten attenuation setting used to select the corresponding lookup table
* @param[in] bit_width bit width of ADC
* @param[out] chars pointer to structure used to store ADC characteristics of module
* @return
* - ESP_ADC_CAL_VAL_EFUSE_VREF: eFuse Vref used for characterization
* - ESP_ADC_CAL_VAL_EFUSE_TP: Two Point value used for characterization (only in Linear Mode)
* - ESP_ADC_CAL_VAL_DEFAULT_VREF: Default Vref used for characterization
*/
void esp_adc_cal_get_characteristics(uint32_t v_ref,
adc_atten_t atten,
adc_bits_width_t bit_width,
esp_adc_cal_characteristics_t *chars);
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);
/**
* @brief Convert raw ADC reading to voltage in mV
* @brief Convert an ADC reading to voltage in mV
*
* This function converts a raw ADC reading to a voltage in mV. This conversion
* is based on the ADC's characteristics. The raw ADC reading is referenced
* against the LUT (pointed to inside characteristics struct) to obtain a voltage.
* Gain and offset factors are then applied to the voltage in order to obtain
* the final result.
* This function converts an ADC reading to a voltage in mV based on the ADC's
* characteristics.
*
* @param[in] adc ADC reading (different bit widths will be handled)
* @param[in] chars pointer to structure containing ADC characteristics of
* the module. Structure also contains pointer to the
* corresponding LUT
* @note Characteristics structure must be initialized before this function
* is called (call esp_adc_cal_characterize())
*
* @return Calculated voltage in mV
* @param[in] adc_reading ADC reading
* @param[in] chars Pointer to initialized structure containing ADC characteristics
*
* @note characteristics structure must be initialized using
* esp_adc_cal_get_characteristics() before this function is used
* @return Voltage in mV
*/
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc,
const esp_adc_cal_characteristics_t *chars);
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars);
/**
* @brief Reads ADC1 and returns voltage in mV
* @brief Reads an ADC and converts the reading to a voltage in mV
*
* This function reads the ADC1 using adc1_get_raw() to obtain a raw ADC
* reading. The reading is then converted into a voltage value using
* esp_adc_cal_raw_to_voltage().
* This function reads an ADC then converts the raw reading to a voltage in mV
* based on the characteristics provided. The ADC that is read is also
* determined by the characteristics.
*
* @param[in] channel Channel of ADC1 to measure
* @param[in] chars Pointer to ADC characteristics struct
* @note The Characteristics structure must be initialized before this
* function is called (call esp_adc_cal_characterize())
*
* @return voltage Calculated voltage in mV
* @param[in] channel ADC Channel to read
* @param[in] chars Pointer to initialized ADC characteristics structure
* @param[out] voltage Pointer to store converted voltage
*
* @note ADC must be initialized using adc1_config_width() and
* adc1_config_channel_atten() before this function is used
*
* @note characteristics structure must be initialized using
* esp_adc_cal_get_characteristics() before this function is used
* @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
*/
uint32_t adc1_to_voltage(adc1_channel_t channel, const esp_adc_cal_characteristics_t *chars);
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel, const esp_adc_cal_characteristics_t *chars, uint32_t *voltage);
/* -------------------------- Deprecated API ------------------------------- */
/** @cond */ //Doxygen command to hide deprecated function from API Reference
/**
* @deprecated ADC1 characterization function. Deprecated in order to accommodate
* ADC2 and eFuse functionality. Use esp_adc_cal_characterize() instead
*/
void esp_adc_cal_get_characteristics(uint32_t vref, adc_atten_t atten, adc_bits_width_t bit_width, esp_adc_cal_characteristics_t *chars) __attribute__((deprecated));
/*
* @deprecated This function reads ADC1 and returns the corrected voltage. This
* has been deprecated in order to accommodate ADC2 support. Use the
* new function esp_adc_cal_get_voltage() instead.
*/
uint32_t adc1_to_voltage(adc1_channel_t channel, const esp_adc_cal_characteristics_t *chars) __attribute__((deprecated));
/** @endcond */
#ifdef __cplusplus
}

View file

@ -295,7 +295,7 @@ config FREERTOS_USE_TRACE_FACILITY
config FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
bool "Enable FreeRTOS stats formatting functions"
depends on FREERTOS_USE_TRACE_FACILITY || FREERTOS_GENERATE_RUN_TIME_STATS
depends on FREERTOS_USE_TRACE_FACILITY
default n
help
If enabled, configUSE_STATS_FORMATTING_FUNCTIONS will be defined as 1 in
@ -305,6 +305,8 @@ config FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
config FREERTOS_GENERATE_RUN_TIME_STATS
bool "Enable FreeRTOS to collect run time stats"
default n
select FREERTOS_USE_TRACE_FACILITY
select FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
help
If enabled, configGENERATE_RUN_TIME_STATS will be defined as 1 in
FreeRTOS. This will allow FreeRTOS to collect information regarding the

View file

@ -49,11 +49,11 @@ esp_err_t esp_ping_set_target(ping_target_id_t opt_id, void *opt_val, uint32_t o
break;
case PING_TARGET_RCV_TIMEO:
ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
ping_option_info->ping_rcv_timeout = (*(uint32_t *)opt_val) * 1000;
ping_option_info->ping_rcv_timeout = (*(uint32_t *)opt_val);
break;
case PING_TARGET_DELAY_TIME:
ESP_PING_CHECK_OPTLEN(opt_len, uint32_t);
ping_option_info->ping_delay = (*(uint32_t *)opt_val) * 1000;
ping_option_info->ping_delay = (*(uint32_t *)opt_val);
break;
case PING_TARGET_ID:
ESP_PING_CHECK_OPTLEN(opt_len, uint16_t);

View file

@ -45,8 +45,8 @@ typedef struct _ping_found {
typedef enum {
PING_TARGET_IP_ADDRESS = 50, /**< target IP address */
PING_TARGET_IP_ADDRESS_COUNT = 51, /**< target IP address total counter */
PING_TARGET_RCV_TIMEO = 52, /**< receive timeout */
PING_TARGET_DELAY_TIME = 53, /**< delay time */
PING_TARGET_RCV_TIMEO = 52, /**< receive timeout in milliseconds */
PING_TARGET_DELAY_TIME = 53, /**< delay time in milliseconds */
PING_TARGET_ID = 54, /**< identifier */
PING_TARGET_RES_FN = 55, /**< ping result callback function */
PING_TARGET_RES_RESET = 56 /**< ping result statistic reset */

View file

@ -335,14 +335,16 @@ int pthread_once(pthread_once_t *once_control, void (*init_routine)(void))
return EINVAL;
}
// Check if once_control belongs to internal DRAM for uxPortCompare to succeed
if (!esp_ptr_internal(once_control)) {
ESP_LOGE(TAG, "%s: once_control should belong to internal DRAM region!", __FUNCTION__);
return EINVAL;
}
uint32_t res = 1;
uxPortCompareSet((uint32_t *) &once_control->init_executed, 0, &res);
#if defined(CONFIG_SPIRAM_SUPPORT)
if (esp_ptr_external_ram(once_control)) {
uxPortCompareSetExtram((uint32_t *) &once_control->init_executed, 0, &res);
} else {
#endif
uxPortCompareSet((uint32_t *) &once_control->init_executed, 0, &res);
#if defined(CONFIG_SPIRAM_SUPPORT)
}
#endif
// Check if compare and set was successful
if (res == 0) {
ESP_LOGV(TAG, "%s: call init_routine %p", __FUNCTION__, once_control);

View file

@ -79,17 +79,23 @@
#define EFUSE_RD_WIFI_MAC_CRC_HIGH_S 0
#define EFUSE_BLK0_RDATA3_REG (DR_REG_EFUSE_BASE + 0x00c)
/* EFUSE_RD_CHIP_VER_REV1 : R/W ;bitpos:[16] ;default: 1'b0 ; */
/* EFUSE_RD_CHIP_VER_REV1 : R/W ;bitpos:[15] ;default: 1'b0 ; */
/*description: bit is set to 1 for rev1 silicon*/
#define EFUSE_RD_CHIP_VER_REV1 (BIT(15))
#define EFUSE_RD_CHIP_VER_REV1_M ((EFUSE_RD_CHIP_VER_REV1_V)<<(EFUSE_RD_CHIP_VER_REV1_S))
#define EFUSE_RD_CHIP_VER_REV1_V 0x1
#define EFUSE_RD_CHIP_VER_REV1_S 15
/* EFUSE_RD_CHIP_VER_RESERVE : R/W ;bitpos:[15:12] ;default: 3'b0 ; */
/* EFUSE_RD_BLK3_PART_RESERVE : R/W ; bitpos:[14] ; default: 1'b0; */
/*description: If set, this bit indicates that BLOCK3[143:96] is reserved for internal use*/
#define EFUSE_RD_BLK3_PART_RESERVE (BIT(14))
#define EFUSE_RD_BLK3_PART_RESERVE_M ((EFUSE_RD_BLK3_PART_RESERVE_V)<<(EFUSE_RD_BLK3_PART_RESERVE_S))
#define EFUSE_RD_BLK3_PART_RESERVE_V 0x1
#define EFUSE_RD_BLK3_PART_RESERVE_S 14
/* EFUSE_RD_CHIP_VER_RESERVE : R/W ;bitpos:[13:12] ;default: 2'b0 ; */
/*description: */
#define EFUSE_RD_CHIP_VER_RESERVE 0x00000007
#define EFUSE_RD_CHIP_VER_RESERVE 0x00000003
#define EFUSE_RD_CHIP_VER_RESERVE_M ((EFUSE_RD_CHIP_VER_RESERVE_V)<<(EFUSE_RD_CHIP_VER_RESERVE_S))
#define EFUSE_RD_CHIP_VER_RESERVE_V 0x7
#define EFUSE_RD_CHIP_VER_RESERVE_V 0x3
#define EFUSE_RD_CHIP_VER_RESERVE_S 12
/* EFUSE_RD_CHIP_VER : R/W ;bitpos:[11:9] ;default: 3'b0 ; */
/*description: chip package */
@ -152,6 +158,15 @@
#define EFUSE_RD_XPD_SDIO_REG_M (BIT(14))
#define EFUSE_RD_XPD_SDIO_REG_V 0x1
#define EFUSE_RD_XPD_SDIO_REG_S 14
/* EFUSE_RD_ADC_VREF : R/W ;bitpos:[12:8] ;default: 5'b0 ; */
/*description: True ADC reference voltage */
#define EFUSE_RD_ADC_VREF 0x0000001F
#define EFUSE_RD_ADC_VREF_M ((EFUSE_RD_ADC_VREF_V)<<(EFUSE_RD_ADC_VREF_S))
#define EFUSE_RD_ADC_VREF_V 0x1F
#define EFUSE_RD_ADC_VREF_S 8
/* Note: EFUSE_ADC_VREF and SDIO_DREFH/M/L share the same address space. Newer
* versions of ESP32 come with EFUSE_ADC_VREF already burned, therefore
* SDIO_DREFH/M/L is only available in older versions of ESP32 */
/* EFUSE_RD_SDIO_DREFL : RO ;bitpos:[13:12] ;default: 2'b0 ; */
/*description: */
#define EFUSE_RD_SDIO_DREFL 0x00000003
@ -314,17 +329,23 @@
#define EFUSE_WIFI_MAC_CRC_HIGH_S 0
#define EFUSE_BLK0_WDATA3_REG (DR_REG_EFUSE_BASE + 0x028)
/* EFUSE_CHIP_VER_REV1 : R/W ;bitpos:[16] ;default: 1'b0 ; */
/* EFUSE_CHIP_VER_REV1 : R/W ;bitpos:[15] ;default: 1'b0 ; */
/*description: */
#define EFUSE_CHIP_VER_REV1 (BIT(15))
#define EFUSE_CHIP_VER_REV1_M ((EFUSE_CHIP_VER_REV1_V)<<(EFUSE_CHIP_VER_REV1_S))
#define EFUSE_CHIP_VER_REV1_V 0x1
#define EFUSE_CHIP_VER_REV1_S 15
/* EFUSE_CHIP_VER_RESERVE : R/W ;bitpos:[15:12] ;default: 3'b0 ; */
/* EFUSE_BLK3_PART_RESERVE : R/W ; bitpos:[14] ; default: 1'b0; */
/*description: If set, this bit indicates that BLOCK3[143:96] is reserved for internal use*/
#define EFUSE_BLK3_PART_RESERVE (BIT(14))
#define EFUSE_BLK3_PART_RESERVE_M ((EFUSE_BLK3_PART_RESERVE_V)<<(EFUSE_BLK3_PART_RESERVE_S))
#define EFUSE_BLK3_PART_RESERVE_V 0x1
#define EFUSE_BLK3_PART_RESERVE_S 14
/* EFUSE_CHIP_VER_RESERVE : R/W ;bitpos:[13:12] ;default: 2'b0 ; */
/*description: */
#define EFUSE_CHIP_VER_RESERVE 0x00000007
#define EFUSE_CHIP_VER_RESERVE 0x00000003
#define EFUSE_CHIP_VER_RESERVE_M ((EFUSE_CHIP_VER_RESERVE_V)<<(EFUSE_CHIP_VER_RESERVE_S))
#define EFUSE_CHIP_VER_RESERVE_V 0x7
#define EFUSE_CHIP_VER_RESERVE_V 0x3
#define EFUSE_CHIP_VER_RESERVE_S 12
/* EFUSE_CHIP_VER : R/W ;bitpos:[11:9] ;default: 3'b0 ; */
/*description: */
@ -382,6 +403,15 @@
#define EFUSE_XPD_SDIO_REG_M (BIT(14))
#define EFUSE_XPD_SDIO_REG_V 0x1
#define EFUSE_XPD_SDIO_REG_S 14
/* EFUSE_ADC_VREF : R/W ;bitpos:[12:8] ;default: 5'b0 ; */
/*description: True ADC reference voltage */
#define EFUSE_ADC_VREF 0x0000001F
#define EFUSE_ADC_VREF_M ((EFUSE_ADC_VREF_V)<<(EFUSE_ADC_VREF_S))
#define EFUSE_ADC_VREF_V 0x1F
#define EFUSE_ADC_VREF_S 8
/* Note: EFUSE_ADC_VREF and SDIO_DREFH/M/L share the same address space. Newer
* versions of ESP32 come with EFUSE_ADC_VREF already burned, therefore
* SDIO_DREFH/M/L is only available in older versions of ESP32 */
/* EFUSE_SDIO_DREFL : R/W ;bitpos:[13:12] ;default: 2'b0 ; */
/*description: */
#define EFUSE_SDIO_DREFL 0x00000003
@ -659,6 +689,8 @@
#define EFUSE_BLK3_DOUT2_V 0xFFFFFFFF
#define EFUSE_BLK3_DOUT2_S 0
/* Note: Newer ESP32s utilize BLK3_DATA3 and parts of BLK3_DATA4 for calibration
* purposes. This usage is indicated by the EFUSE_RD_BLK3_PART_RESERVE bit.*/
#define EFUSE_BLK3_RDATA3_REG (DR_REG_EFUSE_BASE + 0x084)
/* EFUSE_BLK3_DOUT3 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
/*description: read for BLOCK3*/
@ -666,6 +698,30 @@
#define EFUSE_BLK3_DOUT3_M ((EFUSE_BLK3_DOUT3_V)<<(EFUSE_BLK3_DOUT3_S))
#define EFUSE_BLK3_DOUT3_V 0xFFFFFFFF
#define EFUSE_BLK3_DOUT3_S 0
/* EFUSE_RD_ADC2_TP_HIGH : R/W ;bitpos:[31:23] ;default: 9'b0 ; */
/*description: ADC2 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_RD_ADC2_TP_HIGH 0x1FF
#define EFUSE_RD_ADC2_TP_HIGH_M ((EFUSE_RD_ADC2_TP_HIGH_V)<<(EFUSE_RD_ADC2_TP_HIGH_S))
#define EFUSE_RD_ADC2_TP_HIGH_V 0x1FF
#define EFUSE_RD_ADC2_TP_HIGH_S 23
/* EFUSE_RD_ADC2_TP_LOW : R/W ;bitpos:[22:16] ;default: 7'b0 ; */
/*description: ADC2 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_RD_ADC2_TP_LOW 0x7F
#define EFUSE_RD_ADC2_TP_LOW_M ((EFUSE_RD_ADC2_TP_LOW_V)<<(EFUSE_RD_ADC2_TP_LOW_S))
#define EFUSE_RD_ADC2_TP_LOW_V 0x7F
#define EFUSE_RD_ADC2_TP_LOW_S 16
/* EFUSE_RD_ADC1_TP_HIGH : R/W ;bitpos:[15:7] ;default: 9'b0 ; */
/*description: ADC1 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_RD_ADC1_TP_HIGH 0x1FF
#define EFUSE_RD_ADC1_TP_HIGH_M ((EFUSE_RD_ADC1_TP_HIGH_V)<<(EFUSE_RD_ADC1_TP_HIGH_S))
#define EFUSE_RD_ADC1_TP_HIGH_V 0x1FF
#define EFUSE_RD_ADC1_TP_HIGH_S 7
/* EFUSE_RD_ADC1_TP_LOW : R/W ;bitpos:[6:0] ;default: 7'b0 ; */
/*description: ADC1 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_RD_ADC1_TP_LOW 0x7F
#define EFUSE_RD_ADC1_TP_LOW_M ((EFUSE_RD_ADC1_TP_LOW_V)<<(EFUSE_RD_ADC1_TP_LOW_S))
#define EFUSE_RD_ADC1_TP_LOW_V 0x7F
#define EFUSE_RD_ADC1_TP_LOW_S 0
#define EFUSE_BLK3_RDATA4_REG (DR_REG_EFUSE_BASE + 0x088)
/* EFUSE_BLK3_DOUT4 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
@ -674,6 +730,12 @@
#define EFUSE_BLK3_DOUT4_M ((EFUSE_BLK3_DOUT4_V)<<(EFUSE_BLK3_DOUT4_S))
#define EFUSE_BLK3_DOUT4_V 0xFFFFFFFF
#define EFUSE_BLK3_DOUT4_S 0
/* EFUSE_RD_CAL_RESERVED: R/W ; bitpos:[0:15] ; default : 16'h0 ; */
/*description: Reserved for future calibration use. Indicated by EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_RD_CAL_RESERVED 0x0000FFFF
#define EFUSE_RD_CAL_RESERVED_M ((EFUSE_RD_CAL_RESERVED_V)<<(EFUSE_RD_CAL_RESERVED_S))
#define EFUSE_RD_CAL_RESERVED_V 0xFFFF
#define EFUSE_RD_CAL_RESERVED_S 0
#define EFUSE_BLK3_RDATA5_REG (DR_REG_EFUSE_BASE + 0x08c)
/* EFUSE_BLK3_DOUT5 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
@ -851,6 +913,8 @@
#define EFUSE_BLK3_DIN2_V 0xFFFFFFFF
#define EFUSE_BLK3_DIN2_S 0
/* Note: Newer ESP32s utilize BLK3_DATA3 and parts of BLK3_DATA4 for calibration
* purposes. This usage is indicated by the EFUSE_RD_BLK3_PART_RESERVE bit.*/
#define EFUSE_BLK3_WDATA3_REG (DR_REG_EFUSE_BASE + 0x0e4)
/* EFUSE_BLK3_DIN3 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
/*description: program for BLOCK3*/
@ -858,6 +922,30 @@
#define EFUSE_BLK3_DIN3_M ((EFUSE_BLK3_DIN3_V)<<(EFUSE_BLK3_DIN3_S))
#define EFUSE_BLK3_DIN3_V 0xFFFFFFFF
#define EFUSE_BLK3_DIN3_S 0
/* EFUSE_ADC2_TP_HIGH : R/W ;bitpos:[31:23] ;default: 9'b0 ; */
/*description: ADC2 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_ADC2_TP_HIGH 0x1FF
#define EFUSE_ADC2_TP_HIGH_M ((EFUSE_ADC2_TP_HIGH_V)<<(EFUSE_ADC2_TP_HIGH_S))
#define EFUSE_ADC2_TP_HIGH_V 0x1FF
#define EFUSE_ADC2_TP_HIGH_S 23
/* EFUSE_ADC2_TP_LOW : R/W ;bitpos:[22:16] ;default: 7'b0 ; */
/*description: ADC2 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_ADC2_TP_LOW 0x7F
#define EFUSE_ADC2_TP_LOW_M ((EFUSE_ADC2_TP_LOW_V)<<(EFUSE_ADC2_TP_LOW_S))
#define EFUSE_ADC2_TP_LOW_V 0x7F
#define EFUSE_ADC2_TP_LOW_S 16
/* EFUSE_ADC1_TP_HIGH : R/W ;bitpos:[15:7] ;default: 9'b0 ; */
/*description: ADC1 Two Point calibration high point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_ADC1_TP_HIGH 0x1FF
#define EFUSE_ADC1_TP_HIGH_M ((EFUSE_ADC1_TP_HIGH_V)<<(EFUSE_ADC1_TP_HIGH_S))
#define EFUSE_ADC1_TP_HIGH_V 0x1FF
#define EFUSE_ADC1_TP_HIGH_S 7
/* EFUSE_ADC1_TP_LOW : R/W ;bitpos:[6:0] ;default: 7'b0 ; */
/*description: ADC1 Two Point calibration low point. Only valid if EFUSE_RD_BLK3_PART_RESERVE */
#define EFUSE_ADC1_TP_LOW 0x7F
#define EFUSE_ADC1_TP_LOW_M ((EFUSE_ADC1_TP_LOW_V)<<(EFUSE_ADC1_TP_LOW_S))
#define EFUSE_ADC1_TP_LOW_V 0x7F
#define EFUSE_ADC1_TP_LOW_S 0
#define EFUSE_BLK3_WDATA4_REG (DR_REG_EFUSE_BASE + 0x0e8)
/* EFUSE_BLK3_DIN4 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
@ -866,6 +954,12 @@
#define EFUSE_BLK3_DIN4_M ((EFUSE_BLK3_DIN4_V)<<(EFUSE_BLK3_DIN4_S))
#define EFUSE_BLK3_DIN4_V 0xFFFFFFFF
#define EFUSE_BLK3_DIN4_S 0
/* EFUSE_CAL_RESERVED: R/W ; bitpos:[0:15] ; default : 16'h0 ; */
/*description: Reserved for future calibration use. Indicated by EFUSE_BLK3_PART_RESERVE */
#define EFUSE_CAL_RESERVED 0x0000FFFF
#define EFUSE_CAL_RESERVED_M ((EFUSE_CAL_RESERVED_V)<<(EFUSE_CAL_RESERVED_S))
#define EFUSE_CAL_RESERVED_V 0xFFFF
#define EFUSE_CAL_RESERVED_S 0
#define EFUSE_BLK3_WDATA5_REG (DR_REG_EFUSE_BASE + 0x0ec)
/* EFUSE_BLK3_DIN5 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */

View file

@ -117,10 +117,15 @@ rtc_vddsdio_config_t rtc_vddsdio_get_config()
result.force = 0;
result.enable = (efuse_reg & EFUSE_RD_XPD_SDIO_REG_M) >> EFUSE_RD_XPD_SDIO_REG_S;
result.tieh = (efuse_reg & EFUSE_RD_SDIO_TIEH_M) >> EFUSE_RD_SDIO_TIEH_S;
// in this case, DREFH/M/L are also set from EFUSE
result.drefh = (efuse_reg & EFUSE_RD_SDIO_DREFH_M) >> EFUSE_RD_SDIO_DREFH_S;
result.drefm = (efuse_reg & EFUSE_RD_SDIO_DREFM_M) >> EFUSE_RD_SDIO_DREFM_S;
result.drefl = (efuse_reg & EFUSE_RD_SDIO_DREFL_M) >> EFUSE_RD_SDIO_DREFL_S;
//DREFH/M/L eFuse are used for EFUSE_ADC_VREF instead. Therefore tuning
//will only be available on older chips that don't have EFUSE_ADC_VREF
if(REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG ,EFUSE_RD_BLK3_PART_RESERVE) == 0){
//BLK3_PART_RESERVE indicates the presence of EFUSE_ADC_VREF
// in this case, DREFH/M/L are also set from EFUSE
result.drefh = (efuse_reg & EFUSE_RD_SDIO_DREFH_M) >> EFUSE_RD_SDIO_DREFH_S;
result.drefm = (efuse_reg & EFUSE_RD_SDIO_DREFM_M) >> EFUSE_RD_SDIO_DREFM_S;
result.drefl = (efuse_reg & EFUSE_RD_SDIO_DREFL_M) >> EFUSE_RD_SDIO_DREFL_S;
}
return result;
}

BIN
docs/_static/adc-noise-graph.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 108 KiB

BIN
docs/_static/adc-vref-graph.jpg vendored Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

View file

@ -85,56 +85,87 @@ The value read in both these examples is 12 bits wide (range 0-4095).
.. _adc-api-adc-calibration:
Minimizing Noise
----------------
The ESP32 ADC can be sensitive to noise leading to large discrepancies in ADC readings. To minimize noise, users may connect a 0.1uF capacitor to the ADC input pad in use. Multisampling may also be used to further mitigate the effects of noise.
.. figure:: ../../_static/adc-noise-graph.jpg
:align: center
:alt: ADC noise mitigation
Graph illustrating noise mitigation using capacitor and multisampling of 64 samples.
ADC Calibration
---------------
The :component_file:`esp_adc_cal/include/esp_adc_cal.h` API provides functions to correct for differences in measured voltages caused by non-ideal ADC reference voltages in ESP32s. The ideal ADC reference voltage is 1100 mV however the reference voltage of different ESP32s can range from 1000 mV to 1200 mV.
The :component_file:`esp_adc_cal/include/esp_adc_cal.h` API provides functions to correct for differences in measured voltages caused by variation of ADC reference voltages (Vref) between chips. Per design the ADC reference voltage is 1100mV, however the true reference voltage can range from 1000mV to 1200mV amongst different ESP32s.
Correcting the measured voltage using this API involves referencing a lookup table of voltages. The voltage obtained from the lookup table is then scaled and shifted by a gain and offset factor that is based on the ADC's reference voltage. This is done with function :cpp:func:`esp_adc_cal_get_characteristics`.
.. figure:: ../../_static/adc-vref-graph.jpg
:align: center
:alt: ADC reference voltage comparison
Graph illustrating effect of differing reference voltages on the ADC voltage curve.
The reference voltage of the ADCs can be routed to certain GPIOs and measured manually using the ADC drivers :cpp:func:`adc2_vref_to_gpio` function.
Correcting ADC readings using this API involves characterizing one of the ADCs at a given attenuation to obtain a characteristics curve (ADC-Voltage curve) that takes into account the difference in ADC reference voltage. The characteristics curve is in the form of ``y = coeff_a * x + coeff_b`` and is used to convert ADC readings to voltages in mV. Calculation of the characteristics curve is based on calibration values which can be stored in eFuse or provided by the user.
Example of Reading Calibrated Values
------------------------------------
Calibration Values
^^^^^^^^^^^^^^^^^^
Reading the ADC and obtaining a result in mV::
Calibration values are used to generate characteristic curves that account for the unique ADC reference voltage of a particular ESP32. There are currently three sources of calibration values. The availability of these calibration values will depend on the type and production date of the ESP32 chip/module.
#include <driver/adc.h>
#include <esp_adc_cal.h>
**Two Point** values represent each of the ADCs readings at 150mV and 850mV. These values are measured and burned into eFuse ``BLOCK3`` during factory calibration.
**eFuse Vref** represents the true ADC reference voltage. This value is measured and burned into eFuse ``BLOCK0`` during factory calibration.
**Default Vref** is an estimate of the ADC reference voltage provided by the user as a parameter during characterization. If Two Point or eFuse Vref values are unavailable, **Default Vref** will be used.
Application Example
^^^^^^^^^^^^^^^^^^^
For a full example see esp-idf: :example:`peripherals/adc`
Characterizing an ADC at a particular attenuation::
#include "driver/adc.h"
#include "esp_adc_cal.h"
...
#define V_REF 1100 // ADC reference voltage
// Configure ADC
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_CHANNEL_6, ADC_ATTEN_11db);
// Calculate ADC characteristics i.e. gain and offset factors
esp_adc_cal_characteristics_t characteristics;
esp_adc_cal_get_characteristics(V_REF, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, &characteristics);
// Read ADC and obtain result in mV
uint32_t voltage = adc1_to_voltage(ADC1_CHANNEL_6, &characteristics);
printf("%d mV\n",voltage);
Routing ADC reference voltage to GPIO, so it can be manually measured and entered in function :cpp:func:`esp_adc_cal_get_characteristics`::
//Characterize ADC at particular atten
esp_adc_cal_characteristics_t *adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
//Check type of calibration value used to characterize ADC
if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
printf("eFuse Vref");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
printf("Two Point");
} else {
printf("Default");
}
#include <driver/adc.h>
#include <driver/gpio.h>
#include <esp_err.h>
Reading an ADC then converting the reading to a voltage::
#include "driver/adc.h"
#include "esp_adc_cal.h"
...
uint32_t reading = adc1_get_raw(ADC1_CHANNEL_5);
uint32_t voltage = esp_adc_cal_raw_to_voltage(reading, adc_chars);
Routing ADC reference voltage to GPIO, so it can be manually measured (for **Default Vref**)::
#include "driver/adc.h"
...
esp_err_t status = adc2_vref_to_gpio(GPIO_NUM_25);
if (status == ESP_OK){
if (status == ESP_OK) {
printf("v_ref routed to GPIO\n");
}else{
} else {
printf("failed to route v_ref\n");
}
An example of using the ADC driver and obtaining calibrated measurements is available in esp-idf: :example:`peripherals/adc`
GPIO Lookup Macros
------------------

View file

@ -122,6 +122,20 @@ The following function can be used to enter deep sleep once wakeup sources are c
.. doxygenfunction:: esp_deep_sleep_start
Configuring IOs
---------------
Some ESP32 IOs have internal pullups or pulldowns, which are enabled by default. If an external circuit drives this pin in deep sleep mode, current consumption may increase due to current flowing through these pullups and pulldowns.
To isolate a pin, preventing extra current draw, call :cpp:func:`rtc_gpio_isolate` function.
For example, on ESP32-WROVER module, GPIO12 is pulled up externally. GPIO12 also has an internal pulldown in the ESP32 chip. This means that in deep sleep, some current will flow through these external and internal resistors, increasing deep sleep current above the minimal possible value.
Add the following code before :cpp:func:`esp_deep_sleep_start` to remove this extra current:
```c++
rtc_gpio_isolate(GPIO_NUM_12);
```
Checking sleep wakeup cause
---------------------------

View file

@ -1,13 +1,13 @@
ESP32-DevKitC Getting Started Guide
===================================
ESP32-DevKitC V4 Getting Started Guide
======================================
This user guide shows how to get started with ESP32-DevKitC development board.
This user guide shows how to get started with ESP32-DevKitC V4 development board. For description of other versions of the ESP32-DevKitC check :doc:`../hw-reference/index`.
What You Need
-------------
* 1 × :ref:`ESP32-DevKitC board <get-started-esp32-devkitc-board-front>`
* 1 × :ref:`ESP32-DevKitC V4 board <get-started-esp32-devkitc-board-front>`
* 1 × USB A / micro USB B cable
* 1 × PC loaded with Windows, Linux or Mac OS
@ -15,7 +15,7 @@ What You Need
Overview
--------
ESP32-DevKitC is a small-sized ESP32-based development board produced by `Espressif <https://espressif.com>`_. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Developers can connect these pins to peripherals as needed. Standard headers also make development easy and convenient when using a breadboard.
ESP32-DevKitC V4 is a small-sized ESP32-based development board produced by `Espressif <https://espressif.com>`_. Most of the I/O pins are broken out to the pin headers on both sides for easy interfacing. Developers can connect these pins to peripherals as needed. Standard headers also make development easy and convenient when using a breadboard.
The board comes in two versions, either with :ref:`esp-modules-and-boards-esp-wroom-32` or :ref:`esp-modules-and-boards-esp32-wrover` module soldered.
@ -23,10 +23,10 @@ The board comes in two versions, either with :ref:`esp-modules-and-boards-esp-wr
Functional Description
----------------------
The following list and figure below describe key components, interfaces and controls of ESP32-DevKitC board.
The following list and figure below describe key components, interfaces and controls of ESP32-DevKitC V4 board.
ESP-WROOM-32
:ref:`esp-modules-and-boards-esp-wroom-32` module soldered to the ESP32-DevKitC board.
:ref:`esp-modules-and-boards-esp-wroom-32` module soldered to the ESP32-DevKitC V4 board.
ESP32-WROVER
Optionally :ref:`esp-modules-and-boards-esp32-wrover` module may be soldered instead of the ESP-WROOM-32.
USB-UART Bridge
@ -55,10 +55,10 @@ I/O
.. figure:: ../_static/esp32-devkitc-functional-overview.jpg
:align: center
:alt: ESP32-DevKitC with ESP-WROOM-32 module soldered
:alt: ESP32-DevKitC V4 with ESP-WROOM-32 module soldered
:figclass: align-center
ESP32-DevKitC with ESP-WROOM-32 module soldered
ESP32-DevKitC V4 with ESP-WROOM-32 module soldered
Power Supply Options
@ -102,7 +102,7 @@ Board Dimensions
Related Documents
-----------------
* `ESP32-DevKitC schematic <https://dl.espressif.com/dl/schematics/esp32_devkitc_v4-sch.pdf>`_ (PDF)
* `ESP32-DevKitC V4 schematic <https://dl.espressif.com/dl/schematics/esp32_devkitc_v4-sch.pdf>`_ (PDF)
* `ESP32 Datasheet <https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf>`_ (PDF)
* `ESP-WROOM-32 Datasheet <https://espressif.com/sites/default/files/documentation/esp-wroom-32_datasheet_en.pdf>`_ (PDF)
* `ESP32-WROVER Datasheet <https://espressif.com/sites/default/files/documentation/esp32-wrover_datasheet_en.pdf>`_ (PDF)

View file

@ -10,42 +10,83 @@
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_system.h"
#include "esp_adc_cal.h"
/*Note: Different ESP32 modules may have different reference voltages varying from
* 1000mV to 1200mV. Use #define GET_VREF to route v_ref to a GPIO
*/
#define V_REF 1100
#define ADC1_TEST_CHANNEL (ADC1_CHANNEL_6) //GPIO 34
//#define V_REF_TO_GPIO //Remove comment on define to route v_ref to GPIO
#define DEFAULT_VREF 1100 //Use adc2_vref_to_gpio() to obtain a better estimate
#define NO_OF_SAMPLES 64 //Multisampling
void app_main(void)
static esp_adc_cal_characteristics_t *adc_chars;
static const adc_channel_t channel = ADC_CHANNEL_6; //GPIO34 if ADC1, GPIO14 if ADC2
static const adc_atten_t atten = ADC_ATTEN_DB_0;
static const adc_unit_t unit = ADC_UNIT_1;
static void check_efuse()
{
#ifndef V_REF_TO_GPIO
//Init ADC and Characteristics
esp_adc_cal_characteristics_t characteristics;
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_DB_0);
esp_adc_cal_get_characteristics(V_REF, ADC_ATTEN_DB_0, ADC_WIDTH_BIT_12, &characteristics);
uint32_t voltage;
while(1){
voltage = adc1_to_voltage(ADC1_TEST_CHANNEL, &characteristics);
printf("%d mV\n",voltage);
//Check TP is burned into eFuse
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_TP) == ESP_OK) {
printf("eFuse Two Point: Supported\n");
} else {
printf("eFuse Two Point: NOT supported\n");
}
//Check Vref is burned into eFuse
if (esp_adc_cal_check_efuse(ESP_ADC_CAL_VAL_EFUSE_VREF) == ESP_OK) {
printf("eFuse Vref: Supported\n");
} else {
printf("eFuse Vref: NOT supported\n");
}
}
static void print_char_val_type(esp_adc_cal_value_t val_type)
{
if (val_type == ESP_ADC_CAL_VAL_EFUSE_TP) {
printf("Characterized using Two Point Value\n");
} else if (val_type == ESP_ADC_CAL_VAL_EFUSE_VREF) {
printf("Characterized using eFuse Vref\n");
} else {
printf("Characterized using Default Vref\n");
}
}
void app_main()
{
//Check if Two Point or Vref are burned into eFuse
check_efuse();
//Configure ADC
if (unit == ADC_UNIT_1) {
adc1_config_width(ADC_WIDTH_BIT_12);
adc1_config_channel_atten(channel, atten);
} else {
adc2_config_channel_atten((adc2_channel_t)channel, atten);
}
//Characterize ADC
adc_chars = calloc(1, sizeof(esp_adc_cal_characteristics_t));
esp_adc_cal_value_t val_type = esp_adc_cal_characterize(unit, atten, ADC_WIDTH_BIT_12, DEFAULT_VREF, adc_chars);
print_char_val_type(val_type);
//Continuously sample ADC1
while (1) {
uint32_t adc_reading = 0;
//Multisampling
for (int i = 0; i < NO_OF_SAMPLES; i++) {
if (unit == ADC_UNIT_1) {
adc_reading += adc1_get_raw((adc1_channel_t)channel);
} else {
int raw;
adc2_get_raw((adc2_channel_t)channel, ADC_WIDTH_BIT_12, &raw);
adc_reading += raw;
}
}
adc_reading /= NO_OF_SAMPLES;
//Convert adc_reading to voltage in mV
uint32_t voltage = esp_adc_cal_raw_to_voltage(adc_reading, adc_chars);
printf("Raw: %d\tVoltage: %dmV\n", adc_reading, voltage);
vTaskDelay(pdMS_TO_TICKS(1000));
}
#else
//Get v_ref
esp_err_t status;
status = adc2_vref_to_gpio(GPIO_NUM_25);
if (status == ESP_OK){
printf("v_ref routed to GPIO\n");
}else{
printf("failed to route v_ref\n");
}
fflush(stdout);
#endif
}

View file

@ -269,9 +269,10 @@ void adc_read_task(void* arg)
adc1_config_width(ADC_WIDTH_12Bit);
adc1_config_channel_atten(ADC1_TEST_CHANNEL, ADC_ATTEN_11db);
esp_adc_cal_characteristics_t characteristics;
esp_adc_cal_get_characteristics(V_REF, ADC_ATTEN_11db, ADC_WIDTH_12Bit, &characteristics);
esp_adc_cal_characterize(ADC_UNIT_1, ADC_ATTEN_DB_11, ADC_WIDTH_BIT_12, V_REF, &characteristics);
while(1) {
uint32_t voltage = adc1_to_voltage(ADC1_TEST_CHANNEL, &characteristics);
uint32_t voltage;
esp_adc_cal_get_voltage(ADC1_TEST_CHANNEL, &characteristics, &voltage);
ESP_LOGI(TAG, "%d mV", voltage);
vTaskDelay(200 / portTICK_RATE_MS);
}

View file

@ -277,7 +277,7 @@ void aws_iot_task(void *param) {
continue;
}
ESP_LOGI(TAG, "-->sleep");
ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
vTaskDelay(1000 / portTICK_RATE_MS);
sprintf(cPayload, "%s : %d ", "hello from ESP32 (QOS0)", i++);
paramsQOS0.payloadLen = strlen(cPayload);
@ -328,10 +328,5 @@ void app_main()
ESP_ERROR_CHECK( err );
initialise_wifi();
#ifdef CONFIG_MBEDTLS_DEBUG
const size_t stack_size = 36*1024;
#else
const size_t stack_size = 36*1024;
#endif
xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", stack_size, NULL, 5, NULL, 1);
xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1);
}

View file

@ -125,18 +125,6 @@ static const char * ROOT_CA_PATH = CONFIG_EXAMPLE_ROOT_CA_PATH;
#error "Invalid method for loading certs"
#endif
/**
* @brief Default MQTT HOST URL is pulled from the aws_iot_config.h which
* uses menuconfig to find a default.
*/
char HostAddress[255] = AWS_IOT_MQTT_HOST;
/**
* @brief Default MQTT port is pulled from the aws_iot_config.h which
* uses menuconfig to find a default.
*/
uint32_t port = AWS_IOT_MQTT_PORT;
static esp_err_t event_handler(void *ctx, system_event_t *event)
{
switch(event->event_id) {
@ -325,6 +313,8 @@ void aws_iot_task(void *param) {
}
}
ESP_LOGI(TAG, "*****************************************************************************************");
ESP_LOGI(TAG, "Stack remaining for task '%s' is %d bytes", pcTaskGetTaskName(NULL), uxTaskGetStackHighWaterMark(NULL));
vTaskDelay(1000 / portTICK_RATE_MS);
}
@ -374,5 +364,5 @@ void app_main()
initialise_wifi();
/* Temporarily pin task to core, due to FPU uncertainty */
xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 16384+1024, NULL, 5, NULL, 1);
xTaskCreatePinnedToCore(&aws_iot_task, "aws_iot_task", 9216, NULL, 5, NULL, 1);
}

View file

@ -155,6 +155,7 @@ static int deep_sleep(int argc, char** argv)
ESP_ERROR_CHECK( esp_sleep_enable_ext1_wakeup(1ULL << io_num, level) );
}
rtc_gpio_isolate(GPIO_NUM_12);
esp_deep_sleep_start();
}

View file

@ -157,6 +157,11 @@ void app_main()
esp_sleep_enable_ulp_wakeup();
#endif
// Isolate GPIO12 pin from external circuits. This is needed for modules
// which have an external pull-up resistor on GPIO12 (such as ESP32-WROVER)
// to minimize current consumption.
rtc_gpio_isolate(GPIO_NUM_12);
printf("Entering deep sleep\n");
gettimeofday(&sleep_enter_time, NULL);

View file

@ -68,11 +68,13 @@ static void init_ulp_program()
rtc_gpio_pullup_dis(gpio_num);
rtc_gpio_hold_en(gpio_num);
/* Disable pullup on GPIO15, in case it is connected to ground to suppress
* boot messages.
/* Disconnect GPIO12 and GPIO15 to remove current drain through
* pullup/pulldown resistors.
* GPIO15 may be connected to ground to suppress boot messages.
* GPIO12 may be pulled high to select flash voltage.
*/
rtc_gpio_pullup_dis(GPIO_NUM_15);
rtc_gpio_hold_en(GPIO_NUM_15);
rtc_gpio_isolate(GPIO_NUM_12);
rtc_gpio_isolate(GPIO_NUM_15);
/* Set ULP wake up period to T = 20ms (3095 cycles of RTC_SLOW_CLK clock).
* Minimum pulse width has to be T * (ulp_debounce_counter + 1) = 80ms.

View file

@ -74,11 +74,13 @@ static void init_ulp_program()
/* Set ULP wake up period to 20ms */
ulp_set_wakeup_period(0, 20000);
/* Disable pullup on GPIO15, in case it is connected to ground to suppress
* boot messages.
/* Disconnect GPIO12 and GPIO15 to remove current drain through
* pullup/pulldown resistors.
* GPIO15 may be connected to ground to suppress boot messages.
* GPIO12 may be pulled high to select flash voltage.
*/
rtc_gpio_pullup_dis(GPIO_NUM_15);
rtc_gpio_hold_en(GPIO_NUM_15);
rtc_gpio_isolate(GPIO_NUM_12);
rtc_gpio_isolate(GPIO_NUM_15);
}
static void start_ulp_program()

View file

@ -580,15 +580,13 @@ if os.name == 'nt':
self.matched = b''
def _output_write(self, data):
# Windows 10 bug since the Fall Creators Update, sometimes writing to console randomly fails
# (but usually succeeds afterwards, it seems.)
# Ref https://github.com/espressif/esp-idf/issues/1136
for tries in range(3):
try:
self.output.write(data)
return
except IOError:
pass
try:
self.output.write(data)
except IOError:
# Windows 10 bug since the Fall Creators Update, sometimes writing to console randomly throws
# an exception (however, the character is still written to the screen)
# Ref https://github.com/espressif/esp-idf/issues/1136
pass
def write(self, data):
for b in data: