build and link hello-world for esp32s2beta

This commit is contained in:
suda-morris 2019-06-06 10:57:29 +08:00
parent 61ce868396
commit 84b2f9f14d
108 changed files with 3377 additions and 645 deletions

View file

@ -15,7 +15,12 @@
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_app_trace_util.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#endif
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////// TIMEOUT /////////////////////////////////////

View file

@ -3,6 +3,7 @@ set(COMPONENT_SRCS "esp_ota_ops.c"
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES spi_flash partition_table bootloader_support)
set(COMPONENT_PRIV_REQUIRES)
register_component()

View file

@ -39,10 +39,12 @@
#include "bootloader_common.h"
#include "sys/param.h"
#include "esp_system.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_efuse.h"
#endif
#define SUB_TYPE_ID(i) (i & 0x0F)
#define SUB_TYPE_ID(i) (i & 0x0F)
typedef struct ota_ops_entry_ {
uint32_t handle;

View file

@ -64,7 +64,7 @@
#include "bootloader_utility.h"
#include "bootloader_sha.h"
#ifndef BOOTLOADER_BUILD // TODO: efuse component on esp32s2beta
#if CONFIG_IDF_TARGET_ESP32
#include "esp_efuse.h"
#endif

View file

@ -11,7 +11,7 @@
// 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 "freertos/FreeRTOS.h"
#include "freertos/portmacro.h"
#include "freertos/task.h"
@ -25,6 +25,7 @@
#include "driver/gpio.h"
#include "driver/periph_ctrl.h"
#include "driver/can.h"
#if CONFIG_IDF_TARGET_ESP32
/* ---------------------------- Definitions --------------------------------- */
//Internal Macros
@ -1004,3 +1005,4 @@ esp_err_t can_clear_receive_queue()
return ESP_OK;
}
#endif

View file

@ -212,7 +212,11 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull)
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
{
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
#if CONFIG_IDF_TARGET_ESP32
if (gpio_num >= 34 && (mode & GPIO_MODE_DEF_OUTPUT)) {
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if (gpio_num >= 46 && (mode & GPIO_MODE_DEF_OUTPUT)) {
#endif
ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
return ESP_ERR_INVALID_ARG;
}
@ -516,7 +520,11 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num)
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
r = rtc_gpio_hold_en(gpio_num);
} else if (GPIO_HOLD_MASK[gpio_num]) {
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
#endif
} else {
r = ESP_ERR_NOT_SUPPORTED;
}
@ -530,7 +538,11 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num)
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
r = rtc_gpio_hold_dis(gpio_num);
} else if (GPIO_HOLD_MASK[gpio_num]) {
#if CONFIG_IDF_TARGET_ESP32
CLEAR_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
#endif
} else {
r = ESP_ERR_NOT_SUPPORTED;
}

View file

@ -34,6 +34,9 @@
#include "esp_err.h"
#include "esp_log.h"
#include "esp_pm.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
static const char* I2S_TAG = "I2S";
@ -453,12 +456,20 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
I2S[i2s_num]->clkm_conf.clkm_div_a = 1;
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = m_scale;
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = m_scale;
#if CONFIG_IDF_TARGET_ESP32
I2S[i2s_num]->clkm_conf.clka_en = 1;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
I2S[i2s_num]->clkm_conf.clk_sel = 1;
#endif
double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir);
ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0);
} else {
#if CONFIG_IDF_TARGET_ESP32
I2S[i2s_num]->clkm_conf.clka_en = 0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
I2S[i2s_num]->clkm_conf.clk_sel = 2;
#endif
I2S[i2s_num]->clkm_conf.clkm_div_a = 63;
I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals;
I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger;
@ -1378,3 +1389,4 @@ int i2s_pop_sample(i2s_port_t i2s_num, void *sample, TickType_t ticks_to_wait)
return bytes_pop;
}
}
#endif

View file

