bringup esp32-s3 on FPGA

This commit is contained in:
morris 2020-07-29 13:13:51 +08:00
parent d7e50c6457
commit 61f89b97c6
97 changed files with 4037 additions and 816 deletions

View File

@ -20,6 +20,8 @@
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#endif
///////////////////////////////////////////////////////////////////////////////

View File

@ -1,3 +1,5 @@
idf_build_get_property(target IDF_TARGET)
set(srcs
"adc_common.c"
"dac_common.c"
@ -23,9 +25,9 @@ set(srcs
"twai.c"
"uart.c")
set(includes "include")
set(includes "include" "${target}/include")
if(IDF_TARGET STREQUAL "esp32")
if(${target} STREQUAL "esp32")
# SDMMC and MCPWM are in ESP32 only.
list(APPEND srcs "mcpwm.c"
"sdio_slave.c"
@ -37,7 +39,7 @@ if(IDF_TARGET STREQUAL "esp32")
list(APPEND includes "esp32/include")
endif()
if(IDF_TARGET STREQUAL "esp32s2")
if(${target} STREQUAL "esp32s2")
list(APPEND srcs "esp32s2/rtc_tempsensor.c"
"esp32s2/touch_sensor.c"
"esp32s2/adc.c"

View File

@ -82,7 +82,7 @@ static _lock_t adc2_wifi_lock;
#define ADC2_WIFI_LOCK_TRY_ACQUIRE() _lock_try_acquire( &adc2_wifi_lock )
#define ADC2_WIFI_LOCK_CHECK() ((uint32_t *)adc2_wifi_lock != NULL)
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
#define ADC2_WIFI_LOCK_ACQUIRE()
#define ADC2_WIFI_LOCK_RELEASE()
@ -101,7 +101,7 @@ static _lock_t adc1_dma_lock;
#define ADC1_DMA_LOCK_ACQUIRE() _lock_acquire( &adc1_dma_lock )
#define ADC1_DMA_LOCK_RELEASE() _lock_release( &adc1_dma_lock )
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#ifdef CONFIG_PM_ENABLE
static esp_pm_lock_handle_t s_adc2_arbiter_lock;
#endif //CONFIG_PM_ENABLE
@ -209,7 +209,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
{
#ifdef CONFIG_IDF_TARGET_ESP32
ADC_CHECK(bits < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
ADC_CHECK(bits == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
#endif
@ -231,7 +231,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
* @return
* - ESP_OK Success
*/
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
esp_err_t adc_rtc_reset(void)
{
ADC_ENTER_CRITICAL();
@ -284,7 +284,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
{
#ifdef CONFIG_IDF_TARGET_ESP32
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
#endif
@ -341,13 +341,17 @@ int adc1_get_raw(adc1_channel_t channel)
adc_power_on();
ADC_ENTER_CRITICAL();
#ifdef CONFIG_IDF_TARGET_ESP32S2
#ifdef CONFIG_IDF_TARGET_ESP32
adc_hal_hall_disable(); //Disable other peripherals.
adc_hal_amp_disable(); //Currently the LNA is not open, close it by default.
#endif
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
adc_set_init_code(ADC_NUM_1, channel); // calibration for adc
#endif
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); //Set controller
adc_hal_convert(ADC_NUM_1, channel, &adc_value); //Start conversion, For ADC1, the data always valid.
ADC_EXIT_CRITICAL();
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
adc_hal_rtc_reset(); //Reset FSM of rtc controller
#endif
@ -434,7 +438,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
static inline void adc2_config_width(adc_bits_width_t width_bit)
{
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#ifdef CONFIG_PM_ENABLE
/* Lock APB clock. */
if (s_adc2_arbiter_lock == NULL) {
@ -455,7 +459,7 @@ static inline void adc2_dac_disable( adc2_channel_t channel)
} else if ( channel == ADC2_CHANNEL_9 ) {
dac_output_disable(DAC_CHANNEL_2);
}
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
if ( channel == ADC2_CHANNEL_6 ) { // the same as DAC channel 1
dac_output_disable(DAC_CHANNEL_1);
} else if ( channel == ADC2_CHANNEL_7 ) {
@ -478,7 +482,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
ADC_CHECK(channel < ADC2_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
#ifdef CONFIG_IDF_TARGET_ESP32
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
#endif
@ -494,12 +498,12 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
adc2_dac_disable(channel); //disable other peripherals
#endif
adc2_config_width(width_bit); // in critical section with whole rtc module. because the PWDET use the same registers, place it here.
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
adc_set_init_code(ADC_NUM_2, channel); // calibration for adc
#endif
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);// set controller
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#ifdef CONFIG_PM_ENABLE
if (s_adc2_arbiter_lock) {
esp_pm_lock_acquire(s_adc2_arbiter_lock);
@ -511,7 +515,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
adc_value = -1;
}
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#ifdef CONFIG_PM_ENABLE
/* Release APB clock. */
if (s_adc2_arbiter_lock) {
@ -523,7 +527,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
ADC2_WIFI_LOCK_RELEASE();
ADC2_EXIT_CRITICAL();
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
adc_rtc_reset();
#endif

View File

@ -0,0 +1,277 @@
// Copyright 2019-2020 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.
#pragma once
#include "driver/adc_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------
Common setting
---------------------------------------------------------------*/
/**
* @brief Config ADC module arbiter.
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
*
* @note Only ADC2 support arbiter.
* @note Default priority: Wi-Fi > RTC > Digital;
* @note In normal use, there is no need to call this interface to config arbiter.
*
* @param adc_unit ADC unit.
* @param config Refer to `adc_arbiter_t`.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
*/
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* @brief ADC digital controller initialization.
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_init(void);
/**
* @brief ADC digital controller deinitialization.
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_deinit(void);
/**
* @brief Setting the digital controller.
*
* @param config Pointer to digital controller paramter. Refer to `adc_digi_config_t`.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
/**
* @brief Enable digital controller to trigger the measurement.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_start(void);
/**
* @brief Disable digital controller to trigger the measurement.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_stop(void);
/*************************************/
/* Digital controller filter setting */
/*************************************/
/**
* @brief Reset adc digital controller filter.
*
* @param idx Filter index.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
/**
* @brief Set adc digital controller filter configuration.
*
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
*
* @param idx Filter index.
* @param config See ``adc_digi_filter_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
/**
* @brief Get adc digital controller filter configuration.
*
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
*
* @param idx Filter index.
* @param config See ``adc_digi_filter_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
/**
* @brief Enable/disable adc digital controller filter.
* Filtering the ADC data to obtain smooth data at higher sampling rates.
*
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
*
* @param idx Filter index.
* @param enable Enable/Disable filter.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
/**************************************/
/* Digital controller monitor setting */
/**************************************/
/**
* @brief Config monitor of adc digital controller.
*
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
*
* @param idx Monitor index.
* @param config See ``adc_digi_monitor_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
/**
* @brief Enable/disable monitor of adc digital controller.
*
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
*
* @param idx Monitor index.
* @param enable True or false enable monitor.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
/**************************************/
/* Digital controller intr setting */
/**************************************/
/**
* @brief Enable interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Disable interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Clear interrupt of adc digital controller by bitmask.
*
* @param adc_unit ADC unit.
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
*
* @return
* - ESP_OK Success
*/
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
/**
* @brief Get interrupt status mask of adc digital controller.
*
* @param adc_unit ADC unit.
* @return
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
*/
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
/**
* @brief Register ADC interrupt handler, the handler is an ISR.
* The handler will be attached to the same CPU core that this function is running on.
*
* @param fn Interrupt handler function.
* @param arg Parameter for handler function
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
*
* @return
* - ESP_OK Success
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
* - ESP_ERR_INVALID_ARG Function pointer error.
*/
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
/**
* @brief Deregister ADC interrupt handler, the handler is an ISR.
*
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG hander error.
* - ESP_FAIL ISR not be registered.
*/
esp_err_t adc_digi_isr_deregister(void);
/*---------------------------------------------------------------
RTC controller setting
---------------------------------------------------------------*/
/*---------------------------------------------------------------
Deprecated API
---------------------------------------------------------------*/
/**
* @brief Set I2S data source
*
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
*
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
*
* @return
* - ESP_OK success
*/
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated));
/**
* @brief Initialize I2S ADC mode
*
* @param adc_unit ADC unit index
* @param channel ADC channel index
*
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,80 @@
// Copyright 2019 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.
#pragma once
#include "driver/dac_common.h"
#ifdef __cplusplus
extern "C" {
#endif
/*---------------------------------------------------------------
Digital controller setting
---------------------------------------------------------------*/
/**
* @brief DAC digital controller initialization.
* @return
* - ESP_OK success
*/
esp_err_t dac_digi_init(void);
/**
* @brief DAC digital controller deinitialization.
* @return
* - ESP_OK success
*/
esp_err_t dac_digi_deinit(void);
/**
* @brief Setting the DAC digital controller.
*
* @param cfg Pointer to digital controller paramter. See ``dac_digi_config_t``.
*
* @return
* - ESP_OK success
* - ESP_ERR_INVALID_ARG Parameter error
*/
esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg);
/**
* @brief DAC digital controller start output voltage.
* @return
* - ESP_OK success
*/
esp_err_t dac_digi_start(void);
/**
* @brief DAC digital controller stop output voltage.
* @return
* - ESP_OK success
*/
esp_err_t dac_digi_stop(void);
/**
* @brief Reset DAC digital controller FIFO.
* @return
* - ESP_OK success
*/
esp_err_t dac_digi_fifo_reset(void);
/**
* @brief Reset DAC digital controller.
* @return
* - ESP_OK success
*/
esp_err_t dac_digi_reset(void);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,105 @@
// Copyright 2010-2020 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.
#pragma once
#include <stdint.h>
#include "esp_err.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief temperature sensor range option.
*/
typedef enum {
TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */
TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */
TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */
TSENS_DAC_MAX,
TSENS_DAC_DEFAULT = TSENS_DAC_L2,
} temp_sensor_dac_offset_t;
/**
* @brief Configuration for temperature sensor reading
*/
typedef struct {
temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */
uint8_t clk_div; /*!< Default: 6 */
} temp_sensor_config_t;
/**
* @brief temperature sensor default setting.
*/
#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
.clk_div = 6}
/**
* @brief Set parameter of temperature sensor.
* @param tsens
* @return
* - ESP_OK Success
*/
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens);
/**
* @brief Get parameter of temperature sensor.
* @param tsens
* @return
* - ESP_OK Success
*/
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens);
/**
* @brief Start temperature sensor measure.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG
*/
esp_err_t temp_sensor_start(void);
/**
* @brief Stop temperature sensor measure.
* @return
* - ESP_OK Success
*/
esp_err_t temp_sensor_stop(void);
/**
* @brief Read temperature sensor raw data.
* @param tsens_out Pointer to raw data, Range: 0 ~ 255
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG `tsens_out` is NULL
* - ESP_ERR_INVALID_STATE temperature sensor dont start
*/
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out);
/**
* @brief Read temperature sensor data that is converted to degrees Celsius.
* @note Should not be called from interrupt.
* @param celsius The measure output value.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG ARG is NULL.
* - ESP_ERR_INVALID_STATE The ambient temperature is out of range.
*/
esp_err_t temp_sensor_read_celsius(float *celsius);
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1,582 @@
// Copyright 2019-2020 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#include "driver/touch_sensor_common.h"
/**
* @brief Set touch sensor FSM start
* @note Start FSM after the touch sensor FSM mode is set.
* @note Call this function will reset benchmark of all touch channels.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_fsm_start(void);
/**
* @brief Stop touch sensor FSM.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_fsm_stop(void);
/**
* @brief Trigger a touch sensor measurement, only support in SW mode of FSM
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_sw_start(void);
/**
* @brief Set touch sensor times of charge and discharge and sleep time.
* Excessive total time will slow down the touch response.
* Too small measurement time will not be sampled enough, resulting in inaccurate measurements.
*
* @note The greater the duty cycle of the measurement time, the more system power is consumed.
* @param sleep_cycle The touch sensor will sleep after each measurement.
* sleep_cycle decide the interval between each measurement.
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
* @param meas_times The times of charge and discharge in each measure process of touch channels.
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
* Recommended typical value: Modify this value to make the measurement time around 1ms.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_times);
/**
* @brief Get touch sensor times of charge and discharge and sleep time
* @param sleep_cycle Pointer to accept sleep cycle number
* @param meas_times Pointer to accept measurement times count.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_times);
/**
* @brief Set connection type of touch channel in idle status.
* When a channel is in measurement mode, other initialized channels are in idle mode.
* The touch channel is generally adjacent to the trace, so the connection state of the idle channel
* affects the stability and sensitivity of the test channel.
* The `CONN_HIGHZ`(high resistance) setting increases the sensitivity of touch channels.
* The `CONN_GND`(grounding) setting increases the stability of touch channels.
* @param type Select idle channel connect to high resistance state or ground.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_set_idle_channel_connect(touch_pad_conn_type_t type);
/**
* @brief Set connection type of touch channel in idle status.
* When a channel is in measurement mode, other initialized channels are in idle mode.
* The touch channel is generally adjacent to the trace, so the connection state of the idle channel
* affects the stability and sensitivity of the test channel.
* The `CONN_HIGHZ`(high resistance) setting increases the sensitivity of touch channels.
* The `CONN_GND`(grounding) setting increases the stability of touch channels.
* @param type Pointer to connection type.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_get_idle_channel_connect(touch_pad_conn_type_t *type);
/**
* @brief Set the trigger threshold of touch sensor.
* The threshold determines the sensitivity of the touch sensor.
* The threshold is the original value of the trigger state minus the benchmark value.
* @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered.
* @param touch_num touch pad index
* @param threshold threshold of touch sensor. Should be less than the max change value of touch.
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold);
/**
* @brief Get touch sensor trigger threshold
* @param touch_num touch pad index
* @param threshold pointer to accept threshold
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if argument is wrong
*/
esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold);
/**
* @brief Register touch channel into touch sensor scan group.
* The working mode of the touch sensor is cyclically scanned.
* This function will set the scan bits according to the given bitmask.
* @note If set this mask, the FSM timer should be stop firsty.
* @note The touch sensor that in scan map, should be deinit GPIO function firstly by `touch_pad_io_init`.
* @param enable_mask bitmask of touch sensor scan group.
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_set_channel_mask(uint16_t enable_mask);
/**
* @brief Get the touch sensor scan group bit mask.
* @param enable_mask Pointer to bitmask of touch sensor scan group.
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_get_channel_mask(uint16_t *enable_mask);
/**
* @brief Clear touch channel from touch sensor scan group.
* The working mode of the touch sensor is cyclically scanned.
* This function will clear the scan bits according to the given bitmask.
* @note If clear all mask, the FSM timer should be stop firsty.
* @param enable_mask bitmask of touch sensor scan group.
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_clear_channel_mask(uint16_t enable_mask);
/**
* @brief Configure parameter for each touch channel.
* @note Touch num 0 is denoise channel, please use `touch_pad_denoise_enable` to set denoise function
* @param touch_num touch pad index
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG if argument wrong
* - ESP_FAIL if touch pad not initialized
*/
esp_err_t touch_pad_config(touch_pad_t touch_num);
/**
* @brief Reset the FSM of touch module.
* @note Call this function after `touch_pad_fsm_stop`.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_reset(void);
/**
* @brief Get the current measure channel.
* @note Should be called when touch sensor measurement is in cyclic scan mode.
* @return
* - touch channel number
*/
touch_pad_t touch_pad_get_current_meas_channel(void);
/**
* @brief Get the touch sensor interrupt status mask.
* @return
* - touch interrupt bit
*/
uint32_t touch_pad_read_intr_status_mask(void);
/**
* @brief Enable touch sensor interrupt by bitmask.
* @param int_mask Pad mask to enable interrupts
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_intr_enable(touch_pad_intr_mask_t int_mask);
/**
* @brief Disable touch sensor interrupt by bitmask.
* @param int_mask Pad mask to disable interrupts
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_intr_disable(touch_pad_intr_mask_t int_mask);
/**
* @brief Clear touch sensor interrupt by bitmask.
* @param int_mask Pad mask to clear interrupts
* @return
* - ESP_OK on success
*/
esp_err_t touch_pad_intr_clear(touch_pad_intr_mask_t int_mask);
/**
* @brief Register touch-pad ISR.
* The handler will be attached to the same CPU core that this function is running on.
* @param fn Pointer to ISR handler
* @param arg Parameter for ISR
* @param intr_mask Enable touch sensor interrupt handler by bitmask.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Arguments error
* - ESP_ERR_NO_MEM No memory
*/
esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_mask_t intr_mask);
/**
* @brief Enable/disable the timeout check and set timeout threshold for all touch sensor channels measurements.
* If enable: When the touch reading of a touch channel exceeds the measurement threshold, a timeout interrupt will be generated.
* If disable: the FSM does not check if the channel under measurement times out.
*
* @note The threshold compared with touch readings.
* @note In order to avoid abnormal short circuit of some touch channels. This function should be turned on.
* Ensure the normal operation of other touch channels.
*
* @param enable true(default): Enable the timeout check; false: Disable the timeout check.
* @param threshold For all channels, the maximum value that will not be exceeded during normal operation.
*
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_timeout_set(bool enable, uint32_t threshold);
/**
* @brief Call this interface after timeout to make the touch channel resume normal work. Point on the next channel to measure.
* If this API is not called, the touch FSM will stop the measurement after timeout interrupt.
*
* @note Call this API after finishes the exception handling by user.
*
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_timeout_resume(void);
/**
* @brief get raw data of touch sensor.
* @note After the initialization is complete, the "raw_data" is max value. You need to wait for a measurement
* cycle before you can read the correct touch value.
* @param touch_num touch pad index
* @param raw_data pointer to accept touch sensor value
* @return
* - ESP_OK Success
* - ESP_FAIL Touch channel 0 haven't this parameter.
*/
esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint32_t *raw_data);
/**
* @brief get benchmark of touch sensor.
* @note After initialization, the benchmark value is the maximum during the first measurement period.
* @param touch_num touch pad index
* @param benchmark pointer to accept touch sensor benchmark value
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Touch channel 0 haven't this parameter.
*/
esp_err_t touch_pad_read_benchmark(touch_pad_t touch_num, uint32_t *benchmark);
/**
* @brief Get smoothed data that obtained by filtering the raw data.
*
* @param touch_num touch pad index
* @param smooth pointer to smoothed data
*/
esp_err_t touch_pad_filter_read_smooth(touch_pad_t touch_num, uint32_t *smooth);
/**
* @brief Force reset benchmark to raw data of touch sensor.
* @param touch_num touch pad index
* - TOUCH_PAD_MAX Reset basaline of all channels
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_reset_benchmark(touch_pad_t touch_num);
/**
* @brief set parameter of touch sensor filter and detection algorithm.
* For more details on the detection algorithm, please refer to the application documentation.
* @param filter_info select filter type and threshold of detection algorithm
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_filter_set_config(touch_filter_config_t *filter_info);
/**
* @brief get parameter of touch sensor filter and detection algorithm.
* For more details on the detection algorithm, please refer to the application documentation.
* @param filter_info select filter type and threshold of detection algorithm
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_filter_get_config(touch_filter_config_t *filter_info);
/**
* @brief enable touch sensor filter for detection algorithm.
* For more details on the detection algorithm, please refer to the application documentation.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_filter_enable(void);
/**
* @brief disable touch sensor filter for detection algorithm.
* For more details on the detection algorithm, please refer to the application documentation.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_filter_disable(void);
/**
* @brief set parameter of denoise pad (TOUCH_PAD_NUM0).
* T0 is an internal channel that does not have a corresponding external GPIO.
* T0 will work simultaneously with the measured channel Tn. Finally, the actual
* measured value of Tn is the value after subtracting lower bits of T0.
* The noise reduction function filters out interference introduced simultaneously on all channels,
* such as noise introduced by power supplies and external EMI.
* @param denoise parameter of denoise
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_denoise_set_config(touch_pad_denoise_t *denoise);
/**
* @brief get parameter of denoise pad (TOUCH_PAD_NUM0).
* @param denoise Pointer to parameter of denoise
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_denoise_get_config(touch_pad_denoise_t *denoise);
/**
* @brief enable denoise function.
* T0 is an internal channel that does not have a corresponding external GPIO.
* T0 will work simultaneously with the measured channel Tn. Finally, the actual
* measured value of Tn is the value after subtracting lower bits of T0.
* The noise reduction function filters out interference introduced simultaneously on all channels,
* such as noise introduced by power supplies and external EMI.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_denoise_enable(void);
/**
* @brief disable denoise function.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_denoise_disable(void);
/**
* @brief Get denoise measure value (TOUCH_PAD_NUM0).
* @param data Pointer to receive denoise value
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_denoise_read_data(uint32_t *data);
/**
* @brief set parameter of waterproof function.
*
* The waterproof function includes a shielded channel (TOUCH_PAD_NUM14) and a guard channel.
* Guard pad is used to detect the large area of water covering the touch panel.
* Shield pad is used to shield the influence of water droplets covering the touch panel.
* It is generally designed as a grid and is placed around the touch buttons.
*
* @param waterproof parameter of waterproof
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_waterproof_set_config(touch_pad_waterproof_t *waterproof);
/**
* @brief get parameter of waterproof function.
* @param waterproof parameter of waterproof
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_waterproof_get_config(touch_pad_waterproof_t *waterproof);
/**
* @brief Enable parameter of waterproof function.
* Should be called after function ``touch_pad_waterproof_set_config``.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_waterproof_enable(void);
/**
* @brief Disable parameter of waterproof function.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_waterproof_disable(void);
/**
* @brief Enable/disable proximity function of touch channels.
* The proximity sensor measurement is the accumulation of touch channel measurements.
*
* @note Supports up to three touch channels configured as proximity sensors.
* @param touch_num touch pad index
* @param enabled true: enable the proximity function; false: disable the proximity function
* @return
* - ESP_OK: Configured correctly.
* - ESP_ERR_INVALID_ARG: Touch channel number error.
* - ESP_ERR_NOT_SUPPORTED: Don't support configured.
*/
esp_err_t touch_pad_proximity_enable(touch_pad_t touch_num, bool enabled);
/**
* @brief Set measure count of proximity channel.
* The proximity sensor measurement is the accumulation of touch channel measurements.
*
* @note All proximity channels use the same `count` value. So please pass the parameter `TOUCH_PAD_MAX`.
* @param touch_num Touch pad index. In this version, pass the parameter `TOUCH_PAD_MAX`.
* @param count The cumulative times of measurements for proximity pad. Range: 0 ~ 255.
* @return
* - ESP_OK: Configured correctly.
* - ESP_ERR_INVALID_ARG: Touch channel number error.
*/
esp_err_t touch_pad_proximity_set_count(touch_pad_t touch_num, uint32_t count);
/**
* @brief Get measure count of proximity channel.
* The proximity sensor measurement is the accumulation of touch channel measurements.
*
* @note All proximity channels use the same `count` value. So please pass the parameter `TOUCH_PAD_MAX`.
* @param touch_num Touch pad index. In this version, pass the parameter `TOUCH_PAD_MAX`.
* @param count The cumulative times of measurements for proximity pad. Range: 0 ~ 255.
* @return
* - ESP_OK: Configured correctly.
* - ESP_ERR_INVALID_ARG: Touch channel number error.
*/
esp_err_t touch_pad_proximity_get_count(touch_pad_t touch_num, uint32_t *count);
/**
* @brief Get the accumulated measurement of the proximity sensor.
* The proximity sensor measurement is the accumulation of touch channel measurements.
* @param touch_num touch pad index
* @param measure_out If the accumulation process does not end, the `measure_out` is the process value.
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG Touch num is not proximity
*/
esp_err_t touch_pad_proximity_get_data(touch_pad_t touch_num, uint32_t *measure_out);
/**
* @brief Get parameter of touch sensor sleep channel.
* The touch sensor can works in sleep mode to wake up sleep.
*
* @note After the sleep channel is configured, Please use special functions for sleep channel.
* e.g. The user should uses `touch_pad_sleep_channel_read_data` instead of `touch_pad_read_raw_data` to obtain the sleep channel reading.
*
* @param slp_config touch sleep pad config.
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_channel_get_info(touch_pad_sleep_channel_t *slp_config);
/**
* @brief Enable/Disable sleep channel function for touch sensor.
* The touch sensor can works in sleep mode to wake up sleep.
*
* @note ESP32S2 only support one sleep channel.
* @note After the sleep channel is configured, Please use special functions for sleep channel.
* e.g. The user should uses `touch_pad_sleep_channel_read_data` instead of `touch_pad_read_raw_data` to obtain the sleep channel reading.
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param enable true: enable sleep pad for touch sensor; false: disable sleep pad for touch sensor;
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_channel_enable(touch_pad_t pad_num, bool enable);
/**
* @brief Enable/Disable proximity function for sleep channel.
* The touch sensor can works in sleep mode to wake up sleep.
*
* @note ESP32S2 only support one sleep channel.
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param enable true: enable proximity for sleep channel; false: disable proximity for sleep channel;
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_channel_enable_proximity(touch_pad_t pad_num, bool enable);
/**
* @brief Set the trigger threshold of touch sensor in deep sleep.
* The threshold determines the sensitivity of the touch sensor.
*
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param touch_thres touch sleep pad threshold
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_set_threshold(touch_pad_t pad_num, uint32_t touch_thres);
/**
* @brief Get the trigger threshold of touch sensor in deep sleep.
* The threshold determines the sensitivity of the touch sensor.
*
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
*
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param touch_thres touch sleep pad threshold
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_get_threshold(touch_pad_t pad_num, uint32_t *touch_thres);
/**
* @brief Read benchmark of touch sensor sleep channel.
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param benchmark pointer to accept touch sensor benchmark value
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG parameter is NULL
*/
esp_err_t touch_pad_sleep_channel_read_benchmark(touch_pad_t pad_num, uint32_t *benchmark);
/**
* @brief Read smoothed data of touch sensor sleep channel.
* Smoothed data is filtered from the raw data.
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param smooth_data pointer to accept touch sensor smoothed data
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG parameter is NULL
*/
esp_err_t touch_pad_sleep_channel_read_smooth(touch_pad_t pad_num, uint32_t *smooth_data);
/**
* @brief Read raw data of touch sensor sleep channel.
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param raw_data pointer to accept touch sensor raw data
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG parameter is NULL
*/
esp_err_t touch_pad_sleep_channel_read_data(touch_pad_t pad_num, uint32_t *raw_data);
/**
* @brief Reset benchmark of touch sensor sleep channel.
*
* @return
* - ESP_OK Success
*/
esp_err_t touch_pad_sleep_channel_reset_benchmark(void);
/**
* @brief Read proximity count of touch sensor sleep channel.
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
* @param proximity_cnt pointer to accept touch sensor proximity count value
* @return
* - ESP_OK Success
* - ESP_ERR_INVALID_ARG parameter is NULL
*/
esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32_t *proximity_cnt);
#ifdef __cplusplus
}
#endif

