ulp-riscv: add support for using ADC as well as an example show-casing it.

pull/9408/head
Marius Vikhammer 2022-02-28 18:12:28 +08:00
rodzic 627b171a3c
commit e8b5096f52
33 zmienionych plików z 415 dodań i 29 usunięć

Wyświetl plik

@ -83,8 +83,6 @@ void bootloader_random_disable(void)
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_ENT_RTC_ADDR, 0);
REGI2C_WRITE_MASK(I2C_SAR_ADC, ADC_SARADC_DTEST_RTC_ADDR, 0);
//Stop SAR ADC clock
CLEAR_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_SARADC_CLK_EN);
//Power off SAR ADC
REG_SET_FIELD(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0);
//return to ADC RTC controller

Wyświetl plik

@ -225,7 +225,7 @@ esp_err_t adc2_pad_get_io_num(adc2_channel_t channel, gpio_num_t *gpio_num)
#if SOC_ADC_RTC_CTRL_SUPPORTED
#if SOC_ADC_CALIBRATION_V1_SUPPORTED
static uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan)
uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan)
{
adc_atten_t atten = adc_ll_get_atten(adc_n, chan);
extern uint32_t adc_get_calibration_offset(adc_unit_t adc_n, adc_atten_t atten);

Wyświetl plik

@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Enables the use of ADC and temperature sensor in monitor (ULP) mode
*
* @note This state is kept in RTC memory and will keep its value after a deep sleep wakeup
*
*/
void esp_sleep_enable_adc_tsens_monitor(bool enable);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -182,7 +182,7 @@ static bool s_light_sleep_wakeup = false;
static portMUX_TYPE spinlock_rtc_deep_sleep = portMUX_INITIALIZER_UNLOCKED;
static const char *TAG = "sleep";
static bool s_adc_tsen_enabled = false;
static RTC_FAST_ATTR bool s_adc_tsen_enabled = false;
//in this mode, 2uA is saved, but RTC memory can't use at high temperature, and RTCIO can't be used as INPUT.
static bool s_ultra_low_enabled = false;
@ -1386,7 +1386,7 @@ void esp_deep_sleep_disable_rom_logging(void)
rtc_suppress_rom_log();
}
void rtc_sleep_enable_adc_tesn_monitor(bool enable)
void esp_sleep_enable_adc_tsens_monitor(bool enable)
{
s_adc_tsen_enabled = enable;
}

Wyświetl plik

@ -8,12 +8,12 @@ This test app is to enter 7 different sub power modes we have, so that the power
Currently there are 6 sub power modes, 3 for deepsleep and 3 for lightsleep. Show as below (priority from high to low).
## Deepsleep
1. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mode, call `rtc_sleep_enable_adc_tesn_monitor`.
1. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mode, call `esp_sleep_enable_adc_tsens_monitor`.
2. Default mode.
3. Ultra low power mode. To enable this mode, call `rtc_sleep_enable_ultra_low`. Note if mode 1 has higher priority than this.
## Lightsleep
1. Mode for using 40 MHz XTAL in lightsleep. To enable this mode, call `esp_sleep_pd_config(ESP_PD_DOMAIN_XTAL, ESP_PD_OPTION_ON)`.
2. Mode for using 8M clock by digital system (peripherals). To enable this mode, initialize LEDC with 8M clock source.
3. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mdoe, call `rtc_sleep_enable_adc_tesn_monitor`.
3. Mode for ADC/Temp Sensor in monitor mode (ULP). To enable this mdoe, call `esp_sleep_enable_adc_tsens_monitor`.
4. Default mode.

Wyświetl plik