@ -76,6 +76,7 @@ extern "C" {
#define GPIO_SEL_38 ((uint64_t)(((uint64_t)1)<<38)) /*!< Pin 38 selected */
#define GPIO_SEL_39 ((uint64_t)(((uint64_t)1)<<39)) /*!< Pin 39 selected */
#if CONFIG_IDF_TARGET_ESP32
#define GPIO_PIN_REG_0 IO_MUX_GPIO0_REG
#define GPIO_PIN_REG_1 IO_MUX_GPIO1_REG
#define GPIO_PIN_REG_2 IO_MUX_GPIO2_REG
@ -111,6 +112,56 @@ extern "C" {
#define GPIO_PIN_REG_37 IO_MUX_GPIO37_REG
#define GPIO_PIN_REG_38 IO_MUX_GPIO38_REG
#define GPIO_PIN_REG_39 IO_MUX_GPIO39_REG
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define GPIO_PIN_REG_0 IO_MUX_GPIO0_REG
#define GPIO_PIN_REG_1 IO_MUX_GPIO1_REG
#define GPIO_PIN_REG_2 IO_MUX_GPIO2_REG
#define GPIO_PIN_REG_3 IO_MUX_GPIO3_REG
#define GPIO_PIN_REG_4 IO_MUX_GPIO4_REG
#define GPIO_PIN_REG_5 IO_MUX_GPIO5_REG
#define GPIO_PIN_REG_6 IO_MUX_GPIO6_REG
#define GPIO_PIN_REG_7 IO_MUX_GPIO7_REG
#define GPIO_PIN_REG_8 IO_MUX_GPIO8_REG
#define GPIO_PIN_REG_9 IO_MUX_GPIO9_REG
#define GPIO_PIN_REG_10 IO_MUX_GPIO10_REG
#define GPIO_PIN_REG_11 IO_MUX_GPIO11_REG
#define GPIO_PIN_REG_12 IO_MUX_GPIO12_REG
#define GPIO_PIN_REG_13 IO_MUX_GPIO13_REG
#define GPIO_PIN_REG_14 IO_MUX_GPIO14_REG
#define GPIO_PIN_REG_15 IO_MUX_GPIO15_REG
#define GPIO_PIN_REG_16 IO_MUX_GPIO16_REG
#define GPIO_PIN_REG_17 IO_MUX_GPIO17_REG
#define GPIO_PIN_REG_18 IO_MUX_GPIO18_REG
#define GPIO_PIN_REG_19 IO_MUX_GPIO19_REG
#define GPIO_PIN_REG_20 IO_MUX_GPIO20_REG
#define GPIO_PIN_REG_21 IO_MUX_GPIO21_REG
#define GPIO_PIN_REG_22 IO_MUX_GPIO22_REG
#define GPIO_PIN_REG_23 IO_MUX_GPIO23_REG
#define GPIO_PIN_REG_24 IO_MUX_GPIO24_REG
#define GPIO_PIN_REG_25 IO_MUX_GPIO25_REG
#define GPIO_PIN_REG_26 IO_MUX_GPIO26_REG
#define GPIO_PIN_REG_27 IO_MUX_GPIO27_REG
#define GPIO_PIN_REG_28 IO_MUX_GPIO28_REG
#define GPIO_PIN_REG_29 IO_MUX_GPIO29_REG
#define GPIO_PIN_REG_30 IO_MUX_GPIO30_REG
#define GPIO_PIN_REG_31 IO_MUX_GPIO31_REG
#define GPIO_PIN_REG_32 IO_MUX_GPIO32_REG
#define GPIO_PIN_REG_33 IO_MUX_GPIO33_REG
#define GPIO_PIN_REG_34 IO_MUX_GPIO34_REG
#define GPIO_PIN_REG_35 IO_MUX_GPIO35_REG
#define GPIO_PIN_REG_36 IO_MUX_GPIO36_REG
#define GPIO_PIN_REG_37 IO_MUX_GPIO37_REG
#define GPIO_PIN_REG_38 IO_MUX_GPIO38_REG
#define GPIO_PIN_REG_39 IO_MUX_GPIO39_REG
#define GPIO_PIN_REG_40 IO_MUX_GPIO40_REG
#define GPIO_PIN_REG_41 IO_MUX_GPIO41_REG
#define GPIO_PIN_REG_42 IO_MUX_GPIO42_REG
#define GPIO_PIN_REG_43 IO_MUX_GPIO43_REG
#define GPIO_PIN_REG_44 IO_MUX_GPIO44_REG
#define GPIO_PIN_REG_45 IO_MUX_GPIO45_REG
#define GPIO_PIN_REG_46 IO_MUX_GPIO46_REG
#define GPIO_PIN_REG_47 IO_MUX_GPIO47_REG
#endif
#define GPIO_APP_CPU_INTR_ENA (BIT(0))
#define GPIO_APP_CPU_NMI_INTR_ENA (BIT(1))
@ -127,7 +178,11 @@ extern "C" {
/** @endcond */
#define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0)) /*!< Check whether it is a valid GPIO number */
#if CONFIG_IDF_TARGET_ESP32
#define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34)) /*!< Check whether it can be a valid GPIO number of output mode */
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 46)) /*!< Check whether it can be a valid GPIO number of output mode */
#endif
typedef enum {
GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */
@ -173,7 +228,19 @@ typedef enum {
GPIO_NUM_37 = 37, /*!< GPIO37, input mode only */
GPIO_NUM_38 = 38, /*!< GPIO38, input mode only */
GPIO_NUM_39 = 39, /*!< GPIO39, input mode only */
#if CONFIG_IDF_TARGET_ESP32
GPIO_NUM_MAX = 40,
#elif CONFIG_IDF_TARGET_ESP32S2BETA
GPIO_NUM_40 = 40, /*!< GPIO40, input mode only */
GPIO_NUM_41 = 41, /*!< GPIO41, input mode only */
GPIO_NUM_42 = 42, /*!< GPIO42, input mode only */
GPIO_NUM_43 = 43, /*!< GPIO43, input mode only */
GPIO_NUM_44 = 44, /*!< GPIO44, input mode only */
GPIO_NUM_45 = 45, /*!< GPIO45, input mode only */
GPIO_NUM_46 = 46, /*!< GPIO46, input mode only */
GPIO_NUM_47 = 47, /*!< GPIO47, input mode only */
GPIO_NUM_MAX = 48,
#endif
/** @endcond */
} gpio_num_t;

View file

@ -61,15 +61,52 @@ extern "C"
*/
#define SPI_SWAP_DATA_RX(data, len) (__builtin_bswap32(data)>>(32-len))
/**
* Transform unsigned integer of length <= 32 bits to the format which can be
* sent by the SPI driver directly.
*
* E.g. to send 9 bits of data, you can:
*
* uint16_t data = SPI_SWAP_DATA_TX(0x145, 9);
*
* Then points tx_buffer to ``&data``.
*
* @param data Data to be sent, can be uint8_t, uint16_t or uint32_t. @param
* len Length of data to be sent, since the SPI peripheral sends from the MSB,
* this helps to shift the data to the MSB.
*/
#define SPI_SWAP_DATA_TX(data, len) __builtin_bswap32((uint32_t)data<<(32-len))
/**
* Transform received data of length <= 32 bits to the format of an unsigned integer.
*
* E.g. to transform the data of 15 bits placed in a 4-byte array to integer:
*
* uint16_t data = SPI_SWAP_DATA_RX(*(uint32_t*)t->rx_data, 15);
*
* @param data Data to be rearranged, can be uint8_t, uint16_t or uint32_t.
* @param len Length of data received, since the SPI peripheral writes from
* the MSB, this helps to shift the data to the LSB.
*/
#define SPI_SWAP_DATA_RX(data, len) (__builtin_bswap32(data)>>(32-len))
/**
* @brief Enum with the three SPI peripherals that are software-accessible in it
*/
#if CONFIG_IDF_TARGET_ESP32
typedef enum {
SPI_HOST=0, ///< SPI1, SPI
HSPI_HOST=1, ///< SPI2, HSPI
VSPI_HOST=2 ///< SPI3, VSPI
} spi_host_device_t;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
typedef enum {
SPI_HOST=0, ///< SPI1, SPI
FSPI_HOST=1, ///< SPI2, FSPI
HSPI_HOST=2, ///< SPI3, HSPI
VSPI_HOST=3 ///< SPI4, VSPI
} spi_host_device_t;
#endif
/**
* @brief This is a configuration structure for a SPI bus.
*
@ -85,6 +122,9 @@ typedef struct {
int sclk_io_num; ///< GPIO pin for Spi CLocK signal, or -1 if not used.
int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
int quadhd_io_num; ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
#if CONFIG_IDF_TARGET_ESP32S2BETA
int spicd_io_num; ///< CD GPIO pin for this device, or -1 if not used
#endif
int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4094 if 0.
uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see

View file

@ -25,6 +25,7 @@
/** SPI master clock is divided by 80MHz apb clock. Below defines are example frequencies, and are accurate. Be free to specify a random frequency, it will be rounded to closest frequency (to macros below if above 8MHz).
* 8MHz
*/
#if APB_CLK_FREQ==80*1000*1000
#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10)
#define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) ///< 8.89MHz
#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/8) ///< 10MHz
@ -35,7 +36,14 @@
#define SPI_MASTER_FREQ_26M (APB_CLK_FREQ/3) ///< 26.67MHz
#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/2) ///< 40MHz
#define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz
#elif APB_CLK_FREQ==40*1000*1000
#define SPI_MASTER_FREQ_7M (APB_CLK_FREQ/6) ///< 13.33MHz
#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/5) ///< 16MHz
#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/4) ///< 20MHz
#define SPI_MASTER_FREQ_13M (APB_CLK_FREQ/3) ///< 26.67MHz
#define SPI_MASTER_FREQ_20M (APB_CLK_FREQ/2) ///< 40MHz
#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/1) ///< 80MHz
#endif
#ifdef __cplusplus
extern "C"
{
@ -54,6 +62,7 @@ extern "C"
* Set this flag to confirm that you're going to work with output only, or read without dummy bits at your own risk.
*/
#define SPI_DEVICE_NO_DUMMY (1<<6)
#define SPI_DEVICE_DDRCLK (1<<7)
typedef struct spi_transaction_t spi_transaction_t;
@ -67,8 +76,8 @@ typedef struct {
uint8_t address_bits; ///< Default amount of bits in address phase (0-64), used when ``SPI_TRANS_VARIABLE_ADDR`` is not used, otherwise ignored.
uint8_t dummy_bits; ///< Amount of dummy bits to insert between address and data phase
uint8_t mode; ///< SPI mode (0-3)
uint8_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
uint8_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
uint16_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16)
int clock_speed_hz; ///< Clock speed, divisors of 80MHz, in Hz. See ``SPI_MASTER_FREQ_*``.
int input_delay_ns; /**< Maximum data valid time of slave. The time required between SCLK and MISO
@ -110,6 +119,7 @@ typedef struct {
#define SPI_TRANS_VARIABLE_CMD (1<<5) ///< Use the ``command_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
#define SPI_TRANS_VARIABLE_ADDR (1<<6) ///< Use the ``address_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
#define SPI_TRANS_VARIABLE_DUMMY (1<<7) ///< Use the ``dummy_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
#define SPI_TRANS_SET_CD (1<<7) ///< Set the CD pin
/**
* This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.

View file

@ -278,7 +278,9 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
if (speed_mode == LEDC_HIGH_SPEED_MODE) {
#if CONFIG_IDF_TARGET_ESP32
gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0);
#endif
} else {
gpio_matrix_out(gpio_num, LEDC_LS_SIG_OUT0_IDX + ledc_channel, 0, 0);
}
@ -318,7 +320,9 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf)
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
if (speed_mode == LEDC_HIGH_SPEED_MODE) {
#if CONFIG_IDF_TARGET_ESP32
gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0);
#endif
} else {
gpio_matrix_out(gpio_num, LEDC_LS_SIG_OUT0_IDX + ledc_channel, 0, 0);
}

View file

@ -23,6 +23,9 @@
#include "soc/gpio_periph.h"
#include "driver/mcpwm.h"
#include "driver/periph_ctrl.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
static mcpwm_dev_t *MCPWM[2] = {&MCPWM0, &MCPWM1};
static const char *MCPWM_TAG = "MCPWM";
@ -41,7 +44,7 @@ static portMUX_TYPE mcpwm_spinlock = portMUX_INITIALIZER_UNLOCKED;
#define MCPWM_DB_ERROR "MCPWM DEADTIME TYPE ERROR"
#define MCPWM_BASE_CLK (2 * APB_CLK_FREQ) //2*APB_CLK_FREQ 160Mhz
#define MCPWM_CLK_PRESCL 15 //MCPWM clock prescale
#define MCPWM_CLK_PRESCL 15 //MCPWM clock prescale
#define TIMER_CLK_PRESCALE 9 //MCPWM timer prescales
#define MCPWM_CLK (MCPWM_BASE_CLK/(MCPWM_CLK_PRESCL +1))
#define MCPWM_PIN_IGNORE (-1)
@ -727,3 +730,4 @@ esp_err_t mcpwm_isr_register(mcpwm_unit_t mcpwm_num, void (*fn)(void *), void *a
ret = esp_intr_alloc((ETS_PWM0_INTR_SOURCE + mcpwm_num), intr_alloc_flags, fn, arg, handle);
return ret;
}
#endif

View file

@ -101,11 +101,11 @@ esp_err_t pcnt_set_pin(pcnt_unit_t unit, pcnt_channel_t channel, int pulse_io, i
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
PCNT_CHECK(GPIO_IS_VALID_GPIO(pulse_io) || pulse_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
PCNT_CHECK(GPIO_IS_VALID_GPIO(ctrl_io) || ctrl_io < 0, PCNT_GPIO_ERR_STR, ESP_ERR_INVALID_ARG);
int sig_base = (channel == 0) ? PCNT_SIG_CH0_IN0_IDX : PCNT_SIG_CH1_IN0_IDX;
int ctrl_base = (channel == 0) ? PCNT_CTRL_CH0_IN0_IDX : PCNT_CTRL_CH1_IN0_IDX;
if (unit > 4) {
sig_base += 12; // GPIO matrix assignments have a gap between units 4 & 5
if (unit > 4) {
sig_base += 12; // GPIO matrix assignments have a gap between units 4 & 5
ctrl_base += 12;
}
int input_sig_index = sig_base + (4 * unit);
@ -156,7 +156,11 @@ esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit)
{
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
#if CONFIG_IDF_TARGET_ESP32
uint32_t reset_bit = BIT(PCNT_PLUS_CNT_RST_U0_S + (pcnt_unit * 2));
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t reset_bit = BIT(PCNT_PULSE_CNT_RST_U0_S + (pcnt_unit * 2));
#endif
PCNT.ctrl.val |= reset_bit;
PCNT.ctrl.val &= ~reset_bit;
PCNT_EXIT_CRITICAL(&pcnt_spinlock);

View file

@ -16,7 +16,9 @@
#include "freertos/semphr.h"
#include "freertos/xtensa_api.h"
#include "soc/dport_reg.h"
#include "soc/syscon_reg.h"
#include "driver/periph_ctrl.h"
#include "sdkconfig.h"
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
@ -61,8 +63,13 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
return DPORT_UART_CLK_EN;
case PERIPH_UART1_MODULE:
return DPORT_UART1_CLK_EN;
#if CONFIG_IDF_TARGET_ESP32
case PERIPH_UART2_MODULE:
return DPORT_UART2_CLK_EN;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
case PERIPH_USB_MODULE:
return DPORT_USB_CLK_EN;
#endif
case PERIPH_I2C0_MODULE:
return DPORT_I2C_EXT0_CLK_EN;
case PERIPH_I2C1_MODULE:
@ -91,12 +98,27 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
return DPORT_PCNT_CLK_EN;
case PERIPH_SPI_MODULE:
return DPORT_SPI01_CLK_EN;
#if CONFIG_IDF_TARGET_ESP32
case PERIPH_HSPI_MODULE:
return DPORT_SPI2_CLK_EN;
case PERIPH_VSPI_MODULE:
return DPORT_SPI3_CLK_EN;
case PERIPH_SPI_DMA_MODULE:
return DPORT_SPI_DMA_CLK_EN;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
case PERIPH_FSPI_MODULE:
return DPORT_SPI2_CLK_EN;
case PERIPH_HSPI_MODULE:
return DPORT_SPI3_CLK_EN;
case PERIPH_VSPI_MODULE:
return DPORT_SPI4_CLK_EN;
case PERIPH_SPI2_DMA_MODULE:
return DPORT_SPI2_DMA_CLK_EN;
case PERIPH_SPI3_DMA_MODULE:
return DPORT_SPI3_DMA_CLK_EN;
case PERIPH_SPI_SHARED_DMA_MODULE:
return DPORT_SPI_SHARED_DMA_CLK_EN;
#endif
case PERIPH_SDMMC_MODULE:
return DPORT_WIFI_CLK_SDIO_HOST_EN;
case PERIPH_SDIO_SLAVE_MODULE:
@ -117,12 +139,14 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
return DPORT_BT_BASEBAND_EN;
case PERIPH_BT_LC_MODULE:
return DPORT_BT_LC_EN;
#if CONFIG_IDF_TARGET_ESP32
case PERIPH_AES_MODULE:
return DPORT_PERI_EN_AES;
case PERIPH_SHA_MODULE:
return DPORT_PERI_EN_SHA;
case PERIPH_RSA_MODULE:
return DPORT_PERI_EN_RSA;
#endif
default:
return 0;
}
@ -139,8 +163,13 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
return DPORT_UART_RST;
case PERIPH_UART1_MODULE:
return DPORT_UART1_RST;
#if CONFIG_IDF_TARGET_ESP32
case PERIPH_UART2_MODULE:
return DPORT_UART2_RST;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
case PERIPH_USB_MODULE:
return DPORT_USB_RST;
#endif
case PERIPH_I2C0_MODULE:
return DPORT_I2C_EXT0_RST;
case PERIPH_I2C1_MODULE:
@ -169,12 +198,27 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
return DPORT_PCNT_RST;
case PERIPH_SPI_MODULE:
return DPORT_SPI01_RST;
#if CONFIG_IDF_TARGET_ESP32
case PERIPH_HSPI_MODULE:
return DPORT_SPI2_RST;
case PERIPH_VSPI_MODULE:
return DPORT_SPI3_RST;
case PERIPH_SPI_DMA_MODULE:
return DPORT_SPI_DMA_RST;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
case PERIPH_FSPI_MODULE:
return DPORT_SPI2_RST;
case PERIPH_HSPI_MODULE:
return DPORT_SPI3_RST;
case PERIPH_VSPI_MODULE:
return DPORT_SPI4_RST;
case PERIPH_SPI2_DMA_MODULE:
return DPORT_SPI2_DMA_RST;
case PERIPH_SPI3_DMA_MODULE:
return DPORT_SPI3_DMA_RST;
case PERIPH_SPI_SHARED_DMA_MODULE:
return DPORT_SPI_SHARED_DMA_RST;
#endif
case PERIPH_SDMMC_MODULE:
return DPORT_SDIO_HOST_RST;
case PERIPH_SDIO_SLAVE_MODULE:
@ -183,6 +227,7 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
return DPORT_CAN_RST;
case PERIPH_EMAC_MODULE:
return DPORT_EMAC_RST;
#if CONFIG_IDF_TARGET_ESP32
case PERIPH_AES_MODULE:
if (enable == true) {
// Clear reset on digital signature & secure boot units, otherwise AES unit is held in reset also.
@ -207,6 +252,7 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
// Don't reset digital signature unit, as this resets AES also
return DPORT_PERI_EN_RSA;
}
#endif
case PERIPH_WIFI_MODULE:
case PERIPH_BT_MODULE:
case PERIPH_WIFI_BT_COMMON_MODULE:
@ -240,18 +286,32 @@ static bool is_wifi_clk_peripheral(periph_module_t periph)
static uint32_t get_clk_en_reg(periph_module_t periph)
{
#if CONFIG_IDF_TARGET_ESP32
if (periph == PERIPH_AES_MODULE || periph == PERIPH_SHA_MODULE || periph == PERIPH_RSA_MODULE) {
return DPORT_PERI_CLK_EN_REG;
} else {
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if(periph == PERIPH_SPI_SHARED_DMA_MODULE) {
return DPORT_PERIP_CLK_EN1_REG;
}
#endif
else {
return is_wifi_clk_peripheral(periph) ? DPORT_WIFI_CLK_EN_REG : DPORT_PERIP_CLK_EN_REG;
}
}
static uint32_t get_rst_en_reg(periph_module_t periph)
{
#if CONFIG_IDF_TARGET_ESP32
if (periph == PERIPH_AES_MODULE || periph == PERIPH_SHA_MODULE || periph == PERIPH_RSA_MODULE) {
return DPORT_PERI_RST_EN_REG;
} else {
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if(periph == PERIPH_SPI_SHARED_DMA_MODULE){
return DPORT_PERIP_CLK_EN1_REG;
}
#endif
else {
return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG : DPORT_PERIP_RST_EN_REG;
}
}

View file

@ -317,7 +317,11 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool* idle_out_en, rmt_idle_
esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t* status)
{
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
#if CONFIG_IDF_TARGET_ESP32
*status = RMT.status_ch[channel];
#elif CONFIG_IDF_TARGET_ESP32S2BETA
*status = RMT.status_ch[channel].val;
#endif
return ESP_OK;
}

View file

@ -15,12 +15,12 @@
#include <esp_types.h>
#include <stdlib.h>
#include <ctype.h>
#include "esp32/rom/ets_sys.h"
#include "esp_log.h"
#include "soc/rtc_periph.h"
#include "soc/sens_periph.h"
#include "soc/syscon_periph.h"
#include "soc/rtc.h"
#include "soc/periph_defs.h"
#include "rtc_io.h"
#include "touch_pad.h"
#include "adc.h"
@ -34,6 +34,12 @@
#include "driver/rtc_cntl.h"
#include "driver/gpio.h"
#include "adc1_i2s_private.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds
@ -83,14 +89,14 @@ portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
static SemaphoreHandle_t rtc_touch_mux = NULL;
/*
In ADC2, there're two locks used for different cases:
1. lock shared with app and WIFI:
when wifi using the ADC2, we assume it will never stop,
1. lock shared with app and WIFI:
when wifi using the ADC2, we assume it will never stop,
so app checks the lock and returns immediately if failed.
2. lock shared between tasks:
when several tasks sharing the ADC2, we want to guarantee
2. lock shared between tasks:
when several tasks sharing the ADC2, we want to guarantee
all the requests will be handled.
Since conversions are short (about 31us), app returns the lock very soon,
Since conversions are short (about 31us), app returns the lock very soon,
we use a spinlock to stand there waiting to do conversions one by one.
adc2_spinlock should be acquired first, then adc2_wifi_lock or rtc_spinlock.
@ -373,7 +379,9 @@ void rtc_gpio_force_hold_dis_all()
for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) {
const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio];
if (desc->hold_force != 0) {
#if CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold_force);
#endif
}
}
}
@ -432,13 +440,21 @@ inline static touch_pad_t touch_pad_num_wrap(touch_pad_t touch_num)
esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
{
RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
#if CONFIG_IDF_TARGET_ESP32
return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
#else
return ESP_FAIL;
#endif
}
esp_err_t touch_pad_isr_register(intr_handler_t fn, void* arg)
{
RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
#if CONFIG_IDF_TARGET_ESP32
return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
#else
return ESP_FAIL;
#endif
}
esp_err_t touch_pad_isr_deregister(intr_handler_t fn, void *arg)
@ -566,7 +582,7 @@ esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, t
ESP_ERR_INVALID_ARG);
RTC_MODULE_CHECK(((atten < TOUCH_HVOLT_ATTEN_MAX) && (refh >= (int )TOUCH_HVOLT_ATTEN_KEEP)), "touch atten error",
ESP_ERR_INVALID_ARG);
#if CONFIG_IDF_TARGET_ESP32
portENTER_CRITICAL(&rtc_spinlock);
if (refh > TOUCH_HVOLT_KEEP) {
RTCIO.touch_cfg.drefh = refh;
@ -578,11 +594,13 @@ esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, t
RTCIO.touch_cfg.drange = atten;
}
portEXIT_CRITICAL(&rtc_spinlock);
#endif
return ESP_OK;
}
esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten)
{
#if CONFIG_IDF_TARGET_ESP32
portENTER_CRITICAL(&rtc_spinlock);
if (refh) {
*refh = RTCIO.touch_cfg.drefh;
@ -594,6 +612,7 @@ esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl,
*atten = RTCIO.touch_cfg.drange;
}
portEXIT_CRITICAL(&rtc_spinlock);
#endif
return ESP_OK;
}
@ -601,7 +620,7 @@ esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope,
{
RTC_MODULE_CHECK((slope < TOUCH_PAD_SLOPE_MAX), "touch slope error", ESP_ERR_INVALID_ARG);
RTC_MODULE_CHECK((opt < TOUCH_PAD_TIE_OPT_MAX), "touch opt error", ESP_ERR_INVALID_ARG);
touch_pad_t touch_pad_wrap = touch_pad_num_wrap(touch_num);
portENTER_CRITICAL(&rtc_spinlock);
RTCIO.touch_pad[touch_pad_wrap].tie_opt = opt;
@ -613,7 +632,7 @@ esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope,
esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt)
{
RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX), "touch IO error", ESP_ERR_INVALID_ARG);
touch_pad_t touch_pad_wrap = touch_pad_num_wrap(touch_num);
portENTER_CRITICAL(&rtc_spinlock);
if(opt) {
@ -1152,7 +1171,7 @@ void adc_power_on()
#ifndef CONFIG_ADC_FORCE_XPD_FSM
//Set the power always on to increase precision.
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
#else
#else
//Use the FSM to turn off the power while not used to save power.
if (SENS.sar_meas_wait2.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
@ -1266,12 +1285,12 @@ static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl )
break;
default:
ESP_LOGE(TAG, "adc1 selects invalid controller");
break;
break;
}
} else if ( unit == ADC_UNIT_2) {
switch( ctrl ) {
case ADC_CTRL_RTC:
SENS.sar_meas_start2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
SENS.sar_meas_start2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
SENS.sar_meas_start2.sar2_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
SENS.sar_read_ctrl2.sar2_dig_force = false; //RTC controller controls the ADC, not digital controller
SENS.sar_read_ctrl2.sar2_pwdet_force = false; //RTC controller controls the ADC, not PWDET
@ -1301,7 +1320,7 @@ static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl )
break;
default:
ESP_LOGE(TAG, "adc2 selects invalid controller");
break;
break;
}
} else {
ESP_LOGE(TAG, "invalid adc unit");
@ -1321,12 +1340,12 @@ static int adc_convert( adc_unit_t unit, int channel)
while (SENS.sar_meas_start1.meas1_done_sar == 0);
adc_value = SENS.sar_meas_start1.meas1_data_sar;
} else if ( unit == ADC_UNIT_2 ) {
SENS.sar_meas_start2.sar2_en_pad = (1 << channel); //only one channel is selected.
SENS.sar_meas_start2.sar2_en_pad = (1 << channel); //only one channel is selected.
SENS.sar_meas_start2.meas2_start_sar = 0; //start force 0
SENS.sar_meas_start2.meas2_start_sar = 1; //start force 1
while (SENS.sar_meas_start2.meas2_done_sar == 0) {}; //read done
adc_value = SENS.sar_meas_start2.meas2_data_sar;
adc_value = SENS.sar_meas_start2.meas2_data_sar;
} else {
ESP_LOGE(TAG, "invalid adc unit");
return ESP_ERR_INVALID_ARG;
@ -1479,7 +1498,7 @@ static inline void adc1_fsm_disable()
SENS.sar_meas_ctrl.amp_short_ref_gnd_fsm = 0;
SENS.sar_meas_wait1.sar_amp_wait1 = 1;
SENS.sar_meas_wait1.sar_amp_wait2 = 1;
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
}
esp_err_t adc1_i2s_mode_acquire()
@ -1530,7 +1549,7 @@ int adc1_get_raw(adc1_channel_t channel)
adc1_adc_mode_acquire();
adc_power_on();
portENTER_CRITICAL(&rtc_spinlock);
portENTER_CRITICAL(&rtc_spinlock);
//disable other peripherals
adc1_hall_enable(false);
adc1_fsm_disable(); //currently the LNA is not open, close it by default
@ -1652,7 +1671,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
}
SENS.sar_atten2 = ( SENS.sar_atten2 & ~(3<<(channel*2)) ) | ((atten&3) << (channel*2));
_lock_release( &adc2_wifi_lock );
portEXIT_CRITICAL( &adc2_spinlock );
return ESP_OK;
}
@ -1682,7 +1701,7 @@ static inline void adc2_dac_disable( adc2_channel_t channel)
}
//registers in critical section with adc1:
//SENS_SAR_START_FORCE_REG,
//SENS_SAR_START_FORCE_REG,
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int* raw_out)
{
uint16_t adc_value = 0;
@ -1692,7 +1711,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int*
adc_power_on();
//avoid collision with other tasks
portENTER_CRITICAL(&adc2_spinlock);
portENTER_CRITICAL(&adc2_spinlock);
//lazy initialization
//try the lock, return if failed (wifi using).
if ( _lock_try_acquire( &adc2_wifi_lock ) == -1 ) {
@ -1895,7 +1914,9 @@ esp_err_t dac_i2s_disable()
static inline void adc1_hall_enable(bool enable)
{
RTCIO.hall_sens.xpd_hall = enable;
#if CONFIG_IDF_TARGET_ESP32
RTCIO.hall_sens.xpd_hall = enable;
#endif
}
static int hall_sensor_get_value() //hall sensor without LNA
@ -1904,14 +1925,15 @@ static int hall_sensor_get_value() //hall sensor without LNA
int Sens_Vn0;
int Sens_Vp1;
int Sens_Vn1;
int hall_value;
int hall_value = 0;
adc_power_on();
#if CONFIG_IDF_TARGET_ESP32
portENTER_CRITICAL(&rtc_spinlock);
//disable other peripherals
adc1_fsm_disable();//currently the LNA is not open, close it by default
adc1_hall_enable(true);
adc1_fsm_disable();//currently the LNA is not open, close it by default
adc1_hall_enable(true);
// set controller
adc_set_controller( ADC_UNIT_1, ADC_CTRL_RTC );
// convert for 4 times with different phase and outputs
@ -1923,7 +1945,7 @@ static int hall_sensor_get_value() //hall sensor without LNA
Sens_Vn1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 );
portEXIT_CRITICAL(&rtc_spinlock);
hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
#endif
return hall_value;
}

View file

@ -25,7 +25,7 @@
#include "sdmmc_private.h"
#include "freertos/semphr.h"
#include "soc/sdmmc_periph.h"
#if CONFIG_IDF_TARGET_ESP32
#define SDMMC_EVENT_QUEUE_LENGTH 32
@ -635,3 +635,4 @@ esp_err_t sdmmc_host_pullup_en(int slot, int width)
}
return ESP_OK;
}
#endif

View file

@ -14,6 +14,8 @@
#include <string.h>
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "driver/spi_master.h"
#include "soc/spi_periph.h"
#include "esp32/rom/ets_sys.h"
@ -30,6 +32,9 @@
#include "driver/spi_common.h"
#include "stdatomic.h"
#include "hal/spi_hal.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "cas.h"
#endif
static const char *SPI_TAG = "spi";
@ -112,7 +117,17 @@ bool spicommon_dma_chan_claim (int dma_chan)
spi_dma_chan_enabled |= DMA_CHANNEL_ENABLED(dma_chan);
ret = true;
}
#if CONFIG_IDF_TARGET_ESP32
periph_module_enable( PERIPH_SPI_DMA_MODULE );
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if (dma_chan==1) {
periph_module_enable(PERIPH_SPI2_DMA_MODULE);
} else if (dma_chan==2) {
periph_module_enable(PERIPH_SPI3_DMA_MODULE);
} else if (dma_chan==3) {
periph_module_enable(PERIPH_SPI_SHARED_DMA_MODULE);
}
#endif
portEXIT_CRITICAL(&spi_dma_spinlock);
return ret;
@ -131,10 +146,20 @@ bool spicommon_dma_chan_free(int dma_chan)
portENTER_CRITICAL(&spi_dma_spinlock);
spi_dma_chan_enabled &= ~DMA_CHANNEL_ENABLED(dma_chan);
#if CONFIG_IDF_TARGET_ESP32
if ( spi_dma_chan_enabled == 0 ) {
//disable the DMA only when all the channels are freed.
periph_module_disable( PERIPH_SPI_DMA_MODULE );
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if (dma_chan==1) {
periph_module_disable(PERIPH_SPI2_DMA_MODULE);
} else if (dma_chan==2) {
periph_module_disable(PERIPH_SPI3_DMA_MODULE);
} else if (dma_chan==3) {
periph_module_disable(PERIPH_SPI_SHARED_DMA_MODULE);
}
#endif
portEXIT_CRITICAL(&spi_dma_spinlock);
return true;
@ -234,23 +259,43 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1);
if (bus_config->mosi_io_num >= 0) {
gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in);
#if CONFIG_IDF_TARGET_ESP32
gpio_iomux_out(bus_config->mosi_io_num, FUNC_SPI, false);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
#endif
}
if (bus_config->miso_io_num >= 0) {
gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in);
#if CONFIG_IDF_TARGET_ESP32
gpio_iomux_out(bus_config->miso_io_num, FUNC_SPI, false);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
#endif
}
if (bus_config->quadwp_io_num >= 0) {
gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in);
#if CONFIG_IDF_TARGET_ESP32
gpio_iomux_out(bus_config->quadwp_io_num, FUNC_SPI, false);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
#endif
}
if (bus_config->quadhd_io_num >= 0) {
gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in);
#if CONFIG_IDF_TARGET_ESP32
gpio_iomux_out(bus_config->quadhd_io_num, FUNC_SPI, false);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
#endif
}
if (bus_config->sclk_io_num >= 0) {
gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in);
#if CONFIG_IDF_TARGET_ESP32
gpio_iomux_out(bus_config->sclk_io_num, FUNC_SPI, false);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
#endif
}
temp_flag |= SPICOMMON_BUSFLAG_NATIVE_PINS;
} else {
@ -264,6 +309,9 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT);
}
gpio_matrix_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in, false);
#if CONFIG_IDF_TARGET_ESP32S2BETA
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->mosi_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
}
if (bus_config->miso_io_num >= 0) {
@ -274,18 +322,27 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT);
}
gpio_matrix_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in, false);
#if CONFIG_IDF_TARGET_ESP32S2BETA
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->miso_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO);
}
if (bus_config->quadwp_io_num >= 0) {
gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT);
gpio_matrix_out(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_out, false, false);
gpio_matrix_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in, false);
#if CONFIG_IDF_TARGET_ESP32S2BETA
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO);
}
if (bus_config->quadhd_io_num >= 0) {
gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT);
gpio_matrix_out(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_out, false, false);
gpio_matrix_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in, false);
#if CONFIG_IDF_TARGET_ESP32S2BETA
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO);
}
if (bus_config->sclk_io_num >= 0) {
@ -296,12 +353,30 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT);
}
gpio_matrix_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in, false);
#if CONFIG_IDF_TARGET_ESP32S2BETA
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->sclk_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO);
}
#if CONFIG_IDF_TARGET_ESP32S2BETA
if (bus_config->spicd_io_num >= 0) {
gpio_set_direction(bus_config->spicd_io_num, GPIO_MODE_INPUT_OUTPUT);
gpio_matrix_out(bus_config->spicd_io_num, spi_periph_signal[host].spicd_out, false, false);
gpio_matrix_in(bus_config->spicd_io_num, spi_periph_signal[host].spicd_in, false);
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->spicd_io_num]);
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->spicd_io_num], FUNC_GPIO);
}
#endif
}
//Select DMA channel.
#if CONFIG_IDF_TARGET_ESP32
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if (dma_chan==VSPI_HOST) {
DPORT_SET_PERI_REG_MASK(DPORT_SPI_DMA_CHAN_SEL_REG, DPORT_SPI_SHARED_DMA_SEL_M);
}
#endif
if (flags_o) *flags_o = temp_flag;
return ESP_OK;
@ -354,7 +429,11 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
if (!force_gpio_matrix && cs_io_num == spi_periph_signal[host].spics0_iomux_pin && cs_num == 0) {
//The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define.
gpio_iomux_in(cs_io_num, spi_periph_signal[host].spics_in);
#if CONFIG_IDF_TARGET_ESP32
gpio_iomux_out(cs_io_num, FUNC_SPI, false);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
gpio_iomux_out(cs_io_num, spi_periph_signal[host].func, false);
#endif
} else {
//Use GPIO matrix
if (GPIO_IS_VALID_OUTPUT_GPIO(cs_io_num)) {
@ -364,6 +443,9 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
gpio_set_direction(cs_io_num, GPIO_MODE_INPUT);
}
if (cs_num == 0) gpio_matrix_in(cs_io_num, spi_periph_signal[host].spics_in, false);
#if CONFIG_IDF_TARGET_ESP32S2BETA
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[cs_io_num]);
#endif
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO);
}
}
@ -402,6 +484,7 @@ static int dmaworkaround_waiting_for_chan = 0;
bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg)
{
#if CONFIG_IDF_TARGET_ESP32
int otherchan = (dmachan == 1) ? 2 : 1;
bool ret;
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
@ -418,6 +501,9 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
}
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
return ret;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
return true;
#endif
}
bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress()
@ -427,6 +513,7 @@ bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress()
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
{
#if CONFIG_IDF_TARGET_ESP32
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
dmaworkaround_channels_busy[dmachan-1] = 0;
if (dmaworkaround_waiting_for_chan == dmachan) {
@ -438,6 +525,7 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
}
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
#endif
}
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
@ -447,4 +535,4 @@ void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
}
#endif

View file

@ -122,7 +122,6 @@ We have two bits to control the interrupt:
#include "driver/spi_common.h"
#include "driver/spi_master.h"
#include "soc/spi_periph.h"
#include "esp32/rom/ets_sys.h"
#include "esp_types.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
@ -139,8 +138,12 @@ We have two bits to control the interrupt:
#include "esp_heap_caps.h"
#include "stdatomic.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#include "hal/spi_hal.h"
#if CONFIG_IDF_TARGET_ESP32S2BETA
#include "cas.h"
#endif
typedef struct spi_device_t spi_device_t;
@ -183,6 +186,9 @@ typedef struct {
int dma_chan;
int max_transfer_sz;
spi_bus_config_t bus_cfg;
#if CONFIG_IDF_TARGET_ESP32S2BETA
int id;
#endif
#ifdef CONFIG_PM_ENABLE
esp_pm_lock_handle_t pm_lock;
#endif
@ -199,7 +205,7 @@ struct spi_device_t {
bool waiting; //the device is waiting for the exclusive control of the bus
};
static spi_host_t *spihost[3];
static spi_host_t *spihost[SPI_PERIPH_NUM];
static const char *SPI_TAG = "spi_master";
@ -245,6 +251,10 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
}
memset(spihost[host], 0, sizeof(spi_host_t));
memcpy( &spihost[host]->bus_cfg, bus_config, sizeof(spi_bus_config_t));
#if CONFIG_IDF_TARGET_ESP32S2BETA
spihost[host]->id = host;
#endif
#ifdef CONFIG_PM_ENABLE
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master",
&spihost[host]->pm_lock);
@ -259,7 +269,13 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
ret = err;
goto cleanup;
}
#if CONFIG_IDF_TARGET_ESP32
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if (host==VSPI_HOST) {
DPORT_SET_PERI_REG_BITS(DPORT_SPI_SHARED_DMA_SEL_REG, DPORT_SPI_SHARED_DMA_SEL_M, 1, DPORT_SPI_SHARED_DMA_SEL_S);
}
#endif
int dma_desc_ct=0;
spihost[host]->dma_chan=dma_chan;
if (dma_chan == 0) {
@ -1084,4 +1100,4 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_transmit(spi_device_handle_t ha
return ESP_OK;
}
#endif

View file

@ -13,13 +13,14 @@
// limitations under the License.
#include <string.h>
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include <hal/spi_ll.h>
#include <hal/spi_slave_hal.h>
#include <soc/lldesc.h>
#include "driver/spi_common.h"
#include "driver/spi_slave.h"
#include "soc/spi_periph.h"
#include "esp32/rom/ets_sys.h"
#include "esp_types.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
@ -34,7 +35,7 @@
#include "esp32/rom/lldesc.h"
#include "driver/gpio.h"
#include "esp_heap_caps.h"
#include "esp32/rom/ets_sys.h"
static const char *SPI_TAG = "spi_slave";
#define SPI_CHECK(a, str, ret_val) \
if (!(a)) { \
@ -392,4 +393,4 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
if (do_yield) portYIELD_FROM_ISR();
}
#endif

View file

@ -19,6 +19,7 @@
#include "freertos/xtensa_api.h"
#include "driver/timer.h"
#include "driver/periph_ctrl.h"
#include "sdkconfig.h"
static const char* TIMER_TAG = "timer_group";
#define TIMER_CHECK(a, str, ret_val) \
@ -47,7 +48,11 @@ esp_err_t timer_get_counter_value(timer_group_t group_num, timer_idx_t timer_num
TIMER_CHECK(timer_num < TIMER_MAX, TIMER_NUM_ERROR, ESP_ERR_INVALID_ARG);
TIMER_CHECK(timer_val != NULL, TIMER_PARAM_ADDR_ERROR, ESP_ERR_INVALID_ARG);
portENTER_CRITICAL_SAFE(&timer_spinlock[group_num]);
#if CONFIG_IDF_TARGET_ESP32
TG[group_num]->hw_timer[timer_num].update = 1;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
TG[group_num]->hw_timer[timer_num].update.update = 1;
#endif
*timer_val = ((uint64_t) TG[group_num]->hw_timer[timer_num].cnt_high << 32)
| (TG[group_num]->hw_timer[timer_num].cnt_low);
portEXIT_CRITICAL_SAFE(&timer_spinlock[group_num]);
@ -171,7 +176,7 @@ esp_err_t timer_set_alarm(timer_group_t group_num, timer_idx_t timer_num, timer_
return ESP_OK;
}
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
void (*fn)(void*), void * arg, int intr_alloc_flags, timer_isr_handle_t *handle)
{
TIMER_CHECK(group_num < TIMER_GROUP_MAX, TIMER_GROUP_NUM_ERROR, ESP_ERR_INVALID_ARG);
@ -222,7 +227,11 @@ esp_err_t timer_init(timer_group_t group_num, timer_idx_t timer_num, const timer
//but software reset does not clear interrupt status. This is not safe for application when enable the interrupt of timer_group.
//we need to disable the interrupt and clear the interrupt status here.
TG[group_num]->int_ena.val &= (~BIT(timer_num));
#if CONFIG_IDF_TARGET_ESP32
TG[group_num]->int_clr_timers.val = BIT(timer_num);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
TG[group_num]->int_clr.val = BIT(timer_num);
#endif
TG[group_num]->hw_timer[timer_num].config.autoreload = config->auto_reload;
TG[group_num]->hw_timer[timer_num].config.divider = (uint16_t) config->divider;
TG[group_num]->hw_timer[timer_num].config.enable = config->counter_en;

View file

@ -17,7 +17,6 @@
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "esp_err.h"
#include "esp32/clk.h"
#include "malloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
@ -28,6 +27,12 @@
#include "driver/uart.h"
#include "driver/gpio.h"
#include "driver/uart_select.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#endif
#define XOFF (char)0x13
#define XON (char)0x11
@ -79,7 +84,7 @@ typedef struct {
intr_handle_t intr_handle; /*!< UART interrupt handle*/
uart_mode_t uart_mode; /*!< UART controller actual mode set by uart_set_mode() */
bool coll_det_flg; /*!< UART collision detection flag */
//rx parameters
int rx_buffered_len; /*!< UART cached data length */
SemaphoreHandle_t rx_mux; /*!< UART RX data mutex*/
@ -298,9 +303,15 @@ static esp_err_t uart_reset_rx_fifo(uart_port_t uart_num)
//See description about UART_TXFIFO_RST and UART_RXFIFO_RST in <<esp32_technical_reference_manual>> v2.6 or later.
// we read the data out and make `fifo_len == 0 && rd_addr == wr_addr`.
#if CONFIG_IDF_TARGET_ESP32
while(UART[uart_num]->status.rxfifo_cnt != 0 || (UART[uart_num]->mem_rx_status.wr_addr != UART[uart_num]->mem_rx_status.rd_addr)) {
READ_PERI_REG(UART_FIFO_REG(uart_num));
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
while(UART[uart_num]->status.rxfifo_cnt != 0 || (UART[uart_num]->mem_rx_status.rx_waddr != UART[uart_num]->mem_rx_status.apb_rx_raddr)) {
READ_PERI_REG(UART_FIFO_AHB_REG(uart_num));
}
#endif
return ESP_OK;
}
@ -577,12 +588,14 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
rts_sig = U1RTS_OUT_IDX;
cts_sig = U1CTS_IN_IDX;
break;
#if CONFIG_IDF_TARGET_ESP32
case UART_NUM_2:
tx_sig = U2TXD_OUT_IDX;
rx_sig = U2RXD_IN_IDX;
rts_sig = U2RTS_OUT_IDX;
cts_sig = U2CTS_IN_IDX;
break;
#endif
case UART_NUM_MAX:
default:
tx_sig = U0TXD_OUT_IDX;
@ -657,7 +670,11 @@ esp_err_t uart_param_config(uart_port_t uart_num, const uart_config_t *uart_conf
} else if(uart_num == UART_NUM_1) {
periph_module_enable(PERIPH_UART1_MODULE);
} else if(uart_num == UART_NUM_2) {
#if CONFIG_IDF_TARGET_ESP32
periph_module_enable(PERIPH_UART2_MODULE);
#else
return ESP_FAIL;
#endif
}
r = uart_set_hw_flow_ctrl(uart_num, uart_config->flow_ctrl, uart_config->rx_flow_ctrl_thresh);
if (r != ESP_OK) return r;
@ -861,7 +878,11 @@ static void uart_rx_intr_handler_default(void *param)
if (p_uart->rx_buffer_full_flg == false) {
//We have to read out all data in RX FIFO to clear the interrupt signal
while (buf_idx < rx_fifo_len) {
#if CONFIG_IDF_TARGET_ESP32
p_uart->rx_data_buf[buf_idx++] = uart_reg->fifo.rw_byte;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
p_uart->rx_data_buf[buf_idx++] = READ_PERI_REG(UART_FIFO_AHB_REG(uart_num));
#endif
}
uint8_t pat_chr = uart_reg->at_cmd_char.data;
int pat_num = uart_reg->at_cmd_char.char_num;
@ -997,13 +1018,13 @@ static void uart_rx_intr_handler_default(void *param)
UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
uart_reset_rx_fifo(uart_num);
// Set collision detection flag
p_uart_obj[uart_num]->coll_det_flg = true;
p_uart_obj[uart_num]->coll_det_flg = true;
UART_EXIT_CRITICAL_ISR(&uart_spinlock[uart_num]);
uart_event.type = UART_EVENT_MAX;
} else if(uart_intr_status & UART_TX_DONE_INT_ST_M) {
uart_disable_intr_mask_from_isr(uart_num, UART_TX_DONE_INT_ENA_M);
uart_clear_intr_status(uart_num, UART_TX_DONE_INT_CLR_M);
// If RS485 half duplex mode is enable then reset FIFO and
// If RS485 half duplex mode is enable then reset FIFO and
// reset RTS pin to start receiver driver
if (UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)) {
UART_ENTER_CRITICAL_ISR(&uart_spinlock[uart_num]);
@ -1461,7 +1482,11 @@ esp_err_t uart_driver_delete(uart_port_t uart_num)
} else if(uart_num == UART_NUM_1) {
periph_module_disable(PERIPH_UART1_MODULE);
} else if(uart_num == UART_NUM_2) {
periph_module_disable(PERIPH_UART2_MODULE);
#if CONFIG_IDF_TARGET_ESP32
periph_module_disable(PERIPH_UART2_MODULE);
#else
return ESP_FAIL;
#endif
}
}
return ESP_OK;
@ -1479,11 +1504,11 @@ portMUX_TYPE *uart_get_selectlock()
return &uart_selectlock;
}
// Set UART mode
esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode)
esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode)
{
UART_CHECK((p_uart_obj[uart_num]), "uart driver error", ESP_ERR_INVALID_STATE);
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
if ((mode == UART_MODE_RS485_COLLISION_DETECT) || (mode == UART_MODE_RS485_APP_CTRL)
if ((mode == UART_MODE_RS485_COLLISION_DETECT) || (mode == UART_MODE_RS485_APP_CTRL)
|| (mode == UART_MODE_RS485_HALF_DUPLEX)) {
UART_CHECK((UART[uart_num]->conf1.rx_flow_en != 1),
"disable hw flowctrl before using RS485 mode", ESP_ERR_INVALID_ARG);
@ -1538,13 +1563,13 @@ esp_err_t uart_set_mode(uart_port_t uart_num, uart_mode_t mode)
return ESP_OK;
}
esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh)
esp_err_t uart_set_rx_timeout(uart_port_t uart_num, const uint8_t tout_thresh)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((tout_thresh < 127), "tout_thresh max value is 126", ESP_ERR_INVALID_ARG);
UART_ENTER_CRITICAL(&uart_spinlock[uart_num]);
// The tout_thresh = 1, defines TOUT interrupt timeout equal to
// transmission time of one symbol (~11 bit) on current baudrate
// The tout_thresh = 1, defines TOUT interrupt timeout equal to
// transmission time of one symbol (~11 bit) on current baudrate
if (tout_thresh > 0) {
UART[uart_num]->conf1.rx_tout_thrhd = (tout_thresh & UART_RX_TOUT_THRHD_V);
UART[uart_num]->conf1.rx_tout_en = 1;
@ -1559,8 +1584,8 @@ esp_err_t uart_get_collision_flag(uart_port_t uart_num, bool* collision_flag)
{
UART_CHECK((uart_num < UART_NUM_MAX), "uart_num error", ESP_ERR_INVALID_ARG);
UART_CHECK((collision_flag != NULL), "wrong parameter pointer", ESP_ERR_INVALID_ARG);
UART_CHECK((UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)
|| UART_IS_MODE_SET(uart_num, UART_MODE_RS485_COLLISION_DETECT)),
UART_CHECK((UART_IS_MODE_SET(uart_num, UART_MODE_RS485_HALF_DUPLEX)
|| UART_IS_MODE_SET(uart_num, UART_MODE_RS485_COLLISION_DETECT)),
"wrong mode", ESP_ERR_INVALID_ARG);
*collision_flag = p_uart_obj[uart_num]->coll_det_flg;
return ESP_OK;

View file

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ESP_EFUSE_MANAGER_H_
#define _ESP_EFUSE_MANAGER_H_
#pragma once
#ifdef __cplusplus
extern "C" {
@ -358,5 +357,3 @@ void esp_efuse_init(uint32_t offset, uint32_t size);
#ifdef __cplusplus
}
#endif
#endif // _ESP_EFUSE_MANAGER_H_

View file

@ -46,12 +46,14 @@ elseif(CONFIG_IDF_TARGET_ESP32S2BETA)
target_linker_script(${COMPONENT_LIB} "${CMAKE_CURRENT_BINARY_DIR}/esp32s2beta_out.ld")
# Rely on user code to define app_main
target_link_libraries(${COMPONENT_LIB} "-u app_main")
# Process the template file through the linker script generation mechanism, and use the output for linking the
# final binary
target_linker_script(${COMPONENT_LIB} "${CMAKE_CURRENT_LIST_DIR}/ld/esp32s2beta.project.ld.in" PROCESS)
target_linker_script(${COMPONENT_LIB} "ld/esp32s2beta.peripherals.ld")
target_link_libraries(${COMPONENT_LIB} gcc)
target_link_libraries(${COMPONENT_LIB} "-u call_user_start_cpu0")
@ -79,6 +81,4 @@ elseif(CONFIG_IDF_TARGET_ESP32S2BETA)
cpu_start.c
PROPERTIES COMPILE_FLAGS
-fno-stack-protector)
else()
register_config_only_component()
endif()

View file

@ -24,6 +24,8 @@
#include "esp32s2beta/rom/ets_sys.h"
#include "esp32s2beta/rom/uart.h"
#include "esp32s2beta/rom/rtc.h"
#include "soc/system_reg.h"
#include "soc/dport_access.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"

View file

@ -14,7 +14,7 @@
#include <stdint.h>
#include <string.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
@ -22,6 +22,10 @@
#include "esp32s2beta/rom/uart.h"
#include "esp32s2beta/rom/rtc.h"
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/dport_access.h"
#include "esp32s2beta/brownout.h"
#include "esp32s2beta/cache_err_int.h"
#include "esp32s2beta/spiram.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
@ -40,36 +44,33 @@
#include "freertos/portmacro.h"
#include "esp_heap_caps_init.h"
#include "sdkconfig.h"
#include "esp_system.h"
#include "esp_spi_flash.h"
#include "nvs_flash.h"
#include "esp_event.h"
#include "esp_spi_flash.h"
#include "esp_ipc.h"
#include "esp32s2beta/dport_access.h"
#include "esp_private/crosscore_int.h"
#include "esp_log.h"
#include "esp_vfs_dev.h"
#include "esp_newlib.h"
#include "esp32s2beta/brownout.h"
#include "esp_int_wdt.h"
#include "esp_task.h"
#include "esp_task_wdt.h"
#include "esp_phy_init.h"
#include "esp32s2beta/cache_err_int.h"
#include "esp_coexist_internal.h"
#include "esp_debug_helpers.h"
#include "esp_core_dump.h"
#include "esp_app_trace.h"
#include "esp_private/dbg_stubs.h"
#include "esp_efuse.h"
#include "esp32s2beta/spiram.h"
#include "esp_clk_internal.h"
#include "esp_timer.h"
#include "esp_pm.h"
#include "esp_private/pm_impl.h"
#include "trax.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_efuse.h"
#endif
#define STRINGIFY(s) STRINGIFY2(s)
#define STRINGIFY2(s) #s
@ -137,7 +138,9 @@ void IRAM_ATTR call_start_cpu0()
|| rst_reas[1] == RTCWDT_SYS_RESET || rst_reas[1] == TG0WDT_SYS_RESET
#endif
) {
esp_panic_wdt_stop();
#ifndef CONFIG_BOOTLOADER_WDT_ENABLE
rtc_wdt_disable();
#endif
}
//Clear BSS. Please do not attempt to do any complex stuff (like early logging) before this.
@ -396,7 +399,6 @@ void start_cpu0_default(void)
#endif
//esp_cache_err_int_init();
esp_crosscore_int_init();
esp_ipc_init();
#ifndef CONFIG_FREERTOS_UNICORE
esp_dport_access_int_init();
#endif
@ -459,7 +461,7 @@ void start_cpu1_default(void)
}
#endif //!CONFIG_FREERTOS_UNICORE
#ifdef CONFIG_CXX_EXCEPTIONS
#ifdef CONFIG_COMPILER_CXX_EXCEPTIONS
size_t __cxx_eh_arena_size_get()
{
return CONFIG_CXX_EXCEPTIONS_EMG_POOL_SIZE;

View file

@ -18,6 +18,7 @@
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
/**
@ -41,7 +42,7 @@ void esp_spiram_init_cache();
/**
* @brief Memory test for SPI RAM. Should be called after SPI RAM is initialized and
* (in case of a dual-core system) the app CPU is online. This test overwrites the
* (in case of a dual-core system) the app CPU is online. This test overwrites the
* memory with crap, so do not call after e.g. the heap allocator has stored important
* stuff in SPI RAM.
*

View file

@ -1,58 +0,0 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __ESP_ATTR_H__
#define __ESP_ATTR_H__
#define ROMFN_ATTR
//Normally, the linker script will put all code and rodata in flash,
//and all variables in shared RAM. These macros can be used to redirect
//particular functions/variables to other memory regions.
// Forces code into IRAM instead of flash.
#define IRAM_ATTR __attribute__((section(".iram1")))
// Forces data into DRAM instead of flash
#define DRAM_ATTR __attribute__((section(".dram1")))
// Forces data to be 4 bytes aligned
#define WORD_ALIGNED_ATTR __attribute__((aligned(4)))
// Forces data to be placed to DMA-capable places
#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR
// Forces a string into DRAM instead of flash
// Use as ets_printf(DRAM_STR("Hello world!\n"));
#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;}))
// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst"
#define RTC_IRAM_ATTR __attribute__((section(".rtc.text")))
// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst"
// Any variable marked with this attribute will keep its value
// during a deep sleep / wake cycle.
#define RTC_DATA_ATTR __attribute__((section(".rtc.data")))
// Forces read-only data into RTC slow memory. See "docs/deep-sleep-stub.rst"
#define RTC_RODATA_ATTR __attribute__((section(".rtc.rodata")))
// Forces data into noinit section to avoid initialization after restart.
#define __NOINIT_ATTR __attribute__((section(".noinit")))
// Forces data into RTC slow memory of .noinit section.
// Any variable marked with this attribute will keep its value
// after restart or during a deep sleep / wake cycle.
#define RTC_NOINIT_ATTR __attribute__((section(".rtc_noinit")))
#endif /* __ESP_ATTR_H__ */

View file

@ -15,7 +15,7 @@
#ifndef __ESP_INTR_H__
#define __ESP_INTR_H__
#include "rom/ets_sys.h"
#include "esp32s2beta/rom/ets_sys.h"
#include "freertos/xtensa_api.h"
#ifdef __cplusplus

View file

@ -18,6 +18,7 @@
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "freertos/xtensa_api.h"
#ifdef __cplusplus
extern "C" {
@ -80,7 +81,10 @@ extern "C" {
// This is used to provide SystemView with positive IRQ IDs, otherwise sheduler events are not shown properly
#define ETS_INTERNAL_INTR_SOURCE_OFF (-ETS_INTERNAL_PROFILING_INTR_SOURCE)
typedef void (*intr_handler_t)(void *arg);
#define ESP_INTR_ENABLE(inum) xt_ints_on((1<<inum))
#define ESP_INTR_DISABLE(inum) xt_ints_off((1<<inum))
typedef void (*intr_handler_t)(void *arg);
typedef struct intr_handle_data_t intr_handle_data_t;
@ -88,7 +92,7 @@ typedef intr_handle_data_t* intr_handle_t ;
/**
* @brief Mark an interrupt as a shared interrupt
*
*
* This will mark a certain interrupt on the specified CPU as
* an interrupt that can be used to hook shared interrupt handlers
* to.
@ -105,7 +109,7 @@ esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_in_iram);
/**
* @brief Reserve an interrupt to be used outside of this framework
*
*
* This will mark a certain interrupt on the specified CPU as
* reserved, not to be allocated for any reason.
*
@ -137,7 +141,7 @@ esp_err_t esp_intr_reserve(int intno, int cpu);
* choice of interrupts that this routine can choose from. If this value
* is 0, it will default to allocating a non-shared interrupt of level
* 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
* from this function with the interrupt disabled.
* @param handler The interrupt handler. Must be NULL when an interrupt of level >3
* is requested, because these types of interrupts aren't C-callable.
@ -158,7 +162,7 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar
*
*
* This essentially does the same as esp_intr_alloc, but allows specifying a register and mask
* combo. For shared interrupts, the handler is only called if a read from the specified
* combo. For shared interrupts, the handler is only called if a read from the specified
* register, ANDed with the mask, returns non-zero. By passing an interrupt status register
* address and a fitting mask, this can be used to accelerate interrupt handling in the case
* a shared interrupt is triggered; by checking the interrupt statuses first, the code can
@ -171,7 +175,7 @@ esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *ar
* choice of interrupts that this routine can choose from. If this value
* is 0, it will default to allocating a non-shared interrupt of level
* 1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
* interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
* from this function with the interrupt disabled.
* @param intrstatusreg The address of an interrupt status register
* @param intrstatusmask A mask. If a read of address intrstatusreg has any of the bits
@ -197,9 +201,9 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
* Use an interrupt handle to disable the interrupt and release the resources
* associated with it.
*
* @note
* When the handler shares its source with other handlers, the interrupt status
* bits it's responsible for should be managed properly before freeing it. see
* @note
* When the handler shares its source with other handlers, the interrupt status
* bits it's responsible for should be managed properly before freeing it. see
* ``esp_intr_disable`` for more details.
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
@ -213,7 +217,7 @@ esp_err_t esp_intr_free(intr_handle_t handle);
/**
* @brief Get CPU number an interrupt is tied to
*
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return The core number where the interrupt is allocated
@ -222,7 +226,7 @@ int esp_intr_get_cpu(intr_handle_t handle);
/**
* @brief Get the allocated interrupt for a certain handle
*
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
*
* @return The interrupt number
@ -231,13 +235,13 @@ int esp_intr_get_intno(intr_handle_t handle);
/**
* @brief Disable the interrupt associated with the handle
*
* @note
*
* @note
* 1. For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the
* CPU the interrupt is allocated on. Other interrupts have no such restriction.
* 2. When several handlers sharing a same interrupt source, interrupt status bits, which are
* 2. When several handlers sharing a same interrupt source, interrupt status bits, which are
* handled in the handler to be disabled, should be masked before the disabling, or handled
* in other enabled interrupts properly. Miss of interrupt status handling will cause infinite
* in other enabled interrupts properly. Miss of interrupt status handling will cause infinite
* interrupt calls and finally system crash.
*
* @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus

View file

@ -24,11 +24,10 @@
#include "freertos/task.h"
#include <esp_types.h>
#include "esp_err.h"
//#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#include "esp_log.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "soc/soc.h"
#include <limits.h>
#include <assert.h>

View file

@ -1,253 +0,0 @@
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
/* RTC fast memory holds RTC wake stub code,
including from any source file named rtc_wake_stub*.c
*/
.rtc.text :
{
. = ALIGN(4);
*(.rtc.literal .rtc.text)
*rtc_wake_stub*.o(.literal .text .literal.* .text.*)
} > rtc_iram_seg
/* RTC slow memory holds RTC wake stub
data/rodata, including from any source file
named rtc_wake_stub*.c
*/
.rtc.data :
{
_rtc_data_start = ABSOLUTE(.);
*(.rtc.data)
*(.rtc.rodata)
*rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*)
_rtc_data_end = ABSOLUTE(.);
} > rtc_slow_seg
/* RTC bss, from any source file named rtc_wake_stub*.c */
.rtc.bss (NOLOAD) :
{
_rtc_bss_start = ABSOLUTE(.);
*rtc_wake_stub*.o(.bss .bss.*)
*rtc_wake_stub*.o(COMMON)
_rtc_bss_end = ABSOLUTE(.);
} > rtc_slow_seg
/* This section holds data that should not be initialized at power up
and will be retained during deep sleep. The section located in
RTC SLOW Memory area. User data marked with RTC_NOINIT_ATTR will be placed
into this section. See the file "esp_attr.h" for more information.
*/
.rtc_noinit (NOLOAD):
{
. = ALIGN(4);
_rtc_noinit_start = ABSOLUTE(.);
*(.rtc_noinit .rtc_noinit.*)
. = ALIGN(4) ;
_rtc_noinit_end = ABSOLUTE(.);
} > rtc_slow_seg
/* Send .iram0 code to iram */
.iram0.vectors :
{
/* Vectors go to IRAM */
_init_start = ABSOLUTE(.);
/* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */
. = 0x0;
KEEP(*(.WindowVectors.text));
. = 0x180;
KEEP(*(.Level2InterruptVector.text));
. = 0x1c0;
KEEP(*(.Level3InterruptVector.text));
. = 0x200;
KEEP(*(.Level4InterruptVector.text));
. = 0x240;
KEEP(*(.Level5InterruptVector.text));
. = 0x280;
KEEP(*(.DebugExceptionVector.text));
. = 0x2c0;
KEEP(*(.NMIExceptionVector.text));
. = 0x300;
KEEP(*(.KernelExceptionVector.text));
. = 0x340;
KEEP(*(.UserExceptionVector.text));
. = 0x3C0;
KEEP(*(.DoubleExceptionVector.text));
. = 0x400;
*(.*Vector.literal)
*(.UserEnter.literal);
*(.UserEnter.text);
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
_init_end = ABSOLUTE(.);
/* This goes here, not at top of linker script, so addr2line finds it last,
and uses it in preference to the first symbol in IRAM */
_iram_start = ABSOLUTE(0);
} > iram0_0_seg
.iram0.text :
{
/* Code marked as runnning out of IRAM */
_iram_text_start = ABSOLUTE(.);
*(.iram1 .iram1.*)
*libfreertos.a:(.literal .text .literal.* .text.*)
*libheap.a:multi_heap.o(.literal .text .literal.* .text.*)
*libheap.a:multi_heap_poisoning.o(.literal .text .literal.* .text.*)
*libesp32c.a:panic.o(.literal .text .literal.* .text.*)
*libesp32c.a:core_dump.o(.literal .text .literal.* .text.*)
*libapp_trace.a:(.literal .text .literal.* .text.*)
*libxtensa-debug-module.a:eri.o(.literal .text .literal.* .text.*)
*librtc.a:(.literal .text .literal.* .text.*)
*libsoc.a:(.literal .text .literal.* .text.*)
*libhal.a:(.literal .text .literal.* .text.*)
*libgcc.a:lib2funcs.o(.literal .text .literal.* .text.*)
*libspi_flash.a:spi_flash_rom_patch.o(.literal .text .literal.* .text.*)
*libgcov.a:(.literal .text .literal.* .text.*)
INCLUDE esp32.spiram.rom-functions-iram.ld
_iram_text_end = ABSOLUTE(.);
} > iram0_0_seg
.dram0.data :
{
_data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.sdata2)
*(.sdata2.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
*(.dram1 .dram1.*)
*libesp32c.a:panic.o(.rodata .rodata.*)
*libphy.a:(.rodata .rodata.*)
*libsoc.a:rtc_clk.o(.rodata .rodata.*)
*libapp_trace.a:(.rodata .rodata.*)
*libgcov.a:(.rodata .rodata.*)
*libheap.a:multi_heap.o(.rodata .rodata.*)
*libheap.a:multi_heap_poisoning.o(.rodata .rodata.*)
INCLUDE esp32.spiram.rom-functions-dram.ld
_data_end = ABSOLUTE(.);
. = ALIGN(4);
} > dram0_0_seg
/*This section holds data that should not be initialized at power up.
The section located in Internal SRAM memory region. The macro _NOINIT
can be used as attribute to place data into this section.
See the esp_attr.h file for more information.
*/
.noinit (NOLOAD):
{
. = ALIGN(4);
_noinit_start = ABSOLUTE(.);
*(.noinit .noinit.*)
. = ALIGN(4) ;
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.share.mem)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
/* The heap starts right after end of this section */
_heap_start = ABSOLUTE(.);
} > dram0_0_seg
.flash.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
*(.gnu.linkonce.r.*)
*(.rodata1)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table .gcc_except_table.*)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
. = (. + 3) & ~ 3;
__eh_frame = ABSOLUTE(.);
KEEP(*(.eh_frame))
. = (. + 7) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.o(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.o(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_thread_local_start = ABSOLUTE(.);
*(.tdata)
*(.tdata.*)
*(.tbss)
*(.tbss.*)
_thread_local_end = ABSOLUTE(.);
. = ALIGN(4);
} >drom0_0_seg
.flash.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
_text_end = ABSOLUTE(.);
_etext = .;
/* Similar to _iram_start, this symbol goes here so it is
resolved by addr2line in preference to the first symbol in
the flash.text segment.
*/
_flash_cache_start = ABSOLUTE(0);
} >iram0_2_seg
}