View File

@ -498,7 +498,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
portBASE_TYPE high_priority_task_awoken = 0;
lldesc_t *finish_desc;
lldesc_t *finish_desc = NULL;
if ((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) {
ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", status);

View File

@ -138,6 +138,8 @@ static inline uint32_t get_dma_periph(int dma_chan)
}
#elif CONFIG_IDF_TARGET_ESP32
return PERIPH_SPI_DMA_MODULE;
#else
return 0;
#endif
}

View File

@ -190,7 +190,7 @@ static inline bool is_valid_host(spi_host_device_t host)
{
#if CONFIG_IDF_TARGET_ESP32
return host >= SPI1_HOST && host <= SPI3_HOST;
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master driver on ESP32-S2
return host >= SPI2_HOST && host <= SPI3_HOST;
#endif

View File

@ -80,7 +80,7 @@ static inline bool is_valid_host(spi_host_device_t host)
{
#if CONFIG_IDF_TARGET_ESP32
return host >= SPI1_HOST && host <= SPI3_HOST;
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
// SPI_HOST (SPI1_HOST) is not supported by the SPI Slave driver on ESP32-S2
return host >= SPI2_HOST && host <= SPI3_HOST;
#endif

View File

@ -272,18 +272,25 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
switch (group_num) {
case TIMER_GROUP_0:
default:
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE)) {
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
}
#endif
timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_0][timer_num]->hal), &status_reg, &mask);
break;
case TIMER_GROUP_1:
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE)) {
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
}
#endif
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
} else {
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
}
timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_1][timer_num]->hal), &status_reg, &mask);
break;

View File