@ -16,6 +16,7 @@
#include "soc/soc_caps.h"
#include "driver/ledc.h"
#include "soc/rtc.h"
#include "esp_private/esp_sleep_internal.h"
static const char TAG[] = "rtc_power";
@ -30,8 +31,7 @@ TEST_CASE("Power Test: Deepsleep (with ADC/TSEN in monitor)", "[pm]")
{
rtc_dig_clk8m_disable(); //This is workaround for bootloader not disable 8M as digital clock source
extern void rtc_sleep_enable_adc_tesn_monitor(bool);
rtc_sleep_enable_adc_tesn_monitor(true);
esp_sleep_enable_adc_tsens_monitor(true);
test_deepsleep();
}
@ -108,8 +108,8 @@ TEST_CASE("Power Test: Lightsleep (with ADC/TSEN in monitor)", "[pm]")
{
rtc_dig_clk8m_disable(); //This is workaround for bootloader not disable 8M as digital clock source
extern void rtc_sleep_enable_adc_tesn_monitor(bool);
rtc_sleep_enable_adc_tesn_monitor(true);
extern void esp_sleep_enable_adc_tsens_monitor(bool);
esp_sleep_enable_adc_tsens_monitor(true);
test_lightsleep();
}

Wyświetl plik

@ -31,7 +31,9 @@ extern void abort(void);
#endif
#endif
#if CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 1 // silent
#if IS_ULP_COCPU
#define HAL_ASSERT(__e) ((void)(__e))
#elif CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 1 // silent
#define HAL_ASSERT(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : abort())
#elif CONFIG_HAL_DEFAULT_ASSERTION_LEVEL == 2 // full assertion
#define HAL_ASSERT(__e) (__builtin_expect(!!(__e), 1) ? (void)0 : __assert_func(__FILE__, __LINE__, __ASSERT_FUNC, #__e))

Wyświetl plik

@ -23,7 +23,8 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
elseif(CONFIG_ULP_COPROC_TYPE_RISCV)
list(APPEND srcs
"ulp_riscv/ulp_riscv.c")
"ulp_riscv/ulp_riscv.c"
"ulp_riscv/ulp_riscv_adc.c")
list(APPEND includes
ulp_riscv/include)
@ -31,4 +32,5 @@ if(CONFIG_SOC_ULP_SUPPORTED OR CONFIG_SOC_RISCV_COPROC_SUPPORTED)
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${includes})
INCLUDE_DIRS ${includes}
REQUIRES driver)

Wyświetl plik

@ -71,8 +71,9 @@ add_custom_target(${ULP_APP_NAME}_ld_script
if(ULP_COCPU_IS_RISCV)
#risc-v ulp uses extra files for building:
list(APPEND ULP_S_SOURCES
"${IDF_PATH}/components/ulp/ulp_riscv/start.S"
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_riscv_utils.c")
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/start.S"
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_adc.c"
"${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/ulp_riscv_utils.c")
#dummy loop to force pre-processed linker file generation:
foreach(ulp_s_source ${ULP_S_SOURCES})
@ -95,7 +96,9 @@ if(ULP_COCPU_IS_RISCV)
list(APPEND EXTRA_LINKER_ARGS "-Wl,--gc-sections")
list(APPEND EXTRA_LINKER_ARGS "-Wl,-Map=\"${CMAKE_CURRENT_BINARY_DIR}/${ULP_APP_NAME}.map\"")
#Makes the csr utillies for riscv visible:
target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/include")
target_include_directories(${ULP_APP_NAME} PRIVATE "${IDF_PATH}/components/ulp/ulp_riscv/ulp_core/include")
target_link_libraries(${ULP_APP_NAME} "-T \"${IDF_PATH}/components/ulp/ld/${IDF_TARGET}.periperals.ld\"")
target_compile_definitions(${ULP_APP_NAME} PRIVATE IS_ULP_COCPU)
else()

Wyświetl plik

@ -0,0 +1,9 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
PROVIDE ( RTCCNTL = 0x8000 );
PROVIDE ( RTCIO = 0xA400 );
PROVIDE ( SENS = 0xC800 );

Wyświetl plik

@ -0,0 +1,9 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
PROVIDE ( RTCCNTL = 0x8000 );
PROVIDE ( RTCIO = 0xA400 );
PROVIDE ( SENS = 0xC800 );

Wyświetl plik

@ -58,6 +58,7 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs)
-DULP_APP_NAME=${app_name}
-DCOMPONENT_DIR=${COMPONENT_DIR}
-DCOMPONENT_INCLUDES=$<TARGET_PROPERTY:${COMPONENT_TARGET},INTERFACE_INCLUDE_DIRECTORIES>
-DIDF_TARGET=${idf_target}
-DIDF_PATH=${idf_path}
-DSDKCONFIG_HEADER=${SDKCONFIG_HEADER}
-DPYTHON=${python}