View file

@ -15,9 +15,9 @@ SECTIONS
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
_rtc_text_end = ABSOLUTE(.);
} > rtc_iram_seg
/*
This section is required to skip rtc.text area because rtc_iram_seg and
This section is required to skip rtc.text area because rtc_iram_seg and
rtc_data_seg are reflect the same address space on different buses.
*/
.rtc.dummy :
@ -28,8 +28,8 @@ SECTIONS
_rtc_dummy_end = ABSOLUTE(.);
} > rtc_data_seg
/* This section located in RTC FAST Memory area.
It holds data marked with RTC_FAST_ATTR attribute.
/* This section located in RTC FAST Memory area.
It holds data marked with RTC_FAST_ATTR attribute.
See the file "esp_attr.h" for more information.
*/
.rtc.force_fast :
@ -45,7 +45,7 @@ SECTIONS
data/rodata, including from any source file
named rtc_wake_stub*.c and the data marked with
RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
The memory location of the data is dependent on
The memory location of the data is dependent on
CONFIG_ESP32_RTCDATA_IN_FAST_MEM option.
*/
.rtc.data :
@ -70,11 +70,11 @@ SECTIONS
_rtc_bss_end = ABSOLUTE(.);
} > rtc_data_location
/* This section holds data that should not be initialized at power up
/* This section holds data that should not be initialized at power up
and will be retained during deep sleep.
User data marked with RTC_NOINIT_ATTR will be placed
into this section. See the file "esp_attr.h" for more information.
The memory location of the data is dependent on
into this section. See the file "esp_attr.h" for more information.
The memory location of the data is dependent on
CONFIG_ESP32_RTCDATA_IN_FAST_MEM option.
*/
.rtc_noinit (NOLOAD):
@ -86,8 +86,8 @@ SECTIONS
_rtc_noinit_end = ABSOLUTE(.);
} > rtc_data_location
/* This section located in RTC SLOW Memory area.
It holds data marked with RTC_SLOW_ATTR attribute.
/* This section located in RTC SLOW Memory area.
It holds data marked with RTC_SLOW_ATTR attribute.
See the file "esp_attr.h" for more information.
*/
.rtc.force_slow :
@ -100,17 +100,17 @@ SECTIONS
} > rtc_slow_seg
/* Get size of rtc slow data based on rtc_data_location alias */
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_slow_end - _rtc_data_start)
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_slow_end - _rtc_data_start)
: (_rtc_force_slow_end - _rtc_force_slow_start);
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_fast_end - _rtc_fast_start)
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
? (_rtc_force_fast_end - _rtc_fast_start)
: (_rtc_noinit_end - _rtc_fast_start);
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
"RTC_SLOW segment data does not fit.")
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
"RTC_FAST segment data does not fit.")
@ -203,7 +203,7 @@ SECTIONS
{
. = ALIGN(4);
_noinit_start = ABSOLUTE(.);
*(.noinit .noinit.*)
*(.noinit .noinit.*)
. = ALIGN(4) ;
_noinit_end = ABSOLUTE(.);
} > dram0_0_seg
@ -245,7 +245,7 @@ SECTIONS
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
"DRAM segment data does not fit.")
.flash.rodata :
{
_rodata_start = ABSOLUTE(.);

View file

@ -34,7 +34,7 @@
#include "esp_private/pm_impl.h"
#include "esp_private/pm_trace.h"
#include "esp_private/esp_timer_impl.h"
#include "esp32/pm.h"
#include "esp32s2beta/pm.h"
/* CCOMPARE update timeout, in CPU cycles. Any value above ~600 cycles will work
* for the purpose of detecting a deadlock.
@ -449,6 +449,24 @@ void esp_pm_impl_idle_hook()
ESP_PM_TRACE_ENTER(IDLE, core_id);
}
void esp_pm_impl_waiti()
{
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
int core_id = xPortGetCoreID();
if (s_skipped_light_sleep[core_id]) {
asm("waiti 0");
/* Interrupt took the CPU out of waiti and s_rtos_lock_handle[core_id]
* is now taken. However since we are back to idle task, we can release
* the lock so that vApplicationSleep can attempt to enter light sleep.
*/
esp_pm_impl_idle_hook();
s_skipped_light_sleep[core_id] = false;
}
#else
asm("waiti 0");
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE
}
void IRAM_ATTR esp_pm_impl_isr_hook()
{
int core_id = xPortGetCoreID();

View file

@ -25,6 +25,7 @@
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/rom/rtc.h"
#include "esp32s2beta/rom/uart.h"
#include "esp32s2beta/rom/ets_sys.h"
#include "soc/cpu.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"

View file

@ -365,3 +365,4 @@ void esp_chip_info(esp_chip_info_t* out_info)
out_info->features = CHIP_FEATURE_WIFI_BGN;
// FIXME: other features?
}

