mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/bringup_esp32s3_fpga' into 'master'
esp32-s3 (beta2) chip bringup Closes IDF-958 See merge request espressif/esp-idf!9978
This commit is contained in:
commit
afe1413c9c
14
Kconfig
14
Kconfig
@ -33,7 +33,19 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
config IDF_TARGET_ESP32S3
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s3"
|
||||
select IDF_ENV_FPGA
|
||||
|
||||
choice IDF_TARGET_ESP32S3_BETA_VERSION
|
||||
prompt "ESP32-S3 beta version"
|
||||
depends on IDF_TARGET_ESP32S3
|
||||
default IDF_TARGET_ESP32S3_BETA_VERSION_2
|
||||
help
|
||||
Currently ESP32-S3 has several beta versions for internal use only.
|
||||
Select the one that matches your chip model.
|
||||
|
||||
config IDF_TARGET_ESP32S3_BETA_VERSION_2
|
||||
bool
|
||||
prompt "ESP32-S3 beta2"
|
||||
endchoice
|
||||
|
||||
config IDF_FIRMWARE_CHIP_ID
|
||||
hex
|
||||
|
@ -20,6 +20,8 @@
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/clk.h"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -24,7 +24,9 @@ COMPONENT_OBJEXCLUDE := src/bootloader_init.o \
|
||||
endif
|
||||
|
||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
|
||||
src/bootloader_efuse_esp32s2.o
|
||||
src/bootloader_flash_config_esp32s3.o \
|
||||
src/bootloader_efuse_esp32s2.o \
|
||||
src/bootloader_efuse_esp32s3.o \
|
||||
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||
ifndef CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -49,7 +49,7 @@ typedef enum {
|
||||
*/
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void)
|
||||
{
|
||||
uint32_t flash_crypt_cnt;
|
||||
uint32_t flash_crypt_cnt = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
|
@ -24,10 +24,13 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#define CPU_RESET_REASON RTC_SW_CPU_RESET
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define CPU_RESET_REASON RTC_SW_CPU_RESET
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#endif
|
||||
#include "esp_rom_uart.h"
|
||||
|
||||
void bootloader_clock_configure(void)
|
||||
__attribute__((weak)) void bootloader_clock_configure(void)
|
||||
{
|
||||
// ROM bootloader may have put a lot of text into UART0 FIFO.
|
||||
// Wait for it to be printed.
|
||||
@ -38,7 +41,7 @@ void bootloader_clock_configure(void)
|
||||
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
|
||||
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
|
||||
@ -51,23 +54,24 @@ void bootloader_clock_configure(void)
|
||||
cpu_freq_mhz = 240;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (rtc_clk_apb_freq_get() < APB_CLK_FREQ || rtc_get_reset_reason(0) != CPU_RESET_REASON) {
|
||||
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
|
||||
#endif
|
||||
#endif
|
||||
/* ESP32-S2 doesn't have XTAL_FREQ choice, always 40MHz */
|
||||
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
|
||||
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
|
||||
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
|
||||
rtc_clk_init(clk_cfg);
|
||||
/* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable
|
||||
* it here. Usually it needs some time to start up, so we amortize at least
|
||||
* part of the start up time by enabling 32k XTAL early.
|
||||
* App startup code will wait until the oscillator has started up.
|
||||
*/
|
||||
}
|
||||
|
||||
/* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable
|
||||
* it here. Usually it needs some time to start up, so we amortize at least
|
||||
* part of the start up time by enabling 32k XTAL early.
|
||||
* App startup code will wait until the oscillator has started up.
|
||||
*/
|
||||
#if CONFIG_ESP_SYSTEM_RTC_EXT_XTAL
|
||||
if (!rtc_clk_32k_enabled()) {
|
||||
rtc_clk_32k_bootstrap(CONFIG_ESP_SYSTEM_RTC_EXT_XTAL_BOOTSTRAP_CYCLES);
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#endif
|
||||
#include "esp_rom_crc.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
@ -74,7 +74,11 @@ void bootloader_console_init(void)
|
||||
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
|
||||
|
||||
// Set configured UART console baud rate
|
||||
esp_rom_uart_set_clock_baudrate(uart_num, rtc_clk_apb_freq_get(), CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
uint32_t clock_hz = rtc_clk_apb_freq_get();
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
clock_hz = UART_CLK_FREQ_ROM; // From esp32-s3 on, UART clock source is selected to XTAL in ROM
|
||||
#endif
|
||||
esp_rom_uart_set_clock_baudrate(uart_num, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE);
|
||||
}
|
||||
#endif // CONFIG_ESP_CONSOLE_UART
|
||||
|
||||
|
21
components/bootloader_support/src/bootloader_efuse_esp32s3.c
Normal file
21
components/bootloader_support/src/bootloader_efuse_esp32s3.c
Normal file
@ -0,0 +1,21 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
/* No other revisions for ESP32-S3 */
|
||||
return 0;
|
||||
}
|
@ -32,7 +32,9 @@
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/spi_flash.h" //For SPI_Encrypt_Write
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
|
||||
@ -87,7 +89,7 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_flash_write_encrypted(dest_addr, src, size);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
return SPI_Encrypt_Write(dest_addr, src, size);
|
||||
#endif
|
||||
} else {
|
||||
@ -115,6 +117,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#endif
|
||||
static const char *TAG = "bootloader_flash";
|
||||
|
||||
@ -126,7 +132,7 @@ static const char *TAG = "bootloader_flash";
|
||||
#define MMU_SIZE (0x320000)
|
||||
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Use first 63 blocks in MMU for bootloader_mmap,
|
||||
63th block for bootloader_flash_read
|
||||
*/
|
||||
@ -171,6 +177,9 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
uint32_t autoload = Cache_Suspend_DCache();
|
||||
Cache_Invalidate_DCache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
|
||||
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||
@ -178,6 +187,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||
#endif
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
@ -185,6 +196,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
Cache_Resume_ICache(autoload);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
Cache_Resume_DCache(autoload);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
@ -192,6 +205,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
Cache_Resume_ICache(autoload);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
Cache_Resume_DCache(autoload);
|
||||
#endif
|
||||
|
||||
mapped = true;
|
||||
@ -212,6 +227,11 @@ void bootloader_munmap(const void *mapping)
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
//TODO, save the autoload value.
|
||||
Cache_Suspend_DCache();
|
||||
Cache_Invalidate_DCache_All();
|
||||
Cache_MMU_Init();
|
||||
#endif
|
||||
mapped = false;
|
||||
current_read_mapping = UINT32_MAX;
|
||||
@ -239,12 +259,16 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
uint32_t autoload = Cache_Suspend_DCache();
|
||||
#endif
|
||||
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
Cache_Resume_ICache(autoload);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
Cache_Resume_DCache(autoload);
|
||||
#endif
|
||||
|
||||
return spi_to_esp_err(r);
|
||||
@ -266,12 +290,17 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
uint32_t autoload = Cache_Suspend_DCache();
|
||||
Cache_Invalidate_DCache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
||||
#endif
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
@ -279,6 +308,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
Cache_Resume_ICache(autoload);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
Cache_Resume_DCache(autoload);
|
||||
#endif
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -287,6 +318,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
Cache_Resume_ICache(autoload);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
Cache_Resume_DCache(autoload);
|
||||
#endif
|
||||
}
|
||||
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
|
||||
@ -342,8 +375,8 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
// TODO: use the same ROM AP here
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
// TODO: use the same ROM API here
|
||||
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
|
||||
#endif
|
||||
} else {
|
||||
|
@ -0,0 +1,80 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
||||
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
||||
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
|
||||
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(0), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(0), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(1), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(1), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_clock_config(const esp_image_header_t *pfhdr)
|
||||
{
|
||||
uint32_t spi_clk_div = 0;
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
spi_clk_div = 1;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
spi_clk_div = 2;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
spi_clk_div = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
spi_clk_div = 4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
esp_rom_spiflash_config_clk(spi_clk_div, 0);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_set_dummy_out(void)
|
||||
{
|
||||
REG_SET_BIT(SPI_MEM_CTRL_REG(0), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
|
||||
REG_SET_BIT(SPI_MEM_CTRL_REG(1), SPI_MEM_FDUMMY_OUT | SPI_MEM_D_POL | SPI_MEM_Q_POL);
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t *pfhdr)
|
||||
{
|
||||
bootloader_configure_spi_pins(1);
|
||||
bootloader_flash_set_dummy_out();
|
||||
}
|
@ -22,7 +22,7 @@
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "soc/apb_saradc_reg.h"
|
||||
#endif
|
||||
|
||||
@ -30,13 +30,13 @@
|
||||
#include "esp_system.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
__attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
return esp_fill_random(buffer, length);
|
||||
}
|
||||
|
||||
#else
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
__attribute__((weak)) void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
uint8_t *buffer_bytes = (uint8_t *)buffer;
|
||||
uint32_t random;
|
||||
@ -71,7 +71,11 @@ void bootloader_random_enable(void)
|
||||
never disabled while the CPU is running), this is a "belts and braces" type check.
|
||||
*/
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
SET_PERI_REG_MASK(SYSTEM_WIFI_CLK_EN_REG, SYSTEM_WIFI_CLK_RNG_EN);
|
||||
#else
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, DPORT_WIFI_CLK_RNG_EN);
|
||||
#endif
|
||||
#else
|
||||
periph_module_enable(PERIPH_RNG_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
@ -105,6 +109,17 @@ void bootloader_random_enable(void)
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Disable IO1 digital function for random function. */
|
||||
PIN_INPUT_DISABLE(PERIPHS_IO_MUX_GPIO1_U);
|
||||
PIN_PULLDWN_DIS(PERIPHS_IO_MUX_GPIO1_U);
|
||||
PIN_PULLUP_DIS(PERIPHS_IO_MUX_GPIO1_U);
|
||||
WRITE_PERI_REG(APB_SARADC_SAR1_PATT_TAB1_REG, 0xFFFFFFFF);
|
||||
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP);
|
||||
#endif
|
||||
|
||||
// Test pattern configuration byte 0xAD:
|
||||
@ -119,7 +134,7 @@ void bootloader_random_enable(void)
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB1_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB2_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(APB_SARADC_SAR2_PATT_TAB3_REG, 0xADADADAD);
|
||||
@ -147,15 +162,18 @@ void bootloader_random_enable(void)
|
||||
SET_PERI_REG_BITS(I2S_SAMPLE_RATE_CONF_REG(0), I2S_RX_BCK_DIV_NUM, 20, I2S_RX_BCK_DIV_NUM_S);
|
||||
SET_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_DATA_TO_I2S);
|
||||
#endif
|
||||
#if !CONFIG_IDF_TARGET_ESP32S3
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_CAMERA_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE);
|
||||
SET_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN);
|
||||
SET_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
#endif
|
||||
}
|
||||
|
||||
void bootloader_random_disable(void)
|
||||
{
|
||||
#if !CONFIG_IDF_TARGET_ESP32S3
|
||||
/* Reset some i2s configuration (possibly redundant as we reset entire
|
||||
I2S peripheral further down). */
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
@ -165,10 +183,14 @@ void bootloader_random_disable(void)
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_LCD_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE_TEST_EN);
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF2_REG(0), I2S_DATA_ENABLE);
|
||||
|
||||
#endif
|
||||
/* Disable i2s clock */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_CLK_EN0_REG, SYSTEM_I2S0_CLK_EN);
|
||||
#else
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
#endif
|
||||
#else
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
#endif // BOOTLOADER_BUILD
|
||||
@ -177,7 +199,7 @@ void bootloader_random_disable(void)
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
@ -187,7 +209,7 @@ void bootloader_random_disable(void)
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX
|
||||
| SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(APB_SARADC_CTRL_REG, APB_SARADC_SAR_SEL | APB_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
@ -199,8 +221,13 @@ void bootloader_random_disable(void)
|
||||
|
||||
/* Reset i2s peripheral */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
#if CONFIG_IDF_TARGET_ESP32S3
|
||||
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_I2S0_RST);
|
||||
CLEAR_PERI_REG_MASK(SYSTEM_PERIP_RST_EN0_REG, SYSTEM_I2S0_RST);
|
||||
#else
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST);
|
||||
#endif
|
||||
#else
|
||||
periph_module_reset(PERIPH_I2S0_MODULE);
|
||||
#endif
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "esp_log.h"
|
||||
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
@ -32,10 +33,16 @@
|
||||
#include "esp32s2/rom/secure_boot.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#else
|
||||
#error "Unsupported IDF_TARGET"
|
||||
#endif
|
||||
#include "esp_rom_uart.h"
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
@ -683,6 +690,9 @@ static void set_cache_and_start_app(
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
uint32_t autoload = Cache_Suspend_DCache();
|
||||
Cache_Invalidate_DCache_All();
|
||||
#endif
|
||||
|
||||
/* Clear the MMU entries that are already set up,
|
||||
@ -692,7 +702,7 @@ static void set_cache_and_start_app(
|
||||
for (int i = 0; i < DPORT_FLASH_MMU_TABLE_SIZE; i++) {
|
||||
DPORT_PRO_FLASH_MMU_TABLE[i] = DPORT_FLASH_MMU_TABLE_INVALID_VAL;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
for (int i = 0; i < FLASH_MMU_TABLE_SIZE; i++) {
|
||||
FLASH_MMU_TABLE[i] = MMU_TABLE_INVALID_VAL;
|
||||
}
|
||||
@ -705,6 +715,8 @@ static void set_cache_and_start_app(
|
||||
rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -728,6 +740,8 @@ static void set_cache_and_start_app(
|
||||
REG_CLR_BIT(EXTMEM_PRO_ICACHE_CTRL1_REG, EXTMEM_PRO_ICACHE_MASK_IRAM1);
|
||||
}
|
||||
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -743,11 +757,18 @@ static void set_cache_and_start_app(
|
||||
DPORT_APP_CACHE_MASK_DRAM1 );
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
REG_CLR_BIT( EXTMEM_PRO_ICACHE_CTRL1_REG, (EXTMEM_PRO_ICACHE_MASK_IRAM0) | (EXTMEM_PRO_ICACHE_MASK_IRAM1 & 0) | EXTMEM_PRO_ICACHE_MASK_DROM0 );
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
||||
#endif
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
Cache_Resume_ICache(autoload);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
Cache_Resume_DCache(autoload);
|
||||
#endif
|
||||
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
|
||||
|
||||
|
@ -18,9 +18,6 @@
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
@ -29,6 +26,8 @@
|
||||
#include "bootloader_console.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp32s2/rom/cache.h"
|
||||
#include "esp32s2/rom/spi_flash.h"
|
||||
|
341
components/bootloader_support/src/esp32s3/bootloader_esp32s3.c
Normal file
341
components/bootloader_support/src/esp32s3/bootloader_esp32s3.c
Normal file
@ -0,0 +1,341 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdint.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_mem.h"
|
||||
#include "bootloader_console.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
|
||||
|
||||
static const char *TAG = "boot.esp32s3";
|
||||
|
||||
void IRAM_ATTR bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
uint8_t wp_pin = esp_rom_efuse_get_flash_wp_gpio();
|
||||
uint8_t clk_gpio_num = SPI_CLK_GPIO_NUM;
|
||||
uint8_t q_gpio_num = SPI_Q_GPIO_NUM;
|
||||
uint8_t d_gpio_num = SPI_D_GPIO_NUM;
|
||||
uint8_t cs0_gpio_num = SPI_CS0_GPIO_NUM;
|
||||
uint8_t hd_gpio_num = SPI_HD_GPIO_NUM;
|
||||
uint8_t wp_gpio_num = SPI_WP_GPIO_NUM;
|
||||
if (spiconfig == 0) {
|
||||
|
||||
} else {
|
||||
clk_gpio_num = spiconfig & 0x3f;
|
||||
q_gpio_num = (spiconfig >> 6) & 0x3f;
|
||||
d_gpio_num = (spiconfig >> 12) & 0x3f;
|
||||
cs0_gpio_num = (spiconfig >> 18) & 0x3f;
|
||||
hd_gpio_num = (spiconfig >> 24) & 0x3f;
|
||||
wp_gpio_num = wp_pin;
|
||||
}
|
||||
esp_rom_gpio_pad_set_drv(clk_gpio_num, drv);
|
||||
esp_rom_gpio_pad_set_drv(q_gpio_num, drv);
|
||||
esp_rom_gpio_pad_set_drv(d_gpio_num, drv);
|
||||
esp_rom_gpio_pad_set_drv(cs0_gpio_num, drv);
|
||||
if (hd_gpio_num <= MAX_PAD_GPIO_NUM) {
|
||||
esp_rom_gpio_pad_set_drv(hd_gpio_num, drv);
|
||||
}
|
||||
if (wp_gpio_num <= MAX_PAD_GPIO_NUM) {
|
||||
esp_rom_gpio_pad_set_drv(wp_gpio_num, drv);
|
||||
}
|
||||
}
|
||||
|
||||
static void bootloader_reset_mmu(void)
|
||||
{
|
||||
Cache_Suspend_DCache();
|
||||
Cache_Invalidate_DCache_All();
|
||||
Cache_MMU_Init();
|
||||
|
||||
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_CORE0_BUS);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_CORE1_BUS);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void update_flash_config(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
uint32_t size;
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
size = 1;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
size = 2;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
size = 4;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
size = 8;
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
size = 16;
|
||||
break;
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
uint32_t autoload = Cache_Suspend_DCache();
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
Cache_Resume_DCache(autoload);
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *bootloader_hdr)
|
||||
{
|
||||
ESP_LOGD(TAG, "magic %02x", bootloader_hdr->magic);
|
||||
ESP_LOGD(TAG, "segments %02x", bootloader_hdr->segment_count);
|
||||
ESP_LOGD(TAG, "spi_mode %02x", bootloader_hdr->spi_mode);
|
||||
ESP_LOGD(TAG, "spi_speed %02x", bootloader_hdr->spi_speed);
|
||||
ESP_LOGD(TAG, "spi_size %02x", bootloader_hdr->spi_size);
|
||||
|
||||
const char *str;
|
||||
switch (bootloader_hdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
str = "40MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_26M:
|
||||
str = "26.7MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_20M:
|
||||
str = "20MHz";
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
str = "80MHz";
|
||||
break;
|
||||
default:
|
||||
str = "20MHz";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Speed : %s", str);
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
uint32_t spi_ctrl = REG_READ(SPI_MEM_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_MEM_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_QUAD) {
|
||||
str = "QOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DIO) {
|
||||
str = "DIO";
|
||||
} else if (spi_ctrl & SPI_MEM_FREAD_DUAL) {
|
||||
str = "DOUT";
|
||||
} else if (spi_ctrl & SPI_MEM_FASTRD_MODE) {
|
||||
str = "FAST READ";
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str);
|
||||
|
||||
switch (bootloader_hdr->spi_size) {
|
||||
case ESP_IMAGE_FLASH_SIZE_1MB:
|
||||
str = "1MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_2MB:
|
||||
str = "2MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_4MB:
|
||||
str = "4MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_8MB:
|
||||
str = "8MB";
|
||||
break;
|
||||
case ESP_IMAGE_FLASH_SIZE_16MB:
|
||||
str = "16MB";
|
||||
break;
|
||||
default:
|
||||
str = "2MB";
|
||||
break;
|
||||
}
|
||||
ESP_LOGI(TAG, "SPI Flash Size : %s", str);
|
||||
}
|
||||
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(void)
|
||||
{
|
||||
bootloader_flash_dummy_config(&bootloader_image_hdr);
|
||||
bootloader_flash_cs_timing_config();
|
||||
}
|
||||
|
||||
static esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
bootloader_init_flash_configure();
|
||||
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
|
||||
ESP_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_unlock();
|
||||
|
||||
#if CONFIG_ESPTOOLPY_FLASHMODE_QIO || CONFIG_ESPTOOLPY_FLASHMODE_QOUT
|
||||
bootloader_enable_qio_mode();
|
||||
#endif
|
||||
|
||||
print_flash_info(&bootloader_image_hdr);
|
||||
update_flash_config(&bootloader_image_hdr);
|
||||
//ensure the flash is write-protected
|
||||
bootloader_enable_wp();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
REG_SET_BIT(SYSTEM_CPU_PERI_CLK_EN_REG, SYSTEM_CLK_EN_ASSIST_DEBUG);
|
||||
REG_CLR_BIT(SYSTEM_CPU_PERI_RST_EN_REG, SYSTEM_RST_EN_ASSIST_DEBUG);
|
||||
REG_WRITE(ASSIST_DEBUG_CORE_0_RCD_PDEBUGENABLE_REG, 1);
|
||||
REG_WRITE(ASSIST_DEBUG_CORE_0_RCD_RECORDING_REG, 1);
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
{
|
||||
uint32_t inst = 0, pid = 0, stat = 0, data = 0, pc = 0,
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
stat = 0xdeadbeef;
|
||||
pid = 0;
|
||||
if (cpu == 0) {
|
||||
inst = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGINST_REG);
|
||||
dstat = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGSTATUS_REG);
|
||||
data = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGDATA_REG);
|
||||
pc = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGPC_REG);
|
||||
lsstat = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = REG_READ(ASSIST_DEBUG_CORE_0_RCD_PDEBUGLS0DATA_REG);
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
inst = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGINST_REG);
|
||||
dstat = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGSTATUS_REG);
|
||||
data = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGDATA_REG);
|
||||
pc = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGPC_REG);
|
||||
lsstat = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = REG_READ(ASSIST_DEBUG_CORE_1_RCD_PDEBUGLS0DATA_REG);
|
||||
#else
|
||||
ESP_LOGE(TAG, "WDT reset info: %s CPU not support!\n", cpu_name);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU STATUS 0x%08x", cpu_name, stat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PID 0x%08x", cpu_name, pid);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGINST 0x%08x", cpu_name, inst);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGSTATUS 0x%08x", cpu_name, dstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGDATA 0x%08x", cpu_name, data);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGPC 0x%08x", cpu_name, pc);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0STAT 0x%08x", cpu_name, lsstat);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0ADDR 0x%08x", cpu_name, lsaddr);
|
||||
ESP_LOGD(TAG, "WDT reset info: %s CPU PDEBUGLS0DATA 0x%08x", cpu_name, lsdata);
|
||||
}
|
||||
|
||||
static void bootloader_check_wdt_reset(void)
|
||||
{
|
||||
int wdt_rst = 0;
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TG0WDT_CPU_RESET || rst_reas[0] == TG1WDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
ESP_LOGW(TAG, "PRO CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
wdt_reset_info_dump(1);
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
|
||||
static void bootloader_super_wdt_auto_feed(void)
|
||||
{
|
||||
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
|
||||
}
|
||||
|
||||
esp_err_t bootloader_init(void)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
bootloader_super_wdt_auto_feed();
|
||||
// protect memory region
|
||||
bootloader_init_mem();
|
||||
/* check that static RAM is after the stack */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
}
|
||||
#endif
|
||||
// clear bss section
|
||||
bootloader_clear_bss_section();
|
||||
// reset MMU
|
||||
bootloader_reset_mmu();
|
||||
// config clock
|
||||
bootloader_clock_configure();
|
||||
// initialize console, from now on, we can use esp_log
|
||||
bootloader_console_init();
|
||||
/* print 2nd bootloader banner */
|
||||
bootloader_print_banner();
|
||||
// update flash ID
|
||||
bootloader_flash_update_id();
|
||||
// read bootloader header
|
||||
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// read chip revision and check if it's compatible to bootloader
|
||||
if ((ret = bootloader_check_bootloader_validity()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// initialize spi flash
|
||||
if ((ret = bootloader_init_spi_flash()) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
// check whether a WDT reset happend
|
||||
bootloader_check_wdt_reset();
|
||||
// config WDT
|
||||
bootloader_config_wdt();
|
||||
// enable RNG early entropy source
|
||||
bootloader_enable_random();
|
||||
err:
|
||||
return ret;
|
||||
}
|
48
components/bootloader_support/src/esp32s3/bootloader_sha.c
Normal file
48
components/bootloader_support/src/esp32s3/bootloader_sha.c
Normal file
@ -0,0 +1,48 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32s3/rom/sha.h"
|
||||
|
||||
static SHA_CTX ctx;
|
||||
|
||||
bootloader_sha256_handle_t bootloader_sha256_start()
|
||||
{
|
||||
// Enable SHA hardware
|
||||
ets_sha_enable();
|
||||
ets_sha_init(&ctx, SHA2_256);
|
||||
return &ctx; // Meaningless non-NULL value
|
||||
}
|
||||
|
||||
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
assert(data_len % 4 == 0);
|
||||
ets_sha_update(&ctx, data, data_len, false);
|
||||
}
|
||||
|
||||
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
|
||||
{
|
||||
assert(handle != NULL);
|
||||
|
||||
if (digest == NULL) {
|
||||
bzero(&ctx, sizeof(ctx));
|
||||
return;
|
||||
}
|
||||
ets_sha_finish(&ctx, digest);
|
||||
}
|
414
components/bootloader_support/src/esp32s3/flash_encrypt.c
Normal file
414
components/bootloader_support/src/esp32s3/flash_encrypt.c
Normal file
@ -0,0 +1,414 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_flash_encrypt.h"
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32s3/rom/efuse.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
static const char *TAG = "flash_encrypt";
|
||||
|
||||
/* Static functions for stages of flash encryption */
|
||||
static esp_err_t initialise_flash_encryption(void);
|
||||
static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_crypt_wr_dis) __attribute__((unused));
|
||||
static esp_err_t encrypt_bootloader(void);
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions);
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition);
|
||||
|
||||
esp_err_t esp_flash_encrypt_check_and_update(void)
|
||||
{
|
||||
uint8_t flash_crypt_wr_dis = 0;
|
||||
uint32_t flash_crypt_cnt = 0;
|
||||
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &flash_crypt_cnt, 3);
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT, &flash_crypt_wr_dis, 1);
|
||||
|
||||
ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", flash_crypt_cnt);
|
||||
ESP_LOGV(TAG, "EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT 0x%x", flash_crypt_wr_dis);
|
||||
|
||||
if (__builtin_parity(flash_crypt_cnt) == 1) {
|
||||
/* Flash is already encrypted */
|
||||
int left = (flash_crypt_cnt == 1) ? 1 : 0;
|
||||
if (flash_crypt_wr_dis) {
|
||||
left = 0; /* can't update FLASH_CRYPT_CNT, no more flashes */
|
||||
}
|
||||
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
|
||||
return ESP_OK;
|
||||
} else {
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
/* Flash is not encrypted, so encrypt it! */
|
||||
return encrypt_flash_contents(flash_crypt_cnt, flash_crypt_wr_dis);
|
||||
#else
|
||||
ESP_LOGE(TAG, "flash encryption is not enabled, and SECURE_FLASH_REQUIRE_ALREADY_ENABLED "
|
||||
"is set, refusing to boot.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
#endif // CONFIG_SECURE_FLASH_REQUIRE_ALREADY_ENABLED
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static bool s_key_dis_read(ets_efuse_block_t block)
|
||||
{
|
||||
// TODO: eFuse support on ESP32-S3
|
||||
// unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0;
|
||||
// return REG_GET_FIELD(EFUSE_RD_REPEAT_DATA0_REG, EFUSE_RD_DIS) & (EFUSE_RD_DIS_KEY0 << key_num);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool s_key_dis_write(ets_efuse_block_t block)
|
||||
{
|
||||
// TODO: eFuse support on ESP32-S3
|
||||
// unsigned key_num = block - ETS_EFUSE_BLOCK_KEY0;
|
||||
// return REG_GET_FIELD(EFUSE_RD_WR_DIS_REG, EFUSE_WR_DIS) & (EFUSE_WR_DIS_KEY0 << key_num);
|
||||
return true;
|
||||
}
|
||||
|
||||
static esp_err_t check_and_generate_encryption_keys(void)
|
||||
{
|
||||
esp_err_t err = ESP_ERR_INVALID_STATE;
|
||||
ets_efuse_block_t aes_128_key_block;
|
||||
ets_efuse_block_t aes_256_key_block_1;
|
||||
ets_efuse_block_t aes_256_key_block_2;
|
||||
|
||||
bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block);
|
||||
bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, &aes_256_key_block_1);
|
||||
bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, &aes_256_key_block_2);
|
||||
bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2);
|
||||
bool dis_write = false;
|
||||
bool dis_read = false;
|
||||
|
||||
// If there are keys set, they must be write and read protected!
|
||||
if(has_key && has_aes128) {
|
||||
dis_write = s_key_dis_write(aes_128_key_block);
|
||||
dis_read = s_key_dis_read(aes_128_key_block);
|
||||
} else if (has_key && has_aes256_1 && has_aes256_2) {
|
||||
dis_write = s_key_dis_write(aes_256_key_block_1) && s_key_dis_write(aes_256_key_block_2);
|
||||
dis_read = s_key_dis_read(aes_256_key_block_1) && s_key_dis_read(aes_256_key_block_2);
|
||||
}
|
||||
|
||||
if (!has_key && (has_aes256_1 || has_aes256_2)) {
|
||||
ESP_LOGE(TAG, "Invalid efuse key blocks: Both AES-256 key blocks must be set.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if(has_key && (!dis_read || !dis_write)) {
|
||||
ESP_LOGE(TAG, "Invalid key state, a key was set but not read and write protected.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if(!has_key && !dis_write && !dis_read) {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256
|
||||
const unsigned BLOCKS_NEEDED = 2;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2;
|
||||
#else
|
||||
const unsigned BLOCKS_NEEDED = 1;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
#endif
|
||||
|
||||
if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) {
|
||||
ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) {
|
||||
uint32_t buf[8] = {0};
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
ets_efuse_block_t block = ets_efuse_find_unused_key_block();
|
||||
ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d",
|
||||
block - ETS_EFUSE_BLOCK_KEY0, purpose);
|
||||
|
||||
/* Note: everything else in this function is deferred as a batch write, but we write the
|
||||
key (and write protect it) immediately as it's too fiddly to manage unused key blocks, etc.
|
||||
in bootloader size footprint otherwise. */
|
||||
int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf));
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.",
|
||||
block, purpose);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* assuming numbering of esp_efuse_block_t matches ets_efuse_block_t */
|
||||
_Static_assert((int)EFUSE_BLK_KEY0 == (int)ETS_EFUSE_BLOCK_KEY0, "esp_efuse_block_t doesn't match ets_efuse_block_t");
|
||||
_Static_assert((int)EFUSE_BLK_KEY1 == (int)ETS_EFUSE_BLOCK_KEY1, "esp_efuse_block_t doesn't match ets_efuse_block_t");
|
||||
_Static_assert((int)EFUSE_BLK_KEY2 == (int)ETS_EFUSE_BLOCK_KEY2, "esp_efuse_block_t doesn't match ets_efuse_block_t");
|
||||
_Static_assert((int)EFUSE_BLK_KEY3 == (int)ETS_EFUSE_BLOCK_KEY3, "esp_efuse_block_t doesn't match ets_efuse_block_t");
|
||||
_Static_assert((int)EFUSE_BLK_KEY4 == (int)ETS_EFUSE_BLOCK_KEY4, "esp_efuse_block_t doesn't match ets_efuse_block_t");
|
||||
_Static_assert((int)EFUSE_BLK_KEY5 == (int)ETS_EFUSE_BLOCK_KEY5, "esp_efuse_block_t doesn't match ets_efuse_block_t");
|
||||
|
||||
// protect this block against reading after key is set (writing is done by ets_efuse_write_key)
|
||||
err = esp_efuse_set_read_protect(block);
|
||||
if(err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to set read protect to efuse block %d. Can't continue.", block);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "Key generation complete");
|
||||
return ESP_OK;
|
||||
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Using pre-existing key in efuse");
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
|
||||
|
||||
esp_err_t key_state = check_and_generate_encryption_keys();
|
||||
if(key_state != ESP_OK) {
|
||||
esp_efuse_batch_write_cancel();
|
||||
return key_state;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
|
||||
ESP_LOGI(TAG, "Disable UART bootloader encryption...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader encryption");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_FLASH_UART_BOOTLOADER_ALLOW_CACHE
|
||||
ESP_LOGI(TAG, "Disable UART bootloader cache...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_DCACHE);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling UART bootloader cache - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable JTAG...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
|
||||
|
||||
esp_err_t err = esp_efuse_batch_write_commit();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Encrypt all flash data that should be encrypted */
|
||||
static esp_err_t encrypt_flash_contents(uint32_t spi_boot_crypt_cnt, bool flash_crypt_wr_dis)
|
||||
{
|
||||
esp_err_t err;
|
||||
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
|
||||
int num_partitions;
|
||||
|
||||
/* If the last spi_boot_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data SPI_BOOT_CRYPT_CNT 0x%02x write disabled %d", spi_boot_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
if (spi_boot_crypt_cnt == 0) {
|
||||
/* Very first flash of encrypted data: generate keys, etc. */
|
||||
err = initialise_flash_encryption();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
err = encrypt_bootloader();
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
err = encrypt_and_load_partition_table(partition_table, &num_partitions);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Now iterate the just-loaded partition table, looking for entries to encrypt */
|
||||
for (int i = 0; i < num_partitions; i++) {
|
||||
err = encrypt_partition(i, &partition_table[i]);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "All flash regions checked for encryption pass");
|
||||
|
||||
/* Set least significant 0-bit in spi_boot_crypt_cnt */
|
||||
int ffs_inv = __builtin_ffs((~spi_boot_crypt_cnt) & 0x7);
|
||||
/* ffs_inv shouldn't be zero, as zero implies spi_boot_crypt_cnt == 0xFF */
|
||||
uint32_t new_spi_boot_crypt_cnt = (1 << (ffs_inv - 1));
|
||||
ESP_LOGD(TAG, "SPI_BOOT_CRYPT_CNT 0x%x -> 0x%x", spi_boot_crypt_cnt, new_spi_boot_crypt_cnt + spi_boot_crypt_cnt);
|
||||
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_SPI_BOOT_CRYPT_CNT, &new_spi_boot_crypt_cnt, 3);
|
||||
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_MODE_RELEASE
|
||||
//Secure SPI boot cnt after its update if needed.
|
||||
const uint32_t spi_boot_cnt_wr_dis = 1;
|
||||
ESP_LOGI(TAG, "Write protecting SPI_CRYPT_CNT eFuse");
|
||||
esp_efuse_write_field_blob(ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT, &spi_boot_cnt_wr_dis, 1);
|
||||
#endif
|
||||
ESP_LOGI(TAG, "Flash encryption completed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_bootloader(void)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t image_length;
|
||||
/* Check for plaintext bootloader (verification will fail if it's already encrypted) */
|
||||
if (esp_image_verify_bootloader(&image_length) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "bootloader is plaintext. Encrypting...");
|
||||
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
// Account for the signature sector after the bootloader
|
||||
image_length = (image_length + FLASH_SECTOR_SIZE - 1) & ~(FLASH_SECTOR_SIZE - 1);
|
||||
image_length += FLASH_SECTOR_SIZE;
|
||||
if (ESP_BOOTLOADER_OFFSET + image_length > ESP_PARTITION_TABLE_OFFSET) {
|
||||
ESP_LOGE(TAG, "Bootloader is too large to fit Secure Boot V2 signature sector and partition table (configured offset 0x%x)", ESP_PARTITION_TABLE_OFFSET);
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
#endif // CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
|
||||
err = esp_flash_encrypt_region(ESP_BOOTLOADER_OFFSET, image_length);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt bootloader in place: 0x%x", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "bootloader encrypted successfully");
|
||||
return err;
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "no valid bootloader was found");
|
||||
return ESP_ERR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err;
|
||||
/* Check for plaintext partition table */
|
||||
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data");
|
||||
return err;
|
||||
}
|
||||
if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Valid partition table loded */
|
||||
ESP_LOGI(TAG, "partition table encrypted and loaded successfully");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
static esp_err_t encrypt_partition(int index, const esp_partition_info_t *partition)
|
||||
{
|
||||
esp_err_t err;
|
||||
bool should_encrypt = (partition->flags & PART_FLAG_ENCRYPTED);
|
||||
|
||||
if (partition->type == PART_TYPE_APP) {
|
||||
/* check if the partition holds a valid unencrypted app */
|
||||
esp_image_metadata_t data_ignored;
|
||||
err = esp_image_verify(ESP_IMAGE_VERIFY,
|
||||
&partition->pos,
|
||||
&data_ignored);
|
||||
should_encrypt = (err == ESP_OK);
|
||||
} else if (partition->type == PART_TYPE_DATA && partition->subtype == PART_SUBTYPE_DATA_OTA) {
|
||||
/* check if we have ota data partition and the partition should be encrypted unconditionally */
|
||||
should_encrypt = true;
|
||||
}
|
||||
|
||||
if (!should_encrypt) {
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
/* should_encrypt */
|
||||
ESP_LOGI(TAG, "Encrypting partition %d at offset 0x%x (length 0x%x)...", index, partition->pos.offset, partition->pos.size);
|
||||
|
||||
err = esp_flash_encrypt_region(partition->pos.offset, partition->pos.size);
|
||||
ESP_LOGI(TAG, "Done encrypting");
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition %d", index);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_flash_encrypt_region(uint32_t src_addr, size_t data_length)
|
||||
{
|
||||
esp_err_t err;
|
||||
uint32_t buf[FLASH_SECTOR_SIZE / sizeof(uint32_t)];
|
||||
|
||||
if (src_addr % FLASH_SECTOR_SIZE != 0) {
|
||||
ESP_LOGE(TAG, "esp_flash_encrypt_region bad src_addr 0x%x",src_addr);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
||||
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_feed(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
|
||||
uint32_t sec_start = i + src_addr;
|
||||
err = bootloader_flash_read(sec_start, buf, FLASH_SECTOR_SIZE, false);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_erase_sector(sec_start / FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
err = bootloader_flash_write(sec_start, buf, FLASH_SECTOR_SIZE, true);
|
||||
if (err != ESP_OK) {
|
||||
goto flash_failed;
|
||||
}
|
||||
}
|
||||
return ESP_OK;
|
||||
|
||||
flash_failed:
|
||||
ESP_LOGE(TAG, "flash operation failed: 0x%x", err);
|
||||
return err;
|
||||
}
|
325
components/bootloader_support/src/esp32s3/secure_boot.c
Normal file
325
components/bootloader_support/src/esp32s3/secure_boot.c
Normal file
@ -0,0 +1,325 @@
|
||||
// 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.
|
||||
#include <string.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
|
||||
#include "esp_rom_crc.h"
|
||||
#include "esp_efuse.h"
|
||||
#include "esp_efuse_table.h"
|
||||
|
||||
#include "esp32s3/rom/efuse.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
|
||||
static const char *TAG = "secure_boot_v2";
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
#define SIG_BLOCK_MAGIC_BYTE 0xe7
|
||||
#define CRC_SIGN_BLOCK_LEN 1196
|
||||
#define SIG_BLOCK_PADDING 4096
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
/* A signature block is valid when it has correct magic byte, crc and image digest. */
|
||||
static esp_err_t validate_signature_block(const ets_secure_boot_sig_block_t *block, int block_num, const uint8_t *image_digest)
|
||||
{
|
||||
uint32_t crc = esp_rom_crc32_le(0, (uint8_t *)block, CRC_SIGN_BLOCK_LEN);
|
||||
if (block->magic_byte != SIG_BLOCK_MAGIC_BYTE) {
|
||||
// All signature blocks have been parsed, no new signature block present.
|
||||
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (block->block_crc != crc) {
|
||||
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
|
||||
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
ESP_LOGD(TAG, "valid signature block(%d) found", block_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Structure to hold public key digests calculated from the signature blocks of a single image.
|
||||
|
||||
Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
|
||||
includes a public key.
|
||||
|
||||
Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
|
||||
in this data structure the digest data is included.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t key_digests[SECURE_BOOT_NUM_BLOCKS][DIGEST_LEN];
|
||||
unsigned num_digests; /* Number of valid digests, starting at index 0 */
|
||||
} image_sig_public_key_digests_t;
|
||||
|
||||
/* Generates the public key digests of the valid public keys in an image's
|
||||
signature block, verifies each signature, and stores the key digests in the
|
||||
public_key_digests structure.
|
||||
|
||||
@param flash_offset Image offset in flash
|
||||
@param flash_size Image size in flash (not including signature block)
|
||||
@param[out] public_key_digests Pointer to structure to hold the key digests for valid sig blocks
|
||||
|
||||
|
||||
Note that this function doesn't read any eFuses, so it doesn't know if the
|
||||
keys are ultimately trusted by the hardware or not
|
||||
|
||||
@return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
|
||||
- ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
|
||||
*/
|
||||
static esp_err_t s_calculate_image_public_key_digests(uint32_t flash_offset, uint32_t flash_size, image_sig_public_key_digests_t *public_key_digests)
|
||||
{
|
||||
esp_err_t ret;
|
||||
uint8_t image_digest[DIGEST_LEN] = {0};
|
||||
uint8_t __attribute__((aligned(4))) key_digest[DIGEST_LEN] = {0};
|
||||
size_t sig_block_addr = flash_offset + ALIGN_UP(flash_size, FLASH_SECTOR_SIZE);
|
||||
|
||||
ESP_LOGD(TAG, "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)", flash_offset, sig_block_addr);
|
||||
|
||||
bzero(public_key_digests, sizeof(image_sig_public_key_digests_t));
|
||||
|
||||
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "error generating image digest, %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "reading signatures");
|
||||
const ets_secure_boot_signature_t *signatures = bootloader_mmap(sig_block_addr, sizeof(ets_secure_boot_signature_t));
|
||||
if (signatures == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
const ets_secure_boot_sig_block_t *block = &signatures->block[i];
|
||||
|
||||
ret = validate_signature_block(block, i, image_digest);
|
||||
if (ret != ESP_OK) {
|
||||
ret = ESP_OK; // past the last valid signature block
|
||||
break;
|
||||
}
|
||||
|
||||
/* Generating the SHA of the public key components in the signature block */
|
||||
bootloader_sha256_handle_t sig_block_sha;
|
||||
sig_block_sha = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sig_block_sha, &block->key, sizeof(block->key));
|
||||
bootloader_sha256_finish(sig_block_sha, key_digest);
|
||||
|
||||
// Check we can verify the image using this signature and this key
|
||||
uint8_t temp_verified_digest[DIGEST_LEN];
|
||||
bool verified = ets_rsa_pss_verify(&block->key, block->signature, image_digest, temp_verified_digest);
|
||||
|
||||
if (!verified) {
|
||||
/* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,
|
||||
so this is a fatal error
|
||||
*/
|
||||
ret = ESP_FAIL;
|
||||
ESP_LOGE(TAG, "Secure boot key (%d) verification failed.", i);
|
||||
break;
|
||||
}
|
||||
ESP_LOGD(TAG, "Signature block (%d) is verified", i);
|
||||
/* Copy the key digest to the buffer provided by the caller */
|
||||
memcpy((void *)public_key_digests->key_digests[i], key_digest, DIGEST_LEN);
|
||||
public_key_digests->num_digests++;
|
||||
}
|
||||
|
||||
if (ret == ESP_OK && public_key_digests->num_digests > 0) {
|
||||
ESP_LOGI(TAG, "Digests successfully calculated, %d valid signatures (image offset 0x%x)",
|
||||
public_key_digests->num_digests, flash_offset);
|
||||
}
|
||||
|
||||
bootloader_munmap(signatures);
|
||||
return ret;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
|
||||
{
|
||||
ESP_LOGI(TAG, "enabling secure boot v2 - ESP32-S2...");
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t ret;
|
||||
/* Verify the bootloader */
|
||||
esp_image_metadata_t bootloader_data = { 0 };
|
||||
ret = esp_image_verify_bootloader_data(&bootloader_data);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "bootloader image appears invalid! error %d", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Check if secure boot digests are present */
|
||||
bool has_secure_boot_digest = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL);
|
||||
has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL);
|
||||
has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL);
|
||||
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
if (!has_secure_boot_digest) {
|
||||
image_sig_public_key_digests_t boot_key_digests = {0};
|
||||
image_sig_public_key_digests_t app_key_digests = {0};
|
||||
|
||||
/* Generate the bootloader public key digests */
|
||||
ret = s_calculate_image_public_key_digests(bootloader_data.start_addr, bootloader_data.image_len - SIG_BLOCK_PADDING, &boot_key_digests);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Bootloader signature block is invalid");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (boot_key_digests.num_digests == 0) {
|
||||
ESP_LOGE(TAG, "No valid bootloader signature blocks found.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_LOGI(TAG, "%d signature block(s) found appended to the bootloader.", boot_key_digests.num_digests);
|
||||
|
||||
int unused_key_slots = ets_efuse_count_unused_key_blocks();
|
||||
if (boot_key_digests.num_digests > unused_key_slots) {
|
||||
ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots(%d).", boot_key_digests.num_digests, unused_key_slots);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < boot_key_digests.num_digests; i++) {
|
||||
ets_efuse_block_t block;
|
||||
const uint32_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
|
||||
ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 };
|
||||
|
||||
block = ets_efuse_find_unused_key_block();
|
||||
if (block == ETS_EFUSE_BLOCK_MAX) {
|
||||
ESP_LOGE(TAG, "No more unused key blocks available.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int r = ets_efuse_write_key(block, secure_boot_key_purpose[i], boot_key_digests.key_digests[i], DIGEST_LEN);
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", block, secure_boot_key_purpose[i]);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Note: write key will write protect both the block and the purpose eFuse, always
|
||||
}
|
||||
|
||||
/* Generate the application public key digests */
|
||||
ret = s_calculate_image_public_key_digests(image_data->start_addr, image_data->image_len - SIG_BLOCK_PADDING, &app_key_digests);
|
||||
if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "App signature block is invalid.");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (app_key_digests.num_digests == 0) {
|
||||
ESP_LOGE(TAG, "No valid applications signature blocks found.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "%d signature block(s) found appended to the app.", app_key_digests.num_digests);
|
||||
if (app_key_digests.num_digests > boot_key_digests.num_digests) {
|
||||
ESP_LOGW(TAG, "App has %d signature blocks but bootloader only has %d. Some keys missing from bootloader?");
|
||||
}
|
||||
|
||||
/* Confirm if at least one public key from the application matches a public key in the bootloader
|
||||
(Also, ensure if that public revoke bit is not set for the matched key) */
|
||||
bool match = false;
|
||||
const uint32_t revoke_bits[SECURE_BOOT_NUM_BLOCKS] = { EFUSE_SECURE_BOOT_KEY_REVOKE0,
|
||||
EFUSE_SECURE_BOOT_KEY_REVOKE1, EFUSE_SECURE_BOOT_KEY_REVOKE2 };
|
||||
|
||||
for (int i = 0; i < boot_key_digests.num_digests; i++) {
|
||||
|
||||
if (REG_GET_BIT(EFUSE_RD_REPEAT_DATA1_REG, revoke_bits[i])) {
|
||||
ESP_LOGI(TAG, "Key block(%d) has been revoked.", i);
|
||||
continue; // skip if the key block is revoked
|
||||
}
|
||||
|
||||
for (int j = 0; j < app_key_digests.num_digests; j++) {
|
||||
if (!memcmp(boot_key_digests.key_digests[i], app_key_digests.key_digests[j], DIGEST_LEN)) {
|
||||
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
|
||||
match = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (match == false) {
|
||||
ESP_LOGE(TAG, "No application key digest matches the bootloader key digest.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Revoke the empty signature blocks */
|
||||
if (boot_key_digests.num_digests < SECURE_BOOT_NUM_BLOCKS) {
|
||||
/* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */
|
||||
for (uint8_t i = boot_key_digests.num_digests; i < SECURE_BOOT_NUM_BLOCKS; i++) {
|
||||
ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i);
|
||||
ets_secure_boot_revoke_public_key_digest(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t err = esp_efuse_batch_write_begin();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGI(TAG, "Error batch programming security eFuses.");
|
||||
return err;
|
||||
}
|
||||
|
||||
__attribute__((unused)) static const uint8_t enable = 1;
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_BOOT_REMAP);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
|
||||
|
||||
#ifdef CONFIG_SECURE_ENABLE_SECURE_ROM_DL_MODE
|
||||
ESP_LOGI(TAG, "Enabling Security download mode...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not enabling Security download mode - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_SECURE_BOOT_ALLOW_JTAG
|
||||
ESP_LOGI(TAG, "Disable hardware & software JTAG...");
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SOFT_DIS_JTAG);
|
||||
#else
|
||||
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
|
||||
#endif
|
||||
|
||||
esp_efuse_write_field_bit(ESP_EFUSE_SECURE_BOOT_EN);
|
||||
|
||||
err = esp_efuse_batch_write_commit();
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGI(TAG, "Error programming security eFuses.");
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
|
||||
assert(ets_efuse_secure_boot_aggressive_revoke_enabled());
|
||||
#endif
|
||||
|
||||
assert(esp_rom_efuse_is_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -0,0 +1,93 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_fault.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
uint8_t verified_digest[DIGEST_LEN] = { 0 }; /* Note: this function doesn't do any anti-FI checks on this buffer */
|
||||
const uint8_t *data;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
/* Padding to round off the input to the nearest 4k boundary */
|
||||
int padded_length = ALIGN_UP(length, FLASH_SECTOR_SIZE);
|
||||
ESP_LOGD(TAG, "verifying src_addr 0x%x length", src_addr, padded_length);
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
if (data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
/* Calculate digest of main image */
|
||||
esp_err_t err = bootloader_sha256_flash_contents(src_addr, padded_length, digest);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Digest calculation failed 0x%x, 0x%x", src_addr, padded_length);
|
||||
bootloader_munmap(data);
|
||||
return err;
|
||||
}
|
||||
|
||||
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
|
||||
int r = esp_secure_boot_verify_rsa_signature_block(sig, digest, verified_digest);
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_rsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys;
|
||||
ets_secure_boot_key_digests_t trusted_key_copies[2];
|
||||
ETS_STATUS r;
|
||||
ets_secure_boot_status_t sb_result;
|
||||
|
||||
memset(&trusted_keys, 0, sizeof(ets_secure_boot_key_digests_t));
|
||||
memset(trusted_key_copies, 0, 2 * sizeof(ets_secure_boot_key_digests_t));
|
||||
|
||||
if (!esp_secure_boot_enabled()) {
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != ETS_OK) {
|
||||
ESP_LOGI(TAG, "Could not read secure boot digests!");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Create the copies for FI checks (assuming result is ETS_OK, if it's not then it'll fail the fault check anyhow)
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[0]);
|
||||
ets_secure_boot_read_key_digests(&trusted_key_copies[1]);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[0], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
ESP_FAULT_ASSERT(memcmp(&trusted_keys, &trusted_key_copies[1], sizeof(ets_secure_boot_key_digests_t)) == 0);
|
||||
|
||||
ESP_LOGI(TAG, "Verifying with RSA-PSS boot...");
|
||||
sb_result = ets_secure_boot_verify_signature(sig_block, image_digest, &trusted_keys, verified_digest);
|
||||
return (sb_result == SB_SUCCESS) ? ESP_OK : ESP_FAIL;
|
||||
}
|
@ -32,6 +32,9 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/rtc.h"
|
||||
#include "esp32s2/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#include "esp32s3/rom/secure_boot.h"
|
||||
#endif
|
||||
|
||||
/* Checking signatures as part of verifying images is necessary:
|
||||
@ -209,7 +212,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
bool verify_sha;
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
verify_sha = true;
|
||||
#else // ESP32, or ESP32S2 without secure boot enabled
|
||||
#else // Secure boot not enabled
|
||||
verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET);
|
||||
#endif
|
||||
|
||||
|
@ -26,6 +26,9 @@
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT
|
||||
#define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#define CRYPT_CNT ESP_EFUSE_SPI_BOOT_CRYPT_CNT
|
||||
#define WR_DIS_CRYPT_CNT ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
|
@ -15,10 +15,12 @@
|
||||
#include <stdint.h>
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_flash_priv.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
@ -28,7 +30,6 @@
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
static const char *TAG = "qio_mode";
|
||||
@ -194,7 +195,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int wp_pin = bootloader_flash_get_wp_pin();
|
||||
esp_rom_spiflash_select_qio_pins(wp_pin, spiconfig);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_rom_spiflash_select_qio_pins(esp_rom_efuse_get_flash_wp_gpio(), spiconfig);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
|
@ -1,3 +1,5 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
set(srcs
|
||||
"adc_common.c"
|
||||
"dac_common.c"
|
||||
@ -23,9 +25,9 @@ set(srcs
|
||||
"twai.c"
|
||||
"uart.c")
|
||||
|
||||
set(includes "include")
|
||||
set(includes "include" "${target}/include")
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
if(${target} STREQUAL "esp32")
|
||||
# SDMMC and MCPWM are in ESP32 only.
|
||||
list(APPEND srcs "mcpwm.c"
|
||||
"sdio_slave.c"
|
||||
@ -37,7 +39,7 @@ if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND includes "esp32/include")
|
||||
endif()
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32s2")
|
||||
if(${target} STREQUAL "esp32s2")
|
||||
list(APPEND srcs "esp32s2/rtc_tempsensor.c"
|
||||
"esp32s2/touch_sensor.c"
|
||||
"esp32s2/adc.c"
|
||||
|
@ -82,7 +82,7 @@ static _lock_t adc2_wifi_lock;
|
||||
#define ADC2_WIFI_LOCK_TRY_ACQUIRE() _lock_try_acquire( &adc2_wifi_lock )
|
||||
#define ADC2_WIFI_LOCK_CHECK() ((uint32_t *)adc2_wifi_lock != NULL)
|
||||
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
#define ADC2_WIFI_LOCK_ACQUIRE()
|
||||
#define ADC2_WIFI_LOCK_RELEASE()
|
||||
@ -101,7 +101,7 @@ static _lock_t adc1_dma_lock;
|
||||
#define ADC1_DMA_LOCK_ACQUIRE() _lock_acquire( &adc1_dma_lock )
|
||||
#define ADC1_DMA_LOCK_RELEASE() _lock_release( &adc1_dma_lock )
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
static esp_pm_lock_handle_t s_adc2_arbiter_lock;
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
@ -209,7 +209,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ADC_CHECK(bits < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
ADC_CHECK(bits == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
@ -231,7 +231,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_err_t adc_rtc_reset(void)
|
||||
{
|
||||
ADC_ENTER_CRITICAL();
|
||||
@ -284,7 +284,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
@ -341,13 +341,17 @@ int adc1_get_raw(adc1_channel_t channel)
|
||||
adc_power_on();
|
||||
|
||||
ADC_ENTER_CRITICAL();
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
adc_hal_hall_disable(); //Disable other peripherals.
|
||||
adc_hal_amp_disable(); //Currently the LNA is not open, close it by default.
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
adc_set_init_code(ADC_NUM_1, channel); // calibration for adc
|
||||
#endif
|
||||
adc_hal_set_controller(ADC_NUM_1, ADC_CTRL_RTC); //Set controller
|
||||
adc_hal_convert(ADC_NUM_1, channel, &adc_value); //Start conversion, For ADC1, the data always valid.
|
||||
ADC_EXIT_CRITICAL();
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
adc_hal_rtc_reset(); //Reset FSM of rtc controller
|
||||
#endif
|
||||
|
||||
@ -434,7 +438,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
|
||||
static inline void adc2_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
/* Lock APB clock. */
|
||||
if (s_adc2_arbiter_lock == NULL) {
|
||||
@ -455,7 +459,7 @@ static inline void adc2_dac_disable( adc2_channel_t channel)
|
||||
} else if ( channel == ADC2_CHANNEL_9 ) {
|
||||
dac_output_disable(DAC_CHANNEL_2);
|
||||
}
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
if ( channel == ADC2_CHANNEL_6 ) { // the same as DAC channel 1
|
||||
dac_output_disable(DAC_CHANNEL_1);
|
||||
} else if ( channel == ADC2_CHANNEL_7 ) {
|
||||
@ -478,7 +482,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
ADC_CHECK(channel < ADC2_CHANNEL_MAX, "ADC Channel Err", ESP_ERR_INVALID_ARG);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ADC_CHECK(width_bit < ADC_WIDTH_MAX, "WIDTH ERR: ESP32 support 9 ~ 12 bit width", ESP_ERR_INVALID_ARG);
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
ADC_CHECK(width_bit == ADC_WIDTH_BIT_13, "WIDTH ERR: ESP32S2 support 13 bit width", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
@ -494,12 +498,12 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
adc2_dac_disable(channel); //disable other peripherals
|
||||
#endif
|
||||
adc2_config_width(width_bit); // in critical section with whole rtc module. because the PWDET use the same registers, place it here.
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
adc_set_init_code(ADC_NUM_2, channel); // calibration for adc
|
||||
#endif
|
||||
adc_hal_set_controller(ADC_NUM_2, ADC_CTRL_RTC);// set controller
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
if (s_adc2_arbiter_lock) {
|
||||
esp_pm_lock_acquire(s_adc2_arbiter_lock);
|
||||
@ -511,7 +515,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
adc_value = -1;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
/* Release APB clock. */
|
||||
if (s_adc2_arbiter_lock) {
|
||||
@ -523,7 +527,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *
|
||||
ADC2_WIFI_LOCK_RELEASE();
|
||||
ADC2_EXIT_CRITICAL();
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
adc_rtc_reset();
|
||||
#endif
|
||||
|
||||
|
277
components/driver/esp32s3/include/driver/adc.h
Normal file
277
components/driver/esp32s3/include/driver/adc.h
Normal file
@ -0,0 +1,277 @@
|
||||
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/adc_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Common setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief Config ADC module arbiter.
|
||||
* The arbiter is to improve the use efficiency of ADC2. After the control right is robbed by the high priority,
|
||||
* the low priority controller will read the invalid ADC2 data, and the validity of the data can be judged by the flag bit in the data.
|
||||
*
|
||||
* @note Only ADC2 support arbiter.
|
||||
* @note Default priority: Wi-Fi > RTC > Digital;
|
||||
* @note In normal use, there is no need to call this interface to config arbiter.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param config Refer to `adc_arbiter_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_SUPPORTED ADC unit not support arbiter.
|
||||
*/
|
||||
esp_err_t adc_arbiter_config(adc_unit_t adc_unit, adc_arbiter_t *config);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief ADC digital controller initialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_init(void);
|
||||
|
||||
/**
|
||||
* @brief ADC digital controller deinitialization.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Setting the digital controller.
|
||||
*
|
||||
* @param config Pointer to digital controller paramter. Refer to `adc_digi_config_t`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable digital controller to trigger the measurement.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief Disable digital controller to trigger the measurement.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_stop(void);
|
||||
|
||||
/*************************************/
|
||||
/* Digital controller filter setting */
|
||||
/*************************************/
|
||||
/**
|
||||
* @brief Reset adc digital controller filter.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx);
|
||||
|
||||
/**
|
||||
* @brief Set adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Get adc digital controller filter configuration.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param config See ``adc_digi_filter_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable adc digital controller filter.
|
||||
* Filtering the ADC data to obtain smooth data at higher sampling rates.
|
||||
*
|
||||
* @note For ESP32S2, Filter IDX0/IDX1 can only be used to filter all enabled channels of ADC1/ADC2 unit at the same time.
|
||||
*
|
||||
* @param idx Filter index.
|
||||
* @param enable Enable/Disable filter.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller monitor setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Config monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param config See ``adc_digi_monitor_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable monitor of adc digital controller.
|
||||
*
|
||||
* @note For ESP32S2, The monitor will monitor all the enabled channel data of the each ADC unit at the same time.
|
||||
*
|
||||
* @param idx Monitor index.
|
||||
* @param enable True or false enable monitor.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable);
|
||||
|
||||
/**************************************/
|
||||
/* Digital controller intr setting */
|
||||
/**************************************/
|
||||
|
||||
/**
|
||||
* @brief Enable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_enable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Disable interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_disable(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt of adc digital controller by bitmask.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @param intr_mask Interrupt bitmask. See ``adc_digi_intr_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t adc_digi_intr_clear(adc_unit_t adc_unit, adc_digi_intr_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Get interrupt status mask of adc digital controller.
|
||||
*
|
||||
* @param adc_unit ADC unit.
|
||||
* @return
|
||||
* - intr Interrupt bitmask, See ``adc_digi_intr_t``.
|
||||
*/
|
||||
uint32_t adc_digi_intr_get_status(adc_unit_t adc_unit);
|
||||
|
||||
/**
|
||||
* @brief Register ADC interrupt handler, the handler is an ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
*
|
||||
* @param fn Interrupt handler function.
|
||||
* @param arg Parameter for handler function
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_NOT_FOUND Can not find the interrupt that matches the flags.
|
||||
* - ESP_ERR_INVALID_ARG Function pointer error.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_register(void (*fn)(void *), void *arg, int intr_alloc_flags);
|
||||
|
||||
/**
|
||||
* @brief Deregister ADC interrupt handler, the handler is an ISR.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG hander error.
|
||||
* - ESP_FAIL ISR not be registered.
|
||||
*/
|
||||
esp_err_t adc_digi_isr_deregister(void);
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
RTC controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Deprecated API
|
||||
---------------------------------------------------------------*/
|
||||
/**
|
||||
* @brief Set I2S data source
|
||||
*
|
||||
* @param src I2S DMA data source, I2S DMA can get data from digital signals or from ADC.
|
||||
*
|
||||
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t adc_set_i2s_data_source(adc_i2s_source_t src) __attribute__((deprecated));
|
||||
|
||||
/**
|
||||
* @brief Initialize I2S ADC mode
|
||||
*
|
||||
* @param adc_unit ADC unit index
|
||||
* @param channel ADC channel index
|
||||
*
|
||||
* @deprecated The ESP32S2 don't use I2S DMA. Call ``adc_digi_controller_config`` instead.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t adc_i2s_mode_init(adc_unit_t adc_unit, adc_channel_t channel) __attribute__((deprecated));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
80
components/driver/esp32s3/include/driver/dac.h
Normal file
80
components/driver/esp32s3/include/driver/dac.h
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "driver/dac_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/*---------------------------------------------------------------
|
||||
Digital controller setting
|
||||
---------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller initialization.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_init(void);
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller deinitialization.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Setting the DAC digital controller.
|
||||
*
|
||||
* @param cfg Pointer to digital controller paramter. See ``dac_digi_config_t``.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
*/
|
||||
esp_err_t dac_digi_controller_config(const dac_digi_config_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller start output voltage.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_start(void);
|
||||
|
||||
/**
|
||||
* @brief DAC digital controller stop output voltage.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Reset DAC digital controller FIFO.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_fifo_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Reset DAC digital controller.
|
||||
* @return
|
||||
* - ESP_OK success
|
||||
*/
|
||||
esp_err_t dac_digi_reset(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
105
components/driver/esp32s3/include/driver/temp_sensor.h
Normal file
105
components/driver/esp32s3/include/driver/temp_sensor.h
Normal file
@ -0,0 +1,105 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief temperature sensor range option.
|
||||
*/
|
||||
typedef enum {
|
||||
TSENS_DAC_L0 = 0, /*!< offset = -2, measure range: 50℃ ~ 125℃, error < 3℃. */
|
||||
TSENS_DAC_L1, /*!< offset = -1, measure range: 20℃ ~ 100℃, error < 2℃. */
|
||||
TSENS_DAC_L2, /*!< offset = 0, measure range:-10℃ ~ 80℃, error < 1℃. */
|
||||
TSENS_DAC_L3, /*!< offset = 1, measure range:-30℃ ~ 50℃, error < 2℃. */
|
||||
TSENS_DAC_L4, /*!< offset = 2, measure range:-40℃ ~ 20℃, error < 3℃. */
|
||||
TSENS_DAC_MAX,
|
||||
TSENS_DAC_DEFAULT = TSENS_DAC_L2,
|
||||
} temp_sensor_dac_offset_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration for temperature sensor reading
|
||||
*/
|
||||
typedef struct {
|
||||
temp_sensor_dac_offset_t dac_offset; /*!< The temperature measurement range is configured with a built-in temperature offset DAC. */
|
||||
uint8_t clk_div; /*!< Default: 6 */
|
||||
} temp_sensor_config_t;
|
||||
|
||||
/**
|
||||
* @brief temperature sensor default setting.
|
||||
*/
|
||||
#define TSENS_CONFIG_DEFAULT() {.dac_offset = TSENS_DAC_L2, \
|
||||
.clk_div = 6}
|
||||
|
||||
/**
|
||||
* @brief Set parameter of temperature sensor.
|
||||
* @param tsens
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens);
|
||||
|
||||
/**
|
||||
* @brief Get parameter of temperature sensor.
|
||||
* @param tsens
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens);
|
||||
|
||||
/**
|
||||
* @brief Start temperature sensor measure.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG
|
||||
*/
|
||||
esp_err_t temp_sensor_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop temperature sensor measure.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t temp_sensor_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Read temperature sensor raw data.
|
||||
* @param tsens_out Pointer to raw data, Range: 0 ~ 255
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG `tsens_out` is NULL
|
||||
* - ESP_ERR_INVALID_STATE temperature sensor dont start
|
||||
*/
|
||||
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out);
|
||||
|
||||
/**
|
||||
* @brief Read temperature sensor data that is converted to degrees Celsius.
|
||||
* @note Should not be called from interrupt.
|
||||
* @param celsius The measure output value.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG ARG is NULL.
|
||||
* - ESP_ERR_INVALID_STATE The ambient temperature is out of range.
|
||||
*/
|
||||
esp_err_t temp_sensor_read_celsius(float *celsius);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
582
components/driver/esp32s3/include/driver/touch_sensor.h
Normal file
582
components/driver/esp32s3/include/driver/touch_sensor.h
Normal file
@ -0,0 +1,582 @@
|
||||
// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "driver/touch_sensor_common.h"
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor FSM start
|
||||
* @note Start FSM after the touch sensor FSM mode is set.
|
||||
* @note Call this function will reset benchmark of all touch channels.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_fsm_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop touch sensor FSM.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_fsm_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Trigger a touch sensor measurement, only support in SW mode of FSM
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_sw_start(void);
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor times of charge and discharge and sleep time.
|
||||
* Excessive total time will slow down the touch response.
|
||||
* Too small measurement time will not be sampled enough, resulting in inaccurate measurements.
|
||||
*
|
||||
* @note The greater the duty cycle of the measurement time, the more system power is consumed.
|
||||
* @param sleep_cycle The touch sensor will sleep after each measurement.
|
||||
* sleep_cycle decide the interval between each measurement.
|
||||
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
|
||||
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
|
||||
* @param meas_times The times of charge and discharge in each measure process of touch channels.
|
||||
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
|
||||
* Recommended typical value: Modify this value to make the measurement time around 1ms.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_times);
|
||||
|
||||
/**
|
||||
* @brief Get touch sensor times of charge and discharge and sleep time
|
||||
* @param sleep_cycle Pointer to accept sleep cycle number
|
||||
* @param meas_times Pointer to accept measurement times count.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_times);
|
||||
|
||||
/**
|
||||
* @brief Set connection type of touch channel in idle status.
|
||||
* When a channel is in measurement mode, other initialized channels are in idle mode.
|
||||
* The touch channel is generally adjacent to the trace, so the connection state of the idle channel
|
||||
* affects the stability and sensitivity of the test channel.
|
||||
* The `CONN_HIGHZ`(high resistance) setting increases the sensitivity of touch channels.
|
||||
* The `CONN_GND`(grounding) setting increases the stability of touch channels.
|
||||
* @param type Select idle channel connect to high resistance state or ground.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_idle_channel_connect(touch_pad_conn_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Set connection type of touch channel in idle status.
|
||||
* When a channel is in measurement mode, other initialized channels are in idle mode.
|
||||
* The touch channel is generally adjacent to the trace, so the connection state of the idle channel
|
||||
* affects the stability and sensitivity of the test channel.
|
||||
* The `CONN_HIGHZ`(high resistance) setting increases the sensitivity of touch channels.
|
||||
* The `CONN_GND`(grounding) setting increases the stability of touch channels.
|
||||
* @param type Pointer to connection type.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_idle_channel_connect(touch_pad_conn_type_t *type);
|
||||
|
||||
/**
|
||||
* @brief Set the trigger threshold of touch sensor.
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
* The threshold is the original value of the trigger state minus the benchmark value.
|
||||
* @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be triggered.
|
||||
* @param touch_num touch pad index
|
||||
* @param threshold threshold of touch sensor. Should be less than the max change value of touch.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Get touch sensor trigger threshold
|
||||
* @param touch_num touch pad index
|
||||
* @param threshold pointer to accept threshold
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if argument is wrong
|
||||
*/
|
||||
esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold);
|
||||
|
||||
/**
|
||||
* @brief Register touch channel into touch sensor scan group.
|
||||
* The working mode of the touch sensor is cyclically scanned.
|
||||
* This function will set the scan bits according to the given bitmask.
|
||||
* @note If set this mask, the FSM timer should be stop firsty.
|
||||
* @note The touch sensor that in scan map, should be deinit GPIO function firstly by `touch_pad_io_init`.
|
||||
* @param enable_mask bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_channel_mask(uint16_t enable_mask);
|
||||
|
||||
/**
|
||||
* @brief Get the touch sensor scan group bit mask.
|
||||
* @param enable_mask Pointer to bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_channel_mask(uint16_t *enable_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear touch channel from touch sensor scan group.
|
||||
* The working mode of the touch sensor is cyclically scanned.
|
||||
* This function will clear the scan bits according to the given bitmask.
|
||||
* @note If clear all mask, the FSM timer should be stop firsty.
|
||||
* @param enable_mask bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_clear_channel_mask(uint16_t enable_mask);
|
||||
|
||||
/**
|
||||
* @brief Configure parameter for each touch channel.
|
||||
* @note Touch num 0 is denoise channel, please use `touch_pad_denoise_enable` to set denoise function
|
||||
* @param touch_num touch pad index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG if argument wrong
|
||||
* - ESP_FAIL if touch pad not initialized
|
||||
*/
|
||||
esp_err_t touch_pad_config(touch_pad_t touch_num);
|
||||
|
||||
/**
|
||||
* @brief Reset the FSM of touch module.
|
||||
* @note Call this function after `touch_pad_fsm_stop`.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Get the current measure channel.
|
||||
* @note Should be called when touch sensor measurement is in cyclic scan mode.
|
||||
* @return
|
||||
* - touch channel number
|
||||
*/
|
||||
touch_pad_t touch_pad_get_current_meas_channel(void);
|
||||
|
||||
/**
|
||||
* @brief Get the touch sensor interrupt status mask.
|
||||
* @return
|
||||
* - touch interrupt bit
|
||||
*/
|
||||
uint32_t touch_pad_read_intr_status_mask(void);
|
||||
|
||||
/**
|
||||
* @brief Enable touch sensor interrupt by bitmask.
|
||||
* @param int_mask Pad mask to enable interrupts
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_intr_enable(touch_pad_intr_mask_t int_mask);
|
||||
|
||||
/**
|
||||
* @brief Disable touch sensor interrupt by bitmask.
|
||||
* @param int_mask Pad mask to disable interrupts
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_intr_disable(touch_pad_intr_mask_t int_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear touch sensor interrupt by bitmask.
|
||||
* @param int_mask Pad mask to clear interrupts
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_intr_clear(touch_pad_intr_mask_t int_mask);
|
||||
|
||||
/**
|
||||
* @brief Register touch-pad ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
* @param fn Pointer to ISR handler
|
||||
* @param arg Parameter for ISR
|
||||
* @param intr_mask Enable touch sensor interrupt handler by bitmask.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Arguments error
|
||||
* - ESP_ERR_NO_MEM No memory
|
||||
*/
|
||||
esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_mask_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable the timeout check and set timeout threshold for all touch sensor channels measurements.
|
||||
* If enable: When the touch reading of a touch channel exceeds the measurement threshold, a timeout interrupt will be generated.
|
||||
* If disable: the FSM does not check if the channel under measurement times out.
|
||||
*
|
||||
* @note The threshold compared with touch readings.
|
||||
* @note In order to avoid abnormal short circuit of some touch channels. This function should be turned on.
|
||||
* Ensure the normal operation of other touch channels.
|
||||
*
|
||||
* @param enable true(default): Enable the timeout check; false: Disable the timeout check.
|
||||
* @param threshold For all channels, the maximum value that will not be exceeded during normal operation.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_timeout_set(bool enable, uint32_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Call this interface after timeout to make the touch channel resume normal work. Point on the next channel to measure.
|
||||
* If this API is not called, the touch FSM will stop the measurement after timeout interrupt.
|
||||
*
|
||||
* @note Call this API after finishes the exception handling by user.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_timeout_resume(void);
|
||||
|
||||
/**
|
||||
* @brief get raw data of touch sensor.
|
||||
* @note After the initialization is complete, the "raw_data" is max value. You need to wait for a measurement
|
||||
* cycle before you can read the correct touch value.
|
||||
* @param touch_num touch pad index
|
||||
* @param raw_data pointer to accept touch sensor value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Touch channel 0 haven't this parameter.
|
||||
*/
|
||||
|
||||
esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint32_t *raw_data);
|
||||
|
||||
/**
|
||||
* @brief get benchmark of touch sensor.
|
||||
* @note After initialization, the benchmark value is the maximum during the first measurement period.
|
||||
* @param touch_num touch pad index
|
||||
* @param benchmark pointer to accept touch sensor benchmark value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Touch channel 0 haven't this parameter.
|
||||
*/
|
||||
esp_err_t touch_pad_read_benchmark(touch_pad_t touch_num, uint32_t *benchmark);
|
||||
|
||||
/**
|
||||
* @brief Get smoothed data that obtained by filtering the raw data.
|
||||
*
|
||||
* @param touch_num touch pad index
|
||||
* @param smooth pointer to smoothed data
|
||||
*/
|
||||
esp_err_t touch_pad_filter_read_smooth(touch_pad_t touch_num, uint32_t *smooth);
|
||||
|
||||
/**
|
||||
* @brief Force reset benchmark to raw data of touch sensor.
|
||||
* @param touch_num touch pad index
|
||||
* - TOUCH_PAD_MAX Reset basaline of all channels
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_reset_benchmark(touch_pad_t touch_num);
|
||||
|
||||
/**
|
||||
* @brief set parameter of touch sensor filter and detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @param filter_info select filter type and threshold of detection algorithm
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_set_config(touch_filter_config_t *filter_info);
|
||||
|
||||
/**
|
||||
* @brief get parameter of touch sensor filter and detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @param filter_info select filter type and threshold of detection algorithm
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_get_config(touch_filter_config_t *filter_info);
|
||||
|
||||
/**
|
||||
* @brief enable touch sensor filter for detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_enable(void);
|
||||
|
||||
/**
|
||||
* @brief disable touch sensor filter for detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_disable(void);
|
||||
|
||||
/**
|
||||
* @brief set parameter of denoise pad (TOUCH_PAD_NUM0).
|
||||
* T0 is an internal channel that does not have a corresponding external GPIO.
|
||||
* T0 will work simultaneously with the measured channel Tn. Finally, the actual
|
||||
* measured value of Tn is the value after subtracting lower bits of T0.
|
||||
* The noise reduction function filters out interference introduced simultaneously on all channels,
|
||||
* such as noise introduced by power supplies and external EMI.
|
||||
* @param denoise parameter of denoise
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_set_config(touch_pad_denoise_t *denoise);
|
||||
|
||||
/**
|
||||
* @brief get parameter of denoise pad (TOUCH_PAD_NUM0).
|
||||
* @param denoise Pointer to parameter of denoise
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_get_config(touch_pad_denoise_t *denoise);
|
||||
|
||||
/**
|
||||
* @brief enable denoise function.
|
||||
* T0 is an internal channel that does not have a corresponding external GPIO.
|
||||
* T0 will work simultaneously with the measured channel Tn. Finally, the actual
|
||||
* measured value of Tn is the value after subtracting lower bits of T0.
|
||||
* The noise reduction function filters out interference introduced simultaneously on all channels,
|
||||
* such as noise introduced by power supplies and external EMI.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_enable(void);
|
||||
|
||||
/**
|
||||
* @brief disable denoise function.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Get denoise measure value (TOUCH_PAD_NUM0).
|
||||
* @param data Pointer to receive denoise value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_read_data(uint32_t *data);
|
||||
|
||||
/**
|
||||
* @brief set parameter of waterproof function.
|
||||
*
|
||||
* The waterproof function includes a shielded channel (TOUCH_PAD_NUM14) and a guard channel.
|
||||
* Guard pad is used to detect the large area of water covering the touch panel.
|
||||
* Shield pad is used to shield the influence of water droplets covering the touch panel.
|
||||
* It is generally designed as a grid and is placed around the touch buttons.
|
||||
*
|
||||
* @param waterproof parameter of waterproof
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_set_config(touch_pad_waterproof_t *waterproof);
|
||||
|
||||
/**
|
||||
* @brief get parameter of waterproof function.
|
||||
* @param waterproof parameter of waterproof
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_get_config(touch_pad_waterproof_t *waterproof);
|
||||
|
||||
/**
|
||||
* @brief Enable parameter of waterproof function.
|
||||
* Should be called after function ``touch_pad_waterproof_set_config``.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Disable parameter of waterproof function.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Enable/disable proximity function of touch channels.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
*
|
||||
* @note Supports up to three touch channels configured as proximity sensors.
|
||||
* @param touch_num touch pad index
|
||||
* @param enabled true: enable the proximity function; false: disable the proximity function
|
||||
* @return
|
||||
* - ESP_OK: Configured correctly.
|
||||
* - ESP_ERR_INVALID_ARG: Touch channel number error.
|
||||
* - ESP_ERR_NOT_SUPPORTED: Don't support configured.
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_enable(touch_pad_t touch_num, bool enabled);
|
||||
|
||||
/**
|
||||
* @brief Set measure count of proximity channel.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
*
|
||||
* @note All proximity channels use the same `count` value. So please pass the parameter `TOUCH_PAD_MAX`.
|
||||
* @param touch_num Touch pad index. In this version, pass the parameter `TOUCH_PAD_MAX`.
|
||||
* @param count The cumulative times of measurements for proximity pad. Range: 0 ~ 255.
|
||||
* @return
|
||||
* - ESP_OK: Configured correctly.
|
||||
* - ESP_ERR_INVALID_ARG: Touch channel number error.
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_set_count(touch_pad_t touch_num, uint32_t count);
|
||||
|
||||
/**
|
||||
* @brief Get measure count of proximity channel.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
*
|
||||
* @note All proximity channels use the same `count` value. So please pass the parameter `TOUCH_PAD_MAX`.
|
||||
* @param touch_num Touch pad index. In this version, pass the parameter `TOUCH_PAD_MAX`.
|
||||
* @param count The cumulative times of measurements for proximity pad. Range: 0 ~ 255.
|
||||
* @return
|
||||
* - ESP_OK: Configured correctly.
|
||||
* - ESP_ERR_INVALID_ARG: Touch channel number error.
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_get_count(touch_pad_t touch_num, uint32_t *count);
|
||||
|
||||
/**
|
||||
* @brief Get the accumulated measurement of the proximity sensor.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
* @param touch_num touch pad index
|
||||
* @param measure_out If the accumulation process does not end, the `measure_out` is the process value.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Touch num is not proximity
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_get_data(touch_pad_t touch_num, uint32_t *measure_out);
|
||||
|
||||
/**
|
||||
* @brief Get parameter of touch sensor sleep channel.
|
||||
* The touch sensor can works in sleep mode to wake up sleep.
|
||||
*
|
||||
* @note After the sleep channel is configured, Please use special functions for sleep channel.
|
||||
* e.g. The user should uses `touch_pad_sleep_channel_read_data` instead of `touch_pad_read_raw_data` to obtain the sleep channel reading.
|
||||
*
|
||||
* @param slp_config touch sleep pad config.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_get_info(touch_pad_sleep_channel_t *slp_config);
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable sleep channel function for touch sensor.
|
||||
* The touch sensor can works in sleep mode to wake up sleep.
|
||||
*
|
||||
* @note ESP32S2 only support one sleep channel.
|
||||
* @note After the sleep channel is configured, Please use special functions for sleep channel.
|
||||
* e.g. The user should uses `touch_pad_sleep_channel_read_data` instead of `touch_pad_read_raw_data` to obtain the sleep channel reading.
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param enable true: enable sleep pad for touch sensor; false: disable sleep pad for touch sensor;
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_enable(touch_pad_t pad_num, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Enable/Disable proximity function for sleep channel.
|
||||
* The touch sensor can works in sleep mode to wake up sleep.
|
||||
*
|
||||
* @note ESP32S2 only support one sleep channel.
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param enable true: enable proximity for sleep channel; false: disable proximity for sleep channel;
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_enable_proximity(touch_pad_t pad_num, bool enable);
|
||||
|
||||
/**
|
||||
* @brief Set the trigger threshold of touch sensor in deep sleep.
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
*
|
||||
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param touch_thres touch sleep pad threshold
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_set_threshold(touch_pad_t pad_num, uint32_t touch_thres);
|
||||
|
||||
/**
|
||||
* @brief Get the trigger threshold of touch sensor in deep sleep.
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
*
|
||||
* @note In general, the touch threshold during sleep can use the threshold parameter parameters before sleep.
|
||||
*
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param touch_thres touch sleep pad threshold
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_get_threshold(touch_pad_t pad_num, uint32_t *touch_thres);
|
||||
|
||||
/**
|
||||
* @brief Read benchmark of touch sensor sleep channel.
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param benchmark pointer to accept touch sensor benchmark value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_read_benchmark(touch_pad_t pad_num, uint32_t *benchmark);
|
||||
|
||||
/**
|
||||
* @brief Read smoothed data of touch sensor sleep channel.
|
||||
* Smoothed data is filtered from the raw data.
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param smooth_data pointer to accept touch sensor smoothed data
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_read_smooth(touch_pad_t pad_num, uint32_t *smooth_data);
|
||||
|
||||
/**
|
||||
* @brief Read raw data of touch sensor sleep channel.
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param raw_data pointer to accept touch sensor raw data
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_read_data(touch_pad_t pad_num, uint32_t *raw_data);
|
||||
|
||||
/**
|
||||
* @brief Reset benchmark of touch sensor sleep channel.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_reset_benchmark(void);
|
||||
|
||||
/**
|
||||
* @brief Read proximity count of touch sensor sleep channel.
|
||||
* @param pad_num Set touch channel number for sleep pad. Only one touch sensor channel is supported in deep sleep mode.
|
||||
* @param proximity_cnt pointer to accept touch sensor proximity count value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_read_proximity_cnt(touch_pad_t pad_num, uint32_t *proximity_cnt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -498,7 +498,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
|
||||
portBASE_TYPE high_priority_task_awoken = 0;
|
||||
|
||||
lldesc_t *finish_desc;
|
||||
lldesc_t *finish_desc = NULL;
|
||||
|
||||
if ((status & I2S_INTR_OUT_DSCR_ERR) || (status & I2S_INTR_IN_DSCR_ERR)) {
|
||||
ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", status);
|
||||
|
@ -138,6 +138,8 @@ static inline uint32_t get_dma_periph(int dma_chan)
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
return PERIPH_SPI_DMA_MODULE;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -190,7 +190,7 @@ static inline bool is_valid_host(spi_host_device_t host)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return host >= SPI1_HOST && host <= SPI3_HOST;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
// SPI_HOST (SPI1_HOST) is not supported by the SPI Master driver on ESP32-S2
|
||||
return host >= SPI2_HOST && host <= SPI3_HOST;
|
||||
#endif
|
||||
|
@ -80,7 +80,7 @@ static inline bool is_valid_host(spi_host_device_t host)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return host >= SPI1_HOST && host <= SPI3_HOST;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
// SPI_HOST (SPI1_HOST) is not supported by the SPI Slave driver on ESP32-S2
|
||||
return host >= SPI2_HOST && host <= SPI3_HOST;
|
||||
#endif
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "test_utils.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2) // This testcase for ESP32
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2, ESP32S3) // This testcase for ESP32
|
||||
|
||||
/*
|
||||
* ADC DMA testcase
|
||||
|
@ -36,7 +36,7 @@
|
||||
#include "test/test_common_adc.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32) // This testcase for ESP32S2
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32, ESP32S3) // This testcase for ESP32S2
|
||||
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/lldesc.h"
|
||||
|
@ -31,7 +31,7 @@
|
||||
#include "test_dac_audio_file.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2) // This testcase for ESP32
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2, ESP32S3) // This testcase for ESP32
|
||||
|
||||
/*
|
||||
* DAC DMA config.
|
||||
|
@ -37,7 +37,7 @@
|
||||
#include "soc/dac_periph.h"
|
||||
#include "test/test_common_adc.h"
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32) // This testcase for ESP32S2
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32, ESP32S3) // This testcase for ESP32S2
|
||||
|
||||
#include "soc/system_reg.h"
|
||||
#include "esp32s2/rom/lldesc.h"
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "nvs_flash.h"
|
||||
#include "test_utils.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
static const char* TAG = "test_adc2";
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
@ -165,3 +167,5 @@ TEST_CASE("adc2 work with wifi","[adc]")
|
||||
|
||||
TEST_IGNORE_MESSAGE("this test case is ignored due to the critical memory leak of esp_netif and event_loop.");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "test_utils.h"
|
||||
#include "soc/adc_periph.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
static const char *TAG = "test_adc";
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
@ -382,4 +384,6 @@ void test_adc_slope_debug(void)
|
||||
vTaskDelay(SCOPE_DEBUG_FREQ_MS / portTICK_RATE_MS);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -3,6 +3,8 @@
|
||||
#include "esp_log.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
int test_freq_default[]=TEST_FREQ_DEFAULT();
|
||||
|
||||
const char MASTER_TAG[] = "test_master";
|
||||
@ -204,4 +206,6 @@ void spitest_gpio_output_sel(uint32_t gpio_num, int func, uint32_t signal_idx)
|
||||
{
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], func);
|
||||
GPIO.func_out_sel_cfg[gpio_num].func_sel=signal_idx;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "test_utils.h"
|
||||
#include "driver/i2s.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
#include "esp_adc_cal.h"
|
||||
|
||||
static const char *TAG = "test_dac";
|
||||
@ -180,3 +181,5 @@ TEST_CASE("esp32s2 adc2-dac with adc2 calibration", "[adc-dac]")
|
||||
subtest_adc_dac(2500, &chars);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define WAKE_UP_IGNORE 1 // gpio_wakeup function development is not completed yet, set it deprecated.
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
@ -770,3 +772,5 @@ TEST_CASE("GPIO ISR service test", "[gpio][ignore]")
|
||||
gpio_uninstall_isr_service();
|
||||
TEST_ASSERT((io18_param.isr_cnt == 1) && (io19_param.isr_cnt == 1));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
|
||||
#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
|
||||
@ -686,3 +687,5 @@ TEST_CASE("I2C SCL freq test (local test)", "[i2c][ignore]")
|
||||
free(data);
|
||||
TEST_ESP_OK(i2c_driver_delete(i2c_num));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -15,6 +15,8 @@
|
||||
#include "math.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define SAMPLE_RATE (36000)
|
||||
#define SAMPLE_BITS (16)
|
||||
#define MASTER_BCK_IO 15
|
||||
@ -516,3 +518,5 @@ TEST_CASE("I2S APLL clock variation test", "[i2s]")
|
||||
vTaskDelay(100 / portTICK_PERIOD_MS);
|
||||
TEST_ASSERT(initial_size == esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "driver/ledc.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define PULSE_IO 18
|
||||
#define PCNT_INPUT_IO 4
|
||||
#define PCNT_CTRL_FLOATING_IO 5
|
||||
@ -543,3 +545,5 @@ TEST_CASE("LEDC memory test", "[ledc][test_env=UT_T1_LEDC]")
|
||||
}
|
||||
|
||||
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "unity.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define PULSE_IO 21
|
||||
#define PCNT_INPUT_IO 4
|
||||
#define PCNT_CTRL_VCC_IO 5
|
||||
@ -669,4 +671,6 @@ TEST_CASE("PCNT counting mode test", "[pcnt]")
|
||||
count_mode_test(PCNT_CTRL_VCC_IO);
|
||||
printf("PCNT mode test for negative count\n");
|
||||
count_mode_test(PCNT_CTRL_GND_IO);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,8 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#ifdef SOC_MCPWM_SUPPORTED
|
||||
#include "soc/mcpwm_periph.h"
|
||||
#include "driver/mcpwm.h"
|
||||
@ -786,4 +788,6 @@ TEST_CASE("MCPWM unit1, timer2 capture test", "[mcpwm][test_env=UT_T1_MCPWM][tim
|
||||
capture_test(MCPWM_UNIT_1, MCPWM_TIMER_2, MCPWM_POS_EDGE);
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "test_utils.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
// CI ONLY: Don't connect any other signals to this GPIO
|
||||
#define RMT_DATA_IO (12) // bind signal RMT_SIG_OUT0_IDX and RMT_SIG_IN0_IDX on the same GPIO
|
||||
|
||||
@ -519,3 +521,5 @@ TEST_CASE("RMT TX loop", "[rmt]")
|
||||
rmt_clean_testbench(tx_channel, rx_channel);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h" // for uint32_t esp_random()
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define UART_TAG "Uart"
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
#define BUF_SIZE (100)
|
||||
@ -283,4 +285,6 @@ static void rs485_master(void)
|
||||
*/
|
||||
TEST_CASE_MULTIPLE_DEVICES("RS485 half duplex uart multiple devices test.", "[driver_RS485][test_env=UT_T2_RS485]", rs485_master, rs485_slave);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -16,6 +16,8 @@
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc_io_periph.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define RTCIO_CHECK(condition) TEST_ASSERT_MESSAGE((condition == ESP_OK), "ret is not ESP_OK")
|
||||
#define RTCIO_VERIFY(condition, msg) TEST_ASSERT_MESSAGE((condition), msg)
|
||||
|
||||
@ -267,4 +269,6 @@ TEST_CASE("RTCIO output hold test", "[rtcio]")
|
||||
}
|
||||
}
|
||||
ESP_LOGI(TAG, "RTCIO hold test over");
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "soc/soc_caps.h"
|
||||
#include "ccomp_timer.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#if defined(SOC_SDMMC_HOST_SUPPORTED) && defined(SOC_SDIO_SLAVE_SUPPORTED)
|
||||
#include "driver/sdio_slave.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
@ -805,4 +807,6 @@ ptest_func_t tohost_slave = {
|
||||
|
||||
TEST_MASTER_SLAVE(SDIO_TOHOST, test_cfg_array, "[sdio][timeout=180][test_env=UT_SDIO]", &tohost_master, &tohost_slave);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "freertos/task.h"
|
||||
#include "driver/sigmadelta.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
TEST_CASE("SigmaDelta config test", "[sigma_delta]")
|
||||
{
|
||||
sigmadelta_config_t sigmadelta_cfg = {
|
||||
@ -85,3 +87,5 @@ TEST_CASE("SigmaDelta pin, duty, prescale set", "[sigma_delta][ignore]")
|
||||
TEST_ESP_OK(sigmadelta_set_pin(SIGMADELTA_CHANNEL_0, 5));
|
||||
vTaskDelay(3000 / portTICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "test/test_common_spi.h"
|
||||
#include "unity.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// The VSPI pins on UT_T1_ESP_FLASH are connected to a external flash
|
||||
@ -344,4 +345,6 @@ TEST_CASE("spi master can be used on SPI1", "[spi]")
|
||||
|
||||
//TODO: add a case when a non-polling transaction happened in the bus-acquiring time and then release the bus then queue a new trans
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
@ -26,6 +26,7 @@
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "driver/spi_common_internal.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
const static char TAG[] = "test_spi";
|
||||
|
||||
@ -1094,3 +1095,5 @@ TEST_CASE("spi_speed","[spi]")
|
||||
master_free_device_bus(spi);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "test/test_common_spi.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(a, b)((a) > (b)? (b): (a))
|
||||
#endif
|
||||
@ -1164,3 +1166,5 @@ spitest_param_set_t mode_conf[] = {
|
||||
TEST_SPI_MASTER_SLAVE(MODE, mode_conf, "")
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -25,6 +25,7 @@
|
||||
|
||||
#include "hal/spi_ll.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
/********************************************************************************
|
||||
* Test SIO
|
||||
@ -221,3 +222,5 @@ void test_sio_slave(void)
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("sio mode", "[spi][test_env=Example_SPI_Multi_device]", test_sio_master, test_sio_slave);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -12,6 +12,8 @@
|
||||
#include "test/test_common_spi.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#ifndef CONFIG_SPIRAM
|
||||
//This test should be removed once the timing test is merged.
|
||||
|
||||
@ -142,3 +144,5 @@ TEST_CASE("test slave send unaligned","[spi]")
|
||||
}
|
||||
|
||||
#endif // !CONFIG_SPIRAM
|
||||
|
||||
#endif
|
@ -17,6 +17,7 @@
|
||||
#include "unity.h"
|
||||
#include "test/test_common_spi.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define TEST_DMA_MAX_SIZE 14000
|
||||
#define TEST_BUFFER_SIZE 256 ///< buffer size of each wrdma buffer in fifo mode
|
||||
@ -573,4 +574,6 @@ TEST_CASE("test spi slave hd continuous mode, master too long", "[spi][spi_slv_h
|
||||
master_free_device_bus(spi);
|
||||
}
|
||||
|
||||
#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2
|
||||
#endif //SOC_SPI_SUPPORT_SLAVE_HD_VER2
|
||||
|
||||
#endif
|
||||
|
@ -9,6 +9,8 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define TIMER_DIVIDER 16
|
||||
#define TIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */
|
||||
#define TIMER_DELTA 0.001
|
||||
@ -973,3 +975,5 @@ TEST_CASE_MULTIPLE_STAGES("timer_group software reset test",
|
||||
"[intr_status][intr_status = 0]",
|
||||
timer_group_test_first_stage,
|
||||
timer_group_test_second_stage);
|
||||
|
||||
#endif
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h" // for uint32_t esp_random()
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
#define UART_TAG "Uart"
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
#define BUF_SIZE (100)
|
||||
@ -312,3 +314,5 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]")
|
||||
free(rd_data);
|
||||
free(wr_data);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -34,7 +34,7 @@
|
||||
#include "soc/rtc_io_struct.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2) // This testcase for ESP32
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32S2, ESP32S3) // This testcase for ESP32
|
||||
|
||||
static const char *TAG = "test_touch";
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "driver/rtc_io.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32) // This testcase for ESP32S2
|
||||
#if !DISABLED_FOR_TARGETS(ESP8266, ESP32, ESP32S3) // This testcase for ESP32S2
|
||||
|
||||
static const char *TAG = "test_touch";
|
||||
|
||||
|
@ -272,18 +272,25 @@ esp_err_t timer_isr_register(timer_group_t group_num, timer_idx_t timer_num,
|
||||
switch (group_num) {
|
||||
case TIMER_GROUP_0:
|
||||
default:
|
||||
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
|
||||
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
|
||||
} else {
|
||||
intr_source = ETS_TG0_T0_LEVEL_INTR_SOURCE + timer_num;
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE)) {
|
||||
intr_source = ETS_TG0_T0_EDGE_INTR_SOURCE + timer_num;
|
||||
}
|
||||
#endif
|
||||
timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_0][timer_num]->hal), &status_reg, &mask);
|
||||
break;
|
||||
case TIMER_GROUP_1:
|
||||
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
|
||||
#if CONFIG_IDF_TARGET_ESP32 || CONFIG_IDF_TARGET_ESP32S2
|
||||
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE)) {
|
||||
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
|
||||
}
|
||||
#endif
|
||||
if ((intr_alloc_flags & ESP_INTR_FLAG_EDGE) == 0) {
|
||||
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
|
||||
} else {
|
||||
intr_source = ETS_TG1_T0_EDGE_INTR_SOURCE + timer_num;
|
||||
intr_source = ETS_TG1_T0_LEVEL_INTR_SOURCE + timer_num;
|
||||
}
|
||||
timer_hal_get_status_reg_mask_bit(&(p_timer_obj[TIMER_GROUP_1][timer_num]->hal), &status_reg, &mask);
|
||||
break;
|
||||
|
@ -42,7 +42,7 @@ static const char *TOUCH_TAG = "TOUCH_SENSOR";
|
||||
#define TOUCH_CHANNEL_CHECK(channel) do { \
|
||||
TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \
|
||||
} while (0);
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
#define TOUCH_CHANNEL_CHECK(channel) do { \
|
||||
TOUCH_CHECK(channel < SOC_TOUCH_SENSOR_NUM && channel >= 0, "Touch channel error", ESP_ERR_INVALID_ARG); \
|
||||
TOUCH_CHECK(channel != SOC_TOUCH_DENOISE_CHANNEL, "TOUCH0 is internal denoise channel", ESP_ERR_INVALID_ARG); \
|
||||
@ -194,7 +194,7 @@ esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold)
|
||||
TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold)
|
||||
{
|
||||
TOUCH_CHANNEL_CHECK(touch_num);
|
||||
@ -214,7 +214,7 @@ esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint16_t *threshold)
|
||||
touch_hal_get_threshold(touch_num, threshold);
|
||||
return ESP_OK;
|
||||
}
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold)
|
||||
{
|
||||
TOUCH_CHANNEL_CHECK(touch_num);
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/clk.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_UART_ISR_IN_IRAM
|
||||
|
0
components/efuse/esp32s3/component.mk
Normal file
0
components/efuse/esp32s3/component.mk
Normal file
13
components/efuse/esp32s3/esp_efuse_table.c
Normal file
13
components/efuse/esp32s3/esp_efuse_table.c
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at",
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
0
components/efuse/esp32s3/esp_efuse_table.csv
Normal file
0
components/efuse/esp32s3/esp_efuse_table.csv
Normal file
|
123
components/efuse/esp32s3/include/esp_efuse_table.h
Normal file
123
components/efuse/esp32s3/include/esp_efuse_table.h
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at",
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_DIS_RTC_RAM_BOOT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SPI_BOOT_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0_PURPOSE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1_PURPOSE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2_PURPOSE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3_PURPOSE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4_PURPOSE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5_PURPOSE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_EN[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SECURE_BOOT_AGGRESSIVE_REVOKE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_GROUP_3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_BLK1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_USER_DATA[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_KEY5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_SYS_DATA_PART2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_USB_EXCHG_PINS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_KEY5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_RD_DIS_SYS_DATA_PART2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_RTC_RAM_BOOT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_ICACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DCACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_DCACHE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_FORCE_DOWNLOAD[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_CAN[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_BOOT_REMAP[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SOFT_DIS_JTAG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_HARD_DIS_JTAG[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_USB_EXCHG_PINS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_USB_EXT_PHY_ENABLE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_XPD[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_TIEH[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_FORCE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_WDT_DELAY_SEL[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_BOOT_CRYPT_CNT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY_PURPOSE_5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_EN[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_TPUW[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MODE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_LEGACY_SPI_BOOT[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CHANNEL[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_TINY_BASIC[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DOWNLOAD_MODE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_UART_PRINT_CONTROL[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_PIN_POWER_SELECTION[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_TYPE[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_FORCE_SEND_RESUME[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SECURE_VERSION[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_MAC_FACTORY[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CLK[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_Q_D1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D_D0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_CS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_HD_D3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_WP_D2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_DQS[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D6[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SPI_PAD_CONFIG_D7[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_CLK8M_FREQ[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_USER_DATA[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY0[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY1[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY2[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY3[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY4[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_KEY5[];
|
||||
extern const esp_efuse_desc_t* ESP_EFUSE_SYS_DATA_PART2[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
1
components/efuse/esp32s3/sources.cmake
Normal file
1
components/efuse/esp32s3/sources.cmake
Normal file
@ -0,0 +1 @@
|
||||
set(EFUSE_SOC_SRCS "esp_efuse_table.c")
|
69
components/efuse/include/esp32s3/esp_efuse.h
Normal file
69
components/efuse/include/esp32s3/esp_efuse.h
Normal file
@ -0,0 +1,69 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Type of eFuse blocks ESP32S3
|
||||
*/
|
||||
typedef enum {
|
||||
EFUSE_BLK0 = 0, /**< Number of eFuse BLOCK0. REPEAT_DATA */
|
||||
|
||||
EFUSE_BLK1 = 1, /**< Number of eFuse BLOCK1. MAC_SPI_8M_SYS */
|
||||
|
||||
EFUSE_BLK2 = 2, /**< Number of eFuse BLOCK2. SYS_DATA_PART1 */
|
||||
EFUSE_BLK_SYS_DATA_PART1 = 2, /**< Number of eFuse BLOCK2. SYS_DATA_PART1 */
|
||||
|
||||
EFUSE_BLK3 = 3, /**< Number of eFuse BLOCK3. USER_DATA*/
|
||||
EFUSE_BLK_USER_DATA = 3, /**< Number of eFuse BLOCK3. USER_DATA*/
|
||||
|
||||
EFUSE_BLK4 = 4, /**< Number of eFuse BLOCK4. KEY0 */
|
||||
EFUSE_BLK_KEY0 = 4, /**< Number of eFuse BLOCK4. KEY0 */
|
||||
|
||||
EFUSE_BLK5 = 5, /**< Number of eFuse BLOCK5. KEY1 */
|
||||
EFUSE_BLK_KEY1 = 5, /**< Number of eFuse BLOCK5. KEY1 */
|
||||
|
||||
EFUSE_BLK6 = 6, /**< Number of eFuse BLOCK6. KEY2 */
|
||||
EFUSE_BLK_KEY2 = 6, /**< Number of eFuse BLOCK6. KEY2 */
|
||||
|
||||
EFUSE_BLK7 = 7, /**< Number of eFuse BLOCK7. KEY3 */
|
||||
EFUSE_BLK_KEY3 = 7, /**< Number of eFuse BLOCK7. KEY3 */
|
||||
|
||||
EFUSE_BLK8 = 8, /**< Number of eFuse BLOCK8. KEY4 */
|
||||
EFUSE_BLK_KEY4 = 8, /**< Number of eFuse BLOCK8. KEY4 */
|
||||
|
||||
EFUSE_BLK9 = 9, /**< Number of eFuse BLOCK9. KEY5 */
|
||||
EFUSE_BLK_KEY5 = 9, /**< Number of eFuse BLOCK9. KEY5 */
|
||||
|
||||
EFUSE_BLK10 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */
|
||||
EFUSE_BLK_SYS_DATA_PART2 = 10, /**< Number of eFuse BLOCK10. SYS_DATA_PART2 */
|
||||
|
||||
EFUSE_BLK_MAX
|
||||
} esp_efuse_block_t;
|
||||
|
||||
/**
|
||||
* @brief Type of coding scheme
|
||||
*/
|
||||
typedef enum {
|
||||
EFUSE_CODING_SCHEME_NONE = 0, /**< None */
|
||||
EFUSE_CODING_SCHEME_RS = 3, /**< Reed-Solomon coding */
|
||||
} esp_efuse_coding_scheme_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -27,6 +27,8 @@ extern "C" {
|
||||
#include "esp32/esp_efuse.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/esp_efuse.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/esp_efuse.h"
|
||||
#endif
|
||||
|
||||
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */
|
||||
|
30
components/efuse/private_include/esp32s3/esp_efuse_utility.h
Normal file
30
components/efuse/private_include/esp32s3/esp_efuse_utility.h
Normal file
@ -0,0 +1,30 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define COUNT_EFUSE_BLOCKS 11 /* The number of blocks. */
|
||||
#define COUNT_EFUSE_REG_PER_BLOCK 8 /* The number of registers per block. */
|
||||
|
||||
#define ESP_EFUSE_SECURE_VERSION_NUM_BLOCK EFUSE_BLK0
|
||||
|
||||
#define ESP_EFUSE_FIELD_CORRESPONDS_CODING_SCHEME(scheme, max_num_bit)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -27,6 +27,8 @@ extern "C" {
|
||||
#include "esp32/esp_efuse_utility.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/esp_efuse_utility.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/esp_efuse_utility.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
13
components/efuse/src/esp32s3/esp_efuse_api.c
Normal file
13
components/efuse/src/esp32s3/esp_efuse_api.c
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
13
components/efuse/src/esp32s3/esp_efuse_fields.c
Normal file
13
components/efuse/src/esp32s3/esp_efuse_fields.c
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
13
components/efuse/src/esp32s3/esp_efuse_utility.c
Normal file
13
components/efuse/src/esp32s3/esp_efuse_utility.c
Normal file
@ -0,0 +1,13 @@
|
||||
// Copyright 2017-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
@ -19,6 +19,8 @@
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
||||
static const char* TAG = "efuse_test";
|
||||
|
||||
static void test_read_blob(void)
|
||||
@ -858,3 +860,5 @@ TEST_CASE("Test chip_revision APIs return the same value", "[efuse]")
|
||||
esp_efuse_utility_update_virt_blocks();
|
||||
TEST_ASSERT_EQUAL_INT(esp_efuse_get_chip_ver(), bootloader_common_get_chip_revision());
|
||||
}
|
||||
|
||||
#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S3)
|
||||
|
@ -16,13 +16,13 @@ else()
|
||||
"clk.c"
|
||||
"crosscore_int.c"
|
||||
"dport_access.c"
|
||||
"esp_crypto_lock.c"
|
||||
"hw_random.c"
|
||||
"intr_alloc.c"
|
||||
"memprot.c"
|
||||
"pm_esp32s3.c"
|
||||
"pm_trace.c"
|
||||
"sleep_modes.c"
|
||||
"spiram.c"
|
||||
"spiram_psram.c"
|
||||
"system_api_esp32s3.c")
|
||||
set(include_dirs "include")
|
||||
|
||||
|
@ -171,16 +171,25 @@ menu "ESP32S3-Specific"
|
||||
|
||||
choice SPIRAM_TYPE
|
||||
prompt "Type of SPI RAM chip in use"
|
||||
default SPIRAM_TYPE_ESPPSRAM32
|
||||
default SPIRAM_TYPE_AUTO
|
||||
|
||||
config SPIRAM_TYPE_AUTO
|
||||
bool "Auto-detect"
|
||||
|
||||
config SPIRAM_TYPE_ESPPSRAM16
|
||||
bool "ESP-PSRAM16 or APS1604"
|
||||
|
||||
config SPIRAM_TYPE_ESPPSRAM32
|
||||
bool "ESP-PSRAM32 or IS25WP032"
|
||||
|
||||
config SPIRAM_TYPE_ESPPSRAM64
|
||||
bool "ESP-PSRAM64 or LY68L6400"
|
||||
endchoice
|
||||
|
||||
config SPIRAM_SIZE
|
||||
int
|
||||
default -1 if SPIRAM_TYPE_AUTO
|
||||
default 2097152 if SPIRAM_TYPE_ESPPSRAM16
|
||||
default 4194304 if SPIRAM_TYPE_ESPPSRAM32
|
||||
default 8388608 if SPIRAM_TYPE_ESPPSRAM64
|
||||
default 0
|
||||
@ -201,22 +210,6 @@ menu "ESP32S3-Specific"
|
||||
help
|
||||
The PSRAM CS IO can be any unused GPIO, please refer to your hardware design.
|
||||
endmenu
|
||||
|
||||
config SPIRAM_SPIWP_SD3_PIN
|
||||
int "SPI PSRAM WP(SD3) Pin when customizing pins via eFuse (read help)"
|
||||
depends on ESPTOOLPY_FLASHMODE_DIO || ESPTOOLPY_FLASHMODE_DOUT
|
||||
range 0 33
|
||||
default 28
|
||||
help
|
||||
This value is ignored unless flash mode is set to DIO or DOUT and the SPI flash pins have been
|
||||
overridden by setting the eFuses SPI_PAD_CONFIG_xxx.
|
||||
|
||||
Different from esp32 chip, on esp32-s3, the WP pin would also be defined in efuse.
|
||||
This value would only be used if the WP pin recorded in efuse SPI_PAD_CONFIG_xxx is invalid.
|
||||
|
||||
When flash mode is set to QIO or QOUT,
|
||||
the PSRAM WP pin will be set as the value configured in bootloader.
|
||||
|
||||
config SPIRAM_FETCH_INSTRUCTIONS
|
||||
bool "Cache fetch instructions from SPI RAM"
|
||||
default n
|
||||
@ -237,11 +230,6 @@ menu "ESP32S3-Specific"
|
||||
default SPIRAM_SPEED_40M
|
||||
help
|
||||
Select the speed for the SPI RAM chip.
|
||||
If SPI RAM is enabled, we only support three combinations of SPI speed mode we supported now:
|
||||
|
||||
1. Flash SPI running at 40Mhz and RAM SPI running at 40Mhz
|
||||
2. Flash SPI running at 80Mhz and RAM SPI running at 40Mhz
|
||||
3. Flash SPI running at 80Mhz and RAM SPI running at 80Mhz
|
||||
|
||||
config SPIRAM_SPEED_80M
|
||||
bool "80MHz clock speed"
|
||||
|
@ -23,9 +23,6 @@
|
||||
|
||||
// g_ticks_us defined in ROMs for PRO and APP CPU
|
||||
extern uint32_t g_ticks_per_us_pro;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
extern uint32_t g_ticks_per_us_app;
|
||||
#endif
|
||||
|
||||
int IRAM_ATTR esp_clk_cpu_freq(void)
|
||||
{
|
||||
@ -46,7 +43,4 @@ void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
||||
{
|
||||
/* Update scale factors used by esp_rom_delay_us */
|
||||
g_ticks_per_us_pro = ticks_per_us;
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
g_ticks_per_us_app = ticks_per_us;
|
||||
#endif
|
||||
}
|
39
components/esp32s3/include/esp32s3/rtc.h
Normal file
39
components/esp32s3/include/esp32s3/rtc.h
Normal file
@ -0,0 +1,39 @@
|
||||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file esp32s2/rtc.h
|
||||
*
|
||||
* This file contains declarations of rtc related functions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get current value of RTC counter in microseconds
|
||||
*
|
||||
* Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute
|
||||
*
|
||||
* @return current value of RTC counter in microseconds
|
||||
*/
|
||||
uint64_t esp_rtc_get_time_us(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -87,5 +87,52 @@ void esp_spiram_writeback_cache(void);
|
||||
*/
|
||||
esp_err_t esp_spiram_reserve_dma_pool(size_t size);
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
|
||||
extern int _instruction_reserved_start, _instruction_reserved_end;
|
||||
|
||||
/**
|
||||
* @brief Get the start page number of the instruction in SPI flash
|
||||
*
|
||||
* @return start page number
|
||||
*/
|
||||
uint32_t instruction_flash_start_page_get(void);
|
||||
/**
|
||||
* @brief Get the end page number of the instruction in SPI flash
|
||||
*
|
||||
* @return end page number
|
||||
*/
|
||||
uint32_t instruction_flash_end_page_get(void);
|
||||
/**
|
||||
* @brief Get the offset of instruction from SPI flash to SPI RAM
|
||||
*
|
||||
* @return instruction offset
|
||||
*/
|
||||
int instruction_flash2spiram_offset(void);
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
|
||||
extern int _rodata_reserved_start, _rodata_reserved_end;
|
||||
|
||||
/**
|
||||
* @brief Get the start page number of the rodata in SPI flash
|
||||
*
|
||||
* @return start page number
|
||||
*/
|
||||
uint32_t rodata_flash_start_page_get(void);
|
||||
/**
|
||||
* @brief Get the end page number of the rodata in SPI flash
|
||||
*
|
||||
* @return end page number
|
||||
*/
|
||||
uint32_t rodata_flash_end_page_get(void);
|
||||
/**
|
||||
* @brief Get the offset number of rodata from SPI flash to SPI RAM
|
||||
*
|
||||
* @return rodata offset
|
||||
*/
|
||||
int rodata_flash2spiram_offset(void);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -11,7 +11,7 @@
|
||||
#define SRAM_IRAM_START 0x40370000
|
||||
#define SRAM_DRAM_START 0x3FC80000
|
||||
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
|
||||
#define SRAM_DRAM_END 0x40054000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
|
||||
#define SRAM_DRAM_END 0x403BC000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
|
||||
|
||||
#define SRAM_IRAM_ORG (SRAM_IRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE)
|
||||
#define SRAM_DRAM_ORG (SRAM_DRAM_START + CONFIG_ESP32S3_INSTRUCTION_CACHE_SIZE)
|
||||
|
@ -21,6 +21,7 @@ PROVIDE ( LEDC = 0x60019000 );
|
||||
PROVIDE ( MCP = 0x600c3000 );
|
||||
PROVIDE ( TIMERG0 = 0x6001F000 );
|
||||
PROVIDE ( TIMERG1 = 0x60020000 );
|
||||
PROVIDE ( SYS_TIMER = 0x60023000 );
|
||||
PROVIDE ( GPSPI2 = 0x60024000 );
|
||||
PROVIDE ( GPSPI3 = 0x60025000 );
|
||||
PROVIDE ( SYSCON = 0x60026000 );
|
||||
@ -28,5 +29,6 @@ PROVIDE ( I2C1 = 0x60027000 );
|
||||
PROVIDE ( GPSPI4 = 0x60037000 );
|
||||
PROVIDE ( GDMA = 0x6003F000 );
|
||||
PROVIDE ( UART2 = 0x60010000 );
|
||||
PROVIDE ( DMA = 0x6003F000 );
|
||||
PROVIDE ( APB_SARADC = 0x60040000 );
|
||||
PROVIDE ( LCD_CAM = 0x60041000 );
|
||||
|
@ -284,6 +284,7 @@ SECTIONS
|
||||
.flash.text :
|
||||
{
|
||||
_stext = .;
|
||||
_instruction_reserved_start = ABSOLUTE(.);
|
||||
_text_start = ABSOLUTE(.);
|
||||
|
||||
mapping[flash_text]
|
||||
@ -294,6 +295,7 @@ SECTIONS
|
||||
*(.fini)
|
||||
*(.gnu.version)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_instruction_reserved_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
|
||||
/**
|
||||
@ -308,6 +310,7 @@ SECTIONS
|
||||
{
|
||||
. = SIZEOF(.flash.text);
|
||||
. = ALIGN(0x10000) + 0x20;
|
||||
_rodata_reserved_start = .;
|
||||
} > drom0_0_seg
|
||||
|
||||
/* When modifying the alignment, don't forget to update tls_section_alignment in pxPortInitialiseStack */
|
||||
@ -367,6 +370,7 @@ SECTIONS
|
||||
*(.tbss)
|
||||
*(.tbss.*)
|
||||
_thread_local_end = ABSOLUTE(.);
|
||||
_rodata_reserved_end = ABSOLUTE(.);
|
||||
. = ALIGN(4);
|
||||
} > default_rodata_seg
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool esp_memprot_is_assoc_intr_any()
|
||||
bool esp_memprot_is_assoc_intr_any(void)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
@ -1,717 +0,0 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stddef.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/param.h>
|
||||
#include "esp_attr.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "esp_private/esp_timer_private.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s3/clk.h"
|
||||
#include "esp_newlib.h"
|
||||
#include "esp_spi_flash.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32s3/rom/rtc.h"
|
||||
#include "esp_rom_uart.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/uart_caps.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
#include "hal/clk_gate_ll.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
// If light sleep time is less than that, don't power down flash
|
||||
#define FLASH_PD_MIN_SLEEP_TIME_US 2000
|
||||
|
||||
// Time from VDD_SDIO power up to first flash read in ROM code
|
||||
#define VDD_SDIO_POWERUP_TO_FLASH_READ_US 700
|
||||
|
||||
// Extra time it takes to enter and exit light sleep and deep sleep
|
||||
// For deep sleep, this is until the wake stub runs (not the app).
|
||||
#ifdef CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US (650 + 30 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (650 + 100 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
|
||||
#else
|
||||
#define LIGHT_SLEEP_TIME_OVERHEAD_US (250 + 30 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
|
||||
#define DEEP_SLEEP_TIME_OVERHEAD_US (250 + 100 * 240 / CONFIG_ESP32S3_DEFAULT_CPU_FREQ_MHZ)
|
||||
#endif // CONFIG_ESP32S3_RTC_CLK_SRC_EXT_CRYS
|
||||
|
||||
// Minimal amount of time we can sleep for
|
||||
#define LIGHT_SLEEP_MIN_TIME_US 200
|
||||
|
||||
#define CHECK_SOURCE(source, value, mask) ((s_config.wakeup_triggers & mask) && \
|
||||
(source == value))
|
||||
|
||||
/**
|
||||
* Internal structure which holds all requested deep sleep parameters
|
||||
*/
|
||||
typedef struct {
|
||||
esp_sleep_pd_option_t pd_options[ESP_PD_DOMAIN_MAX];
|
||||
uint64_t sleep_duration;
|
||||
uint32_t wakeup_triggers : 15;
|
||||
uint32_t ext1_trigger_mode : 1;
|
||||
uint32_t ext1_rtc_gpio_mask : 18;
|
||||
uint32_t ext0_trigger_level : 1;
|
||||
uint32_t ext0_rtc_gpio_num : 5;
|
||||
uint32_t sleep_time_adjustment;
|
||||
uint64_t rtc_ticks_at_sleep_start;
|
||||
} sleep_config_t;
|
||||
|
||||
static sleep_config_t s_config = {
|
||||
.pd_options = { ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO, ESP_PD_OPTION_AUTO },
|
||||
.wakeup_triggers = 0
|
||||
};
|
||||
|
||||
/* Internal variable used to track if light sleep wakeup sources are to be
|
||||
expected when determining wakeup cause. */
|
||||
static bool s_light_sleep_wakeup = false;
|
||||
|
||||
/* Updating RTC_MEMORY_CRC_REG register via set_rtc_memory_crc()
|
||||
is not thread-safe. */
|
||||
static _lock_t lock_rtc_memory_crc;
|
||||
|
||||
static const char *TAG = "sleep";
|
||||
|
||||
static uint32_t get_power_down_flags(void);
|
||||
static void ext0_wakeup_prepare(void);
|
||||
static void ext1_wakeup_prepare(void);
|
||||
static void timer_wakeup_prepare(void);
|
||||
static void touch_wakeup_prepare(void);
|
||||
|
||||
/* Wake from deep sleep stub
|
||||
See esp_deepsleep.h esp_wake_deep_sleep() comments for details.
|
||||
*/
|
||||
esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void)
|
||||
{
|
||||
_lock_acquire(&lock_rtc_memory_crc);
|
||||
uint32_t stored_crc = REG_READ(RTC_MEMORY_CRC_REG);
|
||||
set_rtc_memory_crc();
|
||||
uint32_t calc_crc = REG_READ(RTC_MEMORY_CRC_REG);
|
||||
REG_WRITE(RTC_MEMORY_CRC_REG, stored_crc);
|
||||
_lock_release(&lock_rtc_memory_crc);
|
||||
|
||||
if (stored_crc != calc_crc) {
|
||||
return NULL;
|
||||
}
|
||||
esp_deep_sleep_wake_stub_fn_t stub_ptr = (esp_deep_sleep_wake_stub_fn_t) REG_READ(RTC_ENTRY_ADDR_REG);
|
||||
if (!esp_ptr_executable(stub_ptr)) {
|
||||
return NULL;
|
||||
}
|
||||
return stub_ptr;
|
||||
}
|
||||
|
||||
void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub)
|
||||
{
|
||||
_lock_acquire(&lock_rtc_memory_crc);
|
||||
REG_WRITE(RTC_ENTRY_ADDR_REG, (uint32_t)new_stub);
|
||||
set_rtc_memory_crc();
|
||||
_lock_release(&lock_rtc_memory_crc);
|
||||
}
|
||||
|
||||
void RTC_IRAM_ATTR esp_default_wake_deep_sleep(void)
|
||||
{
|
||||
REG_SET_BIT(EXTMEM_CACHE_CONF_MISC_REG, EXTMEM_CACHE_TRACE_ENA);
|
||||
}
|
||||
|
||||
void __attribute__((weak, alias("esp_default_wake_deep_sleep"))) esp_wake_deep_sleep(void);
|
||||
|
||||
void esp_deep_sleep(uint64_t time_in_us)
|
||||
{
|
||||
esp_sleep_enable_timer_wakeup(time_in_us);
|
||||
esp_deep_sleep_start();
|
||||
}
|
||||
|
||||
static void IRAM_ATTR flush_uarts(void)
|
||||
{
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
|
||||
esp_rom_uart_tx_wait_idle(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR suspend_uarts(void)
|
||||
{
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
|
||||
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
|
||||
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XOFF);
|
||||
while (REG_GET_FIELD(UART_FSM_STATUS_REG(i), UART_ST_UTX_OUT) != 0) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void IRAM_ATTR resume_uarts(void)
|
||||
{
|
||||
for (int i = 0; i < SOC_UART_NUM; ++i) {
|
||||
if (periph_ll_periph_enabled(PERIPH_UART0_MODULE + i)) {
|
||||
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XOFF);
|
||||
REG_SET_BIT(UART_FLOW_CONF_REG(i), UART_FORCE_XON);
|
||||
REG_CLR_BIT(UART_FLOW_CONF_REG(i), UART_SW_FLOW_CON_EN | UART_FORCE_XON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags)
|
||||
{
|
||||
// Stop UART output so that output is not lost due to APB frequency change.
|
||||
// For light sleep, suspend UART output — it will resume after wakeup.
|
||||
// For deep sleep, wait for the contents of UART FIFO to be sent.
|
||||
if (pd_flags & RTC_SLEEP_PD_DIG) {
|
||||
flush_uarts();
|
||||
} else {
|
||||
suspend_uarts();
|
||||
}
|
||||
|
||||
// Save current frequency and switch to XTAL
|
||||
// Save current frequency and switch to XTAL
|
||||
rtc_cpu_freq_config_t cpu_freq_config;
|
||||
rtc_clk_cpu_freq_get_config(&cpu_freq_config);
|
||||
rtc_clk_cpu_freq_set_xtal();
|
||||
|
||||
// Configure pins for external wakeup
|
||||
if (s_config.wakeup_triggers & RTC_EXT0_TRIG_EN) {
|
||||
ext0_wakeup_prepare();
|
||||
}
|
||||
if (s_config.wakeup_triggers & RTC_EXT1_TRIG_EN) {
|
||||
ext1_wakeup_prepare();
|
||||
}
|
||||
// Enable ULP wakeup
|
||||
if (s_config.wakeup_triggers & RTC_ULP_TRIG_EN) {
|
||||
// no-op for esp32s3
|
||||
}
|
||||
// Enable Touch wakeup
|
||||
if (s_config.wakeup_triggers & RTC_TOUCH_TRIG_EN) {
|
||||
touch_wakeup_prepare();
|
||||
}
|
||||
|
||||
uint32_t reject_triggers = 0;
|
||||
if ((pd_flags & RTC_SLEEP_PD_DIG) == 0) {
|
||||
/* Light sleep, enable sleep reject for faster return from this function,
|
||||
* in case the wakeup is already triggerred.
|
||||
*/
|
||||
reject_triggers = s_config.wakeup_triggers;
|
||||
}
|
||||
|
||||
// Enter sleep
|
||||
rtc_sleep_config_t config = RTC_SLEEP_CONFIG_DEFAULT(pd_flags);
|
||||
rtc_sleep_init(config);
|
||||
|
||||
// Configure timer wakeup
|
||||
if ((s_config.wakeup_triggers & RTC_TIMER_TRIG_EN) &&
|
||||
s_config.sleep_duration > 0) {
|
||||
timer_wakeup_prepare();
|
||||
}
|
||||
|
||||
uint32_t result = rtc_sleep_start(s_config.wakeup_triggers, reject_triggers, 1);
|
||||
|
||||
// Restore CPU frequency
|
||||
rtc_clk_cpu_freq_set_config(&cpu_freq_config);
|
||||
|
||||
// re-enable UART output
|
||||
resume_uarts();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_deep_sleep_start(void)
|
||||
{
|
||||
// record current RTC time
|
||||
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
||||
esp_sync_counters_rtc_and_frc();
|
||||
// Configure wake stub
|
||||
if (esp_get_deep_sleep_wake_stub() == NULL) {
|
||||
esp_set_deep_sleep_wake_stub(esp_wake_deep_sleep);
|
||||
}
|
||||
|
||||
// Decide which power domains can be powered down
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
|
||||
// Correct the sleep time
|
||||
s_config.sleep_time_adjustment = DEEP_SLEEP_TIME_OVERHEAD_US;
|
||||
|
||||
// Enter sleep
|
||||
esp_sleep_start(RTC_SLEEP_PD_DIG | RTC_SLEEP_PD_VDDSDIO | pd_flags);
|
||||
|
||||
// Because RTC is in a slower clock domain than the CPU, it
|
||||
// can take several CPU cycles for the sleep mode to start.
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function which handles entry to and exit from light sleep
|
||||
* Placed into IRAM as flash may need some time to be powered on.
|
||||
*/
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
uint32_t flash_enable_time_us,
|
||||
rtc_vddsdio_config_t vddsdio_config) IRAM_ATTR __attribute__((noinline));
|
||||
|
||||
static esp_err_t esp_light_sleep_inner(uint32_t pd_flags,
|
||||
uint32_t flash_enable_time_us,
|
||||
rtc_vddsdio_config_t vddsdio_config)
|
||||
{
|
||||
// Enter sleep
|
||||
esp_err_t err = esp_sleep_start(pd_flags);
|
||||
|
||||
// If VDDSDIO regulator was controlled by RTC registers before sleep,
|
||||
// restore the configuration.
|
||||
if (vddsdio_config.force) {
|
||||
rtc_vddsdio_set_config(vddsdio_config);
|
||||
}
|
||||
|
||||
// If SPI flash was powered down, wait for it to become ready
|
||||
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
|
||||
// Wait for the flash chip to start up
|
||||
esp_rom_delay_us(flash_enable_time_us);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_light_sleep_start(void)
|
||||
{
|
||||
static portMUX_TYPE light_sleep_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||
portENTER_CRITICAL(&light_sleep_lock);
|
||||
/* We will be calling esp_timer_private_advance inside DPORT access critical
|
||||
* section. Make sure the code on the other CPU is not holding esp_timer
|
||||
* lock, otherwise there will be deadlock.
|
||||
*/
|
||||
esp_timer_private_lock();
|
||||
s_config.rtc_ticks_at_sleep_start = rtc_time_get();
|
||||
uint64_t frc_time_at_start = esp_timer_get_time();
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
|
||||
// Decide which power domains can be powered down
|
||||
uint32_t pd_flags = get_power_down_flags();
|
||||
|
||||
// Amount of time to subtract from actual sleep time.
|
||||
// This is spent on entering and leaving light sleep.
|
||||
s_config.sleep_time_adjustment = LIGHT_SLEEP_TIME_OVERHEAD_US;
|
||||
|
||||
// Decide if VDD_SDIO needs to be powered down;
|
||||
// If it needs to be powered down, adjust sleep time.
|
||||
const uint32_t flash_enable_time_us = VDD_SDIO_POWERUP_TO_FLASH_READ_US;
|
||||
|
||||
#ifndef CONFIG_SPIRAM
|
||||
const uint32_t vddsdio_pd_sleep_duration = MAX(FLASH_PD_MIN_SLEEP_TIME_US,
|
||||
flash_enable_time_us + LIGHT_SLEEP_TIME_OVERHEAD_US + LIGHT_SLEEP_MIN_TIME_US);
|
||||
|
||||
if (s_config.sleep_duration > vddsdio_pd_sleep_duration) {
|
||||
pd_flags |= RTC_SLEEP_PD_VDDSDIO;
|
||||
s_config.sleep_time_adjustment += flash_enable_time_us;
|
||||
}
|
||||
#endif //CONFIG_SPIRAM
|
||||
|
||||
rtc_vddsdio_config_t vddsdio_config = rtc_vddsdio_get_config();
|
||||
|
||||
// Safety net: enable WDT in case exit from light sleep fails
|
||||
wdt_hal_context_t rtc_wdt_ctx = {.inst = WDT_RWDT, .rwdt_dev = &RTCCNTL};
|
||||
bool wdt_was_enabled = wdt_hal_is_enabled(&rtc_wdt_ctx); // If WDT was enabled in the user code, then do not change it here.
|
||||
if (!wdt_was_enabled) {
|
||||
wdt_hal_init(&rtc_wdt_ctx, WDT_RWDT, 0, false);
|
||||
uint32_t stage_timeout_ticks = (uint32_t)(1000ULL * rtc_clk_slow_freq_get_hz() / 1000ULL);
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_config_stage(&rtc_wdt_ctx, WDT_STAGE0, stage_timeout_ticks, WDT_STAGE_ACTION_RESET_RTC);
|
||||
wdt_hal_enable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
}
|
||||
|
||||
// Enter sleep, then wait for flash to be ready on wakeup
|
||||
esp_err_t err = esp_light_sleep_inner(pd_flags,
|
||||
flash_enable_time_us, vddsdio_config);
|
||||
|
||||
s_light_sleep_wakeup = true;
|
||||
|
||||
// FRC1 has been clock gated for the duration of the sleep, correct for that.
|
||||
uint64_t rtc_ticks_at_end = rtc_time_get();
|
||||
uint64_t frc_time_at_end = esp_timer_get_time();
|
||||
|
||||
uint64_t rtc_time_diff = rtc_time_slowclk_to_us(rtc_ticks_at_end - s_config.rtc_ticks_at_sleep_start,
|
||||
esp_clk_slowclk_cal_get());
|
||||
uint64_t frc_time_diff = frc_time_at_end - frc_time_at_start;
|
||||
|
||||
int64_t time_diff = rtc_time_diff - frc_time_diff;
|
||||
/* Small negative values (up to 1 RTC_SLOW clock period) are possible,
|
||||
* for very small values of sleep_duration. Ignore those to keep esp_timer
|
||||
* monotonic.
|
||||
*/
|
||||
if (time_diff > 0) {
|
||||
esp_timer_private_advance(time_diff);
|
||||
}
|
||||
esp_set_time_from_rtc();
|
||||
|
||||
esp_timer_private_unlock();
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
if (!wdt_was_enabled) {
|
||||
wdt_hal_write_protect_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_disable(&rtc_wdt_ctx);
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
}
|
||||
portEXIT_CRITICAL(&light_sleep_lock);
|
||||
return err;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source)
|
||||
{
|
||||
// For most of sources it is enough to set trigger mask in local
|
||||
// configuration structure. The actual RTC wake up options
|
||||
// will be updated by esp_sleep_start().
|
||||
if (source == ESP_SLEEP_WAKEUP_ALL) {
|
||||
s_config.wakeup_triggers = 0;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TIMER, RTC_TIMER_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_TIMER_TRIG_EN;
|
||||
s_config.sleep_duration = 0;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT0, RTC_EXT0_TRIG_EN)) {
|
||||
s_config.ext0_rtc_gpio_num = 0;
|
||||
s_config.ext0_trigger_level = 0;
|
||||
s_config.wakeup_triggers &= ~RTC_EXT0_TRIG_EN;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_EXT1, RTC_EXT1_TRIG_EN)) {
|
||||
s_config.ext1_rtc_gpio_mask = 0;
|
||||
s_config.ext1_trigger_mode = 0;
|
||||
s_config.wakeup_triggers &= ~RTC_EXT1_TRIG_EN;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_TOUCHPAD, RTC_TOUCH_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_TOUCH_TRIG_EN;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_GPIO, RTC_GPIO_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_GPIO_TRIG_EN;
|
||||
} else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) {
|
||||
s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN);
|
||||
}
|
||||
#ifdef CONFIG_ESP32S3_ULP_COPROC_ENABLED
|
||||
else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) {
|
||||
s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
ESP_LOGE(TAG, "Incorrect wakeup source (%d) to disable.", (int) source);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_ulp_wakeup(void)
|
||||
{
|
||||
s_config.wakeup_triggers |= (RTC_ULP_TRIG_EN | RTC_COCPU_TRIG_EN | RTC_COCPU_TRAP_TRIG_EN);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us)
|
||||
{
|
||||
s_config.wakeup_triggers |= RTC_TIMER_TRIG_EN;
|
||||
s_config.sleep_duration = time_in_us;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void timer_wakeup_prepare(void)
|
||||
{
|
||||
uint32_t period = esp_clk_slowclk_cal_get();
|
||||
int64_t sleep_duration = (int64_t) s_config.sleep_duration - (int64_t) s_config.sleep_time_adjustment;
|
||||
if (sleep_duration < 0) {
|
||||
sleep_duration = 0;
|
||||
}
|
||||
int64_t rtc_count_delta = rtc_time_us_to_slowclk(sleep_duration, period);
|
||||
rtc_sleep_set_wakeup_time(s_config.rtc_ticks_at_sleep_start + rtc_count_delta);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_MAIN_TIMER_INT_CLR_M);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_SLP_TIMER1_REG, RTC_CNTL_MAIN_TIMER_ALARM_EN_M);
|
||||
}
|
||||
|
||||
/* In deep sleep mode, only the sleep channel is supported, and other touch channels should be turned off. */
|
||||
static void touch_wakeup_prepare(void)
|
||||
{
|
||||
touch_pad_sleep_channel_t slp_config;
|
||||
touch_pad_fsm_stop();
|
||||
touch_pad_clear_channel_mask(SOC_TOUCH_SENSOR_BIT_MASK_MAX);
|
||||
touch_pad_sleep_channel_get_info(&slp_config);
|
||||
touch_pad_set_channel_mask(BIT(slp_config.touch_num));
|
||||
touch_pad_fsm_start();
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_touchpad_wakeup(void)
|
||||
{
|
||||
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN)) {
|
||||
ESP_LOGE(TAG, "Conflicting wake-up trigger: ext0");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_config.wakeup_triggers |= RTC_TOUCH_TRIG_EN;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
touch_pad_t esp_sleep_get_touchpad_wakeup_status(void)
|
||||
{
|
||||
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_TOUCHPAD) {
|
||||
return TOUCH_PAD_MAX;
|
||||
}
|
||||
touch_pad_t pad_num;
|
||||
esp_err_t ret = touch_pad_get_wakeup_status(&pad_num); //TODO 723diff commit id:fda9ada1b
|
||||
assert(ret == ESP_OK && "wakeup reason is RTC_TOUCH_TRIG_EN but SENS_TOUCH_MEAS_EN is zero");
|
||||
return pad_num;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level)
|
||||
{
|
||||
if (level < 0 || level > 1) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (!RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
||||
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_config.ext0_rtc_gpio_num = rtc_io_number_get(gpio_num);
|
||||
s_config.ext0_trigger_level = level;
|
||||
s_config.wakeup_triggers |= RTC_EXT0_TRIG_EN;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void ext0_wakeup_prepare(void)
|
||||
{
|
||||
int rtc_gpio_num = s_config.ext0_rtc_gpio_num;
|
||||
// Set GPIO to be used for wakeup
|
||||
REG_SET_FIELD(RTC_IO_EXT_WAKEUP0_REG, RTC_IO_EXT_WAKEUP0_SEL, rtc_gpio_num);
|
||||
// Set level which will trigger wakeup
|
||||
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
|
||||
s_config.ext0_trigger_level, RTC_CNTL_EXT_WAKEUP0_LV_S);
|
||||
// Find GPIO descriptor in the rtc_io_desc table and configure the pad
|
||||
const rtc_io_desc_t *desc = &rtc_io_desc[rtc_gpio_num];
|
||||
REG_SET_BIT(desc->reg, desc->mux);
|
||||
SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func);
|
||||
REG_SET_BIT(desc->reg, desc->ie);
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode)
|
||||
{
|
||||
if (mode > ESP_EXT1_WAKEUP_ANY_HIGH) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
// Translate bit map of GPIO numbers into the bit map of RTC IO numbers
|
||||
uint32_t rtc_gpio_mask = 0;
|
||||
for (int gpio = 0; mask; ++gpio, mask >>= 1) {
|
||||
if ((mask & 1) == 0) {
|
||||
continue;
|
||||
}
|
||||
if (!RTC_GPIO_IS_VALID_GPIO(gpio)) {
|
||||
ESP_LOGE(TAG, "Not an RTC IO: GPIO%d", gpio);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
rtc_gpio_mask |= BIT(rtc_io_number_get(gpio));
|
||||
}
|
||||
s_config.ext1_rtc_gpio_mask = rtc_gpio_mask;
|
||||
s_config.ext1_trigger_mode = mode;
|
||||
s_config.wakeup_triggers |= RTC_EXT1_TRIG_EN;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void ext1_wakeup_prepare(void)
|
||||
{
|
||||
// Configure all RTC IOs selected as ext1 wakeup inputs
|
||||
uint32_t rtc_gpio_mask = s_config.ext1_rtc_gpio_mask;
|
||||
for (int gpio = 0; gpio < GPIO_PIN_COUNT && rtc_gpio_mask != 0; ++gpio) {
|
||||
int rtc_pin = rtc_io_number_get(gpio);
|
||||
if ((rtc_gpio_mask & BIT(rtc_pin)) == 0) {
|
||||
continue;
|
||||
}
|
||||
const rtc_io_desc_t *desc = &rtc_io_desc[rtc_pin];
|
||||
// Route pad to RTC
|
||||
REG_SET_BIT(desc->reg, desc->mux);
|
||||
SET_PERI_REG_BITS(desc->reg, 0x3, 0, desc->func);
|
||||
// set input enable in sleep mode
|
||||
REG_SET_BIT(desc->reg, desc->ie);
|
||||
// Pad configuration depends on RTC_PERIPH state in sleep mode
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) {
|
||||
// RTC_PERIPH will be powered down, so RTC_IO_ registers will
|
||||
// loose their state. Lock pad configuration.
|
||||
// Pullups/pulldowns also need to be disabled.
|
||||
REG_CLR_BIT(desc->reg, desc->pulldown);
|
||||
REG_CLR_BIT(desc->reg, desc->pullup);
|
||||
REG_SET_BIT(RTC_CNTL_PAD_HOLD_REG, desc->hold_force);
|
||||
}
|
||||
// Keep track of pins which are processed to bail out early
|
||||
rtc_gpio_mask &= ~BIT(rtc_pin);
|
||||
}
|
||||
// Clear state from previous wakeup
|
||||
REG_SET_BIT(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_STATUS_CLR);
|
||||
// Set pins to be used for wakeup
|
||||
REG_SET_FIELD(RTC_CNTL_EXT_WAKEUP1_REG, RTC_CNTL_EXT_WAKEUP1_SEL, s_config.ext1_rtc_gpio_mask);
|
||||
// Set logic function (any low, all high)
|
||||
SET_PERI_REG_BITS(RTC_CNTL_EXT_WAKEUP_CONF_REG, 0x1,
|
||||
s_config.ext1_trigger_mode, RTC_CNTL_EXT_WAKEUP1_LV_S);
|
||||
}
|
||||
|
||||
uint64_t esp_sleep_get_ext1_wakeup_status(void)
|
||||
{
|
||||
if (esp_sleep_get_wakeup_cause() != ESP_SLEEP_WAKEUP_EXT1) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t status = REG_GET_FIELD(RTC_CNTL_EXT_WAKEUP1_STATUS_REG, RTC_CNTL_EXT_WAKEUP1_STATUS);
|
||||
// Translate bit map of RTC IO numbers into the bit map of GPIO numbers
|
||||
uint64_t gpio_mask = 0;
|
||||
for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) {
|
||||
if (!RTC_GPIO_IS_VALID_GPIO(gpio)) {
|
||||
continue;
|
||||
}
|
||||
int rtc_pin = rtc_io_number_get(gpio);
|
||||
if ((status & BIT(rtc_pin)) == 0) {
|
||||
continue;
|
||||
}
|
||||
gpio_mask |= 1ULL << gpio;
|
||||
}
|
||||
return gpio_mask;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_gpio_wakeup(void)
|
||||
{
|
||||
if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
||||
ESP_LOGE(TAG, "Conflicting wake-up triggers: touch / ULP");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
s_config.wakeup_triggers |= RTC_GPIO_TRIG_EN;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_uart_wakeup(int uart_num)
|
||||
{
|
||||
if (uart_num == 0) {
|
||||
s_config.wakeup_triggers |= RTC_UART0_TRIG_EN;
|
||||
} else if (uart_num == 1) {
|
||||
s_config.wakeup_triggers |= RTC_UART1_TRIG_EN;
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_enable_wifi_wakeup(void)
|
||||
{
|
||||
s_config.wakeup_triggers |= RTC_MAC_TRIG_EN;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void)
|
||||
{
|
||||
if (rtc_get_reset_reason(0) != DEEPSLEEP_RESET && !s_light_sleep_wakeup) {
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
|
||||
uint32_t wakeup_cause = REG_GET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_CAUSE);
|
||||
if (wakeup_cause & RTC_EXT0_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_EXT0;
|
||||
} else if (wakeup_cause & RTC_EXT1_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_EXT1;
|
||||
} else if (wakeup_cause & RTC_TIMER_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_TIMER;
|
||||
} else if (wakeup_cause & RTC_TOUCH_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_TOUCHPAD;
|
||||
} else if (wakeup_cause & RTC_ULP_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_ULP;
|
||||
} else if (wakeup_cause & RTC_GPIO_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_GPIO;
|
||||
} else if (wakeup_cause & (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN)) {
|
||||
return ESP_SLEEP_WAKEUP_UART;
|
||||
} else if (wakeup_cause & RTC_MAC_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_WIFI;
|
||||
} else if (wakeup_cause & RTC_COCPU_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_ULP;
|
||||
} else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) {
|
||||
return ESP_SLEEP_WAKEUP_COCPU_TRAP_TRIG;
|
||||
} else {
|
||||
return ESP_SLEEP_WAKEUP_UNDEFINED;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
|
||||
esp_sleep_pd_option_t option)
|
||||
{
|
||||
if (domain >= ESP_PD_DOMAIN_MAX || option > ESP_PD_OPTION_AUTO) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
s_config.pd_options[domain] = option;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static uint32_t get_power_down_flags(void)
|
||||
{
|
||||
// Where needed, convert AUTO options to ON. Later interpret AUTO as OFF.
|
||||
|
||||
// RTC_SLOW_MEM is needed for the ULP, so keep RTC_SLOW_MEM powered up if ULP
|
||||
// is used and RTC_SLOW_MEM is Auto.
|
||||
// If there is any data placed into .rtc.data or .rtc.bss segments, and
|
||||
// RTC_SLOW_MEM is Auto, keep it powered up as well.
|
||||
|
||||
// Labels are defined in the linker script, see esp32s3.ld.
|
||||
extern int _rtc_slow_length;
|
||||
|
||||
if ((s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] == ESP_PD_OPTION_AUTO) &&
|
||||
((size_t) &_rtc_slow_length > 0 ||
|
||||
(s_config.wakeup_triggers & RTC_ULP_TRIG_EN))) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] = ESP_PD_OPTION_ON;
|
||||
}
|
||||
|
||||
// RTC_FAST_MEM is needed for deep sleep stub.
|
||||
// If RTC_FAST_MEM is Auto, keep it powered on, so that deep sleep stub
|
||||
// can run.
|
||||
// In the new chip revision, deep sleep stub will be optional,
|
||||
// and this can be changed.
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] == ESP_PD_OPTION_AUTO) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] = ESP_PD_OPTION_ON;
|
||||
}
|
||||
|
||||
// RTC_PERIPH is needed for EXT0 wakeup and GPIO wakeup.
|
||||
// If RTC_PERIPH is auto, and EXT0/GPIO aren't enabled, power down RTC_PERIPH.
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] == ESP_PD_OPTION_AUTO) {
|
||||
if (s_config.wakeup_triggers & (RTC_EXT0_TRIG_EN | RTC_GPIO_TRIG_EN)) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_ON;
|
||||
} else if (s_config.wakeup_triggers & (RTC_TOUCH_TRIG_EN | RTC_ULP_TRIG_EN)) {
|
||||
// In both rev. 0 and rev. 1 of ESP32, forcing power up of RTC_PERIPH
|
||||
// prevents ULP timer and touch FSMs from working correctly.
|
||||
s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] = ESP_PD_OPTION_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_XTAL] == ESP_PD_OPTION_AUTO) {
|
||||
s_config.pd_options[ESP_PD_DOMAIN_XTAL] = ESP_PD_OPTION_OFF;
|
||||
}
|
||||
|
||||
const char *option_str[] = {"OFF", "ON", "AUTO(OFF)" /* Auto works as OFF */};
|
||||
ESP_LOGD(TAG, "RTC_PERIPH: %s, RTC_SLOW_MEM: %s, RTC_FAST_MEM: %s",
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH]],
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM]],
|
||||
option_str[s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM]]);
|
||||
|
||||
// Prepare flags based on the selected options
|
||||
uint32_t pd_flags = 0;
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_FAST_MEM] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_FAST_MEM;
|
||||
}
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_SLOW_MEM] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_SLOW_MEM;
|
||||
}
|
||||
if (s_config.pd_options[ESP_PD_DOMAIN_RTC_PERIPH] != ESP_PD_OPTION_ON) {
|
||||
pd_flags |= RTC_SLEEP_PD_RTC_PERIPH;
|
||||
}
|
||||
return pd_flags;
|
||||
}
|
327
components/esp32s3/spiram.c
Normal file
327
components/esp32s3/spiram.c
Normal file
@ -0,0 +1,327 @@
|
||||
/*
|
||||
Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if
|
||||
we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
|
||||
*/
|
||||
|
||||
// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp32s3/spiram.h"
|
||||
#include "spiram_psram.h"
|
||||
#include "esp_log.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "soc/soc.h"
|
||||
#include "esp_heap_caps_init.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
|
||||
#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
|
||||
static const char *TAG = "spiram";
|
||||
|
||||
#if CONFIG_SPIRAM_SPEED_40M
|
||||
#define PSRAM_SPEED PSRAM_CACHE_S40M
|
||||
#elif CONFIG_SPIRAM_SPEED_80M
|
||||
#define PSRAM_SPEED PSRAM_CACHE_S80M
|
||||
#else
|
||||
#define PSRAM_SPEED PSRAM_CACHE_S20M
|
||||
#endif
|
||||
|
||||
static bool spiram_inited = false;
|
||||
|
||||
|
||||
/*
|
||||
Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
|
||||
true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
|
||||
initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
|
||||
*/
|
||||
bool esp_spiram_test(void)
|
||||
{
|
||||
size_t spiram_size = esp_spiram_get_size();
|
||||
volatile int *spiram = (volatile int *)(SOC_EXTRAM_DATA_HIGH - spiram_size);
|
||||
size_t p;
|
||||
size_t s = spiram_size;
|
||||
int errct = 0;
|
||||
int initial_err = -1;
|
||||
|
||||
if (SOC_EXTRAM_DATA_SIZE < spiram_size) {
|
||||
ESP_EARLY_LOGW(TAG, "Only test spiram from %08x to %08x\n", SOC_EXTRAM_DATA_LOW, SOC_EXTRAM_DATA_HIGH);
|
||||
spiram = (volatile int *)SOC_EXTRAM_DATA_LOW;
|
||||
s = SOC_EXTRAM_DATA_HIGH - SOC_EXTRAM_DATA_LOW;
|
||||
}
|
||||
for (p = 0; p < (s / sizeof(int)); p += 8) {
|
||||
spiram[p] = p ^ 0xAAAAAAAA;
|
||||
}
|
||||
for (p = 0; p < (s / sizeof(int)); p += 8) {
|
||||
if (spiram[p] != (p ^ 0xAAAAAAAA)) {
|
||||
errct++;
|
||||
if (errct == 1) {
|
||||
initial_err = p * 4;
|
||||
}
|
||||
if (errct < 4) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI SRAM error@%08x:%08x/%08x \n", &spiram[p], spiram[p], p ^ 0xAAAAAAAA);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (errct) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s / 32, initial_err + SOC_EXTRAM_DATA_LOW);
|
||||
return false;
|
||||
} else {
|
||||
ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
void IRAM_ATTR esp_spiram_init_cache(void)
|
||||
{
|
||||
size_t spiram_size = esp_spiram_get_size();
|
||||
Cache_Suspend_DCache();
|
||||
if ((SOC_EXTRAM_DATA_HIGH - SOC_EXTRAM_DATA_LOW) >= spiram_size) {
|
||||
Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SOC_EXTRAM_DATA_HIGH - spiram_size, 0, 64, spiram_size >> 16, 0);
|
||||
} else {
|
||||
Cache_Dbus_MMU_Set(MMU_ACCESS_SPIRAM, SOC_EXTRAM_DATA_HIGH - spiram_size, 0, 64, (SOC_EXTRAM_DATA_HIGH - SOC_EXTRAM_DATA_LOW) >> 16, 0);
|
||||
}
|
||||
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE0_BUS);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
REG_CLR_BIT(EXTMEM_DCACHE_CTRL1_REG, EXTMEM_DCACHE_SHUT_CORE1_BUS);
|
||||
#endif
|
||||
Cache_Resume_DCache(0);
|
||||
}
|
||||
|
||||
static uint32_t pages_for_flash = 0;
|
||||
static uint32_t instrcution_in_spiram = 0;
|
||||
static uint32_t rodata_in_spiram = 0;
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
static int instr_flash2spiram_offs = 0;
|
||||
static uint32_t instr_start_page = 0;
|
||||
static uint32_t instr_end_page = 0;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
static int rodata_flash2spiram_offs = 0;
|
||||
static uint32_t rodata_start_page = 0;
|
||||
static uint32_t rodata_end_page = 0;
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS || CONFIG_SPIRAM_RODATA
|
||||
static uint32_t page0_mapped = 0;
|
||||
static uint32_t page0_page = INVALID_PHY_PAGE;
|
||||
#endif
|
||||
|
||||
uint32_t esp_spiram_instruction_access_enabled(void)
|
||||
{
|
||||
return instrcution_in_spiram;
|
||||
}
|
||||
|
||||
uint32_t esp_spiram_rodata_access_enabled(void)
|
||||
{
|
||||
return rodata_in_spiram;
|
||||
}
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
esp_err_t esp_spiram_enable_instruction_access(void)
|
||||
{
|
||||
size_t spiram_size = esp_spiram_get_size();
|
||||
uint32_t pages_in_flash = 0;
|
||||
pages_in_flash += Cache_Count_Flash_Pages(CACHE_IBUS, &page0_mapped);
|
||||
if ((pages_in_flash + pages_for_flash) > (spiram_size >> 16)) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the instructions, has %d pages, need %d pages.", (spiram_size >> 16), (pages_in_flash + pages_for_flash));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_EARLY_LOGI(TAG, "Instructions copied and mapped to SPIRAM");
|
||||
uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START);
|
||||
instr_flash2spiram_offs = mmu_value - pages_for_flash;
|
||||
ESP_EARLY_LOGV(TAG, "Instructions from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, instr_flash2spiram_offs);
|
||||
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(CACHE_IBUS, IRAM0_CACHE_ADDRESS_LOW, pages_for_flash, &page0_page);
|
||||
instrcution_in_spiram = 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
esp_err_t esp_spiram_enable_rodata_access(void)
|
||||
{
|
||||
size_t spiram_size = esp_spiram_get_size();
|
||||
uint32_t pages_in_flash = 0;
|
||||
pages_in_flash += Cache_Count_Flash_Pages(CACHE_DBUS, &page0_mapped);
|
||||
|
||||
if ((pages_in_flash + pages_for_flash) > (spiram_size >> 16)) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI RAM space not enough for the read only data.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
ESP_EARLY_LOGI(TAG, "Read only data copied and mapped to SPIRAM");
|
||||
uint32_t mmu_value = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
|
||||
rodata_flash2spiram_offs = mmu_value - pages_for_flash;
|
||||
ESP_EARLY_LOGV(TAG, "Rodata from flash page%d copy to SPIRAM page%d, Offset: %d", mmu_value, pages_for_flash, rodata_flash2spiram_offs);
|
||||
pages_for_flash = Cache_Flash_To_SPIRAM_Copy(CACHE_DBUS, DRAM0_CACHE_ADDRESS_LOW, pages_for_flash, &page0_page);
|
||||
rodata_in_spiram = 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
|
||||
void instruction_flash_page_info_init(void)
|
||||
{
|
||||
uint32_t instr_page_cnt = ((uint32_t)&_instruction_reserved_end - SOC_IROM_LOW + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||
|
||||
instr_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_IROM_MMU_START);
|
||||
instr_start_page &= MMU_ADDRESS_MASK;
|
||||
instr_end_page = instr_start_page + instr_page_cnt - 1;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR instruction_flash_start_page_get(void)
|
||||
{
|
||||
return instr_start_page;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR instruction_flash_end_page_get(void)
|
||||
{
|
||||
return instr_end_page;
|
||||
}
|
||||
|
||||
int IRAM_ATTR instruction_flash2spiram_offset(void)
|
||||
{
|
||||
return instr_flash2spiram_offs;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG_SPIRAM_RODATA
|
||||
void rodata_flash_page_info_init(void)
|
||||
{
|
||||
uint32_t rodata_page_cnt = ((uint32_t)&_rodata_reserved_end - ((uint32_t)&_rodata_reserved_start & ~ (MMU_PAGE_SIZE - 1)) + MMU_PAGE_SIZE - 1) / MMU_PAGE_SIZE;
|
||||
|
||||
rodata_start_page = *(volatile uint32_t *)(DR_REG_MMU_TABLE + CACHE_DROM_MMU_START);
|
||||
rodata_start_page &= MMU_ADDRESS_MASK;
|
||||
rodata_end_page = rodata_start_page + rodata_page_cnt - 1;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR rodata_flash_start_page_get(void)
|
||||
{
|
||||
return rodata_start_page;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR rodata_flash_end_page_get(void)
|
||||
{
|
||||
return rodata_end_page;
|
||||
}
|
||||
|
||||
int IRAM_ATTR rodata_flash2spiram_offset(void)
|
||||
{
|
||||
return rodata_flash2spiram_offs;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t esp_spiram_init(void)
|
||||
{
|
||||
esp_err_t r;
|
||||
r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
|
||||
if (r != ESP_OK) {
|
||||
#if CONFIG_SPIRAM_IGNORE_NOTFOUND
|
||||
ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
spiram_inited = true;
|
||||
#if (CONFIG_SPIRAM_SIZE != -1)
|
||||
if (esp_spiram_get_size() != CONFIG_SPIRAM_SIZE) {
|
||||
ESP_EARLY_LOGE(TAG, "Expected %dKiB chip but found %dKiB chip. Bailing out..", CONFIG_SPIRAM_SIZE / 1024, esp_spiram_get_size() / 1024);
|
||||
return ESP_ERR_INVALID_SIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
ESP_EARLY_LOGI(TAG, "Found %dMBit SPI RAM device",
|
||||
(esp_spiram_get_size() * 8) / (1024 * 1024));
|
||||
ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_S40M ? "sram 40m" : \
|
||||
PSRAM_SPEED == PSRAM_CACHE_S80M ? "sram 80m" : "sram 20m");
|
||||
ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
|
||||
(PSRAM_MODE == PSRAM_VADDR_MODE_EVENODD) ? "even/odd (2-core)" : \
|
||||
(PSRAM_MODE == PSRAM_VADDR_MODE_LOWHIGH) ? "low/high (2-core)" : \
|
||||
(PSRAM_MODE == PSRAM_VADDR_MODE_NORMAL) ? "normal (1-core)" : "ERROR");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t esp_spiram_add_to_heapalloc(void)
|
||||
{
|
||||
size_t spiram_size = esp_spiram_get_size();
|
||||
uint32_t size_for_flash = (pages_for_flash << 16);
|
||||
ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", (spiram_size - (pages_for_flash << 16)) / 1024);
|
||||
//Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's
|
||||
//no need to explicitly specify them.
|
||||
|
||||
return heap_caps_add_region((intptr_t)SOC_EXTRAM_DATA_HIGH - spiram_size + size_for_flash, (intptr_t)SOC_EXTRAM_DATA_HIGH - 1);
|
||||
}
|
||||
|
||||
|
||||
static uint8_t *dma_heap;
|
||||
|
||||
esp_err_t esp_spiram_reserve_dma_pool(size_t size)
|
||||
{
|
||||
if (size == 0) {
|
||||
return ESP_OK; //no-op
|
||||
}
|
||||
ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size / 1024);
|
||||
dma_heap = heap_caps_malloc(size, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
|
||||
if (!dma_heap) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
uint32_t caps[] = {MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT | MALLOC_CAP_32BIT};
|
||||
return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap + size - 1);
|
||||
}
|
||||
|
||||
size_t esp_spiram_get_size(void)
|
||||
{
|
||||
if (!spiram_inited) {
|
||||
ESP_EARLY_LOGE(TAG, "SPI RAM not initialized");
|
||||
abort();
|
||||
}
|
||||
|
||||
psram_size_t size = psram_get_size();
|
||||
if (size == PSRAM_SIZE_16MBITS) {
|
||||
return 2 * 1024 * 1024;
|
||||
}
|
||||
if (size == PSRAM_SIZE_32MBITS) {
|
||||
return 4 * 1024 * 1024;
|
||||
}
|
||||
if (size == PSRAM_SIZE_64MBITS) {
|
||||
return 8 * 1024 * 1024;
|
||||
}
|
||||
return CONFIG_SPIRAM_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
|
||||
otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
|
||||
*/
|
||||
void IRAM_ATTR esp_spiram_writeback_cache(void)
|
||||
{
|
||||
extern void Cache_WriteBack_All(void);
|
||||
Cache_WriteBack_All();
|
||||
}
|
||||
|
||||
#endif
|
541
components/esp32s3/spiram_psram.c
Normal file
541
components/esp32s3/spiram_psram.c
Normal file
@ -0,0 +1,541 @@
|
||||
/*
|
||||
Driver bits for PSRAM chips (at the moment only the ESP-PSRAM32 chip).
|
||||
*/
|
||||
|
||||
// Copyright 2013-2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "string.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_log.h"
|
||||
#include "spiram_psram.h"
|
||||
#include "esp32s3/rom/spi_flash.h"
|
||||
#include "esp32s3/rom/opi_flash.h"
|
||||
#include "esp32s3/rom/cache.h"
|
||||
#include "esp32s3/rom/efuse.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_rom_efuse.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/spi_caps.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_common_internal.h"
|
||||
#include "driver/spi_common.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#if CONFIG_SPIRAM
|
||||
#include "soc/rtc.h"
|
||||
|
||||
static const char* TAG = "psram";
|
||||
|
||||
//Commands for PSRAM chip
|
||||
#define PSRAM_READ 0x03
|
||||
#define PSRAM_FAST_READ 0x0B
|
||||
#define PSRAM_FAST_READ_DUMMY 0x3
|
||||
#define PSRAM_FAST_READ_QUAD 0xEB
|
||||
#define PSRAM_FAST_READ_QUAD_DUMMY 0x5
|
||||
#define PSRAM_WRITE 0x02
|
||||
#define PSRAM_QUAD_WRITE 0x38
|
||||
#define PSRAM_ENTER_QMODE 0x35
|
||||
#define PSRAM_EXIT_QMODE 0xF5
|
||||
#define PSRAM_RESET_EN 0x66
|
||||
#define PSRAM_RESET 0x99
|
||||
#define PSRAM_SET_BURST_LEN 0xC0
|
||||
#define PSRAM_DEVICE_ID 0x9F
|
||||
// ID
|
||||
#define PSRAM_ID_KGD_M 0xff
|
||||
#define PSRAM_ID_KGD_S 8
|
||||
#define PSRAM_ID_KGD 0x5d
|
||||
#define PSRAM_ID_EID_M 0xff
|
||||
#define PSRAM_ID_EID_S 16
|
||||
|
||||
// Use the [7:5](bit7~bit5) of EID to distinguish the psram size:
|
||||
//
|
||||
// BIT7 | BIT6 | BIT5 | SIZE(MBIT)
|
||||
// -------------------------------------
|
||||
// 0 | 0 | 0 | 16
|
||||
// 0 | 0 | 1 | 32
|
||||
// 0 | 1 | 0 | 64
|
||||
#define PSRAM_EID_SIZE_M 0x07
|
||||
#define PSRAM_EID_SIZE_S 5
|
||||
|
||||
#define PSRAM_KGD(id) (((id) >> PSRAM_ID_KGD_S) & PSRAM_ID_KGD_M)
|
||||
#define PSRAM_EID(id) (((id) >> PSRAM_ID_EID_S) & PSRAM_ID_EID_M)
|
||||
#define PSRAM_SIZE_ID(id) ((PSRAM_EID(id) >> PSRAM_EID_SIZE_S) & PSRAM_EID_SIZE_M)
|
||||
#define PSRAM_IS_VALID(id) (PSRAM_KGD(id) == PSRAM_ID_KGD)
|
||||
|
||||
// For the old version 32Mbit psram, using the spicial driver */
|
||||
#define PSRAM_IS_32MBIT_VER0(id) (PSRAM_EID(id) == 0x20)
|
||||
#define PSRAM_IS_64MBIT_TRIAL(id) (PSRAM_EID(id) == 0x26)
|
||||
|
||||
// IO-pins for PSRAM.
|
||||
// WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines
|
||||
// hardcode the flash pins as well, making this code incompatible with either a setup
|
||||
// that has the flash on non-standard pins or ESP32s with built-in flash.
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
// PSRAM clock and cs IO should be configured based on hardware design.
|
||||
#define PSRAM_CLK_IO CONFIG_DEFAULT_PSRAM_CLK_IO // Default value is 30
|
||||
#define PSRAM_CS_IO CONFIG_DEFAULT_PSRAM_CS_IO // Default value is 26
|
||||
#define PSRAM_SPIQ_SD0_IO SPI_Q_GPIO_NUM
|
||||
#define PSRAM_SPID_SD1_IO SPI_D_GPIO_NUM
|
||||
#define PSRAM_SPIWP_SD3_IO SPI_WP_GPIO_NUM
|
||||
#define PSRAM_SPIHD_SD2_IO SPI_HD_GPIO_NUM
|
||||
|
||||
#define CS_PSRAM_SEL SPI_MEM_CS1_DIS_M
|
||||
#define CS_FLASH_SEL SPI_MEM_CS0_DIS_M
|
||||
|
||||
#define PSRAM_IO_MATRIX_DUMMY_20M 0
|
||||
#define PSRAM_IO_MATRIX_DUMMY_40M 0
|
||||
#define PSRAM_IO_MATRIX_DUMMY_80M 0
|
||||
#define _SPI_CACHE_PORT 0
|
||||
#define _SPI_FLASH_PORT 1
|
||||
#define _SPI_80M_CLK_DIV 1
|
||||
#define _SPI_40M_CLK_DIV 2
|
||||
#define _SPI_20M_CLK_DIV 4
|
||||
|
||||
typedef enum {
|
||||
PSRAM_CLK_MODE_NORM = 0, /*!< Normal SPI mode */
|
||||
PSRAM_CLK_MODE_A1C, /*!< ONE extra clock cycles after CS is set high level */
|
||||
PSRAM_CLK_MODE_A2C, /*!< Two extra clock cycles after CS is set high level */
|
||||
PSRAM_CLK_MODE_ALON, /*!< clock always on */
|
||||
PSRAM_CLK_MODE_MAX,
|
||||
} psram_clk_mode_t;
|
||||
|
||||
|
||||
typedef enum {
|
||||
PSRAM_EID_SIZE_16MBITS = 0,
|
||||
PSRAM_EID_SIZE_32MBITS = 1,
|
||||
PSRAM_EID_SIZE_64MBITS = 2,
|
||||
} psram_eid_size_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t flash_clk_io;
|
||||
uint8_t flash_cs_io;
|
||||
uint8_t psram_clk_io;
|
||||
uint8_t psram_cs_io;
|
||||
uint8_t psram_spiq_sd0_io;
|
||||
uint8_t psram_spid_sd1_io;
|
||||
uint8_t psram_spiwp_sd3_io;
|
||||
uint8_t psram_spihd_sd2_io;
|
||||
} psram_io_t;
|
||||
|
||||
#define PSRAM_IO_CONF_DEFAULT() { \
|
||||
.flash_clk_io = FLASH_CLK_IO, \
|
||||
.flash_cs_io = FLASH_CS_IO, \
|
||||
.psram_clk_io = PSRAM_CLK_IO, \
|
||||
.psram_cs_io = PSRAM_CS_IO, \
|
||||
.psram_spiq_sd0_io = PSRAM_SPIQ_SD0_IO, \
|
||||
.psram_spid_sd1_io = PSRAM_SPID_SD1_IO, \
|
||||
.psram_spiwp_sd3_io = PSRAM_SPIWP_SD3_IO, \
|
||||
.psram_spihd_sd2_io = PSRAM_SPIHD_SD2_IO, \
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
PSRAM_SPI_1 = 0x1,
|
||||
/* PSRAM_SPI_2, */
|
||||
/* PSRAM_SPI_3, */
|
||||
PSRAM_SPI_MAX ,
|
||||
} psram_spi_num_t;
|
||||
|
||||
typedef enum {
|
||||
PSRAM_CMD_QPI,
|
||||
PSRAM_CMD_SPI,
|
||||
} psram_cmd_mode_t;
|
||||
|
||||
typedef esp_rom_spi_cmd_t psram_cmd_t;
|
||||
|
||||
static uint32_t s_psram_id = 0;
|
||||
static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
|
||||
extern void esp_rom_spi_set_op_mode(int spi_num, esp_rom_spiflash_read_mode_t mode);
|
||||
|
||||
static void psram_set_op_mode(int spi_num, psram_cmd_mode_t mode)
|
||||
{
|
||||
if (mode == PSRAM_CMD_QPI) {
|
||||
esp_rom_spi_set_op_mode(spi_num, ESP_ROM_SPIFLASH_QIO_MODE);
|
||||
SET_PERI_REG_MASK(SPI_MEM_CTRL_REG(spi_num), SPI_MEM_FCMD_QUAD_M);
|
||||
} else if (mode == PSRAM_CMD_SPI) {
|
||||
esp_rom_spi_set_op_mode(spi_num, ESP_ROM_SPIFLASH_SLOWRD_MODE);
|
||||
}
|
||||
}
|
||||
static void _psram_exec_cmd(int spi_num,
|
||||
uint32_t cmd, int cmd_bit_len,
|
||||
uint32_t addr, int addr_bit_len,
|
||||
int dummy_bits,
|
||||
uint8_t* mosi_data, int mosi_bit_len,
|
||||
uint8_t* miso_data, int miso_bit_len)
|
||||
{
|
||||
esp_rom_spi_cmd_t conf;
|
||||
uint32_t _addr = addr;
|
||||
conf.addr = &_addr;
|
||||
conf.addrBitLen = addr_bit_len;
|
||||
conf.cmd = cmd;
|
||||
conf.cmdBitLen = cmd_bit_len;
|
||||
conf.dummyBitLen = dummy_bits; // There is a hardware approach on chip723
|
||||
conf.txData = (uint32_t*) mosi_data;
|
||||
conf.txDataBitLen = mosi_bit_len;
|
||||
conf.rxData = (uint32_t*) miso_data;
|
||||
conf.rxDataBitLen = miso_bit_len;
|
||||
esp_rom_spi_cmd_config(spi_num, &conf);
|
||||
}
|
||||
|
||||
void psram_exec_cmd(int spi_num, psram_cmd_mode_t mode,
|
||||
uint32_t cmd, int cmd_bit_len,
|
||||
uint32_t addr, int addr_bit_len,
|
||||
int dummy_bits,
|
||||
uint8_t* mosi_data, int mosi_bit_len,
|
||||
uint8_t* miso_data, int miso_bit_len,
|
||||
uint32_t cs_mask,
|
||||
bool is_write_erase_operation)
|
||||
{
|
||||
uint32_t backup_usr = READ_PERI_REG(SPI_MEM_USER_REG(spi_num));
|
||||
uint32_t backup_usr1 = READ_PERI_REG(SPI_MEM_USER1_REG(spi_num));
|
||||
uint32_t backup_usr2 = READ_PERI_REG(SPI_MEM_USER2_REG(spi_num));
|
||||
uint32_t backup_ctrl = READ_PERI_REG(SPI_MEM_CTRL_REG(spi_num));
|
||||
psram_set_op_mode(spi_num, mode);
|
||||
_psram_exec_cmd(spi_num, cmd, cmd_bit_len, addr, addr_bit_len,
|
||||
dummy_bits, mosi_data, mosi_bit_len, miso_data, miso_bit_len);
|
||||
esp_rom_spi_cmd_start(spi_num, miso_data, miso_bit_len / 8, cs_mask, is_write_erase_operation);
|
||||
|
||||
WRITE_PERI_REG(SPI_MEM_USER_REG(spi_num), backup_usr);
|
||||
WRITE_PERI_REG(SPI_MEM_USER1_REG(spi_num), backup_usr1);
|
||||
WRITE_PERI_REG(SPI_MEM_USER2_REG(spi_num), backup_usr2);
|
||||
WRITE_PERI_REG(SPI_MEM_CTRL_REG(spi_num), backup_ctrl);
|
||||
}
|
||||
|
||||
//exit QPI mode(set back to SPI mode)
|
||||
static void psram_disable_qio_mode(int spi_num)
|
||||
{
|
||||
psram_exec_cmd(spi_num, PSRAM_CMD_QPI,
|
||||
PSRAM_EXIT_QMODE, 8, /* command and command bit len*/
|
||||
0, 0, /* address and address bit len*/
|
||||
0, /* dummy bit len */
|
||||
NULL, 0, /* tx data and tx bit len*/
|
||||
NULL, 0, /* rx data and rx bit len*/
|
||||
CS_PSRAM_SEL, /* cs bit mask*/
|
||||
false); /* whether is program/erase operation */
|
||||
}
|
||||
|
||||
//switch psram burst length(32 bytes or 1024 bytes)
|
||||
//datasheet says it should be 1024 bytes by default
|
||||
static void psram_set_wrap_burst_length(int spi_num, psram_cmd_mode_t mode)
|
||||
{
|
||||
psram_exec_cmd(spi_num, mode,
|
||||
PSRAM_SET_BURST_LEN, 8, /* command and command bit len*/
|
||||
0, 0, /* address and address bit len*/
|
||||
0, /* dummy bit len */
|
||||
NULL, 0, /* tx data and tx bit len*/
|
||||
NULL, 0, /* rx data and rx bit len*/
|
||||
CS_PSRAM_SEL, /* cs bit mask*/
|
||||
false); /* whether is program/erase operation */
|
||||
}
|
||||
|
||||
//send reset command to psram, in spi mode
|
||||
static void psram_reset_mode(int spi_num)
|
||||
{
|
||||
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
|
||||
PSRAM_RESET_EN, 8, /* command and command bit len*/
|
||||
0, 0, /* address and address bit len*/
|
||||
0, /* dummy bit len */
|
||||
NULL, 0, /* tx data and tx bit len*/
|
||||
NULL, 0, /* rx data and rx bit len*/
|
||||
CS_PSRAM_SEL, /* cs bit mask*/
|
||||
false); /* whether is program/erase operation */
|
||||
|
||||
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
|
||||
PSRAM_RESET, 8, /* command and command bit len*/
|
||||
0, 0, /* address and address bit len*/
|
||||
0, /* dummy bit len */
|
||||
NULL, 0, /* tx data and tx bit len*/
|
||||
NULL, 0, /* rx data and rx bit len*/
|
||||
CS_PSRAM_SEL, /* cs bit mask*/
|
||||
false); /* whether is program/erase operation */
|
||||
}
|
||||
|
||||
esp_err_t psram_enable_wrap(uint32_t wrap_size)
|
||||
{
|
||||
static int current_wrap_size = 0;
|
||||
if (current_wrap_size == wrap_size) {
|
||||
return ESP_OK;
|
||||
}
|
||||
switch (wrap_size) {
|
||||
case 32:
|
||||
case 0:
|
||||
psram_set_wrap_burst_length(PSRAM_SPI_1, PSRAM_CMD_QPI);
|
||||
current_wrap_size = wrap_size;
|
||||
return ESP_OK;
|
||||
case 16:
|
||||
case 64:
|
||||
default:
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
bool psram_support_wrap_size(uint32_t wrap_size)
|
||||
{
|
||||
switch (wrap_size) {
|
||||
case 0:
|
||||
case 32:
|
||||
return true;
|
||||
case 16:
|
||||
case 64:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//read psram id, should issue `psram_disable_qio_mode` before calling this
|
||||
static void psram_read_id(int spi_num, uint32_t* dev_id)
|
||||
{
|
||||
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
|
||||
PSRAM_DEVICE_ID, 8, /* command and command bit len*/
|
||||
0, 24, /* address and address bit len*/
|
||||
0, /* dummy bit len */
|
||||
NULL, 0, /* tx data and tx bit len*/
|
||||
(uint8_t*) dev_id, 24, /* rx data and rx bit len*/
|
||||
CS_PSRAM_SEL, /* cs bit mask*/
|
||||
false); /* whether is program/erase operation */
|
||||
}
|
||||
|
||||
//enter QPI mode
|
||||
static void IRAM_ATTR psram_enable_qio_mode(int spi_num)
|
||||
{
|
||||
psram_exec_cmd(spi_num, PSRAM_CMD_SPI,
|
||||
PSRAM_ENTER_QMODE, 8, /* command and command bit len*/
|
||||
0, 0, /* address and address bit len*/
|
||||
0, /* dummy bit len */
|
||||
NULL, 0, /* tx data and tx bit len*/
|
||||
NULL, 0, /* rx data and rx bit len*/
|
||||
CS_PSRAM_SEL, /* cs bit mask*/
|
||||
false); /* whether is program/erase operation */
|
||||
}
|
||||
|
||||
static void psram_set_spi1_cmd_cs_timing(psram_clk_mode_t clk_mode)
|
||||
{
|
||||
if (clk_mode == PSRAM_CLK_MODE_NORM) {
|
||||
// SPI1 Flash Operation port
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_TIME_V, 1, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_FLASH_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
} else {
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_FLASH_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
}
|
||||
}
|
||||
|
||||
static void psram_set_spi0_cache_cs_timing(psram_clk_mode_t clk_mode)
|
||||
{
|
||||
if (clk_mode == PSRAM_CLK_MODE_NORM) {
|
||||
// SPI0 SRAM Cache port
|
||||
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_TIME_V, 1, SPI_MEM_SPI_SMEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_SETUP_TIME_V, 0, SPI_MEM_SPI_SMEM_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_MEM_SPI_SMEM_AC_REG(_SPI_CACHE_PORT), SPI_MEM_SPI_SMEM_CS_HOLD_M | SPI_MEM_SPI_SMEM_CS_SETUP_M);
|
||||
// SPI0 Flash Cache port
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_TIME_V, 0, SPI_MEM_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_CTRL2_REG(_SPI_CACHE_PORT), SPI_MEM_CS_SETUP_TIME_V, 0, SPI_MEM_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_MEM_CS_HOLD_M | SPI_MEM_CS_SETUP_M);
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(SPI_MEM_USER_REG(_SPI_CACHE_PORT), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
}
|
||||
}
|
||||
|
||||
//psram gpio init , different working frequency we have different solutions
|
||||
static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
|
||||
{
|
||||
psram_io_t psram_io = PSRAM_IO_CONF_DEFAULT();
|
||||
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
|
||||
if (spiconfig == ESP_ROM_EFUSE_FLASH_DEFAULT_SPI) {
|
||||
/* FLASH pins(except wp / hd) are all configured via IO_MUX in rom. */
|
||||
} else {
|
||||
// FLASH pins are all configured via GPIO matrix in ROM.
|
||||
psram_io.flash_clk_io = EFUSE_SPICONFIG_RET_SPICLK(spiconfig);
|
||||
psram_io.flash_cs_io = EFUSE_SPICONFIG_RET_SPICS0(spiconfig);
|
||||
psram_io.psram_spiq_sd0_io = EFUSE_SPICONFIG_RET_SPIQ(spiconfig);
|
||||
psram_io.psram_spid_sd1_io = EFUSE_SPICONFIG_RET_SPID(spiconfig);
|
||||
psram_io.psram_spihd_sd2_io = EFUSE_SPICONFIG_RET_SPIHD(spiconfig);
|
||||
psram_io.psram_spiwp_sd3_io = esp_rom_efuse_get_flash_wp_gpio();
|
||||
}
|
||||
esp_rom_spiflash_select_qio_pins(psram_io.psram_spiwp_sd3_io, spiconfig);
|
||||
|
||||
if (psram_io.psram_cs_io == SPI_CS1_GPIO_NUM) {
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], FUNC_SPICS1_SPICS1);
|
||||
} else {
|
||||
esp_rom_gpio_connect_out_signal(psram_io.psram_cs_io, SPICS1_OUT_IDX, 0, 0);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[psram_io.psram_cs_io], PIN_FUNC_GPIO);
|
||||
}
|
||||
}
|
||||
|
||||
psram_size_t psram_get_size(void)
|
||||
{
|
||||
if ((PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_64MBITS) || PSRAM_IS_64MBIT_TRIAL(s_psram_id)) {
|
||||
return PSRAM_SIZE_64MBITS;
|
||||
} else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_32MBITS) {
|
||||
return PSRAM_SIZE_32MBITS;
|
||||
} else if (PSRAM_SIZE_ID(s_psram_id) == PSRAM_EID_SIZE_16MBITS) {
|
||||
return PSRAM_SIZE_16MBITS;
|
||||
} else {
|
||||
return PSRAM_SIZE_MAX;
|
||||
}
|
||||
return PSRAM_SIZE_MAX;
|
||||
}
|
||||
|
||||
//used in UT only
|
||||
bool psram_is_32mbit_ver0(void)
|
||||
{
|
||||
return PSRAM_IS_32MBIT_VER0(s_psram_id);
|
||||
}
|
||||
|
||||
static void psram_set_clk_mode(int spi_num, psram_clk_mode_t clk_mode)
|
||||
{
|
||||
if (spi_num == _SPI_CACHE_PORT) {
|
||||
REG_SET_FIELD(SPI_MEM_SRAM_CMD_REG(0), SPI_MEM_SCLK_MODE, clk_mode);
|
||||
} else if (spi_num == _SPI_FLASH_PORT) {
|
||||
REG_SET_FIELD(SPI_MEM_CTRL1_REG(1), SPI_MEM_CLK_MODE, clk_mode);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
|
||||
* Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
|
||||
*/
|
||||
esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode) //psram init
|
||||
{
|
||||
assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
|
||||
// GPIO related settings
|
||||
psram_gpio_config(mode);
|
||||
|
||||
/* SPI1: set spi1 clk mode, in order to send commands on SPI1 */
|
||||
/* SPI1: set cs timing(hold time) in order to send commands on SPI1 */
|
||||
psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_A1C);
|
||||
psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_A1C);
|
||||
|
||||
int spi_num = PSRAM_SPI_1;
|
||||
psram_disable_qio_mode(spi_num);
|
||||
psram_read_id(spi_num, &s_psram_id);
|
||||
if (!PSRAM_IS_VALID(s_psram_id)) {
|
||||
/* 16Mbit psram ID read error workaround:
|
||||
* treat the first read id as a dummy one as the pre-condition,
|
||||
* Send Read ID command again
|
||||
*/
|
||||
psram_read_id(spi_num, &s_psram_id);
|
||||
if (!PSRAM_IS_VALID(s_psram_id)) {
|
||||
ESP_EARLY_LOGE(TAG, "PSRAM ID read error: 0x%08x", s_psram_id);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
psram_clk_mode_t clk_mode = PSRAM_CLK_MODE_MAX;
|
||||
if (psram_is_32mbit_ver0()) {
|
||||
clk_mode = PSRAM_CLK_MODE_A1C;
|
||||
// SPI1: keep clock mode and cs timing for spi1
|
||||
} else {
|
||||
// For other psram, we don't need any extra clock cycles after cs get back to high level
|
||||
clk_mode = PSRAM_CLK_MODE_NORM;
|
||||
// SPI1: set clock mode and cs timing to normal mode
|
||||
psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM);
|
||||
psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM);
|
||||
}
|
||||
|
||||
/* SPI1: send psram reset command */
|
||||
/* SPI1: send QPI enable command */
|
||||
psram_reset_mode(PSRAM_SPI_1);
|
||||
psram_enable_qio_mode(PSRAM_SPI_1);
|
||||
|
||||
// after sending commands, set spi1 clock mode and cs timing to normal mode.
|
||||
// since all the operations are sent via SPI0 Cache
|
||||
/* SPI1: set clock mode to normal mode. */
|
||||
/* SPI1: set cs timing to normal */
|
||||
psram_set_clk_mode(_SPI_FLASH_PORT, PSRAM_CLK_MODE_NORM);
|
||||
psram_set_spi1_cmd_cs_timing(PSRAM_CLK_MODE_NORM);
|
||||
|
||||
/* SPI0: set spi0 clock mode */
|
||||
/* SPI0: set spi0 flash/cache cs timing */
|
||||
psram_set_clk_mode(_SPI_CACHE_PORT, clk_mode);
|
||||
psram_set_spi0_cache_cs_timing(clk_mode);
|
||||
|
||||
// SPI0: init SPI commands for Cache
|
||||
psram_cache_init(mode, vaddrmode);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void IRAM_ATTR psram_clock_set(int spi_num, int8_t freqdiv)
|
||||
{
|
||||
uint32_t freqbits;
|
||||
if (1 >= freqdiv) {
|
||||
WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), SPI_MEM_SCLK_EQU_SYSCLK);
|
||||
} else {
|
||||
freqbits = (((freqdiv-1)<<SPI_MEM_SCLKCNT_N_S)) | (((freqdiv/2-1)<<SPI_MEM_SCLKCNT_H_S)) | ((freqdiv-1)<<SPI_MEM_SCLKCNT_L_S);
|
||||
WRITE_PERI_REG(SPI_MEM_SRAM_CLK_REG(spi_num), freqbits);
|
||||
}
|
||||
}
|
||||
|
||||
//register initialization for sram cache params and r/w commands
|
||||
static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
|
||||
{
|
||||
int extra_dummy = 0;
|
||||
switch (psram_cache_mode) {
|
||||
case PSRAM_CACHE_S80M:
|
||||
psram_clock_set(0, 1);
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
|
||||
break;
|
||||
case PSRAM_CACHE_S40M:
|
||||
psram_clock_set(0, 2);
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
|
||||
break;
|
||||
case PSRAM_CACHE_S26M:
|
||||
psram_clock_set(0, 3);
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M;
|
||||
break;
|
||||
case PSRAM_CACHE_S20M:
|
||||
psram_clock_set(0, 4);
|
||||
extra_dummy = PSRAM_IO_MATRIX_DUMMY_20M;
|
||||
break;
|
||||
default:
|
||||
psram_clock_set(0, 2);
|
||||
break;
|
||||
}
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_DIO_M); //disable dio mode for cache command
|
||||
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_SRAM_QIO_M); //enable qio mode for cache command
|
||||
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_RCMD_M); //enable cache read command
|
||||
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_CACHE_SRAM_USR_WCMD_M); //enable cache write command
|
||||
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_ADDR_BITLEN_V, 23, SPI_MEM_SRAM_ADDR_BITLEN_S); //write address for cache command.
|
||||
SET_PERI_REG_MASK(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
|
||||
|
||||
//config sram cache r/w command
|
||||
SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
|
||||
SPI_MEM_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_SRAM_DWR_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
|
||||
SPI_MEM_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
|
||||
SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
|
||||
SPI_MEM_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
|
||||
SET_PERI_REG_BITS(SPI_MEM_SRAM_DRD_CMD_REG(0), SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ_QUAD,
|
||||
SPI_MEM_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
|
||||
SET_PERI_REG_BITS(SPI_MEM_CACHE_SCTRL_REG(0), SPI_MEM_SRAM_RDUMMY_CYCLELEN_V, PSRAM_FAST_READ_QUAD_DUMMY + extra_dummy,
|
||||
SPI_MEM_SRAM_RDUMMY_CYCLELEN_S); //dummy, psram cache : 40m--+1dummy,80m--+2dummy
|
||||
|
||||
CLEAR_PERI_REG_MASK(SPI_MEM_MISC_REG(0), SPI_MEM_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
|
||||
}
|
||||
#endif // CONFIG_SPIRAM
|
80
components/esp32s3/spiram_psram.h
Normal file
80
components/esp32s3/spiram_psram.h
Normal file
@ -0,0 +1,80 @@
|
||||
// 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 _PSRAM_H
|
||||
#define _PSRAM_H
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "esp_err.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
typedef enum {
|
||||
PSRAM_CACHE_S80M = 1,
|
||||
PSRAM_CACHE_S40M,
|
||||
PSRAM_CACHE_S26M,
|
||||
PSRAM_CACHE_S20M,
|
||||
PSRAM_CACHE_MAX,
|
||||
} psram_cache_mode_t;
|
||||
|
||||
typedef enum {
|
||||
PSRAM_SIZE_16MBITS = 0,
|
||||
PSRAM_SIZE_32MBITS = 1,
|
||||
PSRAM_SIZE_64MBITS = 2,
|
||||
PSRAM_SIZE_MAX,
|
||||
} psram_size_t;
|
||||
|
||||
/*
|
||||
See the TRM, chapter PID/MPU/MMU, header 'External RAM' for the definitions of these modes.
|
||||
|
||||
Important is that NORMAL works with the app CPU cache disabled, but gives huge cache coherency
|
||||
issues when both app and pro CPU are enabled. LOWHIGH and EVENODD do not have these coherency
|
||||
issues but cannot be used when the app CPU cache is disabled.
|
||||
*/
|
||||
typedef enum {
|
||||
PSRAM_VADDR_MODE_NORMAL=0, ///< App and pro CPU use their own flash cache for external RAM access
|
||||
PSRAM_VADDR_MODE_LOWHIGH, ///< App and pro CPU share external RAM caches: pro CPU has low 2M, app CPU has high 2M
|
||||
PSRAM_VADDR_MODE_EVENODD, ///< App and pro CPU share external RAM caches: pro CPU does even 32yte ranges, app does odd ones.
|
||||
} psram_vaddr_mode_t;
|
||||
|
||||
/**
|
||||
* @brief get psram size
|
||||
* @return
|
||||
* - PSRAM_SIZE_MAX if psram not enabled or not valid
|
||||
* - PSRAM size
|
||||
*/
|
||||
psram_size_t psram_get_size(void);
|
||||
|
||||
/**
|
||||
* @brief psram cache enable function
|
||||
*
|
||||
* Esp-idf uses this to initialize cache for psram, mapping it into the main memory
|
||||
* address space.
|
||||
*
|
||||
* @param mode SPI mode to access psram in
|
||||
* @param vaddrmode Mode the psram cache works in.
|
||||
* @return ESP_OK on success, ESP_ERR_INVALID_STATE when VSPI peripheral is needed but cannot be claimed.
|
||||
*/
|
||||
esp_err_t psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode);
|
||||
|
||||
typedef enum {
|
||||
SPIRAM_WRAP_MODE_16B,
|
||||
SPIRAM_WRAP_MODE_32B,
|
||||
SPIRAM_WRAP_MODE_64B,
|
||||
SPIRAM_WRAP_MODE_DISABLE
|
||||
} spiram_wrap_mode_t;
|
||||
|
||||
esp_err_t esp_spiram_wrap_set(spiram_wrap_mode_t mode);
|
||||
|
||||
|
||||
#endif
|
@ -1,12 +1,18 @@
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
|
||||
if(CONFIG_IDF_ENV_FPGA)
|
||||
list(APPEND srcs "src/fpga_overrides.c")
|
||||
endif()
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
# For bootloader, all we need from esp_common is headers
|
||||
idf_component_register(INCLUDE_DIRS include)
|
||||
idf_component_register(SRCS ${srcs}
|
||||
INCLUDE_DIRS include
|
||||
PRIV_REQUIRES soc)
|
||||
set_property(TARGET ${COMPONENT_LIB} APPEND PROPERTY INTERFACE_LINK_LIBRARIES "-Wl,--gc-sections")
|
||||
else()
|
||||
# Regular app build
|
||||
set(srcs "src/brownout.c"
|
||||
list(APPEND srcs "src/brownout.c"
|
||||
"src/esp_err.c"
|
||||
"src/dbg_stubs.c"
|
||||
"src/esp_err_to_name.c"
|
||||
@ -61,3 +67,8 @@ else()
|
||||
endforeach()
|
||||
|
||||
endif()
|
||||
|
||||
if(CONFIG_IDF_ENV_FPGA)
|
||||
# Forces the linker to include fpga stubs from this component
|
||||
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u esp_common_include_fpga_overrides")
|
||||
endif()
|
||||
|
@ -125,7 +125,7 @@ menu "Common ESP-related"
|
||||
depends on ESP_CONSOLE_UART_CUSTOM
|
||||
range 0 46
|
||||
default 1 if IDF_TARGET_ESP32
|
||||
default 43 if IDF_TARGET_ESP32S2
|
||||
default 43
|
||||
help
|
||||
This GPIO is used for console UART TX output in the ESP-IDF Bootloader and the app (including
|
||||
boot log output and default standard output and standard error of the app).
|
||||
@ -138,7 +138,7 @@ menu "Common ESP-related"
|
||||
depends on ESP_CONSOLE_UART_CUSTOM
|
||||
range 0 46
|
||||
default 3 if IDF_TARGET_ESP32
|
||||
default 44 if IDF_TARGET_ESP32S2
|
||||
default 44
|
||||
help
|
||||
This GPIO is used for UART RX input in the ESP-IDF Bootloader and the app (including
|
||||
default default standard input of the app).
|
||||
@ -292,6 +292,7 @@ menu "Common ESP-related"
|
||||
int
|
||||
default 2 if ESP32_UNIVERSAL_MAC_ADDRESSES_FOUR
|
||||
default 1 if ESP32_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||
default 1
|
||||
|
||||
config ESP_MAC_ADDR_UNIVERSE_ETH
|
||||
bool
|
||||
|
@ -5,5 +5,9 @@
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
COMPONENT_SRCDIRS := src
|
||||
|
||||
ifndef CONFIG_IDF_ENV_FPGA
|
||||
COMPONENT_OBJEXCLUDE += src/fpga_overrides.o
|
||||
endif
|
||||
|
||||
# disable stack protection in files which are involved in initialization of that feature
|
||||
src/stack_check.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS))
|
||||
|
@ -21,6 +21,8 @@
|
||||
#include "esp32/pm.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/pm.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/pm.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
57
components/esp_common/src/fpga_overrides.c
Normal file
57
components/esp_common/src/fpga_overrides.c
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2010-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/system_reg.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "esp_rom_uart.h"
|
||||
|
||||
extern void ets_update_cpu_frequency(uint32_t ticks_per_us);
|
||||
|
||||
void bootloader_clock_configure(void)
|
||||
{
|
||||
esp_rom_uart_tx_wait_idle(0);
|
||||
|
||||
uint32_t clock = 40000000;
|
||||
ets_update_cpu_frequency(clock / 1000000);
|
||||
REG_WRITE(RTC_CNTL_STORE5_REG, (clock >> 12) | ((clock >> 12) << 16));
|
||||
}
|
||||
|
||||
void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
uint8_t *buffer_bytes = (uint8_t *)buffer;
|
||||
for (int i = 0; i < length; i++) {
|
||||
buffer_bytes[i] = 0x5A;
|
||||
}
|
||||
}
|
||||
|
||||
void esp_clk_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void esp_perip_clk_init(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief No-op function, used to force linking this file
|
||||
*
|
||||
*/
|
||||
void esp_common_include_fpga_overrides(void)
|
||||
{
|
||||
}
|
@ -82,7 +82,7 @@ static void IRAM_ATTR tick_hook(void) {
|
||||
}
|
||||
#else
|
||||
static void IRAM_ATTR tick_hook(void) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
if (xPortGetCoreID()!=0) {
|
||||
return;
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ esp_err_t esp_base_mac_addr_get(uint8_t *mac)
|
||||
|
||||
esp_err_t esp_efuse_mac_get_custom(uint8_t *mac)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2
|
||||
return ESP_ERR_NOT_SUPPORTED; // TODO: support custom MAC in efuse
|
||||
#if !CONFIG_IDF_TARGET_ESP32
|
||||
return ESP_ERR_NOT_SUPPORTED;
|
||||
#else
|
||||
uint8_t version;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_MAC_CUSTOM_VER, &version, 8);
|
||||
@ -76,7 +76,7 @@ esp_err_t esp_efuse_mac_get_custom(uint8_t *mac)
|
||||
return ESP_ERR_INVALID_CRC;
|
||||
}
|
||||
return ESP_OK;
|
||||
#endif // IDF_TARGET_ESP32S2
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
|
||||
@ -86,7 +86,7 @@ esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
|
||||
return err;
|
||||
}
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
// Only ESP32 has MAC CRC in efuse, ESP32-S2 has internal efuse consistency checks
|
||||
// Only ESP32 has MAC CRC in efuse
|
||||
uint8_t efuse_crc;
|
||||
esp_efuse_read_field_blob(ESP_EFUSE_MAC_FACTORY_CRC, &efuse_crc, 8);
|
||||
uint8_t calc_crc = esp_rom_efuse_mac_address_crc8(mac, 6);
|
||||
|
@ -35,6 +35,8 @@ static const char *TAG = "esp32_eth_test";
|
||||
#define ETH_PING_DURATION_MS (5000)
|
||||
#define ETH_PING_END_TIMEOUT_MS (ETH_PING_DURATION_MS * 2)
|
||||
|
||||
#define TEST_ICMP_DESTINATION_DOMAIN_NAME "127.0.0.1"
|
||||
|
||||
// compute md5 of download file
|
||||
static md5_context_t md5_context;
|
||||
static uint8_t digest[16];
|
||||
@ -343,7 +345,7 @@ TEST_CASE("esp32 ethernet icmp test", "[ethernet][test_env=UT_T2_Ethernet]")
|
||||
memset(&hint, 0, sizeof(hint));
|
||||
memset(&target_addr, 0, sizeof(target_addr));
|
||||
/* convert URL to IP */
|
||||
TEST_ASSERT(getaddrinfo("www.espressif.com", NULL, &hint, &res) == 0);
|
||||
TEST_ASSERT(getaddrinfo(TEST_ICMP_DESTINATION_DOMAIN_NAME, NULL, &hint, &res) == 0);
|
||||
struct in_addr addr4 = ((struct sockaddr_in *)(res->ai_addr))->sin_addr;
|
||||
inet_addr_to_ip4addr(ip_2_ip4(&target_addr), &addr4);
|
||||
freeaddrinfo(res);
|
||||
|
51
components/esp_gdbstub/esp32s3/gdbstub_esp32s3.c
Normal file
51
components/esp_gdbstub/esp32s3/gdbstub_esp32s3.c
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/uart_periph.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "esp_gdbstub_common.h"
|
||||
|
||||
#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM
|
||||
|
||||
void esp_gdbstub_target_init()
|
||||
{
|
||||
}
|
||||
|
||||
int esp_gdbstub_getchar()
|
||||
{
|
||||
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_RXFIFO_CNT) == 0) {
|
||||
;
|
||||
}
|
||||
return REG_READ(UART_FIFO_AHB_REG(UART_NUM));
|
||||
}
|
||||
|
||||
void esp_gdbstub_putchar(int c)
|
||||
{
|
||||
while (REG_GET_FIELD(UART_STATUS_REG(UART_NUM), UART_TXFIFO_CNT) >= 126) {
|
||||
;
|
||||
}
|
||||
REG_WRITE(UART_FIFO_AHB_REG(UART_NUM), c);
|
||||
}
|
||||
|
||||
int esp_gdbstub_readmem(intptr_t addr)
|
||||
{
|
||||
if (addr < 0x20000000 || addr >= 0x80000000) {
|
||||
/* see cpu_configure_region_protection */
|
||||
return -1;
|
||||
}
|
||||
uint32_t val_aligned = *(uint32_t *)(addr & (~3));
|
||||
uint32_t shift = (addr & 3) * 8;
|
||||
return (val_aligned >> shift) & 0xff;
|
||||
}
|
18
components/esp_gdbstub/esp32s3/gdbstub_target_config.h
Normal file
18
components/esp_gdbstub/esp32s3/gdbstub_target_config.h
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
/* Number of extra TIE defined registers, not listed in the XCHAL */
|
||||
#define GDBSTUB_EXTRA_TIE_SIZE 1
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user