mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-03 12:44:33 +02:00
Merge branch 'feature/add_esp32h2_target' into 'master'
esp32h2: add esp32h2 build target See merge request espressif/esp-idf!13944
This commit is contained in:
9
Kconfig
9
Kconfig
@@ -11,6 +11,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
|||||||
config IDF_ENV_FPGA
|
config IDF_ENV_FPGA
|
||||||
# This option is for internal use only
|
# This option is for internal use only
|
||||||
bool
|
bool
|
||||||
|
default "y" if IDF_TARGET="esp32h2" # ESP32H2-TODO: IDF-3378
|
||||||
option env="IDF_ENV_FPGA"
|
option env="IDF_ENV_FPGA"
|
||||||
|
|
||||||
config IDF_TARGET_ARCH_RISCV
|
config IDF_TARGET_ARCH_RISCV
|
||||||
@@ -51,6 +52,12 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
|||||||
select FREERTOS_UNICORE
|
select FREERTOS_UNICORE
|
||||||
select IDF_TARGET_ARCH_RISCV
|
select IDF_TARGET_ARCH_RISCV
|
||||||
|
|
||||||
|
config IDF_TARGET_ESP32H2
|
||||||
|
bool
|
||||||
|
default "y" if IDF_TARGET="esp32h2"
|
||||||
|
select FREERTOS_UNICORE
|
||||||
|
select IDF_TARGET_ARCH_RISCV
|
||||||
|
|
||||||
config IDF_TARGET_LINUX
|
config IDF_TARGET_LINUX
|
||||||
bool
|
bool
|
||||||
default "y" if IDF_TARGET="linux"
|
default "y" if IDF_TARGET="linux"
|
||||||
@@ -61,6 +68,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
|||||||
default 0x0002 if IDF_TARGET_ESP32S2
|
default 0x0002 if IDF_TARGET_ESP32S2
|
||||||
default 0x0005 if IDF_TARGET_ESP32C3
|
default 0x0005 if IDF_TARGET_ESP32C3
|
||||||
default 0x0009 if IDF_TARGET_ESP32S3
|
default 0x0009 if IDF_TARGET_ESP32S3
|
||||||
|
default 0x000A if IDF_TARGET_ESP32H2 # ESP32H2-TODO: IDF-3475
|
||||||
default 0xFFFF
|
default 0xFFFF
|
||||||
|
|
||||||
menu "SDK tool configuration"
|
menu "SDK tool configuration"
|
||||||
@@ -70,6 +78,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
|||||||
default "xtensa-esp32s2-elf-" if IDF_TARGET_ESP32S2
|
default "xtensa-esp32s2-elf-" if IDF_TARGET_ESP32S2
|
||||||
default "xtensa-esp32s3-elf-" if IDF_TARGET_ESP32S3
|
default "xtensa-esp32s3-elf-" if IDF_TARGET_ESP32S3
|
||||||
default "riscv32-esp-elf-" if IDF_TARGET_ESP32C3
|
default "riscv32-esp-elf-" if IDF_TARGET_ESP32C3
|
||||||
|
default "riscv32-esp-elf-" if IDF_TARGET_ESP32H2
|
||||||
|
|
||||||
help
|
help
|
||||||
The prefix/path that is used to call the toolchain. The default setting assumes
|
The prefix/path that is used to call the toolchain. The default setting assumes
|
||||||
|
@@ -4,7 +4,7 @@ idf_component_register(SRCS "bootloader_start.c"
|
|||||||
idf_build_get_property(target IDF_TARGET)
|
idf_build_get_property(target IDF_TARGET)
|
||||||
set(scripts "ld/${target}/bootloader.ld")
|
set(scripts "ld/${target}/bootloader.ld")
|
||||||
|
|
||||||
if(NOT CONFIG_IDF_TARGET_ESP32C3)
|
if(NOT CONFIG_IDF_TARGET_ESP32C3 AND NOT CONFIG_IDF_TARGET_ESP32H2)
|
||||||
list(APPEND scripts "ld/${target}/bootloader.rom.ld")
|
list(APPEND scripts "ld/${target}/bootloader.rom.ld")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
189
components/bootloader/subproject/main/ld/esp32h2/bootloader.ld
Normal file
189
components/bootloader/subproject/main/ld/esp32h2/bootloader.ld
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
/** Simplified memory map for the bootloader.
|
||||||
|
* Make sure the bootloader can load into main memory without overwriting itself.
|
||||||
|
* We put 2nd bootloader in the high address space (before ROM stack/data/bss).
|
||||||
|
* See memory usage for ROM bootloader at the end of this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
iram_seg (RWX) : org = 0x403CE000, len = 0x2000
|
||||||
|
iram_loader_seg (RWX) : org = 0x403D0000, len = 0x6000
|
||||||
|
dram_seg (RW) : org = 0x3FCD6000, len = 0x4000
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Default entry point: */
|
||||||
|
ENTRY(call_start_cpu0);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
|
||||||
|
.iram_loader.text :
|
||||||
|
{
|
||||||
|
. = ALIGN (16);
|
||||||
|
_loader_text_start = ABSOLUTE(.);
|
||||||
|
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||||
|
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
|
||||||
|
*liblog.a:(.literal .text .literal.* .text.*)
|
||||||
|
*libgcc.a:(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
|
||||||
|
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
|
||||||
|
*libbootloader_support.a:bootloader_efuse_esp32h2.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
|
||||||
|
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
|
||||||
|
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||||
|
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||||
|
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
|
||||||
|
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
|
||||||
|
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
|
||||||
|
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
|
||||||
|
*libefuse.a:*.*(.literal .text .literal.* .text.*)
|
||||||
|
*(.fini.literal)
|
||||||
|
*(.fini)
|
||||||
|
*(.gnu.version)
|
||||||
|
_loader_text_end = ABSOLUTE(.);
|
||||||
|
} > iram_loader_seg
|
||||||
|
|
||||||
|
.iram.text :
|
||||||
|
{
|
||||||
|
. = ALIGN (16);
|
||||||
|
*(.entry.text)
|
||||||
|
*(.init.literal)
|
||||||
|
*(.init)
|
||||||
|
} > iram_seg
|
||||||
|
|
||||||
|
|
||||||
|
/* Shared RAM */
|
||||||
|
.dram0.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (8);
|
||||||
|
_dram_start = ABSOLUTE(.);
|
||||||
|
_bss_start = ABSOLUTE(.);
|
||||||
|
*(.dynsbss)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss.*)
|
||||||
|
*(.gnu.linkonce.sb.*)
|
||||||
|
*(.scommon)
|
||||||
|
*(.sbss2)
|
||||||
|
*(.sbss2.*)
|
||||||
|
*(.gnu.linkonce.sb2.*)
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(.gnu.linkonce.b.*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN (8);
|
||||||
|
_bss_end = ABSOLUTE(.);
|
||||||
|
} > dram_seg
|
||||||
|
|
||||||
|
.dram0.data :
|
||||||
|
{
|
||||||
|
_data_start = ABSOLUTE(.);
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.data1)
|
||||||
|
*(.sdata)
|
||||||
|
*(.sdata.*)
|
||||||
|
*(.gnu.linkonce.s.*)
|
||||||
|
*(.sdata2)
|
||||||
|
*(.sdata2.*)
|
||||||
|
*(.gnu.linkonce.s2.*)
|
||||||
|
*(.jcr)
|
||||||
|
_data_end = ABSOLUTE(.);
|
||||||
|
} > dram_seg
|
||||||
|
|
||||||
|
.dram0.rodata :
|
||||||
|
{
|
||||||
|
_rodata_start = ABSOLUTE(.);
|
||||||
|
*(.rodata)
|
||||||
|
*(.rodata.*)
|
||||||
|
*(.gnu.linkonce.r.*)
|
||||||
|
*(.rodata1)
|
||||||
|
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
||||||
|
*(.xt_except_table)
|
||||||
|
*(.gcc_except_table)
|
||||||
|
*(.gnu.linkonce.e.*)
|
||||||
|
*(.gnu.version_r)
|
||||||
|
*(.eh_frame)
|
||||||
|
. = (. + 3) & ~ 3;
|
||||||
|
/* C++ constructor and destructor tables, properly ordered: */
|
||||||
|
__init_array_start = ABSOLUTE(.);
|
||||||
|
KEEP (*crtbegin.*(.ctors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
__init_array_end = ABSOLUTE(.);
|
||||||
|
KEEP (*crtbegin.*(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
/* C++ exception handlers table: */
|
||||||
|
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
||||||
|
*(.xt_except_desc)
|
||||||
|
*(.gnu.linkonce.h.*)
|
||||||
|
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||||
|
*(.xt_except_desc_end)
|
||||||
|
*(.dynamic)
|
||||||
|
*(.gnu.version_d)
|
||||||
|
_rodata_end = ABSOLUTE(.);
|
||||||
|
/* Literals are also RO data. */
|
||||||
|
_lit4_start = ABSOLUTE(.);
|
||||||
|
*(*.lit4)
|
||||||
|
*(.lit4.*)
|
||||||
|
*(.gnu.linkonce.lit4.*)
|
||||||
|
_lit4_end = ABSOLUTE(.);
|
||||||
|
. = ALIGN(4);
|
||||||
|
_dram_end = ABSOLUTE(.);
|
||||||
|
} > dram_seg
|
||||||
|
|
||||||
|
.iram.text :
|
||||||
|
{
|
||||||
|
_stext = .;
|
||||||
|
_text_start = ABSOLUTE(.);
|
||||||
|
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||||
|
*(.iram .iram.*) /* catch stray IRAM_ATTR */
|
||||||
|
*(.fini.literal)
|
||||||
|
*(.fini)
|
||||||
|
*(.gnu.version)
|
||||||
|
|
||||||
|
/** CPU will try to prefetch up to 16 bytes of
|
||||||
|
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||||
|
* safe access to up to 16 bytes after the last real instruction, add
|
||||||
|
* dummy bytes to ensure this
|
||||||
|
*/
|
||||||
|
. += 16;
|
||||||
|
|
||||||
|
_text_end = ABSOLUTE(.);
|
||||||
|
_etext = .;
|
||||||
|
} > iram_seg
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appendix: Memory Usage of ROM bootloader
|
||||||
|
*
|
||||||
|
* +--------+--------------+------+ 0x3FCC_B900
|
||||||
|
* | ^ |
|
||||||
|
* | | |
|
||||||
|
* | | data/bss |
|
||||||
|
* | | |
|
||||||
|
* | v |
|
||||||
|
* +------------------------------+ 0x3FCD_D210
|
||||||
|
* | ^ |
|
||||||
|
* | | |
|
||||||
|
* | | stack |
|
||||||
|
* | | |
|
||||||
|
* | v |
|
||||||
|
* +------------------------------+ 0x3FCD_F210
|
||||||
|
*/
|
@@ -31,12 +31,15 @@ endif
|
|||||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
|
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2.o \
|
||||||
src/bootloader_flash_config_esp32s3.o \
|
src/bootloader_flash_config_esp32s3.o \
|
||||||
src/bootloader_flash_config_esp32c3.o \
|
src/bootloader_flash_config_esp32c3.o \
|
||||||
|
src/bootloader_flash_config_esp32h2.o \
|
||||||
src/bootloader_efuse_esp32s2.o \
|
src/bootloader_efuse_esp32s2.o \
|
||||||
src/bootloader_efuse_esp32s3.o \
|
src/bootloader_efuse_esp32s3.o \
|
||||||
src/bootloader_efuse_esp32c3.o \
|
src/bootloader_efuse_esp32c3.o \
|
||||||
|
src/bootloader_efuse_esp32h2.o \
|
||||||
src/bootloader_random_esp32s2.o \
|
src/bootloader_random_esp32s2.o \
|
||||||
src/bootloader_random_esp32s3.o \
|
src/bootloader_random_esp32s3.o \
|
||||||
src/bootloader_random_esp32c3.o
|
src/bootloader_random_esp32c3.o \
|
||||||
|
src/bootloader_random_esp32h2.o
|
||||||
|
|
||||||
ifdef IS_BOOTLOADER_BUILD
|
ifdef IS_BOOTLOADER_BUILD
|
||||||
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
ifndef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
#include "esp32s3/rom/rtc.h"
|
#include "esp32s3/rom/rtc.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/rtc.h"
|
#include "esp32c3/rom/rtc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@@ -16,6 +16,7 @@ typedef enum {
|
|||||||
ESP_CHIP_ID_ESP32S2 = 0x0002, /*!< chip ID: ESP32-S2 */
|
ESP_CHIP_ID_ESP32S2 = 0x0002, /*!< chip ID: ESP32-S2 */
|
||||||
ESP_CHIP_ID_ESP32C3 = 0x0005, /*!< chip ID: ESP32-C3 */
|
ESP_CHIP_ID_ESP32C3 = 0x0005, /*!< chip ID: ESP32-C3 */
|
||||||
ESP_CHIP_ID_ESP32S3 = 0x0009, /*!< chip ID: ESP32-S3 */
|
ESP_CHIP_ID_ESP32S3 = 0x0009, /*!< chip ID: ESP32-S3 */
|
||||||
|
ESP_CHIP_ID_ESP32H2 = 0x000A, /*!< chip ID: ESP32-H2 */ // ESP32H2-TODO: IDF-3475
|
||||||
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
|
ESP_CHIP_ID_INVALID = 0xFFFF /*!< Invalid chip ID (we defined it to make sure the esp_chip_id_t is 2 bytes size) */
|
||||||
} __attribute__((packed)) esp_chip_id_t;
|
} __attribute__((packed)) esp_chip_id_t;
|
||||||
|
|
||||||
|
@@ -25,6 +25,9 @@
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/efuse.h"
|
#include "esp32s3/rom/efuse.h"
|
||||||
#include "esp32s3/rom/secure_boot.h"
|
#include "esp32s3/rom/secure_boot.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
#include "esp32h2/rom/secure_boot.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
#ifdef CONFIG_SECURE_BOOT_V1_ENABLED
|
||||||
|
@@ -22,6 +22,8 @@
|
|||||||
#include "esp32s3/rom/rtc.h"
|
#include "esp32s3/rom/rtc.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/rtc.h"
|
#include "esp32c3/rom/rtc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esp_rom_uart.h"
|
#include "esp_rom_uart.h"
|
||||||
|
|
||||||
|
@@ -17,6 +17,8 @@
|
|||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/spi_flash.h"
|
#include "esp32c3/rom/spi_flash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esp_rom_crc.h"
|
#include "esp_rom_crc.h"
|
||||||
#include "esp_rom_gpio.h"
|
#include "esp_rom_gpio.h"
|
||||||
|
@@ -22,6 +22,9 @@
|
|||||||
#include "esp32c3/rom/uart.h"
|
#include "esp32c3/rom/uart.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/uart.h"
|
#include "esp32s3/rom/uart.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp32h2/rom/uart.h"
|
||||||
#endif
|
#endif
|
||||||
#include "esp_rom_gpio.h"
|
#include "esp_rom_gpio.h"
|
||||||
#include "esp_rom_uart.h"
|
#include "esp_rom_uart.h"
|
||||||
|
20
components/bootloader_support/src/bootloader_efuse_esp32h2.c
Normal file
20
components/bootloader_support/src/bootloader_efuse_esp32h2.c
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "soc/efuse_reg.h"
|
||||||
|
|
||||||
|
uint8_t bootloader_common_get_chip_revision(void)
|
||||||
|
{
|
||||||
|
// should return the same value as esp_efuse_get_chip_ver()
|
||||||
|
return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_WAFER_VERSION);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t bootloader_common_get_chip_ver_pkg(void)
|
||||||
|
{
|
||||||
|
// should return the same value as esp_efuse_get_pkg_ver()
|
||||||
|
return REG_GET_FIELD(EFUSE_RD_MAC_SPI_SYS_3_REG, EFUSE_PKG_VERSION);
|
||||||
|
}
|
@@ -29,6 +29,8 @@
|
|||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/spi_flash.h"
|
#include "esp32c3/rom/spi_flash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
|
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
|
||||||
@@ -124,6 +126,10 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
|||||||
#include "esp32c3/rom/spi_flash.h"
|
#include "esp32c3/rom/spi_flash.h"
|
||||||
#include "esp32c3/rom/cache.h"
|
#include "esp32c3/rom/cache.h"
|
||||||
#include "soc/cache_memory.h"
|
#include "soc/cache_memory.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
|
#include "esp32h2/rom/cache.h"
|
||||||
|
#include "soc/cache_memory.h"
|
||||||
#endif
|
#endif
|
||||||
static const char *TAG = "bootloader_flash";
|
static const char *TAG = "bootloader_flash";
|
||||||
|
|
||||||
@@ -188,6 +194,9 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
uint32_t autoload = Cache_Suspend_ICache();
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
Cache_Invalidate_ICache_All();
|
Cache_Invalidate_ICache_All();
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
|
Cache_Invalidate_ICache_All();
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
|
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 );
|
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||||
@@ -195,7 +204,7 @@ 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);
|
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||||
int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
int e = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||||
#else // S3, C3
|
#else // S3, C3, H2
|
||||||
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||||
#endif
|
#endif
|
||||||
if (e != 0) {
|
if (e != 0) {
|
||||||
@@ -208,6 +217,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
|||||||
Cache_Resume_DCache(autoload);
|
Cache_Resume_DCache(autoload);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
Cache_Resume_ICache(autoload);
|
Cache_Resume_ICache(autoload);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Resume_ICache(autoload);
|
||||||
#endif
|
#endif
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@@ -219,6 +230,8 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
|||||||
Cache_Resume_DCache(autoload);
|
Cache_Resume_DCache(autoload);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
Cache_Resume_ICache(autoload);
|
Cache_Resume_ICache(autoload);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Resume_ICache(autoload);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mapped = true;
|
mapped = true;
|
||||||
@@ -248,6 +261,10 @@ void bootloader_munmap(const void *mapping)
|
|||||||
Cache_Suspend_ICache();
|
Cache_Suspend_ICache();
|
||||||
Cache_Invalidate_ICache_All();
|
Cache_Invalidate_ICache_All();
|
||||||
Cache_MMU_Init();
|
Cache_MMU_Init();
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Suspend_ICache();
|
||||||
|
Cache_Invalidate_ICache_All();
|
||||||
|
Cache_MMU_Init();
|
||||||
#endif
|
#endif
|
||||||
mapped = false;
|
mapped = false;
|
||||||
current_read_mapping = UINT32_MAX;
|
current_read_mapping = UINT32_MAX;
|
||||||
@@ -279,6 +296,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
|
|||||||
uint32_t autoload = Cache_Suspend_DCache();
|
uint32_t autoload = Cache_Suspend_DCache();
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
uint32_t autoload = Cache_Suspend_ICache();
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
#endif
|
#endif
|
||||||
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
|
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
@@ -289,6 +308,8 @@ static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, s
|
|||||||
Cache_Resume_DCache(autoload);
|
Cache_Resume_DCache(autoload);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
Cache_Resume_ICache(autoload);
|
Cache_Resume_ICache(autoload);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Resume_ICache(autoload);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return spi_to_esp_err(r);
|
return spi_to_esp_err(r);
|
||||||
@@ -316,6 +337,9 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
uint32_t autoload = Cache_Suspend_ICache();
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
Cache_Invalidate_ICache_All();
|
Cache_Invalidate_ICache_All();
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
|
Cache_Invalidate_ICache_All();
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
|
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
@@ -326,6 +350,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
|||||||
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
int e = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, MMU_BLOCK63_VADDR, map_at, 64, 1, 0);
|
||||||
#endif
|
#endif
|
||||||
if (e != 0) {
|
if (e != 0) {
|
||||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||||
@@ -337,6 +363,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
|||||||
Cache_Resume_DCache(autoload);
|
Cache_Resume_DCache(autoload);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
Cache_Resume_ICache(autoload);
|
Cache_Resume_ICache(autoload);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Resume_ICache(autoload);
|
||||||
#endif
|
#endif
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
@@ -349,6 +377,8 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
|||||||
Cache_Resume_DCache(autoload);
|
Cache_Resume_DCache(autoload);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
Cache_Resume_ICache(autoload);
|
Cache_Resume_ICache(autoload);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Resume_ICache(autoload);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
|
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
|
||||||
|
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include "string.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp32h2/rom/gpio.h"
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
#include "soc/gpio_periph.h"
|
||||||
|
#include "soc/efuse_reg.h"
|
||||||
|
#include "soc/spi_reg.h"
|
||||||
|
#include "soc/spi_mem_reg.h"
|
||||||
|
#include "soc/soc_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
|
||||||
|
|
||||||
|
void bootloader_flash_update_id()
|
||||||
|
{
|
||||||
|
esp_rom_spiflash_chip_t *chip = &rom_spiflash_legacy_data->chip;
|
||||||
|
chip->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();
|
||||||
|
}
|
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "bootloader_random.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "soc/syscon_reg.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/apb_saradc_reg.h"
|
||||||
|
#include "soc/system_reg.h"
|
||||||
|
#include "regi2c_ctrl.h"
|
||||||
|
|
||||||
|
// ESP32H2-TODO: IDF-3381
|
||||||
|
void bootloader_random_enable(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void bootloader_random_disable(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
@@ -45,6 +45,18 @@
|
|||||||
#include "esp32c3/rom/secure_boot.h"
|
#include "esp32c3/rom/secure_boot.h"
|
||||||
#include "soc/extmem_reg.h"
|
#include "soc/extmem_reg.h"
|
||||||
#include "soc/cache_memory.h"
|
#include "soc/cache_memory.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/cache.h"
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
|
#include "esp32h2/rom/crc.h"
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
|
#include "esp32h2/rom/uart.h"
|
||||||
|
#include "esp32h2/rom/gpio.h"
|
||||||
|
#include "esp32h2/rom/secure_boot.h"
|
||||||
|
#include "soc/extmem_reg.h"
|
||||||
|
#include "soc/cache_memory.h"
|
||||||
#else // CONFIG_IDF_TARGET_*
|
#else // CONFIG_IDF_TARGET_*
|
||||||
#error "Unsupported IDF_TARGET"
|
#error "Unsupported IDF_TARGET"
|
||||||
#endif
|
#endif
|
||||||
@@ -700,6 +712,9 @@ static void set_cache_and_start_app(
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
uint32_t autoload = Cache_Suspend_ICache();
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
Cache_Invalidate_ICache_All();
|
Cache_Invalidate_ICache_All();
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
uint32_t autoload = Cache_Suspend_ICache();
|
||||||
|
Cache_Invalidate_ICache_All();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Clear the MMU entries that are already set up,
|
/* Clear the MMU entries that are already set up,
|
||||||
@@ -726,6 +741,8 @@ static void set_cache_and_start_app(
|
|||||||
rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
rc = Cache_Dbus_MMU_Set(MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000, 64, drom_page_count, 0);
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGV(TAG, "rc=%d", rc);
|
ESP_LOGV(TAG, "rc=%d", rc);
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
@@ -753,6 +770,8 @@ static void set_cache_and_start_app(
|
|||||||
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
rc = Cache_Ibus_MMU_Set(MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||||
#endif
|
#endif
|
||||||
ESP_LOGV(TAG, "rc=%d", rc);
|
ESP_LOGV(TAG, "rc=%d", rc);
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
@@ -776,6 +795,9 @@ static void set_cache_and_start_app(
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
|
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
|
||||||
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
|
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
|
||||||
|
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
|
||||||
#endif
|
#endif
|
||||||
#if CONFIG_IDF_TARGET_ESP32
|
#if CONFIG_IDF_TARGET_ESP32
|
||||||
Cache_Read_Enable(0);
|
Cache_Read_Enable(0);
|
||||||
@@ -785,6 +807,8 @@ static void set_cache_and_start_app(
|
|||||||
Cache_Resume_DCache(autoload);
|
Cache_Resume_DCache(autoload);
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
Cache_Resume_ICache(autoload);
|
Cache_Resume_ICache(autoload);
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
Cache_Resume_ICache(autoload);
|
||||||
#endif
|
#endif
|
||||||
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
|
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
|
||||||
|
|
||||||
|
327
components/bootloader_support/src/esp32h2/bootloader_esp32h2.c
Normal file
327
components/bootloader_support/src/esp32h2/bootloader_esp32h2.c
Normal file
@@ -0,0 +1,327 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#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 "esp_rom_gpio.h"
|
||||||
|
#include "esp_rom_efuse.h"
|
||||||
|
#include "esp_rom_uart.h"
|
||||||
|
#include "esp_rom_sys.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/rtc.h"
|
||||||
|
#include "soc/spi_periph.h"
|
||||||
|
#include "soc/extmem_reg.h"
|
||||||
|
#include "soc/io_mux_reg.h"
|
||||||
|
#include "soc/system_reg.h"
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
|
#include "esp32h2/rom/cache.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
|
#include "esp32h2/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 "regi2c_ctrl.h"
|
||||||
|
#include "bootloader_console.h"
|
||||||
|
#include "bootloader_flash_priv.h"
|
||||||
|
|
||||||
|
static const char *TAG = "boot.esp32h2";
|
||||||
|
|
||||||
|
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_ICache();
|
||||||
|
Cache_Invalidate_ICache_All();
|
||||||
|
Cache_MMU_Init();
|
||||||
|
|
||||||
|
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_IBUS);
|
||||||
|
REG_CLR_BIT(EXTMEM_ICACHE_CTRL1_REG, EXTMEM_ICACHE_SHUT_DBUS);
|
||||||
|
}
|
||||||
|
|
||||||
|
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_ICache();
|
||||||
|
// Set flash chip size
|
||||||
|
esp_rom_spiflash_config_param(rom_spiflash_legacy_data->chip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff); // TODO: set mode
|
||||||
|
Cache_Resume_ICache(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 void bootloader_spi_flash_resume(void)
|
||||||
|
{
|
||||||
|
bootloader_execute_flash_command(CMD_RESUME, 0, 0, 0);
|
||||||
|
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
bootloader_spi_flash_resume();
|
||||||
|
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_EN_REG, ASSIST_DEBUG_CORE_0_RCD_PDEBUGEN | ASSIST_DEBUG_CORE_0_RCD_RECORDEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void wdt_reset_info_dump(int cpu)
|
||||||
|
{
|
||||||
|
(void) cpu;
|
||||||
|
// saved PC was already printed by the ROM bootloader.
|
||||||
|
// nothing to do here.
|
||||||
|
}
|
||||||
|
|
||||||
|
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_cpu0_info_enable();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void bootloader_super_wdt_auto_feed(void)
|
||||||
|
{
|
||||||
|
REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, RTC_CNTL_SWD_WKEY_VALUE);
|
||||||
|
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
|
||||||
|
REG_WRITE(RTC_CNTL_SWD_WPROTECT_REG, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bootloader_hardware_init(void)
|
||||||
|
{
|
||||||
|
// This check is always included in the bootloader so it can
|
||||||
|
// print the minimum revision error message later in the boot
|
||||||
|
if (bootloader_common_get_chip_revision() < 3) {
|
||||||
|
REGI2C_WRITE_MASK(I2C_ULP, I2C_ULP_IR_FORCE_XPD_IPH, 1);
|
||||||
|
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 12);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void bootloader_glitch_reset_disable(void)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
For origin chip & ECO1: only support swt reset;
|
||||||
|
For ECO2: fix brownout reset bug, support swt & brownout reset;
|
||||||
|
For ECO3: fix clock glitch reset bug, support all reset, include: swt & brownout & clock glitch reset.
|
||||||
|
*/
|
||||||
|
uint8_t chip_version = bootloader_common_get_chip_revision();
|
||||||
|
if (chip_version < 2) {
|
||||||
|
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST);
|
||||||
|
} else if (chip_version == 2) {
|
||||||
|
REG_SET_FIELD(RTC_CNTL_FIB_SEL_REG, RTC_CNTL_FIB_SEL, RTC_CNTL_FIB_SUPER_WDT_RST | RTC_CNTL_FIB_BOR_RST);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t bootloader_init(void)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
bootloader_hardware_init();
|
||||||
|
bootloader_glitch_reset_disable();
|
||||||
|
bootloader_super_wdt_auto_feed();
|
||||||
|
// protect memory region
|
||||||
|
bootloader_init_mem();
|
||||||
|
/* check that static RAM is after the stack */
|
||||||
|
assert(&_bss_start <= &_bss_end);
|
||||||
|
assert(&_data_start <= &_data_end);
|
||||||
|
// 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;
|
||||||
|
}
|
40
components/bootloader_support/src/esp32h2/bootloader_sha.c
Normal file
40
components/bootloader_support/src/esp32h2/bootloader_sha.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#include "bootloader_sha.h"
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
|
||||||
|
#include "esp32h2/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);
|
||||||
|
}
|
346
components/bootloader_support/src/esp32h2/flash_encrypt.c
Normal file
346
components/bootloader_support/src/esp32h2/flash_encrypt.c
Normal file
@@ -0,0 +1,346 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#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 "esp32h2/rom/secure_boot.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 esp_err_t check_and_generate_encryption_keys(void)
|
||||||
|
{
|
||||||
|
esp_efuse_block_t aes_128_key_block;
|
||||||
|
|
||||||
|
bool has_key = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, &aes_128_key_block);
|
||||||
|
bool dis_write = false;
|
||||||
|
bool dis_read = false;
|
||||||
|
|
||||||
|
// If there are keys set, they must be write and read protected!
|
||||||
|
if(has_key) {
|
||||||
|
dis_write = esp_efuse_get_key_dis_write(aes_128_key_block);
|
||||||
|
dis_read = esp_efuse_get_key_dis_read(aes_128_key_block);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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...");
|
||||||
|
|
||||||
|
enum { BLOCKS_NEEDED = 1 };
|
||||||
|
esp_efuse_purpose_t purposes[BLOCKS_NEEDED] = {
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY,
|
||||||
|
};
|
||||||
|
|
||||||
|
uint8_t keys[BLOCKS_NEEDED][32] = { 0 };
|
||||||
|
for (int i = 0; i < BLOCKS_NEEDED; ++i) {
|
||||||
|
bootloader_fill_random(keys[i], 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t err = esp_efuse_write_keys(purposes, keys, BLOCKS_NEEDED);
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
if (err == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
|
||||||
|
ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", err);
|
||||||
|
}
|
||||||
|
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_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_DIS_PAD_JTAG);
|
||||||
|
esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_JTAG);
|
||||||
|
#else
|
||||||
|
ESP_LOGW(TAG, "Not disabling JTAG - SECURITY COMPROMISED");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_efuse_write_field_bit(ESP_EFUSE_DIS_LEGACY_SPI_BOOT);
|
||||||
|
|
||||||
|
esp_err_t err = esp_efuse_batch_write_commit();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
|
||||||
|
}
|
||||||
|
|
||||||
|
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 || spi_boot_crypt_cnt == EFUSE_SPI_BOOT_CRYPT_CNT) {
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Go through each partition and encrypt if necessary */
|
||||||
|
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
|
||||||
|
/* The image length obtained from esp_image_verify_bootloader includes the sector boundary padding and the signature block lengths */
|
||||||
|
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 loaded */
|
||||||
|
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;
|
||||||
|
}
|
289
components/bootloader_support/src/esp32h2/secure_boot.c
Normal file
289
components/bootloader_support/src/esp32h2/secure_boot.c
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
#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 "esp32h2/rom/efuse.h"
|
||||||
|
#include "esp32h2/rom/secure_boot.h"
|
||||||
|
|
||||||
|
static const char *TAG = "secure_boot_v2";
|
||||||
|
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
|
||||||
|
|
||||||
|
/* 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 != ETS_SECURE_BOOT_V2_SIGNATURE_MAGIC) {
|
||||||
|
// 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, ESP_SECURE_BOOT_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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, esp_image_sig_public_key_digests_t *public_key_digests)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = {0};
|
||||||
|
uint8_t __attribute__((aligned(4))) key_digest[ESP_SECURE_BOOT_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(esp_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[ESP_SECURE_BOOT_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, ESP_SECURE_BOOT_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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t check_and_generate_secure_boot_keys(const esp_image_metadata_t *image_data)
|
||||||
|
{
|
||||||
|
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 = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0, NULL);
|
||||||
|
has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, NULL);
|
||||||
|
has_secure_boot_digest |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL);
|
||||||
|
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
|
||||||
|
|
||||||
|
if (!has_secure_boot_digest) {
|
||||||
|
esp_image_sig_public_key_digests_t boot_key_digests = {0};
|
||||||
|
esp_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);
|
||||||
|
|
||||||
|
esp_efuse_purpose_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = {
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1,
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2,
|
||||||
|
};
|
||||||
|
|
||||||
|
ret = esp_efuse_write_keys(secure_boot_key_purpose, boot_key_digests.key_digests, boot_key_digests.num_digests);
|
||||||
|
if (ret) {
|
||||||
|
if (ret == ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS) {
|
||||||
|
ESP_LOGE(TAG, "Bootloader signatures(%d) more than available key slots.", boot_key_digests.num_digests);
|
||||||
|
} else {
|
||||||
|
ESP_LOGE(TAG, "Failed to write efuse block with purpose (err=0x%x). Can't continue.", ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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;
|
||||||
|
|
||||||
|
for (int i = 0; i < boot_key_digests.num_digests; i++) {
|
||||||
|
|
||||||
|
if (esp_efuse_get_digest_revoke(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], ESP_SECURE_BOOT_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);
|
||||||
|
esp_efuse_set_digest_revoke(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "enabling secure boot v2...");
|
||||||
|
|
||||||
|
if (esp_secure_boot_enabled()) {
|
||||||
|
ESP_LOGI(TAG, "secure boot v2 is already enabled, continuing..");
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_efuse_batch_write_begin(); /* Batch all efuse writes at the end of this function */
|
||||||
|
|
||||||
|
esp_err_t key_state = check_and_generate_secure_boot_keys(image_data);
|
||||||
|
if (key_state != ESP_OK) {
|
||||||
|
esp_efuse_batch_write_cancel();
|
||||||
|
return key_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
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_DIS_PAD_JTAG);
|
||||||
|
esp_efuse_write_field_bit(ESP_EFUSE_DIS_USB_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);
|
||||||
|
|
||||||
|
esp_err_t err = esp_efuse_batch_write_commit();
|
||||||
|
if (err != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Error programming security eFuses (err=0x%x).", err);
|
||||||
|
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;
|
||||||
|
}
|
@@ -30,6 +30,9 @@
|
|||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/rtc.h"
|
#include "esp32c3/rom/rtc.h"
|
||||||
#include "esp32c3/rom/secure_boot.h"
|
#include "esp32c3/rom/secure_boot.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
|
#include "esp32h2/rom/secure_boot.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Checking signatures as part of verifying images is necessary:
|
/* Checking signatures as part of verifying images is necessary:
|
||||||
|
@@ -86,7 +86,7 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
|
|||||||
uint8_t dis_dl_enc = 0;
|
uint8_t dis_dl_enc = 0;
|
||||||
uint8_t dis_dl_icache = 0;
|
uint8_t dis_dl_icache = 0;
|
||||||
uint8_t dis_dl_dcache = 0;
|
uint8_t dis_dl_dcache = 0;
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
uint8_t dis_dl_enc = 0;
|
uint8_t dis_dl_enc = 0;
|
||||||
uint8_t dis_dl_icache = 0;
|
uint8_t dis_dl_icache = 0;
|
||||||
#endif
|
#endif
|
||||||
@@ -123,7 +123,7 @@ esp_flash_enc_mode_t esp_get_flash_encryption_mode(void)
|
|||||||
if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) {
|
if (dis_dl_enc && dis_dl_icache && dis_dl_dcache) {
|
||||||
mode = ESP_FLASH_ENC_MODE_RELEASE;
|
mode = ESP_FLASH_ENC_MODE_RELEASE;
|
||||||
}
|
}
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
|
dis_dl_enc = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT);
|
||||||
dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
|
dis_dl_icache = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_ICACHE);
|
||||||
|
|
||||||
|
@@ -13,6 +13,8 @@
|
|||||||
#include "esp32s2/rom/spi_flash.h"
|
#include "esp32s2/rom/spi_flash.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
#else
|
#else
|
||||||
#include "esp32/rom/spi_flash.h"
|
#include "esp32/rom/spi_flash.h"
|
||||||
#endif
|
#endif
|
||||||
|
@@ -21,6 +21,8 @@
|
|||||||
#include "esp32s3/rom/spi_flash.h"
|
#include "esp32s3/rom/spi_flash.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/spi_flash.h"
|
#include "esp32c3/rom/spi_flash.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/spi_flash.h"
|
||||||
#endif
|
#endif
|
||||||
#include "soc/efuse_periph.h"
|
#include "soc/efuse_periph.h"
|
||||||
#include "soc/io_mux_reg.h"
|
#include "soc/io_mux_reg.h"
|
||||||
|
@@ -74,6 +74,15 @@ if(IDF_TARGET STREQUAL "esp32c3")
|
|||||||
"esp32c3/rtc_tempsensor.c")
|
"esp32c3/rtc_tempsensor.c")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(IDF_TARGET STREQUAL "esp32h2")
|
||||||
|
list(APPEND srcs "gdma.c"
|
||||||
|
"spi_slave_hd.c"
|
||||||
|
"adc_common.c"
|
||||||
|
"esp32h2/adc.c"
|
||||||
|
"esp32h2/adc2_init_cal.c"
|
||||||
|
"esp32h2/rtc_tempsensor.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
idf_component_register(SRCS "${srcs}"
|
idf_component_register(SRCS "${srcs}"
|
||||||
INCLUDE_DIRS ${includes}
|
INCLUDE_DIRS ${includes}
|
||||||
PRIV_INCLUDE_DIRS "include/driver"
|
PRIV_INCLUDE_DIRS "include/driver"
|
||||||
|
717
components/driver/esp32h2/adc.c
Normal file
717
components/driver/esp32h2/adc.c
Normal file
@@ -0,0 +1,717 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esp_types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_pm.h"
|
||||||
|
#include "sys/lock.h"
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "freertos/timers.h"
|
||||||
|
#include "freertos/ringbuf.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
|
#include "driver/gpio.h"
|
||||||
|
#include "driver/adc.h"
|
||||||
|
#include "hal/adc_types.h"
|
||||||
|
#include "hal/adc_hal.h"
|
||||||
|
#include "hal/dma_types.h"
|
||||||
|
#include "esp_efuse_rtc_calib.h"
|
||||||
|
#include "esp_private/gdma.h"
|
||||||
|
|
||||||
|
#define ADC_CHECK_RET(fun_ret) ({ \
|
||||||
|
if (fun_ret != ESP_OK) { \
|
||||||
|
ESP_LOGE(ADC_TAG,"%s(%d)",__FUNCTION__,__LINE__); \
|
||||||
|
return ESP_FAIL; \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
static const char *ADC_TAG = "ADC";
|
||||||
|
|
||||||
|
#define ADC_CHECK(a, str, ret_val) ({ \
|
||||||
|
if (!(a)) { \
|
||||||
|
ESP_LOGE(ADC_TAG,"%s(%d) :%s", __FUNCTION__, __LINE__, str); \
|
||||||
|
return (ret_val); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define ADC_GET_IO_NUM(periph, channel) (adc_channel_io_map[periph][channel])
|
||||||
|
|
||||||
|
#define ADC_CHANNEL_CHECK(periph, channel) ADC_CHECK(channel < SOC_ADC_CHANNEL_NUM(periph), "ADC"#periph" channel error", ESP_ERR_INVALID_ARG)
|
||||||
|
|
||||||
|
extern portMUX_TYPE rtc_spinlock; //TODO: Will be placed in the appropriate position after the rtc module is finished.
|
||||||
|
#define ADC_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||||
|
#define ADC_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 1. sar_adc1_lock: this mutex lock is to protect the SARADC1 module.
|
||||||
|
* 2. sar_adc2_lock: this mutex lock is to protect the SARADC2 module. On H2, it is controlled by the digital controller
|
||||||
|
* and PWDET controller.
|
||||||
|
* 3. adc_reg_lock: this spin lock is to protect the shared registers used by ADC1 / ADC2 single read mode.
|
||||||
|
*/
|
||||||
|
static _lock_t sar_adc1_lock;
|
||||||
|
#define SAR_ADC1_LOCK_ACQUIRE() _lock_acquire(&sar_adc1_lock)
|
||||||
|
#define SAR_ADC1_LOCK_RELEASE() _lock_release(&sar_adc1_lock)
|
||||||
|
static _lock_t sar_adc2_lock;
|
||||||
|
#define SAR_ADC2_LOCK_ACQUIRE() _lock_acquire(&sar_adc2_lock)
|
||||||
|
#define SAR_ADC2_LOCK_RELEASE() _lock_release(&sar_adc2_lock)
|
||||||
|
portMUX_TYPE adc_reg_lock = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
#define ADC_REG_LOCK_ENTER() portENTER_CRITICAL(&adc_reg_lock)
|
||||||
|
#define ADC_REG_LOCK_EXIT() portEXIT_CRITICAL(&adc_reg_lock)
|
||||||
|
|
||||||
|
#define INTERNAL_BUF_NUM 5
|
||||||
|
#define IN_SUC_EOF_BIT GDMA_LL_EVENT_RX_SUC_EOF
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------
|
||||||
|
Digital Controller Context
|
||||||
|
---------------------------------------------------------------*/
|
||||||
|
typedef struct adc_digi_context_t {
|
||||||
|
uint8_t *rx_dma_buf; //dma buffer
|
||||||
|
adc_hal_context_t hal; //hal context
|
||||||
|
gdma_channel_handle_t rx_dma_channel; //dma rx channel handle
|
||||||
|
RingbufHandle_t ringbuf_hdl; //RX ringbuffer handler
|
||||||
|
intptr_t rx_eof_desc_addr; //eof descriptor address of RX channel
|
||||||
|
bool ringbuf_overflow_flag; //1: ringbuffer overflow
|
||||||
|
bool driver_start_flag; //1: driver is started; 0: driver is stoped
|
||||||
|
bool use_adc1; //1: ADC unit1 will be used; 0: ADC unit1 won't be used.
|
||||||
|
bool use_adc2; //1: ADC unit2 will be used; 0: ADC unit2 won't be used. This determines whether to acquire sar_adc2_mutex lock or not.
|
||||||
|
adc_atten_t adc1_atten; //Attenuation for ADC1. On this chip each ADC can only support one attenuation.
|
||||||
|
adc_atten_t adc2_atten; //Attenuation for ADC2. On this chip each ADC can only support one attenuation.
|
||||||
|
adc_digi_config_t digi_controller_config; //Digital Controller Configuration
|
||||||
|
esp_pm_lock_handle_t pm_lock; //For power management
|
||||||
|
} adc_digi_context_t;
|
||||||
|
|
||||||
|
static adc_digi_context_t *s_adc_digi_ctx = NULL;
|
||||||
|
|
||||||
|
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t chan, adc_atten_t atten);
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------
|
||||||
|
ADC Continuous Read Mode (via DMA)
|
||||||
|
---------------------------------------------------------------*/
|
||||||
|
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data);
|
||||||
|
|
||||||
|
static int8_t adc_digi_get_io_num(uint8_t adc_unit, uint8_t adc_channel)
|
||||||
|
{
|
||||||
|
return adc_channel_io_map[adc_unit][adc_channel];
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t adc_digi_gpio_init(adc_unit_t adc_unit, uint16_t channel_mask)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
uint64_t gpio_mask = 0;
|
||||||
|
uint32_t n = 0;
|
||||||
|
int8_t io = 0;
|
||||||
|
|
||||||
|
while (channel_mask) {
|
||||||
|
if (channel_mask & 0x1) {
|
||||||
|
io = adc_digi_get_io_num(adc_unit, n);
|
||||||
|
if (io < 0) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
gpio_mask |= BIT64(io);
|
||||||
|
}
|
||||||
|
channel_mask = channel_mask >> 1;
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
gpio_config_t cfg = {
|
||||||
|
.pin_bit_mask = gpio_mask,
|
||||||
|
.mode = GPIO_MODE_DISABLE,
|
||||||
|
};
|
||||||
|
ret = gpio_config(&cfg);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_initialize(const adc_digi_init_config_t *init_config)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
s_adc_digi_ctx = calloc(1, sizeof(adc_digi_context_t));
|
||||||
|
if (s_adc_digi_ctx == NULL) {
|
||||||
|
ret = ESP_ERR_NO_MEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ringbuffer
|
||||||
|
s_adc_digi_ctx->ringbuf_hdl = xRingbufferCreate(init_config->max_store_buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||||
|
if (!s_adc_digi_ctx->ringbuf_hdl) {
|
||||||
|
ret = ESP_ERR_NO_MEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
//malloc internal buffer used by DMA
|
||||||
|
s_adc_digi_ctx->rx_dma_buf = heap_caps_calloc(1, init_config->conv_num_each_intr * INTERNAL_BUF_NUM, MALLOC_CAP_INTERNAL);
|
||||||
|
if (!s_adc_digi_ctx->rx_dma_buf) {
|
||||||
|
ret = ESP_ERR_NO_MEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
//malloc dma descriptor
|
||||||
|
s_adc_digi_ctx->hal.rx_desc = heap_caps_calloc(1, (sizeof(dma_descriptor_t)) * INTERNAL_BUF_NUM, MALLOC_CAP_DMA);
|
||||||
|
if (!s_adc_digi_ctx->hal.rx_desc) {
|
||||||
|
ret = ESP_ERR_NO_MEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
//malloc pattern table
|
||||||
|
s_adc_digi_ctx->digi_controller_config.adc_pattern = calloc(1, SOC_ADC_PATT_LEN_MAX * sizeof(adc_digi_pattern_table_t));
|
||||||
|
if (!s_adc_digi_ctx->digi_controller_config.adc_pattern) {
|
||||||
|
ret = ESP_ERR_NO_MEM;
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
ret = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "adc_dma", &s_adc_digi_ctx->pm_lock);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#endif //CONFIG_PM_ENABLE
|
||||||
|
|
||||||
|
//init gpio pins
|
||||||
|
if (init_config->adc1_chan_mask) {
|
||||||
|
ret = adc_digi_gpio_init(ADC_NUM_1, init_config->adc1_chan_mask);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (init_config->adc2_chan_mask) {
|
||||||
|
ret = adc_digi_gpio_init(ADC_NUM_2, init_config->adc2_chan_mask);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//alloc rx gdma channel
|
||||||
|
gdma_channel_alloc_config_t rx_alloc_config = {
|
||||||
|
.direction = GDMA_CHANNEL_DIRECTION_RX,
|
||||||
|
};
|
||||||
|
ret = gdma_new_channel(&rx_alloc_config, &s_adc_digi_ctx->rx_dma_channel);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
gdma_connect(s_adc_digi_ctx->rx_dma_channel, GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_ADC, 0));
|
||||||
|
|
||||||
|
gdma_strategy_config_t strategy_config = {
|
||||||
|
.auto_update_desc = true,
|
||||||
|
.owner_check = true
|
||||||
|
};
|
||||||
|
gdma_apply_strategy(s_adc_digi_ctx->rx_dma_channel, &strategy_config);
|
||||||
|
|
||||||
|
gdma_rx_event_callbacks_t cbs = {
|
||||||
|
.on_recv_eof = adc_dma_in_suc_eof_callback
|
||||||
|
};
|
||||||
|
gdma_register_rx_event_callbacks(s_adc_digi_ctx->rx_dma_channel, &cbs, s_adc_digi_ctx);
|
||||||
|
|
||||||
|
int dma_chan;
|
||||||
|
gdma_get_channel_id(s_adc_digi_ctx->rx_dma_channel, &dma_chan);
|
||||||
|
|
||||||
|
adc_hal_config_t config = {
|
||||||
|
.desc_max_num = INTERNAL_BUF_NUM,
|
||||||
|
.dma_chan = dma_chan,
|
||||||
|
.eof_num = init_config->conv_num_each_intr / ADC_HAL_DATA_LEN_PER_CONV
|
||||||
|
};
|
||||||
|
adc_hal_context_config(&s_adc_digi_ctx->hal, &config);
|
||||||
|
|
||||||
|
//enable SARADC module clock
|
||||||
|
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||||
|
|
||||||
|
adc_hal_calibration_init(ADC_NUM_1);
|
||||||
|
adc_hal_calibration_init(ADC_NUM_2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
adc_digi_deinitialize();
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx);
|
||||||
|
|
||||||
|
static IRAM_ATTR bool adc_dma_in_suc_eof_callback(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||||
|
{
|
||||||
|
assert(event_data);
|
||||||
|
adc_digi_context_t *adc_digi_ctx = (adc_digi_context_t *)user_data;
|
||||||
|
adc_digi_ctx->rx_eof_desc_addr = event_data->rx_eof_desc_addr;
|
||||||
|
return adc_dma_intr(adc_digi_ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static IRAM_ATTR bool adc_dma_intr(adc_digi_context_t *adc_digi_ctx)
|
||||||
|
{
|
||||||
|
portBASE_TYPE taskAwoken = 0;
|
||||||
|
BaseType_t ret;
|
||||||
|
adc_hal_dma_desc_status_t status = false;
|
||||||
|
dma_descriptor_t *current_desc = NULL;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
status = adc_hal_get_reading_result(&adc_digi_ctx->hal, adc_digi_ctx->rx_eof_desc_addr, ¤t_desc);
|
||||||
|
if (status != ADC_HAL_DMA_DESC_VALID) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = xRingbufferSendFromISR(adc_digi_ctx->ringbuf_hdl, current_desc->buffer, current_desc->dw0.length, &taskAwoken);
|
||||||
|
if (ret == pdFALSE) {
|
||||||
|
//ringbuffer overflow
|
||||||
|
adc_digi_ctx->ringbuf_overflow_flag = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status == ADC_HAL_DMA_DESC_NULL) {
|
||||||
|
//start next turns of dma operation
|
||||||
|
adc_hal_digi_rxdma_start(&adc_digi_ctx->hal, adc_digi_ctx->rx_dma_buf);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (taskAwoken == pdTRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_start(void)
|
||||||
|
{
|
||||||
|
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||||
|
ESP_LOGE(ADC_TAG, "The driver is already started");
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
adc_power_acquire();
|
||||||
|
//reset flags
|
||||||
|
s_adc_digi_ctx->ringbuf_overflow_flag = 0;
|
||||||
|
s_adc_digi_ctx->driver_start_flag = 1;
|
||||||
|
if (s_adc_digi_ctx->use_adc1) {
|
||||||
|
SAR_ADC1_LOCK_ACQUIRE();
|
||||||
|
}
|
||||||
|
if (s_adc_digi_ctx->use_adc2) {
|
||||||
|
SAR_ADC2_LOCK_ACQUIRE();
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
// Lock APB frequency while ADC driver is in use
|
||||||
|
esp_pm_lock_acquire(s_adc_digi_ctx->pm_lock);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
adc_arbiter_t config = ADC_ARBITER_CONFIG_DEFAULT();
|
||||||
|
if (s_adc_digi_ctx->use_adc1) {
|
||||||
|
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc1_atten);
|
||||||
|
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||||
|
}
|
||||||
|
if (s_adc_digi_ctx->use_adc2) {
|
||||||
|
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, ADC_CHANNEL_MAX, s_adc_digi_ctx->adc2_atten);
|
||||||
|
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_hal_init();
|
||||||
|
adc_hal_arbiter_config(&config);
|
||||||
|
adc_hal_digi_init(&s_adc_digi_ctx->hal);
|
||||||
|
adc_hal_digi_controller_config(&s_adc_digi_ctx->digi_controller_config);
|
||||||
|
|
||||||
|
//reset ADC and DMA
|
||||||
|
adc_hal_fifo_reset(&s_adc_digi_ctx->hal);
|
||||||
|
//start DMA
|
||||||
|
adc_hal_digi_rxdma_start(&s_adc_digi_ctx->hal, s_adc_digi_ctx->rx_dma_buf);
|
||||||
|
//start ADC
|
||||||
|
adc_hal_digi_start(&s_adc_digi_ctx->hal);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_stop(void)
|
||||||
|
{
|
||||||
|
if (s_adc_digi_ctx->driver_start_flag != 1) {
|
||||||
|
ESP_LOGE(ADC_TAG, "The driver is already stopped");
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
s_adc_digi_ctx->driver_start_flag = 0;
|
||||||
|
|
||||||
|
//disable the in suc eof intrrupt
|
||||||
|
adc_hal_digi_dis_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||||
|
//clear the in suc eof interrupt
|
||||||
|
adc_hal_digi_clr_intr(&s_adc_digi_ctx->hal, IN_SUC_EOF_BIT);
|
||||||
|
//stop ADC
|
||||||
|
adc_hal_digi_stop(&s_adc_digi_ctx->hal);
|
||||||
|
//stop DMA
|
||||||
|
adc_hal_digi_rxdma_stop(&s_adc_digi_ctx->hal);
|
||||||
|
adc_hal_digi_deinit();
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
if (s_adc_digi_ctx->pm_lock) {
|
||||||
|
esp_pm_lock_release(s_adc_digi_ctx->pm_lock);
|
||||||
|
}
|
||||||
|
#endif //CONFIG_PM_ENABLE
|
||||||
|
|
||||||
|
if (s_adc_digi_ctx->use_adc1) {
|
||||||
|
SAR_ADC1_LOCK_RELEASE();
|
||||||
|
}
|
||||||
|
if (s_adc_digi_ctx->use_adc2) {
|
||||||
|
SAR_ADC2_LOCK_RELEASE();
|
||||||
|
}
|
||||||
|
adc_power_release();
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_length, uint32_t timeout_ms)
|
||||||
|
{
|
||||||
|
TickType_t ticks_to_wait;
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
uint8_t *data = NULL;
|
||||||
|
size_t size = 0;
|
||||||
|
|
||||||
|
ticks_to_wait = timeout_ms / portTICK_RATE_MS;
|
||||||
|
if (timeout_ms == ADC_MAX_DELAY) {
|
||||||
|
ticks_to_wait = portMAX_DELAY;
|
||||||
|
}
|
||||||
|
|
||||||
|
data = xRingbufferReceiveUpTo(s_adc_digi_ctx->ringbuf_hdl, &size, ticks_to_wait, length_max);
|
||||||
|
if (!data) {
|
||||||
|
ESP_LOGV(ADC_TAG, "No data, increase timeout or reduce conv_num_each_intr");
|
||||||
|
ret = ESP_ERR_TIMEOUT;
|
||||||
|
*out_length = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(buf, data, size);
|
||||||
|
vRingbufferReturnItem(s_adc_digi_ctx->ringbuf_hdl, data);
|
||||||
|
assert((size % 4) == 0);
|
||||||
|
*out_length = size;
|
||||||
|
|
||||||
|
if (s_adc_digi_ctx->ringbuf_overflow_flag) {
|
||||||
|
ret = ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_deinitialize(void)
|
||||||
|
{
|
||||||
|
if (!s_adc_digi_ctx) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_adc_digi_ctx->driver_start_flag != 0) {
|
||||||
|
ESP_LOGE(ADC_TAG, "The driver is not stopped");
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_adc_digi_ctx->ringbuf_hdl) {
|
||||||
|
vRingbufferDelete(s_adc_digi_ctx->ringbuf_hdl);
|
||||||
|
s_adc_digi_ctx->ringbuf_hdl = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_PM_ENABLE
|
||||||
|
if (s_adc_digi_ctx->pm_lock) {
|
||||||
|
esp_pm_lock_delete(s_adc_digi_ctx->pm_lock);
|
||||||
|
}
|
||||||
|
#endif //CONFIG_PM_ENABLE
|
||||||
|
|
||||||
|
free(s_adc_digi_ctx->rx_dma_buf);
|
||||||
|
free(s_adc_digi_ctx->hal.rx_desc);
|
||||||
|
free(s_adc_digi_ctx->digi_controller_config.adc_pattern);
|
||||||
|
gdma_disconnect(s_adc_digi_ctx->rx_dma_channel);
|
||||||
|
gdma_del_channel(s_adc_digi_ctx->rx_dma_channel);
|
||||||
|
|
||||||
|
free(s_adc_digi_ctx);
|
||||||
|
s_adc_digi_ctx = NULL;
|
||||||
|
|
||||||
|
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------
|
||||||
|
ADC Single Read Mode
|
||||||
|
---------------------------------------------------------------*/
|
||||||
|
static adc_atten_t s_atten1_single[ADC1_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC1, used by single read API
|
||||||
|
static adc_atten_t s_atten2_single[ADC2_CHANNEL_MAX]; //Array saving attenuate of each channel of ADC2, used by single read API
|
||||||
|
|
||||||
|
esp_err_t adc_vref_to_gpio(adc_unit_t adc_unit, gpio_num_t gpio)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
uint32_t channel = ADC2_CHANNEL_MAX;
|
||||||
|
if (adc_unit == ADC_UNIT_2) {
|
||||||
|
for (int i = 0; i < ADC2_CHANNEL_MAX; i++) {
|
||||||
|
if (gpio == ADC_GET_IO_NUM(ADC_NUM_2, i)) {
|
||||||
|
channel = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (channel == ADC2_CHANNEL_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
adc_power_acquire();
|
||||||
|
if (adc_unit & ADC_UNIT_1) {
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_vref_output(ADC_NUM_1, channel, true);
|
||||||
|
ADC_EXIT_CRITICAL()
|
||||||
|
} else if (adc_unit & ADC_UNIT_2) {
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_vref_output(ADC_NUM_2, channel, true);
|
||||||
|
ADC_EXIT_CRITICAL()
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||||
|
{
|
||||||
|
//On ESP32H2, the data width is always 12-bits.
|
||||||
|
if (width_bit != ADC_WIDTH_BIT_12) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc1_config_channel_atten(adc1_channel_t channel, adc_atten_t atten)
|
||||||
|
{
|
||||||
|
ADC_CHANNEL_CHECK(ADC_NUM_1, channel);
|
||||||
|
ADC_CHECK(atten < ADC_ATTEN_MAX, "ADC Atten Err", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
s_atten1_single[channel] = atten;
|
||||||
|
ret = adc_digi_gpio_init(ADC_NUM_1, BIT(channel));
|
||||||
|
|
||||||
|
adc_hal_calibration_init(ADC_NUM_1);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int adc1_get_raw(adc1_channel_t channel)
|
||||||
|
{
|
||||||
|
int raw_out = 0;
|
||||||
|
|
||||||
|
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||||
|
adc_power_acquire();
|
||||||
|
|
||||||
|
SAR_ADC1_LOCK_ACQUIRE();
|
||||||
|
|
||||||
|
adc_atten_t atten = s_atten1_single[channel];
|
||||||
|
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_1, channel, atten);
|
||||||
|
adc_hal_set_calibration_param(ADC_NUM_1, cal_val);
|
||||||
|
|
||||||
|
ADC_REG_LOCK_ENTER();
|
||||||
|
adc_hal_set_atten(ADC_NUM_2, channel, atten);
|
||||||
|
adc_hal_convert(ADC_NUM_1, channel, &raw_out);
|
||||||
|
ADC_REG_LOCK_EXIT();
|
||||||
|
|
||||||
|
SAR_ADC1_LOCK_RELEASE();
|
||||||
|
|
||||||
|
adc_power_release();
|
||||||
|
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||||
|
|
||||||
|
return raw_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||||
|
{
|
||||||
|
ADC_CHANNEL_CHECK(ADC_NUM_2, channel);
|
||||||
|
ADC_CHECK(atten <= ADC_ATTEN_11db, "ADC2 Atten Err", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
s_atten2_single[channel] = atten;
|
||||||
|
ret = adc_digi_gpio_init(ADC_NUM_2, BIT(channel));
|
||||||
|
|
||||||
|
adc_hal_calibration_init(ADC_NUM_2);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int *raw_out)
|
||||||
|
{
|
||||||
|
//On ESP32H2, the data width is always 12-bits.
|
||||||
|
if (width_bit != ADC_WIDTH_BIT_12) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
periph_module_enable(PERIPH_SARADC_MODULE);
|
||||||
|
adc_power_acquire();
|
||||||
|
|
||||||
|
SAR_ADC2_LOCK_ACQUIRE();
|
||||||
|
|
||||||
|
adc_atten_t atten = s_atten2_single[channel];
|
||||||
|
uint32_t cal_val = adc_get_calibration_offset(ADC_NUM_2, channel, atten);
|
||||||
|
adc_hal_set_calibration_param(ADC_NUM_2, cal_val);
|
||||||
|
|
||||||
|
ADC_REG_LOCK_ENTER();
|
||||||
|
adc_hal_set_atten(ADC_NUM_2, channel, atten);
|
||||||
|
ret = adc_hal_convert(ADC_NUM_2, channel, raw_out);
|
||||||
|
ADC_REG_LOCK_EXIT();
|
||||||
|
|
||||||
|
SAR_ADC2_LOCK_RELEASE();
|
||||||
|
|
||||||
|
adc_power_release();
|
||||||
|
periph_module_disable(PERIPH_SARADC_MODULE);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------
|
||||||
|
Digital controller setting
|
||||||
|
---------------------------------------------------------------*/
|
||||||
|
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config)
|
||||||
|
{
|
||||||
|
if (!s_adc_digi_ctx) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
ADC_CHECK(config->sample_freq_hz <= SOC_ADC_SAMPLE_FREQ_THRES_HIGH && config->sample_freq_hz >= SOC_ADC_SAMPLE_FREQ_THRES_LOW, "ADC sampling frequency out of range", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
s_adc_digi_ctx->digi_controller_config.conv_limit_en = config->conv_limit_en;
|
||||||
|
s_adc_digi_ctx->digi_controller_config.conv_limit_num = config->conv_limit_num;
|
||||||
|
s_adc_digi_ctx->digi_controller_config.adc_pattern_len = config->adc_pattern_len;
|
||||||
|
s_adc_digi_ctx->digi_controller_config.sample_freq_hz = config->sample_freq_hz;
|
||||||
|
memcpy(s_adc_digi_ctx->digi_controller_config.adc_pattern, config->adc_pattern, config->adc_pattern_len * sizeof(adc_digi_pattern_table_t));
|
||||||
|
|
||||||
|
const int atten_uninitialised = 999;
|
||||||
|
s_adc_digi_ctx->adc1_atten = atten_uninitialised;
|
||||||
|
s_adc_digi_ctx->adc2_atten = atten_uninitialised;
|
||||||
|
s_adc_digi_ctx->use_adc1 = 0;
|
||||||
|
s_adc_digi_ctx->use_adc2 = 0;
|
||||||
|
for (int i = 0; i < config->adc_pattern_len; i++) {
|
||||||
|
const adc_digi_pattern_table_t *pat = &config->adc_pattern[i];
|
||||||
|
if (pat->unit == ADC_NUM_1) {
|
||||||
|
s_adc_digi_ctx->use_adc1 = 1;
|
||||||
|
|
||||||
|
if (s_adc_digi_ctx->adc1_atten == atten_uninitialised) {
|
||||||
|
s_adc_digi_ctx->adc1_atten = pat->atten;
|
||||||
|
} else if (s_adc_digi_ctx->adc1_atten != pat->atten) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
} else if (pat->unit == ADC_NUM_2) {
|
||||||
|
//See whether ADC2 will be used or not. If yes, the ``sar_adc2_mutex`` should be acquired in the continuous read driver
|
||||||
|
s_adc_digi_ctx->use_adc2 = 1;
|
||||||
|
|
||||||
|
if (s_adc_digi_ctx->adc2_atten == atten_uninitialised) {
|
||||||
|
s_adc_digi_ctx->adc2_atten = pat->atten;
|
||||||
|
} else if (s_adc_digi_ctx->adc2_atten != pat->atten) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*************************************/
|
||||||
|
/* Digital controller filter setting */
|
||||||
|
/*************************************/
|
||||||
|
|
||||||
|
esp_err_t adc_digi_filter_reset(adc_digi_filter_idx_t idx)
|
||||||
|
{
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_digi_filter_reset(idx);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_filter_set_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
|
||||||
|
{
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_digi_filter_set_factor(idx, config);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_filter_get_config(adc_digi_filter_idx_t idx, adc_digi_filter_t *config)
|
||||||
|
{
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_digi_filter_get_factor(idx, config);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_filter_enable(adc_digi_filter_idx_t idx, bool enable)
|
||||||
|
{
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_digi_filter_enable(idx, enable);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************/
|
||||||
|
/* Digital controller monitor setting */
|
||||||
|
/**************************************/
|
||||||
|
|
||||||
|
esp_err_t adc_digi_monitor_set_config(adc_digi_monitor_idx_t idx, adc_digi_monitor_t *config)
|
||||||
|
{
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_digi_monitor_config(idx, config);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t adc_digi_monitor_enable(adc_digi_monitor_idx_t idx, bool enable)
|
||||||
|
{
|
||||||
|
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_digi_monitor_enable(idx, enable);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------
|
||||||
|
RTC controller setting
|
||||||
|
---------------------------------------------------------------*/
|
||||||
|
|
||||||
|
static uint16_t s_adc_cali_param[ADC_UNIT_MAX][ADC_ATTEN_MAX] = {};
|
||||||
|
|
||||||
|
//NOTE: according to calibration version, different types of lock may be taken during the process:
|
||||||
|
// 1. Semaphore when reading efuse
|
||||||
|
// 2. Lock (Spinlock, or Mutex) if we actually do ADC calibration in the future
|
||||||
|
//This function shoudn't be called inside critical section or ISR
|
||||||
|
static uint32_t adc_get_calibration_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||||
|
{
|
||||||
|
const bool no_cal = false;
|
||||||
|
if (s_adc_cali_param[adc_n][atten]) {
|
||||||
|
return (uint32_t)s_adc_cali_param[adc_n][atten];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (no_cal) {
|
||||||
|
return 0; //indicating failure
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if we can fetch the values from eFuse.
|
||||||
|
int version = esp_efuse_rtc_calib_get_ver();
|
||||||
|
|
||||||
|
uint32_t init_code = 0;
|
||||||
|
if (version == 1) {
|
||||||
|
//for calibration v1, both ADC units use the same init code (calibrated by ADC1)
|
||||||
|
init_code = esp_efuse_rtc_calib_get_init_code(version, atten);
|
||||||
|
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC0, 1 atten=%d: %04X", version, atten, init_code);
|
||||||
|
s_adc_cali_param[0][atten] = init_code;
|
||||||
|
s_adc_cali_param[1][atten] = init_code;
|
||||||
|
} else {
|
||||||
|
adc_power_acquire();
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
const bool internal_gnd = true;
|
||||||
|
init_code = adc_hal_self_calibration(adc_n, channel, atten, internal_gnd);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
adc_power_release();
|
||||||
|
|
||||||
|
ESP_LOGD(ADC_TAG, "Calib(V%d) ADC%d atten=%d: %04X", version, adc_n, atten, init_code);
|
||||||
|
s_adc_cali_param[adc_n][atten] = init_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
return init_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Internal function to calibrate PWDET for WiFi
|
||||||
|
esp_err_t adc_cal_offset(adc_ll_num_t adc_n, adc_channel_t channel, adc_atten_t atten)
|
||||||
|
{
|
||||||
|
adc_hal_calibration_init(adc_n);
|
||||||
|
uint32_t cal_val = adc_get_calibration_offset(adc_n, channel, atten);
|
||||||
|
ADC_ENTER_CRITICAL();
|
||||||
|
adc_hal_set_calibration_param(adc_n, cal_val);
|
||||||
|
ADC_EXIT_CRITICAL();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
31
components/driver/esp32h2/adc2_init_cal.c
Normal file
31
components/driver/esp32h2/adc2_init_cal.c
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file is used to get `adc2_init_code_calibration` executed before the APP when the ADC2 is used by Wi-Fi or other drivers.
|
||||||
|
The linker will link constructor (adc2_init_code_calibration) only when any sections inside the same file (adc2_cal_include) is used.
|
||||||
|
Don't put any other code into this file. */
|
||||||
|
|
||||||
|
#include "adc2_wifi_private.h"
|
||||||
|
#include "hal/adc_hal.h"
|
||||||
|
#include "esp_private/adc_cali.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set initial code to ADC2 after calibration. ADC2 RTC and ADC2 PWDET controller share the initial code.
|
||||||
|
* This API be called in before `app_main()`.
|
||||||
|
*/
|
||||||
|
static __attribute__((constructor)) void adc2_init_code_calibration(void)
|
||||||
|
{
|
||||||
|
const adc_ll_num_t adc_n = ADC_NUM_2;
|
||||||
|
const adc_atten_t atten = ADC_ATTEN_DB_11;
|
||||||
|
const adc_channel_t channel = 0;
|
||||||
|
adc_cal_offset(adc_n, channel, atten);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Don't call `adc2_cal_include` in user code. */
|
||||||
|
void adc2_cal_include(void)
|
||||||
|
{
|
||||||
|
/* When this empty function is called, the `adc2_init_code_calibration` constructor will be linked and executed before the app.*/
|
||||||
|
}
|
93
components/driver/esp32h2/include/driver/adc.h
Normal file
93
components/driver/esp32h2/include/driver/adc.h
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2019-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "driver/adc_common.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------
|
||||||
|
Common setting
|
||||||
|
---------------------------------------------------------------*/
|
||||||
|
/*************************************/
|
||||||
|
/* 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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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.
|
||||||
|
*
|
||||||
|
* @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);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
91
components/driver/esp32h2/include/driver/temp_sensor.h
Normal file
91
components/driver/esp32h2/include/driver/temp_sensor.h
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
#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
|
151
components/driver/esp32h2/rtc_tempsensor.c
Normal file
151
components/driver/esp32h2/rtc_tempsensor.c
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2016-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esp_types.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/semphr.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "hal/adc_ll.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/apb_saradc_struct.h"
|
||||||
|
#include "soc/apb_saradc_reg.h"
|
||||||
|
#include "soc/system_reg.h"
|
||||||
|
#include "driver/temp_sensor.h"
|
||||||
|
#include "regi2c_ctrl.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp_efuse_rtc_calib.h"
|
||||||
|
|
||||||
|
static const char *TAG = "tsens";
|
||||||
|
|
||||||
|
#define TSENS_CHECK(res, ret_val) ({ \
|
||||||
|
if (!(res)) { \
|
||||||
|
ESP_LOGE(TAG, "%s(%d)", __FUNCTION__, __LINE__); \
|
||||||
|
return (ret_val); \
|
||||||
|
} \
|
||||||
|
})
|
||||||
|
#define TSENS_XPD_WAIT_DEFAULT 0xFF /* Set wait cycle time(8MHz) from power up to reset enable. */
|
||||||
|
#define TSENS_ADC_FACTOR (0.4386)
|
||||||
|
#define TSENS_DAC_FACTOR (27.88)
|
||||||
|
#define TSENS_SYS_OFFSET (20.52)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int index;
|
||||||
|
int offset;
|
||||||
|
int set_val;
|
||||||
|
int range_min;
|
||||||
|
int range_max;
|
||||||
|
int error_max;
|
||||||
|
} tsens_dac_offset_t;
|
||||||
|
|
||||||
|
static const tsens_dac_offset_t dac_offset[TSENS_DAC_MAX] = {
|
||||||
|
/* DAC Offset reg_val min max error */
|
||||||
|
{TSENS_DAC_L0, -2, 5, 50, 125, 3},
|
||||||
|
{TSENS_DAC_L1, -1, 7, 20, 100, 2},
|
||||||
|
{TSENS_DAC_L2, 0, 15, -10, 80, 1},
|
||||||
|
{TSENS_DAC_L3, 1, 11, -30, 50, 2},
|
||||||
|
{TSENS_DAC_L4, 2, 10, -40, 20, 3},
|
||||||
|
};
|
||||||
|
|
||||||
|
static float s_deltaT = NAN; // unused number
|
||||||
|
|
||||||
|
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||||
|
{
|
||||||
|
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN);
|
||||||
|
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD);
|
||||||
|
SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU);
|
||||||
|
REGI2C_WRITE_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC, dac_offset[tsens.dac_offset].set_val);
|
||||||
|
APB_SARADC.apb_tsens_ctrl.tsens_clk_div = tsens.clk_div;
|
||||||
|
APB_SARADC.apb_tsens_ctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT;
|
||||||
|
APB_SARADC.apb_tsens_ctrl2.tsens_xpd_force = 1;
|
||||||
|
ESP_LOGD(TAG, "Config temperature range [%d°C ~ %d°C], error < %d°C",
|
||||||
|
dac_offset[tsens.dac_offset].range_min,
|
||||||
|
dac_offset[tsens.dac_offset].range_max,
|
||||||
|
dac_offset[tsens.dac_offset].error_max);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t temp_sensor_get_config(temp_sensor_config_t *tsens)
|
||||||
|
{
|
||||||
|
TSENS_CHECK(tsens != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_SAR_FORCE_PD);
|
||||||
|
SET_PERI_REG_MASK(ANA_CONFIG2_REG, ANA_I2C_SAR_FORCE_PU);
|
||||||
|
tsens->dac_offset = REGI2C_READ_MASK(I2C_SAR_ADC, I2C_SARADC_TSENS_DAC);
|
||||||
|
for (int i = TSENS_DAC_L0; i < TSENS_DAC_MAX; i++) {
|
||||||
|
if (tsens->dac_offset == dac_offset[i].set_val) {
|
||||||
|
tsens->dac_offset = dac_offset[i].index;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tsens->clk_div = APB_SARADC.apb_tsens_ctrl.tsens_clk_div;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t temp_sensor_start(void)
|
||||||
|
{
|
||||||
|
REG_SET_BIT(SYSTEM_PERIP_CLK_EN1_REG, SYSTEM_TSENS_CLK_EN);
|
||||||
|
APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 1;
|
||||||
|
APB_SARADC.apb_tsens_ctrl.tsens_pu = 1;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t temp_sensor_stop(void)
|
||||||
|
{
|
||||||
|
APB_SARADC.apb_tsens_ctrl.tsens_pu = 0;
|
||||||
|
APB_SARADC.apb_tsens_ctrl2.tsens_clk_sel = 0;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
|
||||||
|
{
|
||||||
|
TSENS_CHECK(tsens_out != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
*tsens_out = APB_SARADC.apb_tsens_ctrl.tsens_out;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_delta_t_from_efuse(void)
|
||||||
|
{
|
||||||
|
uint32_t version = esp_efuse_rtc_calib_get_ver();
|
||||||
|
if (version == 1) {
|
||||||
|
// fetch calibration value for temp sensor from eFuse
|
||||||
|
s_deltaT = esp_efuse_rtc_calib_get_cal_temp(version);
|
||||||
|
} else {
|
||||||
|
// no value to fetch, use 0.
|
||||||
|
s_deltaT = 0;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "s_deltaT = %f", s_deltaT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static float parse_temp_sensor_raw_value(uint32_t tsens_raw, const int dac_offset)
|
||||||
|
{
|
||||||
|
if (isnan(s_deltaT)) { //suggests that the value is not initialized
|
||||||
|
read_delta_t_from_efuse();
|
||||||
|
}
|
||||||
|
float result = (TSENS_ADC_FACTOR * (float)tsens_raw - TSENS_DAC_FACTOR * dac_offset - TSENS_SYS_OFFSET) - s_deltaT / 10.0;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t temp_sensor_read_celsius(float *celsius)
|
||||||
|
{
|
||||||
|
TSENS_CHECK(celsius != NULL, ESP_ERR_INVALID_ARG);
|
||||||
|
temp_sensor_config_t tsens;
|
||||||
|
uint32_t tsens_out = 0;
|
||||||
|
esp_err_t ret = temp_sensor_get_config(&tsens);
|
||||||
|
if (ret == ESP_OK) {
|
||||||
|
ret = temp_sensor_read_raw(&tsens_out);
|
||||||
|
printf("tsens_out %d\r\n", tsens_out);
|
||||||
|
TSENS_CHECK(ret == ESP_OK, ret);
|
||||||
|
const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
|
||||||
|
*celsius = parse_temp_sensor_raw_value(tsens_out, dac->offset);
|
||||||
|
if (*celsius < dac->range_min || *celsius > dac->range_max) {
|
||||||
|
ESP_LOGW(TAG, "Exceeding the temperature range!");
|
||||||
|
ret = ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
@@ -35,7 +35,7 @@ esp_err_t adc2_wifi_acquire(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t adc2_wifi_release(void);
|
esp_err_t adc2_wifi_release(void);
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
/**
|
/**
|
||||||
* @brief This API help ADC2 calibration constructor be linked.
|
* @brief This API help ADC2 calibration constructor be linked.
|
||||||
*
|
*
|
||||||
|
@@ -45,7 +45,7 @@ typedef enum {
|
|||||||
ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */
|
ADC1_CHANNEL_9, /*!< ADC1 channel 9 is GPIO10 */
|
||||||
ADC1_CHANNEL_MAX,
|
ADC1_CHANNEL_MAX,
|
||||||
} adc1_channel_t;
|
} adc1_channel_t;
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
/**** `adc1_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */
|
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO0 */
|
||||||
@@ -72,7 +72,7 @@ typedef enum {
|
|||||||
ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */
|
ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */
|
||||||
ADC2_CHANNEL_MAX,
|
ADC2_CHANNEL_MAX,
|
||||||
} adc2_channel_t;
|
} adc2_channel_t;
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
/**** `adc2_channel_t` will be deprecated functions, combine into `adc_channel_t` ********/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
|
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO5 */
|
||||||
@@ -103,7 +103,7 @@ typedef enum {
|
|||||||
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
|
#define ADC_WIDTH_11Bit ADC_WIDTH_BIT_11
|
||||||
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
|
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
/**
|
/**
|
||||||
* @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
|
* @brief Digital ADC DMA read max timeout value, it may make the ``adc_digi_read_bytes`` block forever if the OS supports
|
||||||
*/
|
*/
|
||||||
@@ -121,7 +121,7 @@ typedef enum {
|
|||||||
ADC_ENCODE_MAX,
|
ADC_ENCODE_MAX,
|
||||||
} adc_i2s_encode_t;
|
} adc_i2s_encode_t;
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
||||||
/**
|
/**
|
||||||
* @brief Digital ADC DMA configuration
|
* @brief Digital ADC DMA configuration
|
||||||
@@ -167,7 +167,7 @@ void adc_power_acquire(void);
|
|||||||
*/
|
*/
|
||||||
void adc_power_release(void);
|
void adc_power_release(void);
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
|
||||||
/**
|
/**
|
||||||
* @brief Initialize ADC pad
|
* @brief Initialize ADC pad
|
||||||
* @param adc_unit ADC unit index
|
* @param adc_unit ADC unit index
|
||||||
@@ -177,7 +177,7 @@ void adc_power_release(void);
|
|||||||
* - ESP_ERR_INVALID_ARG Parameter error
|
* - ESP_ERR_INVALID_ARG Parameter error
|
||||||
*/
|
*/
|
||||||
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel);
|
||||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3
|
#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
|
||||||
/*---------------------------------------------------------------
|
/*---------------------------------------------------------------
|
||||||
ADC Single Read Setting
|
ADC Single Read Setting
|
||||||
@@ -276,7 +276,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit);
|
|||||||
*/
|
*/
|
||||||
int adc1_get_raw(adc1_channel_t channel);
|
int adc1_get_raw(adc1_channel_t channel);
|
||||||
|
|
||||||
#if !CONFIG_IDF_TARGET_ESP32C3
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
|
||||||
/**
|
/**
|
||||||
* @brief Set ADC data invert
|
* @brief Set ADC data invert
|
||||||
* @param adc_unit ADC unit index
|
* @param adc_unit ADC unit index
|
||||||
@@ -317,7 +317,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t width_bit);
|
|||||||
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
|
* to be called to configure ADC1 channels, before ADC1 is used by the ULP.
|
||||||
*/
|
*/
|
||||||
void adc1_ulp_enable(void);
|
void adc1_ulp_enable(void);
|
||||||
#endif //#if !CONFIG_IDF_TARGET_ESP32C3
|
#endif //#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Get the GPIO number of a specific ADC2 channel.
|
* @brief Get the GPIO number of a specific ADC2 channel.
|
||||||
@@ -477,7 +477,7 @@ esp_err_t adc_digi_deinit(void);
|
|||||||
*/
|
*/
|
||||||
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
|
esp_err_t adc_digi_controller_config(const adc_digi_config_t *config);
|
||||||
|
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3
|
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
//This feature is currently supported on ESP32C3, will be supported on other chips soon
|
||||||
/*---------------------------------------------------------------
|
/*---------------------------------------------------------------
|
||||||
DMA setting
|
DMA setting
|
||||||
@@ -537,7 +537,7 @@ esp_err_t adc_digi_read_bytes(uint8_t *buf, uint32_t length_max, uint32_t *out_l
|
|||||||
*/
|
*/
|
||||||
esp_err_t adc_digi_deinitialize(void);
|
esp_err_t adc_digi_deinitialize(void);
|
||||||
|
|
||||||
#endif //#if CONFIG_IDF_TARGET_ESP32C3
|
#endif //#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
@@ -33,6 +33,8 @@
|
|||||||
#include "esp32c3/rom/gpio.h"
|
#include "esp32c3/rom/gpio.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/gpio.h"
|
#include "esp32s3/rom/gpio.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/gpio.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS
|
#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS
|
||||||
|
@@ -42,6 +42,7 @@ void periph_module_reset(periph_module_t periph)
|
|||||||
portEXIT_CRITICAL_SAFE(&periph_spinlock);
|
portEXIT_CRITICAL_SAFE(&periph_spinlock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_WIFI_ENABLED
|
||||||
IRAM_ATTR void wifi_bt_common_module_enable(void)
|
IRAM_ATTR void wifi_bt_common_module_enable(void)
|
||||||
{
|
{
|
||||||
portENTER_CRITICAL_SAFE(&periph_spinlock);
|
portENTER_CRITICAL_SAFE(&periph_spinlock);
|
||||||
@@ -71,3 +72,4 @@ void wifi_module_disable(void)
|
|||||||
{
|
{
|
||||||
periph_ll_wifi_module_disable_clk_set_rst();
|
periph_ll_wifi_module_disable_clk_set_rst();
|
||||||
}
|
}
|
||||||
|
#endif // CONFIG_ESP32_WIFI_ENABLED
|
||||||
|
@@ -32,6 +32,8 @@
|
|||||||
#include "esp32s3/clk.h"
|
#include "esp32s3/clk.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/clk.h"
|
#include "esp32c3/clk.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/clk.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_UART_ISR_IN_IRAM
|
#ifdef CONFIG_UART_ISR_IN_IRAM
|
||||||
|
63
components/efuse/esp32h2/esp_efuse_fields.c
Normal file
63
components/efuse/esp32h2/esp_efuse_fields.c
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
#include "esp_efuse_utility.h"
|
||||||
|
#include "esp_efuse_table.h"
|
||||||
|
#include "stdlib.h"
|
||||||
|
#include "esp_types.h"
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "soc/efuse_periph.h"
|
||||||
|
#include "bootloader_random.h"
|
||||||
|
#include "sys/param.h"
|
||||||
|
|
||||||
|
static __attribute__((unused)) const char *TAG = "efuse";
|
||||||
|
|
||||||
|
// Contains functions that provide access to efuse fields which are often used in IDF.
|
||||||
|
|
||||||
|
// Returns chip version from efuse
|
||||||
|
uint8_t esp_efuse_get_chip_ver(void)
|
||||||
|
{
|
||||||
|
uint32_t chip_ver = 0;
|
||||||
|
esp_efuse_read_field_blob(ESP_EFUSE_WAFER_VERSION, &chip_ver, ESP_EFUSE_WAFER_VERSION[0]->bit_count);
|
||||||
|
return chip_ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns chip package from efuse
|
||||||
|
uint32_t esp_efuse_get_pkg_ver(void)
|
||||||
|
{
|
||||||
|
uint32_t pkg_ver = 0;
|
||||||
|
esp_efuse_read_field_blob(ESP_EFUSE_PKG_VERSION, &pkg_ver, ESP_EFUSE_PKG_VERSION[0]->bit_count);
|
||||||
|
return pkg_ver;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_set_rom_log_scheme(esp_efuse_rom_log_scheme_t log_scheme)
|
||||||
|
{
|
||||||
|
int cur_log_scheme = 0;
|
||||||
|
esp_efuse_read_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &cur_log_scheme, 2);
|
||||||
|
if (!cur_log_scheme) { // not burned yet
|
||||||
|
return esp_efuse_write_field_blob(ESP_EFUSE_UART_PRINT_CONTROL, &log_scheme, 2);
|
||||||
|
} else {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_disable_rom_download_mode(void)
|
||||||
|
{
|
||||||
|
return esp_efuse_write_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_enable_rom_secure_download_mode(void)
|
||||||
|
{
|
||||||
|
if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_DOWNLOAD_MODE)) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
return esp_efuse_write_field_bit(ESP_EFUSE_ENABLE_SECURITY_DOWNLOAD);
|
||||||
|
}
|
89
components/efuse/esp32h2/esp_efuse_rtc_calib.c
Normal file
89
components/efuse/esp32h2/esp_efuse_rtc_calib.c
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esp_bit_defs.h>
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
#include "esp_efuse_table.h"
|
||||||
|
|
||||||
|
int esp_efuse_rtc_calib_get_ver(void)
|
||||||
|
{
|
||||||
|
uint32_t result = 0;
|
||||||
|
esp_efuse_read_field_blob(ESP_EFUSE_BLOCK2_VERSION, &result, 3);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten)
|
||||||
|
{
|
||||||
|
assert(version == 1);
|
||||||
|
const esp_efuse_desc_t** init_code_efuse;
|
||||||
|
assert(atten < 4);
|
||||||
|
if (atten == 0) {
|
||||||
|
init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN0;
|
||||||
|
} else if (atten == 1) {
|
||||||
|
init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN1;
|
||||||
|
} else if (atten == 2) {
|
||||||
|
init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN2;
|
||||||
|
} else {
|
||||||
|
init_code_efuse = ESP_EFUSE_ADC1_INIT_CODE_ATTEN3;
|
||||||
|
}
|
||||||
|
|
||||||
|
int init_code_size = esp_efuse_get_field_size(init_code_efuse);
|
||||||
|
assert(init_code_size == 10);
|
||||||
|
|
||||||
|
uint32_t init_code = 0;
|
||||||
|
ESP_ERROR_CHECK(esp_efuse_read_field_blob(init_code_efuse, &init_code, init_code_size));
|
||||||
|
return init_code + 1000; // version 1 logic
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* out_digi, uint32_t* out_vol_mv)
|
||||||
|
{
|
||||||
|
const esp_efuse_desc_t** cal_vol_efuse;
|
||||||
|
uint32_t calib_vol_expected_mv;
|
||||||
|
if (version != 1) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (atten >= 4) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (atten == 0) {
|
||||||
|
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN0;
|
||||||
|
calib_vol_expected_mv = 400;
|
||||||
|
} else if (atten == 1) {
|
||||||
|
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN1;
|
||||||
|
calib_vol_expected_mv = 550;
|
||||||
|
} else if (atten == 2) {
|
||||||
|
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN2;
|
||||||
|
calib_vol_expected_mv = 750;
|
||||||
|
} else {
|
||||||
|
cal_vol_efuse = ESP_EFUSE_ADC1_CAL_VOL_ATTEN3;
|
||||||
|
calib_vol_expected_mv = 1370;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(cal_vol_efuse[0]->bit_count == 10);
|
||||||
|
|
||||||
|
uint32_t cal_vol = 0;
|
||||||
|
ESP_ERROR_CHECK(esp_efuse_read_field_blob(cal_vol_efuse, &cal_vol, cal_vol_efuse[0]->bit_count));
|
||||||
|
|
||||||
|
*out_digi = 2000 + ((cal_vol & BIT(9))? -(cal_vol & ~BIT9): cal_vol);
|
||||||
|
*out_vol_mv = calib_vol_expected_mv;
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
float esp_efuse_rtc_calib_get_cal_temp(int version)
|
||||||
|
{
|
||||||
|
assert(version == 1);
|
||||||
|
const esp_efuse_desc_t** cal_temp_efuse;
|
||||||
|
cal_temp_efuse = ESP_EFUSE_TEMP_CALIB;
|
||||||
|
int cal_temp_size = esp_efuse_get_field_size(cal_temp_efuse);
|
||||||
|
assert(cal_temp_size == 9);
|
||||||
|
|
||||||
|
uint32_t cal_temp = 0;
|
||||||
|
esp_err_t err = esp_efuse_read_field_blob(cal_temp_efuse, &cal_temp, cal_temp_size);
|
||||||
|
assert(err == ESP_OK);
|
||||||
|
(void)err;
|
||||||
|
// BIT(8) stands for sign: 1: negtive, 0: positive
|
||||||
|
return ((cal_temp & BIT(8)) != 0)? -(uint8_t)cal_temp: (uint8_t)cal_temp;
|
||||||
|
}
|
1128
components/efuse/esp32h2/esp_efuse_table.c
Normal file
1128
components/efuse/esp32h2/esp_efuse_table.c
Normal file
File diff suppressed because it is too large
Load Diff
165
components/efuse/esp32h2/esp_efuse_table.csv
Normal file
165
components/efuse/esp32h2/esp_efuse_table.csv
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
# field_name, | efuse_block, | bit_start, | bit_count, |comment #
|
||||||
|
# | (EFUSE_BLK0 | (0..255) | (1..-) | #
|
||||||
|
# | EFUSE_BLK1 | |MAX_BLK_LEN*| #
|
||||||
|
# | ... | | | #
|
||||||
|
# | EFUSE_BLK10)| | | #
|
||||||
|
##########################################################################
|
||||||
|
# *) The value MAX_BLK_LEN depends on CONFIG_EFUSE_MAX_BLK_LEN, will be replaced with "None" - 256. "3/4" - 192. "REPEAT" - 128.
|
||||||
|
# !!!!!!!!!!! #
|
||||||
|
# After editing this file, run the command manually "make efuse_common_table" or "idf.py efuse_common_table"
|
||||||
|
# this will generate new source files, next rebuild all the sources.
|
||||||
|
# !!!!!!!!!!! #
|
||||||
|
|
||||||
|
# ESP32H2-TODO: IDF-3390
|
||||||
|
# EFUSE_RD_REPEAT_DATA BLOCK #
|
||||||
|
##############################
|
||||||
|
# EFUSE_RD_WR_DIS_REG #
|
||||||
|
WR_DIS, EFUSE_BLK0, 0, 32, Write protection
|
||||||
|
WR_DIS.RD_DIS, EFUSE_BLK0, 0, 1, Write protection for RD_DIS_KEY0 RD_DIS_KEY1 RD_DIS_KEY2 RD_DIS_KEY3 RD_DIS_KEY4 RD_DIS_KEY5 RD_DIS_SYS_DATA_PART2
|
||||||
|
WR_DIS.GROUP_1, EFUSE_BLK0, 2, 1, Write protection for DIS_ICACHE DIS_DOWNLOAD_ICACHE DIS_FORCE_DOWNLOAD DIS_USB DIS_CAN SOFT_DIS_JTAG DIS_DOWNLOAD_MANUAL_ENCRYPT
|
||||||
|
WR_DIS.GROUP_2, EFUSE_BLK0, 3, 1, Write protection for WDT_DELAY_SEL
|
||||||
|
WR_DIS.SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 4, 1, Write protection for SPI_BOOT_CRYPT_CNT
|
||||||
|
WR_DIS.SECURE_BOOT_KEY_REVOKE0,EFUSE_BLK0, 5, 1, Write protection for SECURE_BOOT_KEY_REVOKE0
|
||||||
|
WR_DIS.SECURE_BOOT_KEY_REVOKE1,EFUSE_BLK0, 6, 1, Write protection for SECURE_BOOT_KEY_REVOKE1
|
||||||
|
WR_DIS.SECURE_BOOT_KEY_REVOKE2,EFUSE_BLK0, 7, 1, Write protection for SECURE_BOOT_KEY_REVOKE2
|
||||||
|
WR_DIS.KEY0_PURPOSE, EFUSE_BLK0, 8, 1, Write protection for key_purpose. KEY0
|
||||||
|
WR_DIS.KEY1_PURPOSE, EFUSE_BLK0, 9, 1, Write protection for key_purpose. KEY1
|
||||||
|
WR_DIS.KEY2_PURPOSE, EFUSE_BLK0, 10, 1, Write protection for key_purpose. KEY2
|
||||||
|
WR_DIS.KEY3_PURPOSE, EFUSE_BLK0, 11, 1, Write protection for key_purpose. KEY3
|
||||||
|
WR_DIS.KEY4_PURPOSE, EFUSE_BLK0, 12, 1, Write protection for key_purpose. KEY4
|
||||||
|
WR_DIS.KEY5_PURPOSE, EFUSE_BLK0, 13, 1, Write protection for key_purpose. KEY5
|
||||||
|
WR_DIS.SECURE_BOOT_EN, EFUSE_BLK0, 15, 1, Write protection for SECURE_BOOT_EN
|
||||||
|
WR_DIS.SECURE_BOOT_AGGRESSIVE_REVOKE,EFUSE_BLK0, 16, 1, Write protection for SECURE_BOOT_AGGRESSIVE_REVOKE
|
||||||
|
WR_DIS.GROUP_3, EFUSE_BLK0, 18, 1, Write protection for FLASH_TPUW DIS_DOWNLOAD_MODE DIS_LEGACY_SPI_BOOT UART_PRINT_CHANNEL DIS_TINY_BASIC DIS_USB_DOWNLOAD_MODE ENABLE_SECURITY_DOWNLOAD UART_PRINT_CONTROL PIN_POWER_SELECTION FLASH_TYPE FORCE_SEND_RESUME SECURE_VERSION
|
||||||
|
WR_DIS.BLK1, EFUSE_BLK0, 20, 1, Write protection for EFUSE_BLK1. MAC_SPI_8M_SYS
|
||||||
|
WR_DIS.SYS_DATA_PART1, EFUSE_BLK0, 21, 1, Write protection for EFUSE_BLK2. SYS_DATA_PART1
|
||||||
|
WR_DIS.USER_DATA, EFUSE_BLK0, 22, 1, Write protection for EFUSE_BLK3. USER_DATA
|
||||||
|
WR_DIS.KEY0, EFUSE_BLK0, 23, 1, Write protection for EFUSE_BLK4. KEY0
|
||||||
|
WR_DIS.KEY1, EFUSE_BLK0, 24, 1, Write protection for EFUSE_BLK5. KEY1
|
||||||
|
WR_DIS.KEY2, EFUSE_BLK0, 25, 1, Write protection for EFUSE_BLK6. KEY2
|
||||||
|
WR_DIS.KEY3, EFUSE_BLK0, 26, 1, Write protection for EFUSE_BLK7. KEY3
|
||||||
|
WR_DIS.KEY4, EFUSE_BLK0, 27, 1, Write protection for EFUSE_BLK8. KEY4
|
||||||
|
WR_DIS.KEY5, EFUSE_BLK0, 28, 1, Write protection for EFUSE_BLK9. KEY5
|
||||||
|
WR_DIS.SYS_DATA_PART2, EFUSE_BLK0, 29, 1, Write protection for EFUSE_BLK10. SYS_DATA_PART2
|
||||||
|
|
||||||
|
# EFUSE_RD_REPEAT_DATA0_REG #
|
||||||
|
RD_DIS, EFUSE_BLK0, 32, 7, Read protection
|
||||||
|
RD_DIS.KEY0, EFUSE_BLK0, 32, 1, Read protection for EFUSE_BLK4. KEY0
|
||||||
|
RD_DIS.KEY1, EFUSE_BLK0, 33, 1, Read protection for EFUSE_BLK5. KEY1
|
||||||
|
RD_DIS.KEY2, EFUSE_BLK0, 34, 1, Read protection for EFUSE_BLK6. KEY2
|
||||||
|
RD_DIS.KEY3, EFUSE_BLK0, 35, 1, Read protection for EFUSE_BLK7. KEY3
|
||||||
|
RD_DIS.KEY4, EFUSE_BLK0, 36, 1, Read protection for EFUSE_BLK8. KEY4
|
||||||
|
RD_DIS.KEY5, EFUSE_BLK0, 37, 1, Read protection for EFUSE_BLK9. KEY5
|
||||||
|
RD_DIS.SYS_DATA_PART2, EFUSE_BLK0, 38, 1, Read protection for EFUSE_BLK10. SYS_DATA_PART2
|
||||||
|
DIS_RTC_RAM_BOOT, EFUSE_BLK0, 39, 1, Disable boot from RTC RAM
|
||||||
|
DIS_ICACHE, EFUSE_BLK0, 40, 1, Disable Icache
|
||||||
|
DIS_USB_JTAG, EFUSE_BLK0, 41, 1, Disable USB JTAG
|
||||||
|
DIS_DOWNLOAD_ICACHE, EFUSE_BLK0, 42, 1, Disable Icache in download mode
|
||||||
|
DIS_USB_DEVICE, EFUSE_BLK0, 43, 1, Disable USB_DEVICE
|
||||||
|
DIS_FORCE_DOWNLOAD, EFUSE_BLK0, 44, 1, Disable force chip go to download mode function
|
||||||
|
DIS_USB, EFUSE_BLK0, 45, 1, Disable USB function
|
||||||
|
DIS_CAN, EFUSE_BLK0, 46, 1, Disable CAN function
|
||||||
|
JTAG_SEL_ENABLE, EFUSE_BLK0, 47, 1, Set this bit to enable selection between usb_to_jtag and pad_to_jtag through strapping gpio10 when both reg_dis_usb_jtag and reg_dis_pad_jtag are equal to 0.
|
||||||
|
SOFT_DIS_JTAG, EFUSE_BLK0, 48, 2, Set these bits to disable JTAG in the soft way (odd number 1 means disable). JTAG can be enabled in HMAC module.
|
||||||
|
DIS_PAD_JTAG, EFUSE_BLK0, 51, 1, Disable JTAG in the hard way. JTAG is disabled permanently.
|
||||||
|
DIS_DOWNLOAD_MANUAL_ENCRYPT, EFUSE_BLK0, 52, 1, Disable flash encryption when in download boot modes.
|
||||||
|
USB_DREFH, EFUSE_BLK0, 53, 2, Controls single-end input threshold vrefh 1.76 V to 2 V with step of 80 mV stored in eFuse.
|
||||||
|
USB_DREFL, EFUSE_BLK0, 55, 2, Controls single-end input threshold vrefl 0.8 V to 1.04 V with step of 80 mV stored in eFuse.
|
||||||
|
USB_EXCHG_PINS, EFUSE_BLK0, 57, 1, Exchange D+ D- pins
|
||||||
|
VDD_SPI_AS_GPIO, EFUSE_BLK0, 58, 1, Set this bit to vdd spi pin function as gpio
|
||||||
|
BTLC_GPIO_ENABLE, EFUSE_BLK0, 59, 2, Enable btlc gpio
|
||||||
|
POWERGLITCH_EN, EFUSE_BLK0, 61, 1, Set this bit to enable power glitch function
|
||||||
|
POWER_GLITCH_DSENSE, EFUSE_BLK0, 62, 2, Sample delay configuration of power glitch
|
||||||
|
|
||||||
|
# EFUSE_RD_REPEAT_DATA1_REG #
|
||||||
|
WDT_DELAY_SEL, EFUSE_BLK0, 80, 2, Select RTC WDT time out threshold
|
||||||
|
SPI_BOOT_CRYPT_CNT, EFUSE_BLK0, 82, 3, SPI boot encrypt decrypt enable. odd number 1 enable. even number 1 disable
|
||||||
|
SECURE_BOOT_KEY_REVOKE0, EFUSE_BLK0, 85, 1, Enable revoke first secure boot key
|
||||||
|
SECURE_BOOT_KEY_REVOKE1, EFUSE_BLK0, 86, 1, Enable revoke second secure boot key
|
||||||
|
SECURE_BOOT_KEY_REVOKE2, EFUSE_BLK0, 87, 1, Enable revoke third secure boot key
|
||||||
|
KEY_PURPOSE_0, EFUSE_BLK0, 88, 4, Key0 purpose
|
||||||
|
KEY_PURPOSE_1, EFUSE_BLK0, 92, 4, Key1 purpose
|
||||||
|
|
||||||
|
# EFUSE_RD_REPEAT_DATA2_REG #
|
||||||
|
KEY_PURPOSE_2, EFUSE_BLK0, 96, 4, Key2 purpose
|
||||||
|
KEY_PURPOSE_3, EFUSE_BLK0, 100, 4, Key3 purpose
|
||||||
|
KEY_PURPOSE_4, EFUSE_BLK0, 104, 4, Key4 purpose
|
||||||
|
KEY_PURPOSE_5, EFUSE_BLK0, 108, 4, Key5 purpose
|
||||||
|
SECURE_BOOT_EN, EFUSE_BLK0, 116, 1, Secure boot enable
|
||||||
|
SECURE_BOOT_AGGRESSIVE_REVOKE, EFUSE_BLK0, 117, 1, Enable aggressive secure boot revoke
|
||||||
|
FLASH_TPUW, EFUSE_BLK0, 124, 4, Flash wait time after power up. (unit is ms). When value is 15. the time is 30 ms
|
||||||
|
|
||||||
|
# EFUSE_RD_REPEAT_DATA3_REG #
|
||||||
|
DIS_DOWNLOAD_MODE, EFUSE_BLK0, 128, 1, Disble download mode include boot_mode[3:0] is 0 1 2 3 6 7
|
||||||
|
DIS_LEGACY_SPI_BOOT, EFUSE_BLK0, 129, 1, Disable_Legcy_SPI_boot mode include boot_mode[3:0] is 4
|
||||||
|
UART_PRINT_CHANNEL, EFUSE_BLK0, 130, 1, 0: UART0. 1: UART1
|
||||||
|
FLASH_ECC_MODE, EFUSE_BLK0, 131, 1, Set this bit to set flsah ecc mode. 0:flash ecc 16to18 byte mode. 1:flash ecc 16to17 byte mode
|
||||||
|
DIS_USB_DOWNLOAD_MODE, EFUSE_BLK0, 132, 1, Disable download through USB
|
||||||
|
ENABLE_SECURITY_DOWNLOAD, EFUSE_BLK0, 133, 1, Enable security download mode
|
||||||
|
UART_PRINT_CONTROL, EFUSE_BLK0, 134, 2, b00:force print. b01:control by GPIO8 - low level print. b10:control by GPIO8 - high level print. b11:force disable print.
|
||||||
|
PIN_POWER_SELECTION, EFUSE_BLK0, 136, 1, GPIO33-GPIO37 power supply selection in ROM code. 0:VDD3P3_CPU. 1:VDD_SPI.
|
||||||
|
FLASH_TYPE, EFUSE_BLK0, 137, 1, Connected Flash interface type. 0: 4 data line. 1: 8 data line
|
||||||
|
FLASH_PAGE_SIZE, EFUSE_BLK0, 138, 2, Flash page size
|
||||||
|
FLASH_ECC_EN, EFUSE_BLK0, 140, 1, Enable ECC for flash boot
|
||||||
|
FORCE_SEND_RESUME, EFUSE_BLK0, 141, 1, Force ROM code to send a resume command during SPI boot
|
||||||
|
SECURE_VERSION, EFUSE_BLK0, 142, 16, Secure version for anti-rollback
|
||||||
|
|
||||||
|
# EFUSE_RD_REPEAT_DATA4_REG #
|
||||||
|
|
||||||
|
|
||||||
|
# MAC_SPI_SYS BLOCK#
|
||||||
|
#######################
|
||||||
|
MAC_FACTORY, EFUSE_BLK1, 40, 8, Factory MAC addr [0]
|
||||||
|
, EFUSE_BLK1, 32, 8, Factory MAC addr [1]
|
||||||
|
, EFUSE_BLK1, 24, 8, Factory MAC addr [2]
|
||||||
|
, EFUSE_BLK1, 16, 8, Factory MAC addr [3]
|
||||||
|
, EFUSE_BLK1, 8, 8, Factory MAC addr [4]
|
||||||
|
, EFUSE_BLK1, 0, 8, Factory MAC addr [5]
|
||||||
|
SPI_PAD_CONFIG_CLK, EFUSE_BLK1, 48, 6, SPI_PAD_configure CLK
|
||||||
|
SPI_PAD_CONFIG_Q_D1, EFUSE_BLK1, 54, 6, SPI_PAD_configure Q(D1)
|
||||||
|
SPI_PAD_CONFIG_D_D0, EFUSE_BLK1, 60, 6, SPI_PAD_configure D(D0)
|
||||||
|
SPI_PAD_CONFIG_CS, EFUSE_BLK1, 66, 6, SPI_PAD_configure CS
|
||||||
|
SPI_PAD_CONFIG_HD_D3, EFUSE_BLK1, 72, 6, SPI_PAD_configure HD(D3)
|
||||||
|
SPI_PAD_CONFIG_WP_D2, EFUSE_BLK1, 78, 6, SPI_PAD_configure WP(D2)
|
||||||
|
SPI_PAD_CONFIG_DQS, EFUSE_BLK1, 84, 6, SPI_PAD_configure DQS
|
||||||
|
SPI_PAD_CONFIG_D4, EFUSE_BLK1, 90, 6, SPI_PAD_configure D4
|
||||||
|
SPI_PAD_CONFIG_D5, EFUSE_BLK1, 96, 6, SPI_PAD_configure D5
|
||||||
|
SPI_PAD_CONFIG_D6, EFUSE_BLK1, 102, 6, SPI_PAD_configure D6
|
||||||
|
SPI_PAD_CONFIG_D7, EFUSE_BLK1, 108, 6, SPI_PAD_configure D7
|
||||||
|
WAFER_VERSION, EFUSE_BLK1, 114, 3, WAFER version
|
||||||
|
PKG_VERSION, EFUSE_BLK1, 117, 3, Package version 0:ESP32H2
|
||||||
|
BLOCK1_VERSION, EFUSE_BLK1, 120, 3, BLOCK1 efuse version
|
||||||
|
|
||||||
|
# SYS_DATA_PART1 BLOCK# - System configuration
|
||||||
|
#######################
|
||||||
|
OPTIONAL_UNIQUE_ID, EFUSE_BLK2, 0, 128, Optional unique 128-bit ID
|
||||||
|
BLOCK2_VERSION, EFUSE_BLK2, 128, 3, Version of BLOCK2
|
||||||
|
TEMP_CALIB, EFUSE_BLK2, 131, 9, Temperature calibration data
|
||||||
|
OCODE, EFUSE_BLK2, 140, 8, ADC OCode
|
||||||
|
ADC1_INIT_CODE_ATTEN0, EFUSE_BLK2, 148, 10, ADC1 init code at atten0
|
||||||
|
ADC1_INIT_CODE_ATTEN1, EFUSE_BLK2, 158, 10, ADC1 init code at atten1
|
||||||
|
ADC1_INIT_CODE_ATTEN2, EFUSE_BLK2, 168, 10, ADC1 init code at atten2
|
||||||
|
ADC1_INIT_CODE_ATTEN3, EFUSE_BLK2, 178, 10, ADC1 init code at atten3
|
||||||
|
ADC1_CAL_VOL_ATTEN0, EFUSE_BLK2, 188, 10, ADC1 calibration voltage at atten0
|
||||||
|
ADC1_CAL_VOL_ATTEN1, EFUSE_BLK2, 198, 10, ADC1 calibration voltage at atten1
|
||||||
|
ADC1_CAL_VOL_ATTEN2, EFUSE_BLK2, 208, 10, ADC1 calibration voltage at atten2
|
||||||
|
ADC1_CAL_VOL_ATTEN3, EFUSE_BLK2, 218, 10, ADC1 calibration voltage at atten3
|
||||||
|
|
||||||
|
################
|
||||||
|
USER_DATA, EFUSE_BLK3, 0, 256, User data
|
||||||
|
KEY0, EFUSE_BLK4, 0, 256, Key0 or user data
|
||||||
|
KEY1, EFUSE_BLK5, 0, 256, Key1 or user data
|
||||||
|
KEY2, EFUSE_BLK6, 0, 256, Key2 or user data
|
||||||
|
KEY3, EFUSE_BLK7, 0, 256, Key3 or user data
|
||||||
|
KEY4, EFUSE_BLK8, 0, 256, Key4 or user data
|
||||||
|
KEY5, EFUSE_BLK9, 0, 256, Key5 or user data
|
||||||
|
SYS_DATA_PART2, EFUSE_BLK10, 0, 256, System configuration
|
||||||
|
|
||||||
|
# AUTO CONFIG DIG&RTC DBIAS#
|
||||||
|
################
|
||||||
|
K_RTC_LDO, EFUSE_BLK1, 135, 7, BLOCK1 K_RTC_LDO
|
||||||
|
K_DIG_LDO, EFUSE_BLK1, 142, 7, BLOCK1 K_DIG_LDO
|
||||||
|
V_RTC_DBIAS20, EFUSE_BLK1, 149, 8, BLOCK1 voltage of rtc dbias20
|
||||||
|
V_DIG_DBIAS20, EFUSE_BLK1, 157, 8, BLOCK1 voltage of digital dbias20
|
||||||
|
DIG_DBIAS_HVT, EFUSE_BLK1, 165, 5, BLOCK1 digital dbias when hvt
|
||||||
|
THRES_HVT, EFUSE_BLK1, 170, 10, BLOCK1 pvt threshold when hvt
|
Can't render this file because it contains an unexpected character in line 7 and column 87.
|
141
components/efuse/esp32h2/esp_efuse_utility.c
Normal file
141
components/efuse/esp32h2/esp_efuse_utility.c
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "assert.h"
|
||||||
|
#include "esp_efuse_utility.h"
|
||||||
|
#include "soc/efuse_periph.h"
|
||||||
|
#include "esp32h2/clk.h"
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
|
||||||
|
static const char *TAG = "efuse";
|
||||||
|
|
||||||
|
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||||
|
extern uint32_t virt_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK];
|
||||||
|
#endif // CONFIG_EFUSE_VIRTUAL
|
||||||
|
|
||||||
|
/*Range addresses to read blocks*/
|
||||||
|
const esp_efuse_range_addr_t range_read_addr_blocks[] = {
|
||||||
|
{EFUSE_RD_WR_DIS_REG, EFUSE_RD_REPEAT_DATA4_REG}, // range address of EFUSE_BLK0 REPEAT
|
||||||
|
{EFUSE_RD_MAC_SPI_SYS_0_REG, EFUSE_RD_MAC_SPI_SYS_5_REG}, // range address of EFUSE_BLK1 MAC_SPI_8M
|
||||||
|
{EFUSE_RD_SYS_PART1_DATA0_REG, EFUSE_RD_SYS_PART1_DATA7_REG}, // range address of EFUSE_BLK2 SYS_DATA
|
||||||
|
{EFUSE_RD_USR_DATA0_REG, EFUSE_RD_USR_DATA7_REG}, // range address of EFUSE_BLK3 USR_DATA
|
||||||
|
{EFUSE_RD_KEY0_DATA0_REG, EFUSE_RD_KEY0_DATA7_REG}, // range address of EFUSE_BLK4 KEY0
|
||||||
|
{EFUSE_RD_KEY1_DATA0_REG, EFUSE_RD_KEY1_DATA7_REG}, // range address of EFUSE_BLK5 KEY1
|
||||||
|
{EFUSE_RD_KEY2_DATA0_REG, EFUSE_RD_KEY2_DATA7_REG}, // range address of EFUSE_BLK6 KEY2
|
||||||
|
{EFUSE_RD_KEY3_DATA0_REG, EFUSE_RD_KEY3_DATA7_REG}, // range address of EFUSE_BLK7 KEY3
|
||||||
|
{EFUSE_RD_KEY4_DATA0_REG, EFUSE_RD_KEY4_DATA7_REG}, // range address of EFUSE_BLK8 KEY4
|
||||||
|
{EFUSE_RD_KEY5_DATA0_REG, EFUSE_RD_KEY5_DATA7_REG}, // range address of EFUSE_BLK9 KEY5
|
||||||
|
{EFUSE_RD_SYS_PART2_DATA0_REG, EFUSE_RD_SYS_PART2_DATA7_REG} // range address of EFUSE_BLK10 KEY6
|
||||||
|
};
|
||||||
|
|
||||||
|
static uint32_t write_mass_blocks[EFUSE_BLK_MAX][COUNT_EFUSE_REG_PER_BLOCK] = { 0 };
|
||||||
|
|
||||||
|
/*Range addresses to write blocks (it is not real regs, it is buffer) */
|
||||||
|
const esp_efuse_range_addr_t range_write_addr_blocks[] = {
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK0][0], (uint32_t) &write_mass_blocks[EFUSE_BLK0][5]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK1][0], (uint32_t) &write_mass_blocks[EFUSE_BLK1][5]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK2][0], (uint32_t) &write_mass_blocks[EFUSE_BLK2][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK3][0], (uint32_t) &write_mass_blocks[EFUSE_BLK3][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK4][0], (uint32_t) &write_mass_blocks[EFUSE_BLK4][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK5][0], (uint32_t) &write_mass_blocks[EFUSE_BLK5][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK6][0], (uint32_t) &write_mass_blocks[EFUSE_BLK6][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK7][0], (uint32_t) &write_mass_blocks[EFUSE_BLK7][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK8][0], (uint32_t) &write_mass_blocks[EFUSE_BLK8][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK9][0], (uint32_t) &write_mass_blocks[EFUSE_BLK9][7]},
|
||||||
|
{(uint32_t) &write_mass_blocks[EFUSE_BLK10][0], (uint32_t) &write_mass_blocks[EFUSE_BLK10][7]},
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef CONFIG_EFUSE_VIRTUAL
|
||||||
|
// Update Efuse timing configuration
|
||||||
|
static esp_err_t esp_efuse_set_timing(void)
|
||||||
|
{
|
||||||
|
// efuse clock is fixed in ESP32-C3, so the ets_efuse_set_timing() function
|
||||||
|
// takes an argument for compatibility with older ROM functions but it's ignored.
|
||||||
|
int res = ets_efuse_set_timing(0);
|
||||||
|
assert(res == 0);
|
||||||
|
(void)res;
|
||||||
|
|
||||||
|
REG_SET_FIELD(EFUSE_WR_TIM_CONF2_REG, EFUSE_PWR_OFF_NUM, 0x60);
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif // ifndef CONFIG_EFUSE_VIRTUAL
|
||||||
|
|
||||||
|
// Efuse read operation: copies data from physical efuses to efuse read registers.
|
||||||
|
void esp_efuse_utility_clear_program_registers(void)
|
||||||
|
{
|
||||||
|
ets_efuse_read();
|
||||||
|
ets_efuse_clear_program_registers();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Burn values written to the efuse write registers
|
||||||
|
void esp_efuse_utility_burn_chip(void)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_EFUSE_VIRTUAL
|
||||||
|
ESP_LOGW(TAG, "Virtual efuses enabled: Not really burning eFuses");
|
||||||
|
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||||
|
int subblock = 0;
|
||||||
|
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||||
|
virt_blocks[num_block][subblock++] |= REG_READ(addr_wr_block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef CONFIG_EFUSE_VIRTUAL_KEEP_IN_FLASH
|
||||||
|
esp_efuse_utility_write_efuses_to_flash();
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
|
if (esp_efuse_set_timing() != ESP_OK) {
|
||||||
|
ESP_LOGE(TAG, "Efuse fields are not burnt");
|
||||||
|
} else {
|
||||||
|
// Permanently update values written to the efuse write registers
|
||||||
|
// It is necessary to process blocks in the order from MAX-> EFUSE_BLK0, because EFUSE_BLK0 has protection bits for other blocks.
|
||||||
|
for (int num_block = EFUSE_BLK_MAX - 1; num_block >= EFUSE_BLK0; num_block--) {
|
||||||
|
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||||
|
if (REG_READ(addr_wr_block) != 0) {
|
||||||
|
if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
|
||||||
|
uint8_t block_rs[12];
|
||||||
|
ets_efuse_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
|
||||||
|
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
|
||||||
|
}
|
||||||
|
int data_len = (range_write_addr_blocks[num_block].end - range_write_addr_blocks[num_block].start) + sizeof(uint32_t);
|
||||||
|
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)range_write_addr_blocks[num_block].start, data_len);
|
||||||
|
ets_efuse_program(num_block);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif // CONFIG_EFUSE_VIRTUAL
|
||||||
|
esp_efuse_utility_reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// After esp_efuse_write.. functions EFUSE_BLKx_WDATAx_REG were filled is not coded values.
|
||||||
|
// This function reads EFUSE_BLKx_WDATAx_REG registers, and checks possible to write these data with RS coding scheme.
|
||||||
|
// The RS coding scheme does not require data changes for the encoded data. esp32s2 has special registers for this.
|
||||||
|
// They will be filled during the burn operation.
|
||||||
|
esp_err_t esp_efuse_utility_apply_new_coding_scheme()
|
||||||
|
{
|
||||||
|
// start with EFUSE_BLK1. EFUSE_BLK0 - always uses EFUSE_CODING_SCHEME_NONE.
|
||||||
|
for (int num_block = EFUSE_BLK1; num_block < EFUSE_BLK_MAX; num_block++) {
|
||||||
|
if (esp_efuse_get_coding_scheme(num_block) == EFUSE_CODING_SCHEME_RS) {
|
||||||
|
for (uint32_t addr_wr_block = range_write_addr_blocks[num_block].start; addr_wr_block <= range_write_addr_blocks[num_block].end; addr_wr_block += 4) {
|
||||||
|
if (REG_READ(addr_wr_block)) {
|
||||||
|
int num_reg = 0;
|
||||||
|
for (uint32_t addr_rd_block = range_read_addr_blocks[num_block].start; addr_rd_block <= range_read_addr_blocks[num_block].end; addr_rd_block += 4, ++num_reg) {
|
||||||
|
if (esp_efuse_utility_read_reg(num_block, num_reg)) {
|
||||||
|
ESP_LOGE(TAG, "Bits are not empty. Write operation is forbidden.");
|
||||||
|
return ESP_ERR_CODING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
79
components/efuse/esp32h2/include/esp_efuse.h
Normal file
79
components/efuse/esp32h2/include/esp_efuse.h
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of eFuse blocks ESP32H2
|
||||||
|
*/
|
||||||
|
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_BLK_KEY_MAX = 10,
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Type of key purpose
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_USER = 0, /**< User purposes (software-only use) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_RESERVED = 1, /**< Reserved */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY = 4, /**< XTS_AES_128_KEY (flash/PSRAM encryption) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL = 5, /**< HMAC Downstream mode */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG = 6, /**< JTAG soft enable key (uses HMAC Downstream mode) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE = 7, /**< Digital Signature peripheral key (uses HMAC Downstream mode) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_HMAC_UP = 8, /**< HMAC Upstream mode */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0 = 9, /**< SECURE_BOOT_DIGEST0 (Secure Boot key digest) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1 = 10, /**< SECURE_BOOT_DIGEST1 (Secure Boot key digest) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 = 11, /**< SECURE_BOOT_DIGEST2 (Secure Boot key digest) */
|
||||||
|
ESP_EFUSE_KEY_PURPOSE_MAX, /**< MAX PURPOSE */
|
||||||
|
} esp_efuse_purpose_t;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
54
components/efuse/esp32h2/include/esp_efuse_rtc_calib.h
Normal file
54
components/efuse/esp32h2/include/esp_efuse_rtc_calib.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <esp_types.h>
|
||||||
|
#include <esp_err.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the RTC calibration efuse version
|
||||||
|
*
|
||||||
|
* @return Version of the stored efuse
|
||||||
|
*/
|
||||||
|
int esp_efuse_rtc_calib_get_ver(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the init code in the efuse, for the corresponding attenuation.
|
||||||
|
*
|
||||||
|
* @param version Version of the stored efuse
|
||||||
|
* @param atten Attenuation of the init code
|
||||||
|
* @return The init code stored in efuse
|
||||||
|
*/
|
||||||
|
uint16_t esp_efuse_rtc_calib_get_init_code(int version, int atten);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the calibration digits stored in the efuse, and the corresponding voltage.
|
||||||
|
*
|
||||||
|
* @param version Version of the stored efuse
|
||||||
|
* @param atten Attenuation to use
|
||||||
|
* @param out_digi Output buffer of the digits
|
||||||
|
* @param out_vol_mv Output of the voltage, in mV
|
||||||
|
* @return
|
||||||
|
* - ESP_ERR_INVALID_ARG: If efuse version or attenuation is invalid
|
||||||
|
* - ESP_OK: if success
|
||||||
|
*/
|
||||||
|
esp_err_t esp_efuse_rtc_calib_get_cal_voltage(int version, int atten, uint32_t* out_digi, uint32_t* out_vol_mv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get the temperature sensor calibration number delta_T stored in the efuse.
|
||||||
|
*
|
||||||
|
* @param version Version of the stored efuse
|
||||||
|
*
|
||||||
|
* @return The specification of temperature sensor calibration number in efuse.
|
||||||
|
*/
|
||||||
|
float esp_efuse_rtc_calib_get_cal_temp(int version);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
144
components/efuse/esp32h2/include/esp_efuse_table.h
Normal file
144
components/efuse/esp32h2/include/esp_efuse_table.h
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// md5_digest_table 9e42b2f9dd879191ca75ad0cf50841a1
|
||||||
|
// This file was generated from the file esp_efuse_table.csv. DO NOT CHANGE THIS FILE MANUALLY.
|
||||||
|
// If you want to change some fields, you need to change esp_efuse_table.csv file
|
||||||
|
// then run `efuse_common_table` or `efuse_custom_table` command it will generate this file.
|
||||||
|
// To show efuse_table run the command 'show_efuse_table'.
|
||||||
|
|
||||||
|
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_WR_DIS_RD_DIS[];
|
||||||
|
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_RD_DIS[];
|
||||||
|
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_USB_JTAG[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_ICACHE[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_USB_DEVICE[];
|
||||||
|
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_JTAG_SEL_ENABLE[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_SOFT_DIS_JTAG[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_PAD_JTAG[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_DIS_DOWNLOAD_MANUAL_ENCRYPT[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_USB_DREFH[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_USB_DREFL[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_USB_EXCHG_PINS[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_VDD_SPI_AS_GPIO[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_BTLC_GPIO_ENABLE[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_POWERGLITCH_EN[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_POWER_GLITCH_DSENSE[];
|
||||||
|
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_FLASH_ECC_MODE[];
|
||||||
|
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_FLASH_PAGE_SIZE[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_FLASH_ECC_EN[];
|
||||||
|
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_WAFER_VERSION[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_PKG_VERSION[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK1_VERSION[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_OPTIONAL_UNIQUE_ID[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_BLOCK2_VERSION[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_TEMP_CALIB[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_OCODE[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN0[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN1[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN2[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_INIT_CODE_ATTEN3[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN0[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN1[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN2[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_ADC1_CAL_VOL_ATTEN3[];
|
||||||
|
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[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_K_RTC_LDO[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_K_DIG_LDO[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_V_RTC_DBIAS20[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_V_DIG_DBIAS20[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_DIG_DBIAS_HVT[];
|
||||||
|
extern const esp_efuse_desc_t* ESP_EFUSE_THRES_HVT[];
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
21
components/efuse/esp32h2/private_include/esp_efuse_utility.h
Normal file
21
components/efuse/esp32h2/private_include/esp_efuse_utility.h
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#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
|
4
components/efuse/esp32h2/sources.cmake
Normal file
4
components/efuse/esp32h2/sources.cmake
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
set(EFUSE_SOC_SRCS "esp_efuse_table.c"
|
||||||
|
"esp_efuse_fields.c"
|
||||||
|
"esp_efuse_rtc_calib.c"
|
||||||
|
"esp_efuse_utility.c")
|
@@ -25,6 +25,8 @@ extern "C" {
|
|||||||
#include "esp32c3/rom/secure_boot.h"
|
#include "esp32c3/rom/secure_boot.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||||
#include "esp32s3/rom/secure_boot.h"
|
#include "esp32s3/rom/secure_boot.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/secure_boot.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */
|
#define ESP_ERR_EFUSE 0x1600 /*!< Base error code for efuse api. */
|
||||||
|
@@ -26,7 +26,7 @@ menu "ESP-TLS"
|
|||||||
|
|
||||||
config ESP_TLS_USE_DS_PERIPHERAL
|
config ESP_TLS_USE_DS_PERIPHERAL
|
||||||
bool "Use Digital Signature (DS) Peripheral with ESP-TLS"
|
bool "Use Digital Signature (DS) Peripheral with ESP-TLS"
|
||||||
depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2) && ESP_TLS_USING_MBEDTLS
|
depends on (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S2 || IDF_TARGET_ESP32H2) && ESP_TLS_USING_MBEDTLS
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral
|
Enable use of the Digital Signature Peripheral for ESP-TLS.The DS peripheral
|
||||||
|
66
components/esp32h2/CMakeLists.txt
Normal file
66
components/esp32h2/CMakeLists.txt
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
idf_build_get_property(target IDF_TARGET)
|
||||||
|
idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
|
||||||
|
if(NOT "${target}" STREQUAL "esp32h2")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(BOOTLOADER_BUILD)
|
||||||
|
# For bootloader, all we need from esp32h2 is headers
|
||||||
|
idf_component_register(INCLUDE_DIRS include REQUIRES riscv)
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32h2.peripherals.ld")
|
||||||
|
else()
|
||||||
|
# Regular app build
|
||||||
|
|
||||||
|
set(srcs "dport_access.c"
|
||||||
|
"esp_hmac.c"
|
||||||
|
"esp_ds.c"
|
||||||
|
"esp_crypto_lock.c"
|
||||||
|
"memprot.c")
|
||||||
|
set(include_dirs "include")
|
||||||
|
|
||||||
|
set(requires driver efuse soc riscv) #unfortunately rom/uart uses SOC registers directly
|
||||||
|
|
||||||
|
# driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
|
||||||
|
# app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
|
||||||
|
# esp_timer is added here because cpu_start.c uses esp_timer
|
||||||
|
set(priv_requires
|
||||||
|
app_trace app_update bootloader_support log mbedtls nvs_flash
|
||||||
|
pthread spi_flash vfs espcoredump esp_common esp_timer)
|
||||||
|
|
||||||
|
idf_component_register(SRCS "${srcs}"
|
||||||
|
INCLUDE_DIRS "${include_dirs}"
|
||||||
|
REQUIRES "${requires}"
|
||||||
|
PRIV_REQUIRES "${priv_requires}"
|
||||||
|
REQUIRED_IDF_TARGETS esp32h2)
|
||||||
|
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_BINARY_DIR}/esp32h2_out.ld")
|
||||||
|
|
||||||
|
# Process the template file through the linker script generation mechanism, and use the output for linking the
|
||||||
|
# final binary
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "${CMAKE_CURRENT_LIST_DIR}/ld/esp32h2.project.ld.in"
|
||||||
|
PROCESS "${CMAKE_CURRENT_BINARY_DIR}/ld/esp32h2.project.ld")
|
||||||
|
target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32h2.peripherals.ld")
|
||||||
|
|
||||||
|
target_link_libraries(${COMPONENT_LIB} PUBLIC gcc)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u call_user_start_cpu0")
|
||||||
|
|
||||||
|
idf_build_get_property(config_dir CONFIG_DIR)
|
||||||
|
# Preprocess esp32h2.ld linker script to include configuration, becomes esp32h2_out.ld
|
||||||
|
set(LD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ld)
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT esp32h2_out.ld
|
||||||
|
COMMAND "${CMAKE_C_COMPILER}" -C -P -x c -E -o esp32h2_out.ld -I ${config_dir} ${LD_DIR}/esp32h2.ld
|
||||||
|
MAIN_DEPENDENCY ${LD_DIR}/esp32h2.ld
|
||||||
|
DEPENDS ${sdkconfig_header}
|
||||||
|
COMMENT "Generating linker script..."
|
||||||
|
VERBATIM)
|
||||||
|
|
||||||
|
add_custom_target(esp32h2_linker_script DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/esp32h2_out.ld)
|
||||||
|
add_dependencies(${COMPONENT_LIB} esp32h2_linker_script)
|
||||||
|
|
||||||
|
# disable stack protection in files which are involved in initialization of that feature
|
||||||
|
set_source_files_properties(
|
||||||
|
cpu_start.c
|
||||||
|
PROPERTIES COMPILE_FLAGS
|
||||||
|
-fno-stack-protector)
|
||||||
|
endif()
|
205
components/esp32h2/Kconfig
Normal file
205
components/esp32h2/Kconfig
Normal file
@@ -0,0 +1,205 @@
|
|||||||
|
menu "ESP32H2-Specific"
|
||||||
|
visible if IDF_TARGET_ESP32H2
|
||||||
|
|
||||||
|
choice ESP32H2_DEFAULT_CPU_FREQ_MHZ
|
||||||
|
prompt "CPU frequency"
|
||||||
|
default ESP32H2_DEFAULT_CPU_FREQ_64 if IDF_ENV_FPGA
|
||||||
|
default ESP32H2_DEFAULT_CPU_FREQ_96 if !IDF_ENV_FPGA
|
||||||
|
help
|
||||||
|
CPU frequency to be set on application startup.
|
||||||
|
|
||||||
|
config ESP32H2_DEFAULT_CPU_FREQ_16
|
||||||
|
bool "16 MHz"
|
||||||
|
config ESP32H2_DEFAULT_CPU_FREQ_32
|
||||||
|
bool "32 MHz"
|
||||||
|
config ESP32H2_DEFAULT_CPU_FREQ_64
|
||||||
|
bool "64 MHz"
|
||||||
|
config ESP32H2_DEFAULT_CPU_FREQ_96
|
||||||
|
bool "96 MHz"
|
||||||
|
depends on !IDF_ENV_FPGA
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ESP32H2_DEFAULT_CPU_FREQ_MHZ
|
||||||
|
int
|
||||||
|
default 16 if ESP32H2_DEFAULT_CPU_FREQ_16
|
||||||
|
default 32 if ESP32H2_DEFAULT_CPU_FREQ_32
|
||||||
|
default 64 if ESP32H2_DEFAULT_CPU_FREQ_64
|
||||||
|
default 96 if ESP32H2_DEFAULT_CPU_FREQ_96
|
||||||
|
|
||||||
|
choice ESP32H2_REV_MIN
|
||||||
|
prompt "Minimum Supported ESP32-H2 Revision"
|
||||||
|
default ESP32H2_REV_MIN_0
|
||||||
|
help
|
||||||
|
Minimum revision that ESP-IDF would support.
|
||||||
|
|
||||||
|
Only supporting higher chip revisions can reduce binary size.
|
||||||
|
|
||||||
|
config ESP32H2_REV_MIN_0
|
||||||
|
bool "Rev 0"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ESP32H2_REV_MIN
|
||||||
|
int
|
||||||
|
default 0 if ESP32H2_REV_MIN_0
|
||||||
|
|
||||||
|
config ESP32H2_DEBUG_OCDAWARE
|
||||||
|
bool "Make exception and panic handlers JTAG/OCD aware"
|
||||||
|
default y
|
||||||
|
select FREERTOS_DEBUG_OCDAWARE
|
||||||
|
help
|
||||||
|
The FreeRTOS panic and unhandled exception handers can detect a JTAG OCD debugger and
|
||||||
|
instead of panicking, have the debugger stop on the offending instruction.
|
||||||
|
|
||||||
|
config ESP32H2_DEBUG_STUBS_ENABLE
|
||||||
|
bool "OpenOCD debug stubs"
|
||||||
|
default COMPILER_OPTIMIZATION_LEVEL_DEBUG
|
||||||
|
depends on !ESP32H2_TRAX
|
||||||
|
help
|
||||||
|
Debug stubs are used by OpenOCD to execute pre-compiled onboard code which does some useful debugging,
|
||||||
|
e.g. GCOV data dump.
|
||||||
|
|
||||||
|
config ESP32H2_BROWNOUT_DET
|
||||||
|
bool "Hardware brownout detect & reset"
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
The ESP32-C3 has a built-in brownout detector which can detect if the voltage is lower than
|
||||||
|
a specific value. If this happens, it will reset the chip in order to prevent unintended
|
||||||
|
behaviour.
|
||||||
|
|
||||||
|
choice ESP32H2_BROWNOUT_DET_LVL_SEL
|
||||||
|
prompt "Brownout voltage level"
|
||||||
|
depends on ESP32H2_BROWNOUT_DET
|
||||||
|
default ESP32H2_BROWNOUT_DET_LVL_SEL_7
|
||||||
|
help
|
||||||
|
The brownout detector will reset the chip when the supply voltage is approximately
|
||||||
|
below this level. Note that there may be some variation of brownout voltage level
|
||||||
|
between each chip.
|
||||||
|
|
||||||
|
#The voltage levels here are estimates, more work needs to be done to figure out the exact voltages
|
||||||
|
#of the brownout threshold levels.
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL_SEL_7
|
||||||
|
bool "2.51V"
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL_SEL_6
|
||||||
|
bool "2.64V"
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL_SEL_5
|
||||||
|
bool "2.76V"
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL_SEL_4
|
||||||
|
bool "2.92V"
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL_SEL_3
|
||||||
|
bool "3.10V"
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL_SEL_2
|
||||||
|
bool "3.27V"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ESP32H2_BROWNOUT_DET_LVL
|
||||||
|
int
|
||||||
|
default 2 if ESP32H2_BROWNOUT_DET_LVL_SEL_2
|
||||||
|
default 3 if ESP32H2_BROWNOUT_DET_LVL_SEL_3
|
||||||
|
default 4 if ESP32H2_BROWNOUT_DET_LVL_SEL_4
|
||||||
|
default 5 if ESP32H2_BROWNOUT_DET_LVL_SEL_5
|
||||||
|
default 6 if ESP32H2_BROWNOUT_DET_LVL_SEL_6
|
||||||
|
default 7 if ESP32H2_BROWNOUT_DET_LVL_SEL_7
|
||||||
|
|
||||||
|
choice ESP32H2_TIME_SYSCALL
|
||||||
|
prompt "Timers used for gettimeofday function"
|
||||||
|
default ESP32H2_TIME_SYSCALL_USE_RTC_SYSTIMER
|
||||||
|
help
|
||||||
|
This setting defines which hardware timers are used to
|
||||||
|
implement 'gettimeofday' and 'time' functions in C library.
|
||||||
|
|
||||||
|
- If both high-resolution (systimer) and RTC timers are used, timekeeping will
|
||||||
|
continue in deep sleep. Time will be reported at 1 microsecond
|
||||||
|
resolution. This is the default, and the recommended option.
|
||||||
|
- If only high-resolution timer (systimer) is used, gettimeofday will
|
||||||
|
provide time at microsecond resolution.
|
||||||
|
Time will not be preserved when going into deep sleep mode.
|
||||||
|
- If only RTC timer is used, timekeeping will continue in
|
||||||
|
deep sleep, but time will be measured at 6.(6) microsecond
|
||||||
|
resolution. Also the gettimeofday function itself may take
|
||||||
|
longer to run.
|
||||||
|
- If no timers are used, gettimeofday and time functions
|
||||||
|
return -1 and set errno to ENOSYS.
|
||||||
|
- When RTC is used for timekeeping, two RTC_STORE registers are
|
||||||
|
used to keep time in deep sleep mode.
|
||||||
|
|
||||||
|
config ESP32H2_TIME_SYSCALL_USE_RTC_SYSTIMER
|
||||||
|
bool "RTC and high-resolution timer"
|
||||||
|
select ESP_TIME_FUNCS_USE_RTC_TIMER
|
||||||
|
select ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||||
|
config ESP32H2_TIME_SYSCALL_USE_RTC
|
||||||
|
bool "RTC"
|
||||||
|
select ESP_TIME_FUNCS_USE_RTC_TIMER
|
||||||
|
config ESP32H2_TIME_SYSCALL_USE_SYSTIMER
|
||||||
|
bool "High-resolution timer"
|
||||||
|
select ESP_TIME_FUNCS_USE_ESP_TIMER
|
||||||
|
config ESP32H2_TIME_SYSCALL_USE_NONE
|
||||||
|
bool "None"
|
||||||
|
select ESP_TIME_FUNCS_USE_NONE
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
choice ESP32H2_RTC_CLK_SRC
|
||||||
|
prompt "RTC clock source"
|
||||||
|
default ESP32H2_RTC_CLK_SRC_INT_RC
|
||||||
|
help
|
||||||
|
Choose which clock is used as RTC clock source.
|
||||||
|
|
||||||
|
config ESP32H2_RTC_CLK_SRC_INT_RC
|
||||||
|
bool "Internal 150kHz RC oscillator"
|
||||||
|
config ESP32H2_RTC_CLK_SRC_EXT_CRYS
|
||||||
|
bool "External 32kHz crystal"
|
||||||
|
select ESP_SYSTEM_RTC_EXT_XTAL
|
||||||
|
config ESP32H2_RTC_CLK_SRC_EXT_OSC
|
||||||
|
bool "External 32kHz oscillator at 32K_XP pin"
|
||||||
|
config ESP32H2_RTC_CLK_SRC_INT_8MD256
|
||||||
|
bool "Internal 8MHz oscillator, divided by 256 (~32kHz)"
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ESP32H2_RTC_CLK_CAL_CYCLES
|
||||||
|
int "Number of cycles for RTC_SLOW_CLK calibration"
|
||||||
|
default 3000 if ESP32H2_RTC_CLK_SRC_EXT_CRYS || ESP32H2_RTC_CLK_SRC_EXT_OSC || ESP32H2_RTC_CLK_SRC_INT_8MD256
|
||||||
|
default 576 if ESP32H2_RTC_CLK_SRC_INT_RC
|
||||||
|
range 0 125000
|
||||||
|
help
|
||||||
|
When the startup code initializes RTC_SLOW_CLK, it can perform
|
||||||
|
calibration by comparing the RTC_SLOW_CLK frequency with main XTAL
|
||||||
|
frequency. This option sets the number of RTC_SLOW_CLK cycles measured
|
||||||
|
by the calibration routine. Higher numbers increase calibration
|
||||||
|
precision, which may be important for applications which spend a lot of
|
||||||
|
time in deep sleep. Lower numbers reduce startup time.
|
||||||
|
|
||||||
|
When this option is set to 0, clock calibration will not be performed at
|
||||||
|
startup, and approximate clock frequencies will be assumed:
|
||||||
|
|
||||||
|
- 150000 Hz if internal RC oscillator is used as clock source. For this use value 1024.
|
||||||
|
- 32768 Hz if the 32k crystal oscillator is used. For this use value 3000 or more.
|
||||||
|
In case more value will help improve the definition of the launch of the crystal.
|
||||||
|
If the crystal could not start, it will be switched to internal RC.
|
||||||
|
|
||||||
|
config ESP32H2_NO_BLOBS
|
||||||
|
bool "No Binary Blobs"
|
||||||
|
depends on !BT_ENABLED
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
If enabled, this disables the linking of binary libraries in the application build. Note
|
||||||
|
that after enabling this Wi-Fi/Bluetooth will not work.
|
||||||
|
|
||||||
|
config ESP32H2_LIGHTSLEEP_GPIO_RESET_WORKAROUND
|
||||||
|
bool "light sleep GPIO reset workaround"
|
||||||
|
default y
|
||||||
|
select PM_SLP_DISABLE_GPIO if FREERTOS_USE_TICKLESS_IDLE
|
||||||
|
help
|
||||||
|
ESP32H2 will reset at wake-up if GPIO is received a small electrostatic pulse during
|
||||||
|
light sleep, with specific condition
|
||||||
|
|
||||||
|
- GPIO needs to be configured as input-mode only
|
||||||
|
- The pin receives a small electrostatic pulse, and reset occurs when the pulse
|
||||||
|
voltage is higher than 6 V
|
||||||
|
|
||||||
|
For GPIO set to input mode only, it is not a good practice to leave it open/floating,
|
||||||
|
The hardware design needs to controlled it with determined supply or ground voltage
|
||||||
|
is necessary.
|
||||||
|
|
||||||
|
This option provides a software workaround for this issue. Configure to isolate all
|
||||||
|
GPIO pins in sleep state.
|
||||||
|
|
||||||
|
endmenu # ESP32H2-Specific
|
1
components/esp32h2/Makefile.projbuild
Normal file
1
components/esp32h2/Makefile.projbuild
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# ESP32-H2 is not supported in the GNU Make build system.
|
4
components/esp32h2/component.mk
Normal file
4
components/esp32h2/component.mk
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#
|
||||||
|
# Component Makefile
|
||||||
|
#
|
||||||
|
COMPONENT_CONFIG_ONLY := 1
|
25
components/esp32h2/dport_access.c
Normal file
25
components/esp32h2/dport_access.c
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// 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 <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "soc/dport_access.h"
|
||||||
|
|
||||||
|
// Read a sequence of DPORT registers to the buffer.
|
||||||
|
void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words)
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < num_words; ++i) {
|
||||||
|
buff_out[i] = DPORT_SEQUENCE_REG_READ(address + i * 4);
|
||||||
|
}
|
||||||
|
}
|
83
components/esp32h2/esp_crypto_lock.c
Normal file
83
components/esp32h2/esp_crypto_lock.c
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
// 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 <sys/lock.h>
|
||||||
|
|
||||||
|
#include "esp_crypto_lock.h"
|
||||||
|
|
||||||
|
/* Lock overview:
|
||||||
|
SHA: peripheral independent, but DMA is shared with AES
|
||||||
|
AES: peripheral independent, but DMA is shared with SHA
|
||||||
|
MPI/RSA: independent
|
||||||
|
HMAC: needs SHA
|
||||||
|
DS: needs HMAC (which needs SHA), AES and MPI
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Lock for DS peripheral */
|
||||||
|
static _lock_t s_crypto_ds_lock;
|
||||||
|
|
||||||
|
/* Lock for HMAC peripheral */
|
||||||
|
static _lock_t s_crypto_hmac_lock;
|
||||||
|
|
||||||
|
/* Lock for the MPI/RSA peripheral, also used by the DS peripheral */
|
||||||
|
static _lock_t s_crypto_mpi_lock;
|
||||||
|
|
||||||
|
/* Single lock for SHA and AES, sharing a reserved GDMA channel */
|
||||||
|
static _lock_t s_crypto_sha_aes_lock;
|
||||||
|
|
||||||
|
void esp_crypto_hmac_lock_acquire(void)
|
||||||
|
{
|
||||||
|
_lock_acquire(&s_crypto_hmac_lock);
|
||||||
|
esp_crypto_sha_aes_lock_acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_hmac_lock_release(void)
|
||||||
|
{
|
||||||
|
esp_crypto_sha_aes_lock_release();
|
||||||
|
_lock_release(&s_crypto_hmac_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_ds_lock_acquire(void)
|
||||||
|
{
|
||||||
|
_lock_acquire(&s_crypto_ds_lock);
|
||||||
|
esp_crypto_hmac_lock_acquire();
|
||||||
|
esp_crypto_mpi_lock_acquire();
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_ds_lock_release(void)
|
||||||
|
{
|
||||||
|
esp_crypto_mpi_lock_release();
|
||||||
|
esp_crypto_hmac_lock_release();
|
||||||
|
_lock_release(&s_crypto_ds_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_sha_aes_lock_acquire(void)
|
||||||
|
{
|
||||||
|
_lock_acquire(&s_crypto_sha_aes_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_sha_aes_lock_release(void)
|
||||||
|
{
|
||||||
|
_lock_release(&s_crypto_sha_aes_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_mpi_lock_acquire(void)
|
||||||
|
{
|
||||||
|
_lock_acquire(&s_crypto_mpi_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_crypto_mpi_lock_release(void)
|
||||||
|
{
|
||||||
|
_lock_release(&s_crypto_mpi_lock);
|
||||||
|
}
|
232
components/esp32h2/esp_ds.c
Normal file
232
components/esp32h2/esp_ds.c
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
// 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 <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/task.h"
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
|
#include "esp_crypto_lock.h"
|
||||||
|
#include "hal/ds_hal.h"
|
||||||
|
#include "hal/ds_ll.h"
|
||||||
|
#include "hal/hmac_hal.h"
|
||||||
|
#include "esp32h2/rom/digital_signature.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "esp_ds.h"
|
||||||
|
|
||||||
|
struct esp_ds_context {
|
||||||
|
const esp_ds_data_t *data;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The vtask delay \c esp_ds_sign() is using while waiting for completion of the signing operation.
|
||||||
|
*/
|
||||||
|
#define ESP_DS_SIGN_TASK_DELAY_MS 10
|
||||||
|
|
||||||
|
#define RSA_LEN_MAX 127
|
||||||
|
|
||||||
|
/*
|
||||||
|
* esp_digital_signature_length_t is used in esp_ds_data_t in contrast to ets_ds_data_t, where unsigned is used.
|
||||||
|
* Check esp_digital_signature_length_t's width here because it's converted to unsigned using raw casts.
|
||||||
|
*/
|
||||||
|
_Static_assert(sizeof(esp_digital_signature_length_t) == sizeof(unsigned),
|
||||||
|
"The size of esp_digital_signature_length_t and unsigned has to be the same");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* esp_ds_data_t is used in the encryption function but casted to ets_ds_data_t.
|
||||||
|
* Check esp_ds_data_t's width here because it's converted using raw casts.
|
||||||
|
*/
|
||||||
|
_Static_assert(sizeof(esp_ds_data_t) == sizeof(ets_ds_data_t),
|
||||||
|
"The size of esp_ds_data_t and ets_ds_data_t has to be the same");
|
||||||
|
|
||||||
|
static void ds_acquire_enable(void)
|
||||||
|
{
|
||||||
|
esp_crypto_ds_lock_acquire();
|
||||||
|
|
||||||
|
// We also enable SHA and HMAC here. SHA is used by HMAC, HMAC is used by DS.
|
||||||
|
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||||
|
periph_module_enable(PERIPH_SHA_MODULE);
|
||||||
|
periph_module_enable(PERIPH_DS_MODULE);
|
||||||
|
|
||||||
|
hmac_hal_start();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ds_disable_release(void)
|
||||||
|
{
|
||||||
|
ds_hal_finish();
|
||||||
|
|
||||||
|
periph_module_disable(PERIPH_DS_MODULE);
|
||||||
|
periph_module_disable(PERIPH_SHA_MODULE);
|
||||||
|
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||||
|
|
||||||
|
esp_crypto_ds_lock_release();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ds_sign(const void *message,
|
||||||
|
const esp_ds_data_t *data,
|
||||||
|
hmac_key_id_t key_id,
|
||||||
|
void *signature)
|
||||||
|
{
|
||||||
|
// Need to check signature here, otherwise the signature is only checked when the signing has finished and fails
|
||||||
|
// but the signing isn't uninitialized and the mutex is still locked.
|
||||||
|
if (!signature) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_ds_context_t *context;
|
||||||
|
esp_err_t result = esp_ds_start_sign(message, data, key_id, &context);
|
||||||
|
if (result != ESP_OK) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (esp_ds_is_busy())
|
||||||
|
vTaskDelay(ESP_DS_SIGN_TASK_DELAY_MS / portTICK_PERIOD_MS);
|
||||||
|
|
||||||
|
return esp_ds_finish_sign(signature, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ds_start_sign(const void *message,
|
||||||
|
const esp_ds_data_t *data,
|
||||||
|
hmac_key_id_t key_id,
|
||||||
|
esp_ds_context_t **esp_ds_ctx)
|
||||||
|
{
|
||||||
|
if (!message || !data || !esp_ds_ctx) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (key_id >= HMAC_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(data->rsa_length == ESP_DS_RSA_1024
|
||||||
|
|| data->rsa_length == ESP_DS_RSA_2048
|
||||||
|
|| data->rsa_length == ESP_DS_RSA_3072)) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
ds_acquire_enable();
|
||||||
|
|
||||||
|
// initiate hmac
|
||||||
|
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_DS, key_id);
|
||||||
|
if (conf_error) {
|
||||||
|
ds_disable_release();
|
||||||
|
return ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
ds_hal_start();
|
||||||
|
|
||||||
|
// check encryption key from HMAC
|
||||||
|
int64_t start_time = esp_timer_get_time();
|
||||||
|
while (ds_ll_busy() != 0) {
|
||||||
|
if ((esp_timer_get_time() - start_time) > SOC_DS_KEY_CHECK_MAX_WAIT_US) {
|
||||||
|
ds_disable_release();
|
||||||
|
return ESP32H2_ERR_HW_CRYPTO_DS_INVALID_KEY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_ds_context_t *context = malloc(sizeof(esp_ds_context_t));
|
||||||
|
if (!context) {
|
||||||
|
ds_disable_release();
|
||||||
|
return ESP_ERR_NO_MEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t rsa_len = (data->rsa_length + 1) * 4;
|
||||||
|
ds_hal_write_private_key_params(data->c);
|
||||||
|
ds_hal_configure_iv(data->iv);
|
||||||
|
ds_hal_write_message(message, rsa_len);
|
||||||
|
|
||||||
|
// initiate signing
|
||||||
|
ds_hal_start_sign();
|
||||||
|
|
||||||
|
context->data = data;
|
||||||
|
*esp_ds_ctx = context;
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_ds_is_busy(void)
|
||||||
|
{
|
||||||
|
return ds_hal_busy();
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx)
|
||||||
|
{
|
||||||
|
if (!signature || !esp_ds_ctx) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
const esp_ds_data_t *data = esp_ds_ctx->data;
|
||||||
|
unsigned rsa_len = (data->rsa_length + 1) * 4;
|
||||||
|
|
||||||
|
while (ds_hal_busy()) { }
|
||||||
|
|
||||||
|
ds_signature_check_t sig_check_result = ds_hal_read_result((uint8_t*) signature, (size_t) rsa_len);
|
||||||
|
|
||||||
|
esp_err_t return_value = ESP_OK;
|
||||||
|
|
||||||
|
if (sig_check_result == DS_SIGNATURE_MD_FAIL || sig_check_result == DS_SIGNATURE_PADDING_AND_MD_FAIL) {
|
||||||
|
return_value = ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sig_check_result == DS_SIGNATURE_PADDING_FAIL) {
|
||||||
|
return_value = ESP32H2_ERR_HW_CRYPTO_DS_INVALID_PADDING;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(esp_ds_ctx);
|
||||||
|
|
||||||
|
hmac_hal_clean();
|
||||||
|
|
||||||
|
ds_disable_release();
|
||||||
|
|
||||||
|
return return_value;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||||
|
const void *iv,
|
||||||
|
const esp_ds_p_data_t *p_data,
|
||||||
|
const void *key)
|
||||||
|
{
|
||||||
|
if (!p_data) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t result = ESP_OK;
|
||||||
|
|
||||||
|
esp_crypto_ds_lock_acquire();
|
||||||
|
periph_module_enable(PERIPH_AES_MODULE);
|
||||||
|
periph_module_enable(PERIPH_DS_MODULE);
|
||||||
|
periph_module_enable(PERIPH_SHA_MODULE);
|
||||||
|
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||||
|
periph_module_enable(PERIPH_RSA_MODULE);
|
||||||
|
|
||||||
|
ets_ds_data_t *ds_data = (ets_ds_data_t*) data;
|
||||||
|
const ets_ds_p_data_t *ds_plain_data = (const ets_ds_p_data_t*) p_data;
|
||||||
|
|
||||||
|
ets_ds_result_t ets_result = ets_ds_encrypt_params(ds_data, iv, ds_plain_data, key, ETS_DS_KEY_HMAC);
|
||||||
|
|
||||||
|
if (ets_result == ETS_DS_INVALID_PARAM) {
|
||||||
|
result = ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
periph_module_disable(PERIPH_RSA_MODULE);
|
||||||
|
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||||
|
periph_module_disable(PERIPH_SHA_MODULE);
|
||||||
|
periph_module_disable(PERIPH_DS_MODULE);
|
||||||
|
periph_module_disable(PERIPH_AES_MODULE);
|
||||||
|
esp_crypto_ds_lock_release();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
132
components/esp32h2/esp_hmac.c
Normal file
132
components/esp32h2/esp_hmac.c
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
// 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 <string.h>
|
||||||
|
#include "driver/periph_ctrl.h"
|
||||||
|
#include "esp32h2/rom/hmac.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp_hmac.h"
|
||||||
|
#include "esp_crypto_lock.h"
|
||||||
|
|
||||||
|
#include "hal/hmac_hal.h"
|
||||||
|
|
||||||
|
#define SHA256_BLOCK_SZ 64
|
||||||
|
#define SHA256_PAD_SZ 8
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Apply the HMAC padding without the embedded length.
|
||||||
|
*
|
||||||
|
* @note This function does not check the data length, it is the responsibility of the other functions in this
|
||||||
|
* module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
|
||||||
|
* Otherwise, this function has undefined behavior.
|
||||||
|
* Note however, that for the actual HMAC implementation on ESP32H2, the length also needs to be applied at the end
|
||||||
|
* of the block. This function alone deosn't do that.
|
||||||
|
*/
|
||||||
|
static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
|
||||||
|
{
|
||||||
|
memcpy(block, data, data_len);
|
||||||
|
// Apply a one bit, followed by zero bits (refer to the ESP32H2 TRM).
|
||||||
|
block[data_len] = 0x80;
|
||||||
|
bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
|
||||||
|
const void *message,
|
||||||
|
size_t message_len,
|
||||||
|
uint8_t *hmac)
|
||||||
|
{
|
||||||
|
const uint8_t *message_bytes = (const uint8_t *)message;
|
||||||
|
|
||||||
|
if (!message || !hmac) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
if (key_id >= HMAC_KEY_MAX) {
|
||||||
|
return ESP_ERR_INVALID_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_crypto_hmac_lock_acquire();
|
||||||
|
|
||||||
|
// We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
|
||||||
|
periph_module_enable(PERIPH_HMAC_MODULE);
|
||||||
|
periph_module_enable(PERIPH_SHA_MODULE);
|
||||||
|
periph_module_enable(PERIPH_DS_MODULE);
|
||||||
|
|
||||||
|
hmac_hal_start();
|
||||||
|
|
||||||
|
uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
|
||||||
|
if (conf_error) {
|
||||||
|
esp_crypto_hmac_lock_release();
|
||||||
|
return ESP_FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
|
||||||
|
// If message including padding is only one block...
|
||||||
|
// Last message block, so apply SHA-256 padding rules in software
|
||||||
|
uint8_t block[SHA256_BLOCK_SZ];
|
||||||
|
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
|
||||||
|
|
||||||
|
write_and_padd(block, message_bytes, message_len);
|
||||||
|
// Final block: append the bit length in this block and signal padding to peripheral
|
||||||
|
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
|
||||||
|
&bit_len, sizeof(bit_len));
|
||||||
|
hmac_hal_write_one_block_512(block);
|
||||||
|
} else {
|
||||||
|
// If message including padding is needs more than one block
|
||||||
|
|
||||||
|
// write all blocks without padding except the last one
|
||||||
|
size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
|
||||||
|
for (int i = 1; i < remaining_blocks; i++) {
|
||||||
|
hmac_hal_write_block_512(message_bytes);
|
||||||
|
message_bytes += SHA256_BLOCK_SZ;
|
||||||
|
hmac_hal_next_block_normal();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If message fits into one block but without padding, we must not write another block.
|
||||||
|
if (remaining_blocks) {
|
||||||
|
hmac_hal_write_block_512(message_bytes);
|
||||||
|
message_bytes += SHA256_BLOCK_SZ;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t remaining = message_len % SHA256_BLOCK_SZ;
|
||||||
|
// Last message block, so apply SHA-256 padding rules in software
|
||||||
|
uint8_t block[SHA256_BLOCK_SZ];
|
||||||
|
uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
|
||||||
|
|
||||||
|
// If the remaining message and appended padding doesn't fit into a single block, we have to write an
|
||||||
|
// extra block with the rest of the message and potential padding first.
|
||||||
|
if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
|
||||||
|
write_and_padd(block, message_bytes, remaining);
|
||||||
|
hmac_hal_next_block_normal();
|
||||||
|
hmac_hal_write_block_512(block);
|
||||||
|
bzero(block, SHA256_BLOCK_SZ);
|
||||||
|
} else {
|
||||||
|
write_and_padd(block, message_bytes, remaining);
|
||||||
|
}
|
||||||
|
memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
|
||||||
|
&bit_len, sizeof(bit_len));
|
||||||
|
hmac_hal_next_block_padding();
|
||||||
|
hmac_hal_write_block_512(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read back result (bit swapped)
|
||||||
|
hmac_hal_read_result_256(hmac);
|
||||||
|
|
||||||
|
periph_module_disable(PERIPH_DS_MODULE);
|
||||||
|
periph_module_disable(PERIPH_SHA_MODULE);
|
||||||
|
periph_module_disable(PERIPH_HMAC_MODULE);
|
||||||
|
|
||||||
|
esp_crypto_hmac_lock_release();
|
||||||
|
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
42
components/esp32h2/include/esp32h2/dport_access.h
Normal file
42
components/esp32h2/include/esp32h2/dport_access.h
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef _ESP_DPORT_ACCESS_H_
|
||||||
|
#define _ESP_DPORT_ACCESS_H_
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Read a sequence of DPORT registers to the buffer.
|
||||||
|
*
|
||||||
|
* @param[out] buff_out Contains the read data.
|
||||||
|
* @param[in] address Initial address for reading registers.
|
||||||
|
* @param[in] num_words The number of words.
|
||||||
|
*/
|
||||||
|
void esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words);
|
||||||
|
|
||||||
|
#define DPORT_STALL_OTHER_CPU_START()
|
||||||
|
#define DPORT_STALL_OTHER_CPU_END()
|
||||||
|
#define DPORT_INTERRUPT_DISABLE()
|
||||||
|
#define DPORT_INTERRUPT_RESTORE()
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _ESP_DPORT_ACCESS_H_ */
|
455
components/esp32h2/include/esp32h2/memprot.h
Normal file
455
components/esp32h2/include/esp32h2/memprot.h
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
|
||||||
|
/* INTERNAL API
|
||||||
|
* generic interface to PMS memory protection features
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp_attr.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef IRAM_SRAM_START
|
||||||
|
#define IRAM_SRAM_START 0x4037C000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef DRAM_SRAM_START
|
||||||
|
#define DRAM_SRAM_START 0x3FC7C000
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAP_DRAM_TO_IRAM
|
||||||
|
#define MAP_DRAM_TO_IRAM(addr) (addr - DRAM_SRAM_START + IRAM_SRAM_START)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef MAP_IRAM_TO_DRAM
|
||||||
|
#define MAP_IRAM_TO_DRAM(addr) (addr - IRAM_SRAM_START + DRAM_SRAM_START)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MEMPROT_NONE = 0x00000000,
|
||||||
|
MEMPROT_IRAM0_SRAM = 0x00000001,
|
||||||
|
MEMPROT_DRAM0_SRAM = 0x00000002,
|
||||||
|
MEMPROT_ALL = 0xFFFFFFFF
|
||||||
|
} mem_type_prot_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MEMPROT_SPLITLINE_NONE = 0,
|
||||||
|
MEMPROT_IRAM0_DRAM0_SPLITLINE,
|
||||||
|
MEMPROT_IRAM0_LINE_0_SPLITLINE,
|
||||||
|
MEMPROT_IRAM0_LINE_1_SPLITLINE,
|
||||||
|
MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE,
|
||||||
|
MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE
|
||||||
|
} split_line_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
MEMPROT_PMS_AREA_NONE = 0,
|
||||||
|
MEMPROT_IRAM0_PMS_AREA_0,
|
||||||
|
MEMPROT_IRAM0_PMS_AREA_1,
|
||||||
|
MEMPROT_IRAM0_PMS_AREA_2,
|
||||||
|
MEMPROT_IRAM0_PMS_AREA_3,
|
||||||
|
MEMPROT_DRAM0_PMS_AREA_0,
|
||||||
|
MEMPROT_DRAM0_PMS_AREA_1,
|
||||||
|
MEMPROT_DRAM0_PMS_AREA_2,
|
||||||
|
MEMPROT_DRAM0_PMS_AREA_3
|
||||||
|
} pms_area_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MEMPROT_PMS_WORLD_0 = 0,
|
||||||
|
MEMPROT_PMS_WORLD_1,
|
||||||
|
MEMPROT_PMS_WORLD_2,
|
||||||
|
MEMPROT_PMS_WORLD_INVALID = 0xFFFFFFFF
|
||||||
|
} pms_world_t;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
MEMPROT_PMS_OP_READ = 0,
|
||||||
|
MEMPROT_PMS_OP_WRITE,
|
||||||
|
MEMPROT_PMS_OP_FETCH,
|
||||||
|
MEMPROT_PMS_OP_INVALID = 0xFFFFFFFF
|
||||||
|
} pms_operation_type_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts Memory protection type to string
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*/
|
||||||
|
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts Split line type to string
|
||||||
|
*
|
||||||
|
* @param line_type Split line type (see split_line_t enum)
|
||||||
|
*/
|
||||||
|
const char *esp_memprot_split_line_to_str(split_line_t line_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Converts PMS Area type to string
|
||||||
|
*
|
||||||
|
* @param area_type PMS Area type (see pms_area_t enum)
|
||||||
|
*/
|
||||||
|
const char *esp_memprot_pms_to_str(pms_area_t area_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns PMS splitting address for given Split line type
|
||||||
|
*
|
||||||
|
* The value is taken from PMS configuration registers (IRam0 range)
|
||||||
|
* For details on split lines see 'esp_memprot_set_prot_int' function description
|
||||||
|
*
|
||||||
|
* @param line_type Split line type (see split_line_t enum)
|
||||||
|
*
|
||||||
|
* @return appropriate split line address
|
||||||
|
*/
|
||||||
|
uint32_t *esp_memprot_get_split_addr(split_line_t line_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns default main IRAM/DRAM splitting address
|
||||||
|
*
|
||||||
|
* The address value is given by _iram_text_end global (IRam0 range)
|
||||||
|
|
||||||
|
* @return Main I/D split line (IRam0_DRam0_Split_Addr)
|
||||||
|
*/
|
||||||
|
void *esp_memprot_get_default_main_split_addr(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a lock for the main IRAM/DRAM splitting address
|
||||||
|
*
|
||||||
|
* Locks can be unlocked only by digital system reset
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_split_line_lock(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a lock status for the main IRAM/DRAM splitting address
|
||||||
|
*
|
||||||
|
* @return true/false (locked/unlocked)
|
||||||
|
*/
|
||||||
|
bool esp_memprot_get_split_line_lock(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets required split line address
|
||||||
|
*
|
||||||
|
* @param line_type Split line type (see split_line_t enum)
|
||||||
|
* @param line_addr target address from a memory range relevant to given line_type (IRAM/DRAM)
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a lock for PMS Area settings of required Memory type
|
||||||
|
*
|
||||||
|
* Locks can be unlocked only by digital system reset
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a lock status for PMS Area settings of required Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return true/false (locked/unlocked)
|
||||||
|
*/
|
||||||
|
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
|
||||||
|
*
|
||||||
|
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
|
||||||
|
* @param r Read permission flag
|
||||||
|
* @param w Write permission flag
|
||||||
|
* @param x Execute permission flag
|
||||||
|
*/
|
||||||
|
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets current permissions for given PMS Area in IRam0 memory range (MEMPROT_IRAM0_SRAM)
|
||||||
|
*
|
||||||
|
* @param area_type IRam0 PMS Area type (see pms_area_t enum)
|
||||||
|
* @param r Read permission flag holder
|
||||||
|
* @param w Write permission flag holder
|
||||||
|
* @param x Execute permission flag holder
|
||||||
|
*/
|
||||||
|
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
|
||||||
|
*
|
||||||
|
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
|
||||||
|
* @param r Read permission flag
|
||||||
|
* @param w Write permission flag
|
||||||
|
*/
|
||||||
|
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets current permissions for given PMS Area in DRam0 memory range (MEMPROT_DRAM0_SRAM)
|
||||||
|
*
|
||||||
|
* @param area_type DRam0 PMS Area type (see pms_area_t enum)
|
||||||
|
* @param r Read permission flag holder
|
||||||
|
* @param w Write permission flag holder
|
||||||
|
*/
|
||||||
|
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets a lock for PMS interrupt monitor settings of required Memory type
|
||||||
|
*
|
||||||
|
* Locks can be unlocked only by digital system reset
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets a lock status for PMS interrupt monitor settings of required Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return true/false (locked/unlocked)
|
||||||
|
*/
|
||||||
|
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Enable PMS violation interrupt monitoring of required Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
* @param enable/disable
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets enable/disable status for PMS interrupt monitor settings of required Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return true/false (enabled/disabled)
|
||||||
|
*/
|
||||||
|
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets CPU ID for currently active PMS violation interrupt
|
||||||
|
*
|
||||||
|
* @return CPU ID (CPU_PRO for ESP32H2)
|
||||||
|
*/
|
||||||
|
int IRAM_ATTR esp_memprot_intr_get_cpuid(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Clears current interrupt ON flag for given Memory type
|
||||||
|
*
|
||||||
|
* Interrupt clearing happens in two steps:
|
||||||
|
* 1. Interrupt CLR flag is set (to clear the interrupt ON status)
|
||||||
|
* 2. Interrupt CLR flag is reset (to allow further monitoring)
|
||||||
|
* This operation is non-atomic by PMS module design
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*/
|
||||||
|
void IRAM_ATTR esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns active PMS violation interrupt (if any)
|
||||||
|
*
|
||||||
|
* This function iterates through supported Memory type status registers
|
||||||
|
* and returns the first interrupt-on flag. If none is found active,
|
||||||
|
* MEMPROT_NONE is returned.
|
||||||
|
* Order of checking (in current version):
|
||||||
|
* 1. MEMPROT_IRAM0_SRAM
|
||||||
|
* 2. MEMPROT_DRAM0_SRAM
|
||||||
|
*
|
||||||
|
* @return mem_type Memory protection type related to active interrupt found (see mem_type_prot_t enum)
|
||||||
|
*/
|
||||||
|
mem_type_prot_t IRAM_ATTR esp_memprot_get_active_intr_memtype(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether any violation interrupt is active
|
||||||
|
*
|
||||||
|
* @return true/false (yes/no)
|
||||||
|
*/
|
||||||
|
bool IRAM_ATTR esp_memprot_is_locked_any(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether any violation interrupt is enabled
|
||||||
|
*
|
||||||
|
* @return true/false (yes/no)
|
||||||
|
*/
|
||||||
|
bool IRAM_ATTR esp_memprot_is_intr_ena_any(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Checks whether any violation interrupt is enabled
|
||||||
|
*
|
||||||
|
* @return true/false (yes/no)
|
||||||
|
*/
|
||||||
|
bool IRAM_ATTR esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the address which caused the violation interrupt (if any)
|
||||||
|
*
|
||||||
|
* The address is taken from appropriate PMS violation status register, based given Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return faulting address
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR esp_memprot_get_violate_addr(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the World identifier of the code causing the violation interrupt (if any)
|
||||||
|
*
|
||||||
|
* The value is taken from appropriate PMS violation status register, based given Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return World identifier (see pms_world_t enum)
|
||||||
|
*/
|
||||||
|
pms_world_t IRAM_ATTR esp_memprot_get_violate_world(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns Read or Write operation type which caused the violation interrupt (if any)
|
||||||
|
*
|
||||||
|
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return PMS operation type relevant to mem_type parameter (se pms_operation_type_t)
|
||||||
|
*/
|
||||||
|
pms_operation_type_t IRAM_ATTR esp_memprot_get_violate_wr(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns LoadStore flag of the operation type which caused the violation interrupt (if any)
|
||||||
|
*
|
||||||
|
* The value (bit) is taken from appropriate PMS violation status register, based given Memory type
|
||||||
|
* Effective only on IRam0 access
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return true/false (LoadStore bit on/off)
|
||||||
|
*/
|
||||||
|
bool IRAM_ATTR esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns byte-enables for the address which caused the violation interrupt (if any)
|
||||||
|
*
|
||||||
|
* The value is taken from appropriate PMS violation status register, based given Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return byte-enables
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns raw contents of DRam0 status register 1
|
||||||
|
*
|
||||||
|
* @return 32-bit register value
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_1(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns raw contents of DRam0 status register 2
|
||||||
|
*
|
||||||
|
* @return 32-bit register value
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR esp_memprot_get_dram_status_reg_2(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns raw contents of IRam0 status register
|
||||||
|
*
|
||||||
|
* @return 32-bit register value
|
||||||
|
*/
|
||||||
|
uint32_t IRAM_ATTR esp_memprot_get_iram_status_reg(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Register PMS violation interrupt in global interrupt matrix for given Memory type
|
||||||
|
*
|
||||||
|
* Memory protection components uses specific interrupt number, see ETS_MEMPROT_ERR_INUM
|
||||||
|
* The registration makes the panic-handler routine being called when the interrupt appears
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convenient routine for setting the PMS defaults
|
||||||
|
*
|
||||||
|
* Called on application startup, depending on CONFIG_ESP_SYSTEM_MEMPROT_FEATURE Kconfig settings
|
||||||
|
* For implementation details see 'esp_memprot_set_prot_int' description
|
||||||
|
*
|
||||||
|
* @param invoke_panic_handler register all interrupts for panic handling (true/false)
|
||||||
|
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
|
||||||
|
* @param mem_type_mask 32-bit field of specific PMS parts to configure (see 'esp_memprot_set_prot_int')
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Internal routine for setting the PMS defaults
|
||||||
|
*
|
||||||
|
* Called on application startup from within 'esp_memprot_set_prot'. Allows setting a specific splitting address
|
||||||
|
* (main I/D split line) - see the parameter 'split_addr'. If the 'split_addr' equals to NULL, default I/D split line
|
||||||
|
* is used (&_iram_text_end) and all the remaining lines share the same address.
|
||||||
|
* The function sets all the split lines and PMS areas to the same space,
|
||||||
|
* ie there is a single instruction space and single data space at the end.
|
||||||
|
* The PMS split lines and permission areas scheme described below:
|
||||||
|
*
|
||||||
|
* DRam0/DMA IRam0
|
||||||
|
* -----------------------------------------------
|
||||||
|
* ... | IRam0_PMS_0 |
|
||||||
|
* DRam0_PMS_0 ----------------------------------------------- IRam0_line1_Split_addr
|
||||||
|
* ... | IRam0_PMS_1 |
|
||||||
|
* ... ----------------------------------------------- IRam0_line0_Split_addr
|
||||||
|
* | IRam0_PMS_2 |
|
||||||
|
* =============================================== IRam0_DRam0_Split_addr (main I/D)
|
||||||
|
* | DRam0_PMS_1 |
|
||||||
|
* DRam0_DMA_line0_Split_addr ----------------------------------------------- ...
|
||||||
|
* | DRam0_PMS_2 | ...
|
||||||
|
* DRam0_DMA_line1_Split_addr ----------------------------------------------- IRam0_PMS_3
|
||||||
|
* | DRam0_PMS_3 | ...
|
||||||
|
* -----------------------------------------------
|
||||||
|
*
|
||||||
|
* Default settings provided by 'esp_memprot_set_prot_int' are as follows:
|
||||||
|
*
|
||||||
|
* DRam0/DMA IRam0
|
||||||
|
* -----------------------------------------------
|
||||||
|
* | IRam0_PMS_0 = IRam0_PMS_1 = IRam0_PMS_2 |
|
||||||
|
* | DRam0_PMS_0 | IRam0_line1_Split_addr
|
||||||
|
* DRam0_DMA_line0_Split_addr | | =
|
||||||
|
* = =============================================== IRam0_line0_Split_addr
|
||||||
|
* DRam0_DMA_line1_Split_addr | | =
|
||||||
|
* | DRam0_PMS_1 = DRam0_PMS_2 = DRam0_PMS_3 | IRam0_DRam0_Split_addr (main I/D)
|
||||||
|
* | IRam0_PMS_3 |
|
||||||
|
* -----------------------------------------------
|
||||||
|
*
|
||||||
|
* Once the memprot feature is locked, it can be unlocked only by digital system reset
|
||||||
|
*
|
||||||
|
* @param invoke_panic_handler register all the violation interrupts for panic handling (true/false)
|
||||||
|
* @param lock_feature lock the defaults to prevent further PMS settings changes (true/false)
|
||||||
|
* @param split_addr specific main I/D adrees or NULL to use default ($_iram_text_end)
|
||||||
|
* @param mem_type_mask 32-bit field of specific PMS parts to configure (members of mem_type_prot_t)
|
||||||
|
*/
|
||||||
|
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns raw contents of PMS interrupt monitor register for given Memory type
|
||||||
|
*
|
||||||
|
* @param mem_type Memory protection type (see mem_type_prot_t enum)
|
||||||
|
*
|
||||||
|
* @return 32-bit register value
|
||||||
|
*/
|
||||||
|
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
40
components/esp32h2/include/esp32h2/rtc.h
Normal file
40
components/esp32h2/include/esp32h2/rtc.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file esp32h2/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
|
76
components/esp32h2/include/esp_crypto_lock.h
Normal file
76
components/esp32h2/include/esp_crypto_lock.h
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire lock for HMAC cryptography peripheral
|
||||||
|
*
|
||||||
|
* Internally also locks the SHA peripheral, as the HMAC depends on the SHA peripheral
|
||||||
|
*/
|
||||||
|
void esp_crypto_hmac_lock_acquire(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release lock for HMAC cryptography peripheral
|
||||||
|
*
|
||||||
|
* Internally also releases the SHA peripheral, as the HMAC depends on the SHA peripheral
|
||||||
|
*/
|
||||||
|
void esp_crypto_hmac_lock_release(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire lock for DS cryptography peripheral
|
||||||
|
*
|
||||||
|
* Internally also locks the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals
|
||||||
|
*/
|
||||||
|
void esp_crypto_ds_lock_acquire(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release lock for DS cryptography peripheral
|
||||||
|
*
|
||||||
|
* Internally also releases the HMAC (which locks SHA), AES and MPI peripheral, as the DS depends on these peripherals
|
||||||
|
*/
|
||||||
|
void esp_crypto_ds_lock_release(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire lock for the SHA and AES cryptography peripheral.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_crypto_sha_aes_lock_acquire(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release lock for the SHA and AES cryptography peripheral.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_crypto_sha_aes_lock_release(void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Acquire lock for the mpi cryptography peripheral.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_crypto_mpi_lock_acquire(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Release lock for the mpi/rsa cryptography peripheral.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void esp_crypto_mpi_lock_release(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
218
components/esp32h2/include/esp_ds.h
Normal file
218
components/esp32h2/include/esp_ds.h
Normal file
@@ -0,0 +1,218 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
#include "esp_hmac.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL ESP_ERR_HW_CRYPTO_BASE + 0x1 /*!< HMAC peripheral problem */
|
||||||
|
#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_KEY ESP_ERR_HW_CRYPTO_BASE + 0x2 /*!< given HMAC key isn't correct,
|
||||||
|
HMAC peripheral problem */
|
||||||
|
#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST ESP_ERR_HW_CRYPTO_BASE + 0x4 /*!< message digest check failed,
|
||||||
|
result is invalid */
|
||||||
|
#define ESP32H2_ERR_HW_CRYPTO_DS_INVALID_PADDING ESP_ERR_HW_CRYPTO_BASE + 0x5 /*!< padding check failed, but result
|
||||||
|
is produced anyway and can be read*/
|
||||||
|
|
||||||
|
#define ESP_DS_IV_BIT_LEN 128
|
||||||
|
#define ESP_DS_IV_LEN (ESP_DS_IV_BIT_LEN / 8)
|
||||||
|
#define ESP_DS_SIGNATURE_MAX_BIT_LEN 3072
|
||||||
|
#define ESP_DS_SIGNATURE_MD_BIT_LEN 256
|
||||||
|
#define ESP_DS_SIGNATURE_M_PRIME_BIT_LEN 32
|
||||||
|
#define ESP_DS_SIGNATURE_L_BIT_LEN 32
|
||||||
|
#define ESP_DS_SIGNATURE_PADDING_BIT_LEN 64
|
||||||
|
|
||||||
|
/* Length of parameter 'C' stored in flash, in bytes
|
||||||
|
- Operands Y, M and r_bar; each 3072 bits
|
||||||
|
- Operand MD (message digest); 256 bits
|
||||||
|
- Operands M' and L; each 32 bits
|
||||||
|
- Operand beta (padding value; 64 bits
|
||||||
|
*/
|
||||||
|
#define ESP_DS_C_LEN (((ESP_DS_SIGNATURE_MAX_BIT_LEN * 3 \
|
||||||
|
+ ESP_DS_SIGNATURE_MD_BIT_LEN \
|
||||||
|
+ ESP_DS_SIGNATURE_M_PRIME_BIT_LEN \
|
||||||
|
+ ESP_DS_SIGNATURE_L_BIT_LEN \
|
||||||
|
+ ESP_DS_SIGNATURE_PADDING_BIT_LEN) / 8))
|
||||||
|
|
||||||
|
typedef struct esp_ds_context esp_ds_context_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
ESP_DS_RSA_1024 = (1024 / 32) - 1,
|
||||||
|
ESP_DS_RSA_2048 = (2048 / 32) - 1,
|
||||||
|
ESP_DS_RSA_3072 = (3072 / 32) - 1
|
||||||
|
} esp_digital_signature_length_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypted private key data. Recommended to store in flash in this format.
|
||||||
|
*
|
||||||
|
* @note This struct has to match to one from the ROM code! This documentation is mostly taken from there.
|
||||||
|
*/
|
||||||
|
typedef struct esp_digital_signature_data {
|
||||||
|
/**
|
||||||
|
* RSA LENGTH register parameters
|
||||||
|
* (number of words in RSA key & operands, minus one).
|
||||||
|
*
|
||||||
|
* Max value 127 (for RSA 3072).
|
||||||
|
*
|
||||||
|
* This value must match the length field encrypted and stored in 'c',
|
||||||
|
* or invalid results will be returned. (The DS peripheral will
|
||||||
|
* always use the value in 'c', not this value, so an attacker can't
|
||||||
|
* alter the DS peripheral results this way, it will just truncate or
|
||||||
|
* extend the message and the resulting signature in software.)
|
||||||
|
*
|
||||||
|
* @note In IDF, the enum type length is the same as of type unsigned, so they can be used interchangably.
|
||||||
|
* See the ROM code for the original declaration of struct \c ets_ds_data_t.
|
||||||
|
*/
|
||||||
|
esp_digital_signature_length_t rsa_length;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IV value used to encrypt 'c'
|
||||||
|
*/
|
||||||
|
uint32_t iv[ESP_DS_IV_BIT_LEN / 32];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encrypted Digital Signature parameters. Result of AES-CBC encryption
|
||||||
|
* of plaintext values. Includes an encrypted message digest.
|
||||||
|
*/
|
||||||
|
uint8_t c[ESP_DS_C_LEN];
|
||||||
|
} esp_ds_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plaintext parameters used by Digital Signature.
|
||||||
|
*
|
||||||
|
* This is only used for encrypting the RSA parameters by calling esp_ds_encrypt_params().
|
||||||
|
* Afterwards, the result can be stored in flash or in other persistent memory.
|
||||||
|
* The encryption is a prerequisite step before any signature operation can be done.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t Y[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA exponent
|
||||||
|
uint32_t M[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA modulus
|
||||||
|
uint32_t Rb[ESP_DS_SIGNATURE_MAX_BIT_LEN / 32]; //!< RSA r inverse operand
|
||||||
|
uint32_t M_prime; //!< RSA M prime operand
|
||||||
|
uint32_t length; //!< RSA length in words (32 bit)
|
||||||
|
} esp_ds_p_data_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sign the message with a hardware key from specific key slot.
|
||||||
|
*
|
||||||
|
* This function is a wrapper around \c esp_ds_finish_sign() and \c esp_ds_start_sign(), so do not use them
|
||||||
|
* in parallel.
|
||||||
|
* It blocks until the signing is finished and then returns the signature.
|
||||||
|
*
|
||||||
|
* @note This function locks the HMAC, SHA, AES and RSA components during its entire execution time.
|
||||||
|
*
|
||||||
|
* @param message the message to be signed; its length is determined by data->rsa_length
|
||||||
|
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||||
|
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||||
|
* signing key data
|
||||||
|
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK if successful, the signature was written to the parameter \c signature.
|
||||||
|
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||||
|
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||||
|
* since the message digest matches.
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ds_sign(const void *message,
|
||||||
|
const esp_ds_data_t *data,
|
||||||
|
hmac_key_id_t key_id,
|
||||||
|
void *signature);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start the signing process.
|
||||||
|
*
|
||||||
|
* This function yields a context object which needs to be passed to \c esp_ds_finish_sign() to finish the signing
|
||||||
|
* process.
|
||||||
|
*
|
||||||
|
* @note This function locks the HMAC, SHA, AES and RSA components, so the user has to ensure to call
|
||||||
|
* \c esp_ds_finish_sign() in a timely manner.
|
||||||
|
*
|
||||||
|
* @param message the message to be signed; its length is determined by data->rsa_length
|
||||||
|
* @param data the encrypted signing key data (AES encrypted RSA key + IV)
|
||||||
|
* @param key_id the HMAC key ID determining the HMAC key of the HMAC which will be used to decrypt the
|
||||||
|
* signing key data
|
||||||
|
* @param esp_ds_ctx the context object which is needed for finishing the signing process later
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK if successful, the ds operation was started now and has to be finished with \c esp_ds_finish_sign()
|
||||||
|
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or data->rsa_length is too long or 0
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_HMAC_FAIL if there was an HMAC failure during retrieval of the decryption key
|
||||||
|
* - ESP_ERR_NO_MEM if there hasn't been enough memory to allocate the context object
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_INVALID_KEY if there's a problem with passing the HMAC key to the DS component
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ds_start_sign(const void *message,
|
||||||
|
const esp_ds_data_t *data,
|
||||||
|
hmac_key_id_t key_id,
|
||||||
|
esp_ds_context_t **esp_ds_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return true if the DS peripheral is busy, otherwise false.
|
||||||
|
*
|
||||||
|
* @note Only valid if \c esp_ds_start_sign() was called before.
|
||||||
|
*/
|
||||||
|
bool esp_ds_is_busy(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Finish the signing process.
|
||||||
|
*
|
||||||
|
* @param signature the destination of the signature, should be (data->rsa_length + 1)*4 bytes long
|
||||||
|
* @param esp_ds_ctx the context object retreived by \c esp_ds_start_sign()
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||||
|
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_INVALID_DIGEST if the message digest didn't match; the signature is invalid.
|
||||||
|
* This means that the encrypted RSA key parameters are invalid, indicating that they may have been tampered
|
||||||
|
* with or indicating a flash error, etc.
|
||||||
|
* - ESP_ERR_HW_CRYPTO_DS_INVALID_PADDING if the message padding is incorrect, the signature can be read though
|
||||||
|
* since the message digest matches (see TRM for more details).
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ds_finish_sign(void *signature, esp_ds_context_t *esp_ds_ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Encrypt the private key parameters.
|
||||||
|
*
|
||||||
|
* The encryption is a prerequisite step before any signature operation can be done.
|
||||||
|
* It is not strictly necessary to use this encryption function, the encryption could also happen on an external
|
||||||
|
* device.
|
||||||
|
*
|
||||||
|
* @param data Output buffer to store encrypted data, suitable for later use generating signatures.
|
||||||
|
* The allocated memory must be in internal memory and word aligned since it's filled by DMA. Both is asserted
|
||||||
|
* at run time.
|
||||||
|
* @param iv Pointer to 16 byte IV buffer, will be copied into 'data'. Should be randomly generated bytes each time.
|
||||||
|
* @param p_data Pointer to input plaintext key data. The expectation is this data will be deleted after this process
|
||||||
|
* is done and 'data' is stored.
|
||||||
|
* @param key Pointer to 32 bytes of key data. Type determined by key_type parameter. The expectation is the
|
||||||
|
* corresponding HMAC key will be stored to efuse and then permanently erased.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK if successful, the ds operation has been finished and the result is written to signature.
|
||||||
|
* - ESP_ERR_INVALID_ARG if one of the parameters is NULL or p_data->rsa_length is too long
|
||||||
|
*/
|
||||||
|
esp_err_t esp_ds_encrypt_params(esp_ds_data_t *data,
|
||||||
|
const void *iv,
|
||||||
|
const esp_ds_p_data_t *p_data,
|
||||||
|
const void *key);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
67
components/esp32h2/include/esp_hmac.h
Normal file
67
components/esp32h2/include/esp_hmac.h
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef _ESP_HMAC_H_
|
||||||
|
#define _ESP_HMAC_H_
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "esp_err.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The possible efuse keys for the HMAC peripheral
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
HMAC_KEY0 = 0,
|
||||||
|
HMAC_KEY1,
|
||||||
|
HMAC_KEY2,
|
||||||
|
HMAC_KEY3,
|
||||||
|
HMAC_KEY4,
|
||||||
|
HMAC_KEY5,
|
||||||
|
HMAC_KEY_MAX
|
||||||
|
} hmac_key_id_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief
|
||||||
|
* Calculate the HMAC of a given message.
|
||||||
|
*
|
||||||
|
* Calculate the HMAC \c hmac of a given message \c message with length \c message_len.
|
||||||
|
* SHA256 is used for the calculation (fixed on ESP32S2).
|
||||||
|
*
|
||||||
|
* @note Uses the HMAC peripheral in "upstream" mode.
|
||||||
|
*
|
||||||
|
* @param key_id Determines which of the 6 key blocks in the efuses should be used for the HMAC calcuation.
|
||||||
|
* The corresponding purpose field of the key block in the efuse must be set to the HMAC upstream purpose value.
|
||||||
|
* @param message the message for which to calculate the HMAC
|
||||||
|
* @param message_len message length
|
||||||
|
* return ESP_ERR_INVALID_STATE if unsuccessful
|
||||||
|
* @param [out] hmac the hmac result; the buffer behind the provided pointer must be 32 bytes long
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* * ESP_OK, if the calculation was successful,
|
||||||
|
* * ESP_FAIL, if the hmac calculation failed
|
||||||
|
*/
|
||||||
|
esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
|
||||||
|
const void *message,
|
||||||
|
size_t message_len,
|
||||||
|
uint8_t *hmac);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _ESP_HMAC_H_
|
118
components/esp32h2/ld/esp32h2.ld
Normal file
118
components/esp32h2/ld/esp32h2.ld
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* ESP32-H2 Linker Script Memory Layout
|
||||||
|
* This file describes the memory layout (memory blocks) by virtual memory addresses.
|
||||||
|
* This linker script is passed through the C preprocessor to include configuration options.
|
||||||
|
* Please use preprocessor features sparingly!
|
||||||
|
* Restrict to simple macros with numeric values, and/or #if/#endif blocks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
|
||||||
|
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
|
||||||
|
#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
|
||||||
|
#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
|
||||||
|
#else
|
||||||
|
#define ESP_BOOTLOADER_RESERVE_RTC 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define SRAM_IRAM_START 0x4037C000
|
||||||
|
#define SRAM_DRAM_START 0x3FC7C000
|
||||||
|
#define ICACHE_SIZE 0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */
|
||||||
|
#define I_D_SRAM_OFFSET (SRAM_IRAM_START - SRAM_DRAM_START)
|
||||||
|
#define SRAM_DRAM_END 0x403D0000 - I_D_SRAM_OFFSET /* 2nd stage bootloader iram_loader_seg start address */
|
||||||
|
|
||||||
|
#define SRAM_IRAM_ORG (SRAM_IRAM_START + ICACHE_SIZE)
|
||||||
|
#define SRAM_DRAM_ORG (SRAM_DRAM_START + ICACHE_SIZE)
|
||||||
|
|
||||||
|
#define I_D_SRAM_SIZE SRAM_DRAM_END - SRAM_DRAM_ORG
|
||||||
|
|
||||||
|
#if CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE
|
||||||
|
ASSERT((CONFIG_ESP32H2_FIXED_STATIC_RAM_SIZE <= I_D_SRAM_SIZE), "Fixed static ram data does not fit.")
|
||||||
|
#define DRAM0_0_SEG_LEN CONFIG_ESP3C3_FIXED_STATIC_RAM_SIZE
|
||||||
|
#else
|
||||||
|
#define DRAM0_0_SEG_LEN I_D_SRAM_SIZE
|
||||||
|
#endif // CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* All these values assume the flash cache is on, and have the blocks this uses subtracted from the length
|
||||||
|
* of the various regions. The 'data access port' dram/drom regions map to the same iram/irom regions but
|
||||||
|
* are connected to the data port of the CPU and eg allow byte-wise access.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* IRAM for PRO CPU. */
|
||||||
|
iram0_0_seg (RX) : org = SRAM_IRAM_ORG, len = I_D_SRAM_SIZE
|
||||||
|
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
/* Flash mapped instruction data */
|
||||||
|
iram0_2_seg (RX) : org = 0x42000020, len = 0x8000000-0x20
|
||||||
|
|
||||||
|
/**
|
||||||
|
* (0x20 offset above is a convenience for the app binary image generation.
|
||||||
|
* Flash cache has 64KB pages. The .bin file which is flashed to the chip
|
||||||
|
* has a 0x18 byte file header, and each segment has a 0x08 byte segment
|
||||||
|
* header. Setting this offset makes it simple to meet the flash cache MMU's
|
||||||
|
* constraint that (paddr % 64KB == vaddr % 64KB).)
|
||||||
|
*/
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shared data RAM, excluding memory reserved for ROM bss/data/stack.
|
||||||
|
* Enabling Bluetooth & Trace Memory features in menuconfig will decrease the amount of RAM available.
|
||||||
|
*/
|
||||||
|
dram0_0_seg (RW) : org = SRAM_DRAM_ORG, len = DRAM0_0_SEG_LEN
|
||||||
|
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
/* Flash mapped constant data */
|
||||||
|
drom0_0_seg (R) : org = 0x3C000020, len = 0x8000000-0x20
|
||||||
|
|
||||||
|
/* (See iram0_2_seg for meaning of 0x20 offset in the above.) */
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RTC fast memory (executable). Persists over deep sleep.
|
||||||
|
*/
|
||||||
|
rtc_iram_seg(RWX) : org = 0x50000000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE
|
||||||
|
/* static data ends at defined address */
|
||||||
|
_static_data_end = 0x3FCA0000 + DRAM0_0_SEG_LEN;
|
||||||
|
#else
|
||||||
|
_static_data_end = _bss_end;
|
||||||
|
#endif // CONFIG_ESP32H2_USE_FIXED_STATIC_RAM_SIZE
|
||||||
|
|
||||||
|
/* Heap ends at top of dram0_0_seg */
|
||||||
|
_heap_end = 0x40000000;
|
||||||
|
|
||||||
|
_data_seg_org = ORIGIN(rtc_data_seg);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The lines below define location alias for .rtc.data section
|
||||||
|
* As C3 only has RTC fast memory, this is not configurable like on other targets
|
||||||
|
*/
|
||||||
|
REGION_ALIAS("rtc_data_seg", rtc_iram_seg );
|
||||||
|
REGION_ALIAS("rtc_slow_seg", rtc_iram_seg );
|
||||||
|
REGION_ALIAS("rtc_data_location", rtc_iram_seg );
|
||||||
|
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
REGION_ALIAS("default_code_seg", iram0_2_seg);
|
||||||
|
#else
|
||||||
|
REGION_ALIAS("default_code_seg", iram0_0_seg);
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
REGION_ALIAS("default_rodata_seg", drom0_0_seg);
|
||||||
|
#else
|
||||||
|
REGION_ALIAS("default_rodata_seg", dram0_0_seg);
|
||||||
|
#endif // CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If rodata default segment is placed in `drom0_0_seg`, then flash's first rodata section must
|
||||||
|
* also be first in the segment.
|
||||||
|
*/
|
||||||
|
#if CONFIG_APP_BUILD_USE_FLASH_SECTIONS
|
||||||
|
ASSERT(_flash_rodata_dummy_start == ORIGIN(default_rodata_seg),
|
||||||
|
".flash_rodata_dummy section must be placed at the beginning of the rodata segment.")
|
||||||
|
#endif
|
30
components/esp32h2/ld/esp32h2.peripherals.ld
Normal file
30
components/esp32h2/ld/esp32h2.peripherals.ld
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
PROVIDE ( UART0 = 0x60000000 );
|
||||||
|
PROVIDE ( UART1 = 0x60010000 );
|
||||||
|
PROVIDE ( SPIMEM1 = 0x60002000 );
|
||||||
|
PROVIDE ( SPIMEM0 = 0x60003000 );
|
||||||
|
PROVIDE ( GPIO = 0x60004000 );
|
||||||
|
PROVIDE ( SIGMADELTA = 0x60004f00 );
|
||||||
|
PROVIDE ( RTCCNTL = 0x60008000 );
|
||||||
|
PROVIDE ( RTCIO = 0x60008400 );
|
||||||
|
PROVIDE ( HINF = 0x6000B000 );
|
||||||
|
PROVIDE ( I2S1 = 0x6002d000 );
|
||||||
|
PROVIDE ( I2C0 = 0x60013000 );
|
||||||
|
PROVIDE ( UHCI0 = 0x60014000 );
|
||||||
|
PROVIDE ( UHCI1 = 0x6000c000 );
|
||||||
|
PROVIDE ( HOST = 0x60015000 );
|
||||||
|
PROVIDE ( RMT = 0x60016000 );
|
||||||
|
PROVIDE ( RMTMEM = 0x60016400 );
|
||||||
|
PROVIDE ( PCNT = 0x60017000 );
|
||||||
|
PROVIDE ( SLC = 0x60018000 );
|
||||||
|
PROVIDE ( LEDC = 0x60019000 );
|
||||||
|
PROVIDE ( TIMERG0 = 0x6001F000 );
|
||||||
|
PROVIDE ( TIMERG1 = 0x60020000 );
|
||||||
|
PROVIDE ( SYSTIMER = 0x60023000 );
|
||||||
|
PROVIDE ( GPSPI2 = 0x60024000 );
|
||||||
|
PROVIDE ( GPSPI3 = 0x60025000 );
|
||||||
|
PROVIDE ( SYSCON = 0x60026000 );
|
||||||
|
PROVIDE ( TWAI = 0x6002B000 );
|
||||||
|
PROVIDE ( GPSPI4 = 0x60037000 );
|
||||||
|
PROVIDE ( APB_SARADC = 0x60040000 );
|
||||||
|
PROVIDE ( USB_SERIAL_JTAG = 0x60043000 );
|
||||||
|
PROVIDE ( GDMA = 0x6003F000 );
|
392
components/esp32h2/ld/esp32h2.project.ld.in
Normal file
392
components/esp32h2/ld/esp32h2.project.ld.in
Normal file
@@ -0,0 +1,392 @@
|
|||||||
|
/* Default entry point */
|
||||||
|
ENTRY(call_start_cpu0);
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* RTC fast memory holds RTC wake stub code,
|
||||||
|
* including from any source file named rtc_wake_stub*.c
|
||||||
|
*/
|
||||||
|
.rtc.text :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
mapping[rtc_text]
|
||||||
|
|
||||||
|
*rtc_wake_stub*.*(.literal .text .literal.* .text.*)
|
||||||
|
_rtc_text_end = ABSOLUTE(.);
|
||||||
|
} > rtc_iram_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section is required to skip rtc.text area because rtc_iram_seg and
|
||||||
|
* rtc_data_seg are reflect the same address space on different buses.
|
||||||
|
*/
|
||||||
|
.rtc.dummy :
|
||||||
|
{
|
||||||
|
_rtc_dummy_start = ABSOLUTE(.);
|
||||||
|
_rtc_fast_start = ABSOLUTE(.);
|
||||||
|
. = SIZEOF(.rtc.text);
|
||||||
|
_rtc_dummy_end = ABSOLUTE(.);
|
||||||
|
} > rtc_data_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section located in RTC FAST Memory area.
|
||||||
|
* It holds data marked with RTC_FAST_ATTR attribute.
|
||||||
|
* See the file "esp_attr.h" for more information.
|
||||||
|
*/
|
||||||
|
.rtc.force_fast :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_rtc_force_fast_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[rtc_force_fast]
|
||||||
|
|
||||||
|
*(.rtc.force_fast .rtc.force_fast.*)
|
||||||
|
. = ALIGN(4) ;
|
||||||
|
_rtc_force_fast_end = ABSOLUTE(.);
|
||||||
|
} > rtc_data_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* RTC data section holds RTC wake stub
|
||||||
|
* data/rodata, including from any source file
|
||||||
|
* named rtc_wake_stub*.c and the data marked with
|
||||||
|
* RTC_DATA_ATTR, RTC_RODATA_ATTR attributes.
|
||||||
|
* The memory location of the data is dependent on
|
||||||
|
* CONFIG_ESP32H2_RTCDATA_IN_FAST_MEM option.
|
||||||
|
*/
|
||||||
|
.rtc.data :
|
||||||
|
{
|
||||||
|
_rtc_data_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[rtc_data]
|
||||||
|
|
||||||
|
*rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*)
|
||||||
|
_rtc_data_end = ABSOLUTE(.);
|
||||||
|
} > rtc_data_location
|
||||||
|
|
||||||
|
/* RTC bss, from any source file named rtc_wake_stub*.c */
|
||||||
|
.rtc.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
_rtc_bss_start = ABSOLUTE(.);
|
||||||
|
*rtc_wake_stub*.*(.bss .bss.*)
|
||||||
|
*rtc_wake_stub*.*(COMMON)
|
||||||
|
|
||||||
|
mapping[rtc_bss]
|
||||||
|
|
||||||
|
_rtc_bss_end = ABSOLUTE(.);
|
||||||
|
} > rtc_data_location
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section holds data that should not be initialized at power up
|
||||||
|
* and will be retained during deep sleep.
|
||||||
|
* User data marked with RTC_NOINIT_ATTR will be placed
|
||||||
|
* into this section. See the file "esp_attr.h" for more information.
|
||||||
|
* The memory location of the data is dependent on CONFIG_ESP32H2_RTCDATA_IN_FAST_MEM option.
|
||||||
|
*/
|
||||||
|
.rtc_noinit (NOLOAD):
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_rtc_noinit_start = ABSOLUTE(.);
|
||||||
|
*(.rtc_noinit .rtc_noinit.*)
|
||||||
|
. = ALIGN(4) ;
|
||||||
|
_rtc_noinit_end = ABSOLUTE(.);
|
||||||
|
} > rtc_data_location
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section located in RTC SLOW Memory area.
|
||||||
|
* It holds data marked with RTC_SLOW_ATTR attribute.
|
||||||
|
* See the file "esp_attr.h" for more information.
|
||||||
|
*/
|
||||||
|
.rtc.force_slow :
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_rtc_force_slow_start = ABSOLUTE(.);
|
||||||
|
*(.rtc.force_slow .rtc.force_slow.*)
|
||||||
|
. = ALIGN(4) ;
|
||||||
|
_rtc_force_slow_end = ABSOLUTE(.);
|
||||||
|
} > rtc_slow_seg
|
||||||
|
|
||||||
|
/* Get size of rtc slow data based on rtc_data_location alias */
|
||||||
|
_rtc_slow_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
|
||||||
|
? (_rtc_force_slow_end - _rtc_data_start)
|
||||||
|
: (_rtc_force_slow_end - _rtc_force_slow_start);
|
||||||
|
|
||||||
|
_rtc_fast_length = (ORIGIN(rtc_slow_seg) == ORIGIN(rtc_data_location))
|
||||||
|
? (_rtc_force_fast_end - _rtc_fast_start)
|
||||||
|
: (_rtc_noinit_end - _rtc_fast_start);
|
||||||
|
|
||||||
|
ASSERT((_rtc_slow_length <= LENGTH(rtc_slow_seg)),
|
||||||
|
"RTC_SLOW segment data does not fit.")
|
||||||
|
|
||||||
|
ASSERT((_rtc_fast_length <= LENGTH(rtc_data_seg)),
|
||||||
|
"RTC_FAST segment data does not fit.")
|
||||||
|
|
||||||
|
.iram0.text :
|
||||||
|
{
|
||||||
|
_iram_start = ABSOLUTE(.);
|
||||||
|
/* Vectors go to start of IRAM */
|
||||||
|
ASSERT(ABSOLUTE(.) % 0x100 == 0, "vector address must be 256 byte aligned");
|
||||||
|
KEEP(*(.exception_vectors.text));
|
||||||
|
. = ALIGN(4);
|
||||||
|
|
||||||
|
_invalid_pc_placeholder = ABSOLUTE(.);
|
||||||
|
|
||||||
|
/* Code marked as running out of IRAM */
|
||||||
|
_iram_text_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[iram0_text]
|
||||||
|
|
||||||
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section is required to skip .iram0.text area because iram0_0_seg and
|
||||||
|
* dram0_0_seg reflect the same address space on different buses.
|
||||||
|
*/
|
||||||
|
.dram0.dummy (NOLOAD):
|
||||||
|
{
|
||||||
|
. = ORIGIN(dram0_0_seg) + _iram_end - _iram_start;
|
||||||
|
} > dram0_0_seg
|
||||||
|
|
||||||
|
.dram0.data :
|
||||||
|
{
|
||||||
|
_data_start = ABSOLUTE(.);
|
||||||
|
*(.gnu.linkonce.d.*)
|
||||||
|
*(.data1)
|
||||||
|
__global_pointer$ = . + 0x800;
|
||||||
|
*(.sdata)
|
||||||
|
*(.sdata.*)
|
||||||
|
*(.gnu.linkonce.s.*)
|
||||||
|
*(.sdata2)
|
||||||
|
*(.sdata2.*)
|
||||||
|
*(.gnu.linkonce.s2.*)
|
||||||
|
*(.jcr)
|
||||||
|
|
||||||
|
_esp_system_init_fn_array_start = ABSOLUTE(.);
|
||||||
|
KEEP (*(SORT(.esp_system_init_fn) SORT(.esp_system_init_fn.*)))
|
||||||
|
_esp_system_init_fn_array_end = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[dram0_data]
|
||||||
|
|
||||||
|
_data_end = ABSOLUTE(.);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > dram0_0_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This section holds data that should not be initialized at power up.
|
||||||
|
* The section located in Internal SRAM memory region. The macro _NOINIT
|
||||||
|
* can be used as attribute to place data into this section.
|
||||||
|
* See the "esp_attr.h" file for more information.
|
||||||
|
*/
|
||||||
|
.noinit (NOLOAD):
|
||||||
|
{
|
||||||
|
. = ALIGN(4);
|
||||||
|
_noinit_start = ABSOLUTE(.);
|
||||||
|
*(.noinit .noinit.*)
|
||||||
|
. = ALIGN(4) ;
|
||||||
|
_noinit_end = ABSOLUTE(.);
|
||||||
|
} > dram0_0_seg
|
||||||
|
|
||||||
|
/* Shared RAM */
|
||||||
|
.dram0.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (8);
|
||||||
|
_bss_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[dram0_bss]
|
||||||
|
|
||||||
|
*(.dynsbss)
|
||||||
|
*(.sbss)
|
||||||
|
*(.sbss.*)
|
||||||
|
*(.gnu.linkonce.sb.*)
|
||||||
|
*(.scommon)
|
||||||
|
*(.sbss2)
|
||||||
|
*(.sbss2.*)
|
||||||
|
*(.gnu.linkonce.sb2.*)
|
||||||
|
*(.dynbss)
|
||||||
|
*(.share.mem)
|
||||||
|
*(.gnu.linkonce.b.*)
|
||||||
|
|
||||||
|
. = ALIGN (8);
|
||||||
|
_bss_end = ABSOLUTE(.);
|
||||||
|
} > dram0_0_seg
|
||||||
|
|
||||||
|
ASSERT(((_bss_end - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)), "DRAM segment data does not fit.")
|
||||||
|
|
||||||
|
.flash.text :
|
||||||
|
{
|
||||||
|
_stext = .;
|
||||||
|
_instruction_reserved_start = ABSOLUTE(.);
|
||||||
|
_text_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[flash_text]
|
||||||
|
|
||||||
|
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
|
||||||
|
*(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||||
|
*(.fini.literal)
|
||||||
|
*(.fini)
|
||||||
|
*(.gnu.version)
|
||||||
|
|
||||||
|
/** CPU will try to prefetch up to 16 bytes of
|
||||||
|
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
|
||||||
|
* safe access to up to 16 bytes after the last real instruction, add
|
||||||
|
* dummy bytes to ensure this
|
||||||
|
*/
|
||||||
|
. += 16;
|
||||||
|
|
||||||
|
_text_end = ABSOLUTE(.);
|
||||||
|
_instruction_reserved_end = ABSOLUTE(.);
|
||||||
|
_etext = .;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to _iram_start, this symbol goes here so it is
|
||||||
|
* resolved by addr2line in preference to the first symbol in
|
||||||
|
* the flash.text segment.
|
||||||
|
*/
|
||||||
|
_flash_cache_start = ABSOLUTE(0);
|
||||||
|
} > default_code_seg
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This dummy section represents the .flash.text section but in default_rodata_seg.
|
||||||
|
* Thus, it must have its alignement and (at least) its size.
|
||||||
|
*/
|
||||||
|
.flash_rodata_dummy (NOLOAD):
|
||||||
|
{
|
||||||
|
_flash_rodata_dummy_start = .;
|
||||||
|
/* Start at the same alignement constraint than .flash.text */
|
||||||
|
. = ALIGN(ALIGNOF(.flash.text));
|
||||||
|
/* Create an empty gap as big as .flash.text section */
|
||||||
|
. = . + SIZEOF(.flash.text);
|
||||||
|
/* Prepare the alignement of the section above. Few bytes (0x20) must be
|
||||||
|
* added for the mapping header. */
|
||||||
|
. = ALIGN(0x10000) + 0x20;
|
||||||
|
_rodata_reserved_start = .;
|
||||||
|
} > default_rodata_seg
|
||||||
|
|
||||||
|
.flash.appdesc : ALIGN(0x10)
|
||||||
|
{
|
||||||
|
_rodata_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
*(.rodata_desc .rodata_desc.*) /* Should be the first. App version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
*(.rodata_custom_desc .rodata_custom_desc.*) /* Should be the second. Custom app version info. DO NOT PUT ANYTHING BEFORE IT! */
|
||||||
|
|
||||||
|
/* Create an empty gap within this section. Thanks to this, the end of this
|
||||||
|
* section will match .flash.rodata's begin address. Thus, both sections
|
||||||
|
* will be merged when creating the final bin image. */
|
||||||
|
. = ALIGN(ALIGNOF(.flash.rodata));
|
||||||
|
} >default_rodata_seg
|
||||||
|
|
||||||
|
.flash.rodata : ALIGN(0x10)
|
||||||
|
{
|
||||||
|
_flash_rodata_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[flash_rodata]
|
||||||
|
|
||||||
|
*(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */
|
||||||
|
*(.gnu.linkonce.r.*)
|
||||||
|
*(.rodata1)
|
||||||
|
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
|
||||||
|
*(.xt_except_table)
|
||||||
|
*(.gcc_except_table .gcc_except_table.*)
|
||||||
|
*(.gnu.linkonce.e.*)
|
||||||
|
*(.gnu.version_r)
|
||||||
|
. = (. + 3) & ~ 3;
|
||||||
|
__eh_frame = ABSOLUTE(.);
|
||||||
|
KEEP(*(.eh_frame))
|
||||||
|
. = (. + 7) & ~ 3;
|
||||||
|
/*
|
||||||
|
* C++ constructor and destructor tables
|
||||||
|
* Don't include anything from crtbegin.o or crtend.o, as IDF doesn't use toolchain crt.
|
||||||
|
*
|
||||||
|
* RISC-V gcc is configured with --enable-initfini-array so it emits an .init_array section instead.
|
||||||
|
* But the init_priority sections will be sorted for iteration in ascending order during startup.
|
||||||
|
* The rest of the init_array sections is sorted for iteration in descending order during startup, however.
|
||||||
|
* Hence a different section is generated for the init_priority functions which is iterated in
|
||||||
|
* ascending order during startup. The corresponding code can be found in startup.c.
|
||||||
|
*/
|
||||||
|
__init_priority_array_start = ABSOLUTE(.);
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array.*))
|
||||||
|
__init_priority_array_end = ABSOLUTE(.);
|
||||||
|
__init_array_start = ABSOLUTE(.);
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.* *crtbegin.*) .init_array))
|
||||||
|
__init_array_end = ABSOLUTE(.);
|
||||||
|
KEEP (*crtbegin.*(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
/* C++ exception handlers table: */
|
||||||
|
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
|
||||||
|
*(.xt_except_desc)
|
||||||
|
*(.gnu.linkonce.h.*)
|
||||||
|
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
|
||||||
|
*(.xt_except_desc_end)
|
||||||
|
*(.dynamic)
|
||||||
|
*(.gnu.version_d)
|
||||||
|
/* Addresses of memory regions reserved via SOC_RESERVE_MEMORY_REGION() */
|
||||||
|
soc_reserved_memory_region_start = ABSOLUTE(.);
|
||||||
|
KEEP (*(.reserved_memory_address))
|
||||||
|
soc_reserved_memory_region_end = ABSOLUTE(.);
|
||||||
|
_rodata_end = ABSOLUTE(.);
|
||||||
|
/* Literals are also RO data. */
|
||||||
|
_lit4_start = ABSOLUTE(.);
|
||||||
|
*(*.lit4)
|
||||||
|
*(.lit4.*)
|
||||||
|
*(.gnu.linkonce.lit4.*)
|
||||||
|
_lit4_end = ABSOLUTE(.);
|
||||||
|
. = ALIGN(4);
|
||||||
|
_thread_local_start = ABSOLUTE(.);
|
||||||
|
*(.tdata)
|
||||||
|
*(.tdata.*)
|
||||||
|
*(.tbss)
|
||||||
|
*(.tbss.*)
|
||||||
|
*(.srodata)
|
||||||
|
*(.srodata.*)
|
||||||
|
_thread_local_end = ABSOLUTE(.);
|
||||||
|
_rodata_reserved_end = ABSOLUTE(.);
|
||||||
|
. = ALIGN(4);
|
||||||
|
} > default_rodata_seg
|
||||||
|
|
||||||
|
/* Marks the end of IRAM code segment */
|
||||||
|
.iram0.text_end (NOLOAD) :
|
||||||
|
{
|
||||||
|
/* C3 memprot requires 512 B alignment for split lines */
|
||||||
|
. = ALIGN (0x200);
|
||||||
|
/* iram_end_test section exists for use by memprot unit tests only */
|
||||||
|
*(.iram_end_test)
|
||||||
|
_iram_text_end = ABSOLUTE(.);
|
||||||
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
.iram0.data :
|
||||||
|
{
|
||||||
|
. = ALIGN(16);
|
||||||
|
_iram_data_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[iram0_data]
|
||||||
|
|
||||||
|
_iram_data_end = ABSOLUTE(.);
|
||||||
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
.iram0.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(16);
|
||||||
|
_iram_bss_start = ABSOLUTE(.);
|
||||||
|
|
||||||
|
mapping[iram0_bss]
|
||||||
|
|
||||||
|
_iram_bss_end = ABSOLUTE(.);
|
||||||
|
. = ALIGN(16);
|
||||||
|
_iram_end = ABSOLUTE(.);
|
||||||
|
} > iram0_0_seg
|
||||||
|
|
||||||
|
/* Marks the end of data, bss and possibly rodata */
|
||||||
|
.dram0.heap_start (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN (16);
|
||||||
|
_heap_start = ABSOLUTE(.);
|
||||||
|
} > dram0_0_seg
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT(((_iram_end - ORIGIN(iram0_0_seg)) <= LENGTH(iram0_0_seg)),
|
||||||
|
"IRAM0 segment data does not fit.")
|
||||||
|
|
||||||
|
ASSERT(((_heap_start - ORIGIN(dram0_0_seg)) <= LENGTH(dram0_0_seg)),
|
||||||
|
"DRAM segment data does not fit.")
|
616
components/esp32h2/memprot.c
Normal file
616
components/esp32h2/memprot.c
Normal file
@@ -0,0 +1,616 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
/* INTERNAL API
|
||||||
|
* implementation of PMS memory protection features
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "soc/sensitive_reg.h"
|
||||||
|
#include "soc/dport_access.h"
|
||||||
|
#include "soc/periph_defs.h"
|
||||||
|
#include "esp_intr_alloc.h"
|
||||||
|
#include "hal/memprot_ll.h"
|
||||||
|
#include "esp32h2/memprot.h"
|
||||||
|
#include "riscv/interrupt.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
|
||||||
|
extern int _iram_text_end;
|
||||||
|
static const char *TAG = "memprot";
|
||||||
|
|
||||||
|
const char *esp_memprot_mem_type_to_str(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch (mem_type) {
|
||||||
|
case MEMPROT_NONE:
|
||||||
|
return "NONE";
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return "IRAM0_SRAM";
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return "DRAM0_SRAM";
|
||||||
|
case MEMPROT_ALL:
|
||||||
|
return "ALL";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *esp_memprot_split_line_to_str(split_line_t line_type)
|
||||||
|
{
|
||||||
|
switch (line_type) {
|
||||||
|
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
|
||||||
|
return "MEMPROT_IRAM0_DRAM0_SPLITLINE";
|
||||||
|
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
|
||||||
|
return "MEMPROT_IRAM0_LINE_0_SPLITLINE";
|
||||||
|
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
|
||||||
|
return "MEMPROT_IRAM0_LINE_1_SPLITLINE";
|
||||||
|
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
|
||||||
|
return "MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE";
|
||||||
|
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
|
||||||
|
return "MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *esp_memprot_pms_to_str(pms_area_t area_type)
|
||||||
|
{
|
||||||
|
switch (area_type) {
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_0:
|
||||||
|
return "MEMPROT_IRAM0_PMS_AREA_0";
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_1:
|
||||||
|
return "MEMPROT_IRAM0_PMS_AREA_1";
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_2:
|
||||||
|
return "MEMPROT_IRAM0_PMS_AREA_2";
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_3:
|
||||||
|
return "MEMPROT_IRAM0_PMS_AREA_3";
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_0:
|
||||||
|
return "MEMPROT_DRAM0_PMS_AREA_0";
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_1:
|
||||||
|
return "MEMPROT_DRAM0_PMS_AREA_1";
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_2:
|
||||||
|
return "MEMPROT_DRAM0_PMS_AREA_2";
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_3:
|
||||||
|
return "MEMPROT_DRAM0_PMS_AREA_3";
|
||||||
|
default:
|
||||||
|
return "UNKNOWN";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* split lines */
|
||||||
|
|
||||||
|
void *esp_memprot_get_default_main_split_addr()
|
||||||
|
{
|
||||||
|
return &_iram_text_end;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t *esp_memprot_get_split_addr(split_line_t line_type)
|
||||||
|
{
|
||||||
|
switch ( line_type ) {
|
||||||
|
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
|
||||||
|
return memprot_ll_get_iram0_split_line_main_I_D();
|
||||||
|
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
|
||||||
|
return memprot_ll_get_iram0_split_line_I_0();
|
||||||
|
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
|
||||||
|
return memprot_ll_get_iram0_split_line_I_1();
|
||||||
|
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
|
||||||
|
return memprot_ll_get_dram0_split_line_D_0();
|
||||||
|
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
|
||||||
|
return memprot_ll_get_dram0_split_line_D_1();
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_split_line_lock()
|
||||||
|
{
|
||||||
|
memprot_ll_set_iram0_dram0_split_line_lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_split_line_lock()
|
||||||
|
{
|
||||||
|
return memprot_ll_get_iram0_dram0_split_line_lock();
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_split_line(split_line_t line_type, const void *line_addr)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "Setting split line %s, addr: 0x%08X", esp_memprot_split_line_to_str(line_type), (uint32_t)line_addr);
|
||||||
|
|
||||||
|
//split-line must be divisible by 512 (PMS module restriction)
|
||||||
|
assert( ((uint32_t)line_addr) % 0x200 == 0 );
|
||||||
|
|
||||||
|
switch ( line_type ) {
|
||||||
|
case MEMPROT_IRAM0_DRAM0_SPLITLINE:
|
||||||
|
memprot_ll_set_iram0_split_line_main_I_D(line_addr);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_LINE_0_SPLITLINE:
|
||||||
|
memprot_ll_set_iram0_split_line_I_0(line_addr);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_LINE_1_SPLITLINE:
|
||||||
|
memprot_ll_set_iram0_split_line_I_1(line_addr);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE:
|
||||||
|
memprot_ll_set_dram0_split_line_D_0(line_addr);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE:
|
||||||
|
memprot_ll_set_dram0_split_line_D_1(line_addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid split line type, aborting: 0x%08X", (uint32_t)line_addr);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* PMS */
|
||||||
|
|
||||||
|
void esp_memprot_set_pms_lock(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_set_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_set_pms_lock();
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_set_pms_lock();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_pms_lock(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_get_pms_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_pms_lock();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_pms_lock();
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_iram_set_pms_area(pms_area_t area_type, bool r, bool w, bool x)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_set_pms_area(area:%s r:%u w:%u, x:%u)", esp_memprot_pms_to_str(area_type), r, w, x);
|
||||||
|
|
||||||
|
switch ( area_type ) {
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_0:
|
||||||
|
memprot_ll_iram0_set_pms_area_0(r, w, x);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_1:
|
||||||
|
memprot_ll_iram0_set_pms_area_1(r, w, x);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_2:
|
||||||
|
memprot_ll_iram0_set_pms_area_2(r, w, x);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_3:
|
||||||
|
memprot_ll_iram0_set_pms_area_3(r, w, x);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_iram_get_pms_area(pms_area_t area_type, bool *r, bool *w, bool *x)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_iram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
|
||||||
|
|
||||||
|
switch ( area_type ) {
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_0:
|
||||||
|
memprot_ll_iram0_get_pms_area_0(r, w, x);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_1:
|
||||||
|
memprot_ll_iram0_get_pms_area_1(r, w, x);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_2:
|
||||||
|
memprot_ll_iram0_get_pms_area_2(r, w, x);
|
||||||
|
break;
|
||||||
|
case MEMPROT_IRAM0_PMS_AREA_3:
|
||||||
|
memprot_ll_iram0_get_pms_area_3(r, w, x);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_dram_set_pms_area(pms_area_t area_type, bool r, bool w)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_set_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
|
||||||
|
|
||||||
|
switch ( area_type ) {
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_0:
|
||||||
|
memprot_ll_dram0_set_pms_area_0(r, w);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_1:
|
||||||
|
memprot_ll_dram0_set_pms_area_1(r, w);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_2:
|
||||||
|
memprot_ll_dram0_set_pms_area_2(r, w);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_3:
|
||||||
|
memprot_ll_dram0_set_pms_area_3(r, w);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_dram_get_pms_area(pms_area_t area_type, bool *r, bool *w)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_dram_get_pms_area(area:%s r:%u w:%u)", esp_memprot_pms_to_str(area_type), r, w);
|
||||||
|
|
||||||
|
switch ( area_type ) {
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_0:
|
||||||
|
memprot_ll_dram0_get_pms_area_0(r, w);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_1:
|
||||||
|
memprot_ll_dram0_get_pms_area_1(r, w);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_2:
|
||||||
|
memprot_ll_dram0_get_pms_area_2(r, w);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_PMS_AREA_3:
|
||||||
|
memprot_ll_dram0_get_pms_area_3(r, w);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid area_type %d", esp_memprot_pms_to_str(area_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* monitor */
|
||||||
|
|
||||||
|
void esp_memprot_set_monitor_lock(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_set_monitor_lock();
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_set_monitor_lock();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_monitor_lock(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_get_monitor_lock(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_lock();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_lock();
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_monitor_en(mem_type_prot_t mem_type, bool enable)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_set_monitor_en(enable);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_set_monitor_en(enable);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_monitor_en(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_set_monitor_en(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_en();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_en();
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_is_intr_ena_any()
|
||||||
|
{
|
||||||
|
return esp_memprot_get_monitor_en(MEMPROT_IRAM0_SRAM) || esp_memprot_get_monitor_en(MEMPROT_DRAM0_SRAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_monitor_clear_intr(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_monitor_clear_intr(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
memprot_ll_iram0_clear_monitor_intr();
|
||||||
|
memprot_ll_iram0_reset_clear_monitor_intr();
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
memprot_ll_dram0_clear_monitor_intr();
|
||||||
|
memprot_ll_dram0_reset_clear_monitor_intr();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_type_prot_t esp_memprot_get_active_intr_memtype()
|
||||||
|
{
|
||||||
|
if ( memprot_ll_iram0_get_monitor_status_intr() > 0 ) {
|
||||||
|
return MEMPROT_IRAM0_SRAM;
|
||||||
|
} else if ( memprot_ll_dram0_get_monitor_status_intr() ) {
|
||||||
|
return MEMPROT_DRAM0_SRAM;
|
||||||
|
}
|
||||||
|
|
||||||
|
return MEMPROT_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_is_locked_any()
|
||||||
|
{
|
||||||
|
return
|
||||||
|
esp_memprot_get_split_line_lock() ||
|
||||||
|
esp_memprot_get_pms_lock(MEMPROT_IRAM0_SRAM) ||
|
||||||
|
esp_memprot_get_pms_lock(MEMPROT_DRAM0_SRAM) ||
|
||||||
|
esp_memprot_get_monitor_lock(MEMPROT_IRAM0_SRAM) ||
|
||||||
|
esp_memprot_get_monitor_lock(MEMPROT_DRAM0_SRAM);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_violate_intr_on(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_status_intr() == 1;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_intr() == 1;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_violate_addr(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_status_fault_addr();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_fault_addr();
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pms_world_t esp_memprot_get_violate_world(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
uint32_t world = 0;
|
||||||
|
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
world = memprot_ll_iram0_get_monitor_status_fault_world();
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
world = memprot_ll_dram0_get_monitor_status_fault_world();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ( world ) {
|
||||||
|
case 0x01: return MEMPROT_PMS_WORLD_0;
|
||||||
|
case 0x10: return MEMPROT_PMS_WORLD_1;
|
||||||
|
default: return MEMPROT_PMS_WORLD_INVALID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pms_operation_type_t esp_memprot_get_violate_wr(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_fault_wr() == 1 ? MEMPROT_PMS_OP_WRITE : MEMPROT_PMS_OP_READ;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool esp_memprot_get_violate_loadstore(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_status_fault_loadstore() == 1;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_violate_byte_en(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch ( mem_type ) {
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_status_fault_byte_en();
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int esp_memprot_intr_get_cpuid()
|
||||||
|
{
|
||||||
|
return PRO_CPU_NUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_intr_matrix(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_set_intr_matrix(%s)", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
|
||||||
|
ESP_INTR_DISABLE(ETS_MEMPROT_ERR_INUM);
|
||||||
|
|
||||||
|
switch (mem_type) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_iram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
|
||||||
|
break;
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
intr_matrix_set(esp_memprot_intr_get_cpuid(), memprot_ll_dram0_get_intr_source_num(), ETS_MEMPROT_ERR_INUM);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ESP_EARLY_LOGE(TAG, "Invalid mem_type (%s), aborting", esp_memprot_mem_type_to_str(mem_type));
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the type and priority to cache error interrupts. */
|
||||||
|
esprv_intc_int_set_type(BIT(ETS_MEMPROT_ERR_INUM), INTR_TYPE_LEVEL);
|
||||||
|
esprv_intc_int_set_priority(ETS_MEMPROT_ERR_INUM, SOC_INTERRUPT_LEVEL_MEDIUM);
|
||||||
|
|
||||||
|
ESP_INTR_ENABLE(ETS_MEMPROT_ERR_INUM);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_prot(bool invoke_panic_handler, bool lock_feature, uint32_t *mem_type_mask)
|
||||||
|
{
|
||||||
|
esp_memprot_set_prot_int(invoke_panic_handler, lock_feature, NULL, mem_type_mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_memprot_set_prot_int(bool invoke_panic_handler, bool lock_feature, void *split_addr, uint32_t *mem_type_mask)
|
||||||
|
{
|
||||||
|
ESP_EARLY_LOGD(TAG, "esp_memprot_set_prot(panic_handler: %u, lock: %u, split.addr: 0x%08X, mem.types: 0x%08X", invoke_panic_handler, lock_feature, (uint32_t)split_addr, (uint32_t)mem_type_mask);
|
||||||
|
|
||||||
|
uint32_t required_mem_prot = mem_type_mask == NULL ? (uint32_t)MEMPROT_ALL : *mem_type_mask;
|
||||||
|
bool use_iram0 = required_mem_prot & MEMPROT_IRAM0_SRAM;
|
||||||
|
bool use_dram0 = required_mem_prot & MEMPROT_DRAM0_SRAM;
|
||||||
|
|
||||||
|
if (required_mem_prot == MEMPROT_NONE) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//disable protection
|
||||||
|
if (use_iram0) {
|
||||||
|
esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, false);
|
||||||
|
}
|
||||||
|
if (use_dram0) {
|
||||||
|
esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//panic handling
|
||||||
|
if (invoke_panic_handler) {
|
||||||
|
if (use_iram0) {
|
||||||
|
esp_memprot_set_intr_matrix(MEMPROT_IRAM0_SRAM);
|
||||||
|
}
|
||||||
|
if (use_dram0) {
|
||||||
|
esp_memprot_set_intr_matrix(MEMPROT_DRAM0_SRAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//set split lines (must-have for all mem_types)
|
||||||
|
const void *line_addr = split_addr == NULL ? esp_memprot_get_default_main_split_addr() : split_addr;
|
||||||
|
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_1_SPLITLINE, line_addr);
|
||||||
|
esp_memprot_set_split_line(MEMPROT_IRAM0_LINE_0_SPLITLINE, line_addr);
|
||||||
|
esp_memprot_set_split_line(MEMPROT_IRAM0_DRAM0_SPLITLINE, line_addr);
|
||||||
|
esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_0_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
|
||||||
|
esp_memprot_set_split_line(MEMPROT_DRAM0_DMA_LINE_1_SPLITLINE, (void *)(MAP_IRAM_TO_DRAM((uint32_t)line_addr)));
|
||||||
|
|
||||||
|
//set permissions
|
||||||
|
if (required_mem_prot & MEMPROT_IRAM0_SRAM) {
|
||||||
|
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_0, true, false, true);
|
||||||
|
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_1, true, false, true);
|
||||||
|
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_2, true, false, true);
|
||||||
|
esp_memprot_iram_set_pms_area(MEMPROT_IRAM0_PMS_AREA_3, true, true, false);
|
||||||
|
}
|
||||||
|
if (required_mem_prot & MEMPROT_DRAM0_SRAM) {
|
||||||
|
esp_memprot_dram_set_pms_area( MEMPROT_DRAM0_PMS_AREA_0, true, false );
|
||||||
|
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_1, true, true);
|
||||||
|
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_2, true, true);
|
||||||
|
esp_memprot_dram_set_pms_area(MEMPROT_DRAM0_PMS_AREA_3, true, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//reenable protection
|
||||||
|
if (use_iram0) {
|
||||||
|
esp_memprot_monitor_clear_intr(MEMPROT_IRAM0_SRAM);
|
||||||
|
esp_memprot_set_monitor_en(MEMPROT_IRAM0_SRAM, true);
|
||||||
|
}
|
||||||
|
if (use_dram0) {
|
||||||
|
esp_memprot_monitor_clear_intr(MEMPROT_DRAM0_SRAM);
|
||||||
|
esp_memprot_set_monitor_en(MEMPROT_DRAM0_SRAM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//lock if required
|
||||||
|
if (lock_feature) {
|
||||||
|
esp_memprot_set_split_line_lock();
|
||||||
|
if (use_iram0) {
|
||||||
|
esp_memprot_set_pms_lock(MEMPROT_IRAM0_SRAM);
|
||||||
|
esp_memprot_set_monitor_lock(MEMPROT_IRAM0_SRAM);
|
||||||
|
}
|
||||||
|
if (use_dram0) {
|
||||||
|
esp_memprot_set_pms_lock(MEMPROT_DRAM0_SRAM);
|
||||||
|
esp_memprot_set_monitor_lock(MEMPROT_DRAM0_SRAM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_dram_status_reg_1()
|
||||||
|
{
|
||||||
|
return memprot_ll_dram0_get_monitor_status_register_1();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_dram_status_reg_2()
|
||||||
|
{
|
||||||
|
return memprot_ll_dram0_get_monitor_status_register_2();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_iram_status_reg()
|
||||||
|
{
|
||||||
|
return memprot_ll_iram0_get_monitor_status_register();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_memprot_get_monitor_enable_reg(mem_type_prot_t mem_type)
|
||||||
|
{
|
||||||
|
switch (mem_type) {
|
||||||
|
case MEMPROT_IRAM0_SRAM:
|
||||||
|
return memprot_ll_iram0_get_monitor_enable_register();
|
||||||
|
case MEMPROT_DRAM0_SRAM:
|
||||||
|
return memprot_ll_dram0_get_monitor_enable_register();
|
||||||
|
default:
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
5
components/esp32h2/project_include.cmake
Normal file
5
components/esp32h2/project_include.cmake
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
set(compile_options "-Wno-error=format="
|
||||||
|
"-nostartfiles"
|
||||||
|
"-Wno-format")
|
||||||
|
|
||||||
|
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
|
9
components/esp32h2/test/CMakeLists.txt
Normal file
9
components/esp32h2/test/CMakeLists.txt
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
if(IDF_TARGET STREQUAL "esp32h2")
|
||||||
|
idf_component_register(SRC_DIRS .
|
||||||
|
INCLUDE_DIRS . ${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
REQUIRES unity test_utils esp_common mbedtls
|
||||||
|
)
|
||||||
|
|
||||||
|
idf_build_set_property(COMPILE_DEFINITIONS "-DESP_TIMER_DYNAMIC_OVERFLOW_VAL" APPEND)
|
||||||
|
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u ld_include_test_dport_xt_highint5")
|
||||||
|
endif()
|
4
components/esp32h2/test/component.mk
Normal file
4
components/esp32h2/test/component.mk
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
#
|
||||||
|
# Component Makefile (not used for tests, but CI checks test parity between GNU Make & CMake)
|
||||||
|
#
|
||||||
|
COMPONENT_CONFIG_ONLY := 1
|
166
components/esp32h2/test/digital_signature_test_cases.h
Normal file
166
components/esp32h2/test/digital_signature_test_cases.h
Normal file
File diff suppressed because one or more lines are too long
382
components/esp32h2/test/test_ds.c
Normal file
382
components/esp32h2/test/test_ds.c
Normal file
@@ -0,0 +1,382 @@
|
|||||||
|
// 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 "unity.h"
|
||||||
|
#include "esp32h2/rom/efuse.h"
|
||||||
|
#include "esp32h2/rom/digital_signature.h"
|
||||||
|
#include "esp32h2/rom/hmac.h"
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "esp_ds.h"
|
||||||
|
|
||||||
|
#define NUM_RESULTS 10
|
||||||
|
#define DS_MAX_BITS (ETS_DS_MAX_BITS)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint8_t iv[ETS_DS_IV_LEN];
|
||||||
|
ets_ds_p_data_t p_data;
|
||||||
|
uint8_t expected_c[ETS_DS_C_LEN];
|
||||||
|
uint8_t hmac_key_idx;
|
||||||
|
uint32_t expected_results[NUM_RESULTS][DS_MAX_BITS/32];
|
||||||
|
} encrypt_testcase_t;
|
||||||
|
|
||||||
|
// Generated header (components/esp32s2/test/gen_digital_signature_tests.py) defines
|
||||||
|
// NUM_HMAC_KEYS, test_hmac_keys, NUM_MESSAGES, NUM_CASES, test_messages[], test_cases[]
|
||||||
|
#include "digital_signature_test_cases.h"
|
||||||
|
|
||||||
|
_Static_assert(NUM_RESULTS == NUM_MESSAGES, "expected_results size should be the same as NUM_MESSAGES in generated header");
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Parameter Encryption data NULL", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
const char iv [32];
|
||||||
|
esp_ds_p_data_t p_data;
|
||||||
|
const char key [32];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(NULL, iv, &p_data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Parameter Encryption iv NULL", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t data;
|
||||||
|
esp_ds_p_data_t p_data;
|
||||||
|
const char key [32];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, NULL, &p_data, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Parameter Encryption p_data NULL", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t data;
|
||||||
|
const char iv [32];
|
||||||
|
const char key [32];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, NULL, key));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Parameter Encryption key NULL", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t data;
|
||||||
|
const char iv [32];
|
||||||
|
esp_ds_p_data_t p_data;
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_encrypt_params(&data, iv, &p_data, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Parameter Encryption", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
for (int i = 0; i < NUM_CASES; i++) {
|
||||||
|
printf("Encrypting test case %d...\n", i);
|
||||||
|
const encrypt_testcase_t *t = &test_cases[i];
|
||||||
|
esp_ds_data_t result = { };
|
||||||
|
esp_ds_p_data_t p_data;
|
||||||
|
|
||||||
|
memcpy(p_data.Y, t->p_data.Y, ESP_DS_SIGNATURE_MAX_BIT_LEN/8);
|
||||||
|
memcpy(p_data.M, t->p_data.M, ESP_DS_SIGNATURE_MAX_BIT_LEN/8);
|
||||||
|
memcpy(p_data.Rb, t->p_data.Rb, ESP_DS_SIGNATURE_MAX_BIT_LEN/8);
|
||||||
|
p_data.M_prime = t->p_data.M_prime;
|
||||||
|
p_data.length = t->p_data.length;
|
||||||
|
|
||||||
|
esp_err_t r = esp_ds_encrypt_params(&result, t->iv, &p_data,
|
||||||
|
test_hmac_keys[t->hmac_key_idx]);
|
||||||
|
printf("Encrypting test case %d done\n", i);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, r);
|
||||||
|
TEST_ASSERT_EQUAL(t->p_data.length, result.rsa_length);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->iv, result.iv, ETS_DS_IV_LEN);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_c, result.c, ETS_DS_C_LEN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature start Invalid message", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = { };
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
esp_ds_context_t *ctx;
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(NULL, &ds_data, HMAC_KEY1, &ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature start Invalid data", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
const char *message = "test";
|
||||||
|
esp_ds_context_t *ctx;
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, NULL, HMAC_KEY1, &ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature start Invalid context", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
const char *message = "test";
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature RSA length 0", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = 0;
|
||||||
|
const char *message = "test";
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature RSA length too long", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = 128;
|
||||||
|
const char *message = "test";
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY1, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature start HMAC key out of range", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
esp_ds_context_t *ctx;
|
||||||
|
const char *message = "test";
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY5 + 1, &ctx));
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_start_sign(message, &ds_data, HMAC_KEY0 - 1, &ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature finish Invalid signature ptr", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_context_t *ctx = NULL;
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(NULL, ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature finish Invalid context", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_finish_sign(signature_data, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking Invalid message", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = { };
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(NULL, &ds_data, HMAC_KEY1, signature_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking Invalid data", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
const char *message = "test";
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, NULL, HMAC_KEY1, signature_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking Invalid signature ptr", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
const char *message = "test";
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking RSA length 0", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = 0;
|
||||||
|
const char *message = "test";
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking RSA length too long", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = 128;
|
||||||
|
const char *message = "test";
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY1, signature_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking HMAC key out of range", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = 127;
|
||||||
|
const char *message = "test";
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY5 + 1, signature_data));
|
||||||
|
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, esp_ds_sign(message, &ds_data, HMAC_KEY0 - 1, signature_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_IDF_ENV_FPGA
|
||||||
|
|
||||||
|
// Burn eFuse blocks 1, 2 and 3. Block 0 is used for HMAC tests already.
|
||||||
|
static void burn_hmac_keys(void)
|
||||||
|
{
|
||||||
|
printf("Burning %d HMAC keys to efuse...\n", NUM_HMAC_KEYS);
|
||||||
|
for (int i = 0; i < NUM_HMAC_KEYS; i++) {
|
||||||
|
// TODO: vary the purpose across the keys
|
||||||
|
ets_efuse_purpose_t purpose = ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE;
|
||||||
|
ets_efuse_write_key(ETS_EFUSE_BLOCK_KEY1 + i,
|
||||||
|
purpose,
|
||||||
|
test_hmac_keys[i], 32);
|
||||||
|
}
|
||||||
|
/* verify the keys are what we expect (possibly they're already burned, doesn't matter but they have to match) */
|
||||||
|
uint8_t block_compare[32];
|
||||||
|
for (int i = 0; i < NUM_HMAC_KEYS; i++) {
|
||||||
|
printf("Checking key %d...\n", i);
|
||||||
|
memcpy(block_compare, (void *)ets_efuse_get_read_register_address(ETS_EFUSE_BLOCK_KEY1 + i), 32);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(test_hmac_keys[i], block_compare, 32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
|
||||||
|
// HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
|
||||||
|
TEST_CASE("Digital Signature wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
esp_ds_context_t *ctx;
|
||||||
|
const char *message = "test";
|
||||||
|
|
||||||
|
// HMAC fails in that case because it checks for the correct purpose
|
||||||
|
TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_start_sign(message, &ds_data, HMAC_KEY0, &ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
// This test uses the HMAC_KEY0 eFuse key which hasn't been burned by burn_hmac_keys().
|
||||||
|
// HMAC_KEY0 is usually used for HMAC upstream (user access) tests.
|
||||||
|
TEST_CASE("Digital Signature Blocking wrong HMAC key purpose (FPGA only)", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
esp_ds_data_t ds_data = {};
|
||||||
|
ds_data.rsa_length = ESP_DS_RSA_3072;
|
||||||
|
const char *message = "test";
|
||||||
|
uint8_t signature_data [128 * 4];
|
||||||
|
|
||||||
|
// HMAC fails in that case because it checks for the correct purpose
|
||||||
|
TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_HMAC_FAIL, esp_ds_sign(message, &ds_data, HMAC_KEY0, signature_data));
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Operation (FPGA only)", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
burn_hmac_keys();
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_CASES; i++) {
|
||||||
|
printf("Running test case %d...\n", i);
|
||||||
|
const encrypt_testcase_t *t = &test_cases[i];
|
||||||
|
|
||||||
|
// copy encrypt parameter test case into ds_data structure
|
||||||
|
esp_ds_data_t ds_data = { };
|
||||||
|
memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
|
||||||
|
memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
|
||||||
|
ds_data.rsa_length = t->p_data.length;
|
||||||
|
|
||||||
|
for (int j = 0; j < NUM_MESSAGES; j++) {
|
||||||
|
uint8_t signature[DS_MAX_BITS/8] = { 0 };
|
||||||
|
printf(" ... message %d\n", j);
|
||||||
|
|
||||||
|
esp_ds_context_t *esp_ds_ctx;
|
||||||
|
esp_err_t ds_r = esp_ds_start_sign(test_messages[j],
|
||||||
|
&ds_data,
|
||||||
|
t->hmac_key_idx + 1,
|
||||||
|
&esp_ds_ctx);
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
|
||||||
|
|
||||||
|
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[j], signature, sizeof(signature));
|
||||||
|
}
|
||||||
|
|
||||||
|
ets_hmac_invalidate_downstream(ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Blocking Operation (FPGA only)", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
burn_hmac_keys();
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_CASES; i++) {
|
||||||
|
printf("Running test case %d...\n", i);
|
||||||
|
const encrypt_testcase_t *t = &test_cases[i];
|
||||||
|
|
||||||
|
// copy encrypt parameter test case into ds_data structure
|
||||||
|
esp_ds_data_t ds_data = { };
|
||||||
|
memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
|
||||||
|
memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
|
||||||
|
ds_data.rsa_length = t->p_data.length;
|
||||||
|
|
||||||
|
uint8_t signature[DS_MAX_BITS/8] = { 0 };
|
||||||
|
|
||||||
|
esp_err_t ds_r = esp_ds_sign(test_messages[0],
|
||||||
|
&ds_data,
|
||||||
|
t->hmac_key_idx + 1,
|
||||||
|
signature);
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(t->expected_results[0], signature, sizeof(signature));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Digital Signature Invalid Data (FPGA only)", "[hw_crypto] [ds]")
|
||||||
|
{
|
||||||
|
burn_hmac_keys();
|
||||||
|
|
||||||
|
// Set up a valid test case
|
||||||
|
const encrypt_testcase_t *t = &test_cases[0];
|
||||||
|
esp_ds_data_t ds_data = { };
|
||||||
|
memcpy(ds_data.iv, t->iv, ETS_DS_IV_LEN);
|
||||||
|
memcpy(ds_data.c, t->expected_c, ETS_DS_C_LEN);
|
||||||
|
ds_data.rsa_length = t->p_data.length;
|
||||||
|
|
||||||
|
uint8_t signature[DS_MAX_BITS/8] = { 0 };
|
||||||
|
const uint8_t zero[DS_MAX_BITS/8] = { 0 };
|
||||||
|
|
||||||
|
// Corrupt the IV one bit at a time, rerun and expect failure
|
||||||
|
for (int bit = 0; bit < 128; bit++) {
|
||||||
|
printf("Corrupting IV bit %d...\n", bit);
|
||||||
|
ds_data.iv[bit / 8] ^= 1 << (bit % 8);
|
||||||
|
esp_ds_context_t *esp_ds_ctx;
|
||||||
|
|
||||||
|
esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
|
||||||
|
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
|
||||||
|
TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8);
|
||||||
|
|
||||||
|
ds_data.iv[bit / 8] ^= 1 << (bit % 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Corrupt encrypted key data one bit at a time, rerun and expect failure
|
||||||
|
printf("Corrupting C...\n");
|
||||||
|
for (int bit = 0; bit < ETS_DS_C_LEN * 8; bit++) {
|
||||||
|
printf("Corrupting C bit %d...\n", bit);
|
||||||
|
ds_data.c[bit / 8] ^= 1 << (bit % 8);
|
||||||
|
esp_ds_context_t *esp_ds_ctx;
|
||||||
|
|
||||||
|
esp_err_t ds_r = esp_ds_start_sign(test_messages[0], &ds_data, t->hmac_key_idx + 1, &esp_ds_ctx);
|
||||||
|
TEST_ASSERT_EQUAL(ESP_OK, ds_r);
|
||||||
|
ds_r = esp_ds_finish_sign(signature, esp_ds_ctx);
|
||||||
|
TEST_ASSERT_EQUAL(ESP32H2_ERR_HW_CRYPTO_DS_INVALID_DIGEST, ds_r);
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(zero, signature, DS_MAX_BITS/8);
|
||||||
|
|
||||||
|
ds_data.c[bit / 8] ^= 1 << (bit % 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // CONFIG_IDF_ENV_FPGA
|
80
components/esp32h2/test/test_sha.c
Normal file
80
components/esp32h2/test/test_sha.c
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_types.h"
|
||||||
|
#include "esp32h2/clk.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_timer.h"
|
||||||
|
#include "esp_heap_caps.h"
|
||||||
|
#include "idf_performance.h"
|
||||||
|
|
||||||
|
#include "unity.h"
|
||||||
|
#include "test_utils.h"
|
||||||
|
#include "mbedtls/sha1.h"
|
||||||
|
#include "mbedtls/sha256.h"
|
||||||
|
#include "sha/sha_dma.h"
|
||||||
|
|
||||||
|
/* Note: Most of the SHA functions are called as part of mbedTLS, so
|
||||||
|
are tested as part of mbedTLS tests. Only esp_sha() is different.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define TAG "sha_test"
|
||||||
|
|
||||||
|
TEST_CASE("Test esp_sha()", "[hw_crypto]")
|
||||||
|
{
|
||||||
|
const size_t BUFFER_SZ = 32 * 1024 + 6; // NB: not an exact multiple of SHA block size
|
||||||
|
|
||||||
|
int64_t begin, end;
|
||||||
|
uint32_t us_sha1;
|
||||||
|
uint8_t sha1_result[20] = { 0 };
|
||||||
|
void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
||||||
|
TEST_ASSERT_NOT_NULL(buffer);
|
||||||
|
memset(buffer, 0xEE, BUFFER_SZ);
|
||||||
|
|
||||||
|
const uint8_t sha1_expected[20] = { 0xc7, 0xbb, 0xd3, 0x74, 0xf2, 0xf6, 0x20, 0x86,
|
||||||
|
0x61, 0xf4, 0x50, 0xd5, 0xf5, 0x18, 0x44, 0xcc,
|
||||||
|
0x7a, 0xb7, 0xa5, 0x4a };
|
||||||
|
|
||||||
|
begin = esp_timer_get_time();
|
||||||
|
esp_sha(SHA1, buffer, BUFFER_SZ, sha1_result);
|
||||||
|
end = esp_timer_get_time();
|
||||||
|
TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, sha1_result, sizeof(sha1_expected));
|
||||||
|
us_sha1 = end - begin;
|
||||||
|
ESP_LOGI(TAG, "esp_sha() 32KB SHA1 in %u us", us_sha1);
|
||||||
|
|
||||||
|
free(buffer);
|
||||||
|
|
||||||
|
TEST_PERFORMANCE_CCOMP_LESS_THAN(TIME_SHA1_32KB, "%dus", us_sha1);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]")
|
||||||
|
{
|
||||||
|
const void* ptr;
|
||||||
|
spi_flash_mmap_handle_t handle;
|
||||||
|
uint8_t sha1_espsha[20] = { 0 };
|
||||||
|
uint8_t sha1_mbedtls[20] = { 0 };
|
||||||
|
uint8_t sha256_espsha[32] = { 0 };
|
||||||
|
uint8_t sha256_mbedtls[32] = { 0 };
|
||||||
|
|
||||||
|
const size_t LEN = 1024 * 1024;
|
||||||
|
|
||||||
|
/* mmap() 1MB of flash, we don't care what it is really */
|
||||||
|
esp_err_t err = spi_flash_mmap(0x0, LEN, SPI_FLASH_MMAP_DATA, &ptr, &handle);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_HEX32(ESP_OK, err);
|
||||||
|
TEST_ASSERT_NOT_NULL(ptr);
|
||||||
|
|
||||||
|
/* Compare esp_sha() result to the mbedTLS result, should always be the same */
|
||||||
|
|
||||||
|
esp_sha(SHA1, ptr, LEN, sha1_espsha);
|
||||||
|
int r = mbedtls_sha1_ret(ptr, LEN, sha1_mbedtls);
|
||||||
|
TEST_ASSERT_EQUAL(0, r);
|
||||||
|
|
||||||
|
esp_sha(SHA2_256, ptr, LEN, sha256_espsha);
|
||||||
|
r = mbedtls_sha256_ret(ptr, LEN, sha256_mbedtls, 0);
|
||||||
|
TEST_ASSERT_EQUAL(0, r);
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_espsha, sha1_mbedtls, sizeof(sha1_espsha), "SHA1 results should match");
|
||||||
|
|
||||||
|
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_espsha, sha256_mbedtls, sizeof(sha256_espsha), "SHA256 results should match");
|
||||||
|
}
|
@@ -14,4 +14,9 @@ elseif(${target} STREQUAL "esp32c3")
|
|||||||
idf_component_register(SRCS "esp_adc_cal_esp32c3.c"
|
idf_component_register(SRCS "esp_adc_cal_esp32c3.c"
|
||||||
INCLUDE_DIRS "include"
|
INCLUDE_DIRS "include"
|
||||||
REQUIRES driver efuse)
|
REQUIRES driver efuse)
|
||||||
|
|
||||||
|
elseif(${target} STREQUAL "esp32h2")
|
||||||
|
idf_component_register(SRCS "esp_adc_cal_esp32h2.c"
|
||||||
|
INCLUDE_DIRS "include"
|
||||||
|
REQUIRES driver efuse)
|
||||||
endif()
|
endif()
|
||||||
|
@@ -3,4 +3,4 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
COMPONENT_ADD_INCLUDEDIRS := include
|
COMPONENT_ADD_INCLUDEDIRS := include
|
||||||
COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o
|
COMPONENT_OBJEXCLUDE += esp_adc_cal_esp32s2.o esp_adc_cal_esp32c3.o esp_adc_cal_esp32h2.o
|
||||||
|
170
components/esp_adc_cal/esp_adc_cal_esp32h2.c
Normal file
170
components/esp_adc_cal/esp_adc_cal_esp32h2.c
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_types.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "driver/adc.h"
|
||||||
|
#include "hal/adc_ll.h"
|
||||||
|
#include "esp_efuse_rtc_calib.h"
|
||||||
|
#include "esp_adc_cal.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define ADC_CALIB_CHECK(cond, err_msg, ret) do {\
|
||||||
|
if (!(cond)) { \
|
||||||
|
ESP_LOGE(LOG_TAG, err_msg); \
|
||||||
|
return (ret); \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
|
const static char LOG_TAG[] = "adc_calib";
|
||||||
|
|
||||||
|
|
||||||
|
/* ------------------------ Characterization Constants ---------------------- */
|
||||||
|
|
||||||
|
// coeff_a and coeff_b are actually floats
|
||||||
|
// they are scaled to put them into uint32_t so that the headers do not have to be changed
|
||||||
|
static const int coeff_a_scaling = 65536;
|
||||||
|
static const int coeff_b_scaling = 1024;
|
||||||
|
/* -------------------- Characterization Helper Data Types ------------------ */
|
||||||
|
typedef struct {
|
||||||
|
uint32_t voltage;
|
||||||
|
uint32_t digi;
|
||||||
|
} adc_calib_data_ver1;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char version_num;
|
||||||
|
adc_unit_t adc_num;
|
||||||
|
adc_atten_t atten_level;
|
||||||
|
union {
|
||||||
|
adc_calib_data_ver1 ver1;
|
||||||
|
} efuse_data;
|
||||||
|
} adc_calib_parsed_info;
|
||||||
|
|
||||||
|
static esp_err_t prepare_calib_data_for(int version_num, adc_unit_t adc_num, adc_atten_t atten, adc_calib_parsed_info *parsed_data_storage)
|
||||||
|
{
|
||||||
|
assert(version_num == 1);
|
||||||
|
esp_err_t ret;
|
||||||
|
|
||||||
|
parsed_data_storage->version_num = version_num;
|
||||||
|
parsed_data_storage->adc_num = adc_num;
|
||||||
|
parsed_data_storage->atten_level = atten;
|
||||||
|
// V1 we don't have calibration data for ADC2, using the efuse data of ADC1
|
||||||
|
uint32_t voltage, digi;
|
||||||
|
ret = esp_efuse_rtc_calib_get_cal_voltage(version_num, atten, &digi, &voltage);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
parsed_data_storage->efuse_data.ver1.voltage = voltage;
|
||||||
|
parsed_data_storage->efuse_data.ver1.digi = digi;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------- Characterization Functions ----------------------- */
|
||||||
|
/*
|
||||||
|
* Estimate the (assumed) linear relationship btwn the measured raw value and the voltage
|
||||||
|
* with the previously done measurement when the chip was manufactured.
|
||||||
|
*/
|
||||||
|
static void calculate_characterization_coefficients(const adc_calib_parsed_info *parsed_data, esp_adc_cal_characteristics_t *chars)
|
||||||
|
{
|
||||||
|
ESP_LOGD(LOG_TAG, "Calib V1, Cal Voltage = %d, Digi out = %d\n", parsed_data->efuse_data.ver1.voltage, parsed_data->efuse_data.ver1.digi);
|
||||||
|
|
||||||
|
chars->coeff_a = coeff_a_scaling * parsed_data->efuse_data.ver1.voltage / parsed_data->efuse_data.ver1.digi;
|
||||||
|
chars->coeff_b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------- Public API ------------------------------------- */
|
||||||
|
esp_err_t esp_adc_cal_check_efuse(esp_adc_cal_value_t source)
|
||||||
|
{
|
||||||
|
if (source != ESP_ADC_CAL_VAL_EFUSE_TP) {
|
||||||
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
|
}
|
||||||
|
uint8_t adc_encoding_version = esp_efuse_rtc_calib_get_ver();
|
||||||
|
if (adc_encoding_version != 1) {
|
||||||
|
// current version only accepts encoding ver 1.
|
||||||
|
return ESP_ERR_INVALID_VERSION;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_adc_cal_value_t esp_adc_cal_characterize(adc_unit_t adc_num,
|
||||||
|
adc_atten_t atten,
|
||||||
|
adc_bits_width_t bit_width,
|
||||||
|
uint32_t default_vref,
|
||||||
|
esp_adc_cal_characteristics_t *chars)
|
||||||
|
{
|
||||||
|
esp_err_t ret;
|
||||||
|
adc_calib_parsed_info efuse_parsed_data = {0};
|
||||||
|
// Check parameters
|
||||||
|
ADC_CALIB_CHECK(adc_num == ADC_UNIT_1 || adc_num == ADC_UNIT_2, "Invalid unit num", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
|
||||||
|
ADC_CALIB_CHECK(chars != NULL, "Invalid characteristic", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
|
||||||
|
ADC_CALIB_CHECK(bit_width == ADC_WIDTH_BIT_12, "Invalid bit_width", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
|
||||||
|
ADC_CALIB_CHECK(atten < 4, "Invalid attenuation", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
|
||||||
|
|
||||||
|
int version_num = esp_efuse_rtc_calib_get_ver();
|
||||||
|
ADC_CALIB_CHECK(version_num == 1, "No calibration efuse burnt", ESP_ADC_CAL_VAL_NOT_SUPPORTED);
|
||||||
|
|
||||||
|
memset(chars, 0, sizeof(esp_adc_cal_characteristics_t));
|
||||||
|
|
||||||
|
// make sure adc is calibrated.
|
||||||
|
ret = prepare_calib_data_for(version_num, adc_num, atten, &efuse_parsed_data);
|
||||||
|
if (ret != ESP_OK) {
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
calculate_characterization_coefficients(&efuse_parsed_data, chars);
|
||||||
|
ESP_LOGD(LOG_TAG, "adc%d (atten leven %d) calibration done: A:%d B:%d\n", adc_num, atten, chars->coeff_a, chars->coeff_b);
|
||||||
|
|
||||||
|
// Initialize remaining fields
|
||||||
|
chars->adc_num = adc_num;
|
||||||
|
chars->atten = atten;
|
||||||
|
chars->bit_width = bit_width;
|
||||||
|
|
||||||
|
// in esp32h2 we only use the two point method to calibrate the adc.
|
||||||
|
return ESP_ADC_CAL_VAL_EFUSE_TP;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t esp_adc_cal_raw_to_voltage(uint32_t adc_reading, const esp_adc_cal_characteristics_t *chars)
|
||||||
|
{
|
||||||
|
ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
return adc_reading * chars->coeff_a / coeff_a_scaling + chars->coeff_b / coeff_b_scaling;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_adc_cal_get_voltage(adc_channel_t channel,
|
||||||
|
const esp_adc_cal_characteristics_t *chars,
|
||||||
|
uint32_t *voltage)
|
||||||
|
{
|
||||||
|
// Check parameters
|
||||||
|
ADC_CALIB_CHECK(chars != NULL, "No characteristic input.", ESP_ERR_INVALID_ARG);
|
||||||
|
ADC_CALIB_CHECK(voltage != NULL, "No output buffer.", ESP_ERR_INVALID_ARG);
|
||||||
|
|
||||||
|
int adc_reading;
|
||||||
|
if (chars->adc_num == ADC_UNIT_1) {
|
||||||
|
//Check if channel is valid on ADC1
|
||||||
|
ADC_CALIB_CHECK((adc1_channel_t)channel < ADC1_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG);
|
||||||
|
adc_reading = adc1_get_raw(channel);
|
||||||
|
} else {
|
||||||
|
//Check if channel is valid on ADC2
|
||||||
|
ADC_CALIB_CHECK((adc2_channel_t)channel < ADC2_CHANNEL_MAX, "Invalid channel", ESP_ERR_INVALID_ARG);
|
||||||
|
if (adc2_get_raw(channel, chars->bit_width, &adc_reading) != ESP_OK) {
|
||||||
|
return ESP_ERR_TIMEOUT; //Timed out waiting for ADC2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*voltage = esp_adc_cal_raw_to_voltage((uint32_t)adc_reading, chars);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
@@ -28,6 +28,7 @@ esp_err_t esp_event_send_noop(system_event_t *event)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP32_WIFI_ENABLED
|
||||||
static system_event_id_t esp_event_legacy_wifi_event_id(int32_t event_id)
|
static system_event_id_t esp_event_legacy_wifi_event_id(int32_t event_id)
|
||||||
{
|
{
|
||||||
switch (event_id) {
|
switch (event_id) {
|
||||||
@@ -102,6 +103,7 @@ static system_event_id_t esp_event_legacy_wifi_event_id(int32_t event_id)
|
|||||||
return SYSTEM_EVENT_MAX;
|
return SYSTEM_EVENT_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // CONFIG_ESP32_WIFI_ENABLED
|
||||||
|
|
||||||
static system_event_id_t esp_event_legacy_ip_event_id(int32_t event_id)
|
static system_event_id_t esp_event_legacy_ip_event_id(int32_t event_id)
|
||||||
{
|
{
|
||||||
@@ -133,9 +135,13 @@ static system_event_id_t esp_event_legacy_ip_event_id(int32_t event_id)
|
|||||||
|
|
||||||
static system_event_id_t esp_event_legacy_event_id(esp_event_base_t event_base, int32_t event_id)
|
static system_event_id_t esp_event_legacy_event_id(esp_event_base_t event_base, int32_t event_id)
|
||||||
{
|
{
|
||||||
|
#if CONFIG_ESP32_WIFI_ENABLED
|
||||||
if (event_base == WIFI_EVENT) {
|
if (event_base == WIFI_EVENT) {
|
||||||
return esp_event_legacy_wifi_event_id(event_id);
|
return esp_event_legacy_wifi_event_id(event_id);
|
||||||
} else if (event_base == IP_EVENT) {
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (event_base == IP_EVENT) {
|
||||||
return esp_event_legacy_ip_event_id(event_id);
|
return esp_event_legacy_ip_event_id(event_id);
|
||||||
} else {
|
} else {
|
||||||
ESP_LOGE(TAG, "invalid event base %s", event_base);
|
ESP_LOGE(TAG, "invalid event base %s", event_base);
|
||||||
|
124
components/esp_gdbstub/esp32h2/gdbstub_esp32h2.c
Normal file
124
components/esp_gdbstub/esp32h2/gdbstub_esp32h2.c
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
// 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 "soc/uart_periph.h"
|
||||||
|
#include "soc/gpio_periph.h"
|
||||||
|
#include "soc/soc.h"
|
||||||
|
#include "soc/usb_serial_jtag_struct.h"
|
||||||
|
#include "hal/usb_serial_jtag_ll.h"
|
||||||
|
#include "esp_gdbstub_common.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
|
#define UART_NUM CONFIG_ESP_CONSOLE_UART_NUM
|
||||||
|
|
||||||
|
#define GDBSTUB_MEM_REGION_COUNT 9
|
||||||
|
|
||||||
|
#define UART_REG_FIELD_LEN 0x84
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
intptr_t lower;
|
||||||
|
intptr_t upper;
|
||||||
|
} mem_bound_t;
|
||||||
|
|
||||||
|
static const mem_bound_t mem_region_table [GDBSTUB_MEM_REGION_COUNT] =
|
||||||
|
{
|
||||||
|
{SOC_DROM_LOW, SOC_DROM_HIGH},
|
||||||
|
{SOC_IROM_LOW, SOC_IROM_HIGH},
|
||||||
|
{SOC_IRAM_LOW, SOC_IRAM_HIGH},
|
||||||
|
{SOC_DRAM_LOW, SOC_DRAM_HIGH},
|
||||||
|
{SOC_IROM_MASK_LOW, SOC_IROM_MASK_HIGH},
|
||||||
|
{SOC_DROM_MASK_LOW, SOC_DROM_MASK_HIGH},
|
||||||
|
{SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH},
|
||||||
|
// RTC DRAM and RTC DATA are identical with RTC IRAM, hence we skip them
|
||||||
|
// We shouldn't read the uart registers since it will disturb the debugging via UART,
|
||||||
|
// so skip UART part of the peripheral registers.
|
||||||
|
{DR_REG_UART_BASE + UART_REG_FIELD_LEN, SOC_PERIPHERAL_HIGH},
|
||||||
|
{SOC_DEBUG_LOW, SOC_DEBUG_HIGH},
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline bool check_inside_valid_region(intptr_t addr)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < GDBSTUB_MEM_REGION_COUNT; i++) {
|
||||||
|
if (addr >= mem_region_table[i].lower && addr < mem_region_table[i].upper) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_target_init()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#if CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG
|
||||||
|
|
||||||
|
int esp_gdbstub_getchar()
|
||||||
|
{
|
||||||
|
uint8_t c;
|
||||||
|
//retry the read until we succeed
|
||||||
|
while (usb_serial_jtag_ll_read_rxfifo(&c, 1)==0) ;
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_putchar(int c)
|
||||||
|
{
|
||||||
|
uint8_t cc=c;
|
||||||
|
//retry the write until we succeed
|
||||||
|
while (usb_serial_jtag_ll_write_txfifo(&cc, 1)<1) ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_flush()
|
||||||
|
{
|
||||||
|
usb_serial_jtag_ll_txfifo_flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
//assume UART gdbstub channel
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_gdbstub_flush()
|
||||||
|
{
|
||||||
|
//not needed for uart
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int esp_gdbstub_readmem(intptr_t addr)
|
||||||
|
{
|
||||||
|
if (!check_inside_valid_region(addr)) {
|
||||||
|
/* see esp_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;
|
||||||
|
}
|
15
components/esp_gdbstub/esp32h2/gdbstub_target_config.h
Normal file
15
components/esp_gdbstub/esp32h2/gdbstub_target_config.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// 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
|
@@ -81,7 +81,8 @@ bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
|
|||||||
#if CONFIG_ESP32_DEBUG_OCDAWARE || \
|
#if CONFIG_ESP32_DEBUG_OCDAWARE || \
|
||||||
CONFIG_ESP32S2_DEBUG_OCDAWARE || \
|
CONFIG_ESP32S2_DEBUG_OCDAWARE || \
|
||||||
CONFIG_ESP32S3_DEBUG_OCDAWARE || \
|
CONFIG_ESP32S3_DEBUG_OCDAWARE || \
|
||||||
CONFIG_ESP32C3_DEBUG_OCDAWARE
|
CONFIG_ESP32C3_DEBUG_OCDAWARE || \
|
||||||
|
CONFIG_ESP32H2_DEBUG_OCDAWARE
|
||||||
return cpu_ll_is_debugger_attached();
|
return cpu_ll_is_debugger_attached();
|
||||||
#else
|
#else
|
||||||
return false; // Always return false if "OCD aware" is disabled
|
return false; // Always return false if "OCD aware" is disabled
|
||||||
|
@@ -36,6 +36,10 @@
|
|||||||
#include "esp32c3/rom/rtc.h"
|
#include "esp32c3/rom/rtc.h"
|
||||||
#include "esp32c3/clk.h"
|
#include "esp32c3/clk.h"
|
||||||
#include "esp32c3/rtc.h"
|
#include "esp32c3/rtc.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
|
#include "esp32h2/clk.h"
|
||||||
|
#include "esp32h2/rtc.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define MHZ (1000000)
|
#define MHZ (1000000)
|
||||||
@@ -53,7 +57,7 @@ static RTC_DATA_ATTR uint64_t s_esp_rtc_time_us = 0, s_rtc_last_ticks = 0;
|
|||||||
|
|
||||||
inline static int IRAM_ATTR s_get_cpu_freq_mhz(void)
|
inline static int IRAM_ATTR s_get_cpu_freq_mhz(void)
|
||||||
{
|
{
|
||||||
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3
|
#if CONFIG_IDF_TARGET_ESP32C3 || CONFIG_IDF_TARGET_ESP32S3 || CONFIG_IDF_TARGET_ESP32H2
|
||||||
return ets_get_cpu_frequency();
|
return ets_get_cpu_frequency();
|
||||||
#else
|
#else
|
||||||
return g_ticks_per_us_pro;
|
return g_ticks_per_us_pro;
|
||||||
@@ -75,7 +79,7 @@ int IRAM_ATTR esp_clk_xtal_freq(void)
|
|||||||
return rtc_clk_xtal_freq_get() * MHZ;
|
return rtc_clk_xtal_freq_get() * MHZ;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONFIG_IDF_TARGET_ESP32C3
|
#if !CONFIG_IDF_TARGET_ESP32C3 && !CONFIG_IDF_TARGET_ESP32H2
|
||||||
void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
|
||||||
{
|
{
|
||||||
/* Update scale factors used by esp_rom_delay_us */
|
/* Update scale factors used by esp_rom_delay_us */
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
#include "esp32s3/clk.h"
|
#include "esp32s3/clk.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/clk.h"
|
#include "esp32c3/clk.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/clk.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
uint32_t IRAM_ATTR esp_random(void)
|
uint32_t IRAM_ATTR esp_random(void)
|
||||||
|
@@ -32,6 +32,7 @@ typedef enum {
|
|||||||
CHIP_ESP32S2 = 2, //!< ESP32-S2
|
CHIP_ESP32S2 = 2, //!< ESP32-S2
|
||||||
CHIP_ESP32S3 = 4, //!< ESP32-S3
|
CHIP_ESP32S3 = 4, //!< ESP32-S3
|
||||||
CHIP_ESP32C3 = 5, //!< ESP32-C3
|
CHIP_ESP32C3 = 5, //!< ESP32-C3
|
||||||
|
CHIP_ESP32H2 = 6, //!< ESP32-H2
|
||||||
} esp_chip_model_t;
|
} esp_chip_model_t;
|
||||||
|
|
||||||
/* Chip feature flags, used in esp_chip_info_t */
|
/* Chip feature flags, used in esp_chip_info_t */
|
||||||
@@ -39,6 +40,7 @@ typedef enum {
|
|||||||
#define CHIP_FEATURE_WIFI_BGN BIT(1) //!< Chip has 2.4GHz WiFi
|
#define CHIP_FEATURE_WIFI_BGN BIT(1) //!< Chip has 2.4GHz WiFi
|
||||||
#define CHIP_FEATURE_BLE BIT(4) //!< Chip has Bluetooth LE
|
#define CHIP_FEATURE_BLE BIT(4) //!< Chip has Bluetooth LE
|
||||||
#define CHIP_FEATURE_BT BIT(5) //!< Chip has Bluetooth Classic
|
#define CHIP_FEATURE_BT BIT(5) //!< Chip has Bluetooth Classic
|
||||||
|
#define CHIP_FEATURE_IEEE802154 BIT(6) //!< Chip has IEEE 802.15.4
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The structure represents information about the chip
|
* @brief The structure represents information about the chip
|
||||||
|
@@ -26,6 +26,7 @@ typedef enum {
|
|||||||
ESP_MAC_WIFI_SOFTAP,
|
ESP_MAC_WIFI_SOFTAP,
|
||||||
ESP_MAC_BT,
|
ESP_MAC_BT,
|
||||||
ESP_MAC_ETH,
|
ESP_MAC_ETH,
|
||||||
|
ESP_MAC_IEEE802154,
|
||||||
} esp_mac_type_t;
|
} esp_mac_type_t;
|
||||||
|
|
||||||
/** @cond */
|
/** @cond */
|
||||||
@@ -39,6 +40,8 @@ typedef enum {
|
|||||||
#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES
|
#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32S3_UNIVERSAL_MAC_ADDRESSES
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES
|
#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32C3_UNIVERSAL_MAC_ADDRESSES
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#define UNIVERSAL_MAC_ADDR_NUM CONFIG_ESP32H2_UNIVERSAL_MAC_ADDRESSES
|
||||||
#endif
|
#endif
|
||||||
/** @endcond */
|
/** @endcond */
|
||||||
|
|
||||||
|
16
components/esp_hw_support/include/soc/esp32h2/clk.h
Normal file
16
components/esp_hw_support/include/soc/esp32h2/clk.h
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// 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 "esp_private/esp_clk.h"
|
@@ -41,6 +41,8 @@
|
|||||||
#include "esp32s3/rom/ets_sys.h"
|
#include "esp32s3/rom/ets_sys.h"
|
||||||
#elif CONFIG_IDF_TARGET_ESP32C3
|
#elif CONFIG_IDF_TARGET_ESP32C3
|
||||||
#include "esp32c3/rom/ets_sys.h"
|
#include "esp32c3/rom/ets_sys.h"
|
||||||
|
#elif CONFIG_IDF_TARGET_ESP32H2
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SOC_LOGE(tag, fmt, ...) esp_rom_printf("%s(err): " fmt, tag, ##__VA_ARGS__)
|
#define SOC_LOGE(tag, fmt, ...) esp_rom_printf("%s(err): " fmt, tag, ##__VA_ARGS__)
|
||||||
|
@@ -9,5 +9,5 @@ entries:
|
|||||||
rtc_pm (noflash_text)
|
rtc_pm (noflash_text)
|
||||||
rtc_sleep (noflash_text)
|
rtc_sleep (noflash_text)
|
||||||
rtc_time (noflash_text)
|
rtc_time (noflash_text)
|
||||||
if IDF_TARGET_ESP32C3 = n:
|
if IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n:
|
||||||
rtc_wdt (noflash_text)
|
rtc_wdt (noflash_text)
|
||||||
|
24
components/esp_hw_support/port/esp32h2/CMakeLists.txt
Normal file
24
components/esp_hw_support/port/esp32h2/CMakeLists.txt
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
set(srcs "cpu_util_esp32h2.c"
|
||||||
|
"rtc_clk_init.c"
|
||||||
|
"rtc_clk.c"
|
||||||
|
"rtc_init.c"
|
||||||
|
"rtc_pm.c"
|
||||||
|
"rtc_sleep.c"
|
||||||
|
"rtc_time.c"
|
||||||
|
"chip_info.c"
|
||||||
|
)
|
||||||
|
|
||||||
|
if(NOT BOOTLOADER_BUILD)
|
||||||
|
list(APPEND srcs "../async_memcpy_impl_gdma.c")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" "${srcs}")
|
||||||
|
|
||||||
|
target_sources(${COMPONENT_LIB} PRIVATE "${srcs}")
|
||||||
|
target_include_directories(${COMPONENT_LIB} PUBLIC . private_include)
|
||||||
|
target_include_directories(${COMPONENT_LIB} PRIVATE ../hal)
|
||||||
|
|
||||||
|
if(NOT CMAKE_BUILD_EARLY_EXPANSION)
|
||||||
|
set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/rtc_clk.c" PROPERTIES
|
||||||
|
COMPILE_FLAGS "-fno-jump-tables -fno-tree-switch-conversion")
|
||||||
|
endif()
|
18
components/esp_hw_support/port/esp32h2/Kconfig.mac
Normal file
18
components/esp_hw_support/port/esp32h2/Kconfig.mac
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
# ESP32H2-TODO: IDF-3390
|
||||||
|
choice ESP32H2_UNIVERSAL_MAC_ADDRESSES
|
||||||
|
bool "Number of universally administered (by IEEE) MAC address"
|
||||||
|
default ESP32H2_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||||
|
help
|
||||||
|
Configure the number of universally administered (by IEEE) MAC addresses.
|
||||||
|
During initialization, MAC addresses for each network interface are generated or derived from a
|
||||||
|
single base MAC address.
|
||||||
|
|
||||||
|
config ESP32H2_UNIVERSAL_MAC_ADDRESSES_TWO
|
||||||
|
bool "Two"
|
||||||
|
select ESP_MAC_ADDR_UNIVERSE_IEEE802154
|
||||||
|
select ESP_MAC_ADDR_UNIVERSE_BT
|
||||||
|
endchoice
|
||||||
|
|
||||||
|
config ESP32H2_UNIVERSAL_MAC_ADDRESSES
|
||||||
|
int
|
||||||
|
default 2 if ESP32H2_UNIVERSAL_MAC_ADDRESSES_TWO
|
26
components/esp_hw_support/port/esp32h2/chip_info.c
Normal file
26
components/esp_hw_support/port/esp32h2/chip_info.c
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Copyright 2013-2020 Espressif Systems (Shanghai) PTE LTD
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
#include "esp_chip_info.h"
|
||||||
|
#include "esp_efuse.h"
|
||||||
|
|
||||||
|
void esp_chip_info(esp_chip_info_t *out_info)
|
||||||
|
{
|
||||||
|
memset(out_info, 0, sizeof(*out_info));
|
||||||
|
out_info->model = CHIP_ESP32H2;
|
||||||
|
out_info->revision = esp_efuse_get_chip_ver();
|
||||||
|
out_info->cores = 1;
|
||||||
|
out_info->features = CHIP_FEATURE_IEEE802154 | CHIP_FEATURE_BLE;
|
||||||
|
}
|
112
components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c
Normal file
112
components/esp_hw_support/port/esp32h2/cpu_util_esp32h2.c
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
// 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 <assert.h>
|
||||||
|
#include "soc/cpu.h"
|
||||||
|
|
||||||
|
void esp_cpu_configure_region_protection(void)
|
||||||
|
{
|
||||||
|
/* Notes on implementation:
|
||||||
|
*
|
||||||
|
* 1) Note: ESP32-C3 CPU doesn't support overlapping PMP regions
|
||||||
|
*
|
||||||
|
* 2) Therefore, we use TOR (top of range) entries to map the whole address
|
||||||
|
* space, bottom to top.
|
||||||
|
*
|
||||||
|
* 3) There are not enough entries to describe all the memory regions 100% accurately.
|
||||||
|
*
|
||||||
|
* 4) This means some gaps (invalid memory) are accessible. Priority for extending regions
|
||||||
|
* to cover gaps is to extend read-only or read-execute regions or read-only regions only
|
||||||
|
* (executing unmapped addresses should always fault with invalid instruction, read-only means
|
||||||
|
* stores will correctly fault even if reads may return some invalid value.)
|
||||||
|
*
|
||||||
|
* 5) Entries are grouped in order with some static asserts to try and verify everything is
|
||||||
|
* correct.
|
||||||
|
*/
|
||||||
|
const unsigned NONE = PMP_L | PMP_TOR;
|
||||||
|
const unsigned R = PMP_L | PMP_TOR | PMP_R;
|
||||||
|
const unsigned RW = PMP_L | PMP_TOR | PMP_R | PMP_W;
|
||||||
|
const unsigned RX = PMP_L | PMP_TOR | PMP_R | PMP_X;
|
||||||
|
const unsigned RWX = PMP_L | PMP_TOR | PMP_R | PMP_W | PMP_X;
|
||||||
|
|
||||||
|
// 1. Gap at bottom of address space
|
||||||
|
PMP_ENTRY_SET(0, SOC_DEBUG_LOW, NONE);
|
||||||
|
|
||||||
|
// 2. Debug region
|
||||||
|
PMP_ENTRY_SET(1, SOC_DEBUG_HIGH, RWX);
|
||||||
|
_Static_assert(SOC_DEBUG_LOW < SOC_DEBUG_HIGH, "Invalid CPU debug region");
|
||||||
|
|
||||||
|
// 3. Gap between debug region & DROM (flash cache)
|
||||||
|
PMP_ENTRY_SET(2, SOC_DROM_LOW, NONE);
|
||||||
|
_Static_assert(SOC_DEBUG_HIGH < SOC_DROM_LOW, "Invalid PMP entry order");
|
||||||
|
|
||||||
|
// 4. DROM (flash cache)
|
||||||
|
// 5. Gap between DROM & DRAM
|
||||||
|
// (Note: To save PMP entries these two are merged into one read-only region)
|
||||||
|
PMP_ENTRY_SET(3, SOC_DRAM_LOW, R);
|
||||||
|
_Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid DROM region");
|
||||||
|
_Static_assert(SOC_DROM_HIGH < SOC_DRAM_LOW, "Invalid PMP entry order");
|
||||||
|
|
||||||
|
// 6. DRAM
|
||||||
|
PMP_ENTRY_SET(4, SOC_DRAM_HIGH, RW);
|
||||||
|
_Static_assert(SOC_DRAM_LOW < SOC_DRAM_HIGH, "Invalid DRAM region");
|
||||||
|
|
||||||
|
// 7. Gap between DRAM and Mask DROM
|
||||||
|
// 8. Mask DROM
|
||||||
|
// (Note: to save PMP entries these two are merged into one read-only region)
|
||||||
|
PMP_ENTRY_SET(5, SOC_DROM_MASK_HIGH, R);
|
||||||
|
_Static_assert(SOC_DRAM_HIGH < SOC_DROM_MASK_LOW, "Invalid PMP entry order");
|
||||||
|
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid mask DROM region");
|
||||||
|
|
||||||
|
// 9. Gap between mask DROM and mask IROM
|
||||||
|
// 10. Mask IROM
|
||||||
|
// (Note: to save PMP entries these two are merged into one RX region)
|
||||||
|
PMP_ENTRY_SET(6, SOC_IROM_MASK_HIGH, RX);
|
||||||
|
_Static_assert(SOC_DROM_MASK_HIGH < SOC_IROM_MASK_LOW, "Invalid PMP entry order");
|
||||||
|
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid mask IROM region");
|
||||||
|
|
||||||
|
// 11. Gap between mask IROM & IRAM
|
||||||
|
PMP_ENTRY_SET(7, SOC_IRAM_LOW, NONE);
|
||||||
|
_Static_assert(SOC_IROM_MASK_HIGH < SOC_IRAM_LOW, "Invalid PMP entry order");
|
||||||
|
|
||||||
|
// 12. IRAM
|
||||||
|
PMP_ENTRY_SET(8, SOC_IRAM_HIGH, RWX);
|
||||||
|
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid IRAM region");
|
||||||
|
|
||||||
|
// 13. Gap between IRAM and IROM
|
||||||
|
// 14. IROM (flash cache)
|
||||||
|
// (Note: to save PMP entries these two are merged into one RX region)
|
||||||
|
PMP_ENTRY_SET(9, SOC_IROM_HIGH, RX);
|
||||||
|
_Static_assert(SOC_IRAM_HIGH < SOC_IROM_LOW, "Invalid PMP entry order");
|
||||||
|
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid IROM region");
|
||||||
|
|
||||||
|
// 15. Gap between IROM & RTC slow memory
|
||||||
|
PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE);
|
||||||
|
_Static_assert(SOC_IROM_HIGH < SOC_RTC_IRAM_LOW, "Invalid PMP entry order");
|
||||||
|
|
||||||
|
// 16. RTC fast memory
|
||||||
|
PMP_ENTRY_SET(11, SOC_RTC_IRAM_HIGH, RWX);
|
||||||
|
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||||
|
|
||||||
|
// 17. Gap between RTC fast memory & peripheral addresses
|
||||||
|
PMP_ENTRY_SET(12, SOC_PERIPHERAL_LOW, NONE);
|
||||||
|
_Static_assert(SOC_RTC_IRAM_HIGH < SOC_PERIPHERAL_LOW, "Invalid PMP entry order");
|
||||||
|
|
||||||
|
// 18. Peripheral addresses
|
||||||
|
PMP_ENTRY_SET(13, SOC_PERIPHERAL_HIGH, RW);
|
||||||
|
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||||
|
|
||||||
|
// 19. End of address space
|
||||||
|
PMP_ENTRY_SET(14, UINT32_MAX, NONE); // all but last 4 bytes
|
||||||
|
PMP_ENTRY_SET(15, UINT32_MAX, PMP_L | PMP_NA4); // last 4 bytes
|
||||||
|
}
|
30
components/esp_hw_support/port/esp32h2/i2c_brownout.h
Normal file
30
components/esp_hw_support/port/esp32h2/i2c_brownout.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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file i2c_brownout.h
|
||||||
|
* @brief Register definitions for brownout detector
|
||||||
|
*
|
||||||
|
* This file lists register fields of the brownout detector, located on an internal configuration
|
||||||
|
* bus. These definitions are used via macros defined in i2c_rtc_clk.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_BOD 0x61
|
||||||
|
#define I2C_BOD_HOSTID 1
|
||||||
|
|
||||||
|
#define I2C_BOD_THRESHOLD 0x5
|
||||||
|
#define I2C_BOD_THRESHOLD_MSB 2
|
||||||
|
#define I2C_BOD_THRESHOLD_LSB 0
|
48
components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h
Normal file
48
components/esp_hw_support/port/esp32h2/i2c_rtc_clk.h
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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "regi2c_ctrl.h"
|
||||||
|
|
||||||
|
/* Analog function control register */
|
||||||
|
#define ANA_CONFIG_REG 0x6000E044
|
||||||
|
#define ANA_CONFIG_S (8)
|
||||||
|
#define ANA_CONFIG_M (0x3FF)
|
||||||
|
/* Clear to enable APLL */
|
||||||
|
#define I2C_APLL_M (BIT(14))
|
||||||
|
/* Clear to enable BBPLL */
|
||||||
|
#define I2C_BBPLL_M (BIT(17))
|
||||||
|
|
||||||
|
/* ROM functions which read/write internal control bus */
|
||||||
|
uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
|
||||||
|
uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
|
||||||
|
void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
|
||||||
|
void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
|
||||||
|
|
||||||
|
/* Convenience macros for the above functions, these use register definitions
|
||||||
|
* from i2c_apll.h/i2c_bbpll.h header files.
|
||||||
|
*/
|
||||||
|
#define I2C_WRITEREG_MASK_RTC(block, reg_add, indata) \
|
||||||
|
rom_i2c_writeReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
|
||||||
|
|
||||||
|
#define I2C_READREG_MASK_RTC(block, reg_add) \
|
||||||
|
rom_i2c_readReg_Mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
|
||||||
|
|
||||||
|
#define I2C_WRITEREG_RTC(block, reg_add, indata) \
|
||||||
|
rom_i2c_writeReg(block, block##_HOSTID, reg_add, indata)
|
||||||
|
|
||||||
|
#define I2C_READREG_RTC(block, reg_add) \
|
||||||
|
rom_i2c_readReg(block, block##_HOSTID, reg_add)
|
@@ -0,0 +1,183 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regi2c_bbpll.h
|
||||||
|
* @brief Register definitions for digital PLL (BBPLL)
|
||||||
|
*
|
||||||
|
* This file lists register fields of BBPLL, located on an internal configuration
|
||||||
|
* bus. These definitions are used via macros defined in regi2c_ctrl.h, by
|
||||||
|
* rtc_clk_cpu_freq_set function in rtc_clk.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_BBPLL 0x66
|
||||||
|
#define I2C_BBPLL_HOSTID 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_DELAY 0
|
||||||
|
#define I2C_BBPLL_IR_CAL_DELAY_MSB 3
|
||||||
|
#define I2C_BBPLL_IR_CAL_DELAY_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_CK_DIV 0
|
||||||
|
#define I2C_BBPLL_IR_CAL_CK_DIV_MSB 7
|
||||||
|
#define I2C_BBPLL_IR_CAL_CK_DIV_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_EXT_CAP 1
|
||||||
|
#define I2C_BBPLL_IR_CAL_EXT_CAP_MSB 3
|
||||||
|
#define I2C_BBPLL_IR_CAL_EXT_CAP_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_ENX_CAP 1
|
||||||
|
#define I2C_BBPLL_IR_CAL_ENX_CAP_MSB 4
|
||||||
|
#define I2C_BBPLL_IR_CAL_ENX_CAP_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_RSTB 1
|
||||||
|
#define I2C_BBPLL_IR_CAL_RSTB_MSB 5
|
||||||
|
#define I2C_BBPLL_IR_CAL_RSTB_LSB 5
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_START 1
|
||||||
|
#define I2C_BBPLL_IR_CAL_START_MSB 6
|
||||||
|
#define I2C_BBPLL_IR_CAL_START_LSB 6
|
||||||
|
|
||||||
|
#define I2C_BBPLL_IR_CAL_UNSTOP 1
|
||||||
|
#define I2C_BBPLL_IR_CAL_UNSTOP_MSB 7
|
||||||
|
#define I2C_BBPLL_IR_CAL_UNSTOP_LSB 7
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_REF_DIV 2
|
||||||
|
#define I2C_BBPLL_OC_REF_DIV_MSB 3
|
||||||
|
#define I2C_BBPLL_OC_REF_DIV_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DCHGP 2
|
||||||
|
#define I2C_BBPLL_OC_DCHGP_MSB 6
|
||||||
|
#define I2C_BBPLL_OC_DCHGP_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_ENB_FCAL 2
|
||||||
|
#define I2C_BBPLL_OC_ENB_FCAL_MSB 7
|
||||||
|
#define I2C_BBPLL_OC_ENB_FCAL_LSB 7
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DIV_7_0 3
|
||||||
|
#define I2C_BBPLL_OC_DIV_7_0_MSB 7
|
||||||
|
#define I2C_BBPLL_OC_DIV_7_0_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_RSTB_DIV_ADC 4
|
||||||
|
#define I2C_BBPLL_RSTB_DIV_ADC_MSB 0
|
||||||
|
#define I2C_BBPLL_RSTB_DIV_ADC_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_MODE_HF 4
|
||||||
|
#define I2C_BBPLL_MODE_HF_MSB 1
|
||||||
|
#define I2C_BBPLL_MODE_HF_LSB 1
|
||||||
|
|
||||||
|
#define I2C_BBPLL_DIV_ADC 4
|
||||||
|
#define I2C_BBPLL_DIV_ADC_MSB 3
|
||||||
|
#define I2C_BBPLL_DIV_ADC_LSB 2
|
||||||
|
|
||||||
|
#define I2C_BBPLL_DIV_DAC 4
|
||||||
|
#define I2C_BBPLL_DIV_DAC_MSB 4
|
||||||
|
#define I2C_BBPLL_DIV_DAC_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_DIV_CPU 4
|
||||||
|
#define I2C_BBPLL_DIV_CPU_MSB 5
|
||||||
|
#define I2C_BBPLL_DIV_CPU_LSB 5
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_ENB_VCON 4
|
||||||
|
#define I2C_BBPLL_OC_ENB_VCON_MSB 6
|
||||||
|
#define I2C_BBPLL_OC_ENB_VCON_LSB 6
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_TSCHGP 4
|
||||||
|
#define I2C_BBPLL_OC_TSCHGP_MSB 7
|
||||||
|
#define I2C_BBPLL_OC_TSCHGP_LSB 7
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DR1 5
|
||||||
|
#define I2C_BBPLL_OC_DR1_MSB 2
|
||||||
|
#define I2C_BBPLL_OC_DR1_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DR3 5
|
||||||
|
#define I2C_BBPLL_OC_DR3_MSB 6
|
||||||
|
#define I2C_BBPLL_OC_DR3_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_EN_USB 5
|
||||||
|
#define I2C_BBPLL_EN_USB_MSB 7
|
||||||
|
#define I2C_BBPLL_EN_USB_LSB 7
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DCUR 6
|
||||||
|
#define I2C_BBPLL_OC_DCUR_MSB 2
|
||||||
|
#define I2C_BBPLL_OC_DCUR_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_INC_CUR 6
|
||||||
|
#define I2C_BBPLL_INC_CUR_MSB 3
|
||||||
|
#define I2C_BBPLL_INC_CUR_LSB 3
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DHREF_SEL 6
|
||||||
|
#define I2C_BBPLL_OC_DHREF_SEL_MSB 5
|
||||||
|
#define I2C_BBPLL_OC_DHREF_SEL_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_DLREF_SEL 6
|
||||||
|
#define I2C_BBPLL_OC_DLREF_SEL_MSB 7
|
||||||
|
#define I2C_BBPLL_OC_DLREF_SEL_LSB 6
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OR_CAL_CAP 8
|
||||||
|
#define I2C_BBPLL_OR_CAL_CAP_MSB 3
|
||||||
|
#define I2C_BBPLL_OR_CAL_CAP_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OR_CAL_UDF 8
|
||||||
|
#define I2C_BBPLL_OR_CAL_UDF_MSB 4
|
||||||
|
#define I2C_BBPLL_OR_CAL_UDF_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OR_CAL_OVF 8
|
||||||
|
#define I2C_BBPLL_OR_CAL_OVF_MSB 5
|
||||||
|
#define I2C_BBPLL_OR_CAL_OVF_LSB 5
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OR_CAL_END 8
|
||||||
|
#define I2C_BBPLL_OR_CAL_END_MSB 6
|
||||||
|
#define I2C_BBPLL_OR_CAL_END_LSB 6
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OR_LOCK 8
|
||||||
|
#define I2C_BBPLL_OR_LOCK_MSB 7
|
||||||
|
#define I2C_BBPLL_OR_LOCK_LSB 7
|
||||||
|
|
||||||
|
#define I2C_BBPLL_OC_VCO_DBIAS 9
|
||||||
|
#define I2C_BBPLL_OC_VCO_DBIAS_MSB 1
|
||||||
|
#define I2C_BBPLL_OC_VCO_DBIAS_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_BBADC_DELAY2 9
|
||||||
|
#define I2C_BBPLL_BBADC_DELAY2_MSB 3
|
||||||
|
#define I2C_BBPLL_BBADC_DELAY2_LSB 2
|
||||||
|
|
||||||
|
#define I2C_BBPLL_BBADC_DVDD 9
|
||||||
|
#define I2C_BBPLL_BBADC_DVDD_MSB 5
|
||||||
|
#define I2C_BBPLL_BBADC_DVDD_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_BBADC_DREF 9
|
||||||
|
#define I2C_BBPLL_BBADC_DREF_MSB 7
|
||||||
|
#define I2C_BBPLL_BBADC_DREF_LSB 6
|
||||||
|
|
||||||
|
#define I2C_BBPLL_BBADC_DCUR 10
|
||||||
|
#define I2C_BBPLL_BBADC_DCUR_MSB 1
|
||||||
|
#define I2C_BBPLL_BBADC_DCUR_LSB 0
|
||||||
|
|
||||||
|
#define I2C_BBPLL_BBADC_INPUT_SHORT 10
|
||||||
|
#define I2C_BBPLL_BBADC_INPUT_SHORT_MSB 2
|
||||||
|
#define I2C_BBPLL_BBADC_INPUT_SHORT_LSB 2
|
||||||
|
|
||||||
|
#define I2C_BBPLL_ENT_PLL 10
|
||||||
|
#define I2C_BBPLL_ENT_PLL_MSB 3
|
||||||
|
#define I2C_BBPLL_ENT_PLL_LSB 3
|
||||||
|
|
||||||
|
#define I2C_BBPLL_DTEST 10
|
||||||
|
#define I2C_BBPLL_DTEST_MSB 5
|
||||||
|
#define I2C_BBPLL_DTEST_LSB 4
|
||||||
|
|
||||||
|
#define I2C_BBPLL_ENT_ADC 10
|
||||||
|
#define I2C_BBPLL_ENT_ADC_MSB 7
|
||||||
|
#define I2C_BBPLL_ENT_ADC_LSB 6
|
@@ -0,0 +1,30 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regi2c_bias.h
|
||||||
|
* @brief Register definitions for bias
|
||||||
|
*
|
||||||
|
* This file lists register fields of BIAS. These definitions are used via macros defined in regi2c_ctrl.h, by
|
||||||
|
* bootloader_hardware_init function in bootloader_esp32c3.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_BIAS 0X6A
|
||||||
|
#define I2C_BIAS_HOSTID 0
|
||||||
|
|
||||||
|
#define I2C_BIAS_DREG_1P1_PVT 1
|
||||||
|
#define I2C_BIAS_DREG_1P1_PVT_MSB 3
|
||||||
|
#define I2C_BIAS_DREG_1P1_PVT_LSB 0
|
@@ -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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regi2c_brownout.h
|
||||||
|
* @brief Register definitions for brownout detector
|
||||||
|
*
|
||||||
|
* This file lists register fields of the brownout detector, located on an internal configuration
|
||||||
|
* bus. These definitions are used via macros defined in regi2c_ctrl.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_BOD 0x61
|
||||||
|
#define I2C_BOD_HOSTID 0
|
||||||
|
|
||||||
|
#define I2C_BOD_THRESHOLD 0x5
|
||||||
|
#define I2C_BOD_THRESHOLD_MSB 2
|
||||||
|
#define I2C_BOD_THRESHOLD_LSB 0
|
@@ -0,0 +1,68 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regi2c_dig_reg.h
|
||||||
|
* @brief Register definitions for digital to get rtc voltage & digital voltage
|
||||||
|
* by setting rtc_dbias_Wak & dig_dbias_wak or by analog self-calibration.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_DIG_REG 0x6D
|
||||||
|
#define I2C_DIG_REG_HOSTID 0
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_EXT_RTC_DREG 4
|
||||||
|
#define I2C_DIG_REG_EXT_RTC_DREG_MSB 4
|
||||||
|
#define I2C_DIG_REG_EXT_RTC_DREG_LSB 0
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_ENX_RTC_DREG 4
|
||||||
|
#define I2C_DIG_REG_ENX_RTC_DREG_MSB 7
|
||||||
|
#define I2C_DIG_REG_ENX_RTC_DREG_LSB 7
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP 5
|
||||||
|
#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_MSB 4
|
||||||
|
#define I2C_DIG_REG_EXT_RTC_DREG_SLEEP_LSB 0
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP 5
|
||||||
|
#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_MSB 7
|
||||||
|
#define I2C_DIG_REG_ENX_RTC_DREG_SLEEP_LSB 7
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_EXT_DIG_DREG 6
|
||||||
|
#define I2C_DIG_REG_EXT_DIG_DREG_MSB 4
|
||||||
|
#define I2C_DIG_REG_EXT_DIG_DREG_LSB 0
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_ENX_DIG_DREG 6
|
||||||
|
#define I2C_DIG_REG_ENX_DIG_DREG_MSB 7
|
||||||
|
#define I2C_DIG_REG_ENX_DIG_DREG_LSB 7
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP 7
|
||||||
|
#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_MSB 4
|
||||||
|
#define I2C_DIG_REG_EXT_DIG_DREG_SLEEP_LSB 0
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP 7
|
||||||
|
#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP_MSB 7
|
||||||
|
#define I2C_DIG_REG_ENX_DIG_DREG_SLEEP_LSB 7
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_OR_EN_CONT_CAL 9
|
||||||
|
#define I2C_DIG_REG_OR_EN_CONT_CAL_MSB 7
|
||||||
|
#define I2C_DIG_REG_OR_EN_CONT_CAL_LSB 7
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_XPD_RTC_REG 13
|
||||||
|
#define I2C_DIG_REG_XPD_RTC_REG_MSB 2
|
||||||
|
#define I2C_DIG_REG_XPD_RTC_REG_LSB 2
|
||||||
|
|
||||||
|
#define I2C_DIG_REG_XPD_DIG_REG 13
|
||||||
|
#define I2C_DIG_REG_XPD_DIG_REG_MSB 3
|
||||||
|
#define I2C_DIG_REG_XPD_DIG_REG_LSB 3
|
@@ -0,0 +1,63 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regi2c_lp_bias.h
|
||||||
|
* @brief Register definitions for analog to calibrate o_code for getting a more precise voltage.
|
||||||
|
*
|
||||||
|
* This file lists register fields of low power dbais, located on an internal configuration
|
||||||
|
* bus. These definitions are used via macros defined in regi2c_ctrl.h, by
|
||||||
|
* rtc_init function in rtc_init.c.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_ULP 0x61
|
||||||
|
#define I2C_ULP_HOSTID 0
|
||||||
|
|
||||||
|
#define I2C_ULP_IR_RESETB 0
|
||||||
|
#define I2C_ULP_IR_RESETB_MSB 0
|
||||||
|
#define I2C_ULP_IR_RESETB_LSB 0
|
||||||
|
|
||||||
|
#define I2C_ULP_IR_FORCE_XPD_CK 0
|
||||||
|
#define I2C_ULP_IR_FORCE_XPD_CK_MSB 2
|
||||||
|
#define I2C_ULP_IR_FORCE_XPD_CK_LSB 2
|
||||||
|
|
||||||
|
#define I2C_ULP_IR_FORCE_XPD_IPH 0
|
||||||
|
#define I2C_ULP_IR_FORCE_XPD_IPH_MSB 4
|
||||||
|
#define I2C_ULP_IR_FORCE_XPD_IPH_LSB 4
|
||||||
|
|
||||||
|
#define I2C_ULP_IR_DISABLE_WATCHDOG_CK 0
|
||||||
|
#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_MSB 6
|
||||||
|
#define I2C_ULP_IR_DISABLE_WATCHDOG_CK_LSB 6
|
||||||
|
|
||||||
|
#define I2C_ULP_O_DONE_FLAG 3
|
||||||
|
#define I2C_ULP_O_DONE_FLAG_MSB 0
|
||||||
|
#define I2C_ULP_O_DONE_FLAG_LSB 0
|
||||||
|
|
||||||
|
#define I2C_ULP_BG_O_DONE_FLAG 3
|
||||||
|
#define I2C_ULP_BG_O_DONE_FLAG_MSB 3
|
||||||
|
#define I2C_ULP_BG_O_DONE_FLAG_LSB 3
|
||||||
|
|
||||||
|
#define I2C_ULP_OCODE 4
|
||||||
|
#define I2C_ULP_OCODE_MSB 7
|
||||||
|
#define I2C_ULP_OCODE_LSB 0
|
||||||
|
|
||||||
|
#define I2C_ULP_IR_FORCE_CODE 5
|
||||||
|
#define I2C_ULP_IR_FORCE_CODE_MSB 6
|
||||||
|
#define I2C_ULP_IR_FORCE_CODE_LSB 6
|
||||||
|
|
||||||
|
#define I2C_ULP_EXT_CODE 6
|
||||||
|
#define I2C_ULP_EXT_CODE_MSB 7
|
||||||
|
#define I2C_ULP_EXT_CODE_LSB 0
|
@@ -0,0 +1,87 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file regi2c_saradc.h
|
||||||
|
* @brief Register definitions for analog to calibrate initial code for getting a more precise voltage of SAR ADC.
|
||||||
|
*
|
||||||
|
* This file lists register fields of SAR, located on an internal configuration
|
||||||
|
* bus. These definitions are used via macros defined in regi2c_ctrl.h, by
|
||||||
|
* function in adc_ll.h.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define I2C_SAR_ADC 0X69
|
||||||
|
#define I2C_SAR_ADC_HOSTID 0
|
||||||
|
|
||||||
|
#define ADC_SAR1_ENCAL_GND_ADDR 0x7
|
||||||
|
#define ADC_SAR1_ENCAL_GND_ADDR_MSB 5
|
||||||
|
#define ADC_SAR1_ENCAL_GND_ADDR_LSB 5
|
||||||
|
|
||||||
|
#define ADC_SAR2_ENCAL_GND_ADDR 0x7
|
||||||
|
#define ADC_SAR2_ENCAL_GND_ADDR_MSB 7
|
||||||
|
#define ADC_SAR2_ENCAL_GND_ADDR_LSB 7
|
||||||
|
|
||||||
|
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR 0x1
|
||||||
|
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_MSB 0x3
|
||||||
|
#define ADC_SAR1_INITIAL_CODE_HIGH_ADDR_LSB 0x0
|
||||||
|
|
||||||
|
#define ADC_SAR1_INITIAL_CODE_LOW_ADDR 0x0
|
||||||
|
#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_MSB 0x7
|
||||||
|
#define ADC_SAR1_INITIAL_CODE_LOW_ADDR_LSB 0x0
|
||||||
|
|
||||||
|
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR 0x4
|
||||||
|
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_MSB 0x3
|
||||||
|
#define ADC_SAR2_INITIAL_CODE_HIGH_ADDR_LSB 0x0
|
||||||
|
|
||||||
|
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR 0x3
|
||||||
|
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_MSB 0x7
|
||||||
|
#define ADC_SAR2_INITIAL_CODE_LOW_ADDR_LSB 0x0
|
||||||
|
|
||||||
|
#define ADC_SAR1_DREF_ADDR 0x2
|
||||||
|
#define ADC_SAR1_DREF_ADDR_MSB 0x6
|
||||||
|
#define ADC_SAR1_DREF_ADDR_LSB 0x4
|
||||||
|
|
||||||
|
#define ADC_SAR2_DREF_ADDR 0x5
|
||||||
|
#define ADC_SAR2_DREF_ADDR_MSB 0x6
|
||||||
|
#define ADC_SAR2_DREF_ADDR_LSB 0x4
|
||||||
|
|
||||||
|
#define ADC_SAR1_SAMPLE_CYCLE_ADDR 0x2
|
||||||
|
#define ADC_SAR1_SAMPLE_CYCLE_ADDR_MSB 0x2
|
||||||
|
#define ADC_SAR1_SAMPLE_CYCLE_ADDR_LSB 0x0
|
||||||
|
|
||||||
|
#define ADC_SARADC_DTEST_RTC_ADDR 0x7
|
||||||
|
#define ADC_SARADC_DTEST_RTC_ADDR_MSB 1
|
||||||
|
#define ADC_SARADC_DTEST_RTC_ADDR_LSB 0
|
||||||
|
|
||||||
|
#define ADC_SARADC_ENT_TSENS_ADDR 0x7
|
||||||
|
#define ADC_SARADC_ENT_TSENS_ADDR_MSB 2
|
||||||
|
#define ADC_SARADC_ENT_TSENS_ADDR_LSB 2
|
||||||
|
|
||||||
|
#define ADC_SARADC_ENT_RTC_ADDR 0x7
|
||||||
|
#define ADC_SARADC_ENT_RTC_ADDR_MSB 3
|
||||||
|
#define ADC_SARADC_ENT_RTC_ADDR_LSB 3
|
||||||
|
|
||||||
|
#define ADC_SARADC1_ENCAL_REF_ADDR 0x7
|
||||||
|
#define ADC_SARADC1_ENCAL_REF_ADDR_MSB 4
|
||||||
|
#define ADC_SARADC1_ENCAL_REF_ADDR_LSB 4
|
||||||
|
|
||||||
|
#define ADC_SARADC2_ENCAL_REF_ADDR 0x7
|
||||||
|
#define ADC_SARADC2_ENCAL_REF_ADDR_MSB 6
|
||||||
|
#define ADC_SARADC2_ENCAL_REF_ADDR_LSB 6
|
||||||
|
|
||||||
|
#define I2C_SARADC_TSENS_DAC 0x6
|
||||||
|
#define I2C_SARADC_TSENS_DAC_MSB 3
|
||||||
|
#define I2C_SARADC_TSENS_DAC_LSB 0
|
109
components/esp_hw_support/port/esp32h2/regi2c_ctrl.h
Normal file
109
components/esp_hw_support/port/esp32h2/regi2c_ctrl.h
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
// 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.
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "regi2c_bbpll.h"
|
||||||
|
#include "regi2c_lp_bias.h"
|
||||||
|
#include "regi2c_dig_reg.h"
|
||||||
|
#include "regi2c_bias.h"
|
||||||
|
#include "regi2c_saradc.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Analog function control register */
|
||||||
|
#define I2C_MST_ANA_CONF0_REG 0x6000E040
|
||||||
|
#define I2C_MST_BBPLL_STOP_FORCE_HIGH (BIT(2))
|
||||||
|
#define I2C_MST_BBPLL_STOP_FORCE_LOW (BIT(3))
|
||||||
|
|
||||||
|
#define ANA_CONFIG_REG 0x6000E044
|
||||||
|
#define ANA_CONFIG_S (8)
|
||||||
|
#define ANA_CONFIG_M (0x3FF)
|
||||||
|
|
||||||
|
#define ANA_I2C_SAR_FORCE_PD BIT(18)
|
||||||
|
#define ANA_I2C_BBPLL_M BIT(17) /* Clear to enable BBPLL */
|
||||||
|
#define ANA_I2C_APLL_M BIT(14) /* Clear to enable APLL */
|
||||||
|
|
||||||
|
|
||||||
|
#define ANA_CONFIG2_REG 0x6000E048
|
||||||
|
#define ANA_CONFIG2_M BIT(18)
|
||||||
|
|
||||||
|
#define ANA_I2C_SAR_FORCE_PU BIT(16)
|
||||||
|
|
||||||
|
/* ROM functions which read/write internal control bus */
|
||||||
|
uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
|
||||||
|
uint8_t rom_i2c_readReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
|
||||||
|
void rom_i2c_writeReg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
|
||||||
|
void rom_i2c_writeReg_Mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
|
||||||
|
|
||||||
|
#ifdef BOOTLOADER_BUILD
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If compiling for the bootloader, ROM functions can be called directly,
|
||||||
|
* without the need of a lock.
|
||||||
|
*/
|
||||||
|
#define regi2c_ctrl_read_reg rom_i2c_readReg
|
||||||
|
#define regi2c_ctrl_read_reg_mask rom_i2c_readReg_Mask
|
||||||
|
#define regi2c_ctrl_write_reg rom_i2c_writeReg
|
||||||
|
#define regi2c_ctrl_write_reg_mask rom_i2c_writeReg_Mask
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define i2c_read_reg_raw rom_i2c_readReg
|
||||||
|
#define i2c_read_reg_mask_raw rom_i2c_readReg_Mask
|
||||||
|
#define i2c_write_reg_raw rom_i2c_writeReg
|
||||||
|
#define i2c_write_reg_mask_raw rom_i2c_writeReg_Mask
|
||||||
|
|
||||||
|
uint8_t regi2c_ctrl_read_reg(uint8_t block, uint8_t host_id, uint8_t reg_add);
|
||||||
|
uint8_t regi2c_ctrl_read_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb);
|
||||||
|
void regi2c_ctrl_write_reg(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t data);
|
||||||
|
void regi2c_ctrl_write_reg_mask(uint8_t block, uint8_t host_id, uint8_t reg_add, uint8_t msb, uint8_t lsb, uint8_t data);
|
||||||
|
|
||||||
|
#endif // BOOTLOADER_BUILD
|
||||||
|
|
||||||
|
/* Convenience macros for the above functions, these use register definitions
|
||||||
|
* from regi2c_bbpll.h/regi2c_dig_reg.h/regi2c_lp_bias.h/regi2c_bias.h header files.
|
||||||
|
*/
|
||||||
|
#define REGI2C_WRITE_MASK(block, reg_add, indata) \
|
||||||
|
regi2c_ctrl_write_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB, indata)
|
||||||
|
|
||||||
|
#define REGI2C_READ_MASK(block, reg_add) \
|
||||||
|
regi2c_ctrl_read_reg_mask(block, block##_HOSTID, reg_add, reg_add##_MSB, reg_add##_LSB)
|
||||||
|
|
||||||
|
#define REGI2C_WRITE(block, reg_add, indata) \
|
||||||
|
regi2c_ctrl_write_reg(block, block##_HOSTID, reg_add, indata)
|
||||||
|
|
||||||
|
#define REGI2C_READ(block, reg_add) \
|
||||||
|
regi2c_ctrl_read_reg(block, block##_HOSTID, reg_add)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
507
components/esp_hw_support/port/esp32h2/rtc_clk.c
Normal file
507
components/esp_hw_support/port/esp32h2/rtc_clk.c
Normal file
@@ -0,0 +1,507 @@
|
|||||||
|
// 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 <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
|
#include "esp32h2/rom/uart.h"
|
||||||
|
#include "esp32h2/rom/gpio.h"
|
||||||
|
#include "soc/rtc.h"
|
||||||
|
#include "soc/rtc_cntl_reg.h"
|
||||||
|
#include "soc/efuse_reg.h"
|
||||||
|
#include "soc/syscon_reg.h"
|
||||||
|
#include "soc/system_reg.h"
|
||||||
|
#include "regi2c_ctrl.h"
|
||||||
|
#include "soc_log.h"
|
||||||
|
#include "rtc_clk_common.h"
|
||||||
|
#include "esp_rom_sys.h"
|
||||||
|
|
||||||
|
static const char *TAG = "rtc_clk";
|
||||||
|
|
||||||
|
#define RTC_PLL_FREQ_320M 320
|
||||||
|
#define RTC_PLL_FREQ_480M 480
|
||||||
|
#define DELAY_RTC_CLK_SWITCH 5
|
||||||
|
|
||||||
|
// Current PLL frequency, in MHZ (320 or 480). Zero if PLL is not enabled.
|
||||||
|
static int s_cur_pll_freq;
|
||||||
|
|
||||||
|
static void rtc_clk_cpu_freq_to_8m(void);
|
||||||
|
|
||||||
|
void rtc_clk_32k_enable_internal(x32k_config_t cfg)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DAC_XTAL_32K, cfg.dac);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DRES_XTAL_32K, cfg.dres);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DGM_XTAL_32K, cfg.dgm);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_DBUF_XTAL_32K, cfg.dbuf);
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_32k_enable(bool enable)
|
||||||
|
{
|
||||||
|
if (enable) {
|
||||||
|
x32k_config_t cfg = X32K_CONFIG_DEFAULT();
|
||||||
|
rtc_clk_32k_enable_internal(cfg);
|
||||||
|
} else {
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XTAL32K_XPD_FORCE);
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_CNTL_EXT_XTL_CONF_REG, RTC_CNTL_XPD_XTAL_32K);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_32k_enable_external(void)
|
||||||
|
{
|
||||||
|
/* TODO ESP32-C3 IDF-2408: external 32k source may need different settings */
|
||||||
|
x32k_config_t cfg = X32K_CONFIG_DEFAULT();
|
||||||
|
rtc_clk_32k_enable_internal(cfg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_32k_bootstrap(uint32_t cycle)
|
||||||
|
{
|
||||||
|
/* No special bootstrapping needed for ESP32-C3, 'cycle' argument is to keep the signature
|
||||||
|
* same as for the ESP32. Just enable the XTAL here.
|
||||||
|
*/
|
||||||
|
(void) cycle;
|
||||||
|
rtc_clk_32k_enable(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtc_clk_32k_enabled(void)
|
||||||
|
{
|
||||||
|
uint32_t xtal_conf = READ_PERI_REG(RTC_CNTL_EXT_XTL_CONF_REG);
|
||||||
|
/* If xtal xpd is controlled by software */
|
||||||
|
bool xtal_xpd_sw = (xtal_conf & RTC_CNTL_XTAL32K_XPD_FORCE) >> RTC_CNTL_XTAL32K_XPD_FORCE_S;
|
||||||
|
/* If xtal xpd software control is on */
|
||||||
|
bool xtal_xpd_st = (xtal_conf & RTC_CNTL_XPD_XTAL_32K) >> RTC_CNTL_XPD_XTAL_32K_S;
|
||||||
|
bool disabled = xtal_xpd_sw && !xtal_xpd_st;
|
||||||
|
return !disabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
|
||||||
|
{
|
||||||
|
if (clk_8m_en) {
|
||||||
|
// CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M); // ESP32H2-TODO: IDF-3396
|
||||||
|
/* no need to wait once enabled by software */
|
||||||
|
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CK8M_ENABLE_WAIT_DEFAULT);
|
||||||
|
esp_rom_delay_us(DELAY_8M_ENABLE);
|
||||||
|
} else {
|
||||||
|
// SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT);
|
||||||
|
}
|
||||||
|
/* d256 should be independent configured with 8M
|
||||||
|
* Maybe we can split this function into 8m and dmd256
|
||||||
|
*/
|
||||||
|
if (d256_en) {
|
||||||
|
// CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
|
||||||
|
} else {
|
||||||
|
// SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtc_clk_8m_enabled(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
// return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0; // ESP32H2-TODO: IDF-3396
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtc_clk_8md256_enabled(void)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
// return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0; // ESP32H2-TODO: IDF-3396
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
|
||||||
|
|
||||||
|
/* Why we need to connect this clock to digital?
|
||||||
|
* Or maybe this clock should be connected to digital when xtal 32k clock is enabled instead?
|
||||||
|
*/
|
||||||
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN,
|
||||||
|
(slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
|
||||||
|
|
||||||
|
/* The clk_8m_d256 will be closed when rtc_state in SLEEP,
|
||||||
|
so if the slow_clk is 8md256, clk_8m must be force power on
|
||||||
|
*/
|
||||||
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU, (slow_freq == RTC_SLOW_FREQ_8MD256) ? 1 : 0);
|
||||||
|
esp_rom_delay_us(DELAY_SLOW_CLK_SWITCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_slow_freq_t rtc_clk_slow_freq_get(void)
|
||||||
|
{
|
||||||
|
return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rtc_clk_slow_freq_get_hz(void)
|
||||||
|
{
|
||||||
|
switch (rtc_clk_slow_freq_get()) {
|
||||||
|
case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_150K;
|
||||||
|
case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K;
|
||||||
|
case RTC_SLOW_FREQ_8MD256: return RTC_SLOW_CLK_FREQ_8MD256;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq)
|
||||||
|
{
|
||||||
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq);
|
||||||
|
esp_rom_delay_us(DELAY_FAST_CLK_SWITCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_fast_freq_t rtc_clk_fast_freq_get(void)
|
||||||
|
{
|
||||||
|
return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rtc_clk_bbpll_disable(void)
|
||||||
|
{
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
|
||||||
|
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
|
||||||
|
s_cur_pll_freq = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rtc_clk_bbpll_enable(void)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BB_I2C_FORCE_PD |
|
||||||
|
RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_bbpll_configure(rtc_xtal_freq_t xtal_freq, int pll_freq)
|
||||||
|
{
|
||||||
|
uint8_t div_ref;
|
||||||
|
uint8_t div7_0;
|
||||||
|
uint8_t dr1;
|
||||||
|
uint8_t dr3;
|
||||||
|
uint8_t dchgp;
|
||||||
|
uint8_t dcur;
|
||||||
|
uint8_t dbias;
|
||||||
|
|
||||||
|
CLEAR_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_HIGH);
|
||||||
|
SET_PERI_REG_MASK(I2C_MST_ANA_CONF0_REG, I2C_MST_BBPLL_STOP_FORCE_LOW);
|
||||||
|
if (pll_freq == RTC_PLL_FREQ_480M) {
|
||||||
|
/* Set this register to let the digital part know 480M PLL is used */
|
||||||
|
// SET_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396
|
||||||
|
/* Configure 480M PLL */
|
||||||
|
switch (xtal_freq) {
|
||||||
|
case RTC_XTAL_FREQ_40M:
|
||||||
|
div_ref = 0;
|
||||||
|
div7_0 = 8;
|
||||||
|
dr1 = 0;
|
||||||
|
dr3 = 0;
|
||||||
|
dchgp = 5;
|
||||||
|
dcur = 3;
|
||||||
|
dbias = 2;
|
||||||
|
break;
|
||||||
|
case RTC_XTAL_FREQ_32M:
|
||||||
|
div_ref = 1;
|
||||||
|
div7_0 = 26;
|
||||||
|
dr1 = 1;
|
||||||
|
dr3 = 1;
|
||||||
|
dchgp = 4;
|
||||||
|
dcur = 0;
|
||||||
|
dbias = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
div_ref = 0;
|
||||||
|
div7_0 = 8;
|
||||||
|
dr1 = 0;
|
||||||
|
dr3 = 0;
|
||||||
|
dchgp = 5;
|
||||||
|
dcur = 3;
|
||||||
|
dbias = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x6B);
|
||||||
|
} else {
|
||||||
|
/* Clear this register to let the digital part know 320M PLL is used */
|
||||||
|
// CLEAR_PERI_REG_MASK(SYSTEM_CPU_PER_CONF_REG, SYSTEM_PLL_FREQ_SEL); // ESP32H2-TODO: IDF-3396
|
||||||
|
/* Configure 320M PLL */
|
||||||
|
switch (xtal_freq) {
|
||||||
|
case RTC_XTAL_FREQ_40M:
|
||||||
|
div_ref = 0;
|
||||||
|
div7_0 = 4;
|
||||||
|
dr1 = 0;
|
||||||
|
dr3 = 0;
|
||||||
|
dchgp = 5;
|
||||||
|
dcur = 3;
|
||||||
|
dbias = 2;
|
||||||
|
break;
|
||||||
|
case RTC_XTAL_FREQ_32M:
|
||||||
|
div_ref = 1;
|
||||||
|
div7_0 = 6;
|
||||||
|
dr1 = 0;
|
||||||
|
dr3 = 0;
|
||||||
|
dchgp = 5;
|
||||||
|
dcur = 3;
|
||||||
|
dbias = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
div_ref = 0;
|
||||||
|
div7_0 = 4;
|
||||||
|
dr1 = 0;
|
||||||
|
dr3 = 0;
|
||||||
|
dchgp = 5;
|
||||||
|
dcur = 3;
|
||||||
|
dbias = 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_MODE_HF, 0x69);
|
||||||
|
}
|
||||||
|
uint8_t i2c_bbpll_lref = (dchgp << I2C_BBPLL_OC_DCHGP_LSB) | (div_ref);
|
||||||
|
uint8_t i2c_bbpll_div_7_0 = div7_0;
|
||||||
|
uint8_t i2c_bbpll_dcur = (2 << I2C_BBPLL_OC_DLREF_SEL_LSB ) | (1 << I2C_BBPLL_OC_DHREF_SEL_LSB) | dcur;
|
||||||
|
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_REF_DIV, i2c_bbpll_lref);
|
||||||
|
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
|
||||||
|
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR1, dr1);
|
||||||
|
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DR3, dr3);
|
||||||
|
REGI2C_WRITE(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
|
||||||
|
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_VCO_DBIAS, dbias);
|
||||||
|
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DHREF_SEL, 2);
|
||||||
|
REGI2C_WRITE_MASK(I2C_BBPLL, I2C_BBPLL_OC_DLREF_SEL, 1);
|
||||||
|
|
||||||
|
s_cur_pll_freq = pll_freq;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
|
||||||
|
* PLL must already be enabled.
|
||||||
|
* @param cpu_freq new CPU frequency
|
||||||
|
*/
|
||||||
|
static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
|
||||||
|
{
|
||||||
|
// int per_conf = DPORT_CPUPERIOD_SEL_80;
|
||||||
|
if (cpu_freq_mhz == 80) {
|
||||||
|
/* nothing to do */
|
||||||
|
} else if (cpu_freq_mhz == 160) {
|
||||||
|
// per_conf = DPORT_CPUPERIOD_SEL_160;
|
||||||
|
} else {
|
||||||
|
SOC_LOGE(TAG, "invalid frequency");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
// REG_SET_FIELD(SYSTEM_CPU_PER_CONF_REG, SYSTEM_CPUPERIOD_SEL, per_conf); // ESP32H2-TODO: IDF-3396
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_PLL);
|
||||||
|
rtc_clk_apb_freq_update(80 * MHZ);
|
||||||
|
ets_update_cpu_frequency(cpu_freq_mhz);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *out_config)
|
||||||
|
{
|
||||||
|
uint32_t source_freq_mhz;
|
||||||
|
rtc_cpu_freq_src_t source;
|
||||||
|
uint32_t divider;
|
||||||
|
uint32_t real_freq_mhz;
|
||||||
|
|
||||||
|
uint32_t xtal_freq = (uint32_t) rtc_clk_xtal_freq_get();
|
||||||
|
if (freq_mhz <= xtal_freq) {
|
||||||
|
divider = xtal_freq / freq_mhz;
|
||||||
|
real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
|
||||||
|
if (real_freq_mhz != freq_mhz) {
|
||||||
|
// no suitable divider
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
source_freq_mhz = xtal_freq;
|
||||||
|
source = RTC_CPU_FREQ_SRC_XTAL;
|
||||||
|
} else if (freq_mhz == 80) {
|
||||||
|
real_freq_mhz = freq_mhz;
|
||||||
|
source = RTC_CPU_FREQ_SRC_PLL;
|
||||||
|
source_freq_mhz = RTC_PLL_FREQ_480M;
|
||||||
|
divider = 6;
|
||||||
|
} else if (freq_mhz == 160) {
|
||||||
|
real_freq_mhz = freq_mhz;
|
||||||
|
source = RTC_CPU_FREQ_SRC_PLL;
|
||||||
|
source_freq_mhz = RTC_PLL_FREQ_480M;
|
||||||
|
divider = 3;
|
||||||
|
} else {
|
||||||
|
// unsupported frequency
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
*out_config = (rtc_cpu_freq_config_t) {
|
||||||
|
.source = source,
|
||||||
|
.div = divider,
|
||||||
|
.source_freq_mhz = source_freq_mhz,
|
||||||
|
.freq_mhz = real_freq_mhz
|
||||||
|
};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
|
||||||
|
{
|
||||||
|
uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
|
||||||
|
if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
|
||||||
|
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||||
|
if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) {
|
||||||
|
rtc_clk_bbpll_disable();
|
||||||
|
}
|
||||||
|
} else if (config->source == RTC_CPU_FREQ_SRC_PLL) {
|
||||||
|
if (soc_clk_sel != DPORT_SOC_CLK_SEL_PLL) {
|
||||||
|
rtc_clk_bbpll_enable();
|
||||||
|
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
|
||||||
|
}
|
||||||
|
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||||
|
} else if (config->source == RTC_CPU_FREQ_SRC_8M) {
|
||||||
|
rtc_clk_cpu_freq_to_8m();
|
||||||
|
if (soc_clk_sel == DPORT_SOC_CLK_SEL_PLL) {
|
||||||
|
rtc_clk_bbpll_disable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
|
||||||
|
{
|
||||||
|
rtc_cpu_freq_src_t source;
|
||||||
|
uint32_t source_freq_mhz;
|
||||||
|
uint32_t div;
|
||||||
|
uint32_t freq_mhz;
|
||||||
|
uint32_t soc_clk_sel = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL);
|
||||||
|
switch (soc_clk_sel) {
|
||||||
|
case DPORT_SOC_CLK_SEL_XTAL: {
|
||||||
|
source = RTC_CPU_FREQ_SRC_XTAL;
|
||||||
|
div = REG_GET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT) + 1;
|
||||||
|
source_freq_mhz = (uint32_t) rtc_clk_xtal_freq_get();
|
||||||
|
freq_mhz = source_freq_mhz / div;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case DPORT_SOC_CLK_SEL_PLL: {
|
||||||
|
// ESP32H2-TODO: IDF-3396
|
||||||
|
source = 0;
|
||||||
|
div = 0;
|
||||||
|
source_freq_mhz = 0;
|
||||||
|
freq_mhz = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case DPORT_SOC_CLK_SEL_8M:
|
||||||
|
source = RTC_CPU_FREQ_SRC_8M;
|
||||||
|
source_freq_mhz = 8;
|
||||||
|
div = 1;
|
||||||
|
freq_mhz = source_freq_mhz;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
SOC_LOGE(TAG, "unsupported frequency configuration");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
*out_config = (rtc_cpu_freq_config_t) {
|
||||||
|
.source = source,
|
||||||
|
.source_freq_mhz = source_freq_mhz,
|
||||||
|
.div = div,
|
||||||
|
.freq_mhz = freq_mhz
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
|
||||||
|
{
|
||||||
|
if (config->source == RTC_CPU_FREQ_SRC_XTAL) {
|
||||||
|
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||||
|
} else if (config->source == RTC_CPU_FREQ_SRC_PLL &&
|
||||||
|
s_cur_pll_freq == config->source_freq_mhz) {
|
||||||
|
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||||
|
} else {
|
||||||
|
/* fallback */
|
||||||
|
rtc_clk_cpu_freq_set_config(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_cpu_freq_set_xtal(void)
|
||||||
|
{
|
||||||
|
int freq_mhz = (int) rtc_clk_xtal_freq_get();
|
||||||
|
|
||||||
|
rtc_clk_cpu_freq_to_xtal(freq_mhz, 1);
|
||||||
|
rtc_clk_bbpll_disable();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switch to XTAL frequency. Does not disable the PLL.
|
||||||
|
*/
|
||||||
|
void rtc_clk_cpu_freq_to_xtal(int freq, int div)
|
||||||
|
{
|
||||||
|
ets_update_cpu_frequency(freq);
|
||||||
|
/* Set divider from XTAL to APB clock. Need to set divider to 1 (reg. value 0) first. */
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, div - 1);
|
||||||
|
/* no need to adjust the REF_TICK */
|
||||||
|
/* switch clock source */
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_XTAL);
|
||||||
|
rtc_clk_apb_freq_update(freq * MHZ);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void rtc_clk_cpu_freq_to_8m(void)
|
||||||
|
{
|
||||||
|
ets_update_cpu_frequency(8);
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_PRE_DIV_CNT, 0);
|
||||||
|
REG_SET_FIELD(SYSTEM_SYSCLK_CONF_REG, SYSTEM_SOC_CLK_SEL, DPORT_SOC_CLK_SEL_8M);
|
||||||
|
rtc_clk_apb_freq_update(RTC_FAST_CLK_FREQ_8M);
|
||||||
|
}
|
||||||
|
|
||||||
|
rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
|
||||||
|
{
|
||||||
|
uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG);
|
||||||
|
if (!clk_val_is_valid(xtal_freq_reg)) {
|
||||||
|
SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg);
|
||||||
|
return RTC_XTAL_FREQ_40M;
|
||||||
|
}
|
||||||
|
return reg_val_to_clk_val(xtal_freq_reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
|
||||||
|
{
|
||||||
|
WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq));
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_apb_freq_update(uint32_t apb_freq)
|
||||||
|
{
|
||||||
|
WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rtc_clk_apb_freq_get(void)
|
||||||
|
{
|
||||||
|
uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12;
|
||||||
|
// round to the nearest MHz
|
||||||
|
freq_hz += MHZ / 2;
|
||||||
|
uint32_t remainder = freq_hz % MHZ;
|
||||||
|
return freq_hz - remainder;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_divider_set(uint32_t div)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV, div);
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_SLOW_CLK_CONF_REG, RTC_CNTL_ANA_CLK_DIV_VLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_clk_8m_divider_set(uint32_t div)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, div);
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL_VLD);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_dig_clk8m_enable(void)
|
||||||
|
{
|
||||||
|
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||||
|
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rtc_dig_clk8m_disable(void)
|
||||||
|
{
|
||||||
|
CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||||
|
esp_rom_delay_us(DELAY_RTC_CLK_SWITCH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Name used in libphy.a:phy_chip_v7.o
|
||||||
|
* TODO: update the library to use rtc_clk_xtal_freq_get
|
||||||
|
*/
|
||||||
|
rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
|
57
components/esp_hw_support/port/esp32h2/rtc_clk_common.h
Normal file
57
components/esp_hw_support/port/esp32h2/rtc_clk_common.h
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
#define MHZ (1000000)
|
||||||
|
|
||||||
|
#define DPORT_CPUPERIOD_SEL_80 0
|
||||||
|
#define DPORT_CPUPERIOD_SEL_160 1
|
||||||
|
|
||||||
|
#define DPORT_SOC_CLK_SEL_XTAL 0
|
||||||
|
#define DPORT_SOC_CLK_SEL_PLL 1
|
||||||
|
#define DPORT_SOC_CLK_SEL_8M 2
|
||||||
|
|
||||||
|
#define RTC_FAST_CLK_FREQ_8M 8500000
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void rtc_clk_cpu_freq_to_xtal(int freq, int div);
|
||||||
|
|
||||||
|
/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in
|
||||||
|
* lower and upper 16-bit halves. These are the routines to work with such a
|
||||||
|
* representation.
|
||||||
|
*/
|
||||||
|
static inline bool clk_val_is_valid(uint32_t val)
|
||||||
|
{
|
||||||
|
return (val & 0xffff) == ((val >> 16) & 0xffff) &&
|
||||||
|
val != 0 &&
|
||||||
|
val != UINT32_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t reg_val_to_clk_val(uint32_t val)
|
||||||
|
{
|
||||||
|
return val & UINT16_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline uint32_t clk_val_to_reg_val(uint32_t val)
|
||||||
|
{
|
||||||
|
return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
88
components/esp_hw_support/port/esp32h2/rtc_clk_init.c
Normal file
88
components/esp_hw_support/port/esp32h2/rtc_clk_init.c
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
// 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 <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "esp32h2/rom/ets_sys.h"
|
||||||
|
#include "esp32h2/rom/rtc.h"
|
||||||
|
#include "esp32h2/rom/uart.h"
|
||||||
|
#include "soc/rtc.h"
|
||||||
|
#include "soc/rtc_periph.h"
|
||||||
|
#include "soc/efuse_periph.h"
|
||||||
|
#include "soc/apb_ctrl_reg.h"
|
||||||
|
#include "hal/cpu_hal.h"
|
||||||
|
#include "regi2c_ctrl.h"
|
||||||
|
#include "soc_log.h"
|
||||||
|
#include "sdkconfig.h"
|
||||||
|
#include "rtc_clk_common.h"
|
||||||
|
#include "esp_rom_uart.h"
|
||||||
|
|
||||||
|
static const char *TAG = "rtc_clk_init";
|
||||||
|
|
||||||
|
void rtc_clk_init(rtc_clk_config_t cfg)
|
||||||
|
{
|
||||||
|
rtc_cpu_freq_config_t old_config, new_config;
|
||||||
|
|
||||||
|
/* Set tuning parameters for 8M and 150k clocks.
|
||||||
|
* Note: this doesn't attempt to set the clocks to precise frequencies.
|
||||||
|
* Instead, we calibrate these clocks against XTAL frequency later, when necessary.
|
||||||
|
* - SCK_DCAP value controls tuning of 150k clock.
|
||||||
|
* The higher the value of DCAP is, the lower is the frequency.
|
||||||
|
* - CK8M_DFREQ value controls tuning of 8M clock.
|
||||||
|
* CLK_8M_DFREQ constant gives the best temperature characteristics.
|
||||||
|
*/
|
||||||
|
REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap);
|
||||||
|
REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq);
|
||||||
|
|
||||||
|
/* Configure 150k clock division */
|
||||||
|
rtc_clk_divider_set(cfg.clk_rtc_clk_div);
|
||||||
|
|
||||||
|
/* Configure 8M clock division */
|
||||||
|
rtc_clk_8m_divider_set(cfg.clk_8m_clk_div);
|
||||||
|
|
||||||
|
/* Enable the internal bus used to configure PLLs */
|
||||||
|
SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S);
|
||||||
|
CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, ANA_I2C_APLL_M | ANA_I2C_BBPLL_M);
|
||||||
|
|
||||||
|
rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
|
||||||
|
esp_rom_uart_tx_wait_idle(0);
|
||||||
|
rtc_clk_xtal_freq_update(xtal_freq);
|
||||||
|
rtc_clk_apb_freq_update(xtal_freq * MHZ);
|
||||||
|
|
||||||
|
/* Set CPU frequency */
|
||||||
|
rtc_clk_cpu_freq_get_config(&old_config);
|
||||||
|
uint32_t freq_before = old_config.freq_mhz;
|
||||||
|
bool res = rtc_clk_cpu_freq_mhz_to_config(cfg.cpu_freq_mhz, &new_config);
|
||||||
|
if (!res) {
|
||||||
|
SOC_LOGE(TAG, "invalid CPU frequency value");
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
rtc_clk_cpu_freq_set_config(&new_config);
|
||||||
|
|
||||||
|
/* Re-calculate the ccount to make time calculation correct. */
|
||||||
|
cpu_hal_set_cycle_count( (uint64_t)cpu_hal_get_cycle_count() * cfg.cpu_freq_mhz / freq_before );
|
||||||
|
|
||||||
|
/* Slow & fast clocks setup */
|
||||||
|
if (cfg.slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
|
||||||
|
rtc_clk_32k_enable(true);
|
||||||
|
}
|
||||||
|
if (cfg.fast_freq == RTC_FAST_FREQ_8M) {
|
||||||
|
bool need_8md256 = cfg.slow_freq == RTC_SLOW_FREQ_8MD256;
|
||||||
|
rtc_clk_8m_enable(true, need_8md256);
|
||||||
|
}
|
||||||
|
rtc_clk_fast_freq_set(cfg.fast_freq);
|
||||||
|
rtc_clk_slow_freq_set(cfg.slow_freq);
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user