View file

@ -179,7 +179,7 @@ esp_err_t esp_task_wdt_init(uint32_t timeout, bool panic)
twdt_config->panic = panic;
//Register Interrupt and ISR
ESP_ERROR_CHECK(esp_intr_alloc(ETS_TG0_WDT_LEVEL_INTR_SOURCE, 0, task_wdt_isr, NULL, &twdt_config->intr_handle))
ESP_ERROR_CHECK(esp_intr_alloc(ETS_TG0_WDT_LEVEL_INTR_SOURCE, 0, task_wdt_isr, NULL, &twdt_config->intr_handle));
//Configure hardware timer
periph_module_enable(PERIPH_TIMG0_MODULE);
@ -227,7 +227,7 @@ esp_err_t esp_task_wdt_deinit()
TIMERG0.wdt_config0.en=0; //Disable timer
TIMERG0.wdt_wprotect=0; //Enable write protection
ESP_ERROR_CHECK(esp_intr_free(twdt_config->intr_handle)) //Unregister interrupt
ESP_ERROR_CHECK(esp_intr_free(twdt_config->intr_handle)); //Unregister interrupt
free(twdt_config); //Free twdt_config
twdt_config = NULL;
portEXIT_CRITICAL(&twdt_spinlock);
@ -269,7 +269,7 @@ esp_err_t esp_task_wdt_add(TaskHandle_t handle)
//If idle task, register the idle hook callback to appropriate core
for(int i = 0; i < portNUM_PROCESSORS; i++){
if(handle == xTaskGetIdleTaskHandleForCPU(i)){
ESP_ERROR_CHECK(esp_register_freertos_idle_hook_for_cpu(idle_hook_cb, i))
ESP_ERROR_CHECK(esp_register_freertos_idle_hook_for_cpu(idle_hook_cb, i));
break;
}
}

View file

@ -1,3 +1,6 @@
if(IDF_TARGET STREQUAL "esp32s2beta")
return()
endif()
set(COMPONENT_SRCS "esp_adc_cal.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")

View file

@ -16,9 +16,12 @@
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
// Include SoC-specific definitions. Only ESP32 supported for now.
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/pm.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/pm.h"
#endif
#ifdef __cplusplus
extern "C" {

View file

@ -24,7 +24,6 @@
#include "esp_log.h"
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "esp32/rom/ets_sys.h"
#include "soc/frc_timer_reg.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -33,6 +32,11 @@
#include "sdkconfig.h"
#include "esp_timer.h"
#include "esp_private/esp_timer_impl.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
/* We abuse 'timer_arg' field of ETSTimer structure to hold a pointer to esp_timer */
#define ESP_TIMER(p_ets_timer) ((esp_timer_handle_t) (p_ets_timer)->timer_arg)

View file

@ -8,7 +8,7 @@ set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_PRIV_INCLUDEDIRS "private_include")
set(COMPONENT_REQUIRES log tcpip_adapter)
if(CONFIG_IDF_TARGET_ESP32)
if(IDF_TARGET STREQUAL "esp32")
set(COMPONENT_PRIV_REQUIRES ethernet)
endif()

View file