Wyświetl plik

@ -1,8 +1,3 @@
if(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3")
#Disabled for now due to RTC bug IDF-4801
return()
endif()
if(NOT CONFIG_ULP_COPROC_TYPE_FSM AND NOT CONFIG_ULP_COPROC_TYPE_RISCV)
# Nothing to test if no co-processor enabled
return()

Wyświetl plik

@ -6,4 +6,4 @@
#pragma once
#warning Contents of ulp_riscv/ulp_riscv.h have been deprecated. Please include the header which contains the actual definitions you are trying to use, e.g. "ulp_riscv_register_ops.h".
#include "../ulp_riscv_register_ops.h"
#include "../../ulp_core/include/ulp_riscv_register_ops.h"

Wyświetl plik

@ -6,5 +6,5 @@
#pragma once
#warning "ulp_riscv_gpio.h has been moved one level up. Please include the file without the ulp_riscv prefix."
#include "../ulp_riscv_gpio.h"
#warning "ulp_riscv_gpio.h has been moved. Please include the file without the ulp_riscv prefix."
#include "../../ulp_core/include/ulp_riscv_gpio.h"

Wyświetl plik

@ -5,5 +5,5 @@
*/
#pragma once
#warning ulp_riscv_register_ops.h has been moved one level up. Please include the file without the ulp_riscv prefix.
#include "../ulp_riscv_register_ops.h"
#warning ulp_riscv_register_ops.h has been moved. Please include the file without the ulp_riscv prefix.
#include "../../ulp_core/include/ulp_riscv_register_ops.h"

Wyświetl plik

@ -5,5 +5,5 @@
*/
#pragma once
#warning ulp_riscv_utils.h has been moved one level up. Please include the file without the ulp_riscv prefix.
#include "../ulp_riscv_utils.h"
#warning ulp_riscv_utils.h has been moved. Please include the file without the ulp_riscv prefix.
#include "../../ulp_core/include/ulp_riscv_utils.h"

Wyświetl plik

@ -0,0 +1,29 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/adc_types.h"
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct {
adc_unit_t adc_n; // ADC Unit
adc_channel_t channel; // ADC channel
adc_atten_t atten; // ADC channel attenuation
adc_bits_width_t width; // ADC bit width, only used for ADC unit 1
} ulp_riscv_adc_cfg_t; // ULP Riscv ADC configuration parameters
/**
* @brief Initialize and calibrate the ADC for use by ULP RISCV
*
* @param cfg Configuration parameters
* @return esp_err_t ESP_OK for successful.
*/
esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg);

Wyświetl plik

@ -0,0 +1,32 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "hal/adc_ll.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Start an ADC conversion and get the converted value.
*
* @note Will block until the conversion is completed
*
* @note ADC should be initilized for ULP by main CPU by calling ulp_riscv_adc_init()
* before calling this.
*
* @param adc_n ADC unit.
* @param channel ADC channel number.
*
* @return Converted value, -1 if conversion failed
*/
int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel);
#ifdef __cplusplus
}
#endif

Wyświetl plik

@ -1,3 +1,8 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
.section .text.vectors
.global irq_vector
.global reset_vector

Wyświetl plik

@ -0,0 +1,30 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_riscv_adc.h"
#include "hal/adc_ll.h"
int32_t ulp_riscv_adc_read_channel(adc_unit_t adc_n, int channel)
{
uint32_t event = (adc_n == ADC_UNIT_1) ? ADC_LL_EVENT_ADC1_ONESHOT_DONE : ADC_LL_EVENT_ADC2_ONESHOT_DONE;
adc_oneshot_ll_clear_event(event);
adc_oneshot_ll_disable_all_unit();
adc_oneshot_ll_enable(adc_n);
adc_oneshot_ll_set_channel(adc_n, channel);
adc_oneshot_ll_start(adc_n);
while (adc_oneshot_ll_get_event(event) != true) {
;
}
int32_t out_raw = adc_oneshot_ll_get_raw_result(adc_n);
if (adc_oneshot_ll_raw_check_valid(adc_n, out_raw) == false) {
return -1;
}
//HW workaround: when enabling periph clock, this should be false
adc_oneshot_ll_disable_all_unit();
return out_raw;
}