@ -42,7 +42,7 @@ static const char *TOUCH_TAG = "TOUCH_SENSOR";
#define TOUCH_CHANNEL_CHECK(channel) do { \
TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \
} while (0);
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif defined CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#define TOUCH_CHANNEL_CHECK(channel) do { \
TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \
TOUCH_CHECK(channel != SOC_TOUCH_DENOISE_CHANNEL, "TOUCH0 is internal denoise channel", ESP_ERR_INVALID_ARG); \
@ -194,7 +194,7 @@ esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold)
TOUCH_EXIT_CRITICAL();
return ESP_OK;
}
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold)
{
TOUCH_CHANNEL_CHECK(touch_num);
@ -214,7 +214,7 @@ esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold)
touch_hal_get_threshold(touch_num, threshold);
return ESP_OK;
}
#elif defined CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold)
{
TOUCH_CHANNEL_CHECK(touch_num);

View File

@ -35,6 +35,8 @@
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#endif
#ifdef CONFIG_UART_ISR_IN_IRAM

View File

View File

@ -0,0 +1,13 @@
// Copyright 2017-2020 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

View File

@ -0,0 +1,123 @@
// Copyright 2017-2020 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
#ifdef __cplusplus
extern "C" {
#endif
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_DIS_RTC_RAM_BOOT[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_2[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0_PURPOSE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1_PURPOSE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2_PURPOSE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3_PURPOSE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4_PURPOSE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5_PURPOSE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_EN[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_3[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART1[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_USER_DATA[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART2[];
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_USB_EXCHG_PINS[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY0[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY1[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY2[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[];
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DCACHE[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_DCACHE[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_FORCE_DOWNLOAD[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_CAN[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_BOOT_REMAP[];
extern const esp_efuse_desc_t* ESP_EFUSE_SOFT_DIS_JTAG[];
extern const esp_efuse_desc_t* ESP_EFUSE_HARD_DIS_JTAG[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT[];
extern const esp_efuse_desc_t* ESP_EFUSE_USB_EXCHG_PINS[];
extern const esp_efuse_desc_t* ESP_EFUSE_USB_EXT_PHY_ENABLE[];
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_XPD[];
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_TIEH[];
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_FORCE[];
extern const esp_efuse_desc_t* ESP_EFUSE_WDT_DELAY_SEL[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_BOOT_CRYPT_CNT[];
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0[];
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1[];
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_0[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_1[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_2[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_3[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_4[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_5[];
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_EN[];
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE[];
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_TPUW[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MODE[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_LEGACY_SPI_BOOT[];
extern const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CHANNEL[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_TINY_BASIC[];
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DOWNLOAD_MODE[];
extern const esp_efuse_desc_t* ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD[];
extern const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CONTROL[];
extern const esp_efuse_desc_t* ESP_EFUSE_PIN_POWER_SELECTION[];
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_TYPE[];
extern const esp_efuse_desc_t* ESP_EFUSE_FORCE_SEND_RESUME[];
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_VERSION[];
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CLK[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_Q_D1[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D_D0[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CS[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_HD_D3[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_WP_D2[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_DQS[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D4[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D5[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D6[];
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[];
extern const esp_efuse_desc_t* ESP_EFUSE_CLK8M_FREQ[];
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[];
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART1[];
extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY3[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY4[];
extern const esp_efuse_desc_t* ESP_EFUSE_KEY5[];
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART2[];
#ifdef __cplusplus
}
#endif

View File

@ -0,0 +1 @@
set(EFUSE_SOC_SRCS "esp_efuse_table.c")

View File

@ -0,0 +1,69 @@
// Copyright 2020 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Type of eFuse blocks ESP32S3
*/
typedef enum {
EFUSE_BLK0 = 0, /**< Number of eFuse BLOCK0. REPEAT_DATA */
EFUSE_BLK1 = 1, /**< Number of eFuse BLOCK1. MAC_SPI_8M_SYS */
EFUSE_BLK2 = 2, /**< Number of eFuse BLOCK2. SYS_DATA_PART1 */
EFUSE_BLK_SYS_DATA_PART1 = 2, /**< Number of eFuse BLOCK2. SYS_DATA_PART1 */
EFUSE_BLK3 = 3, /**< Number of eFuse BLOCK3. USER_DATA*/
EFUSE_BLK_USER_DATA = 3, /**< Number of eFuse BLOCK3. USER_DATA*/
EFUSE_BLK4 = 4, /**< Number of eFuse BLOCK4. KEY0 */
EFUSE_BLK_KEY0 = 4, /**< Number of eFuse BLOCK4. KEY0 */
EFUSE_BLK5 = 5, /**< Number of eFuse BLOCK5. KEY1 */
EFUSE_BLK_KEY1 = 5, /**< Number of eFuse BLOCK5. KEY1 */
EFUSE_BLK6 = 6, /**< Number of eFuse BLOCK6. KEY2 */
EFUSE_BLK_KEY2 = 6, /**< Number of eFuse BLOCK6. KEY2 */
EFUSE_BLK7 = 7, /**< Number of eFuse BLOCK7. KEY3 */
EFUSE_BLK_KEY3 = 7, /**< Number of eFuse BLOCK7. KEY3 */
EFUSE_BLK8 = 8, /**< Number of eFuse BLOCK8. KEY4 */
EFUSE_BLK_KEY4 = 8, /**< Number of eFuse BLOCK8. KEY4 */
EFUSE_BLK9 = 9, /**< Number of eFuse BLOCK9. KEY5 */
EFUSE_BLK_KEY5 = 9, /**< Number of eFuse BLOCK9. KEY5 */
EFUSE_BLK10 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */
EFUSE_BLK_SYS_DATA_PART2 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */
EFUSE_BLK_MAX
} esp_efuse_block_t;
/**
* @brief Type of coding scheme
*/
typedef enum {
EFUSE_CODING_SCHEME_NONE = 0, /**< None */
EFUSE_CODING_SCHEME_RS = 3, /**< Reed-Solomon coding */
} esp_efuse_coding_scheme_t;
#ifdef __cplusplus
}
#endif

View File

@ -27,6 +27,8 @@ extern "C" {
#include "esp32/esp_efuse.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/esp_efuse.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/esp_efuse.h"
#endif
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */

View File

@ -0,0 +1,30 @@
// Copyright 2020 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.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
#define COUNT_EFUSE_BLOCKS 11 /* The number of blocks. */
#define COUNT_EFUSE_REG_PER_BLOCK 8 /* The number of registers per block. */
#define ESP_EFUSE_SECURE_VERSION_NUM_BLOCK EFUSE_BLK0
#define ESP_EFUSE_FIELD_CORRESPONDS_CODING_SCHEME(scheme, max_num_bit)
#ifdef __cplusplus
}
#endif

View File

@ -27,6 +27,8 @@ extern "C" {
#include "esp32/esp_efuse_utility.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/esp_efuse_utility.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/esp_efuse_utility.h"
#endif
/**

View File

@ -0,0 +1,13 @@
// Copyright 2020 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.

View File

@ -0,0 +1,13 @@
// Copyright 2017-2020 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.

View File

@ -0,0 +1,13 @@
// Copyright 2017-2020 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.

View File

@ -21,7 +21,6 @@ else()
"memprot.c"
"pm_esp32s3.c"
"pm_trace.c"
"sleep_modes.c"
"spiram.c"
"spiram_psram.c"
"system_api_esp32s3.c")

View File

@ -0,0 +1,39 @@
// Copyright 2015-2017 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.
#pragma once
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* @file esp32s2/rtc.h
*
* This file contains declarations of rtc related functions.
*/
/**
* @brief Get current value of RTC counter in microseconds
*
* Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute
*
* @return current value of RTC counter in microseconds
*/
uint64_t esp_rtc_get_time_us(void);
#ifdef __cplusplus
}
#endif

View File

@ -11,7 +11,7 @@
#define SRAM_IRAM_START 0x40370000
#define SRAM_DRAM_START 0x3FC80000
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
#define SRAM_DRAM_END 0x40054000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
#define SRAM_DRAM_END 0x403BC000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
#define SRAM_IRAM_ORG (SRAM_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE)
#define SRAM_DRAM_ORG (SRAM_DRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE)

View File

@ -18,7 +18,7 @@
#include <stdbool.h>
bool esp_memprot_is_assoc_intr_any()
bool esp_memprot_is_assoc_intr_any(void)
{
return true;
}

View File

@ -1,717 +0,0 @@
// Copyright 2015-2020 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 <stddef.h>
#include <sys/lock.h>
#include <sys/param.h>
#include "esp_attr.h"
#include "esp_sleep.h"
#include "esp_private/esp_timer_private.h"
#include "esp_log.h"
#include "esp32s3/clk.h"
#include "esp_newlib.h"
#include "esp_spi_flash.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/rom/rtc.h"
#include "esp_rom_uart.h"
#include "esp_rom_sys.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
#include "soc/spi_periph.h"
#include "soc/dport_reg.h"
#include "soc/extmem_reg.h"
#include "soc/soc_memory_layout.h"
#include "soc/uart_caps.h"
#include "hal/wdt_hal.h"
#include "hal/clk_gate_ll.h"
#include "driver/rtc_io.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "sdkconfig.h"
// If light sleep time is less than that, don't power down flash
#define FLASH_PD_MIN_SLEEP_TIME_US 2000
// Time from VDD_SDIO power up to first flash read in ROM code
#define VDD_SDIO_POWERUP_TO_FLASH_READ_US 700
// Extra time it takes to enter and exit light sleep and deep sleep
// For deep sleep, this is until the wake stub runs (not the app).
#ifdef CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS
#define LIGHT_SLEEP_TIME_OVERHEAD_US (650 + 30 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
#else
#define LIGHT_SLEEP_TIME_OVERHEAD_US (250 + 30 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
#endif // CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS
// Minimal amount of time we can sleep for
#define LIGHT_SLEEP_MIN_TIME_US 200
#define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \
(source == value))
/**
* Internal structure which holds all requested deep sleep parameters
*/
typedef struct {
esp_sleep_pd_option_t pd_options[ESP_PD_DOMAIN_MAX];
uint64_t sleep_duration;
uint32_t wakeup_triggers : 15;
uint32_t ext1_trigger_mode : 1;
uint32_t ext1_rtc_gpio_mask : 18;
uint32_t ext0_trigger_level : 1;
uint32_t ext0_rtc_gpio_num : 5;
uint32_t sleep_time_adjustment;
uint64_t rtc_ticks_at_sleep_start;
} sleep_config_t;
static sleep_config_t s_config = {
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
.wakeup_triggers = 0
};
/* Internal variable used to track if light sleep wakeup sources are to be
expected when determining wakeup cause. */
static bool s_light_sleep_wakeup = false;
/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
is not thread-safe. */
static _lock_t lock_rtc_memory_crc;
static const char *TAG = "sleep";
static uint32_t get_power_down_flags(void);
static void ext0_wakeup_prepare(void);
static void ext1_wakeup_prepare(void);
static void timer_wakeup_prepare(void);
static void touch_wakeup_prepare(void);
/* Wake from deep sleep stub
See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
*/
esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
{
_lock_acquire(&lock_rtc_memory_crc);
uint32_t stored_crc = REG_READ(RTC_MEMORY_CRC_REG);
set_rtc_memory_crc();
uint32_t calc_crc = REG_READ(RTC_MEMORY_CRC_REG);
REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc);
_lock_release(&lock_rtc_memory_crc);
if (stored_crc != calc_crc) {
return NULL;
}
esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
if (!esp_ptr_executable(stub_ptr)) {
return NULL;
}
return stub_ptr;
}
void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
{
_lock_acquire(&lock_rtc_memory_crc);
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
set_rtc_memory_crc();
_lock_release(&lock_rtc_memory_crc);
}
void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void)
{
REG_SET_BIT(EXTMEM_CACHE_CONF_MISC_REG, EXTMEM_CACHE_TRACE_ENA);
}
void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void);
void esp_deep_sleep(uint64_t time_in_us)
{
esp_sleep_enable_timer_wakeup(time_in_us);
esp_deep_sleep_start();
}
static void IRAM_ATTR flush_uarts(void)
{
for (int i = 0; i < SOC_UART_NUM; ++i) {
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
esp_rom_uart_tx_wait_idle(i);
}
}
}
static void IRAM_ATTR suspend_uarts(void)
{
for (int i = 0; i < SOC_UART_NUM; ++i) {
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
while (REG_GET_FIELD(UART_FSM_STATUS_REG(i), UART_ST_UTX_OUT) != 0) {
;
}
}
}
}
static void IRAM_ATTR resume_uarts(void)
{
for (int i = 0; i < SOC_UART_NUM; ++i) {
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF);
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
}
}
}
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
{
// Stop UART output so that output is not lost due to APB frequency change.
// For light sleep, suspend UART output — it will resume after wakeup.
// For deep sleep, wait for the contents of UART FIFO to be sent.
if (pd_flags & RTC_SLEEP_PD_DIG) {
flush_uarts();
} else {
suspend_uarts();
}
// Save current frequency and switch to XTAL
// Save current frequency and switch to XTAL
rtc_cpu_freq_config_t cpu_freq_config;
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
rtc_clk_cpu_freq_set_xtal();
// Configure pins for external wakeup
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
ext0_wakeup_prepare();
}
if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) {
ext1_wakeup_prepare();
}
// Enable ULP wakeup
if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) {
// no-op for esp32s3
}
// Enable Touch wakeup
if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) {
touch_wakeup_prepare();
}
uint32_t reject_triggers = 0;
if ((pd_flags & RTC_SLEEP_PD_DIG) == 0) {
/* Light sleep, enable sleep reject for faster return from this function,
* in case the wakeup is already triggerred.
*/
reject_triggers = s_config.wakeup_triggers;
}
// Enter sleep
rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags);
rtc_sleep_init(config);
// Configure timer wakeup
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
s_config.sleep_duration > 0) {
timer_wakeup_prepare();
}
uint32_t result = rtc_sleep_start(s_config.wakeup_triggers, reject_triggers, 1);
// Restore CPU frequency
rtc_clk_cpu_freq_set_config(&cpu_freq_config);
// re-enable UART output
resume_uarts();
return result;
}
void IRAM_ATTR esp_deep_sleep_start(void)
{
// record current RTC time
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
esp_sync_counters_rtc_and_frc();
// Configure wake stub
if (esp_get_deep_sleep_wake_stub() == NULL) {
esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep);
}
// Decide which power domains can be powered down
uint32_t pd_flags = get_power_down_flags();
// Correct the sleep time
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
// Enter sleep
esp_sleep_start(RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | pd_flags);
// Because RTC is in a slower clock domain than the CPU, it
// can take several CPU cycles for the sleep mode to start.
while (1) {
;
}
}
/**
* Helper function which handles entry to and exit from light sleep
* Placed into IRAM as flash may need some time to be powered on.
*/
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
uint32_t flash_enable_time_us,
rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline));
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
uint32_t flash_enable_time_us,
rtc_vddsdio_config_t vddsdio_config)
{
// Enter sleep
esp_err_t err = esp_sleep_start(pd_flags);
// If VDDSDIO regulator was controlled by RTC registers before sleep,
// restore the configuration.
if (vddsdio_config.force) {
rtc_vddsdio_set_config(vddsdio_config);
}
// If SPI flash was powered down, wait for it to become ready
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
// Wait for the flash chip to start up
esp_rom_delay_us(flash_enable_time_us);
}
return err;
}
esp_err_t esp_light_sleep_start(void)
{
static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&light_sleep_lock);
/* We will be calling esp_timer_private_advance inside DPORT access critical
* section. Make sure the code on the other CPU is not holding esp_timer
* lock, otherwise there will be deadlock.
*/
esp_timer_private_lock();
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
uint64_t frc_time_at_start = esp_timer_get_time();
DPORT_STALL_OTHER_CPU_START();
// Decide which power domains can be powered down
uint32_t pd_flags = get_power_down_flags();
// Amount of time to subtract from actual sleep time.
// This is spent on entering and leaving light sleep.
s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US;
// Decide if VDD_SDIO needs to be powered down;
// If it needs to be powered down, adjust sleep time.
const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US;
#ifndef CONFIG_SPIRAM
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
flash_enable_time_us + LIGHT_SLEEP_TIME_OVERHEAD_US + LIGHT_SLEEP_MIN_TIME_US);
if (s_config.sleep_duration > vddsdio_pd_sleep_duration) {
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
s_config.sleep_time_adjustment += flash_enable_time_us;
}
#endif //CONFIG_SPIRAM
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
// Safety net: enable WDT in case exit from light sleep fails
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
bool wdt_was_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx); // If WDT was enabled in the user code, then do not change it here.
if (!wdt_was_enabled) {
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
wdt_hal_enable(&rtc_wdt_ctx);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
}
// Enter sleep, then wait for flash to be ready on wakeup
esp_err_t err = esp_light_sleep_inner(pd_flags,
flash_enable_time_us, vddsdio_config);
s_light_sleep_wakeup = true;
// FRC1 has been clock gated for the duration of the sleep, correct for that.
uint64_t rtc_ticks_at_end = rtc_time_get();
uint64_t frc_time_at_end = esp_timer_get_time();
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start,
esp_clk_slowclk_cal_get());
uint64_t frc_time_diff = frc_time_at_end - frc_time_at_start;
int64_t time_diff = rtc_time_diff - frc_time_diff;
/* Small negative values (up to 1 RTC_SLOW clock period) are possible,
* for very small values of sleep_duration. Ignore those to keep esp_timer
* monotonic.
*/
if (time_diff > 0) {
esp_timer_private_advance(time_diff);
}
esp_set_time_from_rtc();
esp_timer_private_unlock();
DPORT_STALL_OTHER_CPU_END();
if (!wdt_was_enabled) {
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
wdt_hal_disable(&rtc_wdt_ctx);
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
}
portEXIT_CRITICAL(&light_sleep_lock);
return err;
}
esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
{
// For most of sources it is enough to set trigger mask in local
// configuration structure. The actual RTC wake up options
// will be updated by esp_sleep_start().
if (source == ESP_SLEEP_WAKEUP_ALL) {
s_config.wakeup_triggers = 0;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN;
s_config.sleep_duration = 0;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
s_config.ext0_rtc_gpio_num = 0;
s_config.ext0_trigger_level = 0;
s_config.wakeup_triggers &= ~RTC_EXT0_TRIG_EN;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) {
s_config.ext1_rtc_gpio_mask = 0;
s_config.ext1_trigger_mode = 0;
s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_GPIO, RTC_GPIO_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN;
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN);
}
#ifdef CONFIG_ESP32S3_ULP_COPROC_ENABLED
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) {
s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN;
}
#endif
else {
ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source);
return ESP_ERR_INVALID_STATE;
}
return ESP_OK;
}
esp_err_t esp_sleep_enable_ulp_wakeup(void)
{
s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
return ESP_OK;
}
esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
{
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
s_config.sleep_duration = time_in_us;
return ESP_OK;
}
static void timer_wakeup_prepare(void)
{
uint32_t period = esp_clk_slowclk_cal_get();
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
if (sleep_duration < 0) {
sleep_duration = 0;
}
int64_t rtc_count_delta = rtc_time_us_to_slowclk(sleep_duration, period);
rtc_sleep_set_wakeup_time(s_config.rtc_ticks_at_sleep_start + rtc_count_delta);
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR_M);
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
}
/* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */
static void touch_wakeup_prepare(void)
{
touch_pad_sleep_channel_t slp_config;
touch_pad_fsm_stop();
touch_pad_clear_channel_mask(SOC_TOUCH_SENSOR_BIT_MASK_MAX);
touch_pad_sleep_channel_get_info(&slp_config);
touch_pad_set_channel_mask(BIT(slp_config.touch_num));
touch_pad_fsm_start();
}
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
{
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
return ESP_ERR_INVALID_STATE;
}
s_config.wakeup_triggers |= RTC_TOUCH_TRIG_EN;
return ESP_OK;
}
touch_pad_t esp_sleep_get_touchpad_wakeup_status(void)
{
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TOUCHPAD) {
return TOUCH_PAD_MAX;
}
touch_pad_t pad_num;
esp_err_t ret = touch_pad_get_wakeup_status(&pad_num); //TODO 723diff commit id:fda9ada1b
assert(ret == ESP_OK && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero");
return pad_num;
}
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
{
if (level < 0 || level > 1) {
return ESP_ERR_INVALID_ARG;
}
if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
return ESP_ERR_INVALID_ARG;
}
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
return ESP_ERR_INVALID_STATE;
}
s_config.ext0_rtc_gpio_num = rtc_io_number_get(gpio_num);
s_config.ext0_trigger_level = level;
s_config.wakeup_triggers |= RTC_EXT0_TRIG_EN;
return ESP_OK;
}
static void ext0_wakeup_prepare(void)
{
int rtc_gpio_num = s_config.ext0_rtc_gpio_num;
// Set GPIO to be used for wakeup
REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, rtc_gpio_num);
// Set level which will trigger wakeup
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
s_config.ext0_trigger_level, RTC_CNTL_EXT_WAKEUP0_LV_S);
// Find GPIO descriptor in the rtc_io_desc table and configure the pad
const rtc_io_desc_t *desc = &rtc_io_desc[rtc_gpio_num];
REG_SET_BIT(desc->reg, desc->mux);
SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func);
REG_SET_BIT(desc->reg, desc->ie);
}
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode)
{
if (mode > ESP_EXT1_WAKEUP_ANY_HIGH) {
return ESP_ERR_INVALID_ARG;
}
// Translate bit map of GPIO numbers into the bit map of RTC IO numbers
uint32_t rtc_gpio_mask = 0;
for (int gpio = 0; mask; ++gpio, mask >>= 1) {
if ((mask & 1) == 0) {
continue;
}
if (!RTC_GPIO_IS_VALID_GPIO(gpio)) {
ESP_LOGE(TAG, "Not an RTC IO: GPIO%d", gpio);
return ESP_ERR_INVALID_ARG;
}
rtc_gpio_mask |= BIT(rtc_io_number_get(gpio));
}
s_config.ext1_rtc_gpio_mask = rtc_gpio_mask;
s_config.ext1_trigger_mode = mode;
s_config.wakeup_triggers |= RTC_EXT1_TRIG_EN;
return ESP_OK;
}
static void ext1_wakeup_prepare(void)
{
// Configure all RTC IOs selected as ext1 wakeup inputs
uint32_t rtc_gpio_mask = s_config.ext1_rtc_gpio_mask;
for (int gpio = 0; gpio < GPIO_PIN_COUNT && rtc_gpio_mask != 0; ++gpio) {
int rtc_pin = rtc_io_number_get(gpio);
if ((rtc_gpio_mask & BIT(rtc_pin)) == 0) {
continue;
}
const rtc_io_desc_t *desc = &rtc_io_desc[rtc_pin];
// Route pad to RTC
REG_SET_BIT(desc->reg, desc->mux);
SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func);
// set input enable in sleep mode
REG_SET_BIT(desc->reg, desc->ie);
// Pad configuration depends on RTC_PERIPH state in sleep mode
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) {
// RTC_PERIPH will be powered down, so RTC_IO_ registers will
// loose their state. Lock pad configuration.
// Pullups/pulldowns also need to be disabled.
REG_CLR_BIT(desc->reg, desc->pulldown);
REG_CLR_BIT(desc->reg, desc->pullup);
REG_SET_BIT(RTC_CNTL_PAD_HOLD_REG, desc->hold_force);
}
// Keep track of pins which are processed to bail out early
rtc_gpio_mask &= ~BIT(rtc_pin);
}
// Clear state from previous wakeup
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
// Set pins to be used for wakeup
REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, s_config.ext1_rtc_gpio_mask);
// Set logic function (any low, all high)
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
s_config.ext1_trigger_mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
}
uint64_t esp_sleep_get_ext1_wakeup_status(void)
{
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_EXT1) {
return 0;
}
uint32_t status = REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
// Translate bit map of RTC IO numbers into the bit map of GPIO numbers
uint64_t gpio_mask = 0;
for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) {
if (!RTC_GPIO_IS_VALID_GPIO(gpio)) {
continue;
}
int rtc_pin = rtc_io_number_get(gpio);
if ((status & BIT(rtc_pin)) == 0) {
continue;
}
gpio_mask |= 1ULL << gpio;
}
return gpio_mask;
}
esp_err_t esp_sleep_enable_gpio_wakeup(void)
{
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
return ESP_ERR_INVALID_STATE;
}
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
return ESP_OK;
}
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num)
{
if (uart_num == 0) {
s_config.wakeup_triggers |= RTC_UART0_TRIG_EN;
} else if (uart_num == 1) {
s_config.wakeup_triggers |= RTC_UART1_TRIG_EN;
} else {
return ESP_ERR_INVALID_ARG;
}
return ESP_OK;
}
esp_err_t esp_sleep_enable_wifi_wakeup(void)
{
s_config.wakeup_triggers |= RTC_MAC_TRIG_EN;
return ESP_OK;
}
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
{
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET && !s_light_sleep_wakeup) {
return ESP_SLEEP_WAKEUP_UNDEFINED;
}
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
if (wakeup_cause & RTC_EXT0_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT0;
} else if (wakeup_cause & RTC_EXT1_TRIG_EN) {
return ESP_SLEEP_WAKEUP_EXT1;
} else if (wakeup_cause & RTC_TIMER_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TIMER;
} else if (wakeup_cause & RTC_TOUCH_TRIG_EN) {
return ESP_SLEEP_WAKEUP_TOUCHPAD;
} else if (wakeup_cause & RTC_ULP_TRIG_EN) {
return ESP_SLEEP_WAKEUP_ULP;
} else if (wakeup_cause & RTC_GPIO_TRIG_EN) {
return ESP_SLEEP_WAKEUP_GPIO;
} else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) {
return ESP_SLEEP_WAKEUP_UART;
} else if (wakeup_cause & RTC_MAC_TRIG_EN) {
return ESP_SLEEP_WAKEUP_WIFI;
} else if (wakeup_cause & RTC_COCPU_TRIG_EN) {
return ESP_SLEEP_WAKEUP_ULP;
} else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) {
return ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG;
} else {
return ESP_SLEEP_WAKEUP_UNDEFINED;
}
}
esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
esp_sleep_pd_option_t option)
{
if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) {
return ESP_ERR_INVALID_ARG;
}
s_config.pd_options[domain] = option;
return ESP_OK;
}
static uint32_t get_power_down_flags(void)
{
// Where needed, convert AUTO options to ON. Later interpret AUTO as OFF.
// RTC_SLOW_MEM is needed for the ULP, so keep RTC_SLOW_MEM powered up if ULP
// is used and RTC_SLOW_MEM is Auto.
// If there is any data placed into .rtc.data or .rtc.bss segments, and
// RTC_SLOW_MEM is Auto, keep it powered up as well.
// Labels are defined in the linker script, see esp32s3.ld.
extern int _rtc_slow_length;
if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) &&
((size_t) &_rtc_slow_length > 0 ||
(s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON;
}
// RTC_FAST_MEM is needed for deep sleep stub.
// If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub
// can run.
// In the new chip revision, deep sleep stub will be optional,
// and this can be changed.
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) {
s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON;
}
// RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup.
// If RTC_PERIPH is auto, and EXT0/GPIO aren't enabled, power down RTC_PERIPH.
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) {
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) {
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON;
} else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
// In both rev. 0 and rev. 1 of ESP32, forcing power up of RTC_PERIPH
// prevents ULP timer and touch FSMs from working correctly.
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF;
}
}
if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) {
s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF;
}
const char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */};
ESP_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s",
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]],
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]],
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
// Prepare flags based on the selected options
uint32_t pd_flags = 0;
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) {
pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM;
}
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) {
pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM;
}
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) {
pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
}
return pd_flags;
}

View File

@ -0,0 +1,51 @@
// Copyright 2015-2020 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 "sdkconfig.h"
#include "soc/uart_periph.h"
#include "soc/gpio_periph.h"
#include "esp_gdbstub_common.h"
#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM
void esp_gdbstub_target_init()
{
}
int esp_gdbstub_getchar()
{
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_RXFIFO_CNT) == 0) {
;
}
return REG_READ(UART_FIFO_AHB_REG(UART_NUM));
}
void esp_gdbstub_putchar(int c)
{
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_TXFIFO_CNT) >= 126) {
;
}
REG_WRITE(UART_FIFO_AHB_REG(UART_NUM), c);
}
int esp_gdbstub_readmem(intptr_t addr)
{
if (addr < 0x20000000 || addr >= 0x80000000) {
/* see cpu_configure_region_protection */
return -1;
}
uint32_t val_aligned = *(uint32_t *)(addr & (~3));
uint32_t shift = (addr & 3) * 8;
return (val_aligned >> shift) & 0xff;
}

View File

@ -0,0 +1,18 @@
// Copyright 2020 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.
#pragma once
/* Number of extra TIE defined registers, not listed in the XCHAL */
#define GDBSTUB_EXTRA_TIE_SIZE 1

View File