@ -17,7 +17,9 @@
#include "esp_event_legacy.h"
#include "esp_wifi_types.h"
#include "tcpip_adapter.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_eth.h"
#endif
/**
* The purpose of this file is to provide an "esp_event_send_to_default_loop"
@ -87,7 +89,7 @@ esp_err_t esp_event_send_to_default_loop(system_event_t *event)
HANDLE_SYS_EVENT_ARG(WIFI, AP_STACONNECTED, sta_connected);
HANDLE_SYS_EVENT_ARG(WIFI, AP_STADISCONNECTED, sta_disconnected);
HANDLE_SYS_EVENT_ARG(WIFI, AP_PROBEREQRECVED, ap_probereqrecved);
#if CONFIG_IDF_TARGET_ESP32
/* Ethernet events */
/* Some extra defines to fit the old naming scheme... */
#define ETH_EVENT_ETH_START ETHERNET_EVENT_START
@ -99,7 +101,7 @@ esp_err_t esp_event_send_to_default_loop(system_event_t *event)
HANDLE_SYS_EVENT(ETH, ETH_STOP);
HANDLE_SYS_EVENT(ETH, ETH_CONNECTED);
HANDLE_SYS_EVENT(ETH, ETH_DISCONNECTED);
#endif
/* IP events */
HANDLE_SYS_EVENT_ARG(IP, STA_GOT_IP, got_ip);
HANDLE_SYS_EVENT_ARG(IP, ETH_GOT_IP, got_ip);
@ -119,9 +121,9 @@ typedef struct {
int err;
const char *reason;
} wifi_reason_t;
static const wifi_reason_t wifi_reason[] =
{
{
{0, "other reason"},
{WIFI_REASON_UNSPECIFIED, "unspecified"},
{WIFI_REASON_AUTH_EXPIRE, "auth expire"},
@ -150,9 +152,9 @@ static const wifi_reason_t wifi_reason[] =
{WIFI_REASON_UNSUPP_RSN_IE_VERSION, "unsupported RSN IE version"},
{WIFI_REASON_INVALID_RSN_IE_CAP, "invalid RSN IE capability"},
{WIFI_REASON_802_1X_AUTH_FAILED, "802.1x auth failed"},
{WIFI_REASON_CIPHER_SUITE_REJECTED, "cipher suite rejected"}
{WIFI_REASON_CIPHER_SUITE_REJECTED, "cipher suite rejected"}
};
static const char* wifi_disconnect_reason_to_str(int err)
{
for (int i=0; i< sizeof(wifi_reason)/sizeof(wifi_reason[0]); i++){
@ -277,6 +279,7 @@ static void esp_system_event_debug(const system_event_t* event)
IP6_ADDR_BLOCK8(addr));
break;
}
#if CONFIG_IDF_TARGET_ESP32
case SYSTEM_EVENT_ETH_START: {
ESP_LOGD(TAG, "SYSTEM_EVENT_ETH_START");
break;
@ -301,6 +304,7 @@ static void esp_system_event_debug(const system_event_t* event)
IP2STR(&got_ip->ip_info.gw));
break;
}
#endif
default: {
ESP_LOGW(TAG, "unexpected system event %d!", event->event_id);
break;

View file

@ -23,7 +23,7 @@ else()
register_component()
if (CONFIG_IDF_TARGET_ESP32)
if (IDF_TARGET STREQUAL "esp32")
set(scripts
"esp32/ld/esp32.rom.ld"
"esp32/ld/esp32.rom.libgcc.ld"
@ -48,14 +48,12 @@ else()
target_linker_script(${COMPONENT_LIB} "esp32/ld/esp32.rom.spiflash.ld")
endif()
elseif(CONFIG_IDF_TARGET_ESP32S2BETA)
target_linker_script(${COMPONENT_LIB}
"esp32s2beta/ld/esp32s2beta.rom.ld"
"esp32s2beta/ld/esp32s2beta.rom.nanofmt.ld"
"esp32s2beta/ld/esp32s2beta.rom.spiflash.ld"
"esp32s2beta/ld/esp32s2beta.rom.spiram_incompatible_fns.ld"
"esp32s2beta/ld/esp32s2beta.spiram.rom-functions-dram.ld"
"esp32s2beta/ld/esp32s2beta.spiram.rom-functions-iram.ld")
elseif(IDF_TARGET STREQUAL "esp32s2beta")
set(scripts "esp32s2beta/ld/esp32s2beta.rom.ld"
"esp32s2beta/ld/esp32s2beta.rom.nanofmt.ld"
"esp32s2beta/ld/esp32s2beta.rom.spiflash.ld"
"esp32s2beta/ld/esp32s2beta.rom.spiram_incompatible_fns.ld")
target_linker_script(${COMPONENT_LIB} "${scripts}")
endif()
endif()

View file

@ -21,6 +21,7 @@
#include <stdint.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#ifdef __cplusplus
extern "C" {

View file

@ -19,8 +19,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_AES_H_
#define _ROM_AES_H_
#pragma once
#include <stdint.h>
#include <stdbool.h>
@ -61,5 +60,3 @@ void ets_aes_block(const void *input, void *output);
#ifdef __cplusplus
}
#endif
#endif /* _ROM_AES_H_ */

View file

@ -12,8 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef _ROM_ETS_SYS_H_
#define _ROM_ETS_SYS_H_
#pragma once
#include <stdint.h>
#include <stdbool.h>
@ -608,5 +607,3 @@ typedef enum {
#ifdef __cplusplus
}
#endif
#endif /* _ROM_ETS_SYS_H_ */

View file

@ -21,6 +21,7 @@
#include <stdint.h>
#include "soc/soc.h"
#include "soc/rtc_cntl_reg.h"
#ifdef __cplusplus
extern "C" {
@ -174,10 +175,10 @@ void set_rtc_memory_crc(void);
/**
* @brief Fetch entry from RTC memory and RTC STORE reg
*
* @param uint32_t * entry_addr : the address to save entry
* @param uint32_t * entry_addr : the address to save entry
*
* @param RESET_REASON reset_reason : reset reason this time
*
*
* @return None
*/
void rtc_boot_control(uint32_t * entry_addr, RESET_REASON reset_reason);

View file

@ -22,7 +22,9 @@ if(NOT CONFIG_ESP32_NO_BLOBS)
set(blobs coexist core espnow mesh net80211 phy pp rtc smartconfig wpa2 wpa wps)
foreach(blob ${blobs})
add_library(${blob} STATIC IMPORTED)
set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib_${IDF_TARGET}/lib${blob}.a)
# set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib_${IDF_TARGET}/lib${blob}.a)
# ToDo: add lib_esp32s2beta in esp_wifi component
set_property(TARGET ${blob} PROPERTY IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/lib_esp32/lib${blob}.a)
target_link_libraries(${COMPONENT_LIB} ${blob})
foreach(_blob ${blobs})

View file

@ -15,8 +15,12 @@
#include "soc/uart_periph.h"
#include "soc/gpio_periph.h"
#include "driver/gpio.h"
#include "esp32/clk.h"
#include "esp_core_dump_priv.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#endif
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_uart";

@ -1 +1 @@
Subproject commit b4c418a5d90c94863b44c8661b9332cf229b08b7
Subproject commit cd386661033d25521b1312cf7fa4699ff4719f77

View file

@ -50,7 +50,7 @@ if(CONFIG_SECURE_BOOT_ENABLED AND
endif()
if(NOT BOOTLOADER_BUILD)
set(ESPTOOLPY_ELF2IMAGE_OPTIONS --elf-sha256-offset 0xb0)
# set(ESPTOOLPY_ELF2IMAGE_OPTIONS --elf-sha256-offset 0xb0)
endif()
if(CONFIG_ESPTOOLPY_FLASHSIZE_DETECT)

View file

@ -1,12 +1,14 @@
set(COMPONENT_SRCS "emac_dev.c"
"emac_main.c"
"eth_phy/phy_common.c"
"eth_phy/phy_lan8720.c"
"eth_phy/phy_tlk110.c"
"eth_phy/phy_ip101.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
if(IDF_TARGET STREQUAL "esp32")
set(COMPONENT_SRCS "emac_dev.c"
"emac_main.c"
"eth_phy/phy_common.c"
"eth_phy/phy_lan8720.c"
"eth_phy/phy_tlk110.c"
"eth_phy/phy_ip101.c")
set(COMPONENT_ADD_INCLUDEDIRS "include")
set(COMPONENT_REQUIRES)
set(COMPONENT_PRIV_REQUIRES tcpip_adapter esp_event soc)
set(COMPONENT_REQUIRES)
set(COMPONENT_PRIV_REQUIRES tcpip_adapter esp_event soc)
register_component()
register_component()
endif()

View file

@ -45,10 +45,10 @@
#include "port.h"
/* ----------------------- Modbus includes ----------------------------------*/
#include "sdkconfig.h"
#include "mb.h"
#include "mbport.h"
#include "driver/timer.h"
#include "sdkconfig.h"
#include "port_serial_slave.h"
#ifdef CONFIG_FMB_TIMER_PORT_ENABLED
@ -71,9 +71,17 @@ static void IRAM_ATTR vTimerGroupIsr(void *param)
{
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
#if CONFIG_IDF_TARGET_ESP32
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st_timers.val;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st.val;
#endif
if (intr_status & BIT(usTimerIndex)) {
#if CONFIG_IDF_TARGET_ESP32
MB_TG[usTimerGroupIndex]->int_clr_timers.val |= BIT(usTimerIndex);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
MB_TG[usTimerGroupIndex]->int_clr.val |= BIT(usTimerIndex);
#endif
(void)pxMBPortCBTimerExpired(); // Timer callback function
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].config.alarm_en = TIMER_ALARM_EN;
}

View file

@ -40,6 +40,7 @@
#include "mb_m.h"
#include "mbport.h"
#include "port_serial_master.h"
#include "sdkconfig.h"
#define MB_US50_FREQ (20000) // 20kHz 1/20000 = 50mks
#define MB_TICK_TIME_US (50) // 50uS = one tick for timer
@ -69,10 +70,22 @@ static void IRAM_ATTR vTimerGroupIsr(void *param)
{
// Retrieve the interrupt status and the counter value
// from the timer that reported the interrupt
#if CONFIG_IDF_TARGET_ESP32
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st_timers.val;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
uint32_t intr_status = MB_TG[usTimerGroupIndex]->int_st.val;
#endif
if (intr_status & BIT(usTimerIndex)) {
#if CONFIG_IDF_TARGET_ESP32
MB_TG[usTimerGroupIndex]->int_clr_timers.val |= BIT(usTimerIndex);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
MB_TG[usTimerGroupIndex]->int_clr.val |= BIT(usTimerIndex);
#endif
#if CONFIG_IDF_TARGET_ESP32
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].update = 1;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].update.update = 1;
#endif
(void)pxMBMasterPortCBTimerExpired(); // Timer expired callback function
// Enable alarm
MB_TG[usTimerGroupIndex]->hw_timer[usTimerIndex].config.alarm_en = TIMER_ALARM_EN;

View file

@ -76,7 +76,7 @@
/* ESP31 and ESP32 are dualcore processors. */
#ifndef CONFIG_FREERTOS_UNICORE
#define portNUM_PROCESSORS 2
#else
#else
#define portNUM_PROCESSORS 1
#endif
@ -117,7 +117,11 @@ int xt_clock_freq(void) __attribute__((deprecated));
/* configASSERT behaviour */
#ifndef __ASSEMBLER__
#include <stdlib.h> /* for abort() */
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#if defined(CONFIG_FREERTOS_ASSERT_DISABLE)
#define configASSERT(a) /* assertions disabled */
@ -155,7 +159,7 @@ int xt_clock_freq(void) __attribute__((deprecated));
* memory.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1

View file

@ -349,12 +349,14 @@ static inline unsigned portENTER_CRITICAL_NESTED() {
* ESP32 (portMUX assertions would fail).
*/
static inline void uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
#ifndef CONFIG_FREERTOS_UNICORE
__asm__ __volatile__ (
"WSR %2,SCOMPARE1 \n"
"S32C1I %0, %1, 0 \n"
:"=r"(*set)
:"r"(addr), "r"(compare), "0"(*set)
);
#endif
}

View file

@ -97,7 +97,6 @@
#include "xtensa_rtos.h"
#include "esp32/rom/ets_sys.h"
#include "soc/cpu.h"
#include "FreeRTOS.h"
@ -109,6 +108,12 @@
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
/* Defined in portasm.h */
extern void _frxt_tick_timer_init(void);

View file

@ -78,8 +78,12 @@
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when

View file

@ -70,13 +70,17 @@
/* Standard includes. */
#include <stdlib.h>
#include <string.h>
#include "sdkconfig.h"
/* Defining MPU_WRAPPERS_INCLUDED_FROM_API_FILE prevents task.h from redefining
all the API functions to use the MPU wrappers. That should only be done when
task.h is included from an application file. */
#define MPU_WRAPPERS_INCLUDED_FROM_API_FILE
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#include "esp_newlib.h"
#include "esp_debug_helpers.h"

View file

@ -30,11 +30,16 @@ that are implemented in C.
#ifdef XT_BOARD
#include <xtensa/xtbsp.h>
#include "xtensa/xtbsp.h"
#endif
#include "xtensa_rtos.h"
#include "esp32/clk.h"
#include "xtensa_rtos.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#endif
#ifdef XT_RTOS_TIMER_INT

View file

@ -33,8 +33,12 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "freertos/portable.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#if XCHAL_HAVE_EXCEPTIONS

View file

@ -16,7 +16,12 @@
#ifdef ESP_PLATFORM
#include <freertos/FreeRTOS.h>
#include <esp32/rom/ets_sys.h>
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#include <assert.h>
/* Because malloc/free can happen inside an ISR context,

View file

@ -18,7 +18,11 @@
#include <stdint.h>
#include <stdarg.h>
#include "sdkconfig.h"
#include <esp32/rom/ets_sys.h>
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#endif
#ifdef __cplusplus
extern "C" {
@ -154,15 +158,15 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, .
/**
* @brief Dump a buffer to the log at specified level.
*
*
* The dump log shows just like the one below:
*
*
* W (195) log_example: 0x3ffb4280 45 53 50 33 32 20 69 73 20 67 72 65 61 74 2c 20 |ESP32 is great, |
* W (195) log_example: 0x3ffb4290 77 6f 72 6b 69 6e 67 20 61 6c 6f 6e 67 20 77 69 |working along wi|
* W (205) log_example: 0x3ffb42a0 74 68 20 74 68 65 20 49 44 46 2e 00 |th the IDF..|
*
*
* It is highly recommend to use terminals with over 102 text width.
*
*
* @param tag description tag
* @param buffer Pointer to the buffer array
* @param buff_len length of buffer in bytes
@ -287,7 +291,7 @@ void esp_log_write(esp_log_level_t level, const char* tag, const char* format, .
#endif // BOOTLOADER_BUILD
/** runtime macro to output logs at a specified level.
*
*
* @param tag tag of the log, which can be used to change the log level by ``esp_log_level_set`` at runtime.
* @param level level of the output log.
* @param format format of the output log. see ``printf``

View file

@ -1,3 +1,5 @@
idf_build_get_property(idf_target IDF_TARGET)
set(COMPONENT_ADD_INCLUDEDIRS "port/include" "mbedtls/include")
set(COMPONENT_SRCS "mbedtls.c")
set(COMPONENT_REQUIRES lwip)
@ -79,16 +81,16 @@ set_property(TARGET mbedtls PROPERTY SOURCES ${src_tls})
set(mbedtls_targets mbedtls mbedcrypto mbedx509)
# Add port files to mbedtls targets
target_sources(mbedtls PRIVATE "${COMPONENT_DIR}/port/esp_bignum.c"
"${COMPONENT_DIR}/port/esp_hardware.c"
target_sources(mbedtls PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c"
"${COMPONENT_PATH}/port/esp_sha.c"
"${COMPONENT_DIR}/port/esp_sha1.c"
"${COMPONENT_DIR}/port/esp_sha256.c"
"${COMPONENT_DIR}/port/esp_sha512.c"
"${COMPONENT_DIR}/port/mbedtls_debug.c"
"${COMPONENT_DIR}/port/net_sockets.c"
"${COMPONENT_DIR}/port/esp32/aes.c"
"${COMPONENT_DIR}/port/esp32/sha.c")
"${COMPONENT_DIR}/port/${idf_target}/aes.c"
"${COMPONENT_DIR}/port/${idf_target}/sha.c"
"${COMPONENT_DIR}/port/${idf_target}/esp_bignum.c")
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_mem.c")
foreach(target ${mbedtls_targets})
@ -101,4 +103,4 @@ target_link_libraries(${COMPONENT_LIB} ${mbedtls_targets})
# Catch usage of deprecated mbedTLS functions when building tests
if(mbedtls_test IN_LIST BUILD_TEST_COMPONENTS)
add_definitions(-DMBEDTLS_DEPRECATED_WARNING)
endif()
endif()

View file

@ -4,7 +4,7 @@
COMPONENT_ADD_INCLUDEDIRS := port/include mbedtls/include
COMPONENT_SRCDIRS := mbedtls/library port port/esp32
COMPONENT_SRCDIRS := mbedtls/library port port/$(IDF_TARGET)
COMPONENT_OBJEXCLUDE := mbedtls/library/net_sockets.o

View file

@ -27,7 +27,7 @@
*/
#include <string.h>
#include "mbedtls/aes.h"
#include "hwcrypto/aes.h"
#include "esp32s2beta/aes.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
#include <sys/lock.h>

View file

@ -0,0 +1,613 @@
/**
* \brief Multi-precision integer library, ESP32C hardware accelerated parts
*
* based on mbedTLS implementation
*
* 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.
*
*/
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <limits.h>
#include <assert.h>
#include <stdlib.h>
#include <sys/param.h>
#include "mbedtls/bignum.h"
#include "esp32s2beta/rom/bigint.h"
#include "soc/hwcrypto_reg.h"
#include "esp_system.h"
#include "esp_log.h"
#include "esp_intr.h"
#include "esp_intr_alloc.h"
#include "esp_attr.h"
#include "soc/dport_reg.h"
#include "soc/periph_defs.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
static const __attribute__((unused)) char *TAG = "bignum";
#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */
#define biL (ciL << 3) /* bits in limb */
#if defined(CONFIG_MBEDTLS_MPI_USE_INTERRUPT)
static SemaphoreHandle_t op_complete_sem;
static IRAM_ATTR void rsa_complete_isr(void *arg)
{
BaseType_t higher_woken;
DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
if (higher_woken) {
portYIELD_FROM_ISR();
}
}
static void rsa_isr_initialise()
{
if (op_complete_sem == NULL) {
op_complete_sem = xSemaphoreCreateBinary();
esp_intr_alloc(ETS_RSA_INTR_SOURCE, 0, rsa_complete_isr, NULL, NULL);
}
}
#endif /* CONFIG_MBEDTLS_MPI_USE_INTERRUPT */
static _lock_t mpi_lock;
void esp_mpi_acquire_hardware( void )
{
/* newlib locks lazy initialize on ESP-IDF */
_lock_acquire(&mpi_lock);
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_CLK_EN_RSA);
/* also clear reset on digital signature & secure boot, otherwise RSA is held in reset */
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_RST_EN_RSA
| DPORT_RST_EN_DIGITAL_SIGNATURE
| DPORT_RST_EN_SECURE_BOOT);
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_MEM_PD);
while(DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) {
}
// Note: from enabling RSA clock to here takes about 1.3us
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
rsa_isr_initialise();
#endif
}
void esp_mpi_release_hardware( void )
{
DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
/* don't reset digital signature unit, as this resets AES also */
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA);
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
_lock_release(&mpi_lock);
}
/* Return the number of words actually used to represent an mpi
number.
*/
static size_t mpi_words(const mbedtls_mpi *mpi)
{
for (size_t i = mpi->n; i > 0; i--) {
if (mpi->p[i - 1] != 0) {
return i;
}
}
return 0;
}
/* Copy mbedTLS MPI bignum 'mpi' to hardware memory block at 'mem_base'.
If num_words is higher than the number of words in the bignum then
these additional words will be zeroed in the memory buffer.
As this function only writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START()
is required.
*/
static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words)
{
uint32_t *pbase = (uint32_t *)mem_base;
uint32_t copy_words = num_words < mpi->n ? num_words : mpi->n;
/* Copy MPI data to memory block registers */
for (int i = 0; i < copy_words; i++) {
pbase[i] = mpi->p[i];
}
/* Zero any remaining memory block data */
for (int i = copy_words; i < num_words; i++) {
pbase[i] = 0;
}
/* Note: not executing memw here, can do it before we start a bignum operation */
}
/* Read mbedTLS MPI bignum back from hardware memory block.
Reads num_words words from block.
Can return a failure result if fails to grow the MPI result.
Cannot be called inside DPORT_STALL_OTHER_CPU_START() (as may allocate memory).
*/
static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words)
{
int ret = 0;
MBEDTLS_MPI_CHK( mbedtls_mpi_grow(x, num_words) );
/* Copy data from memory block registers */
esp_dport_access_read_buffer(x->p, mem_base, num_words);
/* Zero any remaining limbs in the bignum, if the buffer is bigger
than num_words */
for(size_t i = num_words; i < x->n; i++) {
x->p[i] = 0;
}
asm volatile ("memw");
cleanup:
return ret;
}
/**
*
* There is a need for the value of integer N' such that B^-1(B-1)-N^-1N'=1,
* where B^-1(B-1) mod N=1. Actually, only the least significant part of
* N' is needed, hence the definition N0'=N' mod b. We reproduce below the
* simple algorithm from an article by Dusse and Kaliski to efficiently
* find N0' from N0 and b
*/
static mbedtls_mpi_uint modular_inverse(const mbedtls_mpi *M)
{
int i;
uint64_t t = 1;
uint64_t two_2_i_minus_1 = 2; /* 2^(i-1) */
uint64_t two_2_i = 4; /* 2^i */
uint64_t N = M->p[0];
for (i = 2; i <= 32; i++) {
if ((mbedtls_mpi_uint) N * t % two_2_i >= two_2_i_minus_1) {
t += two_2_i_minus_1;
}
two_2_i_minus_1 <<= 1;
two_2_i <<= 1;
}
return (mbedtls_mpi_uint)(UINT32_MAX - t + 1);
}
/* Calculate Rinv = RR^2 mod M, where:
*
* R = b^n where b = 2^32, n=num_words,
* R = 2^N (where N=num_bits)
* RR = R^2 = 2^(2*N) (where N=num_bits=num_words*32)
*
* This calculation is computationally expensive (mbedtls_mpi_mod_mpi)
* so caller should cache the result where possible.
*
* DO NOT call this function while holding esp_mpi_acquire_hardware().
*
*/
static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words)
{
int ret;
size_t num_bits = num_words * 32;
mbedtls_mpi RR;
mbedtls_mpi_init(&RR);
MBEDTLS_MPI_CHK(mbedtls_mpi_set_bit(&RR, num_bits * 2, 1));
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(Rinv, &RR, M));
cleanup:
mbedtls_mpi_free(&RR);
return ret;
}
/* Begin an RSA operation. op_reg specifies which 'START' register
to write to.
Because the only DPORT operations here are writes,
does not need protecting via DPORT_STALL_OTHER_CPU_START();
*/
static inline void start_op(uint32_t op_reg)
{
/* Clear interrupt status */
DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
/* Note: above REG_WRITE includes a memw, so we know any writes
to the memory blocks are also complete. */
DPORT_REG_WRITE(op_reg, 1);
}
/* Wait for an RSA operation to complete.
This should NOT be called inside a DPORT_STALL_OTHER_CPU_START(), as it will stall the other CPU for an unacceptably long
period (and - depending on config - may require interrupts enabled).
*/
static inline void wait_op_complete(uint32_t op_reg)
{
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
ESP_LOGE(TAG, "Timed out waiting for RSA operation (op_reg 0x%x int_reg 0x%x)",
op_reg, DPORT_REG_READ(RSA_QUERY_INTERRUPT_REG));
abort(); /* indicates a fundamental problem with driver */
}
#else
while(DPORT_REG_READ(RSA_QUERY_INTERRUPT_REG) != 1)
{ }
/* clear the interrupt */
DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1);
#endif
}
/* Z = (X * Y) mod M
Not an mbedTLS function
*/
int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M)
{
int ret;
size_t m_words = mpi_words(M);
mbedtls_mpi Rinv;
mbedtls_mpi_uint Mprime;
size_t num_words = MAX(MAX(m_words, mpi_words(X)), mpi_words(Y));
if (num_words * 32 > 4096) {
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
}
/* Calculate and load the first stage montgomery multiplication */
mbedtls_mpi_init(&Rinv);
MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, m_words));
Mprime = modular_inverse(M);
esp_mpi_acquire_hardware();
DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words - 1));
DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime);
/* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */
mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words);
/* Execute first stage montgomery multiplication */
start_op(RSA_MOD_MULT_START_REG);
wait_op_complete(RSA_MOD_MULT_START_REG);
mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, m_words);
esp_mpi_release_hardware();
cleanup:
mbedtls_mpi_free(&Rinv);
return ret;
}
#if defined(MBEDTLS_MPI_EXP_MOD_ALT)
/*
* Sliding-window exponentiation: Z = X^Y mod M (HAC 14.85)
*
* _Rinv is optional pre-calculated version of Rinv (via calculate_rinv()).
*
* (See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
*
*/
int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, mbedtls_mpi* _Rinv )
{
int ret = 0;
size_t x_words = mpi_words(X);
size_t y_words = mpi_words(Y);
size_t m_words = mpi_words(M);
size_t num_words;
mbedtls_mpi Rinv_new; /* used if _Rinv == NULL */
mbedtls_mpi *Rinv; /* points to _Rinv (if not NULL) othwerwise &RR_new */
mbedtls_mpi_uint Mprime;
/* "all numbers must be the same length", so choose longest number
as cardinal length of operation...
*/
num_words = MAX(m_words, MAX(x_words, y_words));
if (num_words * 32 > 4096) {
return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE;
}
/* Determine RR pointer, either _RR for cached value
or local RR_new */
if (_Rinv == NULL) {
mbedtls_mpi_init(&Rinv_new);
Rinv = &Rinv_new;
} else {
Rinv = _Rinv;
}
if (Rinv->p == NULL) {
MBEDTLS_MPI_CHK(calculate_rinv(Rinv, M, num_words));
}
Mprime = modular_inverse(M);
esp_mpi_acquire_hardware();
DPORT_REG_WRITE(RSA_LENGTH_REG, num_words - 1);
/* Load M, X, Rinv, M-prime (M-prime is mod 2^32) */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words);
mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
DPORT_REG_WRITE(RSA_CONSTANT_TIME_DISABLE_REG, 1);
DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 1);
DPORT_REG_WRITE(RSA_SEARCH_POS_REG, (y_words * 32) - 1);
start_op(RSA_MODEXP_START_REG);
wait_op_complete(RSA_MODEXP_START_REG);
DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 0);
DPORT_REG_WRITE(RSA_SEARCH_POS_REG, (m_words * 32) - 1);
ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, m_words);
esp_mpi_release_hardware();
cleanup:
if (_Rinv == NULL) {
mbedtls_mpi_free(&Rinv_new);
}
return ret;
}
#endif /* MBEDTLS_MPI_EXP_MOD_ALT */
#if defined(MBEDTLS_MPI_MUL_MPI_ALT) /* MBEDTLS_MPI_MUL_MPI_ALT */
static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words);
static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t Y_bits, size_t words_result);
/* Z = X * Y */
int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y )
{
int ret = 0;
size_t bits_x, bits_y, words_x, words_y, words_mult, words_z;
/* Count words needed for X & Y in hardware */
bits_x = mbedtls_mpi_bitlen(X);
bits_y = mbedtls_mpi_bitlen(Y);
words_x = (bits_x + 7) / 8;
words_y = (bits_y + 7) / 8;
/* Short-circuit eval if either argument is 0 or 1.
This is needed as the mpi modular division
argument will sometimes call in here when one
argument is too large for the hardware unit, but the other
argument is zero or one.
This leaks some timing information, although overall there is a
lot less timing variation than a software MPI approach.
*/
if (bits_x == 0 || bits_y == 0) {
mbedtls_mpi_lset(Z, 0);
return 0;
}
if (bits_x == 1) {
ret = mbedtls_mpi_copy(Z, Y);
Z->s *= X->s;
return ret;
}
if (bits_y == 1) {
ret = mbedtls_mpi_copy(Z, X);
Z->s *= Y->s;
return ret;
}
words_mult = (words_x > words_y ? words_x : words_y);
/* Result Z has to have room for double the larger factor */
words_z = words_mult * 2;
/* If either factor is over 2048 bits, we can't use the standard hardware multiplier
(it assumes result is double longest factor, and result is max 4096 bits.)
However, we can fail over to mod_mult for up to 4096 bits of result (modulo
multiplication doesn't have the same restriction, so result is simply the
number of bits in X plus number of bits in in Y.)
*/
if (words_mult * 32 > 2048) {
/* Calculate new length of Z */
words_z = (bits_x + bits_y + 31) / 32;
if (words_z * 32 <= 4096) {
/* Note: it's possible to use mpi_mult_mpi_overlong
for this case as well, but it's very slightly
slower and requires a memory allocation.
*/
return mpi_mult_mpi_failover_mod_mult(Z, X, Y, words_z);
} else {
/* Still too long for the hardware unit... */
if(bits_y > bits_x) {
return mpi_mult_mpi_overlong(Z, X, Y, bits_y, words_z);
} else {
return mpi_mult_mpi_overlong(Z, Y, X, bits_x, words_z);
}
}
}
/* Otherwise, we can use the (faster) multiply hardware unit */
esp_mpi_acquire_hardware();
/* Copy X (right-extended) & Y (left-extended) to memory block */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, words_mult);
mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + words_mult * 4, Y, words_mult);
/* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block.
This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
*/
DPORT_REG_WRITE(RSA_M_DASH_REG, 0);
DPORT_REG_WRITE(RSA_LENGTH_REG, (words_z - 1));
start_op(RSA_MULT_START_REG);
wait_op_complete(RSA_MULT_START_REG);
/* Read back the result */
ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, words_z);
Z->s = X->s * Y->s;
esp_mpi_release_hardware();
return ret;
}
/* Special-case of mbedtls_mpi_mult_mpi(), where we use hardware montgomery mod
multiplication to calculate an mbedtls_mpi_mult_mpi result where either
A or B are >2048 bits so can't use the standard multiplication method.
Result (A bits + B bits) must still be less than 4096 bits.
This case is simpler than the general case modulo multiply of
esp_mpi_mul_mpi_mod() because we can control the other arguments:
* Modulus is chosen with M=(2^num_bits - 1) (ie M=R-1), so output
isn't actually modulo anything.
* Mprime and Rinv are therefore predictable as follows:
Mprime = 1
Rinv = 1
(See RSA Accelerator section in Technical Reference for more about Mprime, Rinv)
*/
static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
{
int ret = 0;
/* Load coefficients to hardware */
esp_mpi_acquire_hardware();
/* M = 2^num_words - 1, so block is entirely FF */
for(int i = 0; i < num_words; i++) {
DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
}
/* Mprime = 1 */
DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
DPORT_REG_WRITE(RSA_LENGTH_REG, num_words -1);
/* Load X & Y */
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words);
/* Rinv = 1 */
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
for(int i = 1; i < num_words; i++) {
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
}
start_op(RSA_MOD_MULT_START_REG);
wait_op_complete(RSA_MOD_MULT_START_REG);
mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, num_words);
esp_mpi_release_hardware();
return ret;
}
/* Deal with the case when X & Y are too long for the hardware unit, by splitting one operand
into two halves.
Y must be the longer operand
Slice Y into Yp, Ypp such that:
Yp = lower 'b' bits of Y
Ypp = upper 'b' bits of Y (right shifted)
Such that
Z = X * Y
Z = X * (Yp + Ypp<<b)
Z = (X * Yp) + (X * Ypp<<b)
Note that this function may recurse multiple times, if both X & Y
are too long for the hardware multiplication unit.
*/
static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t bits_y, size_t words_result)
{
int ret = 0;
mbedtls_mpi Ztemp;
const size_t limbs_y = (bits_y + biL - 1) / biL;
/* Rather than slicing in two on bits we slice on limbs (32 bit words) */
const size_t limbs_slice = limbs_y / 2;
/* Yp holds lower bits of Y (declared to reuse Y's array contents to save on copying) */
const mbedtls_mpi Yp = {
.p = Y->p,
.n = limbs_slice,
.s = Y->s
};
/* Ypp holds upper bits of Y, right shifted (also reuses Y's array contents) */
const mbedtls_mpi Ypp = {
.p = Y->p + limbs_slice,
.n = limbs_y - limbs_slice,
.s = Y->s
};
mbedtls_mpi_init(&Ztemp);
/* Grow Z to result size early, avoid interim allocations */
mbedtls_mpi_grow(Z, words_result);
/* Get result Ztemp = Yp * X (need temporary variable Ztemp) */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(&Ztemp, X, &Yp) );
/* Z = Ypp * Y */
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(Z, X, &Ypp) );
/* Z = Z << b */
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, limbs_slice * biL) );
/* Z += Ztemp */
MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) );
cleanup:
mbedtls_mpi_free(&Ztemp);
return ret;
}
#endif /* MBEDTLS_MPI_MUL_MPI_ALT */