Wyświetl plik

@ -0,0 +1,42 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "ulp_riscv_adc.h"
#include "esp_err.h"
#include "esp_check.h"
#include "esp_log.h"
#include "driver/adc.h"
#include "hal/adc_hal_common.h"
#include "esp_private/esp_sleep_internal.h"
/* Will be refactored when ADC NG is merged, TODO IDF-5513 */
extern esp_err_t adc1_rtc_mode_acquire(void);
extern uint32_t get_calibration_offset(adc_unit_t adc_n, adc_channel_t chan);
static const char *TAG = "ulp_riscv_adc";
esp_err_t ulp_riscv_adc_init(const ulp_riscv_adc_cfg_t *cfg)
{
esp_err_t ret = ESP_OK;
ESP_GOTO_ON_FALSE(cfg, ESP_ERR_INVALID_ARG, err, TAG, "cfg == NULL");
ESP_GOTO_ON_FALSE(cfg->adc_n == ADC_UNIT_1, ESP_ERR_INVALID_ARG, err, TAG, "Only ADC_UNIT_1 is supported for now");
adc1_config_channel_atten(cfg->channel, cfg->atten);
adc1_config_width(cfg->width);
//Calibrate the ADC
uint32_t cal_val = get_calibration_offset(cfg->adc_n, cfg->channel);
adc_hal_set_calibration_param(cfg->adc_n, cal_val);
adc1_rtc_mode_acquire();
esp_sleep_enable_adc_tsens_monitor(true);
err:
return ret;
}

Wyświetl plik

@ -0,0 +1,6 @@
# The following lines of boilerplate have to be in your project's CMakeLists
# in this exact order for cmake to work correctly
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(ulp-riscv-adc-example)

Wyświetl plik

@ -0,0 +1,32 @@
| Supported Targets | ESP32-S3 |
| ----------------- | -------- |
# ULP-RISC-V ADC Example
This example demonstrates how to use the ULP-RISC-V coprocessor to poll the ADC in deep sleep.
The ULP program periodically measures the input voltage on EXAMPLE_ADC_CHANNEL (by default ADC1 channel 0, GPIO1 on both ESP32-S2 and ESP32-S3). The voltage is compared to an upper threshold. If the voltage is higher than the threshold, the ULP wakes up the system.
By default, the threshold is set to 1.75V, approximately.
In this example, you need to connect a voltage source (e.g. a DC power supply) to the GPIO pin corresponding to the ADC channel specified in `ulp/example_config.h` (see the macros defined on the top of the header file). Feel free to modify the channel setting.
### Hardware Required
* A development board with a SOC which has a RISC-V ULP coprocessor (e.g., ESP32-S2 Saola)
* A USB cable for power supply and programming
## Example output
Below is the output from this example.
```
Not a ULP-RISC-V wakeup (cause = 0), initializing it!
Entering in deep sleep
ULP-RISC-V woke up the main CPU
Threshold: high = 2000
Value = 4095 was above threshold
Entering in deep sleep
```

Wyświetl plik

@ -0,0 +1,25 @@
idf_component_register(SRCS "ulp_riscv_adc_example_main.c"
INCLUDE_DIRS ""
REQUIRES soc ulp esp_adc_cal)
#
# ULP support additions to component CMakeLists.txt.
#
# 1. The ULP app name must be unique (if multiple components use ULP).
set(ulp_app_name ulp_${COMPONENT_NAME})
#
# 2. Specify all C and Assembly source files.
# Files should be placed into a separate directory (in this case, ulp/),
# which should not be added to COMPONENT_SRCS.
set(ulp_riscv_sources "ulp/main.c")
#
# 3. List all the component source files which include automatically
# generated ULP export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "ulp_riscv_adc_example_main.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
# values above.
ulp_embed_binary(${ulp_app_name} "${ulp_riscv_sources}" "${ulp_exp_dep_srcs}")