@ -40,6 +40,7 @@ typedef struct {
#define ESP_ROM_SPIFLASH_BP2 BIT4
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
#define ESP_ROM_SPIFLASH_QE BIT9
#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
#define FLASH_OP_MODE_RDCMD_DOUT 0x3B
#define ESP_ROM_FLASH_SECTOR_SIZE 0x1000

View File

@ -111,6 +111,7 @@ extern "C" {
#define ESP_ROM_SPIFLASH_BP2 BIT4
#define ESP_ROM_SPIFLASH_WR_PROTECT (ESP_ROM_SPIFLASH_BP0|ESP_ROM_SPIFLASH_BP1|ESP_ROM_SPIFLASH_BP2)
#define ESP_ROM_SPIFLASH_QE BIT9
#define ESP_ROM_SPIFLASH_BP_MASK_ISSI (BIT7 | BIT5 | BIT4 | BIT3 | BIT2)
#define FLASH_ID_GD25LQ32C 0xC86016

View File

@ -42,9 +42,18 @@
#include "esp32s2/rom/cache.h"
#include "esp32s2/rom/rtc.h"
#include "esp32s2/spiram.h"
#include "soc/periph_defs.h"
#include "esp32s2/dport_access.h"
#include "esp32s2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rtc.h"
#include "esp32s3/brownout.h"
#include "esp32s3/cache_err_int.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/rom/rtc.h"
#include "esp32s3/spiram.h"
#include "esp32s3/dport_access.h"
#include "esp32s3/memprot.h"
#include "soc/assist_debug_reg.h"
#endif
#include "bootloader_flash_config.h"
@ -53,8 +62,10 @@
#include "hal/rtc_io_hal.h"
#include "hal/wdt_hal.h"
#include "soc/rtc.h"
#include "soc/dport_reg.h"
#include "soc/efuse_reg.h"
#include "soc/periph_defs.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
#include "soc/spinlock.h"
@ -117,15 +128,20 @@ void IRAM_ATTR call_start_cpu1(void)
bootloader_init_mem();
#if CONFIG_ESP_CONSOLE_UART_NONE
ets_install_putc1(NULL);
ets_install_putc2(NULL);
esp_rom_install_channel_putc(1, NULL);
esp_rom_install_channel_putc(2, NULL);
#else // CONFIG_ESP_CONSOLE_UART_NONE
ets_install_uart_printf();
esp_rom_uart_set_as_console(CONFIG_ESP_CONSOLE_UART_NUM);
#endif
#if CONFIG_IDF_TARGET_ESP32
DPORT_REG_SET_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_PDEBUG_ENABLE | DPORT_APP_CPU_RECORD_ENABLE);
DPORT_REG_CLR_BIT(DPORT_APP_CPU_RECORD_CTRL_REG, DPORT_APP_CPU_RECORD_ENABLE);
#else
REG_WRITE(ASSIST_DEBUG_CORE_1_RCD_PDEBUGENABLE_REG, 1);
REG_WRITE(ASSIST_DEBUG_CORE_1_RCD_RECORDING_REG, 1);
#endif
s_cpu_up[1] = true;
ESP_EARLY_LOGI(TAG, "App cpu up.");
@ -153,23 +169,38 @@ static void start_other_core(void)
{
// If not the single core variant of ESP32 - check this since there is
// no separate soc_caps.h for the single core variant.
if (!REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
bool is_single_core = false;
#if CONFIG_IDF_TARGET_ESP32
is_single_core = REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU);
#endif
if (!is_single_core) {
ESP_EARLY_LOGI(TAG, "Starting app cpu, entry point is %p", call_start_cpu1);
#if CONFIG_IDF_TARGET_ESP32
Cache_Flush(1);
Cache_Read_Enable(1);
#endif
esp_cpu_unstall(1);
// Enable clock and reset APP CPU. Note that OpenOCD may have already
// enabled clock and taken APP CPU out of reset. In this case don't reset
// APP CPU again, as that will clear the breakpoints which may have already
// been set.
#if CONFIG_IDF_TARGET_ESP32
if (!DPORT_GET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN)) {
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN);
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_C_REG, DPORT_APPCPU_RUNSTALL);
DPORT_SET_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_A_REG, DPORT_APPCPU_RESETTING);
}
#elif CONFIG_IDF_TARGET_ESP32S3
if (!REG_GET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN)) {
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RUNSTALL);
REG_SET_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_RESETING);
}
#endif
ets_set_appcpu_boot_addr((uint32_t)call_start_cpu1);
volatile bool cpus_up = false;
@ -207,8 +238,6 @@ void IRAM_ATTR call_start_cpu0(void)
RESET_REASON rst_reas[1];
#endif
bootloader_init_mem();
// Move exception vectors to IRAM
cpu_hal_set_vecbase(&_init_start);
@ -259,6 +288,20 @@ void IRAM_ATTR call_start_cpu0(void)
#endif
#endif
#if CONFIG_IDF_TARGET_ESP32S3
/* Configure the mode of instruction cache : cache size, cache line size. */
extern void rom_config_instruction_cache_mode(uint32_t cfg_cache_size, uint8_t cfg_cache_ways, uint8_t cfg_cache_line_size);
rom_config_instruction_cache_mode(CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE, CONFIG_ESP32S3_ICACHE_ASSOCIATED_WAYS, CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_SIZE);
/* If we need use SPIRAM, we should use data cache.
Configure the mode of data : cache size, cache line size.*/
Cache_Suspend_DCache();
extern void rom_config_data_cache_mode(uint32_t cfg_cache_size, uint8_t cfg_cache_ways, uint8_t cfg_cache_line_size);
rom_config_data_cache_mode(CONFIG_ESP32S3_DATA_CACHE_SIZE, CONFIG_ESP32S3_DCACHE_ASSOCIATED_WAYS, CONFIG_ESP32S3_DATA_CACHE_LINE_SIZE);
Cache_Resume_DCache(0);
#endif
bootloader_init_mem();
#if CONFIG_SPIRAM_BOOT_INIT
if (esp_spiram_init() != ESP_OK) {
#if CONFIG_IDF_TARGET_ESP32
@ -282,11 +325,7 @@ void IRAM_ATTR call_start_cpu0(void)
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
s_cpu_up[0] = true;
#endif
#ifdef CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
ESP_EARLY_LOGI(TAG, "cpu freq: %d", CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
#else
ESP_EARLY_LOGI(TAG, "cpu freq: %d", CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ);
#endif
ESP_EARLY_LOGI(TAG, "Pro cpu up.");
#if SOC_CPU_CORES_NUM > 1 // there is no 'single-core mode' for natively single-core processors
@ -294,7 +333,11 @@ void IRAM_ATTR call_start_cpu0(void)
start_other_core();
#else
ESP_EARLY_LOGI(TAG, "Single core mode");
#if CONFIG_IDF_TARGET_ESP32
DPORT_CLEAR_PERI_REG_MASK(DPORT_APPCPU_CTRL_B_REG, DPORT_APPCPU_CLKGATE_EN); // stop the other core
#elif CONFIG_IDF_TARGET_ESP32S3
REG_CLR_BIT(SYSTEM_CORE_1_CONTROL_0_REG, SYSTEM_CONTROL_CORE_1_CLKGATE_EN);
#endif
#endif // !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
#endif // SOC_CPU_CORES_NUM > 1
@ -368,7 +411,11 @@ void IRAM_ATTR call_start_cpu0(void)
intr_matrix_clear();
#ifdef CONFIG_ESP_CONSOLE_UART
esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_UART_NUM, APB_CLK_FREQ, CONFIG_ESP_CONSOLE_UART_BAUDRATE);
uint32_t clock_hz = rtc_clk_apb_freq_get();
#if CONFIG_IDF_TARGET_ESP32S3
clock_hz = UART_CLK_FREQ_ROM; // From esp32-s3 on, UART clock source is selected to XTAL in ROM
#endif
esp_rom_uart_set_clock_baudrate(CONFIG_ESP_CONSOLE_UART_NUM, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE);
#endif
rtcio_hal_unhold_all();

View File

@ -45,6 +45,12 @@
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#include "soc/rtc_cntl_reg.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/cache_err_int.h"
#include "esp32s3/memprot.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#include "soc/rtc_cntl_reg.h"
#endif
#include "esp_private/panic_internal.h"
@ -378,6 +384,78 @@ static inline void print_memprot_err_details(const void *f)
panic_print_hex( (uint32_t)fault_addr );
panic_print_str(" not permitted.\r\n");
}
#elif CONFIG_IDF_TARGET_ESP32S3
static inline void print_cache_err_details(const void* f)
{
uint32_t vaddr = 0, size = 0;
uint32_t status;
status = REG_READ(EXTMEM_CACHE_ILG_INT_ST_REG);
for (int i = 0; i < 32; i++) {
switch (status & BIT(i)) {
case EXTMEM_ICACHE_SYNC_OP_FAULT_ST:
//TODO, which size should fetch
//vaddr = REG_READ(EXTMEM_ICACHE_MEM_SYNC0_REG);
//size = REG_READ(EXTMEM_ICACHE_MEM_SYNC1_REG);
panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
panic_print_hex(vaddr);
panic_print_str("(0x");
panic_print_hex(size);
panic_print_str(")\r\n");
break;
case EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST:
//TODO, which size should fetch
vaddr = REG_READ(EXTMEM_ICACHE_PRELOAD_ADDR_REG);
size = REG_READ(EXTMEM_ICACHE_PRELOAD_SIZE_REG);
panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
panic_print_hex(vaddr);
panic_print_str("(0x");
panic_print_hex(size);
panic_print_str(")\r\n");
break;
case EXTMEM_DCACHE_SYNC_OP_FAULT_ST:
//TODO, which size should fetch
//vaddr = REG_READ(EXTMEM_DCACHE_MEM_SYNC0_REG);
//size = REG_READ(EXTMEM_DCACHE_MEM_SYNC1_REG);
panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
panic_print_hex(vaddr);
panic_print_str("(0x");
panic_print_hex(size);
panic_print_str(")\r\n");
break;
case EXTMEM_DCACHE_PRELOAD_OP_FAULT_ST:
//TODO, which size should fetch
vaddr = REG_READ(EXTMEM_DCACHE_PRELOAD_ADDR_REG);
size = REG_READ(EXTMEM_DCACHE_PRELOAD_SIZE_REG);
panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
panic_print_hex(vaddr);
panic_print_str("(0x");
panic_print_hex(size);
panic_print_str(")\r\n");
break;
case EXTMEM_DCACHE_WRITE_FLASH_ST:
panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
break;
case EXTMEM_MMU_ENTRY_FAULT_ST:
vaddr = REG_READ(EXTMEM_CACHE_MMU_FAULT_VADDR_REG);
panic_print_str("MMU entry fault error occurred while accessing the address 0x");
panic_print_hex(vaddr);
if (REG_READ(EXTMEM_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
panic_print_str(" (invalid mmu entry)");
}
panic_print_str("\r\n");
break;
default:
break;
}
}
panic_print_str("\r\n");
}
static inline void print_memprot_err_details(const void *f)
{
}
#endif
static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseudo_excause)
@ -409,7 +487,7 @@ static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseu
"Interrupt wdt timeout on CPU1",
#if CONFIG_IDF_TARGET_ESP32
"Cache disabled but cached memory region accessed",
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
"Cache exception",
#endif
};
@ -426,7 +504,7 @@ static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseu
info->exception = PANIC_EXCEPTION_DEBUG;
}
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (frame->exccause == PANIC_RSN_CACHEERR) {
if ( esp_memprot_is_assoc_intr_any() ) {
info->details = print_memprot_err_details;

View File

@ -48,14 +48,16 @@
#include "esp32/rom/cache.h"
#include "esp32/clk.h"
#include "esp32/rom/rtc.h"
#include "esp32/rom/uart.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#include "esp32s2/rom/cache.h"
#include "esp32s2/rom/rtc.h"
#include "esp32s2/rom/ets_sys.h"
#include "soc/extmem_reg.h"
#include "esp32s2/rom/uart.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/rom/rtc.h"
#include "soc/extmem_reg.h"
#endif
// If light sleep time is less than that, don't power down flash
@ -68,6 +70,8 @@
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ
#elif CONFIG_IDF_TARGET_ESP32S2
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ
#elif CONFIG_IDF_TARGET_ESP32S3
#define DEFAULT_CPU_FREQ_MHZ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ
#endif
#if defined(CONFIG_IDF_TARGET_ESP32)
@ -318,7 +322,7 @@ static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
#ifdef CONFIG_IDF_TARGET_ESP32
uint32_t result = rtc_sleep_start(s_config.wakeup_triggers, reject_triggers);
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
uint32_t result = rtc_sleep_start(s_config.wakeup_triggers, reject_triggers, 1);
#endif
@ -524,7 +528,7 @@ esp_err_t esp_sleep_enable_ulp_wakeup(void)
#else // CONFIG_ESP32_ULP_COPROC_ENABLED
return ESP_ERR_INVALID_STATE;
#endif // CONFIG_ESP32_ULP_COPROC_ENABLED
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
return ESP_OK;
#endif
@ -720,6 +724,9 @@ esp_err_t esp_sleep_enable_wifi_wakeup(void)
#elif CONFIG_IDF_TARGET_ESP32S2
s_config.wakeup_triggers |= RTC_WIFI_TRIG_EN;
return ESP_OK;
#elif CONFIG_IDF_TARGET_ESP32S3
s_config.wakeup_triggers |= RTC_MAC_TRIG_EN;
return ESP_OK;
#endif
}
@ -732,7 +739,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
#ifdef CONFIG_IDF_TARGET_ESP32
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_SLP_WAKEUP_CAUSE_REG, RTC_CNTL_WAKEUP_CAUSE);
#endif

View File