View file

@ -31,8 +31,8 @@
#include <byteswap.h>
#include <assert.h>
#include "hwcrypto/sha.h"
#include "rom/ets_sys.h"
#include "esp32s2beta/sha.h"
#include "esp32s2beta/rom/ets_sys.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"

View file

@ -25,7 +25,7 @@
#define ESP_AES_H
#include "esp_types.h"
#include "rom/aes.h"
#include "esp32s2beta/rom/aes.h"
#ifdef __cplusplus
extern "C" {

View file

@ -14,7 +14,7 @@
#ifndef _ESP_SHA_H_
#define _ESP_SHA_H_
#include "rom/sha.h"
#include "esp32s2beta/rom/sha.h"
#include "esp_types.h"
/** @brief Low-level support functions for the hardware SHA engine

View file

@ -3048,13 +3048,13 @@ void _mdns_disable_pcb(tcpip_adapter_if_t tcpip_if, mdns_ip_protocol_t ip_protoc
/**
* @brief Dispatch interface changes based on system events
*/
static void _mdns_handle_system_event(esp_event_base_t event_base,
static void _mdns_handle_system_event(esp_event_base_t event_base,
int32_t event_id, tcpip_adapter_if_t interface)
{
if (!_mdns_server) {
return;
}
tcpip_adapter_dhcp_status_t dcst;
if (event_base == WIFI_EVENT) {
switch(event_id) {
@ -3079,7 +3079,9 @@ static void _mdns_handle_system_event(esp_event_base_t event_base,
default:
break;
}
} else if (event_base == ETH_EVENT) {
}
#if CONFIG_IDF_TARGET_ESP32
else if (event_base == ETH_EVENT) {
switch (event_id) {
case ETHERNET_EVENT_CONNECTED:
if (!tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &dcst)) {
@ -3095,15 +3097,19 @@ static void _mdns_handle_system_event(esp_event_base_t event_base,
default:
break;
}
} else if (event_base == IP_EVENT) {
}
#endif
else if (event_base == IP_EVENT) {
switch (event_id) {
case IP_EVENT_STA_GOT_IP:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V4);
_mdns_announce_pcb(TCPIP_ADAPTER_IF_STA, MDNS_IP_PROTOCOL_V6, NULL, 0, true);
break;
#if CONFIG_IDF_TARGET_ESP32
case IP_EVENT_ETH_GOT_IP:
_mdns_enable_pcb(TCPIP_ADAPTER_IF_ETH, MDNS_IP_PROTOCOL_V4);
break;
#endif
case IP_EVENT_GOT_IP6:
_mdns_enable_pcb(interface, MDNS_IP_PROTOCOL_V6);
_mdns_announce_pcb(interface, MDNS_IP_PROTOCOL_V4, NULL, 0, true);
@ -3722,7 +3728,7 @@ static void _mdns_execute_action(mdns_action_t * action)
switch(action->type) {
case ACTION_SYSTEM_EVENT:
_mdns_handle_system_event(action->data.sys_event.event_base,
_mdns_handle_system_event(action->data.sys_event.event_base,
action->data.sys_event.event_id, action->data.sys_event.interface);
break;
case ACTION_HOSTNAME_SET:
@ -4117,7 +4123,7 @@ esp_err_t mdns_handle_system_event(void *ctx, system_event_t *event)
return ESP_OK;
}
static void event_handler(void* arg, esp_event_base_t event_base,
static void event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data)
{
if (!_mdns_server) {
@ -4139,7 +4145,7 @@ static void event_handler(void* arg, esp_event_base_t event_base,
if (xQueueSend(_mdns_server->action_queue, &action, (portTickType)0) != pdPASS) {
free(action);
}
}
}
esp_err_t mdns_init()
@ -4168,17 +4174,17 @@ esp_err_t mdns_init()
err = ESP_ERR_NO_MEM;
goto free_lock;
}
if ((err = esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) {
goto free_event_handlers;
}
if ((err = esp_event_handler_register(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) {
goto free_event_handlers;
}
#if CONFIG_IDF_TARGET_ESP32
if ((err = esp_event_handler_register(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler, NULL)) != ESP_OK) {
goto free_event_handlers;
}
#endif
uint8_t i;
ip6_addr_t tmp_addr6;
tcpip_adapter_ip_info_t if_ip_info;
@ -4208,7 +4214,9 @@ free_all_and_disable_pcbs:
free_event_handlers:
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler);
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler);
#if CONFIG_IDF_TARGET_ESP32
esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler);
#endif
vQueueDelete(_mdns_server->action_queue);
free_lock:
vSemaphoreDelete(_mdns_server->lock);
@ -4256,7 +4264,9 @@ void mdns_free()
vSemaphoreDelete(_mdns_server->lock);
esp_event_handler_unregister(WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler);
esp_event_handler_unregister(IP_EVENT, ESP_EVENT_ANY_ID, &event_handler);
#if CONFIG_IDF_TARGET_ESP32
esp_event_handler_unregister(ETH_EVENT, ESP_EVENT_ANY_ID, &event_handler);
#endif
free(_mdns_server);
_mdns_server = NULL;
}

View file

@ -3,7 +3,7 @@
/*
* MDNS Server Networking -- private include
*
*
*/
#include "mdns.h"
#include "mdns_private.h"
@ -21,7 +21,9 @@
#include "esp_system.h"
#include "esp_timer.h"
#include "esp_event.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_eth.h"
#endif
/**

View file

@ -22,20 +22,26 @@
#include <sys/time.h>
#include <sys/times.h>
#include <sys/lock.h>
#include <esp32/rom/rtc.h>
#include "esp_attr.h"
#include "esp_intr_alloc.h"
#include "esp32/clk.h"
#include "esp_timer.h"
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/frc_timer_reg.h"
#include "esp32/rom/ets_sys.h"
#include "freertos/FreeRTOS.h"
#include "freertos/xtensa_api.h"
#include "freertos/task.h"
#include "sdkconfig.h"
#include "limits.h"
#include "sdkconfig.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#include "esp32/clk.h"
#include "esp32/rom/rtc.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#include "esp32s2beta/rom/rtc.h"
#include "esp32s2beta/rom/ets_sys.h"
#endif
#if defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC ) || defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 )
#define WITH_RTC 1

View file

@ -205,7 +205,7 @@ esp_err_t nvs_set_u32 (nvs_handle_t handle, const char* key, uint32_t value);
esp_err_t nvs_set_i64 (nvs_handle_t handle, const char* key, int64_t value);
esp_err_t nvs_set_u64 (nvs_handle_t handle, const char* key, uint64_t value);
esp_err_t nvs_set_str (nvs_handle_t handle, const char* key, const char* value);
/**@}*/
/**@}*/
/**
* @brief set variable length binary value for given key
@ -282,7 +282,7 @@ esp_err_t nvs_get_i32 (nvs_handle_t handle, const char* key, int32_t* out_value)
esp_err_t nvs_get_u32 (nvs_handle_t handle, const char* key, uint32_t* out_value);
esp_err_t nvs_get_i64 (nvs_handle_t handle, const char* key, int64_t* out_value);
esp_err_t nvs_get_u64 (nvs_handle_t handle, const char* key, uint64_t* out_value);
/**@}*/
/**@}*/
/**
* @brief get value for given key

View file

@ -11,10 +11,13 @@ endif()
list(APPEND COMPONENT_ADD_INCLUDEDIRS include)
if(NOT BOOTLOADER_BUILD)
list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c"
"src/lldesc.c src/hal/spi_hal.c"
"src/hal/spi_hal_iram.c"
"src/lldesc.c"
"src/soc_include_legacy_warn.c")
if(IDF_TARGET STREQUAL "esp32")
list(APPEND COMPONENT_SRCS "src/hal/spi_hal.c" "src/hal/spi_hal_iram.c")
endif()
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
endif()

View file

@ -0,0 +1,66 @@
// Copyright 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.
#include "soc/gpio_periph.h"
const uint32_t GPIO_PIN_MUX_REG[GPIO_PIN_COUNT] = {
IO_MUX_GPIO0_REG,
IO_MUX_GPIO1_REG,
IO_MUX_GPIO2_REG,
IO_MUX_GPIO3_REG,
IO_MUX_GPIO4_REG,
IO_MUX_GPIO5_REG,
IO_MUX_GPIO6_REG,
IO_MUX_GPIO7_REG,
IO_MUX_GPIO8_REG,
IO_MUX_GPIO9_REG,
IO_MUX_GPIO10_REG,
IO_MUX_GPIO11_REG,
IO_MUX_GPIO12_REG,
IO_MUX_GPIO13_REG,
IO_MUX_GPIO14_REG,
IO_MUX_GPIO15_REG,
IO_MUX_GPIO16_REG,
IO_MUX_GPIO17_REG,
IO_MUX_GPIO18_REG,
IO_MUX_GPIO19_REG,
IO_MUX_GPIO20_REG,
IO_MUX_GPIO21_REG,
0,
0,
0,
0,
IO_MUX_GPIO26_REG,
IO_MUX_GPIO27_REG,
IO_MUX_GPIO28_REG,
IO_MUX_GPIO29_REG,
IO_MUX_GPIO30_REG,
IO_MUX_GPIO31_REG,
IO_MUX_GPIO32_REG,
IO_MUX_GPIO33_REG,
IO_MUX_GPIO34_REG,
IO_MUX_GPIO35_REG,
IO_MUX_GPIO36_REG,
IO_MUX_GPIO37_REG,
IO_MUX_GPIO38_REG,
IO_MUX_GPIO39_REG,
IO_MUX_GPIO40_REG,
IO_MUX_GPIO41_REG,
IO_MUX_GPIO42_REG,
IO_MUX_GPIO43_REG,
IO_MUX_GPIO44_REG,
IO_MUX_GPIO45_REG,
IO_MUX_GPIO46_REG,
0,
};

View file

@ -23,11 +23,7 @@ typedef enum {
PERIPH_LEDC_MODULE = 0,
PERIPH_UART0_MODULE,
PERIPH_UART1_MODULE,
#ifdef CONFIG_CHIP_IS_ESP32
PERIPH_UART2_MODULE,
#else
PERIPH_USB_MODULE,
#endif
PERIPH_I2C0_MODULE,
PERIPH_I2C1_MODULE,
PERIPH_I2S0_MODULE,

View file

@ -0,0 +1,34 @@
// Copyright 2015-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.
#ifndef _SOC_SDIO_SLAVE_PINS_H_
#define _SOC_SDIO_SLAVE_PINS_H_
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_CLK 12
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_CMD 11
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D0 13
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D1 14
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D2 9
#define SDIO_SLAVE_SLOT0_IOMUX_PIN_NUM_D3 10
#define SDIO_SLAVE_SLOT0_FUNC 0
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CLK 36
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_CMD 35
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D0 37
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D1 38
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D2 33
#define SDIO_SLAVE_SLOT1_IOMUX_PIN_NUM_D3 34
#define SDIO_SLAVE_SLOT1_FUNC 3
#endif /* _SOC_SDIO_SLAVE_PINS_H_ */

View file

@ -0,0 +1,38 @@
// Copyright 2015-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.
#ifndef _SOC_SDMMC_PINS_H_
#define _SOC_SDMMC_PINS_H_
#define SDMMC_SLOT0_IOMUX_PIN_NUM_CLK 12
#define SDMMC_SLOT0_IOMUX_PIN_NUM_CMD 11
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D0 13
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D1 14
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D2 9
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D3 10
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D4 16
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D5 17
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D6 5
#define SDMMC_SLOT0_IOMUX_PIN_NUM_D7 18
#define SDMMC_SLOT0_FUNC 0
#define SDMMC_SLOT1_IOMUX_PIN_NUM_CLK 36
#define SDMMC_SLOT1_IOMUX_PIN_NUM_CMD 35
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D0 37
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D1 38
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D2 33
#define SDMMC_SLOT1_IOMUX_PIN_NUM_D3 34
#define SDMMC_SLOT1_FUNC 3
#endif /* _SOC_SDMMC_PINS_H_ */

View file

@ -57,6 +57,8 @@
#define PRO_CPU_NUM (0)
#define SOC_MAX_CONTIGUOUS_RAM_SIZE 0x400000 ///< Largest span of contiguous memory (DRAM or IRAM) in the address space
#define DR_REG_SYSTEM_BASE 0x3f4c0000
#define DR_REG_SENSITIVE_BASE 0x3f4c1000
#define DR_REG_INTERRUPT_BASE 0x3f4c2000
@ -123,7 +125,7 @@
//Registers Operation {{
#define ETS_UNCACHED_ADDR(addr) (addr)
#define ETS_CACHED_ADDR(addr) (addr)
#define ETS_CACHED_ADDR(addr) (addr)
#ifndef __ASSEMBLER__
#define BIT(nr) (1UL << (nr))

View file

@ -0,0 +1,20 @@
// Copyright 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.
#include "soc/rtc_periph.h"
//Reg,Mux,Fun,IE,Up,Down,Rtc_number
const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = {
0
};

View file

@ -13,4 +13,10 @@
// limitations under the License.
#pragma once
<<<<<<< a7ae5416fbc96f364c1047b2de9ba426677e258b
#include "soc/can_struct.h"
=======
#if CONFIG_IDF_TARGET_ESP32
#include "soc/can_struct.h"
#endif
>>>>>>> build and link hello-world for esp32s2beta

View file

@ -10,12 +10,14 @@ else() # not BOOTLOADER_BUILD
"flash_mmap.c"
"flash_ops.c"
"partition.c"
"spi_flash_rom_patch.c")
"spi_flash_rom_patch.c"
"${IDF_TARGET}/flash_ops_${IDF_TARGET}.c")
set(COMPONENT_REQUIRES app_update)
set(COMPONENT_PRIV_REQUIRES bootloader_support soc)
endif()
set(COMPONENT_ADD_INCLUDEDIRS include)
set(COMPONENT_PRIV_INCLUDEDIRS ".")
set(COMPONENT_ADD_LDFRAGMENTS linker.lf)
register_component()

View file

@ -20,8 +20,13 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#if CONFIG_IDF_TARGET_ESP32
#include <esp32/rom/spi_flash.h>
#include <esp32/rom/cache.h>
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/cache.h"
#endif
#include <soc/soc.h>
#include <soc/dport_reg.h>
#include "sdkconfig.h"
@ -31,6 +36,7 @@
#include "esp_spi_flash.h"
#include "esp_log.h"
static const char* TAG = "spiflash";
static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state);
static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state);
@ -62,7 +68,7 @@ void spi_flash_op_unlock()
}
/*
If you're going to modify this, keep in mind that while the flash caches of the pro and app
cpu are separate, the psram cache is *not*. If one of the CPUs returns from a flash routine
cpu are separate, the psram cache is *not*. If one of the CPUs returns from a flash routine
with its cache enabled but the other CPUs cache is not enabled yet, you will have problems
when accessing psram from the former CPU.
*/
@ -133,7 +139,7 @@ void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu()
}
// Kill interrupts that aren't located in IRAM
esp_intr_noniram_disable();
// This CPU executes this routine, with non-IRAM interrupts and the scheduler
// This CPU executes this routine, with non-IRAM interrupts and the scheduler
// disabled. The other CPU is spinning in the spi_flash_op_block_func task, also
// with non-iram interrupts and the scheduler disabled. None of these CPUs will
// touch external RAM or flash this way, so we can safely disable caches.
@ -255,13 +261,19 @@ void IRAM_ATTR spi_flash_enable_interrupts_caches_no_os()
* function in ROM. They are used to work around a bug where Cache_Read_Disable requires a call to
* Cache_Flush before Cache_Read_Enable, even if cached data was not modified.
*/
#if CONFIG_IDF_TARGET_ESP32
static const uint32_t cache_mask = DPORT_APP_CACHE_MASK_OPSDRAM | DPORT_APP_CACHE_MASK_DROM0 |
DPORT_APP_CACHE_MASK_DRAM1 | DPORT_APP_CACHE_MASK_IROM0 |
DPORT_APP_CACHE_MASK_IRAM1 | DPORT_APP_CACHE_MASK_IRAM0;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
// static const uint32_t icache_mask = DPORT_PRO_ICACHE_MASK_DROM0 |DPORT_PRO_ICACHE_MASK_IROM0 |
// DPORT_PRO_ICACHE_MASK_IRAM1 | DPORT_PRO_ICACHE_MASK_IRAM0;
// static const uint32_t dcache_mask = DPORT_PRO_DCACHE_MASK_DRAM1 | DPORT_PRO_DCACHE_MASK_DRAM0 |
// DPORT_PRO_DCACHE_MASK_DPORT | DPORT_PRO_DCACHE_MASK_DROM0;
#endif
static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_state)
{
#if CONFIG_IDF_TARGET_ESP32
uint32_t ret = 0;
if (cpuid == 0) {
ret |= DPORT_GET_PERI_REG_BITS2(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, 0);
@ -269,33 +281,327 @@ static void IRAM_ATTR spi_flash_disable_cache(uint32_t cpuid, uint32_t* saved_st
;
}
DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
} else {
}
#if !CONFIG_FREERTOS_UNICORE
else {
ret |= DPORT_GET_PERI_REG_BITS2(DPORT_APP_CACHE_CTRL1_REG, cache_mask, 0);
while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1) {
;
}
DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
}
#endif
*saved_state = ret;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
*saved_state = Cache_Suspend_ICache();
if (!Cache_Drom0_Using_ICache()) {
*(saved_state + 1) = Cache_Suspend_DCache();
}
#endif
}
static void IRAM_ATTR spi_flash_restore_cache(uint32_t cpuid, uint32_t saved_state)
{
#if CONFIG_IDF_TARGET_ESP32
if (cpuid == 0) {
DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
} else {
}
#if !CONFIG_FREERTOS_UNICORE
else {
DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL1_REG, cache_mask, saved_state, 0);
}
#endif
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Resume_ICache(saved_state);
if (!Cache_Drom0_Using_ICache()) {
Cache_Resume_DCache(s_flash_op_cache_state[1]);
}
#endif
}
IRAM_ATTR bool spi_flash_cache_enabled()
{
#if CONFIG_IDF_TARGET_ESP32
bool result = (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE) != 0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
bool result = (DPORT_REG_GET_BIT(DPORT_PRO_ICACHE_CTRL_REG, DPORT_PRO_ICACHE_ENABLE) != 0);
if (!Cache_Drom0_Using_ICache()) {
result = result && (DPORT_REG_GET_BIT(DPORT_PRO_DCACHE_CTRL_REG, DPORT_PRO_DCACHE_ENABLE) != 0);
}
#endif
#if portNUM_PROCESSORS == 2
result = result && (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE) != 0);
#endif
return result;
}
#if CONFIG_IDF_TARGET_ESP32S2BETA
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_INSTRUCTION_CACHE_8KB
Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_8KB;
#else
Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_16KB;
#endif
#if CONFIG_INSTRUCTION_CACHE_4WAYS
cache_ways = CACHE_4WAYS_ASSOC;
#else
cache_ways = CACHE_8WAYS_ASSOC;
#endif
#if CONFIG_INSTRUCTION_CACHE_LINE_16B
cache_line_size = CACHE_LINE_SIZE_16B;
#elif CONFIG_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 \t: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_8KB ? 8 : 16,cache_ways == CACHE_4WAYS_ASSOC ? 4: 8, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : (cache_line_size == CACHE_LINE_SIZE_32B ? 2 : 64));
Cache_Suspend_ICache();
Cache_Set_ICache_Mode(cache_size, cache_ways, cache_line_size);
Cache_Invalidate_ICache_All();
Cache_Resume_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_INSTRUCTION_CACHE_8KB
#if CONFIG_DATA_CACHE_8KB
Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_INVALID, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_8KB;
#else
Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_DCACHE_HIGH, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_16KB;
#endif
#else
#if CONFIG_DATA_CACHE_8KB
Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_INVALID);
cache_size = CACHE_SIZE_8KB;
#else
Cache_Allocate_SRAM(CACHE_MEMORY_ICACHE_LOW, CACHE_MEMORY_ICACHE_HIGH, CACHE_MEMORY_DCACHE_LOW, CACHE_MEMORY_DCACHE_HIGH);
cache_size = CACHE_SIZE_16KB;
#endif
#endif
#if CONFIG_DATA_CACHE_4WAYS
cache_ways = CACHE_4WAYS_ASSOC;
#else
cache_ways = CACHE_8WAYS_ASSOC;
#endif
#if CONFIG_DATA_CACHE_LINE_16B
cache_line_size = CACHE_LINE_SIZE_16B;
#elif CONFIG_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 \t\t: size %dKB, %dWays, cache line size %dByte", cache_size == CACHE_SIZE_8KB ? 8 : 16, cache_ways == CACHE_4WAYS_ASSOC ? 4: 8, cache_line_size == CACHE_LINE_SIZE_16B ? 16 : (cache_line_size == CACHE_LINE_SIZE_32B ? 2 : 64));
Cache_Set_DCache_Mode(cache_size, cache_ways, cache_line_size);
Cache_Invalidate_DCache_All();
}
void esp_switch_rodata_to_dcache(void)
{
REG_CLR_BIT(DPORT_PRO_DCACHE_CTRL1_REG, DPORT_PRO_DCACHE_MASK_DROM0);
Cache_Drom0_Source_DCache();
MMU_Drom_ICache_Unmap();
REG_SET_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_DROM0);
ESP_EARLY_LOGI(TAG, "Switch rodata load path to data cache.");
}
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(DPORT_PRO_CACHE_WRAP_AROUND_CTRL_REG, DPORT_PRO_CACHE_FLASH_WRAP_AROUND);
if (icache) {
Cache_Resume_ICache(i_autoload);
}
if (dcache) {
Cache_Resume_DCache(d_autoload);
}
}
#if CONFIG_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(DPORT_PRO_CACHE_WRAP_AROUND_CTRL_REG, DPORT_PRO_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 = true, spiram_support_wrap = true;
if (icache_wrap_enable) {
#if CONFIG_INSTRUCTION_CACHE_LINE_16B
icache_wrap_size = 16;
#elif CONFIG_INSTRUCTION_CACHE_LINE_32B
icache_wrap_size = 32;
#else
icache_wrap_size = 64;
#endif
}
if (dcache_wrap_enable) {
#if CONFIG_DATA_CACHE_LINE_16B
dcache_wrap_size = 16;
#elif CONFIG_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_INSTRUCTION_USE_SPIRAM
extern uint32_t esp_spiram_instruction_access_enabled();
instruction_use_spiram = esp_spiram_instruction_access_enabled();
#endif
#if CONFIG_RODATA_USE_SPIRAM
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 (Cache_Drom0_Using_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 (Cache_Drom0_Using_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_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;
}
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);
}
#ifdef CONFIG_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.");
spi_flash_enable_wrap(flash_wrap_size);
esp_enable_cache_flash_wrap((flash_wrap_sizes[0] > 0), (flash_wrap_sizes[1] > 0));
}
#if CONFIG_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.");
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