Wyświetl plik

@ -0,0 +1,16 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#pragma once
#include "hal/adc_types.h"
#define EXAMPLE_ADC_CHANNEL ADC_CHANNEL_0
#define EXAMPLE_ADC_UNIT ADC_UNIT_1
#define EXAMPLE_ADC_ATTEN ADC_ATTEN_DB_11
#define EXAMPLE_ADC_WIDTH ADC_WIDTH_BIT_12
/* Set high threshold, approx. 1.75V*/
#define EXAMPLE_ADC_TRESHOLD 2000

Wyświetl plik

@ -0,0 +1,36 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* ULP-RISC-V example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
This code runs on ULP-RISC-V coprocessor
*/
#include <stdint.h>
#include "ulp_riscv_utils.h"
#include "ulp_riscv_adc_ulp_core.h"
#include "example_config.h"
uint32_t adc_threshold = EXAMPLE_ADC_TRESHOLD;
int32_t wakeup_result;
int main (void)
{
int32_t last_result = ulp_riscv_adc_read_channel(EXAMPLE_ADC_UNIT, EXAMPLE_ADC_CHANNEL);
if (last_result > adc_threshold) {
wakeup_result = last_result;
ulp_riscv_wakeup_main_processor();
}
return 0;
}

Wyświetl plik

@ -0,0 +1,79 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
/* ULP riscv example
This example code is in the Public Domain (or CC0 licensed, at your option.)
Unless required by applicable law or agreed to in writing, this
software is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
CONDITIONS OF ANY KIND, either express or implied.
*/
#include <stdio.h>
#include "esp_sleep.h"
#include "ulp_riscv.h"
#include "ulp_riscv_adc.h"
#include "ulp_main.h"
#include "ulp/example_config.h"
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
static void init_ulp_program(void);
void app_main(void)
{
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
/* not a wakeup from ULP, load the firmware */
if ((cause != ESP_SLEEP_WAKEUP_ULP) && (cause != ESP_SLEEP_WAKEUP_TIMER)) {
printf("Not a ULP-RISC-V wakeup (cause = %d), initializing it! \n", cause);
init_ulp_program();
}
/* ULP Risc-V read and detected a temperature above the limit */
if (cause == ESP_SLEEP_WAKEUP_ULP) {
printf("ULP-RISC-V woke up the main CPU\n");
printf("Threshold: high = %d\n", ulp_adc_threshold);
printf("Value = %d was above threshold\n", ulp_wakeup_result);
}
/* Go back to sleep, only the ULP Risc-V will run */
printf("Entering in deep sleep\n\n");
/* RTC peripheral power domain needs to be kept on to keep SAR ADC related configs during sleep */
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON);
ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup());
esp_deep_sleep_start();
}
static void init_ulp_program(void)
{
ulp_riscv_adc_cfg_t cfg = {
.adc_n = EXAMPLE_ADC_UNIT,
.channel = EXAMPLE_ADC_CHANNEL,
.width = EXAMPLE_ADC_WIDTH,
.atten = EXAMPLE_ADC_ATTEN,
};
ESP_ERROR_CHECK(ulp_riscv_adc_init(&cfg));
esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
ESP_ERROR_CHECK(err);
/* The first argument is the period index, which is not used by the ULP-RISC-V timer
* The second argument is the period in microseconds, which gives a wakeup time period of: 20ms
*/
ulp_set_wakeup_period(0, 20000);
/* Start the program */
err = ulp_riscv_run();
ESP_ERROR_CHECK(err);
}

Wyświetl plik

@ -0,0 +1,9 @@
# Enable ULP
CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RISCV=y
CONFIG_ULP_COPROC_RESERVE_MEM=4096
# Set log level to Warning to produce clean output
CONFIG_BOOTLOADER_LOG_LEVEL_WARN=y
CONFIG_BOOTLOADER_LOG_LEVEL=2
CONFIG_LOG_DEFAULT_LEVEL_WARN=y
CONFIG_LOG_DEFAULT_LEVEL=2