@ -59,12 +59,15 @@
// [refactor-todo] make this file completely target-independent
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#include "esp32/spiram.h"
#include "esp32/brownout.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#include "esp32s2/spiram.h"
#include "esp32s2/brownout.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#include "esp32s3/spiram.h"
#include "esp32s3/brownout.h"
#endif
@ -311,6 +314,8 @@ static void start_cpu0_default(void)
{
ESP_EARLY_LOGI(TAG, "Pro cpu start user code");
int cpu_freq = esp_clk_cpu_freq();
ESP_EARLY_LOGI(TAG, "cpu freq: %d", cpu_freq);
// Display information about the current running image.
if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) {

View File

@ -10,6 +10,8 @@
#include "esp_rom_uart.h"
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/memprot.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/memprot.h"
#endif

View File

@ -25,6 +25,8 @@
#include "esp32/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rtc.h"
#endif
#include "esp_private/startup_internal.h"

View File

@ -26,6 +26,9 @@
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#include "esp32s2/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#include "esp32s3/rom/rtc.h"
#endif

View File

@ -26,7 +26,7 @@ menu "High resolution timer (esp_timer)"
choice ESP_TIMER_IMPL
prompt "Hardware timer to use for esp_timer"
default ESP_TIMER_IMPL_TG0_LAC if IDF_TARGET_ESP32
default ESP_TIMER_IMPL_SYSTIMER if IDF_TARGET_ESP32S2
default ESP_TIMER_IMPL_SYSTIMER
help
esp_timer APIs can be implemented using different hardware timers.
@ -47,7 +47,7 @@ menu "High resolution timer (esp_timer)"
config ESP_TIMER_IMPL_SYSTIMER
bool "SYSTIMER"
depends on IDF_TARGET_ESP32S2
depends on !IDF_TARGET_ESP32
endchoice

View File

@ -103,8 +103,13 @@ void esp_timer_impl_advance(int64_t time_us)
esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
{
s_alarm_handler = alarm_handler;
#ifdef SOC_SYSTIMER_INT_LEVEL
int int_type = 0;
#else
int int_type = ESP_INTR_FLAG_EDGE;
#endif // SOC_SYSTIMER_INT_LEVEL
esp_err_t err = esp_intr_alloc(ETS_SYSTIMER_TARGET2_EDGE_INTR_SOURCE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM | ESP_INTR_FLAG_EDGE,
ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM | int_type,
&timer_alarm_isr, NULL, &s_timer_interrupt_handle);
if (err != ESP_OK) {
@ -112,9 +117,10 @@ esp_err_t esp_timer_impl_init(intr_handler_t alarm_handler)
goto err_intr_alloc;
}
systimer_hal_enable_counter(SYSTIMER_COUNTER_0);
systimer_hal_init();
systimer_hal_enable_counter(SYSTIMER_COUNTER_0);
systimer_hal_select_alarm_mode(SYSTIMER_ALARM_2, SYSTIMER_ALARM_MODE_ONESHOT);
systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_2, SYSTIMER_COUNTER_0);
/* TODO: if SYSTIMER is used for anything else, access to SYSTIMER_INT_ENA_REG has to be
* protected by a shared spinlock. Since this code runs as part of early startup, this

View File

@ -24,7 +24,6 @@
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "soc/frc_timer_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

View File

@ -1,5 +1,13 @@
idf_build_get_property(idf_target IDF_TARGET)
# remove these when wifi support is ready on esp32-s3
if(${idf_target} STREQUAL "esp32s3")
idf_component_register(INCLUDE_DIRS "include"
REQUIRES esp_event
PRIV_REQUIRES wpa_supplicant nvs_flash esp_netif)
return()
endif()
if(CONFIG_ESP32_NO_BLOBS OR CONFIG_ESP32S2_NO_BLOBS)
set(link_binary_libs 0)
set(ldfragments)

View File

@ -0,0 +1,13 @@
// Copyright 2015-2020 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.

View File

@ -0,0 +1,13 @@
// Copyright 2016-2020 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.

View File

@ -57,7 +57,7 @@ menu "Serial flasher config"
config ESPTOOLPY_WITH_STUB
# Only real reason to disable this is when ESP32-S2 Secure Download Mode is set
bool
default "y"
default "y" if !IDF_ENV_FPGA
depends on !SECURE_ENABLE_SECURE_ROM_DL_MODE
choice ESPTOOLPY_FLASHMODE

@ -1 +1 @@
Subproject commit 10225816df4c9c1b078e677e8a75a87778786ad1
Subproject commit 09549c03111a2b330371d361d56227a457af66c5

View File

@ -125,6 +125,8 @@ int xt_clock_freq(void) __attribute__((deprecated));
#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/ets_sys.h"
#endif
#if defined(CONFIG_FREERTOS_ASSERT_DISABLE)

View File

@ -39,6 +39,8 @@ that are implemented in C.
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#endif
#ifdef XT_RTOS_TIMER_INT

View File

@ -214,6 +214,18 @@ static inline void periph_ll_disable_clk_set_rst(periph_module_t periph)
DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false));
}
static inline void IRAM_ATTR periph_ll_wifi_bt_module_enable_clk_clear_rst(void)
{
DPORT_SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M);
DPORT_CLEAR_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0);
}
static inline void IRAM_ATTR periph_ll_wifi_bt_module_disable_clk_set_rst(void)
{
DPORT_CLEAR_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_WIFI_BT_COMMON_M);
DPORT_SET_PERI_REG_MASK(SYSTEM_CORE_RST_EN_REG, 0);
}
static inline void periph_ll_reset(periph_module_t periph)
{
DPORT_SET_PERI_REG_MASK(periph_ll_get_rst_en_reg(periph), periph_ll_get_rst_en_mask(periph, false));
@ -228,3 +240,4 @@ static inline bool IRAM_ATTR periph_ll_periph_enabled(periph_module_t periph)
#ifdef __cplusplus
}
#endif

View File

@ -55,14 +55,14 @@ typedef enum {
static inline void rtcio_ll_function_select(int rtcio_num, rtcio_ll_func_t func)
{
if (func == RTCIO_FUNC_RTC) {
SENS.sar_io_mux_conf.iomux_clk_gate_en = 1;
// SENS.sar_io_mux_conf.iomux_clk_gate_en = 1;
// 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
SET_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux));
//0:RTC FUNCTION 1,2,3:Reserved
SET_PERI_REG_BITS(rtc_io_desc[rtcio_num].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, SOC_PIN_FUNC_RTC_IO, rtc_io_desc[rtcio_num].func);
} else if (func == RTCIO_FUNC_DIGITAL) {
CLEAR_PERI_REG_MASK(rtc_io_desc[rtcio_num].reg, (rtc_io_desc[rtcio_num].mux));
SENS.sar_io_mux_conf.iomux_clk_gate_en = 0;
// SENS.sar_io_mux_conf.iomux_clk_gate_en = 0;
}
}

View File

@ -40,7 +40,7 @@ typedef struct {
Note: Unreasonable settings can cause waveform to be oversaturated. Range: -128 ~ 127. */
} dac_cw_config_t;
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
/**
* @brief DAC digital controller (DMA mode) work mode.

View File

@ -0,0 +1,17 @@
#pragma once
#define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 14.4
// SHA256 hardware throughput at 240MHz, threshold set lower than worst case
#define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 19.8
// esp_sha() time to process 32KB of input data from RAM
#define IDF_PERFORMANCE_MAX_TIME_SHA1_32KB 1000
#define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 900
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 14000
#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 100000
#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 60000
#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 600000
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING 32
#define IDF_PERFORMANCE_MAX_SPI_PER_TRANS_NO_POLLING_NO_DMA 30

View File

@ -23,6 +23,8 @@
#include "esp32/rom/ets_sys.h" // will be removed in idf v5.0
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/ets_sys.h"
#endif
#ifdef __cplusplus

View File

View File

View File

View File

@ -19,6 +19,8 @@
#include "esp32/sha.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/sha.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/sha.h"
#endif
#include <mbedtls/sha1.h>

View File

@ -32,6 +32,8 @@ extern "C" {
#include "esp32/aes.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/aes.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/aes.h"
#endif
typedef esp_aes_context mbedtls_aes_context;

View File

@ -0,0 +1,369 @@
/**
* \brief AES block cipher, ESP32 hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*
*/
#ifndef ESP_AES_H
#define ESP_AES_H
#include "esp_types.h"
#include "esp32s3/rom/aes.h"
#ifdef __cplusplus
extern "C" {
#endif
/* padlock.c and aesni.c rely on these values! */
#define ESP_AES_ENCRYPT 1
#define ESP_AES_DECRYPT 0
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/**
* \brief AES context structure
*
* \note buf is able to hold 32 extra bytes, which can be used:
* - for alignment purposes if VIA padlock is used, and/or
* - to simplify key expansion in the 256-bit case by
* generating an extra round key
*/
typedef struct {
uint8_t key_bytes;
volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */
uint8_t key[32];
} esp_aes_context;
/**
* \brief The AES XTS context-type definition.
*/
typedef struct {
esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak
computation. */
} esp_aes_xts_context;
/**
* \brief Lock access to AES hardware unit
*
* AES hardware unit can only be used by one
* consumer at a time.
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_acquire_hardware( void );
/**
* \brief Unlock access to AES hardware unit
*
* esp_aes_xxx API calls automatically manage locking & unlocking of
* hardware, this function is only needed if you want to call
* ets_aes_xxx functions directly.
*/
void esp_aes_release_hardware( void );
/**
* \brief Initialize AES context
*
* \param ctx AES context to be initialized
*/
void esp_aes_init( esp_aes_context *ctx );
/**
* \brief Clear AES context
*
* \param ctx AES context to be cleared
*/
void esp_aes_free( esp_aes_context *ctx );
/*
* \brief This function initializes the specified AES XTS context.
*
* It must be the first API called before using
* the context.
*
* \param ctx The AES XTS context to initialize.
*/
void esp_aes_xts_init( esp_aes_xts_context *ctx );
/**
* \brief This function releases and clears the specified AES XTS context.
*
* \param ctx The AES XTS context to clear.
*/
void esp_aes_xts_free( esp_aes_xts_context *ctx );
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
/**
* \brief AES set key schedule (encryption or decryption)
*
* \param ctx AES context to be initialized
* \param key encryption key
* \param keybits must be 128, 192 or 256
*
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
*/
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
/**
* \brief AES-ECB block encryption/decryption
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param input 16-byte input block
* \param output 16-byte output block
*
* \return 0 if successful
*/
int esp_aes_crypt_ecb( esp_aes_context *ctx, int mode, const unsigned char input[16], unsigned char output[16] );
/**
* \brief AES-CBC buffer encryption/decryption
* Length should be a multiple of the block
* size (16 bytes)
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful, or ERR_AES_INVALID_INPUT_LENGTH
*/
int esp_aes_crypt_cbc( esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB128 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv_off offset in IV (updated after use)
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int esp_aes_crypt_cfb128( esp_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CFB8 buffer encryption/decryption.
*
* Note: Due to the nature of CFB you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \note Upon exit, the content of the IV is updated so that you can
* call the function same function again on the following
* block(s) of data and get the same result as if it was
* encrypted in one call. This allows a "streaming" usage.
* If on the other hand you need to retain the contents of the
* IV, you should either save it manually or use the cipher
* module instead.
*
* \param ctx AES context
* \param mode AES_ENCRYPT or AES_DECRYPT
* \param length length of the input data
* \param iv initialization vector (updated after use)
* \param input buffer holding the input data
* \param output buffer holding the output data
*
* \return 0 if successful
*/
int esp_aes_crypt_cfb8( esp_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief AES-CTR buffer encryption/decryption
*
* Warning: You have to keep the maximum use of your counter in mind!
*
* Note: Due to the nature of CTR you should use the same key schedule for
* both encryption and decryption. So a context initialized with
* esp_aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT.
*
* \param ctx AES context
* \param length The length of the data
* \param nc_off The offset in the current stream_block (for resuming
* within current cipher stream). The offset pointer to
* should be 0 at the start of a stream.
* \param nonce_counter The 128-bit nonce and counter.
* \param stream_block The saved stream-block for resuming. Is overwritten
* by the function.
* \param input The input data stream
* \param output The output data stream
*
* \return 0 if successful
*/
int esp_aes_crypt_ctr( esp_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief This function performs an AES-OFB (Output Feedback Mode)
* encryption or decryption operation.
*
* \param ctx The AES context to use for encryption or decryption.
* It must be initialized and bound to a key.
* \param length The length of the input data.
* \param iv_off The offset in IV (updated after use).
* It must point to a valid \c size_t.
* \param iv The initialization vector (updated after use).
* It must be a readable and writeable buffer of \c 16 Bytes.
* \param input The buffer holding the input data.
* It must be readable and of size \p length Bytes.
* \param output The buffer holding the output data.
* It must be writeable and of size \p length Bytes.
*
* \return \c 0 on success.
*/
int esp_aes_crypt_ofb( esp_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
/**
* \brief This function prepares an XTS context for encryption and
* sets the encryption key.
*
* \param ctx The AES XTS context to which the key should be bound.
* \param key The encryption key. This is comprised of the XTS key1
* concatenated with the XTS key2.
* \param keybits The size of \p key passed in bits. Valid options are:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure.
*/
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits );
/**
* \brief Internal AES block encryption function
* (Only exposed to allow overriding it,
* see AES_ENCRYPT_ALT)
*
* \param ctx AES context
* \param input Plaintext block
* \param output Output (ciphertext) block
*/
int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_encrypt */
void esp_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/**
* \brief Internal AES block decryption function
* (Only exposed to allow overriding it,
* see AES_DECRYPT_ALT)
*
* \param ctx AES context
* \param input Ciphertext block
* \param output Output (plaintext) block
*/
int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] );
/** Deprecated, see esp_aes_internal_decrypt */
void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated));
/** AES-XTS buffer encryption/decryption */
int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* aes.h */

View File

@ -0,0 +1,40 @@
/**
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*
*/
#ifndef ESP_CRYPTO_DMA_H
#define ESP_CRYPTO_DMA_H
#include <freertos/FreeRTOS.h>
#ifdef __cplusplus
extern "C" {
#endif
/* Since crypto DMA is shared between DMA-AES and SHA blocks
* Needs to be taken by respective blocks before using Crypto DMA
*/
extern _lock_t crypto_dma_lock;
#ifdef __cplusplus
}
#endif
#endif /* crypto_dma.h */

View File

@ -0,0 +1,238 @@
/**
* \brief AES block cipher, ESP32C hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2019-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
*
*/
#ifndef ESP_GCM_H
#define ESP_GCM_H
#include "aes.h"
#include "mbedtls/cipher.h"
#ifdef __cplusplus
extern "C" {
#endif
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function.*/
typedef enum {
ESP_AES_GCM_STATE_INIT,
ESP_AES_GCM_STATE_UPDATE,
ESP_AES_GCM_STATE_FINISH
} esp_aes_gcm_state;
/**
* \brief The GCM context structure.
*/
typedef struct {
uint8_t H[16]; /*!< Initial hash value */
uint8_t ghash[16]; /*!< GHASH value. */
uint8_t J0[16];
uint64_t HL[16]; /*!< Precalculated HTable low. */
uint64_t HH[16]; /*!< Precalculated HTable high. */
uint8_t ori_j0[16]; /*!< J0 from first iteration. */
const uint8_t *iv;
size_t iv_len; /*!< The length of IV. */
uint64_t aad_len; /*!< The total length of the additional data. */
size_t data_len;
int mode;
const unsigned char *aad; /*!< The additional data. */
esp_aes_context aes_ctx;
esp_aes_gcm_state gcm_state;
} esp_gcm_context;
/**
* \brief This function initializes the specified GCM context
*
* \param ctx The GCM context to initialize.
*/
void esp_aes_gcm_init( esp_gcm_context *ctx);
/**
* \brief This function associates a GCM context with a
* key.
*
* \param ctx The GCM context to initialize.
* \param cipher The 128-bit block cipher to use.
* \param key The encryption key.
* \param keybits The key size in bits. Valid options are:
* <ul><li>128 bits</li>
* <li>192 bits</li>
* <li>256 bits</li></ul>
*
* \return \c 0 on success.
* \return A cipher-specific error code on failure.
*/
int esp_aes_gcm_setkey( esp_gcm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );
/**
* \brief This function starts a GCM encryption or decryption
* operation.
*
* \param ctx The GCM context.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data, or NULL
* if \p add_len is 0.
* \param add_len The length of the additional data. If 0,
* \p add is NULL.
*
* \return \c 0 on success.
*/
int esp_aes_gcm_starts( esp_gcm_context *ctx,
int mode,
const unsigned char *iv,
size_t iv_len,
const unsigned char *aad,
size_t aad_len );
/**
* \brief This function feeds an input buffer into an ongoing GCM
* encryption or decryption operation.
*
* ` The function expects input to be a multiple of 16
* Bytes. Only the last call before calling
* mbedtls_gcm_finish() can be less than 16 Bytes.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/
int esp_aes_gcm_update( esp_gcm_context *ctx,
size_t length,
const unsigned char *input,
unsigned char *output );
/**
* \brief This function finishes the GCM operation and generates
* the authentication tag.
*
* It wraps up the GCM stream, and generates the
* tag. The tag can have a maximum length of 16 Bytes.
*
* \param ctx The GCM context.
* \param tag The buffer for holding the tag.
* \param tag_len The length of the tag to generate. Must be at least four.
*
* \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/
int esp_aes_gcm_finish( esp_gcm_context *ctx,
unsigned char *tag,
size_t tag_len );
/**
* \brief This function clears a GCM context
*
* \param ctx The GCM context to clear.
*/
void esp_aes_gcm_free( esp_gcm_context *ctx);
/**
* \brief This function performs GCM encryption or decryption of a buffer.
*
* \note For encryption, the output buffer can be the same as the
* input buffer. For decryption, the output buffer cannot be
* the same as input buffer. If the buffers overlap, the output
* buffer must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context to use for encryption or decryption.
* \param mode The operation to perform: #MBEDTLS_GCM_ENCRYPT or
* #MBEDTLS_GCM_DECRYPT.
* \param length The length of the input data. This must be a multiple of
* 16 except in the last call before mbedtls_gcm_finish().
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
* \param tag_len The length of the tag to generate.
* \param tag The buffer for holding the tag.
*
* \return \c 0 on success.
*/
int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
int mode,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *input,
unsigned char *output,
size_t tag_len,
unsigned char *tag );
/**
* \brief This function performs a GCM authenticated decryption of a
* buffer.
*
* \note For decryption, the output buffer cannot be the same as
* input buffer. If the buffers overlap, the output buffer
* must trail at least 8 Bytes behind the input buffer.
*
* \param ctx The GCM context.
* \param length The length of the input data. This must be a multiple
* of 16 except in the last call before mbedtls_gcm_finish().
* \param iv The initialization vector.
* \param iv_len The length of the IV.
* \param add The buffer holding the additional data.
* \param add_len The length of the additional data.
* \param tag The buffer holding the tag.
* \param tag_len The length of the tag.
* \param input The buffer holding the input data.
* \param output The buffer for holding the output data.
*
* \return 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
*/
int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
size_t length,
const unsigned char *iv,
size_t iv_len,
const unsigned char *add,
size_t add_len,
const unsigned char *tag,
size_t tag_len,
const unsigned char *input,
unsigned char *output );
#ifdef __cplusplus
}
#endif
#endif /* gcm.h */

View File

@ -0,0 +1,165 @@
// Copyright 2019-2020 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.
#ifndef _ESP_SHA_H_
#define _ESP_SHA_H_
#include "esp32s3/rom/sha.h"
/** @brief Low-level support functions for the hardware SHA engine using DMA
*
* @note If you're looking for a SHA API to use, try mbedtls component
* mbedtls/shaXX.h. That API supports hardware acceleration.
*
* The API in this header provides some building blocks for implementing a
* full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha().
*
* Some technical details about the hardware SHA engine:
*
* - The crypto DMA is shared between the SHA and AES engine, it is not
* possible for them to run calcalutions in parallel.
*
*/
#ifdef __cplusplus
extern "C" {
#endif
/* Defined in rom/sha.h */
typedef SHA_TYPE esp_sha_type;
/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine
*
* @note For more versatile SHA calculations, where data doesn't need
* to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs.
*
* @note It is not necessary to lock any SHA hardware before calling
* this function, thread safety is managed internally.
*
* @param sha_type SHA algorithm to use.
*
* @param input Input data buffer.
*
* @param ilen Length of input data in bytes.
*
* @param output Buffer for output SHA digest. Output is 20 bytes for
* sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for
* sha_type SHA2_384, 64 bytes for sha_type SHA2_512.
*/
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output);
/** @brief Execute SHA block operation using DMA
*
* @note This is a piece of a SHA algorithm, rather than an entire SHA
* algorithm.
*
* @note Call esp_sha_aquire_hardware() before calling this
* function.
*
* @param sha_type SHA algorithm to use.
*
* @param input Pointer to the input data. Block size is
* determined by algorithm (SHA1/SHA2_256 = 64 bytes,
* SHA2_384/SHA2_512 = 128 bytes)
*
* @param ilen length of input data should be multiple of block length.
*
* @param buf Pointer to blocks of data that will be prepended
* to data_block before hashing. Useful when there is two sources of
* data that need to be efficiently calculated in a single SHA DMA
* operation.
*
* @param buf_len length of buf data should be multiple of block length.
* Should not be longer than the maximum amount of bytes in a single block
* (128 bytes)
*
* @param is_first_block If this parameter is true, the SHA state will
* be initialised (with the initial state of the given SHA algorithm)
* before the block is calculated. If false, the existing state of the
* SHA engine will be used.
*
* @param t The number of bits for the SHA512/t hash function, with
* output truncated to t bits. Used for calculating the inital hash.
* t is any positive integer between 1 and 512, except 384.
*
* @return 0 if successful
*/
int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
const void *buf, uint32_t buf_len, bool is_first_block);
/**
* @brief Read out the current state of the SHA digest
*
* @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm.
*
* @note Call esp_sha_aquire_hardware() before calling this
* function.
*
* If the SHA suffix padding block has been executed already, the
* value that is read is the SHA digest.
* Otherwise, the value that is read is an interim SHA state.
*
* @param sha_type SHA algorithm in use.
* @param digest_state Pointer to a memory buffer to hold the SHA state. Size
* is 20 bytes (SHA1), 32 bytes (SHA2_256), or 64 bytes (SHA2_384, SHA2_512).
*/
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state);
/**
* @brief Set the current state of the SHA digest
*
* @note Call esp_sha_aquire_hardware() before calling this
* function.
*
* When resuming a
*
* @param sha_type SHA algorithm in use.
* @param digest_state
*/
void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state);
/**
* @brief Enables the SHA and crypto DMA peripheral and takes the
* locks for both of them.
*/
void esp_sha_acquire_hardware(void);
/**
* @brief Disables the SHA and crypto DMA peripheral and releases the
* locks.
*/
void esp_sha_release_hardware(void);
/**
* @brief Sets the initial hash value for SHA512/t.
*
* @note Is generated according to the algorithm described in the TRM,
* chapter SHA-Accelerator
*
* @note The engine must be locked until the value is used for an operation
* or read out. Else you risk another operation overwriting it.
*
* @param t
*
* @return 0 if successful
*/
int esp_sha_512_t_init_hash(uint16_t t);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -29,6 +29,23 @@ extern "C" {
#if defined(MBEDTLS_GCM_ALT)
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/gcm.h"
typedef esp_gcm_context mbedtls_gcm_context;
#define mbedtls_gcm_init esp_aes_gcm_init
#define mbedtls_gcm_free esp_aes_gcm_free
#define mbedtls_gcm_setkey esp_aes_gcm_setkey
#define mbedtls_gcm_starts esp_aes_gcm_starts
#define mbedtls_gcm_update esp_aes_gcm_update
#define mbedtls_gcm_finish esp_aes_gcm_finish
#define mbedtls_gcm_auth_decrypt esp_aes_gcm_auth_decrypt
#define mbedtls_gcm_crypt_and_tag esp_aes_gcm_crypt_and_tag
#endif // CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/gcm.h"

View File

@ -29,6 +29,28 @@ extern "C" {
#if defined(MBEDTLS_SHA1_ALT)
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/sha.h"
typedef enum {
ESP_SHA1_STATE_INIT,
ESP_SHA1_STATE_IN_PROCESS
} esp_sha1_state;
/**
* \brief SHA-1 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int first_block; /*!< if first then true else false */
esp_sha_type mode;
esp_sha1_state sha_state;
} mbedtls_sha1_context;
#endif //CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/sha.h"

View File

@ -29,6 +29,29 @@ extern "C" {
#if defined(MBEDTLS_SHA256_ALT)
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/sha.h"
typedef enum {
ESP_SHA256_STATE_INIT,
ESP_SHA256_STATE_IN_PROCESS
} esp_sha256_state;
/**
* \brief SHA-256 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int first_block; /*!< if first then true, else false */
esp_sha_type mode;
esp_sha256_state sha_state;
}
mbedtls_sha256_context;
#endif //CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32S2

View File

@ -30,6 +30,42 @@ extern "C" {
#if defined(MBEDTLS_SHA512_ALT)
#if CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/sha.h"
typedef enum {
ESP_SHA512_STATE_INIT,
ESP_SHA512_STATE_IN_PROCESS
} esp_sha512_state;
/**
* \brief SHA-512 context structure
*/
typedef struct {
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[128]; /*!< data block being processed */
int first_block;
esp_sha_type mode;
uint32_t t_val; /*!< t_val for 512/t mode */
esp_sha512_state sha_state;
} mbedtls_sha512_context;
/**
* @brief Sets the specfic algorithm for SHA512
*
* @param ctx The mbedtls sha512 context
*
* @param type The mode, used for setting SHA2_512224 and SHA2_512256:
*
*/
void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type);
/* For SHA512/t mode the intial hash value will depend on t */
void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val);
#endif //CONFIG_IDF_TARGET_ESP32S3
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/sha.h"

View File

@ -35,12 +35,18 @@
#include "esp32s2/rom/rtc.h"
#include "esp32s2/clk.h"
#include "esp32s2/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/rtc.h"
#include "esp32s3/clk.h"
#include "esp32s3/rtc.h"
#endif
#if defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC ) \
|| defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 ) \
|| defined( CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC ) \
|| defined( CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC_FRC1 )
|| defined( CONFIG_ESP32S2_TIME_SYSCALL_USE_RTC_FRC1 ) \
|| defined( CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC ) \
|| defined( CONFIG_ESP32S3_TIME_SYSCALL_USE_RTC_FRC1 )
#define WITH_RTC 1
#endif

View File

@ -31,6 +31,8 @@
#include "esp32/rom/libc_stubs.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/libc_stubs.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/libc_stubs.h"
#endif
static struct _reent s_reent;

View File

@ -25,7 +25,6 @@
#include "esp_system.h"
#include "esp_attr.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"

View File

@ -18,10 +18,8 @@
extern "C" {
#endif
//Chip specific TWAI related macros
//Any even number from 2 to 32768
#define TWAI_BRP_IS_VALID(brp) ((brp) >= 2 && (brp) <= 32768 && ((brp) & 0x1) == 0)
#define TWAI_BRP_MAX 32768
#define TWAI_BRP_MIN 2
#define TWAI_BRP_MAX 32768
#ifdef __cplusplus
}