@ -54,4 +54,12 @@ void spi_flash_enable_interrupts_caches_no_os();
// Returns true if cache was flushed, false otherwise
bool spi_flash_check_and_flush_cache(uint32_t start_addr, uint32_t length);
//config cache mode
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
void esp_config_instruction_cache_mode(void);
void esp_config_data_cache_mode(void);
void esp_switch_rodata_to_dcache(void);
#endif
#endif //ESP_SPI_FLASH_CACHE_UTILS_H

View file

@ -1,5 +1,6 @@
COMPONENT_ADD_INCLUDEDIRS := include
COMPONENT_SRCDIRS := . $(IDF_TARGET)
COMPONENT_PRIV_INCLUDEDIRS := .
COMPONENT_ADD_LDFRAGMENTS += linker.lf
ifdef IS_BOOTLOADER_BUILD

View file

@ -0,0 +1,87 @@
// Copyright 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.
#include "esp_spi_flash_chip.h"
#include "cache_utils.h"
#include "rom/spi_flash.h"
#include "rom/cache.h"
static inline void IRAM_ATTR spi_flash_guard_start()
{
spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
if (ops && s_ops->start) {
ops->start();
}
}
static inline void IRAM_ATTR spi_flash_guard_end()
{
spi_flash_guard_funcs_t *ops = spi_flash_guard_get();
if (ops && s_ops->end) {
ops->end();
}
}
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size)
{
const uint8_t *ssrc = (const uint8_t *)src;
esp_rom_spiflash_result_t rc;
rc = spi_flash_unlock();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
return rc;
}
/* esp_rom_spiflash_write_encrypted encrypts data in RAM as it writes,
so copy to a temporary buffer - 32 bytes at a time.
Each call to esp_rom_spiflash_write_encrypted takes a 32 byte "row" of
data to encrypt, and each row is two 16 byte AES blocks
that share a key (as derived from flash address).
*/
uint8_t encrypt_buf[32] __attribute__((aligned(4)));
uint32_t row_size;
for (size_t i = 0; i < size; i += row_size) {
uint32_t row_addr = dest_addr + i;
if (i == 0 && (row_addr % 32) != 0) {
/* writing to second block of a 32 byte row */
row_size = 16;
row_addr -= 16;
/* copy to second block in buffer */
memcpy(encrypt_buf + 16, ssrc + i, 16);
/* decrypt the first block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr, encrypt_buf, 16);
} else if (size - i == 16) {
/* 16 bytes left, is first block of a 32 byte row */
row_size = 16;
/* copy to first block in buffer */
memcpy(encrypt_buf, ssrc + i, 16);
/* decrypt the second block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr + 16, encrypt_buf + 16, 16);
} else {
/* Writing a full 32 byte row (2 blocks) */
row_size = 32;
memcpy(encrypt_buf, ssrc + i, 32);
}
spi_flash_guard_start();
rc = esp_rom_spiflash_write_encrypted(row_addr, (uint32_t *)encrypt_buf, 32);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
}
bzero(encrypt_buf, sizeof(encrypt_buf));
return rc;
}

View file

@ -0,0 +1,65 @@
// Copyright 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.
#include <string.h>
#include <sys/param.h>
#include "esp_spi_flash.h"
#include "esp_spi_flash_chip.h"
#include "cache_utils.h"
#include "soc/system_reg.h"
#include "soc/soc_memory_layout.h"
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/cache.h"
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;
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
rc = spi_flash_unlock();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
return rc;
}
if (ops && ops->start) {
ops->start();
}
rc = SPI_Encrypt_Write(dest_addr, src, size);
if (ops && ops->end) {
ops->end();
}
return rc;
}
}

View file

@ -0,0 +1,29 @@
// Copyright 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.
/* Private header with chip-specific routines for SPI flash interaction */
#pragma once
#include <stdlib.h>
#include <stdint.h>
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/spi_flash.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/spi_flash.h"
#endif
esp_rom_spiflash_result_t spi_flash_write_encrypted_chip(size_t dest_addr, const void *src, size_t size);
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock();

View file

@ -20,8 +20,6 @@
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <freertos/semphr.h>
#include <esp32/rom/spi_flash.h>
#include <esp32/rom/cache.h>
#include <soc/soc.h>
#include <soc/dport_reg.h>
#include <soc/soc_memory_layout.h>
@ -32,7 +30,15 @@
#include "esp_flash_encrypt.h"
#include "esp_log.h"
#include "cache_utils.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/spi_flash.h"
#include "esp32/rom/cache.h"
#include "esp32/spiram.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/spi_flash.h"
#include "esp32s2beta/rom/cache.h"
#include "esp32s2beta/spiram.h"
#endif
#ifndef NDEBUG
// Enable built-in checks in queue.h in debug builds
@ -40,13 +46,29 @@
#endif
#include "sys/queue.h"
#define REGIONS_COUNT 4
#define PAGES_PER_REGION 64
#define INVALID_ENTRY_VAL 0x100
#define VADDR0_START_ADDR 0x3F400000
#ifdef CONFIG_IDF_TARGET_ESP32
#define REGIONS_COUNT 4
#define IROM0_PAGES_START 64
#define IROM0_PAGES_END 256
#define DROM0_PAGES_START 0
#define DROM0_PAGES_END 64
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#define REGIONS_COUNT 8
#define IROM0_PAGES_START (PRO_CACHE_IBUS0_MMU_START / sizeof(uint32_t))
#define IROM0_PAGES_END (PRO_CACHE_IBUS2_MMU_END / sizeof(uint32_t))
#define DROM0_PAGES_START (Cache_Drom0_Using_ICache()? PRO_CACHE_IBUS3_MMU_START / sizeof(uint32_t) : PRO_CACHE_DBUS3_MMU_START /sizeof(uint32_t))
#define DROM0_PAGES_END (Cache_Drom0_Using_ICache()? PRO_CACHE_IBUS3_MMU_END / sizeof(uint32_t) : PRO_CACHE_DBUS3_MMU_END / sizeof(uint32_t))
#endif
#define MMU_ADDR_MASK DPORT_MMU_ADDRESS_MASK
#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 INVALID_ENTRY_VAL DPORT_FLASH_MMU_TABLE_INVALID_VAL
#define VADDR0_START_ADDR SOC_DROM_LOW
#define VADDR1_START_ADDR 0x40000000
#define VADDR1_FIRST_USABLE_ADDR 0x400D0000
#define PRO_IRAM0_FIRST_USABLE_PAGE ((VADDR1_FIRST_USABLE_ADDR - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + 64)
#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;
@ -70,6 +92,7 @@ static void IRAM_ATTR spi_flash_mmap_init()
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
uint32_t entry_app = DPORT_SEQUENCE_REG_READ((uint32_t)&DPORT_APP_FLASH_MMU_TABLE[i]);
if (entry_pro != entry_app) {
@ -77,11 +100,14 @@ static void IRAM_ATTR spi_flash_mmap_init()
entry_pro = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
}
if ((entry_pro & INVALID_ENTRY_VAL) == 0 && (i == 0 || i == PRO_IRAM0_FIRST_USABLE_PAGE || entry_pro != 0)) {
#endif
if ((entry_pro & INVALID_ENTRY_VAL) == 0 && (i == DROM0_PAGES_START || i == PRO_IRAM0_FIRST_USABLE_PAGE || entry_pro != 0)) {
s_mmap_page_refcnt[i] = 1;
} else {
DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
#if !CONFIG_FREERTOS_UNICORE
DPORT_APP_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
#endif
}
}
DPORT_INTERRUPT_RESTORE();
@ -91,13 +117,13 @@ static void IRAM_ATTR get_mmu_region(spi_flash_mmap_memory_t memory, int* out_be
{
if (memory == SPI_FLASH_MMAP_DATA) {
// Vaddr0
*out_begin = 0;
*out_size = 64;
*out_begin = DROM0_PAGES_START;
*out_size = DROM0_PAGES_NUM;
*region_addr = VADDR0_START_ADDR;
} else {
// only part of VAddr1 is usable, so adjust for that
*out_begin = PRO_IRAM0_FIRST_USABLE_PAGE;
*out_size = 3 * 64 - *out_begin;
*out_size = IROM0_PAGES_END - *out_begin;
*region_addr = VADDR1_FIRST_USABLE_ADDR;
}
}
@ -121,7 +147,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_
return ESP_ERR_NO_MEM;
}
for (int i = 0; i < page_count; i++) {
pages[i] = phys_page+i;
pages[i] = (phys_page+i) | DPORT_MMU_ACCESS_FLASH;
}
ret = spi_flash_mmap_pages(pages, page_count, memory, out_ptr, out_handle);
free(pages);
@ -140,7 +166,7 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
return ESP_ERR_INVALID_ARG;
}
for (int i = 0; i < page_count; i++) {
if (pages[i] < 0 || pages[i]*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) {
if (pages[i] < 0 || (pages[i] & MMU_ADDR_MASK)*SPI_FLASH_MMU_PAGE_SIZE >= g_rom_flashchip.chip_size) {
return ESP_ERR_INVALID_ARG;
}
}
@ -196,14 +222,25 @@ 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
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 == pages[pageno] &&
entry_app == pages[pageno]));
(entry_pro == pages[pageno]
#if !CONFIG_FREERTOS_UNICORE
&& entry_app == pages[pageno]
#endif
));
if (s_mmap_page_refcnt[i] == 0) {
if (entry_pro != pages[pageno] || entry_app != pages[pageno]) {
if (entry_pro != pages[pageno]
#if !CONFIG_FREERTOS_UNICORE
|| entry_app != pages[pageno]
#endif
) {
DPORT_PRO_FLASH_MMU_TABLE[i] = pages[pageno];
#if !CONFIG_FREERTOS_UNICORE
DPORT_APP_FLASH_MMU_TABLE[i] = pages[pageno];
#endif
need_flush = true;
}
}
@ -227,10 +264,24 @@ esp_err_t IRAM_ATTR spi_flash_mmap_pages(const int *pages, size_t page_count, sp
*/
if (need_flush) {
#if CONFIG_ESP32_SPIRAM_SUPPORT
#if CONFIG_IDF_TARGET_ESP32
esp_spiram_writeback_cache();
#endif
#endif
#if CONFIG_IDF_TARGET_ESP32
Cache_Flush(0);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
Cache_Invalidate_ICache_All();
if (!Cache_Drom0_Using_ICache()) {
#if CONFIG_SPIRAM_SUPPORT
Cache_WriteBack_All();
#endif
Cache_Invalidate_DCache_All();
}
#endif
#if !CONFIG_FREERTOS_UNICORE
Cache_Flush(1);
#endif
}
spi_flash_enable_interrupts_caches_and_other_cpu();
@ -254,7 +305,9 @@ 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
DPORT_APP_FLASH_MMU_TABLE[i] = INVALID_ENTRY_VAL;
#endif
}
}
LIST_REMOVE(it, entries);
@ -327,16 +380,15 @@ uint32_t spi_flash_cache2phys(const void *cached)
if (c >= VADDR1_START_ADDR && c < VADDR1_FIRST_USABLE_ADDR) {
/* IRAM address, doesn't map to flash */
return SPI_FLASH_CACHE2PHYS_FAIL;
}
else if (c < VADDR1_FIRST_USABLE_ADDR) {
} else if (c < VADDR1_FIRST_USABLE_ADDR) {
/* expect cache is in DROM */
cache_page = (c - VADDR0_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE;
cache_page = (c - VADDR0_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + DROM0_PAGES_START;
} else {
/* expect cache is in IROM */
cache_page = (c - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + 64;
cache_page = (c - VADDR1_START_ADDR) / SPI_FLASH_MMU_PAGE_SIZE + IROM0_PAGES_START;
}
if (cache_page >= 256) {
if (cache_page >= PAGES_LIMIT) {
/* cached address was not in IROM or DROM */
return SPI_FLASH_CACHE2PHYS_FAIL;
}
@ -345,7 +397,7 @@ uint32_t spi_flash_cache2phys(const void *cached)
/* page is not mapped */
return SPI_FLASH_CACHE2PHYS_FAIL;
}
uint32_t phys_offs = phys_page * SPI_FLASH_MMU_PAGE_SIZE;
uint32_t phys_offs = (phys_page & MMU_ADDR_MASK)* SPI_FLASH_MMU_PAGE_SIZE;
return phys_offs | (c & (SPI_FLASH_MMU_PAGE_SIZE-1));
}
@ -356,15 +408,15 @@ const void *IRAM_ATTR spi_flash_phys2cache(uint32_t phys_offs, spi_flash_mmap_me
intptr_t base;
if (memory == SPI_FLASH_MMAP_DATA) {
start = 0;
end = 64;
start = DROM0_PAGES_START;
end = DROM0_PAGES_END;
base = VADDR0_START_ADDR;
page_delta = 0;
page_delta = DROM0_PAGES_START > IROM0_PAGES_START ? DROM0_PAGES_START : 0;
} else {
start = PRO_IRAM0_FIRST_USABLE_PAGE;
end = 256;
end = IROM0_PAGES_END;
base = VADDR1_START_ADDR;
page_delta = 64;
page_delta = DROM0_PAGES_START > IROM0_PAGES_START ? 0: IROM0_PAGES_START;
}
spi_flash_disable_interrupts_caches_and_other_cpu();
DPORT_INTERRUPT_DISABLE();
@ -421,12 +473,14 @@ IRAM_ATTR bool spi_flash_check_and_flush_cache(size_t start_addr, size_t length)
}
if (is_page_mapped_in_cache(page)) {
#if CONFIG_IDF_TARGET_ESP32
#if CONFIG_ESP32_SPIRAM_SUPPORT
esp_spiram_writeback_cache();
#endif
Cache_Flush(0);
#ifndef CONFIG_FREERTOS_UNICORE
Cache_Flush(1);
#endif
#endif
return true;
}

View file

@ -30,11 +30,18 @@
#include "esp_ipc.h"
#include "esp_attr.h"
#include "esp_spi_flash.h"
#include "esp_spi_flash_chip.h"
#include "esp_log.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#include "soc/spi_mem_reg.h"
#endif
#include "esp_flash_partitions.h"
#include "esp_ota_ops.h"
#include "cache_utils.h"
#include "soc/spi_periph.h"
/* bytes erased by SPIEraseBlock() ROM function */
#define BLOCK_ERASE_SIZE 65536
@ -184,7 +191,7 @@ static inline void IRAM_ATTR spi_flash_guard_op_unlock()
}
}
static esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock()
esp_rom_spiflash_result_t IRAM_ATTR spi_flash_unlock()
{
static bool unlocked = false;
if (!unlocked) {
@ -420,7 +427,6 @@ out:
esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size)
{
CHECK_WRITE_ADDRESS(dest_addr, size);
const uint8_t *ssrc = (const uint8_t *)src;
if ((dest_addr % 16) != 0) {
return ESP_ERR_INVALID_ARG;
}
@ -430,49 +436,7 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src,
COUNTER_START();
esp_rom_spiflash_result_t rc;
rc = spi_flash_unlock();
if (rc == ESP_ROM_SPIFLASH_RESULT_OK) {
/* esp_rom_spiflash_write_encrypted encrypts data in RAM as it writes,
so copy to a temporary buffer - 32 bytes at a time.
Each call to esp_rom_spiflash_write_encrypted takes a 32 byte "row" of
data to encrypt, and each row is two 16 byte AES blocks
that share a key (as derived from flash address).
*/
uint8_t encrypt_buf[32] __attribute__((aligned(4)));
uint32_t row_size;
for (size_t i = 0; i < size; i += row_size) {
uint32_t row_addr = dest_addr + i;
if (i == 0 && (row_addr % 32) != 0) {
/* writing to second block of a 32 byte row */
row_size = 16;
row_addr -= 16;
/* copy to second block in buffer */
memcpy(encrypt_buf + 16, ssrc + i, 16);
/* decrypt the first block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr, encrypt_buf, 16);
} else if (size - i == 16) {
/* 16 bytes left, is first block of a 32 byte row */
row_size = 16;
/* copy to first block in buffer */
memcpy(encrypt_buf, ssrc + i, 16);
/* decrypt the second block from flash, will reencrypt to same bytes */
spi_flash_read_encrypted(row_addr + 16, encrypt_buf + 16, 16);
} else {
/* Writing a full 32 byte row (2 blocks) */
row_size = 32;
memcpy(encrypt_buf, ssrc + i, 32);
}
spi_flash_guard_start();
rc = esp_rom_spiflash_write_encrypted(row_addr, (uint32_t *)encrypt_buf, 32);
spi_flash_guard_end();
if (rc != ESP_ROM_SPIFLASH_RESULT_OK) {
break;
}
}
bzero(encrypt_buf, sizeof(encrypt_buf));
}
rc = spi_flash_write_encrypted_chip(dest_addr, src, size);
COUNTER_ADD_BYTES(write, size);
COUNTER_STOP(write);
@ -689,3 +653,76 @@ void spi_flash_dump_counters()
}
#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
#if CONFIG_IDF_TARGET_ESP32S2BETA
#define SPICACHE SPIMEM0
#define SPIFLASH SPIMEM1
#define FLASH_WRAP_CMD 0x77
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
{
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
uint32_t reg_bkp_usr = SPIFLASH.user.val;
SPIFLASH.user.fwrite_dio = 0;
SPIFLASH.user.fwrite_dual = 0;
SPIFLASH.user.fwrite_qio = 1;
SPIFLASH.user.fwrite_quad = 0;
SPIFLASH.ctrl.fcmd_dual = 0;
SPIFLASH.ctrl.fcmd_quad = 0;
SPIFLASH.user.usr_dummy = 0;
SPIFLASH.user.usr_addr = 1;
SPIFLASH.user.usr_command = 1;
SPIFLASH.user2.usr_command_bitlen = 7;
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
SPIFLASH.user1.usr_addr_bitlen = 23;
SPIFLASH.addr = 0;
SPIFLASH.user.usr_miso = 0;
SPIFLASH.user.usr_mosi = 1;
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
SPIFLASH.cmd.usr = 1;
while(SPIFLASH.cmd.usr != 0)
{ }
SPIFLASH.ctrl.val = reg_bkp_ctrl;
SPIFLASH.user.val = reg_bkp_usr;
return ESP_OK;
}
esp_err_t spi_flash_enable_wrap(uint32_t wrap_size)
{
switch(wrap_size) {
case 8:
return spi_flash_wrap_set(FLASH_WRAP_MODE_8B);
case 16:
return spi_flash_wrap_set(FLASH_WRAP_MODE_16B);
case 32:
return spi_flash_wrap_set(FLASH_WRAP_MODE_32B);
case 64:
return spi_flash_wrap_set(FLASH_WRAP_MODE_64B);
default:
return ESP_FAIL;
}
}
void spi_flash_disable_wrap()
{
spi_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;
}
}
#endif

View file

@ -33,10 +33,28 @@ extern "C" {
#define SPI_FLASH_MMU_PAGE_SIZE 0x10000 /**< Flash cache MMU mapping page size */
typedef enum {
FLASH_WRAP_MODE_8B = 0,
FLASH_WRAP_MODE_16B = 2,
FLASH_WRAP_MODE_32B = 4,
FLASH_WRAP_MODE_64B = 6,
FLASH_WRAP_MODE_DISABLE = 1
} spi_flash_wrap_mode_t;
/**
* @brief set wrap mode of flash
*
* @param spi_flash_wrap_mode_t mode: wrap mode support disable, 16 32, 64 byte
*
* @return esp_err_t : ESP_OK for successful.
*
*/
esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode);
/**
* @brief Initialize SPI flash access driver
*
* This function must be called exactly once, before any other
* This function must be called exactly once, before any other
* spi_flash_* functions are called.
* Currently this function is called from startup code. There is
* no need to call it from application code.

View file

@ -11,11 +11,16 @@
// 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"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/rom/ets_sys.h"
#include "esp32/rom/gpio.h"
#include "esp32/rom/spi_flash.h"
#include "sdkconfig.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/rom/ets_sys.h"
#include "esp32s2beta/rom/gpio.h"
#include "esp32s2beta/rom/spi_flash.h"
#endif
#include "soc/spi_periph.h"
@ -27,12 +32,18 @@ extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi)
{
uint32_t status;
#if CONFIG_IDF_TARGET_ESP32
//wait for spi control ready
while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
}
while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
while ((REG_READ(SPI_MEM_FSM_REG(1)) & SPI_MEM_ST)) {
}
while ((REG_READ(SPI_MEM_FSM_REG(0)) & SPI_MEM_ST)) {
}
#endif
//wait for flash status ready
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_status(spi, &status)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
@ -69,12 +80,21 @@ esp_rom_spiflash_result_t esp_rom_spiflash_unlock()
status &= ESP_ROM_SPIFLASH_QE;
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
#if CONFIG_IDF_TARGET_ESP32
REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN);
while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_WRITE(SPI_MEM_CMD_REG(SPI_IDX), SPI_MEM_FLASH_WREN);
while (REG_READ(SPI_MEM_CMD_REG(SPI_IDX)) != 0) {
}
#endif
esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(SPI_IDX), SPI_MEM_WRSR_2B);
#endif
if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status) != ESP_ROM_SPIFLASH_RESULT_OK) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
}
@ -96,7 +116,11 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip_internal(esp_rom_sp
esp_rom_spiflash_wait_idle(spi);
// Chip erase.
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_CE);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_CE);
#endif
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
// check erase is finished.
@ -117,7 +141,11 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector_internal(esp_rom_
// sector erase 4Kbytes erase is sector erase.
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr & 0xffffff);
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_SE);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_SE);
#endif
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
esp_rom_spiflash_wait_idle(spi);
@ -132,7 +160,11 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_erase_block_internal(esp_rom_s
// sector erase 4Kbytes erase is sector erase.
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr & 0xffffff);
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_BE);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_BE);
#endif
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
esp_rom_spiflash_wait_idle(spi);
@ -186,8 +218,11 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_program_page_internal(esp_rom_
}
temp_bl = 0;
}
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_PP);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_PP);
#endif
while ( READ_PERI_REG(PERIPHS_SPI_FLASH_CMD ) != 0 );
esp_rom_spiflash_wait_idle(spi);
@ -218,9 +253,15 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_read_data(esp_rom_spiflash_chi
while (temp_length > 0) {
if (temp_length >= ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM) {
//WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr |(ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << ESP_ROM_SPIFLASH_BYTES_LEN));
#if CONFIG_IDF_TARGET_ESP32
REG_WRITE(SPI_MISO_DLEN_REG(1), ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_USR_MISO_DBITLEN_S);
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_USR);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_WRITE(SPI_MEM_MISO_DLEN_REG(1), ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_MEM_USR_MISO_DBITLEN_S);
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_MEM_USR);
#endif
while (REG_READ(PERIPHS_SPI_FLASH_CMD) != 0);
for (i = 0; i < (ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM >> 2); i++) {
@ -231,8 +272,13 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_read_data(esp_rom_spiflash_chi
} else {
//WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr |(temp_length << ESP_ROM_SPIFLASH_BYTES_LEN ));
WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
#if CONFIG_IDF_TARGET_ESP32
REG_WRITE(SPI_MISO_DLEN_REG(1), ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_USR_MISO_DBITLEN_S);
REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_USR);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_WRITE(SPI_MEM_MISO_DLEN_REG(1), ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_MEM_USR_MISO_DBITLEN_S);
REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_MEM_USR);
#endif
while (REG_READ(PERIPHS_SPI_FLASH_CMD) != 0);
remain_word_num = (0 == (temp_length & 0x3)) ? (temp_length >> 2) : (temp_length >> 2) + 1;
@ -253,7 +299,11 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read_status(esp_rom_spiflash_chip_t *
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) {
WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, 0); // clear regisrter
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_RDSR);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_RDSR);
#endif
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
status_value = READ_PERI_REG(PERIPHS_SPI_FLASH_STATUS) & (spi->status_mask);
@ -283,7 +333,11 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write_status(esp_rom_spiflash_chip_t
// update status value by status_value
WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, status_value); // write status regisrter
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WRSR);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_WRSR);
#endif
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
esp_rom_spiflash_wait_idle(spi);
@ -297,7 +351,11 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_
esp_rom_spiflash_wait_idle(spi);
//enable write
#if CONFIG_IDF_TARGET_ESP32
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WREN); // enable write operation
#elif CONFIG_IDF_TARGET_ESP32S2BETA
WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_MEM_FLASH_WREN); // enable write operation
#endif
while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
// make sure the flash is ready for writing
@ -310,6 +368,7 @@ static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_
static void spi_cache_mode_switch(uint32_t modebit)
{
#if CONFIG_IDF_TARGET_ESP32
if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) {
REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
@ -345,7 +404,43 @@ static void spi_cache_mode_switch(uint32_t modebit)
REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_SIO_ADDR_BITSLEN);
REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x03);
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if ((modebit & SPI_MEM_FREAD_QIO) && (modebit & SPI_MEM_FASTRD_MODE)) {
REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MOSI);
REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MISO | SPI_MEM_USR_DUMMY | SPI_MEM_USR_ADDR);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_ADDR_BITLEN, SPI0_R_QIO_ADDR_BITSLEN);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, SPI0_R_QIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, 0xEB);
} else if (modebit & SPI_MEM_FASTRD_MODE) {
REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MOSI);
REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MISO | SPI_MEM_USR_DUMMY | SPI_MEM_USR_ADDR);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_ADDR_BITLEN, SPI0_R_FAST_ADDR_BITSLEN);
if ((modebit & SPI_MEM_FREAD_QUAD)) {
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, 0x6B);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
} else if ((modebit & SPI_MEM_FREAD_DIO)) {
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, SPI0_R_DIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, 0xBB);
} else if ((modebit & SPI_MEM_FREAD_DUAL)) {
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, 0x3B);
} else{
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, 0x0B);
}
} else {
REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MOSI);
if (g_rom_spiflash_dummy_len_plus[0] == 0) {
REG_CLR_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY);
} else {
REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_DUMMY);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[0] - 1);
}
REG_SET_BIT(SPI_MEM_USER_REG(0), SPI_MEM_USR_MISO | SPI_MEM_USR_ADDR);
REG_SET_FIELD(SPI_MEM_USER1_REG(0), SPI_MEM_USR_ADDR_BITLEN, SPI0_R_SIO_ADDR_BITSLEN);
REG_SET_FIELD(SPI_MEM_USER2_REG(0), SPI_MEM_USR_COMMAND_VALUE, 0x03);
}
#endif
}
esp_rom_spiflash_result_t esp_rom_spiflash_lock()
@ -374,27 +469,50 @@ esp_rom_spiflash_result_t esp_rom_spiflash_lock()
esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode)
{
uint32_t modebit;
#if CONFIG_IDF_TARGET_ESP32
while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
}
while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
}
#elif CONFIG_IDF_TARGET_ESP32S2BETA
while ((REG_READ(SPI_MEM_FSM_REG(1)) & SPI_MEM_ST)) {
}
while ((REG_READ(SPI_MEM_FSM_REG(0)) & SPI_MEM_ST)) {
}
#endif
//clear old mode bit
#if CONFIG_IDF_TARGET_ESP32
CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FREAD_QIO | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_DUAL | SPI_FASTRD_MODE);
CLEAR_PERI_REG_MASK(SPI_CTRL_REG(0), SPI_FREAD_QIO | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_DUAL | SPI_FASTRD_MODE);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_MEM_FREAD_QIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE);
CLEAR_PERI_REG_MASK(SPI_MEM_CTRL_REG(0), SPI_MEM_FREAD_QIO | SPI_MEM_FREAD_QUAD | SPI_MEM_FREAD_DIO | SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE);
#endif
//configure read mode
switch (mode) {
#if CONFIG_IDF_TARGET_ESP32
case ESP_ROM_SPIFLASH_QIO_MODE : modebit = SPI_FREAD_QIO | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_QOUT_MODE : modebit = SPI_FREAD_QUAD | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_DIO_MODE : modebit = SPI_FREAD_DIO | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_DOUT_MODE : modebit = SPI_FREAD_DUAL | SPI_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_FASTRD_MODE: modebit = SPI_FASTRD_MODE; break;
#elif CONFIG_IDF_TARGET_ESP32S2BETA
case ESP_ROM_SPIFLASH_QIO_MODE : modebit = SPI_MEM_FREAD_QIO | SPI_MEM_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_QOUT_MODE : modebit = SPI_MEM_FREAD_QUAD | SPI_MEM_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_DIO_MODE : modebit = SPI_MEM_FREAD_DIO | SPI_MEM_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_DOUT_MODE : modebit = SPI_MEM_FREAD_DUAL | SPI_MEM_FASTRD_MODE; break;
case ESP_ROM_SPIFLASH_FASTRD_MODE: modebit = SPI_MEM_FASTRD_MODE; break;
#endif
case ESP_ROM_SPIFLASH_SLOWRD_MODE: modebit = 0; break;
default : modebit = 0;
}
SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, modebit);
#if CONFIG_IDF_TARGET_ESP32
SET_PERI_REG_MASK(SPI_CTRL_REG(0), modebit);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(0), modebit);
#endif
spi_cache_mode_switch(modebit);
return ESP_ROM_SPIFLASH_RESULT_OK;
@ -416,9 +534,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip()
esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block_num)
{
// flash write is always 1 line currently
#if CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
#endif
//check program size
if (block_num >= ((g_rom_spiflash_chip.chip_size) / (g_rom_spiflash_chip.block_size))) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
@ -437,9 +559,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block_num)
esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector_num)
{
// flash write is always 1 line currently
#if CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
#endif
//check program size
if (sector_num >= ((g_rom_spiflash_chip.chip_size) / (g_rom_spiflash_chip.sector_size))) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
@ -463,9 +589,13 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t
uint8_t i;
// flash write is always 1 line currently
#if CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
#endif
//check program size
if ( (target + len) > (g_rom_spiflash_chip.chip_size)) {
return ESP_ROM_SPIFLASH_RESULT_ERR;
@ -503,6 +633,7 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t
return ESP_ROM_SPIFLASH_RESULT_OK;
}
#if CONFIG_IDF_TARGET_ESP32
esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len)
{
esp_rom_spiflash_result_t ret = ESP_ROM_SPIFLASH_RESULT_OK;
@ -528,13 +659,14 @@ esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr,
return ret;
}
#endif
esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest_addr, int32_t len)
{
// QIO or SIO, non-QIO regard as SIO
uint32_t modebit;
modebit = READ_PERI_REG(PERIPHS_SPI_FLASH_CTRL);
#if CONFIG_IDF_TARGET_ESP32
if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
@ -546,17 +678,44 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest_
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_ADDR);
if (modebit & SPI_FREAD_DIO) {
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if ((modebit & SPI_MEM_FREAD_QIO) && (modebit & SPI_MEM_FASTRD_MODE)) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_MOSI);
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_MISO | SPI_MEM_USR_DUMMY | SPI_MEM_USR_ADDR);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, SPI1_R_QIO_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_DUMMY_CYCLELEN, SPI1_R_QIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
//REG_SET_FIELD(PERIPHS_SPI_SPI_MEM_H_USRREG2, SPI_USR_COMMAND_VALUE, 0xEB);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_MEM_USR_COMMAND_BITLEN_S) | 0xEB);
} else if (modebit & SPI_MEM_FASTRD_MODE) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_MOSI);
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_MISO | SPI_MEM_USR_ADDR);
if (modebit & SPI_MEM_FREAD_DIO) {
#endif
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
#if CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xBB);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_MEM_USR_COMMAND_BITLEN_S) | 0xBB);
#endif
} else {
#if CONFIG_IDF_TARGET_ESP32
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[1] - 1);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0xBB);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[1] - 1);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_MEM_USR_COMMAND_VALUE, 0xBB);
#endif
}
} else {
#if CONFIG_IDF_TARGET_ESP32
if ((modebit & SPI_FREAD_QUAD)) {
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x6B);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x6B);
@ -570,8 +729,21 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest_
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_FAST_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, SPI1_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
if ((modebit & SPI_MEM_FREAD_QUAD)) {
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_MEM_USR_COMMAND_BITLEN_S) | 0x6B);
} else if ((modebit & SPI_MEM_FREAD_DUAL)) {
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_MEM_USR_COMMAND_BITLEN_S) | 0x3B);
} else {
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_MEM_USR_COMMAND_BITLEN_S) | 0x0B);
}
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, SPI1_R_FAST_ADDR_BITSLEN);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_DUMMY_CYCLELEN, SPI1_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
#endif
}
} else {
#if CONFIG_IDF_TARGET_ESP32
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
@ -583,6 +755,18 @@ esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest_
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_SIO_ADDR_BITSLEN);
//REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x03);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x03);
#elif CONFIG_IDF_TARGET_ESP32S2BETA
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_MOSI);
if (g_rom_spiflash_dummy_len_plus[1] == 0) {
REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
} else {
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_DUMMY);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[1] - 1);
}
REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_MEM_USR_MISO | SPI_MEM_USR_ADDR);
REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_MEM_USR_ADDR_BITLEN, SPI1_R_SIO_ADDR_BITSLEN);
REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_MEM_USR_COMMAND_BITLEN_S) | 0x03);
#endif
}
if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_data(&g_rom_spiflash_chip, target, dest_addr, len)) {

View file

@ -13,3 +13,7 @@ set(COMPONENT_PRIV_REQUIRES bootloader_support)
register_component()
set_source_files_properties(
"spiffs/src/spiffs_nucleus.c"
PROPERTIES COMPILE_FLAGS
-Wno-tautological-compare)

View file

@ -3,3 +3,5 @@ COMPONENT_PRIV_INCLUDEDIRS := . spiffs/src
COMPONENT_SRCDIRS := . spiffs/src
COMPONENT_SUBMODULES := spiffs
spiffs/src/spiffs_nucleus.o: CFLAGS += -Wno-tautological-compare

View file

@ -17,7 +17,9 @@
#include "esp_event.h"
#include "esp_wifi.h"
#include "esp_private/wifi.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp_eth.h"
#endif
#include "esp_err.h"
#include "esp_log.h"
@ -41,7 +43,7 @@ static void handle_sta_stop(void *arg, esp_event_base_t base, int32_t event_id,
static void handle_sta_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_disconnected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data);
#if CONFIG_IDF_TARGET_ESP32
static void handle_eth_start(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_stop(void *arg, esp_event_base_t base, int32_t event_id, void *data);
static void handle_eth_connected(void *arg, esp_event_base_t base, int32_t event_id, void *data);
@ -97,6 +99,16 @@ static void handle_eth_disconnected(void *arg, esp_event_base_t base, int32_t ev
tcpip_adapter_down(TCPIP_ADAPTER_IF_ETH);
}
static void handle_eth_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data;
ESP_LOGI(TAG, "eth ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&event->ip_info.ip),
IP2STR(&event->ip_info.netmask),
IP2STR(&event->ip_info.gw));
}
#endif
static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
API_CALL_CHECK("esp_wifi_internal_set_sta_ip", esp_wifi_internal_set_sta_ip(), ESP_OK);
@ -108,14 +120,6 @@ static void handle_sta_got_ip(void *arg, esp_event_base_t base, int32_t event_id
IP2STR(&event->ip_info.gw));
}
static void handle_eth_got_ip(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
const ip_event_got_ip_t *event = (const ip_event_got_ip_t *) data;
ESP_LOGI(TAG, "eth ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
IP2STR(&event->ip_info.ip),
IP2STR(&event->ip_info.netmask),
IP2STR(&event->ip_info.gw));
}
static void handle_ap_start(void *arg, esp_event_base_t base, int32_t event_id, void *data)
{
@ -261,7 +265,7 @@ esp_err_t tcpip_adapter_clear_default_wifi_handlers()
return ESP_OK;
}
#if CONFIG_IDF_TARGET_ESP32
esp_err_t tcpip_adapter_set_default_eth_handlers()
{
esp_err_t err;
@ -306,3 +310,4 @@ esp_err_t tcpip_adapter_clear_default_eth_handlers()
esp_event_handler_unregister(IP_EVENT, IP_EVENT_ETH_GOT_IP, handle_eth_got_ip);
return ESP_OK;
}
#endif

View file

@ -0,0 +1,920 @@
// 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"
#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 */
/**@}*/
/**@{*/
#define ESP_ERR_ULP_BASE 0x1200 /*!< Offset for ULP-related error codes */
#define ESP_ERR_ULP_SIZE_TOO_BIG (ESP_ERR_ULP_BASE + 1) /*!< Program doesn't fit into RTC memory reserved for the ULP */
#define ESP_ERR_ULP_INVALID_LOAD_ADDR (ESP_ERR_ULP_BASE + 2) /*!< Load address is outside of RTC memory reserved for the ULP */
#define ESP_ERR_ULP_DUPLICATE_LABEL (ESP_ERR_ULP_BASE + 3) /*!< More than one label with the same number was defined */
#define ESP_ERR_ULP_UNDEFINED_LABEL (ESP_ERR_ULP_BASE + 4) /*!< Branch instructions references an undefined label */
#define ESP_ERR_ULP_BRANCH_OUT_OF_RANGE (ESP_ERR_ULP_BASE + 5) /*!< Branch target is out of range of B instruction (try replacing with BX) */
/**@}*/
/**
* @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.
*/
typedef union {
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 */
} 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 */
/**
* @brief Resolve all macro references in a program and load it into RTC memory
* @param load_addr address where the program should be loaded, expressed in 32-bit words
* @param program ulp_insn_t array with the program
* @param psize size of the program, expressed in 32-bit words
* @return
* - ESP_OK on success
* - ESP_ERR_NO_MEM if auxiliary temporary structure can not be allocated
* - one of ESP_ERR_ULP_xxx if program is not valid or can not be loaded
*/
esp_err_t ulp_process_macros_and_load(uint32_t load_addr, const ulp_insn_t* program, size_t* psize);
/**
* @brief Load ULP program binary into RTC memory
*
* ULP program binary should have the following format (all values little-endian):
*
* 1. MAGIC, (value 0x00706c75, 4 bytes)
* 2. TEXT_OFFSET, offset of .text section from binary start (2 bytes)
* 3. TEXT_SIZE, size of .text section (2 bytes)
* 4. DATA_SIZE, size of .data section (2 bytes)
* 5. BSS_SIZE, size of .bss section (2 bytes)
* 6. (TEXT_OFFSET - 12) bytes of arbitrary data (will not be loaded into RTC memory)
* 7. .text section
* 8. .data section
*
* Linker script in components/ulp/ld/esp32.ulp.ld produces ELF files which
* correspond to this format. This linker script produces binaries with load_addr == 0.
*
* @param load_addr address where the program should be loaded, expressed in 32-bit words
* @param program_binary pointer to program binary
* @param program_size size of the program binary
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if load_addr is out of range
* - ESP_ERR_INVALID_SIZE if program_size doesn't match (TEXT_OFFSET + TEXT_SIZE + DATA_SIZE)
* - ESP_ERR_NOT_SUPPORTED if the magic number is incorrect
*/
esp_err_t ulp_load_binary(uint32_t load_addr, const uint8_t* program_binary, size_t program_size);
/**
* @brief Run the program loaded into RTC memory
* @param entry_point entry point, expressed in 32-bit words
* @return ESP_OK on success
*/
esp_err_t ulp_run(uint32_t entry_point);
/**
* @brief Set one of ULP wakeup period values
*
* ULP coprocessor starts running the program when the wakeup timer counts up
* to a given value (called period). There are 5 period values which can be
* programmed into SENS_ULP_CP_SLEEP_CYCx_REG registers, x = 0..4.
* By default, wakeup timer will use the period set into SENS_ULP_CP_SLEEP_CYC0_REG,
* i.e. period number 0. ULP program code can use SLEEP instruction to select
* which of the SENS_ULP_CP_SLEEP_CYCx_REG should be used for subsequent wakeups.
*
* However, please note that SLEEP instruction issued (from ULP program) while the system
* is in deep sleep mode does not have effect, and sleep cycle count 0 is used.
*
* @param period_index wakeup period setting number (0 - 4)
* @param period_us wakeup period, us
* @note The ULP FSM requires two clock cycles to wakeup before being able to run the program.
* Then additional 16 cycles are reserved after wakeup waiting until the 8M clock is stable.
* The FSM also requires two more clock cycles to go to sleep after the program execution is halted.
* The minimum wakeup period that may be set up for the ULP
* is equal to the total number of cycles spent on the above internal tasks.
* For a default configuration of the ULP running at 150kHz it makes about 133us.
* @return
* - ESP_OK on success
* - ESP_ERR_INVALID_ARG if period_index is out of range
*/
esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us);
#ifdef __cplusplus
}
#endif

View file

@ -15,19 +15,24 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "sdkconfig.h"
#include "esp_attr.h"
#include "esp_err.h"
#include "esp_log.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#include "esp32/ulp.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#include "esp32s2beta/ulp.h"
#endif
#include "soc/soc.h"
#include "soc/rtc.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "sdkconfig.h"
typedef struct {
uint32_t magic;
@ -112,7 +117,7 @@ esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us)
}
uint64_t period_us_64 = period_us;
uint64_t period_cycles = (period_us_64 << RTC_CLK_CAL_FRACT) / esp_clk_slowclk_cal_get();
uint64_t min_sleep_period_cycles = ULP_FSM_PREPARE_SLEEP_CYCLES
uint64_t min_sleep_period_cycles = ULP_FSM_PREPARE_SLEEP_CYCLES
+ ULP_FSM_WAKEUP_SLEEP_CYCLES
+ REG_GET_FIELD(RTC_CNTL_TIMER2_REG, RTC_CNTL_ULPCP_TOUCH_START_WAIT);
if (period_cycles < min_sleep_period_cycles) {

View file

@ -14,9 +14,14 @@
#include <string.h>
#include "unity.h"
#include "sdkconfig.h"
#include "soc/cpu.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/clk.h"
#include "esp32/rom/uart.h"
#include "soc/cpu.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/clk.h"
#include "esp32s2beta/rom/uart.h"
#endif
static uint32_t s_test_start, s_test_stop;

Some files were not shown because too many files have changed in this diff Show more