View File

@ -17,4 +17,4 @@
#include "soc.h"
/* Hardware random number generator register */
#define WDEV_RND_REG 0x60035110
#define WDEV_RND_REG 0x6003507C

View File

@ -334,6 +334,7 @@ static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
I2C_WRITEREG_MASK_RTC(I2C_DIG_REG, I2C_DIG_REG_EXT_DIG_DREG, dbias);
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL);
rtc_clk_apb_freq_update(80 * MHZ);
ets_update_cpu_frequency(cpu_freq_mhz);
}

View File

@ -57,7 +57,7 @@ const size_t soc_memory_type_count = sizeof(soc_memory_types) / sizeof(soc_memor
*/
const soc_memory_region_t soc_memory_regions[] = {
#ifdef CONFIG_SPIRAM
{ SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH - SOC_EXTRAM_DATA_LOW, 4, 0}, //SPI SRAM, if available
{ SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_SIZE, 4, 0}, //SPI SRAM, if available
#endif
#if CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB
{ 0x40374000, 0x4000, 3, 0}, //Level 1, IRAM
@ -101,7 +101,9 @@ SOC_RESERVE_MEMORY_REGION((intptr_t)&_iram_start - I_D_OFFSET, (intptr_t)&_iram_
#endif
#ifdef CONFIG_SPIRAM
SOC_RESERVE_MEMORY_REGION( SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH, extram_data_region); //SPI RAM gets added later if needed, in spiram.c; reserve it for now
/* Reserve the whole possible SPIRAM region here, spiram.c will add some or all of this
* memory to heap depending on the actual SPIRAM chip size. */
SOC_RESERVE_MEMORY_REGION( SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH, extram_data_region);
#endif
#if CONFIG_ESP32S3_TRACEMEM_RESERVE_DRAM > 0

View File

@ -28,6 +28,11 @@
#include "esp32s2/rom/cache.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/cache.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#endif
#include <soc/soc.h>
#include <soc/dport_reg.h>
@ -304,6 +309,11 @@ static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t *saved_st
*saved_state = ret;
#elif CONFIG_IDF_TARGET_ESP32S2
*saved_state = Cache_Suspend_ICache();
#elif CONFIG_IDF_TARGET_ESP32S3
uint32_t icache_state, dcache_state;
icache_state = Cache_Suspend_ICache() << 16;
dcache_state = Cache_Suspend_DCache();
*saved_state = icache_state | dcache_state;
#endif
}
@ -323,6 +333,9 @@ static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_sta
#endif
#elif CONFIG_IDF_TARGET_ESP32S2
Cache_Resume_ICache(saved_state);
#elif CONFIG_IDF_TARGET_ESP32S3
Cache_Resume_DCache(saved_state & 0xffff);
Cache_Resume_ICache(saved_state >> 16);
#endif
}
@ -335,6 +348,8 @@ IRAM_ATTR bool spi_flash_cache_enabled(void)
#endif
#elif CONFIG_IDF_TARGET_ESP32S2
bool result = (REG_GET_BIT(EXTMEM_PRO_ICACHE_CTRL_REG, EXTMEM_PRO_ICACHE_ENABLE) != 0);
#elif CONFIG_IDF_TARGET_ESP32S3
bool result = (REG_GET_BIT(EXTMEM_ICACHE_CTRL_REG, EXTMEM_ICACHE_ENABLE) != 0);
#endif
return result;
}
@ -448,16 +463,19 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
int i;
bool flash_spiram_wrap_together, flash_support_wrap = true, spiram_support_wrap = true;
uint32_t drom0_in_icache = 1;//always 1 in esp32s2
#if CONFIG_IDF_TARGET_ESP32S3
drom0_in_icache = 0;
#endif
if (icache_wrap_enable) {
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B
#if CONFIG_ESP32S2_INSTRUCTION_CACHE_LINE_16B || CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
icache_wrap_size = 16;
#else
icache_wrap_size = 32;
#endif
}
if (dcache_wrap_enable) {
#if CONFIG_ESP32S2_DATA_CACHE_LINE_16B
#if CONFIG_ESP32S2_DATA_CACHE_LINE_16B || CONFIG_ESP32S3_DATA_CACHE_LINE_16B
dcache_wrap_size = 16;
#else
dcache_wrap_size = 32;
@ -549,13 +567,13 @@ esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable
#ifdef CONFIG_FLASHMODE_QIO
flash_support_wrap = true;
extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
if (!spi_flash_support_wrap_size(flash_wrap_size)) {
flash_support_wrap = false;
ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
}
#else
ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
#endif
#ifdef CONFIG_ESP32S2_SPIRAM_SUPPORT
@ -588,6 +606,261 @@ extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
return ESP_OK;
}
#endif
#if CONFIG_IDF_TARGET_ESP32S3
IRAM_ATTR void esp_config_instruction_cache_mode(void)
{
cache_size_t cache_size;
cache_ways_t cache_ways;
cache_line_size_t cache_line_size;
#if CONFIG_ESP32S3_INSTRUCTION_CACHE_16KB
Cache_Occupy_ICache_MEMORY(CACHE_MEMORY_IBANK0, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_HALF;
#else
Cache_Occupy_ICache_MEMORY(CACHE_MEMORY_IBANK0, CACHE_MEMORY_IBANK1);
cache_size = CACHE_SIZE_FULL;
#endif
#if CONFIG_ESP32S3_INSTRUCTION_CACHE_4WAYS
cache_ways = CACHE_4WAYS_ASSOC;
#else
cache_ways = CACHE_8WAYS_ASSOC;
#endif
#if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
cache_line_size = CACHE_LINE_SIZE_16B;
#elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B
cache_line_size = CACHE_LINE_SIZE_32B;
#else
cache_line_size = CACHE_LINE_SIZE_64B;
#endif
ESP_EARLY_LOGI(TAG, "Instruction cache: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_HALF ? 16 : 32, cache_ways == CACHE_4WAYS_ASSOC ? 4 : 8, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : (cache_line_size == CACHE_LINE_SIZE_32B ? 32 : 64));
Cache_Set_ICache_Mode(cache_size, cache_ways, cache_line_size);
Cache_Invalidate_ICache_All();
extern void Cache_Enable_ICache(uint32_t autoload);
Cache_Enable_ICache(0);
}
IRAM_ATTR void esp_config_data_cache_mode(void)
{
cache_size_t cache_size;
cache_ways_t cache_ways;
cache_line_size_t cache_line_size;
#if CONFIG_ESP32S3_DATA_CACHE_32KB
Cache_Occupy_DCache_MEMORY(CACHE_MEMORY_DBANK1, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_HALF;
#else
Cache_Occupy_DCache_MEMORY(CACHE_MEMORY_DBANK0, CACHE_MEMORY_DBANK1);
cache_size = CACHE_SIZE_FULL;
#endif
#if CONFIG_ESP32S3_DATA_CACHE_4WAYS
cache_ways = CACHE_4WAYS_ASSOC;
#else
cache_ways = CACHE_8WAYS_ASSOC;
#endif
#if CONFIG_ESP32S3_DATA_CACHE_LINE_16B
cache_line_size = CACHE_LINE_SIZE_16B;
#elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B
cache_line_size = CACHE_LINE_SIZE_32B;
#else
cache_line_size = CACHE_LINE_SIZE_64B;
#endif
// ESP_EARLY_LOGI(TAG, "Data cache: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_HALF ? 32 : 64, cache_ways == CACHE_4WAYS_ASSOC ? 4 : 8, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : (cache_line_size == CACHE_LINE_SIZE_32B ? 32 : 64));
Cache_Set_DCache_Mode(cache_size, cache_ways, cache_line_size);
Cache_Invalidate_DCache_All();
}
static IRAM_ATTR void esp_enable_cache_flash_wrap(bool icache, bool dcache)
{
uint32_t i_autoload, d_autoload;
if (icache) {
i_autoload = Cache_Suspend_ICache();
}
if (dcache) {
d_autoload = Cache_Suspend_DCache();
}
REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_FLASH_WRAP_AROUND);
if (icache) {
Cache_Resume_ICache(i_autoload);
}
if (dcache) {
Cache_Resume_DCache(d_autoload);
}
}
#if CONFIG_ESP32S3_SPIRAM_SUPPORT
static IRAM_ATTR void esp_enable_cache_spiram_wrap(bool icache, bool dcache)
{
uint32_t i_autoload, d_autoload;
if (icache) {
i_autoload = Cache_Suspend_ICache();
}
if (dcache) {
d_autoload = Cache_Suspend_DCache();
}
REG_SET_BIT(EXTMEM_CACHE_WRAP_AROUND_CTRL_REG, EXTMEM_CACHE_SRAM_RD_WRAP_AROUND);
if (icache) {
Cache_Resume_ICache(i_autoload);
}
if (dcache) {
Cache_Resume_DCache(d_autoload);
}
}
#endif
esp_err_t esp_enable_cache_wrap(bool icache_wrap_enable, bool dcache_wrap_enable)
{
int icache_wrap_size = 0, dcache_wrap_size = 0;
int flash_wrap_sizes[2] = {-1, -1}, spiram_wrap_sizes[2] = {-1, -1};
int flash_wrap_size = 0, spiram_wrap_size = 0;
int flash_count = 0, spiram_count = 0;
int i;
bool flash_spiram_wrap_together, flash_support_wrap = false, spiram_support_wrap = true;
uint32_t drom0_in_icache = 0;//always 0 in chip7.2.4
if (icache_wrap_enable) {
#if CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_16B
icache_wrap_size = 16;
#elif CONFIG_ESP32S3_INSTRUCTION_CACHE_LINE_32B
icache_wrap_size = 32;
#else
icache_wrap_size = 64;
#endif
}
if (dcache_wrap_enable) {
#if CONFIG_ESP32S3_DATA_CACHE_LINE_16B
dcache_wrap_size = 16;
#elif CONFIG_ESP32S3_DATA_CACHE_LINE_32B
dcache_wrap_size = 32;
#else
dcache_wrap_size = 64;
#endif
}
uint32_t instruction_use_spiram = 0;
uint32_t rodata_use_spiram = 0;
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
extern uint32_t esp_spiram_instruction_access_enabled();
instruction_use_spiram = esp_spiram_instruction_access_enabled();
#endif
#if CONFIG_SPIRAM_RODATA
extern uint32_t esp_spiram_rodata_access_enabled();
rodata_use_spiram = esp_spiram_rodata_access_enabled();
#endif
if (instruction_use_spiram) {
spiram_wrap_sizes[0] = icache_wrap_size;
} else {
flash_wrap_sizes[0] = icache_wrap_size;
}
if (rodata_use_spiram) {
if (drom0_in_icache) {
spiram_wrap_sizes[0] = icache_wrap_size;
} else {
spiram_wrap_sizes[1] = dcache_wrap_size;
}
#ifdef CONFIG_EXT_RODATA_SUPPORT
spiram_wrap_sizes[1] = dcache_wrap_size;
#endif
} else {
if (drom0_in_icache) {
flash_wrap_sizes[0] = icache_wrap_size;
} else {
flash_wrap_sizes[1] = dcache_wrap_size;
}
#ifdef CONFIG_EXT_RODATA_SUPPORT
flash_wrap_sizes[1] = dcache_wrap_size;
#endif
}
#ifdef CONFIG_ESP32S3_SPIRAM_SUPPORT
spiram_wrap_sizes[1] = dcache_wrap_size;
#endif
for (i = 0; i < 2; i++) {
if (flash_wrap_sizes[i] != -1) {
flash_count++;
flash_wrap_size = flash_wrap_sizes[i];
}
}
for (i = 0; i < 2; i++) {
if (spiram_wrap_sizes[i] != -1) {
spiram_count++;
spiram_wrap_size = spiram_wrap_sizes[i];
}
}
if (flash_count + spiram_count <= 2) {
flash_spiram_wrap_together = false;
} else {
flash_spiram_wrap_together = true;
}
if (flash_count > 1 && flash_wrap_sizes[0] != flash_wrap_sizes[1]) {
ESP_EARLY_LOGW(TAG, "Flash wrap with different length %d and %d, abort wrap.", flash_wrap_sizes[0], flash_wrap_sizes[1]);
if (spiram_wrap_size == 0) {
return ESP_FAIL;
}
if (flash_spiram_wrap_together) {
ESP_EARLY_LOGE(TAG, "Abort spiram wrap because flash wrap length not fixed.");
return ESP_FAIL;
}
}
if (spiram_count > 1 && spiram_wrap_sizes[0] != spiram_wrap_sizes[1]) {
ESP_EARLY_LOGW(TAG, "SPIRAM wrap with different length %d and %d, abort wrap.", spiram_wrap_sizes[0], spiram_wrap_sizes[1]);
if (flash_wrap_size == 0) {
return ESP_FAIL;
}
if (flash_spiram_wrap_together) {
ESP_EARLY_LOGW(TAG, "Abort flash wrap because spiram wrap length not fixed.");
return ESP_FAIL;
}
}
if (flash_spiram_wrap_together && flash_wrap_size != spiram_wrap_size) {
ESP_EARLY_LOGW(TAG, "SPIRAM has different wrap length with flash, %d and %d, abort wrap.", spiram_wrap_size, flash_wrap_size);
return ESP_FAIL;
}
#ifdef CONFIG_FLASHMODE_QIO
flash_support_wrap = true;
extern bool spi_flash_support_wrap_size(uint32_t wrap_size);
if (!spi_flash_support_wrap_size(flash_wrap_size)) {
flash_support_wrap = false;
ESP_EARLY_LOGW(TAG, "Flash do not support wrap size %d.", flash_wrap_size);
}
#else
ESP_EARLY_LOGW(TAG, "Flash is not in QIO mode, do not support wrap.");
#endif
#ifdef CONFIG_ESP32S3_SPIRAM_SUPPORT
extern bool psram_support_wrap_size(uint32_t wrap_size);
if (!psram_support_wrap_size(spiram_wrap_size)) {
spiram_support_wrap = false;
ESP_EARLY_LOGW(TAG, "SPIRAM do not support wrap size %d.", spiram_wrap_size);
}
#endif
if (flash_spiram_wrap_together && !(flash_support_wrap && spiram_support_wrap)) {
ESP_EARLY_LOGW(TAG, "Flash and SPIRAM should support wrap together.");
return ESP_FAIL;
}
extern esp_err_t spi_flash_enable_wrap(uint32_t wrap_size);
if (flash_support_wrap && flash_wrap_size > 0) {
ESP_EARLY_LOGI(TAG, "Flash wrap enabled, size = %d.", flash_wrap_size);
spi_flash_enable_wrap(flash_wrap_size);
esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
}
#if CONFIG_ESP32S3_SPIRAM_SUPPORT
extern esp_err_t psram_enable_wrap(uint32_t wrap_size);
if (spiram_support_wrap && spiram_wrap_size > 0) {
ESP_EARLY_LOGI(TAG, "SPIRAM wrap enabled, size = %d.", spiram_wrap_size);
psram_enable_wrap(spiram_wrap_size);
esp_enable_cache_spiram_wrap((spiram_wrap_sizes[0] > 0), (spiram_wrap_sizes[1] > 0));
}
#endif
return ESP_OK;
}
#endif

View File

@ -60,7 +60,7 @@ void spi_flash_enable_interrupts_caches_no_os(void);
bool spi_flash_check_and_flush_cache(uint32_t start_addr, uint32_t length);
//config cache mode
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
//config instrcutin cache size and cache block size by menuconfig
void esp_config_instruction_cache_mode(void);
//config data cache size and cache block size by menuconfig

View File

@ -0,0 +1,120 @@
// Copyright 2020 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 <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/cache.h"
#include "bootloader_flash.h"
#include "hal/spi_flash_hal.h"
#include "esp_flash.h"
#include "esp_log.h"
static const char *TAG = "spiflash_s3";
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
{
const spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
esp_rom_spiflash_result_t rc;
assert((dest_addr % 16) == 0);
assert((size % 16) == 0);
if (!esp_ptr_internal(src)) {
uint8_t block[128]; // Need to buffer in RAM as we write
while (size > 0) {
size_t next_block = MIN(size, sizeof(block));
memcpy(block, src, next_block);
esp_rom_spiflash_result_t r = spi_flash_write_encrypted_chip(dest_addr, block, next_block);
if (r != ESP_ROM_SPIFLASH_RESULT_OK) {
return r;
}
size -= next_block;
dest_addr += next_block;
src = ((uint8_t *)src) + next_block;
}
bzero(block, sizeof(block));
return ESP_ROM_SPIFLASH_RESULT_OK;
} else { // Already in internal memory
ESP_LOGV(TAG, "calling SPI_Encrypt_Write addr 0x%x src %p size 0x%x", dest_addr, src, size);
#ifndef CONFIG_SPI_FLASH_USE_LEGACY_IMPL
/* The ROM function SPI_Encrypt_Write assumes ADDR_BITLEN is already set but new
implementation doesn't automatically set this to a usable value */
SPIFLASH.user1.usr_addr_bitlen = 23;
#endif
if (ops && ops->start) {
ops->start();
}
rc = SPI_Encrypt_Write(dest_addr, src, size);
if (ops && ops->end) {
ops->end();
}
return rc;
}
}
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
return bootloader_flash_wrap_set(mode);
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch (wrap_size) {
case 8:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return bootloader_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap(void)
{
bootloader_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
}
bool spi_flash_support_wrap_size(uint32_t wrap_size)
{
if (!REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO) || !REG_GET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FASTRD_MODE)) {
return ESP_FAIL;
}
switch (wrap_size) {
case 0:
case 8:
case 16:
case 32:
case 64:
return true;
default:
return false;
}
}

View File

@ -17,7 +17,6 @@
#include "memspi_host_driver.h"
#include "esp_flash_spi_init.h"
#include "driver/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "esp_rom_gpio.h"
#include "esp_rom_efuse.h"
#include "esp_log.h"
@ -25,6 +24,14 @@
#include "hal/spi_types.h"
#include "driver/spi_common_internal.h"
#include "esp_flash_internal.h"
#include "esp_rom_gpio.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/spi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/spi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#endif
__attribute__((unused)) static const char TAG[] = "spi_flash";
@ -68,6 +75,15 @@ __attribute__((unused)) static const char TAG[] = "spi_flash";
.iomux = true, \
.input_delay_ns = 0,\
}
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/efuse.h"
#define ESP_FLASH_HOST_CONFIG_DEFAULT() (memspi_host_config_t){ \
.host_id = SPI_HOST,\
.speed = DEFAULT_FLASH_SPEED, \
.cs_num = 0, \
.iomux = true, \
.input_delay_ns = 0,\
}
#endif
@ -207,7 +223,7 @@ esp_err_t esp_flash_init_default_chip(void)
{
memspi_host_config_t cfg = ESP_FLASH_HOST_CONFIG_DEFAULT();
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
// For esp32s2 spi IOs are configured as from IO MUX by default
cfg.iomux = esp_rom_efuse_get_flash_gpio_info() == 0 ? true : false;
#endif

View File

@ -39,6 +39,12 @@
#include "esp32s2/spiram.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/spiram.h"
#include "soc/extmem_reg.h"
#include "soc/cache_memory.h"
#endif
#ifndef NDEBUG
@ -48,6 +54,7 @@
#include "sys/queue.h"
#ifdef CONFIG_IDF_TARGET_ESP32
#define PAGES_PER_REGION 64
#define REGIONS_COUNT 4
#define IROM0_PAGES_START 64
#define IROM0_PAGES_END 256
@ -56,7 +63,10 @@
#define PAGE_IN_FLASH(page) (page)
#define INVALID_ENTRY_VAL DPORT_FLASH_MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK DPORT_MMU_ADDRESS_MASK
#define VADDR1_START_ADDR 0x40000000
#define PRO_IRAM0_FIRST_USABLE_PAGE ((VADDR1_FIRST_USABLE_ADDR - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START)
#elif CONFIG_IDF_TARGET_ESP32S2
#define PAGES_PER_REGION 64
#define REGIONS_COUNT 6
#define IROM0_PAGES_START (PRO_CACHE_IBUS0_MMU_START / sizeof(uint32_t))
#define IROM0_PAGES_END (PRO_CACHE_IBUS1_MMU_END / sizeof(uint32_t))
@ -66,16 +76,28 @@
#define INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK MMU_ADDRESS_MASK
#define PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH)
#define VADDR1_START_ADDR IRAM0_CACHE_ADDRESS_LOW
#define PRO_IRAM0_FIRST_USABLE_PAGE ((VADDR1_FIRST_USABLE_ADDR - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START)
#elif CONFIG_IDF_TARGET_ESP32S3
#define REGIONS_COUNT 2
#define PAGES_PER_REGION 256
#define IROM0_PAGES_START (CACHE_IBUS_MMU_START / sizeof(uint32_t))
#define IROM0_PAGES_END (CACHE_IBUS_MMU_END / sizeof(uint32_t))
#define DROM0_PAGES_START (CACHE_DBUS_MMU_START / sizeof(uint32_t))
#define DROM0_PAGES_END (CACHE_DBUS_MMU_END / sizeof(uint32_t))
#define DPORT_PRO_FLASH_MMU_TABLE FLASH_MMU_TABLE
#define INVALID_ENTRY_VAL MMU_TABLE_INVALID_VAL
#define MMU_ADDR_MASK MMU_ADDRESS_MASK
#define PAGE_IN_FLASH(page) ((page) | MMU_ACCESS_FLASH)
#define VADDR1_START_ADDR IRAM0_CACHE_ADDRESS_LOW
#define PRO_IRAM0_FIRST_USABLE_PAGE (IROM0_PAGES_START)
#endif
#define PAGES_PER_REGION 64
#define IROM0_PAGES_NUM (IROM0_PAGES_END - IROM0_PAGES_START)
#define DROM0_PAGES_NUM (DROM0_PAGES_END - DROM0_PAGES_START)
#define PAGES_LIMIT (IROM0_PAGES_END > DROM0_PAGES_END ? IROM0_PAGES_END:DROM0_PAGES_END)
#define VADDR0_START_ADDR SOC_DROM_LOW
#define VADDR1_START_ADDR 0x40000000
#define VADDR1_FIRST_USABLE_ADDR SOC_IROM_LOW
#define PRO_IRAM0_FIRST_USABLE_PAGE ((VADDR1_FIRST_USABLE_ADDR - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START)
typedef struct mmap_entry_{
uint32_t handle;
@ -99,7 +121,7 @@ static void IRAM_ATTR spi_flash_mmap_init(void)
DPORT_INTERRUPT_DISABLE();
for (int i = 0; i < REGIONS_COUNT * PAGES_PER_REGION; ++i) {
uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]);
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]);
if (entry_pro != entry_app) {
@ -112,7 +134,7 @@ static void IRAM_ATTR spi_flash_mmap_init(void)
s_mmap_page_refcnt[i] = 1;
} else {
DPORT_PRO_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
DPORT_APP_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
#endif
}
@ -229,27 +251,27 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
for (int i = start; i != start + page_count; ++i, ++pageno) {
// sanity check: we won't reconfigure entries with non-zero reference count
uint32_t entry_pro = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]);
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]);
#endif
assert(s_mmap_page_refcnt[i] == 0 ||
(entry_pro == PAGE_IN_FLASH(pages[pageno])
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
&& entry_app == PAGE_IN_FLASH(pages[pageno])
#endif
));
if (s_mmap_page_refcnt[i] == 0) {
if (entry_pro != PAGE_IN_FLASH(pages[pageno])
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
|| entry_app != PAGE_IN_FLASH(pages[pageno])
#endif
) {
DPORT_PRO_FLASH_MMU_TABLE[i] = PAGE_IN_FLASH(pages[pageno]);
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
DPORT_APP_FLASH_MMU_TABLE[i] = pages[pageno];
#endif
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
Cache_Invalidate_Addr(region_addr + (i - region_begin) * SPI_FLASH_MMU_PAGE_SIZE, SPI_FLASH_MMU_PAGE_SIZE);
#endif
need_flush = true;
@ -306,7 +328,7 @@ void IRAM_ATTR spi_flash_munmap(spi_flash_mmap_handle_t handle)
assert(s_mmap_page_refcnt[i] > 0);
if (--s_mmap_page_refcnt[i] == 0) {
DPORT_PRO_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
#if !CONFIG_FREERTOS_UNICORE
#if !CONFIG_FREERTOS_UNICORE && CONFIG_IDF_TARGET_ESP32
DPORT_APP_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
#endif
}
@ -481,7 +503,7 @@ static bool IRAM_ATTR is_page_mapped_in_cache(uint32_t phys_page, const void **o
for (int j = 0; j < 2; j++) {
for (int i = start[j]; i < end[j]; i++) {
if (DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_PRO_FLASH_MMU_TABLE[i]) == PAGE_IN_FLASH(phys_page)) {
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (j == 0) { /* SPI_FLASH_MMAP_DATA */
*out_ptr = (const void *)(VADDR0_START_ADDR + SPI_FLASH_MMU_PAGE_SIZE * (i - start[0]));
} else { /* SPI_FLASH_MMAP_INST */
@ -522,7 +544,7 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
Cache_Flush(1);
#endif
return true;
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (vaddr != NULL) {
Cache_Invalidate_Addr((uint32_t)vaddr, SPI_FLASH_MMU_PAGE_SIZE);
ret = true;

View File

@ -36,6 +36,10 @@
#include "esp32s2/rom/spi_flash.h"
#include "esp32s2/rom/cache.h"
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/spi_flash.h"
#include "esp32s3/rom/cache.h"
#include "esp32s3/clk.h"
#endif
#include "esp_flash_partitions.h"
#include "cache_utils.h"
@ -776,7 +780,7 @@ void spi_flash_dump_counters(void)
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
#if defined(CONFIG_SPI_FLASH_USE_LEGACY_IMPL) && defined(CONFIG_IDF_TARGET_ESP32S2)
#if defined(CONFIG_SPI_FLASH_USE_LEGACY_IMPL) && (defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3))
// TODO esp32s2: Remove once ESP32S2 has new SPI Flash API support
esp_flash_t *esp_flash_default_chip = NULL;
#endif

View File

@ -25,7 +25,7 @@
static const char TAG[] = "memspi";
DRAM_ATTR static const spi_flash_host_driver_t esp_flash_default_host = ESP_FLASH_DEFAULT_HOST_DRIVER();
#ifdef CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
extern void spi_flash_hal_gpspi_poll_cmd_done(spi_flash_host_inst_t *host);
extern esp_err_t spi_flash_hal_gpspi_device_config(spi_flash_host_inst_t *host);
esp_err_t spi_flash_hal_gpspi_configure_host_io_mode(
@ -67,7 +67,7 @@ esp_err_t memspi_host_init_pointers(memspi_host_inst_t *host, const memspi_host_
{
#ifdef CONFIG_IDF_TARGET_ESP32
host->inst.driver = &esp_flash_default_host;
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
if (cfg->host_id == SPI_HOST)
host->inst.driver = &esp_flash_default_host;
else {

View File

@ -22,11 +22,14 @@
#include "esp32/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/rom/cache.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/rom/ets_sys.h"
#include "esp32s3/rom/cache.h"
#endif
#include "esp_attr.h"
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
typedef struct {
uint32_t icache_autoload;
uint32_t dcache_autoload;
@ -40,7 +43,7 @@ static IRAM_ATTR esp_err_t start(void *arg)
#if CONFIG_IDF_TARGET_ESP32
Cache_Read_Disable(0);
Cache_Read_Disable(1);
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
spi_noos_arg_t *spi_arg = arg;
spi_arg->icache_autoload = Cache_Suspend_ICache();
spi_arg->dcache_autoload = Cache_Suspend_DCache();
@ -55,7 +58,7 @@ static IRAM_ATTR esp_err_t end(void *arg)
Cache_Flush(1);
Cache_Read_Enable(0);
Cache_Read_Enable(1);
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
spi_noos_arg_t *spi_arg = arg;
Cache_Invalidate_ICache_All();
Cache_Resume_ICache(spi_arg->icache_autoload);
@ -85,7 +88,7 @@ esp_err_t IRAM_ATTR esp_flash_app_disable_os_functions(esp_flash_t* chip)
{
chip->os_func = &esp_flash_noos_functions;
#if CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
chip->os_func_data = &spi_arg;
#endif

View File

@ -0,0 +1,840 @@
// Copyright 2016-2018 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.
#pragma once
#include <stdint.h>
#include <stddef.h>
#include <stdlib.h>
#include "esp_err.h"
#include "soc/soc.h"
#include "ulp_common.h"
#ifdef __cplusplus
extern "C" {
#endif
#define ULP_FSM_PREPARE_SLEEP_CYCLES 2 /*!< Cycles spent by FSM preparing ULP for sleep */
#define ULP_FSM_WAKEUP_SLEEP_CYCLES 2 /*!< Cycles spent by FSM waking up ULP from sleep */
/**
* @defgroup ulp_registers ULP coprocessor registers
* @{
*/
#define R0 0 /*!< general purpose register 0 */
#define R1 1 /*!< general purpose register 1 */
#define R2 2 /*!< general purpose register 2 */
#define R3 3 /*!< general purpose register 3 */
/**@}*/
/** @defgroup ulp_opcodes ULP coprocessor opcodes, sub opcodes, and various modifiers/flags
*
* These definitions are not intended to be used directly.
* They are used in definitions of instructions later on.
*
* @{
*/
#define OPCODE_WR_REG 1 /*!< Instruction: write peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */
#define OPCODE_RD_REG 2 /*!< Instruction: read peripheral register (RTC_CNTL/RTC_IO/SARADC) (not implemented yet) */
#define RD_REG_PERIPH_RTC_CNTL 0 /*!< Identifier of RTC_CNTL peripheral for RD_REG and WR_REG instructions */
#define RD_REG_PERIPH_RTC_IO 1 /*!< Identifier of RTC_IO peripheral for RD_REG and WR_REG instructions */
#define RD_REG_PERIPH_SENS 2 /*!< Identifier of SARADC peripheral for RD_REG and WR_REG instructions */
#define RD_REG_PERIPH_RTC_I2C 3 /*!< Identifier of RTC_I2C peripheral for RD_REG and WR_REG instructions */
#define OPCODE_I2C 3 /*!< Instruction: read/write I2C (not implemented yet) */
#define OPCODE_DELAY 4 /*!< Instruction: delay (nop) for a given number of cycles */
#define OPCODE_ADC 5 /*!< Instruction: SAR ADC measurement (not implemented yet) */
#define OPCODE_ST 6 /*!< Instruction: store indirect to RTC memory */
#define SUB_OPCODE_ST 4 /*!< Store 32 bits, 16 MSBs contain PC, 16 LSBs contain value from source register */
#define OPCODE_ALU 7 /*!< Arithmetic instructions */
#define SUB_OPCODE_ALU_REG 0 /*!< Arithmetic instruction, both source values are in register */
#define SUB_OPCODE_ALU_IMM 1 /*!< Arithmetic instruction, one source value is an immediate */
#define SUB_OPCODE_ALU_CNT 2 /*!< Arithmetic instruction between counter register and an immediate (not implemented yet)*/
#define ALU_SEL_ADD 0 /*!< Addition */
#define ALU_SEL_SUB 1 /*!< Subtraction */
#define ALU_SEL_AND 2 /*!< Logical AND */
#define ALU_SEL_OR 3 /*!< Logical OR */
#define ALU_SEL_MOV 4 /*!< Copy value (immediate to destination register or source register to destination register */
#define ALU_SEL_LSH 5 /*!< Shift left by given number of bits */
#define ALU_SEL_RSH 6 /*!< Shift right by given number of bits */
#define OPCODE_BRANCH 8 /*!< Branch instructions */
#define SUB_OPCODE_BX 0 /*!< Branch to absolute PC (immediate or in register) */
#define BX_JUMP_TYPE_DIRECT 0 /*!< Unconditional jump */
#define BX_JUMP_TYPE_ZERO 1 /*!< Branch if last ALU result is zero */
#define BX_JUMP_TYPE_OVF 2 /*!< Branch if last ALU operation caused and overflow */
#define SUB_OPCODE_B 1 /*!< Branch to a relative offset */
#define B_CMP_L 0 /*!< Branch if R0 is less than an immediate */
#define B_CMP_GE 1 /*!< Branch if R0 is greater than or equal to an immediate */
#define OPCODE_END 9 /*!< Stop executing the program */
#define SUB_OPCODE_END 0 /*!< Stop executing the program and optionally wake up the chip */
#define SUB_OPCODE_SLEEP 1 /*!< Stop executing the program and run it again after selected interval */
#define OPCODE_TSENS 10 /*!< Instruction: temperature sensor measurement (not implemented yet) */
#define OPCODE_HALT 11 /*!< Halt the coprocessor */
#define OPCODE_LD 13 /*!< Indirect load lower 16 bits from RTC memory */
#define OPCODE_MACRO 15 /*!< Not a real opcode. Used to identify labels and branches in the program */
#define SUB_OPCODE_MACRO_LABEL 0 /*!< Label macro */
#define SUB_OPCODE_MACRO_BRANCH 1 /*!< Branch macro */
/**@}*/
/**
* @brief Instruction format structure
*
* All ULP instructions are 32 bit long.
* This union contains field layouts used by all of the supported instructions.
* This union also includes a special "macro" instruction layout.
* This is not a real instruction which can be executed by the CPU. It acts
* as a token which is removed from the program by the
* ulp_process_macros_and_load function.
*
* These structures are not intended to be used directly.
* Preprocessor definitions provided below fill the fields of these structure with
* the right arguments.
*/
union ulp_insn {
struct {
uint32_t cycles : 16; /*!< Number of cycles to sleep */
uint32_t unused : 12; /*!< Unused */
uint32_t opcode : 4; /*!< Opcode (OPCODE_DELAY) */
} delay; /*!< Format of DELAY instruction */
struct {
uint32_t dreg : 2; /*!< Register which contains data to store */
uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
uint32_t unused1 : 6; /*!< Unused */
uint32_t offset : 11; /*!< Offset to add to sreg */
uint32_t unused2 : 4; /*!< Unused */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ST) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ST) */
} st; /*!< Format of ST instruction */
struct {
uint32_t dreg : 2; /*!< Register where the data should be loaded to */
uint32_t sreg : 2; /*!< Register which contains address in RTC memory (expressed in words) */
uint32_t unused1 : 6; /*!< Unused */
uint32_t offset : 11; /*!< Offset to add to sreg */
uint32_t unused2 : 7; /*!< Unused */
uint32_t opcode : 4; /*!< Opcode (OPCODE_LD) */
} ld; /*!< Format of LD instruction */
struct {
uint32_t unused : 28; /*!< Unused */
uint32_t opcode : 4; /*!< Opcode (OPCODE_HALT) */
} halt; /*!< Format of HALT instruction */
struct {
uint32_t dreg : 2; /*!< Register which contains target PC, expressed in words (used if .reg == 1) */
uint32_t addr : 11; /*!< Target PC, expressed in words (used if .reg == 0) */
uint32_t unused : 8; /*!< Unused */
uint32_t reg : 1; /*!< Target PC in register (1) or immediate (0) */
uint32_t type : 3; /*!< Jump condition (BX_JUMP_TYPE_xxx) */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_BX) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
} bx; /*!< Format of BRANCH instruction (absolute address) */
struct {
uint32_t imm : 16; /*!< Immediate value to compare against */
uint32_t cmp : 1; /*!< Comparison to perform: B_CMP_L or B_CMP_GE */
uint32_t offset : 7; /*!< Absolute value of target PC offset w.r.t. current PC, expressed in words */
uint32_t sign : 1; /*!< Sign of target PC offset: 0: positive, 1: negative */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_B) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_BRANCH) */
} b; /*!< Format of BRANCH instruction (relative address) */
struct {
uint32_t dreg : 2; /*!< Destination register */
uint32_t sreg : 2; /*!< Register with operand A */
uint32_t treg : 2; /*!< Register with operand B */
uint32_t unused : 15; /*!< Unused */
uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_REG) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_reg; /*!< Format of ALU instruction (both sources are registers) */
struct {
uint32_t dreg : 2; /*!< Destination register */
uint32_t sreg : 2; /*!< Register with operand A */
uint32_t imm : 16; /*!< Immediate value of operand B */
uint32_t unused : 1; /*!< Unused */
uint32_t sel : 4; /*!< Operation to perform, one of ALU_SEL_xxx */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_ALU_IMM) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_ALU) */
} alu_imm; /*!< Format of ALU instruction (one source is an immediate) */
struct {
uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
uint32_t data : 8; /*!< 8 bits of data to write */
uint32_t low : 5; /*!< Low bit */
uint32_t high : 5; /*!< High bit */
uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
} wr_reg; /*!< Format of WR_REG instruction */
struct {
uint32_t addr : 8; /*!< Address within either RTC_CNTL, RTC_IO, or SARADC */
uint32_t periph_sel : 2; /*!< Select peripheral: RTC_CNTL (0), RTC_IO(1), SARADC(2) */
uint32_t unused : 8; /*!< Unused */
uint32_t low : 5; /*!< Low bit */
uint32_t high : 5; /*!< High bit */
uint32_t opcode : 4; /*!< Opcode (OPCODE_WR_REG) */
} rd_reg; /*!< Format of RD_REG instruction */
struct {
uint32_t dreg : 2; /*!< Register where to store ADC result */
uint32_t mux : 4; /*!< Select SARADC pad (mux + 1) */
uint32_t sar_sel : 1; /*!< Select SARADC0 (0) or SARADC1 (1) */
uint32_t unused1 : 1; /*!< Unused */
uint32_t cycles : 16; /*!< TBD, cycles used for measurement */
uint32_t unused2 : 4; /*!< Unused */
uint32_t opcode: 4; /*!< Opcode (OPCODE_ADC) */
} adc; /*!< Format of ADC instruction */
struct {
uint32_t dreg : 2; /*!< Register where to store temperature measurement result */
uint32_t wait_delay: 14; /*!< Cycles to wait after measurement is done */
uint32_t reserved: 12; /*!< Reserved, set to 0 */
uint32_t opcode: 4; /*!< Opcode (OPCODE_TSENS) */
} tsens; /*!< Format of TSENS instruction */
struct {
uint32_t i2c_addr : 8; /*!< I2C slave address */
uint32_t data : 8; /*!< Data to read or write */
uint32_t low_bits : 3; /*!< TBD */
uint32_t high_bits : 3; /*!< TBD */
uint32_t i2c_sel : 4; /*!< TBD, select reg_i2c_slave_address[7:0] */
uint32_t unused : 1; /*!< Unused */
uint32_t rw : 1; /*!< Write (1) or read (0) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_I2C) */
} i2c; /*!< Format of I2C instruction */
struct {
uint32_t wakeup : 1; /*!< Set to 1 to wake up chip */
uint32_t unused : 24; /*!< Unused */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_WAKEUP) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
} end; /*!< Format of END instruction with wakeup */
struct {
uint32_t cycle_sel : 4; /*!< Select which one of SARADC_ULP_CP_SLEEP_CYCx_REG to get the sleep duration from */
uint32_t unused : 21; /*!< Unused */
uint32_t sub_opcode : 3; /*!< Sub opcode (SUB_OPCODE_SLEEP) */
uint32_t opcode : 4; /*!< Opcode (OPCODE_END) */
} sleep; /*!< Format of END instruction with sleep */
struct {
uint32_t label : 16; /*!< Label number */
uint32_t unused : 8; /*!< Unused */
uint32_t sub_opcode : 4; /*!< SUB_OPCODE_MACRO_LABEL or SUB_OPCODE_MACRO_BRANCH */
uint32_t opcode: 4; /*!< Opcode (OPCODE_MACRO) */
} macro; /*!< Format of tokens used by LABEL and BRANCH macros */
};
typedef union ulp_insn ulp_insn_t;
_Static_assert(sizeof(ulp_insn_t) == 4, "ULP coprocessor instruction size should be 4 bytes");
/**
* Delay (nop) for a given number of cycles
*/
#define I_DELAY(cycles_) { .delay = {\
.cycles = cycles_, \
.unused = 0, \
.opcode = OPCODE_DELAY } }
/**
* Halt the coprocessor.
*
* This instruction halts the coprocessor, but keeps ULP timer active.
* As such, ULP program will be restarted again by timer.
* To stop the program and prevent the timer from restarting the program,
* use I_END(0) instruction.
*/
#define I_HALT() { .halt = {\
.unused = 0, \
.opcode = OPCODE_HALT } }
/**
* Map SoC peripheral register to periph_sel field of RD_REG and WR_REG
* instructions.
*
* @param reg peripheral register in RTC_CNTL_, RTC_IO_, SENS_, RTC_I2C peripherals.
* @return periph_sel value for the peripheral to which this register belongs.
*/
static inline uint32_t SOC_REG_TO_ULP_PERIPH_SEL(uint32_t reg)
{
uint32_t ret = 3;
if (reg < DR_REG_RTCCNTL_BASE) {
assert(0 && "invalid register base");
} else if (reg < DR_REG_RTCIO_BASE) {
ret = RD_REG_PERIPH_RTC_CNTL;
} else if (reg < DR_REG_SENS_BASE) {
ret = RD_REG_PERIPH_RTC_IO;
} else if (reg < DR_REG_RTC_I2C_BASE) {
ret = RD_REG_PERIPH_SENS;
} else if (reg < DR_REG_IO_MUX_BASE) {
ret = RD_REG_PERIPH_RTC_I2C;
} else {
assert(0 && "invalid register base");
}
return ret;
}
/**
* Write literal value to a peripheral register
*
* reg[high_bit : low_bit] = val
* This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
*/
#define I_WR_REG(reg, low_bit, high_bit, val) {.wr_reg = {\
.addr = (reg & 0xff) / sizeof(uint32_t), \
.periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
.data = val, \
.low = low_bit, \
.high = high_bit, \
.opcode = OPCODE_WR_REG } }
/**
* Read from peripheral register into R0
*
* R0 = reg[high_bit : low_bit]
* This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
*/
#define I_RD_REG(reg, low_bit, high_bit) {.rd_reg = {\
.addr = (reg & 0xff) / sizeof(uint32_t), \
.periph_sel = SOC_REG_TO_ULP_PERIPH_SEL(reg), \
.unused = 0, \
.low = low_bit, \
.high = high_bit, \
.opcode = OPCODE_RD_REG } }
/**
* Set or clear a bit in the peripheral register.
*
* Sets bit (1 << shift) of register reg to value val.
* This instruction can access RTC_CNTL_, RTC_IO_, SENS_, and RTC_I2C peripheral registers.
*/
#define I_WR_REG_BIT(reg, shift, val) I_WR_REG(reg, shift, shift, val)
/**
* Wake the SoC from deep sleep.
*
* This instruction initiates wake up from deep sleep.
* Use esp_deep_sleep_enable_ulp_wakeup to enable deep sleep wakeup
* triggered by the ULP before going into deep sleep.
* Note that ULP program will still keep running until the I_HALT
* instruction, and it will still be restarted by timer at regular
* intervals, even when the SoC is woken up.
*
* To stop the ULP program, use I_HALT instruction.
*
* To disable the timer which start ULP program, use I_END()
* instruction. I_END instruction clears the
* RTC_CNTL_ULP_CP_SLP_TIMER_EN_S bit of RTC_CNTL_STATE0_REG
* register, which controls the ULP timer.
*/
#define I_WAKE() { .end = { \
.wakeup = 1, \
.unused = 0, \
.sub_opcode = SUB_OPCODE_END, \
.opcode = OPCODE_END } }
/**
* Stop ULP program timer.
*
* This is a convenience macro which disables the ULP program timer.
* Once this instruction is used, ULP program will not be restarted
* anymore until ulp_run function is called.
*
* ULP program will continue running after this instruction. To stop
* the currently running program, use I_HALT().
*/
#define I_END() \
I_WR_REG_BIT(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN_S, 0)
/**
* Select the time interval used to run ULP program.
*
* This instructions selects which of the SENS_SLEEP_CYCLES_Sx
* registers' value is used by the ULP program timer.
* When the ULP program stops at I_HALT instruction, ULP program
* timer start counting. When the counter reaches the value of
* the selected SENS_SLEEP_CYCLES_Sx register, ULP program
* start running again from the start address (passed to the ulp_run
* function).
* There are 5 SENS_SLEEP_CYCLES_Sx registers, so 0 <= timer_idx < 5.
*
* By default, SENS_SLEEP_CYCLES_S0 register is used by the ULP
* program timer.
*/
#define I_SLEEP_CYCLE_SEL(timer_idx) { .sleep = { \
.cycle_sel = timer_idx, \
.unused = 0, \
.sub_opcode = SUB_OPCODE_SLEEP, \
.opcode = OPCODE_END } }
/**
* Perform temperature sensor measurement and store it into reg_dest.
*
* Delay can be set between 1 and ((1 << 14) - 1). Higher values give
* higher measurement resolution.
*/
#define I_TSENS(reg_dest, delay) { .tsens = { \
.dreg = reg_dest, \
.wait_delay = delay, \
.reserved = 0, \
.opcode = OPCODE_TSENS } }
/**
* Perform ADC measurement and store result in reg_dest.
*
* adc_idx selects ADC (0 or 1).
* pad_idx selects ADC pad (0 - 7).
*/
#define I_ADC(reg_dest, adc_idx, pad_idx) { .adc = {\
.dreg = reg_dest, \
.mux = pad_idx + 1, \
.sar_sel = adc_idx, \
.unused1 = 0, \
.cycles = 0, \
.unused2 = 0, \
.opcode = OPCODE_ADC } }
/**
* Store value from register reg_val into RTC memory.
*
* The value is written to an offset calculated by adding value of
* reg_addr register and offset_ field (this offset is expressed in 32-bit words).
* 32 bits written to RTC memory are built as follows:
* - bits [31:21] hold the PC of current instruction, expressed in 32-bit words
* - bits [20:16] = 5'b1
* - bits [15:0] are assigned the contents of reg_val
*
* RTC_SLOW_MEM[addr + offset_] = { 5'b0, insn_PC[10:0], val[15:0] }
*/
#define I_ST(reg_val, reg_addr, offset_) { .st = { \
.dreg = reg_val, \
.sreg = reg_addr, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.sub_opcode = SUB_OPCODE_ST, \
.opcode = OPCODE_ST } }
/**
* Load value from RTC memory into reg_dest register.
*
* Loads 16 LSBs from RTC memory word given by the sum of value in reg_addr and
* value of offset_.
*/
#define I_LD(reg_dest, reg_addr, offset_) { .ld = { \
.dreg = reg_dest, \
.sreg = reg_addr, \
.unused1 = 0, \
.offset = offset_, \
.unused2 = 0, \
.opcode = OPCODE_LD } }
/**
* Branch relative if R0 less than immediate value.
*
* pc_offset is expressed in words, and can be from -127 to 127
* imm_value is a 16-bit value to compare R0 against
*/
#define I_BL(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_L, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B, \
.opcode = OPCODE_BRANCH } }
/**
* Branch relative if R0 greater or equal than immediate value.
*
* pc_offset is expressed in words, and can be from -127 to 127
* imm_value is a 16-bit value to compare R0 against
*/
#define I_BGE(pc_offset, imm_value) { .b = { \
.imm = imm_value, \
.cmp = B_CMP_GE, \
.offset = abs(pc_offset), \
.sign = (pc_offset >= 0) ? 0 : 1, \
.sub_opcode = SUB_OPCODE_B, \
.opcode = OPCODE_BRANCH } }
/**
* Unconditional branch to absolute PC, address in register.
*
* reg_pc is the register which contains address to jump to.
* Address is expressed in 32-bit words.
*/
#define I_BXR(reg_pc) { .bx = { \
.dreg = reg_pc, \
.addr = 0, \
.unused = 0, \
.reg = 1, \
.type = BX_JUMP_TYPE_DIRECT, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
/**
* Unconditional branch to absolute PC, immediate address.
*
* Address imm_pc is expressed in 32-bit words.
*/
#define I_BXI(imm_pc) { .bx = { \
.dreg = 0, \
.addr = imm_pc, \
.unused = 0, \
.reg = 0, \
.type = BX_JUMP_TYPE_DIRECT, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
/**
* Branch to absolute PC if ALU result is zero, address in register.
*
* reg_pc is the register which contains address to jump to.
* Address is expressed in 32-bit words.
*/
#define I_BXZR(reg_pc) { .bx = { \
.dreg = reg_pc, \
.addr = 0, \
.unused = 0, \
.reg = 1, \
.type = BX_JUMP_TYPE_ZERO, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
/**
* Branch to absolute PC if ALU result is zero, immediate address.
*
* Address imm_pc is expressed in 32-bit words.
*/
#define I_BXZI(imm_pc) { .bx = { \
.dreg = 0, \
.addr = imm_pc, \
.unused = 0, \
.reg = 0, \
.type = BX_JUMP_TYPE_ZERO, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
/**
* Branch to absolute PC if ALU overflow, address in register
*
* reg_pc is the register which contains address to jump to.
* Address is expressed in 32-bit words.
*/
#define I_BXFR(reg_pc) { .bx = { \
.dreg = reg_pc, \
.addr = 0, \
.unused = 0, \
.reg = 1, \
.type = BX_JUMP_TYPE_OVF, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
/**
* Branch to absolute PC if ALU overflow, immediate address
*
* Address imm_pc is expressed in 32-bit words.
*/
#define I_BXFI(imm_pc) { .bx = { \
.dreg = 0, \
.addr = imm_pc, \
.unused = 0, \
.reg = 0, \
.type = BX_JUMP_TYPE_OVF, \
.sub_opcode = SUB_OPCODE_BX, \
.opcode = OPCODE_BRANCH } }
/**
* Addition: dest = src1 + src2
*/
#define I_ADDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src1, \
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_ADD, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Subtraction: dest = src1 - src2
*/
#define I_SUBR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src1, \
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_SUB, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Logical AND: dest = src1 & src2
*/
#define I_ANDR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src1, \
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_AND, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Logical OR: dest = src1 | src2
*/
#define I_ORR(reg_dest, reg_src1, reg_src2) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src1, \
.treg = reg_src2, \
.unused = 0, \
.sel = ALU_SEL_OR, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Copy: dest = src
*/
#define I_MOVR(reg_dest, reg_src) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.treg = 0, \
.unused = 0, \
.sel = ALU_SEL_MOV, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Logical shift left: dest = src << shift
*/
#define I_LSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.treg = reg_shift, \
.unused = 0, \
.sel = ALU_SEL_LSH, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Logical shift right: dest = src >> shift
*/
#define I_RSHR(reg_dest, reg_src, reg_shift) { .alu_reg = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.treg = reg_shift, \
.unused = 0, \
.sel = ALU_SEL_RSH, \
.sub_opcode = SUB_OPCODE_ALU_REG, \
.opcode = OPCODE_ALU } }
/**
* Add register and an immediate value: dest = src1 + imm
*/
#define I_ADDI(reg_dest, reg_src, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_ADD, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Subtract register and an immediate value: dest = src - imm
*/
#define I_SUBI(reg_dest, reg_src, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_SUB, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Logical AND register and an immediate value: dest = src & imm
*/
#define I_ANDI(reg_dest, reg_src, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_AND, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Logical OR register and an immediate value: dest = src | imm
*/
#define I_ORI(reg_dest, reg_src, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_OR, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Copy an immediate value into register: dest = imm
*/
#define I_MOVI(reg_dest, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = 0, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_MOV, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Logical shift left register value by an immediate: dest = src << imm
*/
#define I_LSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_LSH, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Logical shift right register value by an immediate: dest = val >> imm
*/
#define I_RSHI(reg_dest, reg_src, imm_) { .alu_imm = { \
.dreg = reg_dest, \
.sreg = reg_src, \
.imm = imm_, \
.unused = 0, \
.sel = ALU_SEL_RSH, \
.sub_opcode = SUB_OPCODE_ALU_IMM, \
.opcode = OPCODE_ALU } }
/**
* Define a label with number label_num.
*
* This is a macro which doesn't generate a real instruction.
* The token generated by this macro is removed by ulp_process_macros_and_load
* function. Label defined using this macro can be used in branch macros defined
* below.
*/
#define M_LABEL(label_num) { .macro = { \
.label = label_num, \
.unused = 0, \
.sub_opcode = SUB_OPCODE_MACRO_LABEL, \
.opcode = OPCODE_MACRO } }
/**
* Token macro used by M_B and M_BX macros. Not to be used directly.
*/
#define M_BRANCH(label_num) { .macro = { \
.label = label_num, \
.unused = 0, \
.sub_opcode = SUB_OPCODE_MACRO_BRANCH, \
.opcode = OPCODE_MACRO } }
/**
* Macro: branch to label label_num if R0 is less than immediate value.
*
* This macro generates two ulp_insn_t values separated by a comma, and should
* be used when defining contents of ulp_insn_t arrays. First value is not a
* real instruction; it is a token which is removed by ulp_process_macros_and_load
* function.
*/
#define M_BL(label_num, imm_value) \
M_BRANCH(label_num), \
I_BL(0, imm_value)
/**
* Macro: branch to label label_num if R0 is greater or equal than immediate value
*
* This macro generates two ulp_insn_t values separated by a comma, and should
* be used when defining contents of ulp_insn_t arrays. First value is not a
* real instruction; it is a token which is removed by ulp_process_macros_and_load
* function.
*/
#define M_BGE(label_num, imm_value) \
M_BRANCH(label_num), \
I_BGE(0, imm_value)
/**
* Macro: unconditional branch to label
*
* This macro generates two ulp_insn_t values separated by a comma, and should
* be used when defining contents of ulp_insn_t arrays. First value is not a
* real instruction; it is a token which is removed by ulp_process_macros_and_load
* function.
*/
#define M_BX(label_num) \
M_BRANCH(label_num), \
I_BXI(0)
/**
* Macro: branch to label if ALU result is zero
*
* This macro generates two ulp_insn_t values separated by a comma, and should
* be used when defining contents of ulp_insn_t arrays. First value is not a
* real instruction; it is a token which is removed by ulp_process_macros_and_load
* function.
*/
#define M_BXZ(label_num) \
M_BRANCH(label_num), \
I_BXZI(0)
/**
* Macro: branch to label if ALU overflow
*
* This macro generates two ulp_insn_t values separated by a comma, and should
* be used when defining contents of ulp_insn_t arrays. First value is not a
* real instruction; it is a token which is removed by ulp_process_macros_and_load
* function.
*/
#define M_BXF(label_num) \
M_BRANCH(label_num), \
I_BXFI(0)
#define RTC_SLOW_MEM ((uint32_t*) 0x50000000) /*!< RTC slow memory, 8k size */
#ifdef __cplusplus
}
#endif

View File

@ -25,6 +25,9 @@
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#include "esp32s2/ulp.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#include "esp32s3/ulp.h"
#endif
#include "soc/soc.h"

View File

@ -16,6 +16,8 @@
#ifdef CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
#define ULP_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM
#else
#elif defined(CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM)
#define ULP_RESERVE_MEM CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM
#elif defined(CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM)
#define ULP_RESERVE_MEM CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM
#endif

View File

@ -20,6 +20,8 @@
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#endif
static uint32_t s_test_start, s_test_stop;

View File

@ -162,7 +162,7 @@ static void uart_tx_char(int fd, int c)
}
#if CONFIG_IDF_TARGET_ESP32
uart->fifo.rw_byte = c;
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
uart->ahb_fifo.rw_byte = c;
#endif
}
@ -181,7 +181,7 @@ static int uart_rx_char(int fd)
}
#if CONFIG_IDF_TARGET_ESP32
return uart->fifo.rw_byte;
#elif CONFIG_IDF_TARGET_ESP32S2
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
return READ_PERI_REG(UART_FIFO_AHB_REG(fd));
#endif
}

View File

@ -23,6 +23,7 @@ check_submodule_sync:
- *show_submodule_urls
- git submodule update --recursive
- echo "IDF was cloned from ${PUBLIC_IDF_URL} completely"
allow_failure: true # remove this line when esp32s3 support in esptool got merged into master
check_ut_cmake_make:
extends: .check_job_template_with_filter

View File

@ -112,6 +112,62 @@
}
]
},
{
"description": "Toolchain for Xtensa (ESP32-S3) based on GCC",
"export_paths": [
[
"xtensa-esp32s3-elf",
"bin"
]
],
"export_vars": {},
"info_url": "https://github.com/espressif/crosstool-NG",
"install": "always",
"license": "GPL-3.0-with-GCC-exception",
"name": "xtensa-esp32s3-elf",
"version_cmd": [
"xtensa-esp32s3-elf-gcc",
"--version"
],
"version_regex": "\\(crosstool-NG\\s+(?:crosstool-ng-)?([0-9a-zA-Z\\.\\-]+)\\)\\s*([0-9\\.]+)",
"version_regex_replace": "\\1-\\2",
"versions": [
{
"linux-amd64": {
"sha256": "22bf5e63baf3f3f5103ae21bcc35d80cd888d8032095e7b9e8f9631074ac462a",
"size": 86029457,
"url": "https://dl.espressif.com/dl/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3-linux-amd64.tar.gz"
},
"linux-armel": {
"sha256": "27f423af3cfb9d8ed7a02173ccd8dc3b0fd3b3e76a92e9ba507121e73bfa5df3",
"size": 84120606,
"url": "https://dl.espressif.com/dl/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3-linux-armel.tar.gz"
},
"linux-i686": {
"sha256": "479a71cfb4b0c0b36371a1aaed2e6095dfc3241937a54f60a1ba115da73ddec5",
"size": 88015798,
"url": "https://dl.espressif.com/dl/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3-linux-i686.tar.gz"
},
"macos": {
"sha256": "c09b8fcbb840540a3f59429b1bbfbe5abfcacccf7a8a955e4e01e3f50b53a079",
"size": 93013216,
"url": "https://dl.espressif.com/dl/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3-macos.tar.gz"
},
"name": "esp-2020r3-8.4.0",
"status": "recommended",
"win32": {
"sha256": "9591fc32896b13d7fe77310afbbff197cbbc20437d316e0e2460c5c50a10d7b5",
"size": 104536285,
"url": "https://dl.espressif.com/dl/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3-win32.zip"
},
"win64": {
"sha256": "1caf56e9588214d8f1bc17734680ebab2906da3b5f31095e60407dad170f1221",
"size": 107245907,
"url": "https://dl.espressif.com/dl/xtensa-esp32s3-elf-gcc8_4_0-esp-2020r3-win64.zip"
}
}
]
},
{
"description": "Toolchain for RISC-V",
"export_paths": [

View File

@ -27,6 +27,8 @@
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#endif

View File

@ -31,6 +31,8 @@
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S3
#include "esp32s3/clk.h"
#endif
#define D_STALL_COUNTER_ID 0