mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Merge branch 'feature/esp32s2beta_merge' into 'master'
esp32s2beta: Merge support to master Closes IDF-513, IDF-756, IDF-758, IDF-999, IDF-753, IDF-749, IDF-754, IDF-840, and IDF-755 See merge request espressif/esp-idf!6100
This commit is contained in:
commit
055cc251b7
@ -26,7 +26,8 @@ variables:
|
||||
# If the "recursive" strategy is used we have a problem with using relative URLs for sub-submodules.
|
||||
GIT_SUBMODULE_STRATEGY: normal
|
||||
|
||||
UNIT_TEST_BUILD_SYSTEM: make
|
||||
UNIT_TEST_BUILD_SYSTEM: cmake
|
||||
EXAMPLE_TEST_BUILD_SYSTEM: cmake
|
||||
# IDF environment
|
||||
|
||||
IDF_PATH: "$CI_PROJECT_DIR"
|
||||
|
5
.gitmodules
vendored
5
.gitmodules
vendored
@ -71,6 +71,10 @@
|
||||
path = components/esp_wifi/lib_esp32
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/esp_wifi/lib_esp32s2beta"]
|
||||
path = components/esp_wifi/lib_esp32s2beta
|
||||
url = ../../espressif/esp32-wifi-lib.git
|
||||
|
||||
[submodule "components/bt/host/nimble/nimble"]
|
||||
path = components/bt/host/nimble/nimble
|
||||
url = ../../espressif/esp-nimble.git
|
||||
@ -78,3 +82,4 @@
|
||||
[submodule "components/cbor/tinycbor"]
|
||||
path = components/cbor/tinycbor
|
||||
url = ../../intel/tinycbor.git
|
||||
|
||||
|
18
Kconfig
18
Kconfig
@ -29,15 +29,29 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "IDF_TARGET_NOT_SET" if IDF_TARGET_ENV=""
|
||||
default IDF_TARGET_ENV
|
||||
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
default "n"
|
||||
|
||||
config IDF_TARGET_ESP32S2BETA
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s2beta"
|
||||
default "n"
|
||||
select FREERTOS_UNICORE
|
||||
|
||||
config IDF_FIRMWARE_CHIP_ID
|
||||
hex
|
||||
default 0x0000 if IDF_TARGET="esp32"
|
||||
default 0x0000 if IDF_TARGET_ESP32
|
||||
# note: S2 beta uses Chip ID 0 still, S2 will use 0x0002
|
||||
default 0x0000 if IDF_TARGET_ESP32S2BETA
|
||||
default 0xFFFF
|
||||
|
||||
menu "SDK tool configuration"
|
||||
config SDK_TOOLPREFIX
|
||||
string "Compiler toolchain path/prefix"
|
||||
default "xtensa-esp32-elf-"
|
||||
default "xtensa-esp32-elf-" if IDF_TARGET_ESP32
|
||||
default "xtensa-esp32s2-elf-" if IDF_TARGET_ESP32S2BETA
|
||||
help
|
||||
The prefix/path that is used to call the toolchain. The default setting assumes
|
||||
a crosstool-ng gcc setup that is in your PATH.
|
||||
|
@ -15,7 +15,12 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////// TIMEOUT /////////////////////////////////////
|
||||
|
@ -65,6 +65,8 @@ Revision: $Rev: 5927 $
|
||||
#ifndef SEGGER_SYSVIEW_CONF_H
|
||||
#define SEGGER_SYSVIEW_CONF_H
|
||||
|
||||
#include "soc/soc.h"
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* Defines, fixed
|
||||
@ -147,7 +149,7 @@ Revision: $Rev: 5927 $
|
||||
* SystemView Id configuration
|
||||
*/
|
||||
//TODO: optimise it
|
||||
#define SEGGER_SYSVIEW_ID_BASE 0x3F400000 // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
|
||||
#define SEGGER_SYSVIEW_ID_BASE SOC_DROM_LOW // Default value for the lowest Id reported by the application. Can be overridden by the application via SEGGER_SYSVIEW_SetRAMBase(). (i.e. 0x20000000 when all Ids are an address in this RAM)
|
||||
#define SEGGER_SYSVIEW_ID_SHIFT 0 // Number of bits to shift the Id to save bandwidth. (i.e. 2 when Ids are 4 byte aligned)
|
||||
|
||||
/*********************************************************************
|
||||
|
@ -63,11 +63,19 @@ Revision: $Rev: 3734 $
|
||||
*/
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "SEGGER_SYSVIEW.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp_app_trace.h"
|
||||
#include "esp_app_trace_util.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/interrupts.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp32/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/clk.h"
|
||||
#endif
|
||||
|
||||
|
||||
extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
@ -81,7 +89,7 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
#define SYSVIEW_APP_NAME "FreeRTOS Application"
|
||||
|
||||
// The target device name
|
||||
#define SYSVIEW_DEVICE_NAME "ESP32"
|
||||
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
|
||||
|
||||
// Determine which timer to use as timestamp source
|
||||
#if CONFIG_SYSVIEW_TS_SOURCE_CCOUNT
|
||||
@ -123,14 +131,19 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
#if TS_USE_CCOUNT
|
||||
// CCOUNT is incremented at CPU frequency
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SYSVIEW_TIMESTAMP_FREQ (CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ * 1000000)
|
||||
#endif
|
||||
|
||||
#endif // TS_USE_CCOUNT
|
||||
|
||||
// System Frequency.
|
||||
#define SYSVIEW_CPU_FREQ (esp_clk_cpu_freq())
|
||||
|
||||
// The lowest RAM address used for IDs (pointers)
|
||||
#define SYSVIEW_RAM_BASE (0x3F400000)
|
||||
#define SYSVIEW_RAM_BASE (SOC_DROM_LOW)
|
||||
|
||||
#if CONFIG_FREERTOS_CORETIMER_0
|
||||
#define SYSTICK_INTR_ID (ETS_INTERNAL_TIMER0_INTR_SOURCE+ETS_INTERNAL_INTR_SOURCE_OFF)
|
||||
@ -147,78 +160,6 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
|
||||
|
||||
static esp_apptrace_lock_t s_sys_view_lock = {.mux = portMUX_INITIALIZER_UNLOCKED, .int_state = 0};
|
||||
|
||||
static const char * const s_isr_names[] = {
|
||||
[0] = "WIFI_MAC",
|
||||
[1] = "WIFI_NMI",
|
||||
[2] = "WIFI_BB",
|
||||
[3] = "BT_MAC",
|
||||
[4] = "BT_BB",
|
||||
[5] = "BT_BB_NMI",
|
||||
[6] = "RWBT",
|
||||
[7] = "RWBLE",
|
||||
[8] = "RWBT_NMI",
|
||||
[9] = "RWBLE_NMI",
|
||||
[10] = "SLC0",
|
||||
[11] = "SLC1",
|
||||
[12] = "UHCI0",
|
||||
[13] = "UHCI1",
|
||||
[14] = "TG0_T0_LEVEL",
|
||||
[15] = "TG0_T1_LEVEL",
|
||||
[16] = "TG0_WDT_LEVEL",
|
||||
[17] = "TG0_LACT_LEVEL",
|
||||
[18] = "TG1_T0_LEVEL",
|
||||
[19] = "TG1_T1_LEVEL",
|
||||
[20] = "TG1_WDT_LEVEL",
|
||||
[21] = "TG1_LACT_LEVEL",
|
||||
[22] = "GPIO",
|
||||
[23] = "GPIO_NMI",
|
||||
[24] = "FROM_CPU0",
|
||||
[25] = "FROM_CPU1",
|
||||
[26] = "FROM_CPU2",
|
||||
[27] = "FROM_CPU3",
|
||||
[28] = "SPI0",
|
||||
[29] = "SPI1",
|
||||
[30] = "SPI2",
|
||||
[31] = "SPI3",
|
||||
[32] = "I2S0",
|
||||
[33] = "I2S1",
|
||||
[34] = "UART0",
|
||||
[35] = "UART1",
|
||||
[36] = "UART2",
|
||||
[37] = "SDIO_HOST",
|
||||
[38] = "ETH_MAC",
|
||||
[39] = "PWM0",
|
||||
[40] = "PWM1",
|
||||
[41] = "PWM2",
|
||||
[42] = "PWM3",
|
||||
[43] = "LEDC",
|
||||
[44] = "EFUSE",
|
||||
[45] = "CAN",
|
||||
[46] = "RTC_CORE",
|
||||
[47] = "RMT",
|
||||
[48] = "PCNT",
|
||||
[49] = "I2C_EXT0",
|
||||
[50] = "I2C_EXT1",
|
||||
[51] = "RSA",
|
||||
[52] = "SPI1_DMA",
|
||||
[53] = "SPI2_DMA",
|
||||
[54] = "SPI3_DMA",
|
||||
[55] = "WDT",
|
||||
[56] = "TIMER1",
|
||||
[57] = "TIMER2",
|
||||
[58] = "TG0_T0_EDGE",
|
||||
[59] = "TG0_T1_EDGE",
|
||||
[60] = "TG0_WDT_EDGE",
|
||||
[61] = "TG0_LACT_EDGE",
|
||||
[62] = "TG1_T0_EDGE",
|
||||
[63] = "TG1_T1_EDGE",
|
||||
[64] = "TG1_WDT_EDGE",
|
||||
[65] = "TG1_LACT_EDGE",
|
||||
[66] = "MMU_IA",
|
||||
[67] = "MPU_IA",
|
||||
[68] = "CACHE_IA",
|
||||
};
|
||||
|
||||
/*********************************************************************
|
||||
*
|
||||
* _cbSendSystemDesc()
|
||||
@ -231,9 +172,9 @@ static void _cbSendSystemDesc(void) {
|
||||
SEGGER_SYSVIEW_SendSysDesc("N="SYSVIEW_APP_NAME",D="SYSVIEW_DEVICE_NAME",C=Xtensa,O=FreeRTOS");
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=SysTick", SYSTICK_INTR_ID);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
size_t isr_count = sizeof(s_isr_names)/sizeof(s_isr_names[0]);
|
||||
size_t isr_count = sizeof(esp_isr_names)/sizeof(esp_isr_names[0]);
|
||||
for (size_t i = 0; i < isr_count; ++i) {
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, s_isr_names[i]);
|
||||
snprintf(irq_str, sizeof(irq_str), "I#%d=%s", ETS_INTERNAL_INTR_SOURCE_OFF + i, esp_isr_names[i]);
|
||||
SEGGER_SYSVIEW_SendSysDesc(irq_str);
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,5 @@
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
idf_component_register(SRC_DIRS "."
|
||||
INCLUDE_DIRS "."
|
||||
REQUIRES unity test_utils app_update bootloader_support nvs_flash)
|
||||
endif()
|
||||
|
@ -7,9 +7,13 @@
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
@ -204,10 +204,13 @@ menu "Bootloader config"
|
||||
config BOOTLOADER_APP_SEC_VER_SIZE_EFUSE_FIELD
|
||||
int "Size of the efuse secure version field"
|
||||
depends on BOOTLOADER_APP_ANTI_ROLLBACK
|
||||
range 1 32
|
||||
default 32
|
||||
range 1 32 if IDF_TARGET_ESP32
|
||||
default 32 if IDF_TARGET_ESP32
|
||||
range 1 16 if IDF_TARGET_ESP32S2BETA
|
||||
default 16 if IDF_TARGET_ESP32S2BETA
|
||||
help
|
||||
The size of the efuse secure version field. Its length is limited to 32 bits.
|
||||
The size of the efuse secure version field.
|
||||
Its length is limited to 32 bits for ESP32 and 16 bits for ESP32S2BETA.
|
||||
This determines how many times the security version can be increased.
|
||||
|
||||
config BOOTLOADER_EFUSE_SECURE_VERSION_EMULATE
|
||||
@ -462,6 +465,26 @@ menu "Security features"
|
||||
Read https://docs.espressif.com/projects/esp-idf/en/latest/security/flash-encryption.html
|
||||
before enabling.
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_KEYSIZE
|
||||
bool "Size of generated AES-XTS key"
|
||||
default SECURE_FLASH_ENCRYPTION_AES128
|
||||
depends on IDF_TARGET_ESP32S2BETA && SECURE_FLASH_ENC_ENABLED
|
||||
help
|
||||
Size of generated AES-XTS key.
|
||||
|
||||
AES-128 uses a 256-bit key (32 bytes) which occupies one Efuse key block.
|
||||
AES-256 uses a 512-bit key (64 bytes) which occupies two Efuse key blocks.
|
||||
|
||||
This setting is ignored if either type of key is already burned to Efuse before the first boot.
|
||||
In this case, the pre-burned key is used and no new key is generated.
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_AES128
|
||||
bool "AES-128 (256-bit key)"
|
||||
|
||||
config SECURE_FLASH_ENCRYPTION_AES256
|
||||
bool "AES-256 (512-bit key)"
|
||||
endchoice
|
||||
|
||||
choice SECURE_FLASH_ENCRYPTION_MODE
|
||||
bool "Enable usage mode"
|
||||
depends on SECURE_FLASH_ENC_ENABLED
|
||||
|
@ -2,7 +2,8 @@ idf_component_register(SRCS "bootloader_start.c"
|
||||
REQUIRES bootloader bootloader_support)
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
set(scripts "${target}.bootloader.ld"
|
||||
"${target}.bootloader.rom.ld")
|
||||
set(scripts "ld/${target}/bootloader.ld"
|
||||
"ld/${target}/bootloader.rom.ld")
|
||||
|
||||
target_linker_script(${COMPONENT_LIB} INTERFACE "${scripts}")
|
||||
|
||||
|
@ -14,17 +14,22 @@
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "esp_log.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_init.h"
|
||||
#include "bootloader_utility.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
static const char *TAG = "boot";
|
||||
|
||||
|
@ -6,15 +6,18 @@
|
||||
#
|
||||
|
||||
LINKER_SCRIPTS := \
|
||||
$(IDF_TARGET).bootloader.ld \
|
||||
$(IDF_TARGET).bootloader.rom.ld \
|
||||
$(COMPONENT_PATH)/ld/$(IDF_TARGET)/bootloader.ld \
|
||||
$(COMPONENT_PATH)/ld/$(IDF_TARGET)/bootloader.rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.ld \
|
||||
$(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.newlib-funcs.ld \
|
||||
$(IDF_PATH)/components/$(IDF_TARGET)/ld/$(IDF_TARGET).peripherals.ld
|
||||
|
||||
# SPI driver patch for ROM is only needed in ESP32
|
||||
ifdef CONFIG_IDF_TARGET_ESP32
|
||||
ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
|
||||
LINKER_SCRIPTS += $(IDF_PATH)/components/esp_rom/$(IDF_TARGET)/ld/$(IDF_TARGET).rom.spiflash.ld
|
||||
endif
|
||||
endif
|
||||
|
||||
COMPONENT_ADD_LDFLAGS += -L $(COMPONENT_PATH) $(addprefix -T ,$(LINKER_SCRIPTS))
|
||||
|
||||
|
@ -0,0 +1,162 @@
|
||||
/*
|
||||
Linker file used to link the bootloader.
|
||||
*/
|
||||
|
||||
|
||||
/* Simplified memory map for the bootloader
|
||||
|
||||
The main purpose is to make sure the bootloader can load into main memory
|
||||
without overwriting itself.
|
||||
*/
|
||||
|
||||
MEMORY
|
||||
{
|
||||
/* I/O */
|
||||
dport0_seg (RW) : org = 0x3FF00000, len = 0x10
|
||||
iram_loader_seg (RWX) : org = 0x40062000, len = 0x4000 /* 16KB, IRAM */
|
||||
iram_seg (RWX) : org = 0x40066000, len = 0x4000 /* 16KB, IRAM */
|
||||
/* 8k at the end of DRAM, before ROM data & stack */
|
||||
dram_seg (RW) : org = 0x3FFFA000, len = 0x2000
|
||||
}
|
||||
|
||||
/* 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_common.*(.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_utility.*(.literal .text .literal.* .text.*)
|
||||
*libbootloader_support.a:bootloader_sha.*(.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.*(.literal .text .literal.* .text.*)
|
||||
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
|
||||
*libsoc.a:rtc_wdt.*(.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);
|
||||
_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);
|
||||
_heap_start = 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)
|
||||
_text_end = ABSOLUTE(.);
|
||||
_etext = .;
|
||||
} > iram_seg
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
/*
|
||||
* ESP32S2 ROM address table
|
||||
* Generated for ROM with MD5sum: f054d40c5f6b9207d3827460a6f5748c
|
||||
*/
|
||||
PROVIDE ( ets_update_cpu_frequency = 0x4000d954 );
|
||||
|
||||
/* ToDo: Following address may need modification */
|
||||
PROVIDE ( MD5Final = 0x400056e8 );
|
||||
PROVIDE ( MD5Init = 0x40005648 );
|
||||
PROVIDE ( MD5Update = 0x40005668 );
|
||||
/* bootloader will use following functions from xtensa hal library */
|
||||
xthal_get_ccount = 0x40015cbc;
|
||||
xthal_get_ccompare = 0x40015ce8;
|
||||
xthal_set_ccompare = 0x40015cc4;
|
@ -2,34 +2,43 @@ set(srcs
|
||||
"src/bootloader_clock.c"
|
||||
"src/bootloader_common.c"
|
||||
"src/bootloader_flash.c"
|
||||
"src/bootloader_flash_config.c"
|
||||
"src/bootloader_random.c"
|
||||
"src/bootloader_utility.c"
|
||||
"src/esp_image_format.c"
|
||||
"src/flash_encrypt.c"
|
||||
"src/flash_partitions.c"
|
||||
"src/flash_qio_mode.c")
|
||||
"src/flash_qio_mode.c"
|
||||
"src/bootloader_flash_config_${IDF_TARGET}.c"
|
||||
"src/bootloader_efuse_${IDF_TARGET}.c"
|
||||
)
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
# Not supported on ESP32S2Beta yet
|
||||
list(APPEND srcs "src/flash_encrypt.c")
|
||||
endif()
|
||||
|
||||
if(BOOTLOADER_BUILD)
|
||||
set(include_dirs "include" "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires micro-ecc spi_flash efuse)
|
||||
# freertos is included just for the CONFIG_FREERTOS_UNICORE macro
|
||||
set(priv_requires micro-ecc spi_flash efuse freertos)
|
||||
list(APPEND srcs
|
||||
"src/bootloader_init.c"
|
||||
"src/${IDF_TARGET}/bootloader_sha.c"
|
||||
"src/${IDF_TARGET}/flash_encrypt.c"
|
||||
"src/${IDF_TARGET}/secure_boot_signatures.c"
|
||||
"src/${IDF_TARGET}/secure_boot.c")
|
||||
"src/${IDF_TARGET}/secure_boot.c"
|
||||
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
|
||||
)
|
||||
else()
|
||||
list(APPEND srcs
|
||||
"src/idf/bootloader_sha.c"
|
||||
"src/idf/secure_boot_signatures.c")
|
||||
set(include_dirs "include")
|
||||
set(priv_include_dirs "include_bootloader")
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
set(priv_requires spi_flash mbedtls efuse)
|
||||
endif()
|
||||
|
||||
set(requires soc) #unfortunately the header directly uses SOC registers
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "${include_dirs}"
|
||||
PRIV_INCLUDE_DIRS "${priv_include_dirs}"
|
||||
|
@ -19,6 +19,9 @@ ifndef IS_BOOTLOADER_BUILD
|
||||
COMPONENT_OBJEXCLUDE := src/bootloader_init.o
|
||||
endif
|
||||
|
||||
COMPONENT_OBJEXCLUDE += src/bootloader_flash_config_esp32s2beta.o \
|
||||
src/bootloader_efuse_esp32s2beta.o
|
||||
|
||||
#
|
||||
# Secure boot signing key support
|
||||
#
|
||||
@ -46,10 +49,10 @@ $(ORIG_SECURE_BOOT_VERIFICATION_KEY):
|
||||
$(SECURE_BOOT_VERIFICATION_KEY): $(ORIG_SECURE_BOOT_VERIFICATION_KEY) $(SDKCONFIG_MAKEFILE)
|
||||
$(summary) CP $< $@
|
||||
cp $< $@
|
||||
endif
|
||||
endif #CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES
|
||||
|
||||
COMPONENT_EXTRA_CLEAN += $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
COMPONENT_EMBED_FILES := $(SECURE_BOOT_VERIFICATION_KEY)
|
||||
|
||||
endif
|
||||
endif #CONFIG_SECURE_SIGNED_APPS
|
||||
|
@ -24,6 +24,11 @@ extern "C" {
|
||||
*/
|
||||
void bootloader_clock_configure(void);
|
||||
|
||||
/** @brief Return the rated maximum frequency of this chip
|
||||
*/
|
||||
int bootloader_clock_get_rated_freq_mhz(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -88,6 +88,13 @@ bool bootloader_common_erase_part_type_data(const char *list_erase, bool ota_dat
|
||||
*/
|
||||
bool bootloader_common_label_search(const char *list, char *label);
|
||||
|
||||
/**
|
||||
* @brief Configure default SPI pin modes and drive strengths
|
||||
*
|
||||
* @param drv GPIO drive level (determined by clock frequency)
|
||||
*/
|
||||
void bootloader_configure_spi_pins(int drv);
|
||||
|
||||
/**
|
||||
* @brief Calculates a sha-256 for a given partition or returns a appended digest.
|
||||
*
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "esp_spi_flash.h"
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -46,8 +47,14 @@ typedef enum {
|
||||
*
|
||||
* @return true if flash encryption is enabled.
|
||||
*/
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void) {
|
||||
uint32_t flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
static inline /** @cond */ IRAM_ATTR /** @endcond */ bool esp_flash_encryption_enabled(void)
|
||||
{
|
||||
uint32_t flash_crypt_cnt;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_BLK0_RDATA0_REG, EFUSE_RD_FLASH_CRYPT_CNT);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
flash_crypt_cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
#endif
|
||||
/* __builtin_parity is in flash, so we calculate parity inline */
|
||||
bool enabled = false;
|
||||
while (flash_crypt_cnt) {
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLED
|
||||
#if !defined(CONFIG_SECURE_SIGNED_ON_BOOT) || !defined(CONFIG_SECURE_SIGNED_ON_UPDATE) || !defined(CONFIG_SECURE_SIGNED_APPS)
|
||||
@ -36,14 +39,18 @@ extern "C" {
|
||||
|
||||
/** @brief Is secure boot currently enabled in hardware?
|
||||
*
|
||||
* Secure boot is enabled if the ABS_DONE_0 efuse is blown. This means
|
||||
* that the ROM bootloader code will only boot a verified secure
|
||||
* bootloader digest from now on.
|
||||
* This means that the ROM bootloader code will only boot
|
||||
* a verified secure bootloader from now on.
|
||||
*
|
||||
* @return true if secure boot is enabled.
|
||||
*/
|
||||
static inline bool esp_secure_boot_enabled(void) {
|
||||
static inline bool esp_secure_boot_enabled(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return REG_READ(EFUSE_BLK0_RDATA6_REG) & EFUSE_RD_ABS_DONE_0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return ets_efuse_secure_boot_enabled();
|
||||
#endif
|
||||
}
|
||||
|
||||
/** @brief Generate secure digest from bootloader image
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "bootloader_config.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_config.h"
|
||||
|
||||
/**
|
||||
* @brief Load partition table.
|
||||
@ -96,3 +97,14 @@ __attribute__((noreturn)) void bootloader_reset(void);
|
||||
* ESP_ERR_INVALID_ARG: Error in the passed arguments
|
||||
*/
|
||||
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len);
|
||||
|
||||
/**
|
||||
* @brief Debug log contents of a buffer as hexadecimal
|
||||
*
|
||||
* @note Only works if component log level is DEBUG or higher.
|
||||
*
|
||||
* @param buffer Buffer to log
|
||||
* @param length Length of buffer in bytes. Maximum length 128 bytes.
|
||||
* @param label Label to print at beginning of log line.
|
||||
*/
|
||||
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label);
|
||||
|
@ -11,13 +11,20 @@
|
||||
// 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 "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#else
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#endif
|
||||
|
||||
void bootloader_clock_configure(void)
|
||||
{
|
||||
// ROM bootloader may have put a lot of text into UART0 FIFO.
|
||||
@ -27,23 +34,30 @@ void bootloader_clock_configure(void)
|
||||
// and will be done with the bootloader much earlier than UART FIFO is empty.
|
||||
uart_tx_wait_idle(0);
|
||||
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
/* On ESP32 rev 0, switching to 80/160 MHz if clock was previously set to
|
||||
* 240 MHz may cause the chip to lock up (see section 3.5 of the errata
|
||||
* document). For rev. 0, switch to 240 instead if it has been enabled
|
||||
* previously.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Set CPU to 80MHz. Keep other clocks unmodified. */
|
||||
int cpu_freq_mhz = 80;
|
||||
|
||||
uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG);
|
||||
if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 &&
|
||||
DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL) == DPORT_CPUPERIOD_SEL_240) {
|
||||
cpu_freq_mhz = 240;
|
||||
}
|
||||
#endif
|
||||
|
||||
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
|
||||
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
clk_cfg.xtal_freq = CONFIG_ESP32S2_XTAL_FREQ;
|
||||
clk_cfg.cpu_freq = RTC_CPU_FREQ_80M;
|
||||
#endif
|
||||
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
|
||||
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
|
||||
rtc_clk_init(clk_cfg);
|
||||
|
@ -17,16 +17,22 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/crc.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp_secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#endif
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "sys/param.h"
|
||||
@ -273,35 +279,6 @@ void bootloader_common_vddsdio_configure(void)
|
||||
#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
case 0:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
case 1:
|
||||
chip_ver = 1;
|
||||
break;
|
||||
case 3:
|
||||
chip_ver = 2;
|
||||
break;
|
||||
case 7:
|
||||
chip_ver = 3;
|
||||
break;
|
||||
default:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t bootloader_common_check_chip_validity(const esp_image_header_t* img_hdr, esp_image_type type)
|
||||
{
|
||||
|
56
components/bootloader_support/src/bootloader_efuse_esp32.c
Normal file
56
components/bootloader_support/src/bootloader_efuse_esp32.c
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/apb_ctrl_reg.h"
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
uint8_t eco_bit0, eco_bit1, eco_bit2;
|
||||
eco_bit0 = (REG_READ(EFUSE_BLK0_RDATA3_REG) & 0xF000) >> 15;
|
||||
eco_bit1 = (REG_READ(EFUSE_BLK0_RDATA5_REG) & 0x100000) >> 20;
|
||||
eco_bit2 = (REG_READ(APB_CTRL_DATE_REG) & 0x80000000) >> 31;
|
||||
uint32_t combine_value = (eco_bit2 << 2) | (eco_bit1 << 1) | eco_bit0;
|
||||
uint8_t chip_ver = 0;
|
||||
switch (combine_value) {
|
||||
case 0:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
case 1:
|
||||
chip_ver = 1;
|
||||
break;
|
||||
case 3:
|
||||
chip_ver = 2;
|
||||
break;
|
||||
case 7:
|
||||
chip_ver = 3;
|
||||
break;
|
||||
default:
|
||||
chip_ver = 0;
|
||||
break;
|
||||
}
|
||||
return chip_ver;
|
||||
}
|
||||
|
||||
int bootloader_clock_get_rated_freq_mhz()
|
||||
{
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
return 160;
|
||||
}
|
||||
return 240;
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
int bootloader_clock_get_rated_freq_mhz()
|
||||
{
|
||||
/* No known limitation: all chips are 240MHz rated */
|
||||
return 240;
|
||||
}
|
||||
|
||||
uint8_t bootloader_common_get_chip_revision(void)
|
||||
{
|
||||
/* No other revisions for ESP32-S2beta */
|
||||
return 0;
|
||||
}
|
@ -17,6 +17,9 @@
|
||||
#include <esp_log.h>
|
||||
#include <esp_spi_flash.h> /* including in bootloader for error values */
|
||||
#include <esp_flash_encrypt.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#endif
|
||||
|
||||
#ifndef BOOTLOADER_BUILD
|
||||
/* Normal app version maps to esp_spi_flash.h operations...
|
||||
@ -67,7 +70,11 @@ esp_err_t bootloader_flash_read(size_t src, void *dest, size_t size, bool allow_
|
||||
esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool write_encrypted)
|
||||
{
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_flash_write_encrypted(dest_addr, src, size);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return SPI_Encrypt_Write(dest_addr, src, size);
|
||||
#endif
|
||||
} else {
|
||||
return spi_flash_write(dest_addr, src, size);
|
||||
}
|
||||
@ -86,17 +93,34 @@ esp_err_t bootloader_flash_erase_range(uint32_t start_addr, uint32_t size)
|
||||
#else
|
||||
/* Bootloader version, uses ROM functions only */
|
||||
#include <soc/dport_reg.h>
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/spi_flash.h>
|
||||
#include <esp32/rom/cache.h>
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include <esp32s2beta/rom/spi_flash.h>
|
||||
#include <esp32s2beta/rom/cache.h>
|
||||
#endif
|
||||
static const char *TAG = "bootloader_flash";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Use first 50 blocks in MMU for bootloader_mmap,
|
||||
50th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR 0x3f400000
|
||||
#define MMU_BLOCK50_VADDR 0x3f720000
|
||||
#define MMU_FREE_PAGES ((MMU_BLOCK50_VADDR - MMU_BLOCK0_VADDR) / FLASH_BLOCK_SIZE)
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#define MMU_SIZE (0x320000)
|
||||
#define MMU_BLOCK50_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK50_VADDR
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
/* Use first 63 blocks in MMU for bootloader_mmap,
|
||||
63th block for bootloader_flash_read
|
||||
*/
|
||||
#define MMU_BLOCK0_VADDR SOC_DROM_LOW
|
||||
#define MMU_SIZE (0x3f0000)
|
||||
#define MMU_BLOCK63_VADDR (MMU_BLOCK0_VADDR + MMU_SIZE)
|
||||
#define FLASH_READ_VADDR MMU_BLOCK63_VADDR
|
||||
#endif
|
||||
|
||||
#define MMU_FREE_PAGES (MMU_SIZE / FLASH_BLOCK_SIZE)
|
||||
|
||||
static bool mapped;
|
||||
|
||||
@ -118,25 +142,41 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
ESP_LOGE(TAG, "tried to bootloader_mmap twice");
|
||||
return NULL; /* can't map twice */
|
||||
}
|
||||
if (size > 0x320000) {
|
||||
/* Allow mapping up to 50 of the 51 available MMU blocks (last one used for reads) */
|
||||
if (size > MMU_SIZE) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap excess size %x", size);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint32_t src_addr_aligned = src_addr & MMU_FLASH_MASK;
|
||||
uint32_t count = bootloader_cache_pages_to_map(size, src_addr);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set paddr=%08x count=%d size=%x src_addr=%x src_addr_aligned=%x",
|
||||
src_addr & MMU_FLASH_MASK, count, size, src_addr, src_addr_aligned );
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, MMU_BLOCK0_VADDR, src_addr_aligned, 64, count, 0);
|
||||
#endif
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
mapped = true;
|
||||
|
||||
@ -146,10 +186,17 @@ const void *bootloader_mmap(uint32_t src_addr, uint32_t size)
|
||||
void bootloader_munmap(const void *mapping)
|
||||
{
|
||||
if (mapped) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Full MMU reset */
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
mmu_init(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//TODO, save the autoload value.
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
#endif
|
||||
mapped = false;
|
||||
current_read_mapping = UINT32_MAX;
|
||||
}
|
||||
@ -171,10 +218,18 @@ static esp_err_t spi_to_esp_err(esp_rom_spiflash_result_t r)
|
||||
|
||||
static esp_err_t bootloader_flash_read_no_decrypt(size_t src_addr, void *dest, size_t size)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
#endif
|
||||
esp_rom_spiflash_result_t r = esp_rom_spiflash_read(src_addr, dest, size);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
|
||||
return spi_to_esp_err(r);
|
||||
}
|
||||
@ -183,28 +238,42 @@ static esp_err_t bootloader_flash_read_allow_decrypt(size_t src_addr, void *dest
|
||||
{
|
||||
uint32_t *dest_words = (uint32_t *)dest;
|
||||
|
||||
/* Use the 51st MMU mapping to read from flash in 64KB blocks.
|
||||
(MMU will transparently decrypt if encryption is enabled.)
|
||||
*/
|
||||
for (int word = 0; word < size / 4; word++) {
|
||||
uint32_t word_src = src_addr + word * 4; /* Read this offset from flash */
|
||||
uint32_t map_at = word_src & MMU_FLASH_MASK; /* Map this 64KB block from flash */
|
||||
uint32_t *map_ptr;
|
||||
if (map_at != current_read_mapping) {
|
||||
/* Move the 64KB mmu mapping window to fit map_at */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
ESP_LOGD(TAG, "mmu set block paddr=0x%08x (was 0x%08x)", map_at, current_read_mapping);
|
||||
int e = cache_flash_mmu_set(0, 0, MMU_BLOCK50_VADDR, map_at, 64, 1);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int e = cache_flash_mmu_set(0, 0, FLASH_READ_VADDR, map_at, 64, 1);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int e = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, FLASH_READ_VADDR, map_at, 64, 1, 0);
|
||||
#endif
|
||||
if (e != 0) {
|
||||
ESP_LOGE(TAG, "cache_flash_mmu_set failed: %d\n", e);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
return ESP_FAIL;
|
||||
}
|
||||
current_read_mapping = map_at;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
}
|
||||
map_ptr = (uint32_t *)(MMU_BLOCK50_VADDR + (word_src - map_at));
|
||||
map_ptr = (uint32_t *)(FLASH_READ_VADDR + (word_src - map_at));
|
||||
dest_words[word] = *map_ptr;
|
||||
}
|
||||
return ESP_OK;
|
||||
@ -255,7 +324,12 @@ esp_err_t bootloader_flash_write(size_t dest_addr, void *src, size_t size, bool
|
||||
}
|
||||
|
||||
if (write_encrypted) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return spi_to_esp_err(esp_rom_spiflash_write_encrypted(dest_addr, src, size));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// TODO: use the same ROM AP here
|
||||
return spi_to_esp_err(SPI_Encrypt_Write(dest_addr, src, size));
|
||||
#endif
|
||||
} else {
|
||||
return spi_to_esp_err(esp_rom_spiflash_write(dest_addr, src, size));
|
||||
}
|
||||
|
@ -0,0 +1,118 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <stdbool.h>
|
||||
#include <assert.h>
|
||||
#include "string.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/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/spi_caps.h"
|
||||
#include "flash_qio_mode.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
#include "bootloader_common.h"
|
||||
|
||||
#define FLASH_IO_MATRIX_DUMMY_40M 0
|
||||
#define FLASH_IO_MATRIX_DUMMY_80M 0
|
||||
|
||||
#define FLASH_IO_DRIVE_GD_WITH_1V8PSRAM 3
|
||||
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
g_rom_flashchip.device_id = bootloader_read_flash_id();
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_cs_timing_config()
|
||||
{
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(0), SPI_CS_SETUP_TIME_V, 0, SPI_CS_SETUP_TIME_S);
|
||||
SET_PERI_REG_MASK(SPI_USER_REG(1), SPI_CS_HOLD_M | SPI_CS_SETUP_M);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_HOLD_TIME_V, 1, SPI_CS_HOLD_TIME_S);
|
||||
SET_PERI_REG_BITS(SPI_CTRL2_REG(1), SPI_CS_SETUP_TIME_V, 0, SPI_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_gpio_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void IRAM_ATTR bootloader_flash_dummy_config(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
int spi_cache_dummy = 0;
|
||||
int drv = 2;
|
||||
switch (pfhdr->spi_mode) {
|
||||
case ESP_IMAGE_SPI_MODE_QIO:
|
||||
spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_DIO:
|
||||
spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //qio 3
|
||||
break;
|
||||
case ESP_IMAGE_SPI_MODE_QOUT:
|
||||
case ESP_IMAGE_SPI_MODE_DOUT:
|
||||
default:
|
||||
spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
|
||||
break;
|
||||
}
|
||||
|
||||
/* dummy_len_plus values defined in ROM for SPI flash configuration */
|
||||
extern uint8_t g_rom_spiflash_dummy_len_plus[];
|
||||
switch (pfhdr->spi_speed) {
|
||||
case ESP_IMAGE_SPI_SPEED_80M:
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M;
|
||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M,
|
||||
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
drv = 3;
|
||||
break;
|
||||
case ESP_IMAGE_SPI_SPEED_40M:
|
||||
g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M;
|
||||
SET_PERI_REG_BITS(SPI_MEM_USER1_REG(0), SPI_MEM_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M,
|
||||
SPI_MEM_USR_DUMMY_CYCLELEN_S); //DUMMY
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
bootloader_configure_spi_pins(drv);
|
||||
}
|
@ -19,6 +19,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
@ -28,6 +29,19 @@
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
#else
|
||||
#error "Unsupported IDF_TARGET"
|
||||
#endif
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
@ -39,6 +53,11 @@
|
||||
#include "soc/timer_periph.h"
|
||||
#include "soc/rtc_wdt.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "soc/spi_mem_reg.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/assist_debug_reg.h"
|
||||
#endif
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_image_format.h"
|
||||
@ -48,6 +67,7 @@
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_random.h"
|
||||
#include "bootloader_config.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_clock.h"
|
||||
#include "bootloader_common.h"
|
||||
#include "bootloader_flash_config.h"
|
||||
@ -78,11 +98,13 @@ esp_err_t bootloader_init(void)
|
||||
/* Sanity check that static RAM is after the stack */
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
int *sp = get_sp();
|
||||
assert(&_bss_start <= &_bss_end);
|
||||
assert(&_data_start <= &_data_end);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int *sp = get_sp();
|
||||
assert(sp < &_bss_start);
|
||||
assert(sp < &_data_start);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -91,14 +113,27 @@ esp_err_t bootloader_init(void)
|
||||
|
||||
/* completely reset MMU for both CPUs
|
||||
(in case serial bootloader was running) */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Read_Disable(1);
|
||||
#endif
|
||||
Cache_Flush(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
Cache_Flush(1);
|
||||
#endif
|
||||
mmu_init(0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_SET_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
mmu_init(1);
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MMU_IA_CLR);
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//TODO, save the autoload value
|
||||
Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
Cache_MMU_Init();
|
||||
#endif
|
||||
/* (above steps probably unnecessary for most serial bootloader
|
||||
usage, all that's absolutely needed is that we unmask DROM0
|
||||
cache on the following two lines - normal ROM boot exits with
|
||||
@ -109,9 +144,14 @@ esp_err_t bootloader_init(void)
|
||||
The lines which manipulate DPORT_APP_CACHE_MMU_IA_CLR bit are
|
||||
necessary to work around a hardware bug.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DROM0);
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_CLR_BIT(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DROM0);
|
||||
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_DROM0);
|
||||
#endif
|
||||
if (bootloader_main() != ESP_OK) {
|
||||
return ESP_FAIL;
|
||||
}
|
||||
@ -137,21 +177,25 @@ static esp_err_t bootloader_main(void)
|
||||
}
|
||||
|
||||
bootloader_init_flash_configure(&fhdr);
|
||||
#if (CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240)
|
||||
//Check if ESP32 is rated for a CPU frequency of 160MHz only
|
||||
if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_RATED) &&
|
||||
REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_CPU_FREQ_LOW)) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for 160MHz. Modify CPU frequency in menuconfig");
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
int rated_freq = bootloader_clock_get_rated_freq_mhz();
|
||||
if (rated_freq < CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ) {
|
||||
ESP_LOGE(TAG, "Chip CPU frequency rated for %dMHz, configured for %dMHz. Modify CPU frequency in menuconfig",
|
||||
rated_freq, CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_clock_configure();
|
||||
uart_console_configure();
|
||||
wdt_reset_check();
|
||||
ESP_LOGI(TAG, "ESP-IDF %s 2nd stage bootloader", IDF_VER);
|
||||
|
||||
ESP_LOGI(TAG, "compile time " __TIME__ );
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
ets_set_appcpu_boot_addr(0);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_WDT_ENABLE
|
||||
ESP_LOGD(TAG, "Enabling RTCWDT(%d ms)", CONFIG_BOOTLOADER_WDT_TIME_MS);
|
||||
@ -215,13 +259,21 @@ static void update_flash_config(const esp_image_header_t* pfhdr)
|
||||
default:
|
||||
size = 2;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
#endif
|
||||
// Set flash chip size
|
||||
esp_rom_spiflash_config_param(g_rom_flashchip.device_id, size * 0x100000, 0x10000, 0x1000, 0x100, 0xffff);
|
||||
// TODO: set mode
|
||||
// TODO: set frequency
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Flush(0);
|
||||
Cache_Read_Enable(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void print_flash_info(const esp_image_header_t *phdr)
|
||||
@ -256,6 +308,7 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
|
||||
/* SPI mode could have been set to QIO during boot already,
|
||||
so test the SPI registers not the flash header */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t spi_ctrl = REG_READ(SPI_CTRL_REG(0));
|
||||
if (spi_ctrl & SPI_FREAD_QIO) {
|
||||
str = "QIO";
|
||||
@ -270,6 +323,22 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
} else {
|
||||
str = "SLOW READ";
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
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";
|
||||
}
|
||||
#endif
|
||||
ESP_LOGI(TAG, "SPI Mode : %s", str );
|
||||
|
||||
switch ( phdr->spi_size ) {
|
||||
@ -296,10 +365,6 @@ static void print_flash_info(const esp_image_header_t* phdr)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Bootloader reads SPI configuration from bin header, so that
|
||||
* the burning configuration can be different with compiling configuration.
|
||||
*/
|
||||
static void IRAM_ATTR bootloader_init_flash_configure(const esp_image_header_t* pfhdr)
|
||||
{
|
||||
bootloader_flash_gpio_config(pfhdr);
|
||||
@ -362,9 +427,16 @@ static void uart_console_configure(void)
|
||||
|
||||
static void wdt_reset_cpu0_info_enable(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//We do not reset core1 info here because it didn't work before cpu1 was up. So we put it into call_start_cpu1.
|
||||
DPORT_REG_SET_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_PDEBUG_ENABLE | DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
DPORT_REG_CLR_BIT(DPORT_PRO_CPU_RECORD_CTRL_REG, DPORT_PRO_CPU_RECORD_ENABLE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_ASSIST_DEBUG);
|
||||
REG_WRITE(ASSIST_DEBUG_PRO_PDEBUGENABLE, 1);
|
||||
REG_WRITE(ASSIST_DEBUG_PRO_RCD_RECORDING, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void wdt_reset_info_dump(int cpu)
|
||||
@ -373,6 +445,7 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsstat = 0, lsaddr = 0, lsdata = 0, dstat = 0;
|
||||
const char *cpu_name = cpu ? "APP" : "PRO";
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (cpu == 0) {
|
||||
stat = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PID_REG);
|
||||
@ -385,6 +458,7 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsdata = DPORT_REG_READ(DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
|
||||
} else {
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
stat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_STATUS_REG);
|
||||
pid = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PID_REG);
|
||||
inst = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGINST_REG);
|
||||
@ -394,7 +468,23 @@ static void wdt_reset_info_dump(int cpu)
|
||||
lsstat = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG);
|
||||
lsaddr = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG);
|
||||
lsdata = DPORT_REG_READ(DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG);
|
||||
#else
|
||||
ESP_LOGE(TAG, "WDT reset info: &s CPU not support!\n", cpu_name);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
stat = 0xdeadbeef;
|
||||
pid = 0;
|
||||
inst = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGINST);
|
||||
dstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGSTATUS);
|
||||
data = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGDATA);
|
||||
pc = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGPC);
|
||||
lsstat = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0STAT);
|
||||
lsaddr = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0ADDR);
|
||||
lsdata = REG_READ(ASSIST_DEBUG_PRO_RCD_PDEBUGLS0DATA);
|
||||
#endif
|
||||
|
||||
if (DPORT_RECORD_PDEBUGINST_SZ(inst) == 0 &&
|
||||
DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(dstat) == DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI) {
|
||||
ESP_LOGW(TAG, "WDT reset info: %s CPU PC=0x%x (waiti mode)", cpu_name, pc);
|
||||
@ -418,6 +508,7 @@ static void wdt_reset_check(void)
|
||||
RESET_REASON rst_reas[2];
|
||||
|
||||
rst_reas[0] = rtc_get_reset_reason(0);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rst_reas[1] = rtc_get_reset_reason(1);
|
||||
if (rst_reas[0] == RTCWDT_SYS_RESET || rst_reas[0] == TG0WDT_SYS_RESET || rst_reas[0] == TG1WDT_SYS_RESET ||
|
||||
rst_reas[0] == TGWDT_CPU_RESET || rst_reas[0] == RTCWDT_CPU_RESET) {
|
||||
@ -429,10 +520,19 @@ static void wdt_reset_check(void)
|
||||
ESP_LOGW(TAG, "APP CPU has been reset by WDT.");
|
||||
wdt_rst = 1;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
if (wdt_rst) {
|
||||
// if reset by WDT dump info from trace port
|
||||
wdt_reset_info_dump(0);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
wdt_reset_info_dump(1);
|
||||
#endif
|
||||
}
|
||||
wdt_reset_cpu0_info_enable();
|
||||
}
|
||||
@ -445,7 +545,7 @@ void __assert_func(const char *file, int line, const char *func, const char *exp
|
||||
|
||||
void abort(void)
|
||||
{
|
||||
#if !CONFIG_ESP32_PANIC_SILENT_REBOOT
|
||||
#if !(CONFIG_ESP32_PANIC_SILENT_REBOOT || CONFIG_ESP32S2_PANIC_SILENT_REBOOT)
|
||||
ets_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
|
||||
#endif
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
|
@ -35,7 +35,9 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
{
|
||||
uint8_t *buffer_bytes = (uint8_t *)buffer;
|
||||
uint32_t random;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t start, now;
|
||||
#endif
|
||||
|
||||
assert(buffer != NULL);
|
||||
|
||||
@ -48,14 +50,18 @@ void bootloader_fill_random(void *buffer, size_t length)
|
||||
as-is, we repeatedly read the RNG register and XOR all
|
||||
values.
|
||||
*/
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
random = REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, start);
|
||||
do {
|
||||
random ^= REG_READ(WDEV_RND_REG);
|
||||
RSR(CCOUNT, now);
|
||||
} while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// ToDo: Get random from register
|
||||
random = 12345678;
|
||||
#endif
|
||||
}
|
||||
|
||||
buffer_bytes[i] = random >> ((i % 4) * 8);
|
||||
}
|
||||
}
|
||||
@ -80,6 +86,7 @@ void bootloader_random_enable(void)
|
||||
*/
|
||||
SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 2, RTC_CNTL_DTEST_RTC_S);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@ -89,6 +96,13 @@ void bootloader_random_enable(void)
|
||||
#endif // BOOTLOADER_BUILD
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_ULP_CP_START_TOP);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_I2S0_CLK_EN);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP);
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_START_TOP);
|
||||
#endif
|
||||
|
||||
// Test pattern configuration byte 0xAD:
|
||||
//--[7:4] channel_sel: 10-->en_test
|
||||
//--[3:2] bit_width : 3-->12bit
|
||||
@ -97,15 +111,24 @@ void bootloader_random_enable(void)
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB2_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB3_REG, 0xADADADAD);
|
||||
WRITE_PERI_REG(SYSCON_SARADC_SAR2_PATT_TAB4_REG, 0xADADADAD);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
SET_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 3, SENS_FORCE_XPD_SAR_S);
|
||||
SET_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX);
|
||||
#endif
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_CLK_DIV, 4, SYSCON_SARADC_SAR_CLK_DIV_S);
|
||||
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_RSTB_WAIT, 8, SYSCON_SARADC_RSTB_WAIT_S); /* was 1 */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 10, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_WORK_MODE, 0, SYSCON_SARADC_WORK_MODE_S);
|
||||
SET_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_DATA_SAR_SEL);
|
||||
@ -139,15 +162,28 @@ void bootloader_random_disable(void)
|
||||
CLEAR_PERI_REG_MASK(I2S_CONF_REG(0), I2S_RX_START);
|
||||
|
||||
/* Restore SYSCON mode registers */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL_REG, SENS_SAR1_DIG_FORCE);
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_READ_CTRL2_REG, SENS_SAR2_DIG_FORCE);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS1_MUX_REG, SENS_SAR1_DIG_FORCE);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/* Restore SAR ADC mode */
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_START_FORCE_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR2_MUX
|
||||
| SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
CLEAR_PERI_REG_MASK(SENS_SAR_MEAS2_CTRL1_REG, SENS_SAR2_EN_TEST);
|
||||
CLEAR_PERI_REG_MASK(SYSCON_SARADC_CTRL_REG, SYSCON_SARADC_SAR_SEL | SYSCON_SARADC_DATA_TO_I2S);
|
||||
SET_PERI_REG_BITS(SENS_SAR_POWER_XPD_SAR_REG, SENS_FORCE_XPD_SAR, 0, SENS_FORCE_XPD_SAR_S);
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(SYSCON_SARADC_FSM_REG, SYSCON_SARADC_START_WAIT, 8, SYSCON_SARADC_START_WAIT_S);
|
||||
#endif
|
||||
|
||||
/* Reset i2s peripheral */
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/cache.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
@ -28,7 +29,19 @@
|
||||
#include "esp32/rom/uart.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/secure_boot.h"
|
||||
#include "esp32/rom/rtc.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/crc.h"
|
||||
#include "esp32s2beta/rom/rtc.h"
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
#else
|
||||
#error "Unsupported IDF_TARGET"
|
||||
#endif
|
||||
|
||||
#include "soc/soc.h"
|
||||
#include "soc/cpu.h"
|
||||
@ -144,8 +157,7 @@ bool bootloader_utility_load_partition_table(bootloader_state_t* bs)
|
||||
bs->ota[partition->subtype & PART_SUBTYPE_OTA_MASK] = partition->pos;
|
||||
++bs->app_count;
|
||||
partition_usage = "OTA app";
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
partition_usage = "Unknown app";
|
||||
}
|
||||
break;
|
||||
@ -595,6 +607,7 @@ static void load_image(const esp_image_metadata_t* image_data)
|
||||
so issue a system reset to ensure flash encryption
|
||||
cache resets properly */
|
||||
ESP_LOGI(TAG, "Resetting with flash encryption enabled...");
|
||||
uart_tx_wait_idle(0);
|
||||
bootloader_reset();
|
||||
}
|
||||
#endif
|
||||
@ -661,8 +674,13 @@ static void set_cache_and_start_app(
|
||||
{
|
||||
int rc;
|
||||
ESP_LOGD(TAG, "configure drom and irom and start");
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Disable(0);
|
||||
Cache_Flush(0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t autoload = Cache_Suspend_ICache();
|
||||
Cache_Invalidate_ICache_All();
|
||||
#endif
|
||||
|
||||
/* Clear the MMU entries that are already set up,
|
||||
so the new app only has the mappings it creates.
|
||||
@ -675,32 +693,69 @@ static void set_cache_and_start_app(
|
||||
uint32_t drom_page_count = bootloader_cache_pages_to_map(drom_size, drom_load_addr);
|
||||
ESP_LOGV(TAG, "d mmu set paddr=%08x vaddr=%08x size=%d n=%d",
|
||||
drom_addr & MMU_FLASH_MASK, drom_load_addr_aligned, drom_size, drom_page_count);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rc = cache_flash_mmu_set(0, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, drom_load_addr & 0xffff0000, drom_addr & 0xffff0000,
|
||||
64, drom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
|
||||
rc = cache_flash_mmu_set(1, 0, drom_load_addr_aligned, drom_addr & MMU_FLASH_MASK, 64, drom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
|
||||
#endif
|
||||
uint32_t irom_load_addr_aligned = irom_load_addr & MMU_FLASH_MASK;
|
||||
uint32_t irom_page_count = bootloader_cache_pages_to_map(irom_size, irom_load_addr);
|
||||
ESP_LOGV(TAG, "i mmu set paddr=%08x vaddr=%08x size=%d n=%d",
|
||||
irom_addr & MMU_FLASH_MASK, irom_load_addr_aligned, irom_size, irom_page_count);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
rc = cache_flash_mmu_set(0, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t iram1_used = 0, irom0_used = 0;
|
||||
if (irom_load_addr + irom_size > IRAM1_ADDRESS_LOW) {
|
||||
iram1_used = 1;
|
||||
}
|
||||
if (irom_load_addr + irom_size > IROM0_ADDRESS_LOW) {
|
||||
irom0_used = 1;
|
||||
}
|
||||
if (iram1_used || irom0_used) {
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM0_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IRAM1_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IRAM1);
|
||||
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IRAM1);
|
||||
if (irom0_used) {
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, IROM0_ADDRESS_LOW, 0, 64, 64, 1);
|
||||
REG_SET_BIT(DPORT_CACHE_SOURCE_1_REG, DPORT_PRO_CACHE_I_SOURCE_PRO_IROM0);
|
||||
REG_CLR_BIT(DPORT_PRO_ICACHE_CTRL1_REG, DPORT_PRO_ICACHE_MASK_IROM0);
|
||||
}
|
||||
}
|
||||
rc = Cache_Ibus_MMU_Set(DPORT_MMU_ACCESS_FLASH, irom_load_addr & 0xffff0000, irom_addr & 0xffff0000, 64, irom_page_count, 0);
|
||||
#endif
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
rc = cache_flash_mmu_set(1, 0, irom_load_addr_aligned, irom_addr & MMU_FLASH_MASK, 64, irom_page_count);
|
||||
ESP_LOGV(TAG, "rc=%d", rc);
|
||||
|
||||
#endif
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_CACHE_CTRL1_REG,
|
||||
(DPORT_PRO_CACHE_MASK_IRAM0) | (DPORT_PRO_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_PRO_CACHE_MASK_IROM0 & 0) | DPORT_PRO_CACHE_MASK_DROM0 |
|
||||
DPORT_PRO_CACHE_MASK_DRAM1 );
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
DPORT_REG_CLR_BIT( DPORT_APP_CACHE_CTRL1_REG,
|
||||
(DPORT_APP_CACHE_MASK_IRAM0) | (DPORT_APP_CACHE_MASK_IRAM1 & 0) |
|
||||
(DPORT_APP_CACHE_MASK_IROM0 & 0) | DPORT_APP_CACHE_MASK_DROM0 |
|
||||
DPORT_APP_CACHE_MASK_DRAM1 );
|
||||
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
DPORT_REG_CLR_BIT( DPORT_PRO_ICACHE_CTRL1_REG, (DPORT_PRO_ICACHE_MASK_IRAM0) | (DPORT_PRO_ICACHE_MASK_IRAM1 & 0) | (DPORT_PRO_ICACHE_MASK_IROM0 & 0) | DPORT_PRO_ICACHE_MASK_DROM0 );
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
Cache_Read_Enable(0);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
Cache_Resume_ICache(autoload);
|
||||
#endif
|
||||
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
|
||||
|
||||
ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
|
||||
@ -712,7 +767,6 @@ static void set_cache_and_start_app(
|
||||
(*entry)();
|
||||
}
|
||||
|
||||
|
||||
void bootloader_reset(void)
|
||||
{
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
@ -743,3 +797,24 @@ esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_he
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void bootloader_debug_buffer(const void *buffer, size_t length, const char *label)
|
||||
{
|
||||
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
|
||||
assert(length <= 128); // Avoid unbounded VLA size
|
||||
const uint8_t *bytes = (const uint8_t *)buffer;
|
||||
char hexbuf[length * 2 + 1];
|
||||
hexbuf[length * 2] = 0;
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (int shift = 0; shift < 2; shift++) {
|
||||
uint8_t nibble = (bytes[i] >> (shift ? 0 : 4)) & 0x0F;
|
||||
if (nibble < 10) {
|
||||
hexbuf[i * 2 + shift] = '0' + nibble;
|
||||
} else {
|
||||
hexbuf[i * 2 + shift] = 'a' + nibble - 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
ESP_LOGD(TAG, "%s: %s", label, hexbuf);
|
||||
#endif
|
||||
}
|
||||
|
88
components/bootloader_support/src/esp32/bootloader_esp32.c
Normal file
88
components/bootloader_support/src/esp32/bootloader_esp32.c
Normal file
@ -0,0 +1,88 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "esp32/rom/gpio.h"
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
||||
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
||||
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
||||
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
||||
|
||||
void bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG);
|
||||
uint32_t pkg_ver = chip_ver & 0x7;
|
||||
|
||||
if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) {
|
||||
// For ESP32D2WD the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
|
||||
// For ESP32PICOD2 the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
|
||||
// For ESP32PICOD4 the SPI pins are already configured
|
||||
// flash clock signal should come from IO MUX.
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
} else {
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA0_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA1_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA2_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_DATA3_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CMD_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
@ -16,9 +16,10 @@
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32/rom/sha.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_periph.h"
|
||||
#include "esp32/rom/ets_sys.h" // TO REMOVE
|
||||
|
||||
static uint32_t words_hashed;
|
||||
|
||||
|
@ -174,7 +174,7 @@ static esp_err_t encrypt_flash_contents(uint32_t flash_crypt_cnt, bool flash_cry
|
||||
|
||||
/* If the last flash_crypt_cnt bit is burned or write-disabled, the
|
||||
device can't re-encrypt itself. */
|
||||
if (flash_crypt_wr_dis) {
|
||||
if (flash_crypt_wr_dis || flash_crypt_cnt == 0xFF) {
|
||||
ESP_LOGE(TAG, "Cannot re-encrypt data (FLASH_CRYPT_CNT 0x%02x write disabled %d", flash_crypt_cnt, flash_crypt_wr_dis);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
@ -0,0 +1,68 @@
|
||||
// Copyright 2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "bootloader_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/efuse_reg.h"
|
||||
#include "soc/gpio_sig_map.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#include "esp32s2beta/rom/gpio.h"
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
|
||||
#define FLASH_CLK_IO SPI_CLK_GPIO_NUM
|
||||
#define FLASH_CS_IO SPI_CS0_GPIO_NUM
|
||||
#define FLASH_SPIQ_IO SPI_Q_GPIO_NUM
|
||||
#define FLASH_SPID_IO SPI_D_GPIO_NUM
|
||||
#define FLASH_SPIWP_IO SPI_WP_GPIO_NUM
|
||||
#define FLASH_SPIHD_IO SPI_HD_GPIO_NUM
|
||||
|
||||
void bootloader_configure_spi_pins(int drv)
|
||||
{
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) {
|
||||
gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
|
||||
gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0);
|
||||
gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
|
||||
gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0);
|
||||
//select pin function gpio
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIHD_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIWP_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICS0_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPIQ_U, PIN_FUNC_GPIO);
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPID_U, PIN_FUNC_GPIO);
|
||||
// flash clock signal should come from IO MUX.
|
||||
// set drive ability for clock
|
||||
PIN_FUNC_SELECT(PERIPHS_IO_MUX_SPICLK_U, FUNC_SPICLK_SPICLK);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, drv, FUN_DRV_S);
|
||||
|
||||
#if CONFIG_SPIRAM_TYPE_ESPPSRAM32 || CONFIG_SPIRAM_TYPE_ESPPSRAM64
|
||||
uint32_t flash_id = g_rom_flashchip.device_id;
|
||||
if (flash_id == FLASH_ID_GD25LQ32C) {
|
||||
// Set drive ability for 1.8v flash in 80Mhz.
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIHD_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIWP_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICS0_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPICLK_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPIQ_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
SET_PERI_REG_BITS(PERIPHS_IO_MUX_SPID_U, FUN_DRV, 3, FUN_DRV_S);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
// Copyright 2017 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "bootloader_sha.h"
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "esp32s2beta/rom/sha.h"
|
||||
|
||||
static SHA_CTX ctx;
|
||||
|
||||
// Words per SHA256 block
|
||||
// static const size_t BLOCK_WORDS = (64/sizeof(uint32_t));
|
||||
// Words in final SHA256 digest
|
||||
// static const size_t DIGEST_WORDS = (32/sizeof(uint32_t));
|
||||
|
||||
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);
|
||||
}
|
303
components/bootloader_support/src/esp32s2beta/flash_encrypt.c
Normal file
303
components/bootloader_support/src/esp32s2beta/flash_encrypt.c
Normal file
@ -0,0 +1,303 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <strings.h>
|
||||
|
||||
#include "bootloader_flash.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 "esp32s2beta/rom/secure_boot.h"
|
||||
#include "esp32s2beta/rom/cache.h"
|
||||
#include "esp32s2beta/rom/efuse.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);
|
||||
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)
|
||||
{
|
||||
// TODO: not clear why this is read from DATA1 and written to PGM_DATA2
|
||||
uint32_t cnt = REG_GET_FIELD(EFUSE_RD_REPEAT_DATA1_REG, EFUSE_SPI_BOOT_CRYPT_CNT);
|
||||
ESP_LOGV(TAG, "SPI_BOOT_CRYPT_CNT 0x%x", cnt);
|
||||
|
||||
bool flash_crypt_wr_dis = false; // TODO: check if CRYPT_CNT is write disabled
|
||||
|
||||
_Static_assert(EFUSE_SPI_BOOT_CRYPT_CNT == 0x7, "assuming CRYPT_CNT is only 3 bits wide");
|
||||
|
||||
if (cnt == 1 || cnt == 3 || cnt == 7) {
|
||||
/* Flash is already encrypted */
|
||||
int left;
|
||||
if (cnt == 7 /* || disabled */) {
|
||||
left = 0;
|
||||
} else if (cnt == 3) {
|
||||
left = 1;
|
||||
} else {
|
||||
left = 2;
|
||||
}
|
||||
ESP_LOGI(TAG, "flash encryption is enabled (%d plaintext flashes left)", left);
|
||||
return ESP_OK;
|
||||
}
|
||||
else {
|
||||
/* Flash is not encrypted, so encrypt it! */
|
||||
return encrypt_flash_contents(cnt, flash_crypt_wr_dis);
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t initialise_flash_encryption(void)
|
||||
{
|
||||
/* Before first flash encryption pass, need to initialise key & crypto config */
|
||||
|
||||
/* Find out if a key is already set */
|
||||
bool has_aes128 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY, NULL);
|
||||
bool has_aes256_1 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1, NULL);
|
||||
bool has_aes256_2 = ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2, NULL);
|
||||
|
||||
bool has_key = has_aes128 || (has_aes256_1 && has_aes256_2);
|
||||
|
||||
if (!has_key && (has_aes256_1 || has_aes256_2)) {
|
||||
ESP_LOGE(TAG, "Invalid efuse key blocks: Both AES-256 key blocks must be set.");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (has_key) {
|
||||
ESP_LOGI(TAG, "Using pre-existing key in efuse");
|
||||
|
||||
ESP_LOGE(TAG, "TODO: Check key is read & write protected"); // TODO
|
||||
} else {
|
||||
ESP_LOGI(TAG, "Generating new flash encryption key...");
|
||||
#ifdef CONFIG_SECURE_FLASH_ENCRYPTION_AES256
|
||||
const unsigned BLOCKS_NEEDED = 2;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2;
|
||||
#else
|
||||
const unsigned BLOCKS_NEEDED = 1;
|
||||
const ets_efuse_purpose_t PURPOSE_START = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
const ets_efuse_purpose_t PURPOSE_END = ETS_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY;
|
||||
#endif
|
||||
|
||||
if (ets_efuse_count_unused_key_blocks() < BLOCKS_NEEDED) {
|
||||
ESP_LOGE(TAG, "Not enough free efuse key blocks (need %d) to continue", BLOCKS_NEEDED);
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
for(ets_efuse_purpose_t purpose = PURPOSE_START; purpose <= PURPOSE_END; purpose++) {
|
||||
uint32_t buf[8];
|
||||
bootloader_fill_random(buf, sizeof(buf));
|
||||
ets_efuse_block_t block = ets_efuse_find_unused_key_block();
|
||||
ESP_LOGD(TAG, "Writing ETS_EFUSE_BLOCK_KEY%d with purpose %d",
|
||||
block - ETS_EFUSE_BLOCK_KEY0, purpose);
|
||||
bootloader_debug_buffer(buf, sizeof(buf), "Key content");
|
||||
int r = ets_efuse_write_key(block, purpose, buf, sizeof(buf));
|
||||
bzero(buf, sizeof(buf));
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.");
|
||||
return ESP_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_LOGD(TAG, "Key generation complete");
|
||||
}
|
||||
|
||||
ESP_LOGE(TAG, "TODO: burn remaining security protection bits"); // TODO
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* 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 = 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);
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_FIELD(EFUSE_PGM_DATA2_REG, EFUSE_SPI_BOOT_CRYPT_CNT, new_spi_boot_crypt_cnt);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
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...");
|
||||
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;
|
||||
}
|
||||
|
||||
if (esp_secure_boot_enabled()) {
|
||||
// TODO: anything different for secure boot?
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGW(TAG, "no valid bootloader was found");
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t encrypt_and_load_partition_table(esp_partition_info_t *partition_table, int *num_partitions)
|
||||
{
|
||||
esp_err_t err;
|
||||
/* Check for plaintext partition table */
|
||||
err = bootloader_flash_read(ESP_PARTITION_TABLE_OFFSET, partition_table, ESP_PARTITION_TABLE_MAX_LEN, false);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data");
|
||||
return err;
|
||||
}
|
||||
if (esp_partition_table_verify(partition_table, false, num_partitions) == ESP_OK) {
|
||||
ESP_LOGD(TAG, "partition table is plaintext. Encrypting...");
|
||||
esp_err_t err = esp_flash_encrypt_region(ESP_PARTITION_TABLE_OFFSET,
|
||||
FLASH_SECTOR_SIZE);
|
||||
if (err != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to encrypt partition table in place. %x", err);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ESP_LOGE(TAG, "Failed to read partition table data - not plaintext?");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Valid partition table loded */
|
||||
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;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < data_length; i += FLASH_SECTOR_SIZE) {
|
||||
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;
|
||||
}
|
45
components/bootloader_support/src/esp32s2beta/secure_boot.c
Normal file
45
components/bootloader_support/src/esp32s2beta/secure_boot.c
Normal file
@ -0,0 +1,45 @@
|
||||
// Copyright 2015-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "esp_secure_boot.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
#define TAG "secure_boot"
|
||||
|
||||
esp_err_t esp_secure_boot_permanently_enable(void)
|
||||
{
|
||||
uint8_t hash[32];
|
||||
|
||||
if (ets_efuse_secure_boot_enabled())
|
||||
{
|
||||
ESP_LOGI(TAG, "secure boot is already enabled, continuing..");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
ESP_LOGI(TAG, "Verifying bootloader signature...\n");
|
||||
int r = ets_secure_boot_verify_bootloader(hash, false);
|
||||
if (r != ESP_OK) {
|
||||
ESP_LOGE(TAG, "Failed to verify bootloader signature");
|
||||
return r;
|
||||
}
|
||||
|
||||
ets_efuse_clear_program_registers();
|
||||
REG_SET_BIT(EFUSE_PGM_DATA3_REG, EFUSE_SECURE_BOOT_EN);
|
||||
ets_efuse_program(ETS_EFUSE_BLOCK0);
|
||||
|
||||
assert(ets_efuse_secure_boot_enabled());
|
||||
ESP_LOGI(TAG, "Secure boot permanently enabled");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
@ -0,0 +1,92 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "bootloader_flash.h"
|
||||
#include "bootloader_sha.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_image_format.h"
|
||||
#include "esp32s2beta/rom/secure_boot.h"
|
||||
|
||||
static const char* TAG = "secure_boot";
|
||||
|
||||
#define DIGEST_LEN 32
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys = { 0 };
|
||||
uint8_t digest[DIGEST_LEN];
|
||||
const uint8_t *data;
|
||||
|
||||
ESP_LOGD(TAG, "verifying signature src_addr 0x%x length 0x%x", src_addr, length);
|
||||
|
||||
if ((src_addr + length) % 4096 != 0) {
|
||||
ESP_LOGE(TAG, "addr 0x%x length 0x%x doesn't end on a sector boundary", src_addr, length);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
data = bootloader_mmap(src_addr, length + sizeof(struct ets_secure_boot_sig_block));
|
||||
if(data == NULL) {
|
||||
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", src_addr, length+sizeof(ets_secure_boot_signature_t));
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
// Calculate digest of main image
|
||||
#ifdef BOOTLOADER_BUILD
|
||||
bootloader_sha256_handle_t handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(handle, data, length);
|
||||
bootloader_sha256_finish(handle, digest);
|
||||
#else
|
||||
/* Use thread-safe esp-idf SHA function */
|
||||
esp_sha(SHA2_256, data, length, digest);
|
||||
#endif
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
|
||||
if (r == ETS_OK) {
|
||||
const ets_secure_boot_signature_t *sig = (const ets_secure_boot_signature_t *)(data + length);
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, digest, &trusted_keys);
|
||||
}
|
||||
bootloader_munmap(data);
|
||||
|
||||
return (r == ETS_OK) ? ESP_OK : ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t esp_secure_boot_verify_signature_block(uint32_t sig_block_flash_offs, const uint8_t *image_digest)
|
||||
{
|
||||
ets_secure_boot_key_digests_t trusted_keys;
|
||||
|
||||
assert(sig_block_flash_offs % 4096 == 0); // TODO: enforce this in a better way
|
||||
|
||||
const ets_secure_boot_signature_t *sig = bootloader_mmap(sig_block_flash_offs, sizeof(ets_secure_boot_signature_t));
|
||||
|
||||
if (sig == NULL) {
|
||||
ESP_LOGE(TAG, "Failed to mmap data at offset 0x%x", sig_block_flash_offs);
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
int r = ets_secure_boot_read_key_digests(&trusted_keys);
|
||||
if (r != 0) {
|
||||
ESP_LOGE(TAG, "No trusted key digests were found in efuse!");
|
||||
} else {
|
||||
ESP_LOGD(TAG, "Verifying with RSA-PSS...");
|
||||
// TODO: calling this function in IDF app context is unsafe
|
||||
r = ets_secure_boot_verify_signature(sig, image_digest, &trusted_keys);
|
||||
}
|
||||
|
||||
bootloader_munmap(sig);
|
||||
|
||||
return (r == 0) ? ESP_OK : ESP_ERR_IMAGE_INVALID;
|
||||
}
|
@ -13,8 +13,6 @@
|
||||
// limitations under the License.
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <soc/cpu.h>
|
||||
#include <bootloader_utility.h>
|
||||
#include <esp_secure_boot.h>
|
||||
@ -25,6 +23,13 @@
|
||||
#include <bootloader_sha.h>
|
||||
#include "bootloader_util.h"
|
||||
#include "bootloader_common.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include <esp32/rom/rtc.h>
|
||||
#include <esp32/rom/secure_boot.h>
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include <esp32s2beta/rom/rtc.h>
|
||||
#include <esp32s2beta/rom/secure_boot.h>
|
||||
#endif
|
||||
|
||||
/* Checking signatures as part of verifying images is necessary:
|
||||
- Always if secure boot is enabled
|
||||
@ -192,17 +197,24 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
}
|
||||
}
|
||||
|
||||
/* For secure boot on ESP32, we don't calculate SHA or verify signautre on bootloaders.
|
||||
For ESP32S2, we do verify signature on botoloaders which includes the SHA calculation.
|
||||
|
||||
(For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because
|
||||
esptool.py may have rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.)
|
||||
*/
|
||||
bool verify_sha;
|
||||
#if defined(CONFIG_SECURE_BOOT_ENABLED) && defined(CONFIG_IDF_TARGET_ESP32S2BETA)
|
||||
verify_sha = true;
|
||||
#else // ESP32, or ESP32S2 without secure boot enabled
|
||||
verify_sha = (data->start_addr != ESP_BOOTLOADER_OFFSET);
|
||||
#endif
|
||||
|
||||
if (verify_sha) {
|
||||
if (data->image_len > part->size) {
|
||||
FAIL_LOAD("Image length %d doesn't fit in partition length %d", data->image_len, part->size);
|
||||
}
|
||||
|
||||
bool is_bootloader = (data->start_addr == ESP_BOOTLOADER_OFFSET);
|
||||
/* For secure boot, we don't verify signature on bootloaders.
|
||||
|
||||
For non-secure boot, we don't verify any SHA-256 hash appended to the bootloader because esptool.py may have
|
||||
rewritten the header - rely on esptool.py having verified the bootloader at flashing time, instead.
|
||||
*/
|
||||
if (!is_bootloader) {
|
||||
#ifdef SECURE_BOOT_CHECK_SIGNATURE
|
||||
// secure boot images have a signature appended
|
||||
err = verify_secure_boot_signature(sha_handle, data);
|
||||
@ -212,12 +224,11 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
err = verify_simple_hash(sha_handle, data);
|
||||
}
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
} else { // is_bootloader
|
||||
} else { // verify_sha
|
||||
// bootloader may still have a sha256 digest handle open
|
||||
if (sha_handle != NULL) {
|
||||
bootloader_sha256_finish(sha_handle, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (data->image.hash_appended) {
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
@ -229,7 +240,8 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
bootloader_munmap(hash);
|
||||
}
|
||||
sha_handle = NULL;
|
||||
} // if (do_verify)
|
||||
} // verify_sha
|
||||
} // do_verify
|
||||
|
||||
if (err != ESP_OK) {
|
||||
goto err;
|
||||
@ -359,7 +371,7 @@ static esp_err_t process_segment(int index, uint32_t flash_addr, esp_image_segme
|
||||
/* Before loading segment, check it doesn't clobber bootloader RAM. */
|
||||
if (do_load) {
|
||||
const intptr_t load_end = load_addr + data_len;
|
||||
if (load_end <= (intptr_t) SOC_DIRAM_DRAM_HIGH) {
|
||||
if (load_end < (intptr_t) SOC_DRAM_HIGH) {
|
||||
/* Writing to DRAM */
|
||||
intptr_t sp = (intptr_t)get_sp();
|
||||
if (load_end > sp - STACK_LOAD_HEADROOM) {
|
||||
@ -602,26 +614,36 @@ static esp_err_t verify_checksum(bootloader_sha256_handle_t sha_handle, uint32_t
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static void debug_log_hash(const uint8_t *image_hash, const char *caption);
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data)
|
||||
{
|
||||
uint8_t image_hash[HASH_LEN] = { 0 };
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// Pad to 4096 byte sector boundary
|
||||
if (end % FLASH_SECTOR_SIZE != 0) {
|
||||
uint32_t pad_len = FLASH_SECTOR_SIZE - (end % FLASH_SECTOR_SIZE);
|
||||
const void *padding = bootloader_mmap(end, pad_len);
|
||||
bootloader_sha256_data(sha_handle, padding, pad_len);
|
||||
bootloader_munmap(padding);
|
||||
end += pad_len;
|
||||
}
|
||||
#endif
|
||||
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
|
||||
// Log the hash for debugging
|
||||
debug_log_hash(image_hash, "Calculated secure boot hash");
|
||||
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated secure boot hash");
|
||||
|
||||
// Use hash to verify signature block
|
||||
const esp_secure_boot_sig_block_t *sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
@ -646,6 +668,11 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// Adjust image length result to include the appended signature
|
||||
data->image_len = end - data->start_addr + sizeof(ets_secure_boot_signature_t);
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -655,13 +682,13 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
|
||||
bootloader_sha256_finish(sha_handle, image_hash);
|
||||
|
||||
// Log the hash for debugging
|
||||
debug_log_hash(image_hash, "Calculated hash");
|
||||
bootloader_debug_buffer(image_hash, HASH_LEN, "Calculated hash");
|
||||
|
||||
// Simple hash for verification only
|
||||
const void *hash = bootloader_mmap(data->start_addr + data->image_len - HASH_LEN, HASH_LEN);
|
||||
if (memcmp(hash, image_hash, HASH_LEN) != 0) {
|
||||
ESP_LOGE(TAG, "Image hash failed - image is corrupt");
|
||||
debug_log_hash(hash, "Expected hash");
|
||||
bootloader_debug_buffer(hash, HASH_LEN, "Expected hash");
|
||||
bootloader_munmap(hash);
|
||||
return ESP_ERR_IMAGE_INVALID;
|
||||
}
|
||||
@ -669,14 +696,3 @@ static esp_err_t verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_i
|
||||
bootloader_munmap(hash);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
// Log a hash as a hex string
|
||||
static void debug_log_hash(const uint8_t *image_hash, const char *label)
|
||||
{
|
||||
#if BOOT_LOG_LEVEL >= LOG_LEVEL_DEBUG
|
||||
char hash_print[HASH_LEN * 2 + 1];
|
||||
hash_print[HASH_LEN * 2] = 0;
|
||||
bootloader_sha256_hex_to_str(hash_print, image_hash, HASH_LEN);
|
||||
ESP_LOGD(TAG, "%s: %s", label, hash_print);
|
||||
#endif
|
||||
}
|
||||
|
@ -16,14 +16,28 @@
|
||||
#include "flash_qio_mode.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_err.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/spi_flash.h"
|
||||
#include "esp32/rom/efuse.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/spi_flash.h"
|
||||
#include "esp32s2beta/rom/efuse.h"
|
||||
#endif
|
||||
#include "soc/spi_struct.h"
|
||||
#include "soc/spi_reg.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "soc/spi_mem_struct.h"
|
||||
#endif
|
||||
#include "soc/efuse_periph.h"
|
||||
#include "soc/io_mux_reg.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
/* SPI flash controller */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define SPIFLASH SPI1
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SPIFLASH SPIMEM1
|
||||
#endif
|
||||
|
||||
/* SPI commands (actual on-wire commands not SPI controller bitmasks)
|
||||
Suitable for use with the execute_flash_command static function.
|
||||
@ -42,7 +56,8 @@ static const char *TAG = "qio_mode";
|
||||
typedef unsigned (*read_status_fn_t)(void);
|
||||
typedef void (*write_status_fn_t)(unsigned);
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
typedef struct __attribute__((packed))
|
||||
{
|
||||
const char *manufacturer;
|
||||
uint8_t mfg_id; /* 8-bit JEDEC manufacturer ID */
|
||||
uint16_t flash_id; /* 16-bit JEDEC flash chip ID */
|
||||
@ -128,6 +143,46 @@ uint32_t bootloader_read_flash_id(void)
|
||||
return id;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define FLASH_WRAP_CMD 0x77
|
||||
typedef enum {
|
||||
FLASH_WRAP_MODE_8B = 0,
|
||||
FLASH_WRAP_MODE_16B = 2,
|
||||
FLASH_WRAP_MODE_32B = 4,
|
||||
FLASH_WRAP_MODE_64B = 6,
|
||||
FLASH_WRAP_MODE_DISABLE = 1
|
||||
} spi_flash_wrap_mode_t;
|
||||
static esp_err_t spi_flash_wrap_set(spi_flash_wrap_mode_t mode)
|
||||
{
|
||||
uint32_t reg_bkp_ctrl = SPIFLASH.ctrl.val;
|
||||
uint32_t reg_bkp_usr = SPIFLASH.user.val;
|
||||
SPIFLASH.user.fwrite_dio = 0;
|
||||
SPIFLASH.user.fwrite_dual = 0;
|
||||
SPIFLASH.user.fwrite_qio = 1;
|
||||
SPIFLASH.user.fwrite_quad = 0;
|
||||
SPIFLASH.ctrl.fcmd_dual = 0;
|
||||
SPIFLASH.ctrl.fcmd_quad = 0;
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 1;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
SPIFLASH.user2.usr_command_bitlen = 7;
|
||||
SPIFLASH.user2.usr_command_value = FLASH_WRAP_CMD;
|
||||
SPIFLASH.user1.usr_addr_bitlen = 23;
|
||||
SPIFLASH.addr = 0;
|
||||
SPIFLASH.user.usr_miso = 0;
|
||||
SPIFLASH.user.usr_mosi = 1;
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = 7;
|
||||
SPIFLASH.data_buf[0] = (uint32_t) mode << 4;;
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = reg_bkp_ctrl;
|
||||
SPIFLASH.user.val = reg_bkp_usr;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void bootloader_enable_qio_mode(void)
|
||||
{
|
||||
uint32_t raw_flash_id;
|
||||
@ -156,7 +211,9 @@ void bootloader_enable_qio_mode(void)
|
||||
if (i == NUM_CHIPS - 1) {
|
||||
ESP_LOGI(TAG, "Enabling default flash chip QIO");
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
spi_flash_wrap_set(FLASH_WRAP_MODE_DISABLE);
|
||||
#endif
|
||||
enable_qio_mode(chip_data[i].read_status_fn,
|
||||
chip_data[i].write_status_fn,
|
||||
chip_data[i].status_qio_bit);
|
||||
@ -169,6 +226,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
uint32_t status;
|
||||
const uint32_t spiconfig = ets_efuse_get_spiconfig();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (spiconfig != EFUSE_SPICONFIG_SPI_DEFAULTS && spiconfig != EFUSE_SPICONFIG_HSPI_DEFAULTS) {
|
||||
// spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP,
|
||||
// which is compiled into the bootloader instead.
|
||||
@ -184,6 +242,7 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
ESP_LOGW(TAG, "Chip is ESP32-D2WD/ESP32-PICOD4 but flash WP pin is different value to internal flash");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_rom_spiflash_wait_idle(&g_rom_flashchip);
|
||||
|
||||
@ -218,8 +277,15 @@ static esp_err_t enable_qio_mode(read_status_fn_t read_status_fn,
|
||||
|
||||
esp_rom_spiflash_config_readmode(mode);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (ets_efuse_get_wp_pad() <= MAX_PAD_GPIO_NUM) {
|
||||
esp_rom_spiflash_select_qio_pins(ets_efuse_get_wp_pad(), spiconfig);
|
||||
} else {
|
||||
esp_rom_spiflash_select_qio_pins(CONFIG_BOOTLOADER_SPI_WP_PIN, spiconfig);
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -274,7 +340,11 @@ static void write_status_8b_xmc25qu64a(unsigned new_status)
|
||||
static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8_t mosi_len, uint8_t miso_len)
|
||||
{
|
||||
uint32_t old_ctrl_reg = SPIFLASH.ctrl.val;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.ctrl.val = SPI_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPIFLASH.ctrl.val = SPI_MEM_WP_REG_M; // keep WP high while idle, otherwise leave DIO mode
|
||||
#endif
|
||||
SPIFLASH.user.usr_dummy = 0;
|
||||
SPIFLASH.user.usr_addr = 0;
|
||||
SPIFLASH.user.usr_command = 1;
|
||||
@ -282,9 +352,17 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
|
||||
SPIFLASH.user2.usr_command_value = command;
|
||||
SPIFLASH.user.usr_miso = miso_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.miso_dlen.usr_miso_dbitlen = miso_len ? (miso_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPIFLASH.miso_dlen.usr_miso_bit_len = miso_len ? (miso_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.user.usr_mosi = mosi_len > 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SPIFLASH.mosi_dlen.usr_mosi_dbitlen = mosi_len ? (mosi_len - 1) : 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPIFLASH.mosi_dlen.usr_mosi_bit_len = mosi_len ? (mosi_len - 1) : 0;
|
||||
#endif
|
||||
SPIFLASH.data_buf[0] = mosi_data;
|
||||
|
||||
if (g_rom_spiflash_dummy_len_plus[1]) {
|
||||
@ -299,8 +377,8 @@ static uint32_t execute_flash_command(uint8_t command, uint32_t mosi_data, uint8
|
||||
}
|
||||
|
||||
SPIFLASH.cmd.usr = 1;
|
||||
while(SPIFLASH.cmd.usr != 0)
|
||||
{ }
|
||||
while (SPIFLASH.cmd.usr != 0) {
|
||||
}
|
||||
|
||||
SPIFLASH.ctrl.val = old_ctrl_reg;
|
||||
return SPIFLASH.data_buf[0];
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <esp_types.h>
|
||||
#include <stdio.h>
|
||||
#include "string.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
@ -34,7 +33,7 @@ TEST_CASE("Verify bootloader image in flash", "[bootloader_support]")
|
||||
TEST_ASSERT_EQUAL(data.image_len, bootloader_length);
|
||||
}
|
||||
|
||||
TEST_CASE("Verify unit test app image", "[bootloader_support]")
|
||||
TEST_CASE_ESP32("Verify unit test app image", "[bootloader_support]")
|
||||
{
|
||||
esp_image_metadata_t data = { 0 };
|
||||
const esp_partition_t *running = esp_ota_get_running_partition();
|
||||
|
@ -2,6 +2,7 @@ menu "Bluetooth"
|
||||
|
||||
config BT_ENABLED
|
||||
bool "Bluetooth"
|
||||
depends on IDF_TARGET_ESP32
|
||||
help
|
||||
Select this option to enable Bluetooth and show the submenu with Bluetooth configuration choices.
|
||||
|
||||
|
@ -276,14 +276,14 @@ TEST_CASE("c++ exceptions emergency pool", "[cxx] [ignore]")
|
||||
|
||||
#else // !CONFIG_COMPILER_CXX_EXCEPTIONS
|
||||
|
||||
TEST_CASE("std::out_of_range exception when -fno-exceptions", "[cxx][reset=abort,SW_CPU_RESET]")
|
||||
TEST_CASE_ESP32("std::out_of_range exception when -fno-exceptions", "[cxx][reset=abort,SW_CPU_RESET]")
|
||||
{
|
||||
std::vector<int> v(10);
|
||||
v.at(20) = 42;
|
||||
TEST_FAIL_MESSAGE("Unreachable because we are aborted on the line above");
|
||||
}
|
||||
|
||||
TEST_CASE("std::bad_alloc exception when -fno-exceptions", "[cxx][reset=abort,SW_CPU_RESET]")
|
||||
TEST_CASE_ESP32("std::bad_alloc exception when -fno-exceptions", "[cxx][reset=abort,SW_CPU_RESET]")
|
||||
{
|
||||
std::string s = std::string(2000000000, 'a');
|
||||
(void)s;
|
||||
|
@ -4,14 +4,10 @@ set(srcs
|
||||
"i2c.c"
|
||||
"i2s.c"
|
||||
"ledc.c"
|
||||
"mcpwm.c"
|
||||
"pcnt.c"
|
||||
"periph_ctrl.c"
|
||||
"rmt.c"
|
||||
"rtc_module.c"
|
||||
"sdio_slave.c"
|
||||
"sdmmc_host.c"
|
||||
"sdmmc_transaction.c"
|
||||
"sdspi_crc.c"
|
||||
"sdspi_host.c"
|
||||
"sdspi_transaction.c"
|
||||
@ -22,8 +18,25 @@ set(srcs
|
||||
"timer.c"
|
||||
"uart.c")
|
||||
|
||||
set(includes "include")
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
# SDMMC and MCPWM are in ESP32 only.
|
||||
list(APPEND srcs "mcpwm.c"
|
||||
"sdio_slave.c"
|
||||
"sdmmc_host.c"
|
||||
"sdmmc_transaction.c")
|
||||
endif()
|
||||
|
||||
if(IDF_TARGET STREQUAL "esp32s2beta")
|
||||
list(APPEND srcs "esp32s2beta/rtc_tempsensor.c"
|
||||
"esp32s2beta/rtc_touchpad.c")
|
||||
# currently only S2 beta has its own target-specific includes
|
||||
list(APPEND includes "esp32s2beta/include")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRCS "${srcs}"
|
||||
INCLUDE_DIRS "include"
|
||||
INCLUDE_DIRS ${includes}
|
||||
PRIV_INCLUDE_DIRS "include/driver"
|
||||
REQUIRES esp_ringbuf soc) #cannot totally hide soc headers, since there are a lot arguments in the driver are chip-dependent
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "freertos/task.h"
|
||||
@ -25,6 +25,7 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "driver/can.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
/* ---------------------------- Definitions --------------------------------- */
|
||||
//Internal Macros
|
||||
@ -1049,3 +1050,4 @@ esp_err_t can_clear_receive_queue(void)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
@ -1,8 +1,9 @@
|
||||
#
|
||||
# Component Makefile
|
||||
#
|
||||
COMPONENT_SRCDIRS := . $(IDF_TARGET)
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := include
|
||||
COMPONENT_ADD_INCLUDEDIRS := include $(IDF_TARGET)/include
|
||||
|
||||
COMPONENT_PRIV_INCLUDEDIRS := include/driver
|
||||
|
||||
|
99
components/driver/esp32s2beta/include/temp_sensor.h
Normal file
99
components/driver/esp32s2beta/include/temp_sensor.h
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright 2010-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "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
|
144
components/driver/esp32s2beta/rtc_tempsensor.c
Normal file
144
components/driver/esp32s2beta/rtc_tempsensor.c
Normal file
@ -0,0 +1,144 @@
|
||||
// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/rtc_io_struct.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/sens_struct.h"
|
||||
#include "temp_sensor.h"
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
|
||||
static const char *TAG = "tsens";
|
||||
|
||||
#define TSENS_CHECK(res, ret_val) ({ \
|
||||
if (!(res)) { \
|
||||
ESP_LOGE(TAG, "%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__); \
|
||||
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 SemaphoreHandle_t rtc_tsens_mux = NULL;
|
||||
|
||||
esp_err_t temp_sensor_set_config(temp_sensor_config_t tsens)
|
||||
{
|
||||
SENS.sar_tctrl.tsens_dac = dac_offset[tsens.dac_offset].set_val;
|
||||
SENS.sar_tctrl.tsens_clk_div = tsens.clk_div;
|
||||
SENS.sar_tctrl.tsens_power_up_force = 1;
|
||||
SENS.sar_tctrl2.tsens_xpd_wait = TSENS_XPD_WAIT_DEFAULT;
|
||||
SENS.sar_tctrl2.tsens_xpd_force = 1;
|
||||
SENS.sar_tctrl2.tsens_reset = 1;// Reset the temp sensor.
|
||||
SENS.sar_tctrl2.tsens_reset = 0;// Clear the reset status.
|
||||
ESP_LOGI(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);
|
||||
tsens->dac_offset = SENS.sar_tctrl.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 = SENS.sar_tctrl.tsens_clk_div;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_start(void)
|
||||
{
|
||||
if (rtc_tsens_mux == NULL) {
|
||||
rtc_tsens_mux = xSemaphoreCreateMutex();
|
||||
}
|
||||
TSENS_CHECK(rtc_tsens_mux != NULL, ESP_ERR_NO_MEM);
|
||||
SENS.sar_tctrl.tsens_dump_out = 0;
|
||||
SENS.sar_tctrl2.tsens_clkgate_en = 1;
|
||||
SENS.sar_tctrl.tsens_power_up = 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_stop(void)
|
||||
{
|
||||
SENS.sar_tctrl.tsens_power_up = 0;
|
||||
SENS.sar_tctrl2.tsens_clkgate_en = 0;
|
||||
if (rtc_tsens_mux != NULL) {
|
||||
vSemaphoreDelete(rtc_tsens_mux);
|
||||
rtc_tsens_mux = NULL;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t temp_sensor_read_raw(uint32_t *tsens_out)
|
||||
{
|
||||
TSENS_CHECK(tsens_out != NULL, ESP_ERR_INVALID_ARG);
|
||||
TSENS_CHECK(rtc_tsens_mux != NULL, ESP_ERR_INVALID_STATE);
|
||||
xSemaphoreTake(rtc_tsens_mux, portMAX_DELAY);
|
||||
SENS.sar_tctrl.tsens_dump_out = 1;
|
||||
while (!SENS.sar_tctrl.tsens_ready);
|
||||
*tsens_out = SENS.sar_tctrl.tsens_out;
|
||||
SENS.sar_tctrl.tsens_dump_out = 0;
|
||||
xSemaphoreGive(rtc_tsens_mux);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
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);
|
||||
TSENS_CHECK(ret == ESP_OK, ret);
|
||||
const tsens_dac_offset_t *dac = &dac_offset[tsens.dac_offset];
|
||||
*celsius = (TSENS_ADC_FACTOR * (float)tsens_out - TSENS_DAC_FACTOR * dac->offset - TSENS_SYS_OFFSET);
|
||||
if (*celsius < dac->range_min || *celsius > dac->range_max) {
|
||||
ESP_LOGW(TAG, "Exceeding the temperature range!");
|
||||
ret = ESP_ERR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
674
components/driver/esp32s2beta/rtc_touchpad.c
Normal file
674
components/driver/esp32s2beta/rtc_touchpad.c
Normal file
@ -0,0 +1,674 @@
|
||||
// Copyright 2016-2018 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/sens_periph.h"
|
||||
#include "soc/rtc_io_reg.h"
|
||||
#include "soc/rtc_io_struct.h"
|
||||
#include "soc/sens_reg.h"
|
||||
#include "soc/sens_struct.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/rtc_cntl_struct.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "rtc_io.h"
|
||||
#include "touch_pad.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/timers.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "sys/lock.h"
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Enable built-in checks in queue.h in debug builds
|
||||
#define INVARIANTS
|
||||
#endif
|
||||
#include "sys/queue.h"
|
||||
|
||||
#define TOUCH_PAD_FILTER_FACTOR_DEFAULT (4) // IIR filter coefficient.
|
||||
#define TOUCH_PAD_SHIFT_DEFAULT (4) // Increase computing accuracy.
|
||||
#define TOUCH_PAD_SHIFT_ROUND_DEFAULT (8) // ROUND = 2^(n-1); rounding off for fractional.
|
||||
#define TOUCH_PAD_MEASURE_WAIT_DEFAULT (0xFF) // The timer frequency is 8Mhz, the max value is 0xff
|
||||
#define DAC_ERR_STR_CHANNEL_ERROR "DAC channel error"
|
||||
|
||||
#define RTC_MODULE_CHECK(a, str, ret_val) ({ \
|
||||
if (!(a)) { \
|
||||
ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s):%s", __FILE__, __LINE__, __FUNCTION__, str); \
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
#define RTC_RES_CHECK(res, ret_val) ({ \
|
||||
if ( (res) != ESP_OK) { \
|
||||
ESP_LOGE(RTC_MODULE_TAG,"%s:%d (%s)", __FILE__, __LINE__, __FUNCTION__);\
|
||||
return (ret_val); \
|
||||
} \
|
||||
})
|
||||
|
||||
static portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#define RTC_TOUCH_ENTER_CRITICAL() portENTER_CRITICAL(&rtc_spinlock)
|
||||
#define RTC_TOUCH_EXIT_CRITICAL() portEXIT_CRITICAL(&rtc_spinlock)
|
||||
|
||||
static SemaphoreHandle_t rtc_touch_mux = NULL;
|
||||
static const char *RTC_MODULE_TAG = "RTC_MODULE";
|
||||
|
||||
/*---------------------------------------------------------------
|
||||
Touch Pad
|
||||
---------------------------------------------------------------*/
|
||||
esp_err_t touch_pad_isr_register(intr_handler_t fn, void *arg, touch_pad_intr_mask_t intr_mask)
|
||||
{
|
||||
assert(fn != NULL);
|
||||
return rtc_isr_register(fn, arg, TOUCH_PAD_INTR_MASK_ALL & (intr_mask << RTC_CNTL_TOUCH_DONE_INT_ENA_S));
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_isr_deregister(intr_handler_t fn, void *arg)
|
||||
{
|
||||
return rtc_isr_deregister(fn, arg);
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_times)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
// touch sensor sleep cycle Time = sleep_cycle / RTC_SLOW_CLK( can be 150k or 32k depending on the options)
|
||||
RTCCNTL.touch_ctrl1.touch_sleep_cycles = sleep_cycle;
|
||||
//The times of charge and discharge in each measure process of touch channels.
|
||||
RTCCNTL.touch_ctrl1.touch_meas_num = meas_times;
|
||||
//the waiting cycles (in 8MHz) between TOUCH_START and TOUCH_XPD
|
||||
RTCCNTL.touch_ctrl2.touch_xpd_wait = TOUCH_PAD_MEASURE_WAIT_DEFAULT; //wait volt stable
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_times)
|
||||
{
|
||||
if (sleep_cycle) {
|
||||
*sleep_cycle = RTCCNTL.touch_ctrl1.touch_sleep_cycles;
|
||||
}
|
||||
if (meas_times) {
|
||||
*meas_times = RTCCNTL.touch_ctrl1.touch_meas_num;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_inactive_connect(touch_pad_conn_type_t type)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_inactive_connection = type;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_inactive_connect(touch_pad_conn_type_t *type)
|
||||
{
|
||||
RTC_MODULE_CHECK(type != NULL, "parameter is NULL", ESP_ERR_INVALID_ARG);
|
||||
*type = RTCCNTL.touch_scan_ctrl.touch_inactive_connection;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, touch_volt_atten_t atten)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
if (refh > TOUCH_HVOLT_KEEP) {
|
||||
RTCCNTL.touch_ctrl2.touch_drefh = refh;
|
||||
}
|
||||
if (refl > TOUCH_LVOLT_KEEP) {
|
||||
RTCCNTL.touch_ctrl2.touch_drefl = refl;
|
||||
}
|
||||
if (atten > TOUCH_HVOLT_ATTEN_KEEP) {
|
||||
RTCCNTL.touch_ctrl2.touch_drange = atten;
|
||||
}
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten)
|
||||
{
|
||||
if (refh) {
|
||||
*refh = RTCCNTL.touch_ctrl2.touch_drefh;
|
||||
}
|
||||
if (refl) {
|
||||
*refl = RTCCNTL.touch_ctrl2.touch_drefl;
|
||||
}
|
||||
if (atten) {
|
||||
*atten = RTCCNTL.touch_ctrl2.touch_drange;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope, touch_tie_opt_t opt)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCIO.touch_pad[touch_num].tie_opt = opt;
|
||||
RTCIO.touch_pad[touch_num].dac = slope;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt)
|
||||
{
|
||||
if (slope) {
|
||||
*slope = RTCIO.touch_pad[touch_num].dac;
|
||||
}
|
||||
if (opt) {
|
||||
*opt = RTCIO.touch_pad[touch_num].tie_opt;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_io_init(touch_pad_t touch_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(touch_num != TOUCH_DENOISE_CHANNEL,
|
||||
"please use `touch_pad_denoise_enable` to set denoise channel", ESP_ERR_INVALID_ARG);
|
||||
rtc_gpio_init(touch_num);
|
||||
rtc_gpio_set_direction(touch_num, RTC_GPIO_MODE_DISABLED);
|
||||
rtc_gpio_pulldown_dis(touch_num);
|
||||
rtc_gpio_pullup_dis(touch_num);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_wait_init_done(void)
|
||||
{
|
||||
// TODO
|
||||
return ESP_FAIL;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_fsm_start(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_ctrl2.touch_clkgate_en = 1; //enable touch clock for FSM. or force enable.
|
||||
SENS.sar_touch_chn_st.touch_channel_clr = TOUCH_PAD_BIT_MASK_MAX; // clear SENS_TOUCH_SLP_BASELINE
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_fsm_stop(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_ctrl2.touch_start_en = 0; //stop touch fsm
|
||||
RTCCNTL.touch_ctrl2.touch_slp_timer_en = 0;
|
||||
RTCCNTL.touch_ctrl2.touch_clkgate_en = 0; //enable touch clock for FSM. or force enable.
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_ctrl2.touch_start_en = 0; //stop touch fsm
|
||||
RTCCNTL.touch_ctrl2.touch_start_force = mode;
|
||||
RTCCNTL.touch_ctrl2.touch_slp_timer_en = (mode == TOUCH_FSM_MODE_TIMER ? 1 : 0);
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode)
|
||||
{
|
||||
assert(mode != NULL);
|
||||
*mode = RTCCNTL.touch_ctrl2.touch_start_force;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
bool touch_pad_meas_is_done(void)
|
||||
{
|
||||
return SENS.sar_touch_chn_st.touch_meas_done;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_sw_start(void)
|
||||
{
|
||||
RTC_MODULE_CHECK((RTCCNTL.touch_ctrl2.touch_start_force == TOUCH_FSM_MODE_SW),
|
||||
"touch fsm mode error", ESP_ERR_INVALID_STATE);
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_ctrl2.touch_start_en = 0;
|
||||
RTCCNTL.touch_ctrl2.touch_start_en = 1;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold)
|
||||
{
|
||||
RTC_MODULE_CHECK((touch_num < TOUCH_PAD_MAX) && (touch_num != TOUCH_DENOISE_CHANNEL), "touch num error", ESP_ERR_INVALID_ARG);
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
SENS.touch_thresh[touch_num - 1].thresh = threshold;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold)
|
||||
{
|
||||
if (threshold) {
|
||||
*threshold = SENS.touch_thresh[touch_num - 1].thresh;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_set_group_mask(uint16_t enable_mask)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_scan_pad_map |= (enable_mask & TOUCH_PAD_BIT_MASK_MAX);
|
||||
SENS.sar_touch_conf.touch_outen |= (enable_mask & TOUCH_PAD_BIT_MASK_MAX);
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_group_mask(uint16_t *enable_mask)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
*enable_mask = SENS.sar_touch_conf.touch_outen \
|
||||
& RTCCNTL.touch_scan_ctrl.touch_scan_pad_map \
|
||||
& TOUCH_PAD_BIT_MASK_MAX;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_clear_group_mask(uint16_t enable_mask)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
SENS.sar_touch_conf.touch_outen &= ~(enable_mask & TOUCH_PAD_BIT_MASK_MAX);
|
||||
RTCCNTL.touch_scan_ctrl.touch_scan_pad_map &= ~(enable_mask & TOUCH_PAD_BIT_MASK_MAX);
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t IRAM_ATTR touch_pad_get_status(void)
|
||||
{
|
||||
return (SENS.sar_touch_chn_st.touch_pad_active & TOUCH_PAD_BIT_MASK_MAX);
|
||||
}
|
||||
|
||||
static esp_err_t touch_pad_clear_status(void)
|
||||
{
|
||||
SENS.sar_touch_conf.touch_status_clr = 1;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
touch_pad_t IRAM_ATTR touch_pad_get_scan_curr(void)
|
||||
{
|
||||
return (touch_pad_t)(SENS.sar_touch_status0.touch_scan_curr);
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_intr_enable(touch_pad_intr_mask_t int_mask)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
if (int_mask & TOUCH_PAD_INTR_MASK_DONE) {
|
||||
RTCCNTL.int_ena.rtc_touch_done = 1;
|
||||
}
|
||||
if (int_mask & TOUCH_PAD_INTR_MASK_ACTIVE) {
|
||||
RTCCNTL.int_ena.rtc_touch_active = 1;
|
||||
}
|
||||
if (int_mask & TOUCH_PAD_INTR_MASK_INACTIVE) {
|
||||
RTCCNTL.int_ena.rtc_touch_inactive = 1;
|
||||
}
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_intr_disable(touch_pad_intr_mask_t int_mask)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
if (int_mask & TOUCH_PAD_INTR_MASK_DONE) {
|
||||
RTCCNTL.int_ena.rtc_touch_done = 0;
|
||||
}
|
||||
if (int_mask & TOUCH_PAD_INTR_MASK_ACTIVE) {
|
||||
RTCCNTL.int_ena.rtc_touch_active = 0;
|
||||
}
|
||||
if (int_mask & TOUCH_PAD_INTR_MASK_INACTIVE) {
|
||||
RTCCNTL.int_ena.rtc_touch_inactive = 0;
|
||||
}
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t touch_pad_intr_status_get_mask(void)
|
||||
{
|
||||
return ((REG_READ(RTC_CNTL_INT_ST_REG) >> (RTC_CNTL_TOUCH_DONE_INT_ST_S)) & TOUCH_PAD_INTR_MASK_ALL);
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_config(touch_pad_t touch_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(touch_num != TOUCH_DENOISE_CHANNEL, \
|
||||
"please use `touch_pad_denoise_enable` to set denoise channel", ESP_ERR_INVALID_ARG);
|
||||
touch_pad_io_init(touch_num);
|
||||
touch_pad_set_cnt_mode(touch_num, TOUCH_PAD_SLOPE_7, TOUCH_PAD_TIE_OPT_LOW);
|
||||
touch_pad_set_thresh(touch_num, TOUCH_PAD_THRESHOLD_MAX);
|
||||
touch_pad_set_group_mask(BIT(touch_num));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_init(void)
|
||||
{
|
||||
if (rtc_touch_mux == NULL) {
|
||||
rtc_touch_mux = xSemaphoreCreateMutex();
|
||||
}
|
||||
if (rtc_touch_mux == NULL) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
touch_pad_intr_disable(TOUCH_PAD_INTR_ALL);
|
||||
touch_pad_clear_group_mask(TOUCH_PAD_BIT_MASK_MAX);
|
||||
touch_pad_clear_status();
|
||||
touch_pad_set_meas_time(TOUCH_PAD_SLEEP_CYCLE_DEFAULT, TOUCH_PAD_MEASURE_CYCLE_DEFAULT);
|
||||
// Set reference voltage for charging/discharging
|
||||
touch_pad_set_voltage(TOUCH_HVOLT_2V7, TOUCH_LVOLT_0V5, TOUCH_HVOLT_ATTEN_0V5);
|
||||
touch_pad_set_inactive_connect(TOUCH_PAD_CONN_GND);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_deinit(void)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_touch_mux != NULL, "Touch pad not initialized", ESP_FAIL);
|
||||
xSemaphoreTake(rtc_touch_mux, portMAX_DELAY);
|
||||
touch_pad_fsm_stop();
|
||||
touch_pad_clear_status();
|
||||
touch_pad_intr_disable(TOUCH_PAD_INTR_ALL);
|
||||
xSemaphoreGive(rtc_touch_mux);
|
||||
vSemaphoreDelete(rtc_touch_mux);
|
||||
rtc_touch_mux = NULL;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t IRAM_ATTR touch_pad_read_raw_data(touch_pad_t touch_num, uint32_t *raw_data)
|
||||
{
|
||||
if (raw_data) {
|
||||
*raw_data = SENS.touch_meas[touch_num].meas_out;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
esp_err_t IRAM_ATTR touch_pad_filter_baseline_read(touch_pad_t touch_num, uint32_t *basedata)
|
||||
{
|
||||
RTC_MODULE_CHECK(touch_num != TOUCH_DENOISE_CHANNEL, "denoise channel don't support", ESP_ERR_INVALID_ARG);
|
||||
if (basedata) {
|
||||
*basedata = SENS.sar_touch_status[touch_num - 1].touch_pad_baseline;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_filter_debounce_read(touch_pad_t touch_num, uint32_t *debounce)
|
||||
{
|
||||
RTC_MODULE_CHECK(touch_num != TOUCH_DENOISE_CHANNEL, "denoise channel don't support", ESP_ERR_INVALID_ARG);
|
||||
if (debounce) {
|
||||
*debounce = SENS.sar_touch_status[touch_num - 1].touch_pad_debounce;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Should be call after clk enable and filter enable. */
|
||||
esp_err_t touch_pad_filter_baseline_reset(touch_pad_t touch_num)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
if (touch_num == TOUCH_PAD_MAX) {
|
||||
SENS.sar_touch_chn_st.touch_channel_clr = TOUCH_PAD_BIT_MASK_MAX;
|
||||
} else {
|
||||
SENS.sar_touch_chn_st.touch_channel_clr = BIT(touch_num);
|
||||
}
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_filter_set_config(touch_filter_config_t *filter_info)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_filter_ctrl.touch_filter_mode = filter_info->mode;
|
||||
RTCCNTL.touch_filter_ctrl.touch_debounce = filter_info->debounce_cnt;
|
||||
RTCCNTL.touch_filter_ctrl.touch_hysteresis = filter_info->hysteresis_thr;
|
||||
RTCCNTL.touch_filter_ctrl.touch_noise_thres = filter_info->noise_thr;
|
||||
RTCCNTL.touch_filter_ctrl.touch_neg_noise_thres = filter_info->noise_neg_thr;
|
||||
RTCCNTL.touch_filter_ctrl.touch_neg_noise_limit = filter_info->neg_noise_limit;
|
||||
RTCCNTL.touch_filter_ctrl.touch_jitter_step = filter_info->jitter_step;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_filter_get_config(touch_filter_config_t *filter_info)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
filter_info->mode = RTCCNTL.touch_filter_ctrl.touch_filter_mode;
|
||||
filter_info->debounce_cnt = RTCCNTL.touch_filter_ctrl.touch_debounce;
|
||||
filter_info->hysteresis_thr = RTCCNTL.touch_filter_ctrl.touch_hysteresis;
|
||||
filter_info->noise_thr = RTCCNTL.touch_filter_ctrl.touch_noise_thres;
|
||||
filter_info->noise_neg_thr = RTCCNTL.touch_filter_ctrl.touch_neg_noise_thres;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_filter_enable(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_filter_ctrl.touch_filter_en = 1;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_filter_disable(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_filter_ctrl.touch_filter_en = 0;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_denoise_enable(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_scan_pad_map &= ~(BIT(TOUCH_DENOISE_CHANNEL));
|
||||
RTCCNTL.touch_scan_ctrl.touch_denoise_en = 1;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_denoise_disable(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_denoise_en = 0;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_denoise_set_config(touch_pad_denoise_t denoise)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCIO.touch_pad[TOUCH_DENOISE_CHANNEL].tie_opt = TOUCH_PAD_TIE_OPT_LOW;
|
||||
RTCIO.touch_pad[TOUCH_DENOISE_CHANNEL].dac = TOUCH_PAD_SLOPE_7;
|
||||
RTCCNTL.touch_ctrl2.touch_refc = denoise.cap_level;
|
||||
RTCCNTL.touch_scan_ctrl.touch_denoise_res = denoise.grade;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_denoise_get_config(touch_pad_denoise_t *denoise)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
denoise->grade = RTCCNTL.touch_scan_ctrl.touch_denoise_res;
|
||||
denoise->cap_level = RTCCNTL.touch_ctrl2.touch_refc;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_denoise_data_get(uint32_t *data)
|
||||
{
|
||||
if (data) {
|
||||
*data = SENS.sar_touch_status0.touch_denoise_data;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_waterproof_set_config(touch_pad_waterproof_t waterproof)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_out_ring = waterproof.guard_ring_pad;
|
||||
RTCCNTL.touch_scan_ctrl.touch_bufdrv = waterproof.shield_driver;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_waterproof_get_config(touch_pad_waterproof_t *waterproof)
|
||||
{
|
||||
if (waterproof) {
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
waterproof->guard_ring_pad = RTCCNTL.touch_scan_ctrl.touch_out_ring;
|
||||
waterproof->shield_driver = RTCCNTL.touch_scan_ctrl.touch_bufdrv;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_waterproof_enable(void)
|
||||
{
|
||||
touch_pad_io_init(TOUCH_SHIELD_CHANNEL);
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_scan_pad_map &= ~(BIT(TOUCH_SHIELD_CHANNEL));
|
||||
RTCCNTL.touch_scan_ctrl.touch_shield_pad_en = 1;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_waterproof_disable(void)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_scan_ctrl.touch_shield_pad_en = 0;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_proximity_set_config(touch_pad_proximity_t proximity)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
if (proximity.select_pad0) {
|
||||
SENS.sar_touch_conf.touch_approach_pad0 = proximity.select_pad0;
|
||||
}
|
||||
if (proximity.select_pad1) {
|
||||
SENS.sar_touch_conf.touch_approach_pad1 = proximity.select_pad1;
|
||||
}
|
||||
if (proximity.select_pad2) {
|
||||
SENS.sar_touch_conf.touch_approach_pad2 = proximity.select_pad2;
|
||||
}
|
||||
RTCCNTL.touch_approach.touch_approach_meas_time = proximity.meas_num;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_proximity_get_config(touch_pad_proximity_t *proximity)
|
||||
{
|
||||
if (proximity) {
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
proximity->select_pad0 = SENS.sar_touch_conf.touch_approach_pad0;
|
||||
proximity->select_pad1 = SENS.sar_touch_conf.touch_approach_pad1;
|
||||
proximity->select_pad2 = SENS.sar_touch_conf.touch_approach_pad2;
|
||||
proximity->meas_num = RTCCNTL.touch_approach.touch_approach_meas_time;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_proximity_get_meas_cnt(touch_pad_t touch_num, uint32_t *cnt)
|
||||
{
|
||||
if (cnt == NULL) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (SENS.sar_touch_conf.touch_approach_pad0 == touch_num) {
|
||||
*cnt = SENS.sar_touch_status16.touch_approach_pad0_cnt;
|
||||
} else if (SENS.sar_touch_conf.touch_approach_pad1 == touch_num) {
|
||||
*cnt = SENS.sar_touch_status16.touch_approach_pad1_cnt;
|
||||
} else if (SENS.sar_touch_conf.touch_approach_pad2 == touch_num) {
|
||||
*cnt = SENS.sar_touch_status16.touch_approach_pad2_cnt;
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_proximity_data_get(touch_pad_t touch_num, uint32_t *measure_out)
|
||||
{
|
||||
if ((SENS.sar_touch_conf.touch_approach_pad0 != touch_num)
|
||||
&& (SENS.sar_touch_conf.touch_approach_pad1 != touch_num)
|
||||
&& (SENS.sar_touch_conf.touch_approach_pad2 != touch_num)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (ESP_OK != touch_pad_filter_baseline_read(touch_num, measure_out)) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_reset()
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_ctrl2.touch_reset = 0;
|
||||
RTCCNTL.touch_ctrl2.touch_reset = 1;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/************** sleep pad setting ***********************/
|
||||
|
||||
esp_err_t touch_pad_sleep_channel_config(touch_pad_sleep_channel_t slp_config)
|
||||
{
|
||||
RTC_TOUCH_ENTER_CRITICAL();
|
||||
RTCCNTL.touch_slp_thres.touch_slp_pad = slp_config.touch_num;
|
||||
RTCCNTL.touch_slp_thres.touch_slp_th = slp_config.sleep_pad_threshold;
|
||||
RTCCNTL.touch_slp_thres.touch_slp_approach_en = slp_config.en_proximity;
|
||||
RTC_TOUCH_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_sleep_channel_baseline_get(uint32_t *baseline)
|
||||
{
|
||||
if (baseline) {
|
||||
*baseline = REG_GET_FIELD(SENS_SAR_TOUCH_STATUS15_REG, SENS_TOUCH_SLP_BASELINE);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_sleep_channel_debounce_get(uint32_t *debounce)
|
||||
{
|
||||
if (debounce) {
|
||||
*debounce = REG_GET_FIELD(SENS_SAR_TOUCH_STATUS15_REG, SENS_TOUCH_SLP_DEBOUNCE);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_sleep_channel_proximity_cnt_get(uint32_t *approach_cnt)
|
||||
{
|
||||
if (approach_cnt) {
|
||||
*approach_cnt = REG_GET_FIELD(SENS_SAR_TOUCH_STATUS16_REG, SENS_TOUCH_SLP_APPROACH_CNT);
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num)
|
||||
{
|
||||
if (pad_num) {
|
||||
*pad_num = (touch_pad_t)RTCCNTL.touch_slp_thres.touch_slp_pad;
|
||||
} else {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
@ -18,6 +18,8 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "soc/soc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "esp_log.h"
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
@ -55,44 +57,60 @@ static portMUX_TYPE gpio_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
esp_err_t gpio_pullup_en(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pullup_en(gpio_num);
|
||||
} else {
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_pullup_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pullup_dis(gpio_num);
|
||||
} else {
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PU);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_pulldown_en(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pulldown_en(gpio_num);
|
||||
} else {
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
REG_SET_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_pulldown_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_pulldown_dis(gpio_num);
|
||||
} else {
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
REG_CLR_BIT(GPIO_PIN_MUX_REG[gpio_num], FUN_PD);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -116,11 +134,17 @@ static void gpio_intr_status_clr(gpio_num_t gpio_num)
|
||||
static esp_err_t gpio_intr_enable_on_core (gpio_num_t gpio_num, uint32_t core_id)
|
||||
{
|
||||
gpio_intr_status_clr(gpio_num);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (core_id == 0) {
|
||||
GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr
|
||||
} else {
|
||||
GPIO.pin[gpio_num].int_ena = GPIO_APP_CPU_INTR_ENA; //enable pro cpu intr
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (core_id == 0) {
|
||||
GPIO.pin[gpio_num].int_ena = GPIO_PRO_CPU_INTR_ENA; //enable pro cpu intr
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -232,7 +256,11 @@ esp_err_t gpio_set_pull_mode(gpio_num_t gpio_num, gpio_pull_mode_t pull)
|
||||
esp_err_t gpio_set_direction(gpio_num_t gpio_num, gpio_mode_t mode)
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (gpio_num >= 34 && (mode & GPIO_MODE_DEF_OUTPUT)) {
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (gpio_num >= 46 && (mode & GPIO_MODE_DEF_OUTPUT)) {
|
||||
#endif
|
||||
ESP_LOGE(GPIO_TAG, "io_num=%d can only be input", gpio_num);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
@ -269,6 +297,7 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
|
||||
ESP_LOGE(GPIO_TAG, "GPIO_PIN mask error ");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ((pGPIOConfig->mode) & (GPIO_MODE_DEF_OUTPUT)) {
|
||||
//GPIO 34/35/36/37/38/39 can only be used as input mode;
|
||||
if ((gpio_pin_mask & ( GPIO_SEL_34 | GPIO_SEL_35 | GPIO_SEL_36 | GPIO_SEL_37 | GPIO_SEL_38 | GPIO_SEL_39))) {
|
||||
@ -276,6 +305,12 @@ esp_err_t gpio_config(const gpio_config_t *pGPIOConfig)
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if ( (pGPIOConfig->mode & GPIO_MODE_DEF_OUTPUT) && (gpio_pin_mask & GPIO_SEL_46) ) {
|
||||
ESP_LOGE(GPIO_TAG, "GPIO46 can only be used as input mode");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
do {
|
||||
io_reg = GPIO_PIN_MUX_REG[io_num];
|
||||
if (((gpio_pin_mask >> io_num) & BIT(0))) {
|
||||
@ -363,14 +398,24 @@ static void IRAM_ATTR gpio_intr_service(void* arg)
|
||||
return;
|
||||
}
|
||||
//read status to get interrupt status for GPIO0-31
|
||||
const uint32_t gpio_intr_status = (isr_core_id == 0) ? GPIO.pcpu_int : GPIO.acpu_int;
|
||||
uint32_t gpio_intr_status;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
gpio_intr_status = (isr_core_id == 0) ? GPIO.pcpu_int : GPIO.acpu_int;
|
||||
#else
|
||||
gpio_intr_status = GPIO.pcpu_int;
|
||||
#endif
|
||||
if (gpio_intr_status) {
|
||||
gpio_isr_loop(gpio_intr_status, 0);
|
||||
GPIO.status_w1tc = gpio_intr_status;
|
||||
}
|
||||
|
||||
//read status1 to get interrupt status for GPIO32-39
|
||||
const uint32_t gpio_intr_status_h = (isr_core_id == 0) ? GPIO.pcpu_int1.intr : GPIO.acpu_int1.intr;
|
||||
uint32_t gpio_intr_status_h;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
gpio_intr_status_h = (isr_core_id == 0) ? GPIO.pcpu_int1.intr : GPIO.acpu_int1.intr;
|
||||
#else
|
||||
gpio_intr_status_h = GPIO.pcpu_int1.intr;
|
||||
#endif
|
||||
if (gpio_intr_status_h) {
|
||||
gpio_isr_loop(gpio_intr_status_h, 32);
|
||||
GPIO.status1_w1tc.intr_st = gpio_intr_status_h;
|
||||
@ -498,12 +543,15 @@ esp_err_t gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t streng
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
GPIO_CHECK(strength < GPIO_DRIVE_CAP_MAX, "GPIO drive capability error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
rtc_gpio_set_drive_capability(gpio_num, strength);
|
||||
} else {
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, strength, FUN_DRV_S);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, strength, FUN_DRV_S);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -511,15 +559,19 @@ esp_err_t gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t* stren
|
||||
{
|
||||
GPIO_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
GPIO_CHECK(strength != NULL, "GPIO drive capability pointer error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
return rtc_gpio_get_drive_capability(gpio_num, strength);
|
||||
} else {
|
||||
*strength = GET_PERI_REG_BITS2(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, FUN_DRV_S);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
*strength = GET_PERI_REG_BITS2(GPIO_PIN_MUX_REG[gpio_num], FUN_DRV_V, FUN_DRV_S);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static const uint32_t GPIO_HOLD_MASK[34] = {
|
||||
0,
|
||||
GPIO_SEL_1,
|
||||
@ -556,6 +608,7 @@ static const uint32_t GPIO_HOLD_MASK[34] = {
|
||||
0,
|
||||
0,
|
||||
};
|
||||
#endif
|
||||
|
||||
esp_err_t gpio_hold_en(gpio_num_t gpio_num)
|
||||
{
|
||||
@ -563,11 +616,17 @@ esp_err_t gpio_hold_en(gpio_num_t gpio_num)
|
||||
esp_err_t r = ESP_OK;
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
r = rtc_gpio_hold_en(gpio_num);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
} else if (GPIO_HOLD_MASK[gpio_num]) {
|
||||
SET_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
|
||||
} else {
|
||||
r = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
} else {
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, BIT(gpio_num - RTC_GPIO_NUMBER));
|
||||
}
|
||||
#endif
|
||||
return r == ESP_OK ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@ -577,11 +636,17 @@ esp_err_t gpio_hold_dis(gpio_num_t gpio_num)
|
||||
esp_err_t r = ESP_OK;
|
||||
if (RTC_GPIO_IS_VALID_GPIO(gpio_num)) {
|
||||
r = rtc_gpio_hold_dis(gpio_num);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
}else if (GPIO_HOLD_MASK[gpio_num]) {
|
||||
CLEAR_PERI_REG_MASK(RTC_IO_DIG_PAD_HOLD_REG, GPIO_HOLD_MASK[gpio_num]);
|
||||
} else {
|
||||
r = ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
} else {
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PAD_HOLD_REG, BIT(gpio_num - RTC_GPIO_NUMBER));
|
||||
}
|
||||
#endif
|
||||
return r == ESP_OK ? ESP_OK : ESP_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
@ -595,10 +660,34 @@ void gpio_deep_sleep_hold_en(void)
|
||||
void gpio_deep_sleep_hold_dis(void)
|
||||
{
|
||||
portENTER_CRITICAL(&gpio_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_AUTOHOLD_EN_M);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
|
||||
#endif
|
||||
portEXIT_CRITICAL(&gpio_spinlock);
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
|
||||
esp_err_t gpio_force_hold_all()
|
||||
{
|
||||
rtc_gpio_force_hold_all();
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t gpio_force_unhold_all()
|
||||
{
|
||||
rtc_gpio_force_hold_dis_all();
|
||||
CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_HOLD);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
|
||||
SET_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CLR_DG_PAD_AUTOHOLD);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
void gpio_iomux_in(uint32_t gpio, uint32_t signal_idx)
|
||||
{
|
||||
GPIO.func_in_sel_cfg[signal_idx].sig_in_sel = 0;
|
||||
|
@ -24,11 +24,12 @@
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/ringbuf.h"
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_pm.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static const char* I2C_TAG = "i2c";
|
||||
#define I2C_CHECK(a, str, ret) if(!(a)) { \
|
||||
@ -458,7 +459,11 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
|
||||
if (p_i2c->mode == I2C_MODE_SLAVE) {
|
||||
int rx_fifo_cnt = I2C[i2c_num]->status_reg.rx_fifo_cnt;
|
||||
for (idx = 0; idx < rx_fifo_cnt; idx++) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
p_i2c->data_buf[idx] = I2C[i2c_num]->fifo_data.data;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
p_i2c->data_buf[idx] = READ_PERI_REG(I2C_DATA_APB_REG(i2c_num));
|
||||
#endif
|
||||
}
|
||||
xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken);
|
||||
I2C[i2c_num]->int_clr.rx_fifo_full = 1;
|
||||
@ -500,7 +505,11 @@ static void IRAM_ATTR i2c_isr_handler_default(void* arg)
|
||||
} else if (status & I2C_RXFIFO_FULL_INT_ST_M) {
|
||||
int rx_fifo_cnt = I2C[i2c_num]->status_reg.rx_fifo_cnt;
|
||||
for (idx = 0; idx < rx_fifo_cnt; idx++) {
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
p_i2c->data_buf[idx] = I2C[i2c_num]->fifo_data.data;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
p_i2c->data_buf[idx] = READ_PERI_REG(I2C_DATA_APB_REG(i2c_num));
|
||||
#endif
|
||||
}
|
||||
xRingbufferSendFromISR(p_i2c->rx_ring_buf, p_i2c->data_buf, rx_fifo_cnt, &HPTaskAwoken);
|
||||
I2C[i2c_num]->int_clr.rx_fifo_full = 1;
|
||||
@ -551,6 +560,7 @@ esp_err_t i2c_get_data_mode(i2c_port_t i2c_num, i2c_trans_mode_t *tx_trans_mode,
|
||||
static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
const int scl_half_period = I2C_CLR_BUS_HALF_PERIOD_US; // use standard 100kHz data rate
|
||||
int sda_in_sig = 0, scl_in_sig = 0;
|
||||
int i = 0;
|
||||
@ -586,6 +596,10 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
|
||||
ets_delay_us(scl_half_period);
|
||||
gpio_set_level(sda_io, 1); // STOP, SDA low -> high while SCL is HIGH
|
||||
i2c_set_pin(i2c_num, sda_io, scl_io, 1, 1, I2C_MODE_MASTER);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
I2C[i2c_num]->scl_sp_conf.scl_rst_slv_num = 9;
|
||||
I2C[i2c_num]->scl_sp_conf.scl_rst_slv_en = 1;
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -596,6 +610,7 @@ static esp_err_t i2c_master_clear_bus(i2c_port_t i2c_num)
|
||||
static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
{
|
||||
I2C_CHECK(i2c_num < I2C_NUM_MAX, I2C_NUM_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t ctr = I2C[i2c_num]->ctr.val;
|
||||
uint32_t fifo_conf = I2C[i2c_num]->fifo_conf.val;
|
||||
uint32_t scl_low_period = I2C[i2c_num]->scl_low_period.val;
|
||||
@ -615,7 +630,7 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
i2c_hw_disable(i2c_num);
|
||||
i2c_master_clear_bus(i2c_num);
|
||||
i2c_hw_enable(i2c_num);
|
||||
I2C[i2c_num]->int_ena.val = 0;
|
||||
|
||||
I2C[i2c_num]->ctr.val = ctr & (~I2C_TRANS_START_M);
|
||||
I2C[i2c_num]->fifo_conf.val = fifo_conf;
|
||||
I2C[i2c_num]->scl_low_period.val = scl_low_period;
|
||||
@ -629,18 +644,28 @@ static esp_err_t i2c_hw_fsm_reset(i2c_port_t i2c_num)
|
||||
I2C[i2c_num]->timeout.val = timeout;
|
||||
I2C[i2c_num]->scl_filter_cfg.val = scl_filter_cfg;
|
||||
I2C[i2c_num]->sda_filter_cfg.val = sda_filter_cfg;
|
||||
uint32_t intr_mask = ( I2C_TRANS_COMPLETE_INT_ENA_M
|
||||
I2C[i2c_num]->slave_addr.val = slave_addr;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
i2c_master_clear_bus(i2c_num);
|
||||
|
||||
I2C[i2c_num]->ctr.fsm_rst = 1;
|
||||
I2C[i2c_num]->ctr.fsm_rst = 0;
|
||||
I2C[i2c_num]->fifo_conf.rx_fifo_rst = 1;
|
||||
I2C[i2c_num]->fifo_conf.rx_fifo_rst = 0;
|
||||
I2C[i2c_num]->fifo_conf.tx_fifo_rst = 1;
|
||||
I2C[i2c_num]->fifo_conf.tx_fifo_rst = 0;
|
||||
#endif
|
||||
|
||||
I2C[i2c_num]->int_ena.val = 0;
|
||||
uint32_t intr_mask = I2C_TRANS_COMPLETE_INT_ENA_M
|
||||
| I2C_TRANS_START_INT_ENA_M
|
||||
| I2C_ACK_ERR_INT_ENA_M
|
||||
| I2C_RXFIFO_OVF_INT_ENA_M
|
||||
| I2C_SLAVE_TRAN_COMP_INT_ENA_M
|
||||
| I2C_TIME_OUT_INT_ENA_M);
|
||||
if (I2C[i2c_num]->ctr.ms_mode == I2C_MODE_SLAVE) {
|
||||
I2C[i2c_num]->slave_addr.val = slave_addr;
|
||||
intr_mask |= ( I2C_RXFIFO_FULL_INT_ENA_M | I2C_TRANS_COMPLETE_INT_ENA_M);
|
||||
} else {
|
||||
intr_mask |= I2C_ARBITRATION_LOST_INT_ENA_M;
|
||||
}
|
||||
| I2C_TIME_OUT_INT_ENA_M
|
||||
| I2C_RXFIFO_FULL_INT_ENA_M
|
||||
| I2C_ARBITRATION_LOST_INT_ENA_M;
|
||||
|
||||
I2C[i2c_num]->int_clr.val = intr_mask;
|
||||
I2C[i2c_num]->int_ena.val = intr_mask;
|
||||
return ESP_OK;
|
||||
@ -657,6 +682,7 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Reset the I2C hardware in case there is a soft reboot.
|
||||
i2c_hw_disable(i2c_num);
|
||||
i2c_hw_enable(i2c_num);
|
||||
@ -668,6 +694,12 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
I2C[i2c_num]->ctr.scl_force_out = 1; // set open-drain output mode
|
||||
I2C[i2c_num]->ctr.sample_scl_level = 0; //sample at high level of clock
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
I2C[i2c_num]->ctr.ref_always_on = 1;
|
||||
I2C[i2c_num]->sda_filter_cfg.val = 0;
|
||||
I2C[i2c_num]->scl_filter_cfg.val = 0;
|
||||
#endif
|
||||
|
||||
if (i2c_conf->mode == I2C_MODE_SLAVE) { //slave mode
|
||||
I2C[i2c_num]->slave_addr.addr = i2c_conf->slave.slave_addr;
|
||||
I2C[i2c_num]->slave_addr.en_10bit = i2c_conf->slave.addr_10bit_en;
|
||||
@ -687,10 +719,21 @@ esp_err_t i2c_param_config(i2c_port_t i2c_num, const i2c_config_t* i2c_conf)
|
||||
I2C[i2c_num]->timeout.tout = cycle * I2C_MASTER_TOUT_CNUM_DEFAULT;
|
||||
//set timing for data
|
||||
I2C[i2c_num]->sda_hold.time = half_cycle / 2;
|
||||
I2C[i2c_num]->sda_sample.time = half_cycle / 2;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
I2C[i2c_num]->sda_sample.time = half_cycle / 2;
|
||||
I2C[i2c_num]->scl_low_period.period = half_cycle;
|
||||
I2C[i2c_num]->scl_high_period.period = half_cycle;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int low_period = half_cycle;
|
||||
int wait_high = 0;
|
||||
int high_period = cycle - low_period - wait_high;
|
||||
I2C[i2c_num]->sda_sample.time = high_period / 2;
|
||||
I2C[i2c_num]->scl_low_period.period = low_period;
|
||||
I2C[i2c_num]->scl_high_period.period = high_period;
|
||||
I2C[i2c_num]->scl_high_period.scl_wait_high_period = wait_high;
|
||||
#endif
|
||||
|
||||
//set timing for start signal
|
||||
I2C[i2c_num]->scl_start_hold.time = half_cycle;
|
||||
I2C[i2c_num]->scl_rstart_setup.time = half_cycle;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -18,7 +18,7 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
|
||||
#include "soc/i2s_periph.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/efuse_periph.h"
|
||||
@ -34,6 +34,8 @@
|
||||
#include "esp_err.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_pm.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
static const char* I2S_TAG = "I2S";
|
||||
|
||||
@ -96,8 +98,13 @@ typedef struct {
|
||||
} i2s_obj_t;
|
||||
|
||||
static i2s_obj_t *p_i2s_obj[I2S_NUM_MAX] = {0};
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0, &I2S1};
|
||||
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED,portMUX_INITIALIZER_UNLOCKED};
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
static i2s_dev_t* I2S[I2S_NUM_MAX] = {&I2S0};
|
||||
static portMUX_TYPE i2s_spinlock[I2S_NUM_MAX] = {portMUX_INITIALIZER_UNLOCKED};
|
||||
#endif
|
||||
static int _i2s_adc_unit = -1;
|
||||
static int _i2s_adc_channel = -1;
|
||||
|
||||
@ -187,18 +194,23 @@ float i2s_get_clk(i2s_port_t i2s_num)
|
||||
|
||||
static esp_err_t i2s_isr_register(i2s_port_t i2s_num, int intr_alloc_flags, void (*fn)(void*), void * arg, i2s_isr_handle_t *handle)
|
||||
{
|
||||
return esp_intr_alloc(ETS_I2S0_INTR_SOURCE + i2s_num, intr_alloc_flags, fn, arg, handle);
|
||||
return esp_intr_alloc(i2s_periph_signal[i2s_num].irq, intr_alloc_flags, fn, arg, handle);
|
||||
}
|
||||
|
||||
|
||||
static float i2s_apll_get_fi2s(int bits_per_sample, int sdm0, int sdm1, int sdm2, int odir)
|
||||
{
|
||||
int f_xtal = (int)rtc_clk_xtal_freq_get() * 1000000;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0);
|
||||
if (is_rev0) {
|
||||
sdm0 = 0;
|
||||
sdm1 = 0;
|
||||
}
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
sdm0 = 0;
|
||||
sdm1 = 0;
|
||||
#endif
|
||||
float fout = f_xtal * (sdm2 + sdm1 / 256.0f + sdm0 / 65536.0f + 4);
|
||||
if (fout < APLL_MIN_FREQ || fout > APLL_MAX_FREQ) {
|
||||
return APLL_MAX_FREQ;
|
||||
@ -408,7 +420,13 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
i2s_driver_uninstall(i2s_num);
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
//On ESP32S2, the eof_num count in words.
|
||||
I2S[i2s_num]->rx_eof_num = (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample)/4;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//On ESP32S2, the eof_num count in bytes.
|
||||
I2S[i2s_num]->rx_eof_num = (p_i2s_obj[i2s_num]->dma_buf_len * p_i2s_obj[i2s_num]->channel_num * p_i2s_obj[i2s_num]->bytes_per_sample);
|
||||
#endif
|
||||
I2S[i2s_num]->in_link.addr = (uint32_t) p_i2s_obj[i2s_num]->rx->desc[0];
|
||||
|
||||
//destroy old rx dma if exist
|
||||
@ -434,6 +452,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
clkmInteger = clkmdiv;
|
||||
clkmDecimals = (clkmdiv - clkmInteger) / denom;
|
||||
bck = mclk / b_clk;
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
} else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_PDM) {
|
||||
uint32_t b_clk = 0;
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
@ -451,6 +470,7 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
clkmInteger = clkmdiv;
|
||||
clkmDecimals = (clkmdiv - clkmInteger) / denom;
|
||||
bck = mclk / b_clk;
|
||||
#endif
|
||||
} else {
|
||||
clkmInteger = clkmdiv;
|
||||
clkmDecimals = (clkmdiv - clkmInteger) / denom;
|
||||
@ -470,13 +490,21 @@ esp_err_t i2s_set_clk(i2s_port_t i2s_num, uint32_t rate, i2s_bits_per_sample_t b
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_a = 1;
|
||||
I2S[i2s_num]->sample_rate_conf.tx_bck_div_num = m_scale;
|
||||
I2S[i2s_num]->sample_rate_conf.rx_bck_div_num = m_scale;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 1;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
I2S[i2s_num]->clkm_conf.clk_sel = 1;
|
||||
#endif
|
||||
double fi2s_rate = i2s_apll_get_fi2s(bits, sdm0, sdm1, sdm2, odir);
|
||||
p_i2s_obj[i2s_num]->real_rate = fi2s_rate/bits/channel/m_scale;
|
||||
ESP_LOGI(I2S_TAG, "APLL: Req RATE: %d, real rate: %0.3f, BITS: %u, CLKM: %u, BCK_M: %u, MCLK: %0.3f, SCLK: %f, diva: %d, divb: %d",
|
||||
rate, fi2s_rate/bits/channel/m_scale, bits, 1, m_scale, fi2s_rate, fi2s_rate/8, 1, 0);
|
||||
} else {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
I2S[i2s_num]->clkm_conf.clka_en = 0;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
I2S[i2s_num]->clkm_conf.clk_sel = 2;
|
||||
#endif
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_a = 63;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_b = clkmDecimals;
|
||||
I2S[i2s_num]->clkm_conf.clkm_div_num = clkmInteger;
|
||||
@ -507,6 +535,13 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
i2s_obj_t *p_i2s = (i2s_obj_t*) arg;
|
||||
uint8_t i2s_num = p_i2s->i2s_num;
|
||||
i2s_dev_t* i2s_reg = I2S[i2s_num];
|
||||
|
||||
typeof(i2s_reg->int_st) int_st_val = i2s_reg->int_st;
|
||||
if(int_st_val.val == 0) {
|
||||
//Avoid spurious interrupt
|
||||
return;
|
||||
}
|
||||
|
||||
i2s_event_t i2s_event;
|
||||
int dummy;
|
||||
|
||||
@ -514,8 +549,8 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
|
||||
lldesc_t *finish_desc;
|
||||
|
||||
if (i2s_reg->int_st.out_dscr_err || i2s_reg->int_st.in_dscr_err) {
|
||||
ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", i2s_reg->int_st.val);
|
||||
if (int_st_val.out_dscr_err || int_st_val.in_dscr_err) {
|
||||
ESP_EARLY_LOGE(I2S_TAG, "dma error, interrupt status: 0x%08x", int_st_val.val);
|
||||
if (p_i2s->i2s_queue) {
|
||||
i2s_event.type = I2S_EVENT_DMA_ERROR;
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->i2s_queue)) {
|
||||
@ -525,7 +560,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_reg->int_st.out_eof && p_i2s->tx) {
|
||||
if (int_st_val.out_eof && p_i2s->tx) {
|
||||
finish_desc = (lldesc_t*) i2s_reg->out_eof_des_addr;
|
||||
// All buffers are empty. This means we have an underflow on our hands.
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->tx->queue)) {
|
||||
@ -547,7 +582,7 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
if (i2s_reg->int_st.in_suc_eof && p_i2s->rx) {
|
||||
if (int_st_val.in_suc_eof && p_i2s->rx) {
|
||||
// All buffers are full. This means we have an overflow.
|
||||
finish_desc = (lldesc_t*) i2s_reg->in_eof_des_addr;
|
||||
if (xQueueIsQueueFullFromISR(p_i2s->rx->queue)) {
|
||||
@ -562,11 +597,11 @@ static void IRAM_ATTR i2s_intr_handler_default(void *arg)
|
||||
xQueueSendFromISR(p_i2s->i2s_queue, (void * )&i2s_event, &high_priority_task_awoken);
|
||||
}
|
||||
}
|
||||
i2s_reg->int_clr.val = int_st_val.val;
|
||||
|
||||
if (high_priority_task_awoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
i2s_reg->int_clr.val = I2S[i2s_num]->int_st.val;
|
||||
}
|
||||
|
||||
static esp_err_t i2s_destroy_dma_queue(i2s_port_t i2s_num, i2s_dma_t *dma)
|
||||
@ -784,72 +819,37 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin)
|
||||
//For TX unit, the input signal index should be I2SnO_xxx_IN_IDX
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_TX) {
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
bck_sig = I2S0O_BCK_OUT_IDX;
|
||||
ws_sig = I2S0O_WS_OUT_IDX;
|
||||
data_out_sig = I2S0O_DATA_OUT23_IDX;
|
||||
} else {
|
||||
bck_sig = I2S1O_BCK_OUT_IDX;
|
||||
ws_sig = I2S1O_WS_OUT_IDX;
|
||||
data_out_sig = I2S1O_DATA_OUT23_IDX;
|
||||
}
|
||||
bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig;
|
||||
ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig;
|
||||
data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig;
|
||||
} else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) {
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
bck_sig = I2S0O_BCK_IN_IDX;
|
||||
ws_sig = I2S0O_WS_IN_IDX;
|
||||
data_out_sig = I2S0O_DATA_OUT23_IDX;
|
||||
} else {
|
||||
bck_sig = I2S1O_BCK_IN_IDX;
|
||||
ws_sig = I2S1O_WS_IN_IDX;
|
||||
data_out_sig = I2S1O_DATA_OUT23_IDX;
|
||||
}
|
||||
bck_sig = i2s_periph_signal[i2s_num].o_bck_in_sig;
|
||||
ws_sig = i2s_periph_signal[i2s_num].o_ws_in_sig;
|
||||
data_out_sig = i2s_periph_signal[i2s_num].o_data_out_sig;
|
||||
}
|
||||
}
|
||||
//For RX unit, the output signal index should be I2SnI_xxx_OUT_IDX
|
||||
//For RX unit, the input signal index shuld be I2SnI_xxx_IN_IDX
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_RX) {
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
bck_sig = I2S0I_BCK_OUT_IDX;
|
||||
ws_sig = I2S0I_WS_OUT_IDX;
|
||||
data_in_sig = I2S0I_DATA_IN15_IDX;
|
||||
} else {
|
||||
bck_sig = I2S1I_BCK_OUT_IDX;
|
||||
ws_sig = I2S1I_WS_OUT_IDX;
|
||||
data_in_sig = I2S1I_DATA_IN15_IDX;
|
||||
}
|
||||
bck_sig = i2s_periph_signal[i2s_num].i_bck_out_sig;
|
||||
ws_sig = i2s_periph_signal[i2s_num].i_ws_out_sig;
|
||||
data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig;
|
||||
} else if (p_i2s_obj[i2s_num]->mode & I2S_MODE_SLAVE) {
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
bck_sig = I2S0I_BCK_IN_IDX;
|
||||
ws_sig = I2S0I_WS_IN_IDX;
|
||||
data_in_sig = I2S0I_DATA_IN15_IDX;
|
||||
} else {
|
||||
bck_sig = I2S1I_BCK_IN_IDX;
|
||||
ws_sig = I2S1I_WS_IN_IDX;
|
||||
data_in_sig = I2S1I_DATA_IN15_IDX;
|
||||
}
|
||||
bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig;
|
||||
ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig;
|
||||
data_in_sig = i2s_periph_signal[i2s_num].i_data_in_sig;
|
||||
}
|
||||
}
|
||||
//For "full-duplex + slave" mode, we should select RX signal index for ws and bck.
|
||||
//For "full-duplex + master" mode, we should select TX signal index for ws and bck.
|
||||
if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_SLAVE_MODE_MASK) == I2S_FULL_DUPLEX_SLAVE_MODE_MASK) {
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
bck_sig = I2S0I_BCK_IN_IDX;
|
||||
ws_sig = I2S0I_WS_IN_IDX;
|
||||
} else {
|
||||
bck_sig = I2S1I_BCK_IN_IDX;
|
||||
ws_sig = I2S1I_WS_IN_IDX;
|
||||
}
|
||||
bck_sig = i2s_periph_signal[i2s_num].i_bck_in_sig;
|
||||
ws_sig = i2s_periph_signal[i2s_num].i_ws_in_sig;
|
||||
} else if ((p_i2s_obj[i2s_num]->mode & I2S_FULL_DUPLEX_MASTER_MODE_MASK) == I2S_FULL_DUPLEX_MASTER_MODE_MASK) {
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
bck_sig = I2S0O_BCK_OUT_IDX;
|
||||
ws_sig = I2S0O_WS_OUT_IDX;
|
||||
} else {
|
||||
bck_sig = I2S1O_BCK_OUT_IDX;
|
||||
ws_sig = I2S1O_WS_OUT_IDX;
|
||||
bck_sig = i2s_periph_signal[i2s_num].o_bck_out_sig;
|
||||
ws_sig = i2s_periph_signal[i2s_num].o_ws_out_sig;
|
||||
}
|
||||
}
|
||||
|
||||
gpio_matrix_out_check(pin->data_out_num, data_out_sig, 0, 0);
|
||||
gpio_matrix_in_check(pin->data_in_num, data_in_sig, 0);
|
||||
if (p_i2s_obj[i2s_num]->mode & I2S_MODE_MASTER) {
|
||||
@ -871,12 +871,14 @@ esp_err_t i2s_set_sample_rates(i2s_port_t i2s_num, uint32_t rate)
|
||||
return i2s_set_clk(i2s_num, rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr)
|
||||
{
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S[i2s_num]->pdm_conf.rx_sinc_dsr_16_en = dsr;
|
||||
return i2s_set_clk(i2s_num, p_i2s_obj[i2s_num]->sample_rate, p_i2s_obj[i2s_num]->bits_per_sample, p_i2s_obj[i2s_num]->channel_num);
|
||||
}
|
||||
#endif
|
||||
|
||||
static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_config)
|
||||
{
|
||||
@ -884,7 +886,10 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
I2S_CHECK((i2s_config), "param null", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK(!((i2s_config->mode & I2S_MODE_ADC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S ADC built-in only support on I2S0", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK(!((i2s_config->mode & I2S_MODE_DAC_BUILT_IN) && (i2s_num != I2S_NUM_0)), "I2S DAC built-in only support on I2S0", ESP_ERR_INVALID_ARG);
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
I2S_CHECK(!((i2s_config->mode & I2S_MODE_PDM) && (i2s_num != I2S_NUM_0)), "I2S DAC PDM only support on I2S0", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
periph_module_enable(i2s_periph_signal[i2s_num].module);
|
||||
|
||||
if(i2s_config->mode & I2S_MODE_ADC_BUILT_IN) {
|
||||
//in ADC built-in mode, we need to call i2s_set_adc_mode to
|
||||
@ -966,6 +971,7 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
I2S[i2s_num]->conf2.camera_en = 0;
|
||||
}
|
||||
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
if (i2s_config->mode & I2S_MODE_PDM) {
|
||||
I2S[i2s_num]->fifo_conf.rx_fifo_mod_force_en = 1;
|
||||
I2S[i2s_num]->fifo_conf.tx_fifo_mod_force_en = 1;
|
||||
@ -984,6 +990,10 @@ static esp_err_t i2s_param_config(i2s_port_t i2s_num, const i2s_config_t *i2s_co
|
||||
I2S[i2s_num]->pdm_conf.rx_pdm_en = 0;
|
||||
I2S[i2s_num]->pdm_conf.tx_pdm_en = 0;
|
||||
}
|
||||
#else
|
||||
I2S[i2s_num]->pdm_conf.rx_pdm_en = 0;
|
||||
I2S[i2s_num]->pdm_conf.tx_pdm_en = 0;
|
||||
#endif
|
||||
if (i2s_config->communication_format & I2S_COMM_FORMAT_I2S) {
|
||||
I2S[i2s_num]->conf.tx_short_sync = 0;
|
||||
I2S[i2s_num]->conf.rx_short_sync = 0;
|
||||
@ -1092,13 +1102,7 @@ esp_err_t i2s_driver_install(i2s_port_t i2s_num, const i2s_config_t *i2s_config,
|
||||
#endif //CONFIG_PM_ENABLE
|
||||
|
||||
//To make sure hardware is enabled before any hardware register operations.
|
||||
if (i2s_num == I2S_NUM_1) {
|
||||
periph_module_reset(PERIPH_I2S1_MODULE);
|
||||
periph_module_enable(PERIPH_I2S1_MODULE);
|
||||
} else {
|
||||
periph_module_reset(PERIPH_I2S0_MODULE);
|
||||
periph_module_enable(PERIPH_I2S0_MODULE);
|
||||
}
|
||||
periph_module_enable(i2s_periph_signal[i2s_num].module);
|
||||
|
||||
//initial interrupt
|
||||
err = i2s_isr_register(i2s_num, i2s_config->intr_alloc_flags, i2s_intr_handler_default, p_i2s_obj[i2s_num], &p_i2s_obj[i2s_num]->i2s_isr_handle);
|
||||
@ -1171,12 +1175,8 @@ esp_err_t i2s_driver_uninstall(i2s_port_t i2s_num)
|
||||
|
||||
free(p_i2s_obj[i2s_num]);
|
||||
p_i2s_obj[i2s_num] = NULL;
|
||||
periph_module_disable(i2s_periph_signal[i2s_num].module);
|
||||
|
||||
if (i2s_num == I2S_NUM_0) {
|
||||
periph_module_disable(PERIPH_I2S0_MODULE);
|
||||
} else if (i2s_num == I2S_NUM_1) {
|
||||
periph_module_disable(PERIPH_I2S1_MODULE);
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -1251,14 +1251,14 @@ esp_err_t i2s_write_expand(i2s_port_t i2s_num, const void *src, size_t size, siz
|
||||
I2S_CHECK((i2s_num < I2S_NUM_MAX), "i2s_num error", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((size > 0), "size must greater than zero", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((aim_bits * size < I2S_MAX_BUFFER_SIZE), "size is too large", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((aim_bits >= src_bits), "aim_bits musn't less than src_bits", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((aim_bits >= src_bits), "aim_bits mustn't be less than src_bits", ESP_ERR_INVALID_ARG);
|
||||
I2S_CHECK((p_i2s_obj[i2s_num]->tx), "tx NULL", ESP_ERR_INVALID_ARG);
|
||||
if (src_bits < I2S_BITS_PER_SAMPLE_8BIT || aim_bits < I2S_BITS_PER_SAMPLE_8BIT) {
|
||||
ESP_LOGE(I2S_TAG,"bits musn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits);
|
||||
ESP_LOGE(I2S_TAG,"bits mustn't be less than 8, src_bits %d aim_bits %d", src_bits, aim_bits);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if (src_bits > I2S_BITS_PER_SAMPLE_32BIT || aim_bits > I2S_BITS_PER_SAMPLE_32BIT) {
|
||||
ESP_LOGE(I2S_TAG,"bits musn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits);
|
||||
ESP_LOGE(I2S_TAG,"bits mustn't be greater than 32, src_bits %d aim_bits %d", src_bits, aim_bits);
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
if ((src_bits == I2S_BITS_PER_SAMPLE_16BIT || src_bits == I2S_BITS_PER_SAMPLE_32BIT) && (size % 2 != 0)) {
|
||||
|
@ -53,28 +53,34 @@ typedef enum {
|
||||
#define ADC_WIDTH_12Bit ADC_WIDTH_BIT_12
|
||||
|
||||
typedef enum {
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 */
|
||||
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 */
|
||||
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 */
|
||||
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 */
|
||||
ADC1_CHANNEL_0 = 0, /*!< ADC1 channel 0 is GPIO36 (ESP32), GPIO1 (ESP32-S2) */
|
||||
ADC1_CHANNEL_1, /*!< ADC1 channel 1 is GPIO37 (ESP32), GPIO2 (ESP32-S2) */
|
||||
ADC1_CHANNEL_2, /*!< ADC1 channel 2 is GPIO38 (ESP32), GPIO3 (ESP32-S2) */
|
||||
ADC1_CHANNEL_3, /*!< ADC1 channel 3 is GPIO39 (ESP32), GPIO4 (ESP32-S2) */
|
||||
ADC1_CHANNEL_4, /*!< ADC1 channel 4 is GPIO32 (ESP32), GPIO5 (ESP32-S2) */
|
||||
ADC1_CHANNEL_5, /*!< ADC1 channel 5 is GPIO33 (ESP32), GPIO6 (ESP32-S2) */
|
||||
ADC1_CHANNEL_6, /*!< ADC1 channel 6 is GPIO34 (ESP32), GPIO7 (ESP32-S2) */
|
||||
ADC1_CHANNEL_7, /*!< ADC1 channel 7 is GPIO35 (ESP32), GPIO8 (ESP32-S2) */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
ADC1_CHANNEL_MAX,
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
ADC1_CHANNEL_8, /*!< ADC1 channel 6 is GPIO9 (ESP32-S2)*/
|
||||
ADC1_CHANNEL_9, /*!< ADC1 channel 7 is GPIO10 (ESP32-S2) */
|
||||
ADC1_CHANNEL_MAX,
|
||||
#endif
|
||||
} adc1_channel_t;
|
||||
|
||||
typedef enum {
|
||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 */
|
||||
ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO0 */
|
||||
ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO2 */
|
||||
ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO15 */
|
||||
ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO13 */
|
||||
ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO12 */
|
||||
ADC2_CHANNEL_6, /*!< ADC2 channel 6 is GPIO14 */
|
||||
ADC2_CHANNEL_7, /*!< ADC2 channel 7 is GPIO27 */
|
||||
ADC2_CHANNEL_8, /*!< ADC2 channel 8 is GPIO25 */
|
||||
ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 */
|
||||
ADC2_CHANNEL_0 = 0, /*!< ADC2 channel 0 is GPIO4 (ESP32), GPIO11 (ESP32-S2) */
|
||||
ADC2_CHANNEL_1, /*!< ADC2 channel 1 is GPIO0 (ESP32), GPIO12 (ESP32-S2) */
|
||||
ADC2_CHANNEL_2, /*!< ADC2 channel 2 is GPIO2 (ESP32), GPIO13 (ESP32-S2) */
|
||||
ADC2_CHANNEL_3, /*!< ADC2 channel 3 is GPIO15 (ESP32), GPIO14 (ESP32-S2) */
|
||||
ADC2_CHANNEL_4, /*!< ADC2 channel 4 is GPIO13 (ESP32), GPIO15 (ESP32-S2) */
|
||||
ADC2_CHANNEL_5, /*!< ADC2 channel 5 is GPIO12 (ESP32), GPIO16 (ESP32-S2) */
|
||||
ADC2_CHANNEL_6, /*!< ADC2 channel 6 is GPIO14 (ESP32), GPIO17 (ESP32-S2) */
|
||||
ADC2_CHANNEL_7, /*!< ADC2 channel 7 is GPIO27 (ESP32), GPIO18 (ESP32-S2) */
|
||||
ADC2_CHANNEL_8, /*!< ADC2 channel 8 is GPIO25 (ESP32), GPIO19 (ESP32-S2) */
|
||||
ADC2_CHANNEL_9, /*!< ADC2 channel 9 is GPIO26 (ESP32), GPIO20 (ESP32-S2) */
|
||||
ADC2_CHANNEL_MAX,
|
||||
} adc2_channel_t;
|
||||
|
||||
|
@ -24,8 +24,8 @@ extern "C" {
|
||||
#include "soc/dac_periph.h"
|
||||
|
||||
typedef enum {
|
||||
DAC_CHANNEL_1 = 1, /*!< DAC channel 1 is GPIO25 */
|
||||
DAC_CHANNEL_2, /*!< DAC channel 2 is GPIO26 */
|
||||
DAC_CHANNEL_1 = 1, /*!< DAC channel 1 is GPIO25 (ESP32), GPIO17 (ESP32-S2) */
|
||||
DAC_CHANNEL_2, /*!< DAC channel 2 is GPIO26 (ESP32), GPIO18 (ESP32-S2) */
|
||||
DAC_CHANNEL_MAX,
|
||||
} dac_channel_t;
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */
|
||||
#define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */
|
||||
#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected
|
||||
@ -76,6 +77,54 @@ extern "C" {
|
||||
#define GPIO_SEL_38 ((uint64_t)(((uint64_t)1)<<38)) /*!< Pin 38 selected */
|
||||
#define GPIO_SEL_39 ((uint64_t)(((uint64_t)1)<<39)) /*!< Pin 39 selected */
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define GPIO_SEL_0 (BIT(0)) /*!< Pin 0 selected */
|
||||
#define GPIO_SEL_1 (BIT(1)) /*!< Pin 1 selected */
|
||||
#define GPIO_SEL_2 (BIT(2)) /*!< Pin 2 selected */
|
||||
#define GPIO_SEL_3 (BIT(3)) /*!< Pin 3 selected */
|
||||
#define GPIO_SEL_4 (BIT(4)) /*!< Pin 4 selected */
|
||||
#define GPIO_SEL_5 (BIT(5)) /*!< Pin 5 selected */
|
||||
#define GPIO_SEL_6 (BIT(6)) /*!< Pin 6 selected */
|
||||
#define GPIO_SEL_7 (BIT(7)) /*!< Pin 7 selected */
|
||||
#define GPIO_SEL_8 (BIT(8)) /*!< Pin 8 selected */
|
||||
#define GPIO_SEL_9 (BIT(9)) /*!< Pin 9 selected */
|
||||
#define GPIO_SEL_10 (BIT(10)) /*!< Pin 10 selected */
|
||||
#define GPIO_SEL_11 (BIT(11)) /*!< Pin 11 selected */
|
||||
#define GPIO_SEL_12 (BIT(12)) /*!< Pin 12 selected */
|
||||
#define GPIO_SEL_13 (BIT(13)) /*!< Pin 13 selected */
|
||||
#define GPIO_SEL_14 (BIT(14)) /*!< Pin 14 selected */
|
||||
#define GPIO_SEL_15 (BIT(15)) /*!< Pin 15 selected */
|
||||
#define GPIO_SEL_16 (BIT(16)) /*!< Pin 16 selected */
|
||||
#define GPIO_SEL_17 (BIT(17)) /*!< Pin 17 selected */
|
||||
#define GPIO_SEL_18 (BIT(18)) /*!< Pin 18 selected */
|
||||
#define GPIO_SEL_19 (BIT(19)) /*!< Pin 19 selected */
|
||||
#define GPIO_SEL_20 (BIT(20)) /*!< Pin 20 selected */
|
||||
#define GPIO_SEL_21 (BIT(21)) /*!< Pin 21 selected */
|
||||
|
||||
#define GPIO_SEL_26 (BIT(26)) /*!< Pin 26 selected */
|
||||
#define GPIO_SEL_27 (BIT(27)) /*!< Pin 27 selected */
|
||||
#define GPIO_SEL_28 (BIT(28)) /*!< Pin 28 selected */
|
||||
#define GPIO_SEL_29 (BIT(29)) /*!< Pin 29 selected */
|
||||
#define GPIO_SEL_30 (BIT(30)) /*!< Pin 30 selected */
|
||||
#define GPIO_SEL_31 (BIT(31)) /*!< Pin 31 selected */
|
||||
#define GPIO_SEL_32 ((uint64_t)(((uint64_t)1)<<32)) /*!< Pin 32 selected */
|
||||
#define GPIO_SEL_33 ((uint64_t)(((uint64_t)1)<<33)) /*!< Pin 33 selected */
|
||||
#define GPIO_SEL_34 ((uint64_t)(((uint64_t)1)<<34)) /*!< Pin 34 selected */
|
||||
#define GPIO_SEL_35 ((uint64_t)(((uint64_t)1)<<35)) /*!< Pin 35 selected */
|
||||
#define GPIO_SEL_36 ((uint64_t)(((uint64_t)1)<<36)) /*!< Pin 36 selected */
|
||||
#define GPIO_SEL_37 ((uint64_t)(((uint64_t)1)<<37)) /*!< Pin 37 selected */
|
||||
#define GPIO_SEL_38 ((uint64_t)(((uint64_t)1)<<38)) /*!< Pin 38 selected */
|
||||
#define GPIO_SEL_39 ((uint64_t)(((uint64_t)1)<<39)) /*!< Pin 39 selected */
|
||||
#define GPIO_SEL_40 ((uint64_t)(((uint64_t)1)<<40)) /*!< Pin 40 selected */
|
||||
#define GPIO_SEL_41 ((uint64_t)(((uint64_t)1)<<41)) /*!< Pin 41 selected */
|
||||
#define GPIO_SEL_42 ((uint64_t)(((uint64_t)1)<<42)) /*!< Pin 42 selected */
|
||||
#define GPIO_SEL_43 ((uint64_t)(((uint64_t)1)<<43)) /*!< Pin 43 selected */
|
||||
#define GPIO_SEL_44 ((uint64_t)(((uint64_t)1)<<44)) /*!< Pin 44 selected */
|
||||
#define GPIO_SEL_45 ((uint64_t)(((uint64_t)1)<<45)) /*!< Pin 45 selected */
|
||||
#define GPIO_SEL_46 ((uint64_t)(((uint64_t)1)<<46)) /*!< Pin 46 selected */
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define GPIO_PIN_REG_0 IO_MUX_GPIO0_REG
|
||||
#define GPIO_PIN_REG_1 IO_MUX_GPIO1_REG
|
||||
#define GPIO_PIN_REG_2 IO_MUX_GPIO2_REG
|
||||
@ -111,12 +160,67 @@ extern "C" {
|
||||
#define GPIO_PIN_REG_37 IO_MUX_GPIO37_REG
|
||||
#define GPIO_PIN_REG_38 IO_MUX_GPIO38_REG
|
||||
#define GPIO_PIN_REG_39 IO_MUX_GPIO39_REG
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define GPIO_PIN_REG_0 IO_MUX_GPIO0_REG
|
||||
#define GPIO_PIN_REG_1 IO_MUX_GPIO1_REG
|
||||
#define GPIO_PIN_REG_2 IO_MUX_GPIO2_REG
|
||||
#define GPIO_PIN_REG_3 IO_MUX_GPIO3_REG
|
||||
#define GPIO_PIN_REG_4 IO_MUX_GPIO4_REG
|
||||
#define GPIO_PIN_REG_5 IO_MUX_GPIO5_REG
|
||||
#define GPIO_PIN_REG_6 IO_MUX_GPIO6_REG
|
||||
#define GPIO_PIN_REG_7 IO_MUX_GPIO7_REG
|
||||
#define GPIO_PIN_REG_8 IO_MUX_GPIO8_REG
|
||||
#define GPIO_PIN_REG_9 IO_MUX_GPIO9_REG
|
||||
#define GPIO_PIN_REG_10 IO_MUX_GPIO10_REG
|
||||
#define GPIO_PIN_REG_11 IO_MUX_GPIO11_REG
|
||||
#define GPIO_PIN_REG_12 IO_MUX_GPIO12_REG
|
||||
#define GPIO_PIN_REG_13 IO_MUX_GPIO13_REG
|
||||
#define GPIO_PIN_REG_14 IO_MUX_GPIO14_REG
|
||||
#define GPIO_PIN_REG_15 IO_MUX_GPIO15_REG
|
||||
#define GPIO_PIN_REG_16 IO_MUX_GPIO16_REG
|
||||
#define GPIO_PIN_REG_17 IO_MUX_GPIO17_REG
|
||||
#define GPIO_PIN_REG_18 IO_MUX_GPIO18_REG
|
||||
#define GPIO_PIN_REG_19 IO_MUX_GPIO19_REG
|
||||
#define GPIO_PIN_REG_20 IO_MUX_GPIO20_REG
|
||||
#define GPIO_PIN_REG_21 IO_MUX_GPIO21_REG
|
||||
#define GPIO_PIN_REG_22 IO_MUX_GPIO22_REG
|
||||
#define GPIO_PIN_REG_23 IO_MUX_GPIO23_REG
|
||||
#define GPIO_PIN_REG_24 IO_MUX_GPIO24_REG
|
||||
#define GPIO_PIN_REG_25 IO_MUX_GPIO25_REG
|
||||
#define GPIO_PIN_REG_26 IO_MUX_GPIO26_REG
|
||||
#define GPIO_PIN_REG_27 IO_MUX_GPIO27_REG
|
||||
#define GPIO_PIN_REG_28 IO_MUX_GPIO28_REG
|
||||
#define GPIO_PIN_REG_29 IO_MUX_GPIO29_REG
|
||||
#define GPIO_PIN_REG_30 IO_MUX_GPIO30_REG
|
||||
#define GPIO_PIN_REG_31 IO_MUX_GPIO31_REG
|
||||
#define GPIO_PIN_REG_32 IO_MUX_GPIO32_REG
|
||||
#define GPIO_PIN_REG_33 IO_MUX_GPIO33_REG
|
||||
#define GPIO_PIN_REG_34 IO_MUX_GPIO34_REG
|
||||
#define GPIO_PIN_REG_35 IO_MUX_GPIO35_REG
|
||||
#define GPIO_PIN_REG_36 IO_MUX_GPIO36_REG
|
||||
#define GPIO_PIN_REG_37 IO_MUX_GPIO37_REG
|
||||
#define GPIO_PIN_REG_38 IO_MUX_GPIO38_REG
|
||||
#define GPIO_PIN_REG_39 IO_MUX_GPIO39_REG
|
||||
#define GPIO_PIN_REG_40 IO_MUX_GPIO40_REG
|
||||
#define GPIO_PIN_REG_41 IO_MUX_GPIO41_REG
|
||||
#define GPIO_PIN_REG_42 IO_MUX_GPIO42_REG
|
||||
#define GPIO_PIN_REG_43 IO_MUX_GPIO43_REG
|
||||
#define GPIO_PIN_REG_44 IO_MUX_GPIO44_REG
|
||||
#define GPIO_PIN_REG_45 IO_MUX_GPIO45_REG
|
||||
#define GPIO_PIN_REG_46 IO_MUX_GPIO46_REG
|
||||
#define GPIO_PIN_REG_47 IO_MUX_GPIO47_REG
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define GPIO_APP_CPU_INTR_ENA (BIT(0))
|
||||
#define GPIO_APP_CPU_NMI_INTR_ENA (BIT(1))
|
||||
#define GPIO_PRO_CPU_INTR_ENA (BIT(2))
|
||||
#define GPIO_PRO_CPU_NMI_INTR_ENA (BIT(3))
|
||||
#define GPIO_SDIO_EXT_INTR_ENA (BIT(4))
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define GPIO_PRO_CPU_INTR_ENA (BIT(0))
|
||||
#define GPIO_PRO_CPU_NMI_INTR_ENA (BIT(1))
|
||||
#endif
|
||||
|
||||
#define GPIO_MODE_DEF_DISABLE (0)
|
||||
#define GPIO_MODE_DEF_INPUT (BIT0)
|
||||
@ -127,8 +231,13 @@ extern "C" {
|
||||
/** @endcond */
|
||||
|
||||
#define GPIO_IS_VALID_GPIO(gpio_num) ((gpio_num < GPIO_PIN_COUNT && GPIO_PIN_MUX_REG[gpio_num] != 0)) /*!< Check whether it is a valid GPIO number */
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 34)) /*!< Check whether it can be a valid GPIO number of output mode */
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) ((GPIO_IS_VALID_GPIO(gpio_num)) && (gpio_num < 46)) /*!< Check whether it can be a valid GPIO number of output mode */
|
||||
#endif
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
typedef enum {
|
||||
GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */
|
||||
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
|
||||
@ -177,6 +286,59 @@ typedef enum {
|
||||
/** @endcond */
|
||||
} gpio_num_t;
|
||||
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
typedef enum {
|
||||
GPIO_NUM_NC = -1, /*!< Use to signal not connected to S/W */
|
||||
GPIO_NUM_0 = 0, /*!< GPIO0, input and output */
|
||||
GPIO_NUM_1 = 1, /*!< GPIO1, input and output */
|
||||
GPIO_NUM_2 = 2, /*!< GPIO2, input and output */
|
||||
GPIO_NUM_3 = 3, /*!< GPIO3, input and output */
|
||||
GPIO_NUM_4 = 4, /*!< GPIO4, input and output */
|
||||
GPIO_NUM_5 = 5, /*!< GPIO5, input and output */
|
||||
GPIO_NUM_6 = 6, /*!< GPIO6, input and output */
|
||||
GPIO_NUM_7 = 7, /*!< GPIO7, input and output */
|
||||
GPIO_NUM_8 = 8, /*!< GPIO8, input and output */
|
||||
GPIO_NUM_9 = 9, /*!< GPIO9, input and output */
|
||||
GPIO_NUM_10 = 10, /*!< GPIO10, input and output */
|
||||
GPIO_NUM_11 = 11, /*!< GPIO11, input and output */
|
||||
GPIO_NUM_12 = 12, /*!< GPIO12, input and output */
|
||||
GPIO_NUM_13 = 13, /*!< GPIO13, input and output */
|
||||
GPIO_NUM_14 = 14, /*!< GPIO14, input and output */
|
||||
GPIO_NUM_15 = 15, /*!< GPIO15, input and output */
|
||||
GPIO_NUM_16 = 16, /*!< GPIO16, input and output */
|
||||
GPIO_NUM_17 = 17, /*!< GPIO17, input and output */
|
||||
GPIO_NUM_18 = 18, /*!< GPIO18, input and output */
|
||||
GPIO_NUM_19 = 19, /*!< GPIO19, input and output */
|
||||
GPIO_NUM_20 = 20, /*!< GPIO20, input and output */
|
||||
GPIO_NUM_21 = 21, /*!< GPIO21, input and output */
|
||||
/* Note: The missing IO is because it is used inside the chip. */
|
||||
GPIO_NUM_26 = 26, /*!< GPIO26, input and output */
|
||||
GPIO_NUM_27 = 27, /*!< GPIO27, input and output */
|
||||
GPIO_NUM_28 = 28, /*!< GPIO28, input and output */
|
||||
GPIO_NUM_29 = 29, /*!< GPIO29, input and output */
|
||||
GPIO_NUM_30 = 30, /*!< GPIO30, input and output */
|
||||
GPIO_NUM_31 = 31, /*!< GPIO31, input and output */
|
||||
GPIO_NUM_32 = 32, /*!< GPIO32, input and output */
|
||||
GPIO_NUM_33 = 33, /*!< GPIO33, input and output */
|
||||
GPIO_NUM_34 = 34, /*!< GPIO34, input and output */
|
||||
GPIO_NUM_35 = 35, /*!< GPIO35, input and output */
|
||||
GPIO_NUM_36 = 36, /*!< GPIO36, input and output */
|
||||
GPIO_NUM_37 = 37, /*!< GPIO37, input and output */
|
||||
GPIO_NUM_38 = 38, /*!< GPIO38, input and output */
|
||||
GPIO_NUM_39 = 39, /*!< GPIO39, input and output */
|
||||
GPIO_NUM_40 = 40, /*!< GPIO40, input and output */
|
||||
GPIO_NUM_41 = 41, /*!< GPIO41, input and output */
|
||||
GPIO_NUM_42 = 42, /*!< GPIO42, input and output */
|
||||
GPIO_NUM_43 = 43, /*!< GPIO43, input and output */
|
||||
GPIO_NUM_44 = 44, /*!< GPIO44, input and output */
|
||||
GPIO_NUM_45 = 45, /*!< GPIO45, input and output */
|
||||
GPIO_NUM_46 = 46, /*!< GPIO46, input mode only */
|
||||
GPIO_NUM_MAX = 47,
|
||||
/** @endcond */
|
||||
} gpio_num_t;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
GPIO_INTR_DISABLE = 0, /*!< Disable GPIO interrupt */
|
||||
GPIO_INTR_POSEDGE = 1, /*!< GPIO interrupt type : rising edge */
|
||||
@ -613,6 +775,20 @@ void gpio_iomux_in(uint32_t gpio_num, uint32_t signal_idx);
|
||||
*/
|
||||
void gpio_iomux_out(uint8_t gpio_num, int func, bool oen_inv);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
/**
|
||||
* @brief Force hold digital and rtc gpio pad.
|
||||
* @note GPIO force hold, whether the chip in sleep mode or wakeup mode.
|
||||
* */
|
||||
esp_err_t gpio_force_hold_all(void);
|
||||
|
||||
/**
|
||||
* @brief Force unhold digital and rtc gpio pad.
|
||||
* @note GPIO force unhold, whether the chip in sleep mode or wakeup mode.
|
||||
* */
|
||||
esp_err_t gpio_force_unhold_all(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -85,15 +85,15 @@ typedef struct{
|
||||
gpio_pullup_t sda_pullup_en; /*!< Internal GPIO pull mode for I2C sda signal*/
|
||||
gpio_num_t scl_io_num; /*!< GPIO number for I2C scl signal */
|
||||
gpio_pullup_t scl_pullup_en; /*!< Internal GPIO pull mode for I2C scl signal*/
|
||||
|
||||
//TODO: add ref tick configure
|
||||
union {
|
||||
struct {
|
||||
uint32_t clk_speed; /*!< I2C clock frequency for master mode, (no higher than 1MHz for now) */
|
||||
} master;
|
||||
} master; /*!< Configuration if the I2C peripheral is master */
|
||||
struct {
|
||||
uint8_t addr_10bit_en; /*!< I2C 10bit address mode enable for slave mode */
|
||||
uint16_t slave_addr; /*!< I2C address for slave mode */
|
||||
} slave;
|
||||
} slave; /*!< Configuration if the I2C peripheral is slave */
|
||||
|
||||
};
|
||||
}i2c_config_t;
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -101,7 +101,9 @@ typedef enum {
|
||||
*/
|
||||
typedef enum {
|
||||
I2S_NUM_0 = 0x0, /*!< I2S 0*/
|
||||
I2S_NUM_1 = 0x1, /*!< I2S 1*/
|
||||
#if SOC_I2S_PERIPH_NUM > 1
|
||||
I2S_NUM_1, /*!< I2S 1*/
|
||||
#endif
|
||||
I2S_NUM_MAX,
|
||||
} i2s_port_t;
|
||||
|
||||
@ -118,7 +120,9 @@ typedef enum {
|
||||
I2S_MODE_RX = 8,
|
||||
I2S_MODE_DAC_BUILT_IN = 16, /*!< Output I2S data to built-in DAC, no matter the data format is 16bit or 32 bit, the DAC module will only take the 8bits from MSB*/
|
||||
I2S_MODE_ADC_BUILT_IN = 32, /*!< Input I2S data from built-in ADC, each data can be 12-bit width at most*/
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
I2S_MODE_PDM = 64,
|
||||
#endif
|
||||
} i2s_mode_t;
|
||||
|
||||
|
||||
@ -187,6 +191,7 @@ typedef struct {
|
||||
int data_in_num; /*!< DATA in pin*/
|
||||
} i2s_pin_config_t;
|
||||
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
/**
|
||||
* @brief I2S PDM RX downsample mode
|
||||
*/
|
||||
@ -195,6 +200,7 @@ typedef enum {
|
||||
I2S_PDM_DSR_16S, /*!< downsampling number is 16 for PDM RX mode*/
|
||||
I2S_PDM_DSR_MAX,
|
||||
} i2s_pdm_dsr_t;
|
||||
#endif
|
||||
|
||||
typedef intr_handle_t i2s_isr_handle_t;
|
||||
/**
|
||||
@ -221,6 +227,7 @@ typedef intr_handle_t i2s_isr_handle_t;
|
||||
*/
|
||||
esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
|
||||
|
||||
#if SOC_I2S_SUPPORT_PDM
|
||||
/**
|
||||
* @brief Set PDM mode down-sample rate
|
||||
* In PDM RX mode, there would be 2 rounds of downsample process in hardware.
|
||||
@ -239,6 +246,7 @@ esp_err_t i2s_set_pin(i2s_port_t i2s_num, const i2s_pin_config_t *pin);
|
||||
* - ESP_ERR_NO_MEM Out of memory
|
||||
*/
|
||||
esp_err_t i2s_set_pdm_rx_down_sample(i2s_port_t i2s_num, i2s_pdm_dsr_t dsr);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Set I2S dac mode, I2S built-in DAC is disabled by default
|
||||
|
@ -30,7 +30,9 @@ extern "C" {
|
||||
#define LEDC_ERR_VAL (-1)
|
||||
|
||||
typedef enum {
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
LEDC_HIGH_SPEED_MODE = 0, /*!< LEDC high speed speed_mode */
|
||||
#endif
|
||||
LEDC_LOW_SPEED_MODE, /*!< LEDC low speed speed_mode */
|
||||
LEDC_SPEED_MODE_MAX, /*!< LEDC speed limit */
|
||||
} ledc_mode_t;
|
||||
@ -93,12 +95,14 @@ typedef enum {
|
||||
LEDC_TIMER_12_BIT, /*!< LEDC PWM duty resolution of 12 bits */
|
||||
LEDC_TIMER_13_BIT, /*!< LEDC PWM duty resolution of 13 bits */
|
||||
LEDC_TIMER_14_BIT, /*!< LEDC PWM duty resolution of 14 bits */
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
LEDC_TIMER_15_BIT, /*!< LEDC PWM duty resolution of 15 bits */
|
||||
LEDC_TIMER_16_BIT, /*!< LEDC PWM duty resolution of 16 bits */
|
||||
LEDC_TIMER_17_BIT, /*!< LEDC PWM duty resolution of 17 bits */
|
||||
LEDC_TIMER_18_BIT, /*!< LEDC PWM duty resolution of 18 bits */
|
||||
LEDC_TIMER_19_BIT, /*!< LEDC PWM duty resolution of 19 bits */
|
||||
LEDC_TIMER_20_BIT, /*!< LEDC PWM duty resolution of 20 bits */
|
||||
#endif
|
||||
LEDC_TIMER_BIT_MAX,
|
||||
} ledc_timer_bit_t;
|
||||
|
||||
@ -307,7 +311,6 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
* @param arg User-supplied argument passed to the handler function.
|
||||
* @param intr_alloc_flags Flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. See esp_intr_alloc.h for more info.
|
||||
* @param arg Parameter for handler function
|
||||
* @param handle Pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
|
@ -20,6 +20,11 @@
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifndef SOC_MCPWM_SUPPORTED
|
||||
#error MCPWM is not supported in this chip target
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -691,7 +696,6 @@ esp_err_t mcpwm_sync_disable(mcpwm_unit_t mcpwm_num, mcpwm_timer_t timer_num);
|
||||
* @param arg user-supplied argument passed to the handler function.
|
||||
* @param intr_alloc_flags flags used to allocate the interrupt. One or multiple (ORred)
|
||||
* ESP_INTR_FLAG_* values. see esp_intr_alloc.h for more info.
|
||||
* @param arg parameter for handler function
|
||||
* @param handle pointer to return handle. If non-NULL, a handle for the interrupt will
|
||||
* be returned here.
|
||||
*
|
||||
|
@ -47,10 +47,13 @@ typedef enum {
|
||||
PCNT_UNIT_1 = 1, /*!< PCNT unit 1 */
|
||||
PCNT_UNIT_2 = 2, /*!< PCNT unit 2 */
|
||||
PCNT_UNIT_3 = 3, /*!< PCNT unit 3 */
|
||||
//ESP32-S2 only have 4 unit
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
PCNT_UNIT_4 = 4, /*!< PCNT unit 4 */
|
||||
PCNT_UNIT_5 = 5, /*!< PCNT unit 5 */
|
||||
PCNT_UNIT_6 = 6, /*!< PCNT unit 6 */
|
||||
PCNT_UNIT_7 = 7, /*!< PCNT unit 7 */
|
||||
#endif
|
||||
PCNT_UNIT_MAX,
|
||||
} pcnt_unit_t;
|
||||
|
||||
@ -67,11 +70,11 @@ typedef enum {
|
||||
* @brief Selection of counter's events the may trigger an interrupt
|
||||
*/
|
||||
typedef enum {
|
||||
PCNT_EVT_L_LIM = 0, /*!< PCNT watch point event: Minimum counter value */
|
||||
PCNT_EVT_H_LIM = 1, /*!< PCNT watch point event: Maximum counter value */
|
||||
PCNT_EVT_THRES_0 = 2, /*!< PCNT watch point event: threshold0 value event */
|
||||
PCNT_EVT_THRES_1 = 3, /*!< PCNT watch point event: threshold1 value event */
|
||||
PCNT_EVT_ZERO = 4, /*!< PCNT watch point event: counter value zero event */
|
||||
PCNT_EVT_THRES_1 = BIT(2), /*!< PCNT watch point event: threshold1 value event */
|
||||
PCNT_EVT_THRES_0 = BIT(3), /*!< PCNT watch point event: threshold0 value event */
|
||||
PCNT_EVT_L_LIM = BIT(4), /*!< PCNT watch point event: Minimum counter value */
|
||||
PCNT_EVT_H_LIM = BIT(5), /*!< PCNT watch point event: Maximum counter value */
|
||||
PCNT_EVT_ZERO = BIT(6), /*!< PCNT watch point event: counter value zero event */
|
||||
PCNT_EVT_MAX
|
||||
} pcnt_evt_type_t;
|
||||
|
||||
|
@ -35,15 +35,18 @@ typedef enum {
|
||||
RMT_CHANNEL_1, /*!< RMT Channel 1 */
|
||||
RMT_CHANNEL_2, /*!< RMT Channel 2 */
|
||||
RMT_CHANNEL_3, /*!< RMT Channel 3 */
|
||||
//ESP32-S2 only have 4 channel
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
RMT_CHANNEL_4, /*!< RMT Channel 4 */
|
||||
RMT_CHANNEL_5, /*!< RMT Channel 5 */
|
||||
RMT_CHANNEL_6, /*!< RMT Channel 6 */
|
||||
RMT_CHANNEL_7, /*!< RMT Channel 7 */
|
||||
#endif
|
||||
RMT_CHANNEL_MAX
|
||||
} rmt_channel_t;
|
||||
|
||||
typedef enum {
|
||||
RMT_MEM_OWNER_TX = 0, /*!< RMT RX mode, RMT transmitter owns the memory block*/
|
||||
RMT_MEM_OWNER_TX = 0, /*!< RMT TX mode, RMT transmitter owns the memory block*/
|
||||
RMT_MEM_OWNER_RX = 1, /*!< RMT RX mode, RMT receiver owns the memory block*/
|
||||
RMT_MEM_OWNER_MAX,
|
||||
}rmt_mem_owner_t;
|
||||
|
@ -30,6 +30,13 @@ typedef enum {
|
||||
RTC_GPIO_MODE_DISABLED, /*!< Pad (output + input) disable */
|
||||
} rtc_gpio_mode_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
typedef enum {
|
||||
RTCIO_MODE_OUTPUT = 0, /*!< Pad output normal mode */
|
||||
RTCIO_MODE_OUTPUT_OD = 1, /*!< Pad output OD mode */
|
||||
} rtc_io_out_mode_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Determine if the specified GPIO is a valid RTC GPIO.
|
||||
*
|
||||
@ -38,8 +45,12 @@ typedef enum {
|
||||
*/
|
||||
inline static bool rtc_gpio_is_valid_gpio(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return gpio_num < GPIO_PIN_COUNT
|
||||
&& rtc_gpio_desc[gpio_num].reg != 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return (gpio_num < RTC_GPIO_NUMBER);
|
||||
#endif
|
||||
}
|
||||
|
||||
#define RTC_GPIO_IS_VALID_GPIO(gpio_num) rtc_gpio_is_valid_gpio(gpio_num) // Deprecated, use rtc_gpio_is_valid_gpio()
|
||||
@ -266,7 +277,71 @@ esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
*/
|
||||
esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
/**
|
||||
* @brief RTC IO set output mode
|
||||
* @param gpio_num Configure GPIO pins number
|
||||
* @param mode GPIO output mode
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
*
|
||||
*/
|
||||
esp_err_t rtc_gpio_set_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief RTC IO get output mode
|
||||
* @param gpio_num Configure GPIO pins number
|
||||
* @param mode GPIO output mode
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
*/
|
||||
esp_err_t rtc_gpio_get_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t *mode);
|
||||
|
||||
/**
|
||||
* @brief Set RTC IO status in deep sleep
|
||||
* In some application scenarios, IO needs to have another states during deep sleep.
|
||||
* @param gpio_num Configure GPIO pins number
|
||||
* @param input input mode. false: close; true: open;
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
*/
|
||||
esp_err_t rtc_gpio_sleep_input_enable(gpio_num_t gpio_num, bool input);
|
||||
|
||||
/**
|
||||
* @brief Set RTC IO status in deep sleep
|
||||
* In some application scenarios, IO needs to have another states during deep sleep.
|
||||
* @param gpio_num Configure GPIO pins number
|
||||
* @param output output mode. false: close; true: open;
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
*/
|
||||
esp_err_t rtc_gpio_sleep_output_enable(gpio_num_t gpio_num, bool output);
|
||||
|
||||
/**
|
||||
* @brief Close RTC IO status in deep sleep
|
||||
* In some application scenarios, IO needs to have another states during deep sleep.
|
||||
* @param gpio_num Configure GPIO pins number
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
*/
|
||||
esp_err_t rtc_gpio_sleep_mode_disable(gpio_num_t gpio_num);
|
||||
|
||||
/**
|
||||
* @brief Enable force hold signal for all RTC IOs
|
||||
*
|
||||
* Each RTC pad has a "force hold" input signal from the RTC controller.
|
||||
* If this signal is set, pad latches current values of input enable,
|
||||
* function, output enable, and other signals which come from the RTC mux.
|
||||
* Force hold signal is enabled before going into deep sleep for pins which
|
||||
* are used for EXT1 wakeup.
|
||||
*/
|
||||
esp_err_t rtc_gpio_force_hold_all(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -20,6 +20,12 @@
|
||||
#include "sdmmc_types.h"
|
||||
#include "driver/gpio.h"
|
||||
|
||||
#include "soc/soc_caps.h"
|
||||
|
||||
#ifndef SOC_SDMMC_HOST_SUPPORTED
|
||||
#error SDMMC host is not supported in this chip target
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
@ -20,7 +20,6 @@
|
||||
#include "sdmmc_types.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "esp_err.h"
|
||||
#include "esp32/rom/lldesc.h"
|
||||
#include "soc/lldesc.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "hal/spi_types.h"
|
||||
#include "sdkconfig.h"
|
||||
@ -138,7 +138,6 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
|
||||
*/
|
||||
esp_err_t spi_bus_free(spi_host_device_t host);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
@ -22,6 +22,7 @@
|
||||
/** SPI master clock is divided by 80MHz apb clock. Below defines are example frequencies, and are accurate. Be free to specify a random frequency, it will be rounded to closest frequency (to macros below if above 8MHz).
|
||||
* 8MHz
|
||||
*/
|
||||
#if APB_CLK_FREQ==80*1000*1000
|
||||
#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/10)
|
||||
#define SPI_MASTER_FREQ_9M (APB_CLK_FREQ/9) ///< 8.89MHz
|
||||
#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/8) ///< 10MHz
|
||||
@ -32,7 +33,14 @@
|
||||
#define SPI_MASTER_FREQ_26M (APB_CLK_FREQ/3) ///< 26.67MHz
|
||||
#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/2) ///< 40MHz
|
||||
#define SPI_MASTER_FREQ_80M (APB_CLK_FREQ/1) ///< 80MHz
|
||||
|
||||
#elif APB_CLK_FREQ==40*1000*1000
|
||||
#define SPI_MASTER_FREQ_7M (APB_CLK_FREQ/6) ///< 13.33MHz
|
||||
#define SPI_MASTER_FREQ_8M (APB_CLK_FREQ/5) ///< 16MHz
|
||||
#define SPI_MASTER_FREQ_10M (APB_CLK_FREQ/4) ///< 20MHz
|
||||
#define SPI_MASTER_FREQ_13M (APB_CLK_FREQ/3) ///< 26.67MHz
|
||||
#define SPI_MASTER_FREQ_20M (APB_CLK_FREQ/2) ///< 40MHz
|
||||
#define SPI_MASTER_FREQ_40M (APB_CLK_FREQ/1) ///< 80MHz
|
||||
#endif
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
@ -51,6 +59,7 @@ extern "C"
|
||||
* Set this flag to confirm that you're going to work with output only, or read without dummy bits at your own risk.
|
||||
*/
|
||||
#define SPI_DEVICE_NO_DUMMY (1<<6)
|
||||
#define SPI_DEVICE_DDRCLK (1<<7)
|
||||
|
||||
|
||||
typedef struct spi_transaction_t spi_transaction_t;
|
||||
@ -64,8 +73,8 @@ typedef struct {
|
||||
uint8_t address_bits; ///< Default amount of bits in address phase (0-64), used when ``SPI_TRANS_VARIABLE_ADDR`` is not used, otherwise ignored.
|
||||
uint8_t dummy_bits; ///< Amount of dummy bits to insert between address and data phase
|
||||
uint8_t mode; ///< SPI mode (0-3)
|
||||
uint8_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
|
||||
uint8_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
|
||||
uint16_t duty_cycle_pos; ///< Duty cycle of positive clock, in 1/256th increments (128 = 50%/50% duty). Setting this to 0 (=not setting it) is equivalent to setting this to 128.
|
||||
uint16_t cs_ena_pretrans; ///< Amount of SPI bit-cycles the cs should be activated before the transmission (0-16). This only works on half-duplex transactions.
|
||||
uint8_t cs_ena_posttrans; ///< Amount of SPI bit-cycles the cs should stay active after the transmission (0-16)
|
||||
int clock_speed_hz; ///< Clock speed, divisors of 80MHz, in Hz. See ``SPI_MASTER_FREQ_*``.
|
||||
int input_delay_ns; /**< Maximum data valid time of slave. The time required between SCLK and MISO
|
||||
@ -107,6 +116,7 @@ typedef struct {
|
||||
#define SPI_TRANS_VARIABLE_CMD (1<<5) ///< Use the ``command_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
|
||||
#define SPI_TRANS_VARIABLE_ADDR (1<<6) ///< Use the ``address_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
|
||||
#define SPI_TRANS_VARIABLE_DUMMY (1<<7) ///< Use the ``dummy_bits`` in ``spi_transaction_ext_t`` rather than default value in ``spi_device_interface_config_t``.
|
||||
#define SPI_TRANS_SET_CD (1<<7) ///< Set the CD pin
|
||||
|
||||
/**
|
||||
* This structure describes one SPI transaction. The descriptor should not be modified until the transaction finishes.
|
||||
|
@ -73,6 +73,16 @@ typedef enum {
|
||||
TIMER_AUTORELOAD_MAX,
|
||||
} timer_autoreload_t;
|
||||
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
/**
|
||||
* @brief Select timer source clock.
|
||||
*/
|
||||
typedef enum {
|
||||
TIMER_SRC_CLK_APB = 0, /*!< Select APB as the source clock*/
|
||||
TIMER_SRC_CLK_XTAL = 1, /*!< Select XTAL as the source clock*/
|
||||
} timer_src_clk_t;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Data structure with timer's configuration settings
|
||||
*/
|
||||
@ -83,6 +93,9 @@ typedef struct {
|
||||
timer_count_dir_t counter_dir; /*!< Counter direction */
|
||||
bool auto_reload; /*!< Timer auto-reload */
|
||||
uint32_t divider; /*!< Counter clock divider. The divider's range is from from 2 to 65536. */
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
timer_src_clk_t clk_sel; /*!< Use XTAL as source clock. */
|
||||
#endif
|
||||
} timer_config_t;
|
||||
|
||||
|
||||
|
@ -14,6 +14,7 @@
|
||||
|
||||
#ifndef _DRIVER_TOUCH_PAD_H_
|
||||
#define _DRIVER_TOUCH_PAD_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -21,6 +22,7 @@ extern "C" {
|
||||
#include "esp_intr_alloc.h"
|
||||
#include "soc/touch_periph.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
typedef enum {
|
||||
TOUCH_PAD_NUM0 = 0, /*!< Touch pad channel 0 is GPIO4 */
|
||||
TOUCH_PAD_NUM1, /*!< Touch pad channel 1 is GPIO0 */
|
||||
@ -34,6 +36,32 @@ typedef enum {
|
||||
TOUCH_PAD_NUM9, /*!< Touch pad channel 9 is GPIO32*/
|
||||
TOUCH_PAD_MAX,
|
||||
} touch_pad_t;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
typedef enum {
|
||||
TOUCH_PAD_NUM0 = 0, /*!< Internal channel, be used for denoise */
|
||||
#define TOUCH_DENOISE_CHANNEL TOUCH_PAD_NUM0 /*!< T0 is an internal channel that does not have a corresponding external GPIO.
|
||||
T0 will work simultaneously with the measured channel Tn. Finally, the actual
|
||||
measured value of Tn is the value after subtracting lower bits of T0. */
|
||||
TOUCH_PAD_NUM1, /*!< Touch channel 1 is GPIO1 */
|
||||
TOUCH_PAD_NUM2, /*!< Touch channel 2 is GPIO2 */
|
||||
TOUCH_PAD_NUM3, /*!< Touch channel 3 is GPIO3 */
|
||||
TOUCH_PAD_NUM4, /*!< Touch channel 4 is GPIO4 */
|
||||
TOUCH_PAD_NUM5, /*!< Touch channel 5 is GPIO5 */
|
||||
TOUCH_PAD_NUM6, /*!< Touch channel 6 is GPIO6 */
|
||||
TOUCH_PAD_NUM7, /*!< Touch channel 7 is GPIO7 */
|
||||
TOUCH_PAD_NUM8, /*!< Touch channel 8 is GPIO8 */
|
||||
TOUCH_PAD_NUM9, /*!< Touch channel 9 is GPIO9 */
|
||||
TOUCH_PAD_NUM10, /*!< Touch channel 9 is GPIO10 */
|
||||
TOUCH_PAD_NUM11, /*!< Touch channel 9 is GPIO11 */
|
||||
TOUCH_PAD_NUM12, /*!< Touch channel 9 is GPIO12 */
|
||||
TOUCH_PAD_NUM13, /*!< Touch channel 9 is GPIO13 */
|
||||
TOUCH_PAD_NUM14, /*!< Touch channel 9 is GPIO14 */
|
||||
#define TOUCH_SHIELD_CHANNEL TOUCH_PAD_NUM14 /*!< The waterproof function includes a shielded channel (TOUCH_PAD_NUM14)
|
||||
The shielded channel outputs the same signal as the channel being measured.
|
||||
It is generally designed as a grid and is placed around the touch buttons. */
|
||||
TOUCH_PAD_MAX,
|
||||
} touch_pad_t;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TOUCH_HVOLT_KEEP = -1, /*!<Touch sensor high reference voltage, no change */
|
||||
@ -74,6 +102,7 @@ typedef enum {
|
||||
TOUCH_PAD_SLOPE_MAX,
|
||||
} touch_cnt_slope_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
typedef enum {
|
||||
TOUCH_TRIGGER_BELOW = 0, /*!<Touch interrupt will happen if counter value is less than threshold.*/
|
||||
TOUCH_TRIGGER_ABOVE = 1, /*!<Touch interrupt will happen if counter value is larger than threshold.*/
|
||||
@ -85,6 +114,7 @@ typedef enum {
|
||||
TOUCH_TRIGGER_SOURCE_SET1 = 1, /*!< wakeup interrupt is generated if SET1 is "touched"*/
|
||||
TOUCH_TRIGGER_SOURCE_MAX,
|
||||
} touch_trigger_src_t;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_TIE_OPT_LOW = 0, /*!<Initial level of charging voltage, low level */
|
||||
@ -98,9 +128,130 @@ typedef enum {
|
||||
TOUCH_FSM_MODE_MAX,
|
||||
} touch_fsm_mode_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
typedef enum {
|
||||
TOUCH_PAD_INTR_DONE = 0, /*!<Each enabled channel measure done */
|
||||
TOUCH_PAD_INTR_ACTIVE = 1, /*!<Each enabled channel be touched */
|
||||
TOUCH_PAD_INTR_INACTIVE = 2,/*!<Each enabled channel be released */
|
||||
TOUCH_PAD_INTR_ALL, /*!<All touch interrupt measure done & touched & released */
|
||||
TOUCH_PAD_INTR_MAX
|
||||
} touch_pad_intr_type_t;
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_INTR_MASK_DONE = BIT(0), /*!<Each enabled channel measure done */
|
||||
TOUCH_PAD_INTR_MASK_ACTIVE = BIT(1), /*!<Each enabled channel be touched */
|
||||
TOUCH_PAD_INTR_MASK_INACTIVE = BIT(2), /*!<Each enabled channel be released */
|
||||
TOUCH_PAD_INTR_MASK_ALL = BIT(2)|BIT(1)|BIT(0), /*!<All touch interrupt measure done & touched & released */
|
||||
TOUCH_PAD_INTR_MASK_MAX
|
||||
} touch_pad_intr_mask_t;
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_DENOISE_BIT12 = 0, /*!<Denoise range is 12bit */
|
||||
TOUCH_PAD_DENOISE_BIT10 = 1, /*!<Denoise range is 10bit */
|
||||
TOUCH_PAD_DENOISE_BIT8 = 2, /*!<Denoise range is 8bit */
|
||||
TOUCH_PAD_DENOISE_BIT4 = 3, /*!<Denoise range is 4bit */
|
||||
TOUCH_PAD_DENOISE_MAX
|
||||
} touch_pad_denoise_grade_t;
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_DENOISE_CAP_L0 = 0, /*!<Denoise channel internal reference capacitance is 0pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L1 = 4, /*!<Denoise channel internal reference capacitance is 1.4pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L2 = 2, /*!<Denoise channel internal reference capacitance is 2.8pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L3 = 6, /*!<Denoise channel internal reference capacitance is 4.2pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L4 = 1, /*!<Denoise channel internal reference capacitance is 5.6pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L5 = 5, /*!<Denoise channel internal reference capacitance is 7.0pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L6 = 3, /*!<Denoise channel internal reference capacitance is 8.4pf */
|
||||
TOUCH_PAD_DENOISE_CAP_L7 = 7, /*!<Denoise channel internal reference capacitance is 9.8pf */
|
||||
TOUCH_PAD_DENOISE_CAP_MAX
|
||||
} touch_pad_denoise_cap_t;
|
||||
|
||||
typedef struct touch_pad_denoise {
|
||||
touch_pad_denoise_grade_t grade; /*!<Select denoise channel denoise range.
|
||||
Determined by measuring the noise amplitude of the denoise channel. */
|
||||
touch_pad_denoise_cap_t cap_level; /*!<Select denoise channel internal reference capacitance.
|
||||
Select the appropriate internal reference capacitance value so that
|
||||
the reading of denoise channel is closest to the reading of the channel being measured. */
|
||||
} touch_pad_denoise_t;
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_SHIELD_DRV_L0 = 0,/*!<The max equivalent capacitance in shield channel is 40pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L1, /*!<The max equivalent capacitance in shield channel is 80pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L2, /*!<The max equivalent capacitance in shield channel is 120pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L3, /*!<The max equivalent capacitance in shield channel is 160pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L4, /*!<The max equivalent capacitance in shield channel is 200pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L5, /*!<The max equivalent capacitance in shield channel is 240pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L6, /*!<The max equivalent capacitance in shield channel is 280pf */
|
||||
TOUCH_PAD_SHIELD_DRV_L7, /*!<The max equivalent capacitance in shield channel is 320pf */
|
||||
TOUCH_PAD_SHIELD_DRV_MAX
|
||||
} touch_pad_shield_driver_t;
|
||||
|
||||
typedef struct touch_pad_waterproof {
|
||||
touch_pad_t guard_ring_pad; /*!<Waterproof. Select touch channel use for guard pad */
|
||||
touch_pad_shield_driver_t shield_driver;/*!<Waterproof. Select max equivalent capacitance for sheild pad
|
||||
Config the Touch14 to the touch sensor and compare the measured
|
||||
reading to the Touch0 reading to estimate the equivalent capacitance.*/
|
||||
} touch_pad_waterproof_t;
|
||||
|
||||
typedef struct touch_pad_proximity {
|
||||
touch_pad_t select_pad0; /*!<Select touch channel use for proximity pad1
|
||||
If clear the proximity channel, point this pad to `TOUCH_PAD_NUM0` */
|
||||
touch_pad_t select_pad1; /*!<Select touch channel use for proximity pad1 */
|
||||
touch_pad_t select_pad2; /*!<Select touch channel use for proximity pad1 */
|
||||
uint8_t meas_num; /*!<Set cumulative number of measurements for proximity pad */
|
||||
} touch_pad_proximity_t;
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_CONN_HIGHZ = 0, /*!<Idel status of touch channel is high resistance state */
|
||||
TOUCH_PAD_CONN_GND = 1, /*!<Idel status of touch channel is ground connection */
|
||||
TOUCH_PAD_CONN_MAX
|
||||
} touch_pad_conn_type_t;
|
||||
|
||||
typedef enum {
|
||||
TOUCH_PAD_FILTER_IIR_2 = 0, /*!<The filter mode is first-order IIR filter. The coefficient is 2 */
|
||||
TOUCH_PAD_FILTER_IIR_4, /*!<The filter mode is first-order IIR filter. The coefficient is 4 */
|
||||
TOUCH_PAD_FILTER_IIR_8, /*!<The filter mode is first-order IIR filter. The coefficient is 8 */
|
||||
TOUCH_PAD_FILTER_JITTER, /*!<The filter mode is jitter filter */
|
||||
TOUCH_PAD_FILTER_MAX
|
||||
} touch_filter_mode_t;
|
||||
|
||||
typedef struct touch_filter_config {
|
||||
touch_filter_mode_t mode; /*!<Set filter mode. The filtered value is baseline
|
||||
The baseline is an important parameter of the touch algorithm */
|
||||
uint8_t debounce_cnt; /*!<Set debounce count is n. If the measured values continue to exceed
|
||||
the threshold for n times, it is determined that the touch sensor state changes.
|
||||
Range: 0 ~ 7 */
|
||||
uint8_t hysteresis_thr; /*!<Hysteresis threshold coefficient. hysteresis = hysteresis_thr * touch threshold.
|
||||
If (raw data - baseline) > (touch threshold + hysteresis), the touch channel be touched.
|
||||
If (raw data - baseline) < (touch threshold - hysteresis), the touch channel be released.
|
||||
Range: 0 ~ 3. The coefficient is 0: 1/8; 1: 3/32; 2: 1/16; 3: 1/32 */
|
||||
uint8_t noise_thr; /*!<Noise threshold coefficient. noise = noise_thr * touch threshold.
|
||||
If (raw data - baseline) > (noise), the baseline stop updating.
|
||||
If (raw data - baseline) < (noise), the baseline start updating.
|
||||
Range: 0 ~ 3. The coefficient is 0: 1/2; 1: 3/8; 2: 1/4; 3: 1/8; */
|
||||
uint8_t noise_neg_thr; /*!<Negative noise threshold coefficient. negative noise = noise_neg_thr * touch threshold.
|
||||
If (raw data - baseline) > (- negative noise), the baseline start updating.
|
||||
If (raw data - baseline) < (- negative noise), the baseline stop updating.
|
||||
Range: 0 ~ 3. The coefficient is 0: 1/2; 1: 3/8; 2: 1/4; 3: 1/8; */
|
||||
uint8_t neg_noise_limit; /*!<Set negative noise limit count is n. If the measured values continue to exceed
|
||||
the negative noise threshold for n times, it is determined that the baseline reset to raw data.
|
||||
Range: 0 ~ 15 */
|
||||
uint8_t jitter_step; /*!<Set jitter filter step size. Range: 0 ~ 15 */
|
||||
} touch_filter_config_t;
|
||||
|
||||
typedef struct {
|
||||
touch_pad_t touch_num; /*!<touch pad index */
|
||||
uint32_t sleep_pad_threshold; /*!<threshold in sleep mode */
|
||||
bool en_proximity; /*!<enable proximity function for sleep pad */
|
||||
} touch_pad_sleep_channel_t;
|
||||
|
||||
#define TOUCH_PAD_THRESHOLD_MAX 0x1FFFFF /*!<If set touch threshold max value, The touch sensor can't be in touched status */
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
|
||||
typedef intr_handle_t touch_isr_handle_t;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
#define TOUCH_PAD_SLEEP_CYCLE_DEFAULT (0x1000) /*!<The timer frequency is RTC_SLOW_CLK (can be 150k or 32k depending on the options), max value is 0xffff */
|
||||
#define TOUCH_PAD_MEASURE_CYCLE_DEFAULT (0x7fff) /*!<The timer frequency is 8Mhz, the max value is 0x7fff */
|
||||
#define TOUCH_PAD_MEASURE_WAIT_DEFAULT (0xFF) /*!<The timer frequency is 8Mhz, the max value is 0xff */
|
||||
@ -109,13 +260,24 @@ typedef intr_handle_t touch_isr_handle_t;
|
||||
#define TOUCH_TRIGGER_SOURCE_DEFAULT (TOUCH_TRIGGER_SOURCE_SET1) /*!<The wakeup trigger source can be SET1 or both SET1 and SET2 */
|
||||
#define TOUCH_PAD_BIT_MASK_MAX (0x3ff)
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
|
||||
#define TOUCH_PAD_SLEEP_CYCLE_DEFAULT (0xf) /*!<The number of sleep cycle in each measure process of touch channels.
|
||||
The timer frequency is RTC_SLOW_CLK (can be 150k or 32k depending on the options).
|
||||
Range: 0 ~ 0xffff */
|
||||
#define TOUCH_PAD_MEASURE_CYCLE_DEFAULT (300) /*!<The times of charge and discharge in each measure process of touch channels.
|
||||
The timer frequency is 8Mhz.
|
||||
Range: 0 ~ 0xffff */
|
||||
#define TOUCH_PAD_BIT_MASK_MAX (0x7fff)/*! 15 Touch channels */
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
/**
|
||||
* @brief Initialize touch module.
|
||||
* @note The default FSM mode is 'TOUCH_FSM_MODE_SW'. If you want to use interrupt trigger mode,
|
||||
* then set it using function 'touch_pad_set_fsm_mode' to 'TOUCH_FSM_MODE_TIMER' after calling 'touch_pad_init'.
|
||||
* @note If default parameter don't match the usage scenario, it can be changed after this function.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Touch pad init error
|
||||
* - ESP_ERR_NO_MEM Touch pad init error
|
||||
*/
|
||||
esp_err_t touch_pad_init(void);
|
||||
|
||||
@ -128,6 +290,53 @@ esp_err_t touch_pad_init(void);
|
||||
*/
|
||||
esp_err_t touch_pad_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Deregister the handler previously registered using touch_pad_isr_handler_register
|
||||
* @param fn handler function to call (as passed to touch_pad_isr_handler_register)
|
||||
* @param arg argument of the handler (as passed to touch_pad_isr_handler_register)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if a handler matching both fn and
|
||||
* arg isn't registered
|
||||
*/
|
||||
esp_err_t touch_pad_isr_deregister(void(*fn)(void *), void *arg);
|
||||
|
||||
/**
|
||||
* @brief Get the touch pad which caused wakeup from sleep
|
||||
* @param pad_num pointer to touch pad which caused wakeup
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num);
|
||||
|
||||
/**
|
||||
* @brief Get the touch sensor status, usually used in ISR to decide which pads are 'touched'.
|
||||
* @return
|
||||
* - touch status
|
||||
*/
|
||||
uint32_t touch_pad_get_status(void);
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor FSM mode, the test action can be triggered by the timer,
|
||||
* as well as by the software.
|
||||
* @param mode FSM mode
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if argument is wrong
|
||||
*/
|
||||
esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get touch sensor FSM mode
|
||||
* @param mode pointer to accept FSM mode
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
|
||||
/**
|
||||
* @brief Configure touch pad interrupt threshold.
|
||||
*
|
||||
@ -233,17 +442,6 @@ esp_err_t touch_pad_set_filter_read_cb(filter_cb_t read_cb);
|
||||
*/
|
||||
esp_err_t touch_pad_isr_register(intr_handler_t fn, void* arg);
|
||||
|
||||
/**
|
||||
* @brief Deregister the handler previously registered using touch_pad_isr_handler_register
|
||||
* @param fn handler function to call (as passed to touch_pad_isr_handler_register)
|
||||
* @param arg argument of the handler (as passed to touch_pad_isr_handler_register)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_STATE if a handler matching both fn and
|
||||
* arg isn't registered
|
||||
*/
|
||||
esp_err_t touch_pad_isr_deregister(void(*fn)(void *), void *arg);
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor measurement and sleep time
|
||||
* @param sleep_cycle The touch sensor will sleep after each measurement.
|
||||
@ -326,24 +524,6 @@ esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope
|
||||
*/
|
||||
esp_err_t touch_pad_io_init(touch_pad_t touch_num);
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor FSM mode, the test action can be triggered by the timer,
|
||||
* as well as by the software.
|
||||
* @param mode FSM mode
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if argument is wrong
|
||||
*/
|
||||
esp_err_t touch_pad_set_fsm_mode(touch_fsm_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Get touch sensor FSM mode
|
||||
* @param mode pointer to accept FSM mode
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_fsm_mode(touch_fsm_mode_t *mode);
|
||||
|
||||
/**
|
||||
* @brief Trigger a touch sensor measurement, only support in SW mode of FSM
|
||||
* @return
|
||||
@ -455,13 +635,6 @@ esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uin
|
||||
*/
|
||||
esp_err_t touch_pad_clear_status(void);
|
||||
|
||||
/**
|
||||
* @brief Get the touch sensor status, usually used in ISR to decide which pads are 'touched'.
|
||||
* @return
|
||||
* - touch status
|
||||
*/
|
||||
uint32_t touch_pad_get_status(void);
|
||||
|
||||
/**
|
||||
* @brief To enable touch pad interrupt
|
||||
* @return
|
||||
@ -535,14 +708,449 @@ esp_err_t touch_pad_filter_stop(void);
|
||||
*/
|
||||
esp_err_t touch_pad_filter_delete(void);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
|
||||
/**
|
||||
* @brief Get the touch pad which caused wakeup from sleep
|
||||
* @param pad_num pointer to touch pad which caused wakeup
|
||||
* @brief Set touch sensor FSM start
|
||||
* @note Start FSM after the touch sensor FSM mode is set.
|
||||
* @note Call this function will reset beseline of all touch channels.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_fsm_start(void);
|
||||
|
||||
/**
|
||||
* @brief Stop touch sensor FSM.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_fsm_stop(void);
|
||||
|
||||
/**
|
||||
* @brief Set touch sensor measurement and sleep time
|
||||
* @param sleep_cycle The touch sensor will sleep after each measurement.
|
||||
* sleep_cycle decide the interval between each measurement.
|
||||
* t_sleep = sleep_cycle / (RTC_SLOW_CLK frequency).
|
||||
* The approximate frequency value of RTC_SLOW_CLK can be obtained using rtc_clk_slow_freq_get_hz function.
|
||||
* @param meas_timers The times of charge and discharge in each measure process of touch channels.
|
||||
* The timer frequency is 8Mhz. Range: 0 ~ 0xffff.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_times);
|
||||
|
||||
/**
|
||||
* @brief Get touch sensor measurement and sleep time
|
||||
* @param sleep_cycle Pointer to accept sleep cycle number
|
||||
* @param meas_times Pointer to accept measurement times count.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_times);
|
||||
|
||||
/**
|
||||
* @brief Set idel status of touch channel. The measurement of each touch channel is not in same time,
|
||||
* So, The value of touch channel can be effected by other's inactive status.
|
||||
* The high resistance setting increases the sensitivity of adjacent touch channels.
|
||||
* The grounding setting increases the stability of adjacent touch channels.
|
||||
* @param type Select connect to high resistance state or ground.
|
||||
* Default: TOUCH_PAD_CONN_GND.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_inactive_connect(touch_pad_conn_type_t type);
|
||||
|
||||
/**
|
||||
* @brief Get idel status of touch channel. The measurement of each touch channel is not in same time,
|
||||
* So, The value of touch channel can be effected by other's inactive status.
|
||||
* The high resistance setting increases the sensitivity of adjacent touch channels.
|
||||
* The grounding setting increases the stability of adjacent touch channels.
|
||||
* @param type Pointer to connection type.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_inactive_connect(touch_pad_conn_type_t *type);
|
||||
|
||||
/**
|
||||
* @brief Set the trigger threshold of touch sensor.
|
||||
* The threshold determines the sensitivity of the touch sensor.
|
||||
* threshold < (touched raw data - released raw data).
|
||||
* @note If set "TOUCH_PAD_THRESHOLD_MAX", the touch is never be trigered.
|
||||
* @param touch_num touch pad index
|
||||
* @param threshold threshold of touch sensor. Should be less than the max change value of touch.
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint32_t threshold);
|
||||
|
||||
/**
|
||||
* @brief Get touch sensor trigger threshold
|
||||
* @param touch_num touch pad index
|
||||
* @param threshold pointer to accept threshold
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
* - ESP_ERR_INVALID_ARG if argument is wrong
|
||||
*/
|
||||
esp_err_t touch_pad_get_thresh(touch_pad_t touch_num, uint32_t *threshold);
|
||||
|
||||
/**
|
||||
* @brief Register touch channel into touch sensor scan group.
|
||||
* The working mode of the touch sensor is cyclically scanned.
|
||||
* This function will set the scan bits according to the given bitmask.
|
||||
* @note If set this mask, the FSM timer should be stop firsty.
|
||||
* @note The touch sensor that in scan map, should be deinit GPIO function firstly by `touch_pad_io_init`.
|
||||
* @param enable_mask bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_set_group_mask(uint16_t enable_mask);
|
||||
|
||||
/**
|
||||
* @brief Get the touch sensor scan group bit mask.
|
||||
* @param enable_mask Pointer to bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_get_group_mask(uint16_t *enable_mask);
|
||||
|
||||
/**
|
||||
* @brief Clear touch channel from touch sensor scan group.
|
||||
* The working mode of the touch sensor is cyclically scanned.
|
||||
* This function will clear the scan bits according to the given bitmask.
|
||||
* @note If clear all mask, the FSM timer should be stop firsty.
|
||||
* @param enable_mask bitmask of touch sensor scan group.
|
||||
* e.g. TOUCH_PAD_NUM14 -> BIT(14)
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_clear_group_mask(uint16_t enable_mask);
|
||||
|
||||
/**
|
||||
* @brief Configure parameter for each touch channel.
|
||||
* @note Touch num 0 is denoise channel, please use `touch_pad_denoise_enable` to set denoise function
|
||||
* @param touch_num touch pad index
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL get status err
|
||||
* - ESP_ERR_INVALID_ARG if argument wrong
|
||||
* - ESP_FAIL if touch pad not initialized
|
||||
*/
|
||||
esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num);
|
||||
esp_err_t touch_pad_config(touch_pad_t touch_num);
|
||||
|
||||
/**
|
||||
* @brief Reset the whole of touch module.
|
||||
* @note Call this funtion after `touch_pad_fsm_stop`,
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_reset(void);
|
||||
|
||||
/**
|
||||
* @brief Check touch sensor measurement status.
|
||||
* If doing measurement, the flag will be clear.
|
||||
* If finish measurement. the flag will be set.
|
||||
* @return
|
||||
* - TRUE finish measurement
|
||||
* - FALSE doing measurement
|
||||
*/
|
||||
bool touch_pad_meas_is_done(void);
|
||||
|
||||
/**
|
||||
* @brief Get the current scan channel.
|
||||
* usually used in ISR to decide channel scaning, and then, get the current measurement value.
|
||||
* The role of each bit is reference to type `touch_pad_intr_mask_t`.
|
||||
* @return
|
||||
* - touch channel number
|
||||
*/
|
||||
touch_pad_t touch_pad_get_scan_curr(void);
|
||||
|
||||
/**
|
||||
* @brief Get the touch sensor interrupt status mask. usually used in ISR to decide interrupt type.
|
||||
* The role of each bit is reference to type `touch_pad_intr_mask_t`.
|
||||
* @return
|
||||
* - touch intrrupt bit
|
||||
*/
|
||||
uint32_t touch_pad_intr_status_get_mask(void);
|
||||
|
||||
/**
|
||||
* @brief Enable touch sensor interrupt.
|
||||
* @param type interrupt type
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_intr_enable(touch_pad_intr_mask_t int_mask);
|
||||
|
||||
/**
|
||||
* @brief Disable touch sensor interrupt.
|
||||
* @param type interrupt type
|
||||
* @return
|
||||
* - ESP_OK on success
|
||||
*/
|
||||
esp_err_t touch_pad_intr_disable(touch_pad_intr_mask_t int_mask);
|
||||
|
||||
/**
|
||||
* @brief Register touch-pad ISR.
|
||||
* The handler will be attached to the same CPU core that this function is running on.
|
||||
* @param fn Pointer to ISR handler
|
||||
* @param arg Parameter for ISR
|
||||
* @return
|
||||
* - ESP_OK Success ;
|
||||
* - ESP_ERR_INVALID_ARG GPIO error
|
||||
* - ESP_ERR_NO_MEM No memory
|
||||
*/
|
||||
esp_err_t touch_pad_isr_register(intr_handler_t fn, void* arg, touch_pad_intr_mask_t intr_mask);
|
||||
|
||||
/**
|
||||
* @brief get raw data of touch sensor.
|
||||
* @note After the initialization is complete, the "raw_data" is max value. You need to wait for a measurement
|
||||
* cycle before you can read the correct touch value.
|
||||
* @param touch_num touch pad index
|
||||
* @param raw_data pointer to accept touch sensor value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Touch channel 0 havent this parameter.
|
||||
*/
|
||||
|
||||
esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint32_t *raw_data);
|
||||
|
||||
/**
|
||||
* @brief get baseline of touch sensor.
|
||||
* @note After the initialization is complete, the "touch_value" is max value. You need to wait for a measurement
|
||||
* cycle before you can read the correct touch value.
|
||||
* @param touch_num touch pad index
|
||||
* @param touch_value pointer to accept touch sensor value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Touch channel 0 havent this parameter.
|
||||
*/
|
||||
esp_err_t touch_pad_filter_baseline_read(touch_pad_t touch_num, uint32_t *basedata);
|
||||
|
||||
/**
|
||||
* @brief Reset baseline to raw data of touch sensor.
|
||||
* @param touch_num touch pad index
|
||||
* - TOUCH_PAD_MAX Reset basaline of all channels
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_baseline_reset(touch_pad_t touch_num);
|
||||
|
||||
/**
|
||||
* @brief get debounce count of touch sensor.
|
||||
* @param touch_num touch pad index
|
||||
* @param debounce pointer to debounce value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG Touch channel 0 havent this parameter.
|
||||
*/
|
||||
esp_err_t touch_pad_filter_debounce_read(touch_pad_t touch_num, uint32_t *debounce);
|
||||
|
||||
/**
|
||||
* @brief set parameter of touch sensor filter and detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @param filter_info select filter type and threshold of detection algorithm
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_set_config(touch_filter_config_t *filter_info);
|
||||
|
||||
/**
|
||||
* @brief get parameter of touch sensor filter and detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @param filter_info select filter type and threshold of detection algorithm
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_get_config(touch_filter_config_t *filter_info);
|
||||
|
||||
/**
|
||||
* @brief enable touch sensor filter and detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_enable(void);
|
||||
|
||||
/**
|
||||
* @brief diaable touch sensor filter and detection algorithm.
|
||||
* For more details on the detection algorithm, please refer to the application documentation.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_filter_disable(void);
|
||||
|
||||
/**
|
||||
* @brief set parameter of denoise pad (TOUCH_PAD_NUM0).
|
||||
* T0 is an internal channel that does not have a corresponding external GPIO.
|
||||
* T0 will work simultaneously with the measured channel Tn. Finally, the actual
|
||||
* measured value of Tn is the value after subtracting lower bits of T0.
|
||||
* This denoise function filters out interference introduced on all channels,
|
||||
* such as noise introduced by the power supply and external EMI.
|
||||
* @param denoise parameter of denoise
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_set_config(touch_pad_denoise_t denoise);
|
||||
|
||||
/**
|
||||
* @brief get parameter of denoise pad (TOUCH_PAD_NUM0).
|
||||
* @param denoise Pointer to parameter of denoise
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_get_config(touch_pad_denoise_t *denoise);
|
||||
|
||||
/**
|
||||
* @brief enable denoise function.
|
||||
* T0 is an internal channel that does not have a corresponding external GPIO.
|
||||
* T0 will work simultaneously with the measured channel Tn. Finally, the actual
|
||||
* measured value of Tn is the value after subtracting lower bits of T0.
|
||||
* This denoise function filters out interference introduced on all channels,
|
||||
* such as noise introduced by the power supply and external EMI.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_enable(void);
|
||||
|
||||
/**
|
||||
* @brief disable denoise function.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_disable(void);
|
||||
|
||||
/**
|
||||
* @brief get denoise measure value (TOUCH_PAD_NUM0).
|
||||
* @param denoise value of denoise
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_denoise_data_get(uint32_t *data);
|
||||
|
||||
/**
|
||||
* @brief set parameter of waterproof function.
|
||||
* The waterproof function includes a shielded channel (TOUCH_PAD_NUM14) and a guard channel.
|
||||
* The shielded channel outputs the same signal as the channel being measured.
|
||||
* It is generally designed as a grid and is placed around the touch buttons.
|
||||
* The shielded channel does not follow the measurement signal of the protection channel.
|
||||
* So that the guard channel can detect a large area of water.
|
||||
* @param waterproof parameter of waterproof
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_set_config(touch_pad_waterproof_t waterproof);
|
||||
|
||||
/**
|
||||
* @brief get parameter of waterproof function.
|
||||
* @param waterproof parameter of waterproof
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_get_config(touch_pad_waterproof_t *waterproof);
|
||||
|
||||
/**
|
||||
* @brief Enable parameter of waterproof function.
|
||||
* The waterproof function includes a shielded channel (TOUCH_PAD_NUM14) and a guard channel.
|
||||
* The shielded channel outputs the same signal as the channel being measured.
|
||||
* It is generally designed as a grid and is placed around the touch buttons.
|
||||
* The shielded channel does not follow the measurement signal of the protection channel.
|
||||
* So that the guard channel can detect a large area of water.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_enable(void);
|
||||
|
||||
/**
|
||||
* @brief Enable parameter of waterproof function.
|
||||
* The waterproof function includes a shielded channel (TOUCH_PAD_NUM14) and a guard channel.
|
||||
* The shielded channel outputs the same signal as the channel being measured.
|
||||
* It is generally designed as a grid and is placed around the touch buttons.
|
||||
* The shielded channel does not follow the measurement signal of the protection channel.
|
||||
* So that the guard channel can detect a large area of water.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_waterproof_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Set parameter of proximity channel. Three proximity sensing channels can be set.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
* @note If stop the proximity function for the channel, point this proximity channel to `TOUCH_PAD_NUM0`.
|
||||
* @param proximity parameter of proximity
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_set_config(touch_pad_proximity_t proximity);
|
||||
|
||||
/**
|
||||
* @brief Get parameter of proximity channel. Three proximity sensing channels can be set.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
* @param proximity parameter of proximity
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_get_config(touch_pad_proximity_t *proximity);
|
||||
|
||||
/**
|
||||
* @brief Get measure count of proximity channel.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
* @param touch_num touch pad index
|
||||
* @param proximity parameter of proximity
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_get_meas_cnt(touch_pad_t touch_num, uint32_t *cnt);
|
||||
|
||||
/**
|
||||
* @brief Get the accumulated measurement of the proximity sensor.
|
||||
* The proximity sensor measurement is the accumulation of touch channel measurements.
|
||||
* @param touch_num touch pad index
|
||||
* @param measure_out If the accumulation process does not end, the `measure_out` is the process value.
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_proximity_data_get(touch_pad_t touch_num, uint32_t *measure_out);
|
||||
|
||||
/**
|
||||
* @brief Set parameter of touch sensor in sleep mode.
|
||||
* In order to achieve low power consumption in sleep mode, other circuits except the RTC part of the register are in a power-off state.
|
||||
* Only one touch channel is supported in the sleep state, which can be used as a wake-up function.
|
||||
* If in non-sleep mode, the sleep parameters do not work.
|
||||
* @param slp_config touch pad config
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_config(touch_pad_sleep_channel_t slp_config);
|
||||
|
||||
/**
|
||||
* @brief get baseline of touch sensor in sleep mode.
|
||||
* @param baseline pointer to accept touch sensor baseline value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_baseline_get(uint32_t *baseline);
|
||||
|
||||
/**
|
||||
* @brief get debounce of touch sensor in sleep mode.
|
||||
* @param debounce pointer to accept touch sensor debounce value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_debounce_get(uint32_t *debounce);
|
||||
|
||||
/**
|
||||
* @brief get proximity count of touch sensor in sleep mode.
|
||||
* @param proximity_cnt pointer to accept touch sensor proximity count value
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_ERR_INVALID_ARG parameter is NULL
|
||||
*/
|
||||
esp_err_t touch_pad_sleep_channel_proximity_cnt_get(uint32_t *proximity_cnt);
|
||||
|
||||
#endif // CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -675,26 +675,51 @@ esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
|
||||
*/
|
||||
esp_err_t uart_disable_pattern_det_intr(uart_port_t uart_num);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/**
|
||||
* @brief UART enable pattern detect function.
|
||||
* Designed for applications like 'AT commands'.
|
||||
* When the hardware detect a series of one same character, the interrupt will be triggered.
|
||||
* @note This function only works for esp32. And this function is deprecated, please use
|
||||
* uart_enable_pattern_det_baud_intr instead.
|
||||
*
|
||||
* @param uart_num UART port number.
|
||||
* @param pattern_chr character of the pattern.
|
||||
* @param chr_num number of the character, 8bit value.
|
||||
* @param chr_tout timeout of the interval between each pattern characters, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* When the duration is less than this value, it will not take this data as at_cmd char.
|
||||
* @param post_idle idle time after the last pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* When the duration is less than this value, it will not take the previous data as the last at_cmd char
|
||||
* @param pre_idle idle time before the first pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* When the duration is less than this value, it will not take this data as the first at_cmd char.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle) __attribute__((deprecated));
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief UART enable pattern detect function.
|
||||
* Designed for applications like 'AT commands'.
|
||||
* When the hardware detect a series of one same character, the interrupt will be triggered.
|
||||
*
|
||||
* @param uart_num UART port number.
|
||||
* @param pattern_chr character of the pattern
|
||||
* @param pattern_chr character of the pattern.
|
||||
* @param chr_num number of the character, 8bit value.
|
||||
* @param chr_tout timeout of the interval between each pattern characters, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* When the duration is less than this value, it will not take this data as at_cmd char
|
||||
* @param post_idle idle time after the last pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* @param chr_tout timeout of the interval between each pattern characters, 16bit value, unit is the baud-rate cycle you configured.
|
||||
* When the duration is more than this value, it will not take this data as at_cmd char.
|
||||
* @param post_idle idle time after the last pattern character, 16bit value, unit is the baud-rate cycle you configured.
|
||||
* When the duration is less than this value, it will not take the previous data as the last at_cmd char
|
||||
* @param pre_idle idle time before the first pattern character, 24bit value, unit is APB (80Mhz) clock cycle.
|
||||
* When the duration is less than this value, it will not take this data as the first at_cmd char
|
||||
* @param pre_idle idle time before the first pattern character, 16bit value, unit is the baud-rate cycle you configured.
|
||||
* When the duration is less than this value, it will not take this data as the first at_cmd char.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK Success
|
||||
* - ESP_FAIL Parameter error
|
||||
*/
|
||||
esp_err_t uart_enable_pattern_det_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
|
||||
esp_err_t uart_enable_pattern_det_baud_intr(uart_port_t uart_num, char pattern_chr, uint8_t chr_num, int chr_tout, int post_idle, int pre_idle);
|
||||
|
||||
/**
|
||||
* @brief Return the nearest detected pattern position in buffer.
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -11,8 +11,8 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#include <esp_types.h>
|
||||
#include <string.h>
|
||||
#include <esp_types.h>
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
@ -52,9 +52,13 @@ static ledc_isr_handle_t s_ledc_fade_isr_handle = NULL;
|
||||
#define LEDC_VAL_NO_CHANGE (-1)
|
||||
#define LEDC_STEP_NUM_MAX (1023)
|
||||
#define LEDC_DUTY_DECIMAL_BIT_NUM (4)
|
||||
#define LEDC_TIMER_DIV_NUM_MAX (0x3FFFF)
|
||||
#define LEDC_DUTY_NUM_MAX (LEDC_DUTY_NUM_LSCH0_V)
|
||||
#define LEDC_DUTY_CYCLE_MAX (LEDC_DUTY_CYCLE_LSCH0_V)
|
||||
#define LEDC_DUTY_SCALE_MAX (LEDC_DUTY_SCALE_LSCH0_V)
|
||||
#define LEDC_HPOINT_VAL_MAX (LEDC_HPOINT_LSCH1_V)
|
||||
#define DELAY_CLK8M_CLK_SWITCH (5)
|
||||
#define SLOW_CLK_CYC_CALIBRATE (13)
|
||||
#define LEDC_HPOINT_VAL_MAX (LEDC_HPOINT_HSCH1_V)
|
||||
#define LEDC_FADE_TOO_SLOW_STR "LEDC FADE TOO SLOW"
|
||||
#define LEDC_FADE_TOO_FAST_STR "LEDC FADE TOO FAST"
|
||||
static const char *LEDC_FADE_SERVICE_ERR_STR = "LEDC fade service not installed";
|
||||
@ -80,6 +84,7 @@ static IRAM_ATTR void ledc_ls_channel_update(ledc_mode_t speed_mode, ledc_channe
|
||||
//We know that CLK8M is about 8M, but don't know the actual value. So we need to do a calibration.
|
||||
static bool ledc_slow_clk_calibrate(void)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
//Enable CLK8M for LEDC
|
||||
SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_EN_M);
|
||||
//Waiting for CLK8M to turn on
|
||||
@ -92,6 +97,10 @@ static bool ledc_slow_clk_calibrate(void)
|
||||
s_ledc_slow_clk_8M = 1000000ULL * (1 << RTC_CLK_CAL_FRACT) * 256 / cal_val;
|
||||
ESP_LOGD(LEDC_TAG, "Calibrate CLK8M_CLK : %d Hz", s_ledc_slow_clk_8M);
|
||||
return true;
|
||||
#else
|
||||
ESP_LOGE(LEDC_TAG, "CLK8M source currently only supported on ESP32");
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel, ledc_intr_type_t type)
|
||||
@ -101,7 +110,11 @@ static esp_err_t ledc_enable_intr_type(ledc_mode_t speed_mode, uint32_t channel,
|
||||
uint32_t intr_type = type;
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
value = LEDC.int_ena.val;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint8_t int_en_base = LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint8_t int_en_base = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
#endif
|
||||
if (speed_mode == LEDC_LOW_SPEED_MODE) {
|
||||
int_en_base = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
}
|
||||
@ -162,7 +175,18 @@ esp_err_t ledc_timer_set(ledc_mode_t speed_mode, ledc_timer_t timer_sel, uint32_
|
||||
LEDC_ARG_CHECK(timer_sel < LEDC_TIMER_MAX, "timer_select");
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.clock_divider = clock_divider;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = clk_src;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if(clk_src == LEDC_REF_TICK) {
|
||||
//REF_TICK can only be used when APB is selected.
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = 1;
|
||||
LEDC.conf.apb_clk_sel = 1;
|
||||
} else {
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.tick_sel = 0;
|
||||
LEDC.conf.apb_clk_sel = clk_src;
|
||||
}
|
||||
#endif
|
||||
LEDC.timer_group[speed_mode].timer[timer_sel].conf.duty_resolution = duty_resolution;
|
||||
ledc_ls_timer_update(speed_mode, timer_sel);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
@ -174,15 +198,18 @@ static IRAM_ATTR esp_err_t ledc_duty_config(ledc_mode_t speed_mode, ledc_channel
|
||||
{
|
||||
portENTER_CRITICAL(&ledc_spinlock);
|
||||
if (hpoint_val >= 0) {
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val & LEDC_HPOINT_HSCH1_V;
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].hpoint.hpoint = hpoint_val;
|
||||
}
|
||||
if (duty_val >= 0) {
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].duty.duty = duty_val;
|
||||
}
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].conf1.val = ((duty_direction & LEDC_DUTY_INC_HSCH0_V) << LEDC_DUTY_INC_HSCH0_S) |
|
||||
((duty_num & LEDC_DUTY_NUM_HSCH0_V) << LEDC_DUTY_NUM_HSCH0_S) |
|
||||
((duty_cycle & LEDC_DUTY_CYCLE_HSCH0_V) << LEDC_DUTY_CYCLE_HSCH0_S) |
|
||||
((duty_scale & LEDC_DUTY_SCALE_HSCH0_V) << LEDC_DUTY_SCALE_HSCH0_S);
|
||||
typeof(LEDC.channel_group[0].channel[0].conf1) channel_cfg;
|
||||
channel_cfg.val = 0;
|
||||
channel_cfg.duty_inc = duty_direction;
|
||||
channel_cfg.duty_num = duty_num;
|
||||
channel_cfg.duty_cycle = duty_cycle;
|
||||
channel_cfg.duty_scale = duty_scale;
|
||||
LEDC.channel_group[speed_mode].channel[channel_num].conf1.val = channel_cfg.val;
|
||||
ledc_ls_channel_update(speed_mode, channel_num);
|
||||
portEXIT_CRITICAL(&ledc_spinlock);
|
||||
return ESP_OK;
|
||||
@ -263,7 +290,7 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
if (clk_cfg == LEDC_AUTO_CLK) {
|
||||
// Try calculating divisor based on LEDC_APB_CLK
|
||||
div_param = ( (uint64_t) LEDC_APB_CLK_HZ << 8 ) / freq_hz / precision;
|
||||
if (div_param > LEDC_DIV_NUM_HSTIMER0_V) {
|
||||
if (div_param > LEDC_TIMER_DIV_NUM_MAX) {
|
||||
// APB_CLK results in divisor which too high. Try using REF_TICK as clock source.
|
||||
timer_clk_src = LEDC_REF_TICK;
|
||||
div_param = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision;
|
||||
@ -278,13 +305,15 @@ static esp_err_t ledc_set_timer_div(ledc_mode_t speed_mode, ledc_timer_t timer_n
|
||||
div_param = ( (uint64_t) sclk_freq << 8 ) / freq_hz / precision;
|
||||
}
|
||||
}
|
||||
if (div_param < 256 || div_param > LEDC_DIV_NUM_LSTIMER0_V) {
|
||||
if (div_param < 256 || div_param > LEDC_TIMER_DIV_NUM_MAX) {
|
||||
goto error;
|
||||
}
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
// For low speed channels, if RTC_8MCLK is used as the source clock, the `slow_clk_sel` register should be cleared, otherwise it should be set.
|
||||
if (speed_mode == LEDC_LOW_SPEED_MODE) {
|
||||
LEDC.conf.slow_clk_sel = (clk_cfg == LEDC_USE_RTC8M_CLK) ? 0 : 1;
|
||||
}
|
||||
#endif
|
||||
//Set the divisor
|
||||
ledc_timer_set(speed_mode, timer_num, div_param, duty_resolution, timer_clk_src);
|
||||
// reset the timer
|
||||
@ -324,11 +353,7 @@ esp_err_t ledc_set_pin(int gpio_num, ledc_mode_t speed_mode, ledc_channel_t ledc
|
||||
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
|
||||
if (speed_mode == LEDC_HIGH_SPEED_MODE) {
|
||||
gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0);
|
||||
} else {
|
||||
gpio_matrix_out(gpio_num, LEDC_LS_SIG_OUT0_IDX + ledc_channel, 0, 0);
|
||||
}
|
||||
gpio_matrix_out(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + ledc_channel, 0, 0);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -364,11 +389,8 @@ esp_err_t ledc_channel_config(const ledc_channel_config_t* ledc_conf)
|
||||
/*set LEDC signal in gpio matrix*/
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
|
||||
if (speed_mode == LEDC_HIGH_SPEED_MODE) {
|
||||
gpio_matrix_out(gpio_num, LEDC_HS_SIG_OUT0_IDX + ledc_channel, 0, 0);
|
||||
} else {
|
||||
gpio_matrix_out(gpio_num, LEDC_LS_SIG_OUT0_IDX + ledc_channel, 0, 0);
|
||||
}
|
||||
gpio_matrix_out(gpio_num, ledc_periph_signal[speed_mode].sig_out0_idx + ledc_channel, 0, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -403,9 +425,9 @@ esp_err_t ledc_set_fade(ledc_mode_t speed_mode, ledc_channel_t channel, uint32_t
|
||||
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
|
||||
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
|
||||
LEDC_ARG_CHECK(fade_direction < LEDC_DUTY_DIR_MAX, "fade_direction");
|
||||
LEDC_ARG_CHECK(step_num <= LEDC_DUTY_NUM_HSCH0_V, "step_num");
|
||||
LEDC_ARG_CHECK(duty_cyle_num <= LEDC_DUTY_CYCLE_HSCH0_V, "duty_cycle_num");
|
||||
LEDC_ARG_CHECK(duty_scale <= LEDC_DUTY_SCALE_HSCH0_V, "duty_scale");
|
||||
LEDC_ARG_CHECK(step_num <= LEDC_DUTY_NUM_MAX, "step_num");
|
||||
LEDC_ARG_CHECK(duty_cyle_num <= LEDC_DUTY_CYCLE_MAX, "duty_cycle_num");
|
||||
LEDC_ARG_CHECK(duty_scale <= LEDC_DUTY_SCALE_MAX, "duty_scale");
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
ledc_duty_config(speed_mode,
|
||||
channel, //uint32_t chan_num,
|
||||
@ -488,7 +510,7 @@ esp_err_t ledc_set_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num, uint32_t
|
||||
} else {
|
||||
clock_divider = ((uint64_t) LEDC_REF_CLK_HZ << 8) / freq_hz / precision;
|
||||
}
|
||||
if (clock_divider <= 256 || clock_divider > LEDC_DIV_NUM_HSTIMER0) {
|
||||
if (clock_divider <= 256 || clock_divider > LEDC_TIMER_DIV_NUM_MAX) {
|
||||
ESP_LOGE(LEDC_TAG, "div param err,div_param=%u", clock_divider);
|
||||
ret = ESP_FAIL;
|
||||
}
|
||||
@ -516,20 +538,30 @@ uint32_t ledc_get_freq(ledc_mode_t speed_mode, ledc_timer_t timer_num)
|
||||
return freq;
|
||||
}
|
||||
|
||||
static inline void ledc_calc_fade_end_channel(uint32_t *fade_end_status, int *channel, int *speed_mode)
|
||||
{
|
||||
int i = __builtin_ffs((*fade_end_status)) - 1;
|
||||
(*fade_end_status) &= ~(1 << i);
|
||||
*speed_mode = LEDC_LOW_SPEED_MODE;
|
||||
*channel = i;
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
if (i < LEDC_CHANNEL_MAX) {
|
||||
*speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
} else {
|
||||
*channel = i - LEDC_CHANNEL_MAX;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
{
|
||||
int channel;
|
||||
portBASE_TYPE HPTaskAwoken = pdFALSE;
|
||||
uint32_t intr_status = LEDC.int_st.val; //read LEDC interrupt status.
|
||||
LEDC.int_clr.val = intr_status; //clear LEDC interrupt status.
|
||||
int speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
for (channel = 0; channel < LEDC_CHANNEL_MAX; channel++) {
|
||||
if (intr_status & (BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ST_S + channel) | BIT(LEDC_DUTY_CHNG_END_LSCH0_INT_ST_S + channel))) {
|
||||
if (intr_status & BIT(LEDC_DUTY_CHNG_END_HSCH0_INT_ST_S + channel)) {
|
||||
speed_mode = LEDC_HIGH_SPEED_MODE;
|
||||
} else {
|
||||
speed_mode = LEDC_LOW_SPEED_MODE;
|
||||
}
|
||||
uint32_t fade_end_status = (intr_status >> LEDC_LSTIMER0_OVF_INT_ST_S);
|
||||
int speed_mode;
|
||||
int channel;
|
||||
while (fade_end_status) {
|
||||
ledc_calc_fade_end_channel(&fade_end_status, &channel, &speed_mode);
|
||||
if (s_ledc_fade_rec[speed_mode][channel] == NULL) {
|
||||
//fade object not initialized yet.
|
||||
continue;
|
||||
@ -537,9 +569,6 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
uint32_t duty_cur = LEDC.channel_group[speed_mode].channel[channel].duty_rd.duty_read >> LEDC_DUTY_DECIMAL_BIT_NUM;
|
||||
if (duty_cur == s_ledc_fade_rec[speed_mode][channel]->target_duty) {
|
||||
xSemaphoreGiveFromISR(s_ledc_fade_rec[speed_mode][channel]->ledc_fade_sem, &HPTaskAwoken);
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
uint32_t duty_tar = s_ledc_fade_rec[speed_mode][channel]->target_duty;
|
||||
@ -574,8 +603,10 @@ void IRAM_ATTR ledc_fade_isr(void* arg)
|
||||
}
|
||||
LEDC.channel_group[speed_mode].channel[channel].conf1.duty_start = 1;
|
||||
}
|
||||
}
|
||||
LEDC.int_clr.val = intr_status; //clear LEDC interrupt status.
|
||||
if (HPTaskAwoken == pdTRUE) {
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
}
|
||||
|
||||
static esp_err_t ledc_fade_channel_deinit(ledc_mode_t speed_mode, ledc_channel_t channel)
|
||||
@ -686,16 +717,16 @@ static esp_err_t _ledc_set_fade_with_time(ledc_mode_t speed_mode, ledc_channel_t
|
||||
if (total_cycles > duty_delta) {
|
||||
scale = 1;
|
||||
cycle_num = total_cycles / duty_delta;
|
||||
if (cycle_num > LEDC_DUTY_NUM_HSCH0_V) {
|
||||
if (cycle_num > LEDC_DUTY_NUM_MAX) {
|
||||
ESP_LOGW(LEDC_TAG, LEDC_FADE_TOO_SLOW_STR);
|
||||
cycle_num = LEDC_DUTY_NUM_HSCH0_V;
|
||||
cycle_num = LEDC_DUTY_NUM_MAX;
|
||||
}
|
||||
} else {
|
||||
cycle_num = 1;
|
||||
scale = duty_delta / total_cycles;
|
||||
if (scale > LEDC_DUTY_SCALE_HSCH0_V) {
|
||||
if (scale > LEDC_DUTY_SCALE_MAX) {
|
||||
ESP_LOGW(LEDC_TAG, LEDC_FADE_TOO_FAST_STR);
|
||||
scale = LEDC_DUTY_SCALE_HSCH0_V;
|
||||
scale = LEDC_DUTY_SCALE_MAX;
|
||||
}
|
||||
}
|
||||
return _ledc_set_fade_with_step(speed_mode, channel, target_duty, scale, cycle_num);
|
||||
@ -705,7 +736,11 @@ static void _ledc_fade_start(ledc_mode_t speed_mode, ledc_channel_t channel, led
|
||||
{
|
||||
s_ledc_fade_rec[speed_mode][channel]->mode = fade_mode;
|
||||
// Clear interrupt status of channel
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
int duty_resolution_ch0 = (speed_mode == LEDC_HIGH_SPEED_MODE) ? LEDC_DUTY_CHNG_END_HSCH0_INT_ENA_S : LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
int duty_resolution_ch0 = LEDC_DUTY_CHNG_END_LSCH0_INT_ENA_S;
|
||||
#endif
|
||||
LEDC.int_clr.val |= BIT(duty_resolution_ch0 + channel);
|
||||
// Enable interrupt for channel
|
||||
ledc_enable_intr_type(speed_mode, channel, LEDC_INTR_FADE_END);
|
||||
@ -732,8 +767,8 @@ esp_err_t ledc_set_fade_with_step(ledc_mode_t speed_mode, ledc_channel_t channel
|
||||
{
|
||||
LEDC_ARG_CHECK(speed_mode < LEDC_SPEED_MODE_MAX, "speed_mode");
|
||||
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
|
||||
LEDC_ARG_CHECK((scale > 0) && (scale <= LEDC_DUTY_SCALE_HSCH0_V), "fade scale");
|
||||
LEDC_ARG_CHECK((cycle_num > 0) && (cycle_num <= LEDC_DUTY_CYCLE_HSCH0_V), "cycle_num");
|
||||
LEDC_ARG_CHECK((scale > 0) && (scale <= LEDC_DUTY_SCALE_MAX), "fade scale");
|
||||
LEDC_ARG_CHECK((cycle_num > 0) && (cycle_num <= LEDC_DUTY_CYCLE_MAX), "cycle_num");
|
||||
LEDC_ARG_CHECK(target_duty <= ledc_get_max_duty(speed_mode, channel), "target_duty");
|
||||
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
|
||||
|
||||
@ -820,8 +855,8 @@ esp_err_t ledc_set_fade_step_and_start(ledc_mode_t speed_mode, ledc_channel_t ch
|
||||
LEDC_ARG_CHECK(channel < LEDC_CHANNEL_MAX, "channel");
|
||||
LEDC_ARG_CHECK(fade_mode < LEDC_FADE_MAX, "fade_mode");
|
||||
LEDC_CHECK(ledc_fade_channel_init_check(speed_mode, channel) == ESP_OK , LEDC_FADE_INIT_ERROR_STR, ESP_FAIL);
|
||||
LEDC_ARG_CHECK((scale > 0) && (scale <= LEDC_DUTY_SCALE_HSCH0_V), "fade scale");
|
||||
LEDC_ARG_CHECK((cycle_num > 0) && (cycle_num <= LEDC_DUTY_CYCLE_HSCH0_V), "cycle_num");
|
||||
LEDC_ARG_CHECK((scale > 0) && (scale <= LEDC_DUTY_SCALE_MAX), "fade scale");
|
||||
LEDC_ARG_CHECK((cycle_num > 0) && (cycle_num <= LEDC_DUTY_CYCLE_MAX), "cycle_num");
|
||||
LEDC_ARG_CHECK(target_duty <= ledc_get_max_duty(speed_mode, channel), "target_duty");
|
||||
_ledc_op_lock_acquire(speed_mode, channel);
|
||||
_ledc_fade_hw_acquire(speed_mode, channel);
|
||||
|
@ -23,6 +23,8 @@
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "driver/mcpwm.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
|
||||
static mcpwm_dev_t *MCPWM[2] = {&MCPWM0, &MCPWM1};
|
||||
static const char *MCPWM_TAG = "MCPWM";
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -53,7 +53,7 @@ esp_err_t pcnt_unit_config(const pcnt_config_t *pcnt_config)
|
||||
|
||||
PCNT_CHECK(unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(channel < PCNT_CHANNEL_MAX, PCNT_CHANNEL_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pluse input io error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(input_io < 0 || (GPIO_IS_VALID_GPIO(input_io) && (input_io != ctrl_io)), "PCNT pulse input io error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK(ctrl_io < 0 || GPIO_IS_VALID_GPIO(ctrl_io), "PCNT ctrl io error", ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((pcnt_config->pos_mode < PCNT_COUNT_MAX) && (pcnt_config->neg_mode < PCNT_COUNT_MAX), PCNT_COUNT_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_CHECK((pcnt_config->hctrl_mode < PCNT_MODE_MAX) && (pcnt_config->lctrl_mode < PCNT_MODE_MAX), PCNT_CTRL_MODE_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
@ -161,7 +161,11 @@ esp_err_t pcnt_counter_clear(pcnt_unit_t pcnt_unit)
|
||||
{
|
||||
PCNT_CHECK(pcnt_unit < PCNT_UNIT_MAX, PCNT_UNIT_ERR_STR, ESP_ERR_INVALID_ARG);
|
||||
PCNT_ENTER_CRITICAL(&pcnt_spinlock);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
uint32_t reset_bit = BIT(PCNT_PLUS_CNT_RST_U0_S + (pcnt_unit * 2));
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
uint32_t reset_bit = BIT(PCNT_PULSE_CNT_RST_U0_S + (pcnt_unit * 2));
|
||||
#endif
|
||||
PCNT.ctrl.val |= reset_bit;
|
||||
PCNT.ctrl.val &= ~reset_bit;
|
||||
PCNT_EXIT_CRITICAL(&pcnt_spinlock);
|
||||
|
@ -16,7 +16,9 @@
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/syscon_reg.h"
|
||||
#include "driver/periph_ctrl.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
@ -61,8 +63,13 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
|
||||
return DPORT_UART_CLK_EN;
|
||||
case PERIPH_UART1_MODULE:
|
||||
return DPORT_UART1_CLK_EN;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case PERIPH_UART2_MODULE:
|
||||
return DPORT_UART2_CLK_EN;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
case PERIPH_USB_MODULE:
|
||||
return DPORT_USB_CLK_EN;
|
||||
#endif
|
||||
case PERIPH_I2C0_MODULE:
|
||||
return DPORT_I2C_EXT0_CLK_EN;
|
||||
case PERIPH_I2C1_MODULE:
|
||||
@ -91,12 +98,27 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
|
||||
return DPORT_PCNT_CLK_EN;
|
||||
case PERIPH_SPI_MODULE:
|
||||
return DPORT_SPI01_CLK_EN;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case PERIPH_HSPI_MODULE:
|
||||
return DPORT_SPI2_CLK_EN;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
return DPORT_SPI3_CLK_EN;
|
||||
case PERIPH_SPI_DMA_MODULE:
|
||||
return DPORT_SPI_DMA_CLK_EN;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
case PERIPH_FSPI_MODULE:
|
||||
return DPORT_SPI2_CLK_EN;
|
||||
case PERIPH_HSPI_MODULE:
|
||||
return DPORT_SPI3_CLK_EN;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
return DPORT_SPI4_CLK_EN;
|
||||
case PERIPH_SPI2_DMA_MODULE:
|
||||
return DPORT_SPI2_DMA_CLK_EN;
|
||||
case PERIPH_SPI3_DMA_MODULE:
|
||||
return DPORT_SPI3_DMA_CLK_EN;
|
||||
case PERIPH_SPI_SHARED_DMA_MODULE:
|
||||
return DPORT_SPI_SHARED_DMA_CLK_EN;
|
||||
#endif
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
return DPORT_WIFI_CLK_SDIO_HOST_EN;
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
@ -108,7 +130,11 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
|
||||
case PERIPH_RNG_MODULE:
|
||||
return DPORT_WIFI_CLK_RNG_EN;
|
||||
case PERIPH_WIFI_MODULE:
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return DPORT_WIFI_CLK_WIFI_EN_M;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
return 0;
|
||||
#endif
|
||||
case PERIPH_BT_MODULE:
|
||||
return DPORT_WIFI_CLK_BT_EN_M;
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
@ -117,12 +143,14 @@ static uint32_t get_clk_en_mask(periph_module_t periph)
|
||||
return DPORT_BT_BASEBAND_EN;
|
||||
case PERIPH_BT_LC_MODULE:
|
||||
return DPORT_BT_LC_EN;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case PERIPH_AES_MODULE:
|
||||
return DPORT_PERI_EN_AES;
|
||||
case PERIPH_SHA_MODULE:
|
||||
return DPORT_PERI_EN_SHA;
|
||||
case PERIPH_RSA_MODULE:
|
||||
return DPORT_PERI_EN_RSA;
|
||||
#endif
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
@ -139,8 +167,13 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
|
||||
return DPORT_UART_RST;
|
||||
case PERIPH_UART1_MODULE:
|
||||
return DPORT_UART1_RST;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case PERIPH_UART2_MODULE:
|
||||
return DPORT_UART2_RST;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
case PERIPH_USB_MODULE:
|
||||
return DPORT_USB_RST;
|
||||
#endif
|
||||
case PERIPH_I2C0_MODULE:
|
||||
return DPORT_I2C_EXT0_RST;
|
||||
case PERIPH_I2C1_MODULE:
|
||||
@ -169,12 +202,27 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
|
||||
return DPORT_PCNT_RST;
|
||||
case PERIPH_SPI_MODULE:
|
||||
return DPORT_SPI01_RST;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case PERIPH_HSPI_MODULE:
|
||||
return DPORT_SPI2_RST;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
return DPORT_SPI3_RST;
|
||||
case PERIPH_SPI_DMA_MODULE:
|
||||
return DPORT_SPI_DMA_RST;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
case PERIPH_FSPI_MODULE:
|
||||
return DPORT_SPI2_RST;
|
||||
case PERIPH_HSPI_MODULE:
|
||||
return DPORT_SPI3_RST;
|
||||
case PERIPH_VSPI_MODULE:
|
||||
return DPORT_SPI4_RST;
|
||||
case PERIPH_SPI2_DMA_MODULE:
|
||||
return DPORT_SPI2_DMA_RST;
|
||||
case PERIPH_SPI3_DMA_MODULE:
|
||||
return DPORT_SPI3_DMA_RST;
|
||||
case PERIPH_SPI_SHARED_DMA_MODULE:
|
||||
return DPORT_SPI_SHARED_DMA_RST;
|
||||
#endif
|
||||
case PERIPH_SDMMC_MODULE:
|
||||
return DPORT_SDIO_HOST_RST;
|
||||
case PERIPH_SDIO_SLAVE_MODULE:
|
||||
@ -183,6 +231,7 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
|
||||
return DPORT_CAN_RST;
|
||||
case PERIPH_EMAC_MODULE:
|
||||
return DPORT_EMAC_RST;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
case PERIPH_AES_MODULE:
|
||||
if (enable == true) {
|
||||
// Clear reset on digital signature & secure boot units, otherwise AES unit is held in reset also.
|
||||
@ -207,6 +256,7 @@ static uint32_t get_rst_en_mask(periph_module_t periph, bool enable)
|
||||
// Don't reset digital signature unit, as this resets AES also
|
||||
return DPORT_PERI_EN_RSA;
|
||||
}
|
||||
#endif
|
||||
case PERIPH_WIFI_MODULE:
|
||||
case PERIPH_BT_MODULE:
|
||||
case PERIPH_WIFI_BT_COMMON_MODULE:
|
||||
@ -240,18 +290,32 @@ static bool is_wifi_clk_peripheral(periph_module_t periph)
|
||||
|
||||
static uint32_t get_clk_en_reg(periph_module_t periph)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (periph == PERIPH_AES_MODULE || periph == PERIPH_SHA_MODULE || periph == PERIPH_RSA_MODULE) {
|
||||
return DPORT_PERI_CLK_EN_REG;
|
||||
} else {
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if(periph == PERIPH_SPI_SHARED_DMA_MODULE) {
|
||||
return DPORT_PERIP_CLK_EN1_REG;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return is_wifi_clk_peripheral(periph) ? DPORT_WIFI_CLK_EN_REG : DPORT_PERIP_CLK_EN_REG;
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t get_rst_en_reg(periph_module_t periph)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (periph == PERIPH_AES_MODULE || periph == PERIPH_SHA_MODULE || periph == PERIPH_RSA_MODULE) {
|
||||
return DPORT_PERI_RST_EN_REG;
|
||||
} else {
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if(periph == PERIPH_SPI_SHARED_DMA_MODULE){
|
||||
return DPORT_PERIP_CLK_EN1_REG;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG : DPORT_PERIP_RST_EN_REG;
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
@ -193,8 +193,12 @@ esp_err_t rmt_tx_stop(rmt_channel_t channel)
|
||||
{
|
||||
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rmt_spinlock);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
RMTMEM.chan[channel].data32[0].val = 0;
|
||||
RMT.conf_ch[channel].conf1.tx_start = 0;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RMT.conf_ch[channel].conf1.tx_stop = 1;
|
||||
#endif
|
||||
RMT.conf_ch[channel].conf1.mem_rd_rst = 1;
|
||||
RMT.conf_ch[channel].conf1.mem_rd_rst = 0;
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
@ -317,7 +321,11 @@ esp_err_t rmt_get_idle_level(rmt_channel_t channel, bool* idle_out_en, rmt_idle_
|
||||
esp_err_t rmt_get_status(rmt_channel_t channel, uint32_t* status)
|
||||
{
|
||||
RMT_CHECK(channel < RMT_CHANNEL_MAX, RMT_CHANNEL_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
*status = RMT.status_ch[channel];
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
*status = RMT.status_ch[channel].val;
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -382,9 +390,15 @@ esp_err_t rmt_set_tx_thr_intr_en(rmt_channel_t channel, bool en, uint16_t evt_th
|
||||
RMT.tx_lim_ch[channel].limit = evt_thresh;
|
||||
portEXIT_CRITICAL(&rmt_spinlock);
|
||||
rmt_set_tx_wrap_en(true);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
rmt_set_intr_enable_mask(BIT(channel + 24));
|
||||
} else {
|
||||
rmt_clr_intr_enable_mask(BIT(channel + 24));
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rmt_set_intr_enable_mask(BIT(channel + 12));
|
||||
} else {
|
||||
rmt_clr_intr_enable_mask(BIT(channel + 12));
|
||||
#endif
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -396,7 +410,7 @@ esp_err_t rmt_set_pin(rmt_channel_t channel, rmt_mode_t mode, gpio_num_t gpio_nu
|
||||
RMT_CHECK(((GPIO_IS_VALID_GPIO(gpio_num) && (mode == RMT_MODE_RX)) || (GPIO_IS_VALID_OUTPUT_GPIO(gpio_num) && (mode == RMT_MODE_TX))),
|
||||
RMT_GPIO_ERROR_STR, ESP_ERR_INVALID_ARG);
|
||||
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], 2);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[gpio_num], PIN_FUNC_GPIO);
|
||||
if(mode == RMT_MODE_TX) {
|
||||
gpio_set_direction(gpio_num, GPIO_MODE_OUTPUT);
|
||||
gpio_matrix_out(gpio_num, RMT_SIG_OUT0_IDX + channel, 0, 0);
|
||||
@ -566,7 +580,12 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg)
|
||||
while (status) {
|
||||
int i = __builtin_ffs(status) - 1;
|
||||
status &= ~(1 << i);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
if(i < 24) {
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if(i >= 15) {
|
||||
} else if(i < 12) {
|
||||
#endif
|
||||
channel = i / 3;
|
||||
rmt_obj_t* p_rmt = p_rmt_obj[channel];
|
||||
if(NULL == p_rmt) {
|
||||
@ -617,8 +636,13 @@ static void IRAM_ATTR rmt_driver_isr_default(void* arg)
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
} else {
|
||||
channel = i - 24;
|
||||
#elif defined CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
} else if(i >= 12 && i < 16) {
|
||||
channel = i - 12;
|
||||
#endif
|
||||
rmt_obj_t* p_rmt = p_rmt_obj[channel];
|
||||
|
||||
if(p_rmt->tx_data == NULL) {
|
||||
|
@ -15,12 +15,12 @@
|
||||
#include <esp_types.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc_periph.h"
|
||||
#include "soc/sens_periph.h"
|
||||
#include "soc/syscon_periph.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "soc/periph_defs.h"
|
||||
#include "rtc_io.h"
|
||||
#include "touch_pad.h"
|
||||
#include "adc.h"
|
||||
@ -34,6 +34,12 @@
|
||||
#include "driver/rtc_cntl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "adc1_i2s_private.h"
|
||||
#include "sdkconfig.h"
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/ets_sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Enable built-in checks in queue.h in debug builds
|
||||
@ -80,7 +86,9 @@ static const char *RTC_MODULE_TAG = "RTC_MODULE";
|
||||
} }while (0)
|
||||
|
||||
portMUX_TYPE rtc_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static SemaphoreHandle_t rtc_touch_mux = NULL;
|
||||
#endif
|
||||
/*
|
||||
In ADC2, there're two locks used for different cases:
|
||||
1. lock shared with app and WIFI:
|
||||
@ -103,6 +111,7 @@ portMUX_TYPE adc2_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
//prevent ADC1 being used by I2S dma and other tasks at the same time.
|
||||
static _lock_t adc1_i2s_lock;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
typedef struct {
|
||||
TimerHandle_t timer;
|
||||
uint16_t filtered_val[TOUCH_PAD_MAX];
|
||||
@ -115,6 +124,7 @@ static touch_pad_filter_t *s_touch_pad_filter = NULL;
|
||||
// check if touch pad be inited.
|
||||
static uint16_t s_touch_pad_init_bit = 0x0000;
|
||||
static filter_cb_t s_filter_cb = NULL;
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
ADC_CTRL_RTC = 0,
|
||||
@ -136,10 +146,15 @@ esp_err_t rtc_gpio_init(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// 0: GPIO connected to digital GPIO module. 1: GPIO connected to analog RTC module.
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, (rtc_gpio_desc[gpio_num].mux));
|
||||
//0:RTC FUNCIOTN 1,2,3:Reserved
|
||||
SET_PERI_REG_BITS(rtc_gpio_desc[gpio_num].reg, RTC_IO_TOUCH_PAD1_FUN_SEL_V, 0x0, rtc_gpio_desc[gpio_num].func);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rtc_gpio_reg[gpio_num]->mux_sel = 0x1;
|
||||
rtc_gpio_reg[gpio_num]->fun_sel = 0x0;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
@ -150,7 +165,11 @@ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num)
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//Select Gpio as Digital Gpio
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, (rtc_gpio_desc[gpio_num].mux));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rtc_gpio_reg[gpio_num]->mux_sel = 0x0;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
@ -158,21 +177,27 @@ esp_err_t rtc_gpio_deinit(gpio_num_t gpio_num)
|
||||
|
||||
static esp_err_t rtc_gpio_output_enable(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;
|
||||
RTC_MODULE_CHECK(rtc_gpio_num != -1, "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
SET_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TS_REG, (1 << (rtc_gpio_num + RTC_GPIO_ENABLE_W1TS_S)));
|
||||
CLEAR_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TC_REG, (1 << (rtc_gpio_num + RTC_GPIO_ENABLE_W1TC_S)));
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
SET_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TS_REG, (1 << ( gpio_num + RTC_GPIO_ENABLE_W1TS_S)));
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
static esp_err_t rtc_gpio_output_disable(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;
|
||||
RTC_MODULE_CHECK(rtc_gpio_num != -1, "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
CLEAR_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TS_REG, (1 << (rtc_gpio_num + RTC_GPIO_ENABLE_W1TS_S)));
|
||||
SET_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TC_REG, (1 << ( rtc_gpio_num + RTC_GPIO_ENABLE_W1TC_S)));
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
SET_PERI_REG_MASK(RTC_GPIO_ENABLE_W1TC_REG, (1 << ( gpio_num + RTC_GPIO_ENABLE_W1TC_S)));
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -180,7 +205,11 @@ static esp_err_t rtc_gpio_input_enable(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].ie);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rtc_gpio_reg[gpio_num]->fun_ie = 1;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
@ -190,14 +219,44 @@ static esp_err_t rtc_gpio_input_disable(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].ie);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rtc_gpio_reg[gpio_num]->fun_ie = 0;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
esp_err_t rtc_gpio_sleep_output_enable(gpio_num_t gpio_num, bool output)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
rtc_gpio_reg[gpio_num]->slp_sel = 1;
|
||||
rtc_gpio_reg[gpio_num]->slp_oe = output;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_sleep_input_enable(gpio_num_t gpio_num, bool input)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
rtc_gpio_reg[gpio_num]->slp_sel = 1;
|
||||
rtc_gpio_reg[gpio_num]->slp_ie = input;
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_sleep_mode_disable(gpio_num_t gpio_num)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
rtc_gpio_reg[gpio_num]->slp_sel = 0;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int rtc_gpio_num = rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;;
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
@ -206,13 +265,21 @@ esp_err_t rtc_gpio_set_level(gpio_num_t gpio_num, uint32_t level)
|
||||
} else {
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT_W1TC_REG, (1 << (rtc_gpio_num + RTC_GPIO_OUT_DATA_W1TC_S)));
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
if (level) {
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT_W1TS_REG, (1 << (gpio_num + RTC_GPIO_OUT_DATA_W1TS_S)));
|
||||
} else {
|
||||
WRITE_PERI_REG(RTC_GPIO_OUT_W1TC_REG, (1 << (gpio_num + RTC_GPIO_OUT_DATA_W1TC_S)));
|
||||
}
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
uint32_t rtc_gpio_get_level(gpio_num_t gpio_num)
|
||||
{
|
||||
uint32_t level = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int rtc_gpio_num = rtc_gpio_desc[gpio_num].rtc_num;
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
@ -220,6 +287,13 @@ uint32_t rtc_gpio_get_level(gpio_num_t gpio_num)
|
||||
level = READ_PERI_REG(RTC_GPIO_IN_REG);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ((level >> (RTC_GPIO_IN_NEXT_S + rtc_gpio_num)) & 0x01);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
level = RTCIO.in_val.in;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ((level >> gpio_num) & 0x1);
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t strength)
|
||||
@ -229,7 +303,11 @@ esp_err_t rtc_gpio_set_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t st
|
||||
RTC_MODULE_CHECK(strength < GPIO_DRIVE_CAP_MAX, "GPIO drive capability error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_BITS(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].drv_v, strength, rtc_gpio_desc[gpio_num].drv_s);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rtc_gpio_reg[gpio_num]->drv = strength;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -239,8 +317,11 @@ esp_err_t rtc_gpio_get_drive_capability(gpio_num_t gpio_num, gpio_drive_cap_t* s
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), "Output pad only", ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(strength != NULL, "GPIO drive pointer error", ESP_ERR_INVALID_ARG);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
*strength = GET_PERI_REG_BITS2(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].drv_v, rtc_gpio_desc[gpio_num].drv_s);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
*strength = rtc_gpio_reg[gpio_num]->drv;
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -272,21 +353,45 @@ esp_err_t rtc_gpio_set_direction(gpio_num_t gpio_num, rtc_gpio_mode_t mode)
|
||||
|
||||
esp_err_t rtc_gpio_pullup_en(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//this is a digital pad
|
||||
if (rtc_gpio_desc[gpio_num].pullup == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#endif
|
||||
//this is a rtc pad
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].pullup);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
rtc_gpio_reg[gpio_num]->rue = 0x1;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
esp_err_t rtc_gpio_set_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t mode)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
RTCIO.pin[gpio_num].pad_driver = mode;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_get_output_mode(gpio_num_t gpio_num, rtc_io_out_mode_t *mode)
|
||||
{
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
*mode = RTCIO.pin[gpio_num].pad_driver;
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
|
||||
esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//this is a digital pad
|
||||
if (rtc_gpio_desc[gpio_num].pulldown == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -296,12 +401,17 @@ esp_err_t rtc_gpio_pulldown_en(gpio_num_t gpio_num)
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].pulldown);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
rtc_gpio_reg[gpio_num]->rde = 0x1;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//this is a digital pad
|
||||
if ( rtc_gpio_desc[gpio_num].pullup == 0 ) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -311,12 +421,17 @@ esp_err_t rtc_gpio_pullup_dis(gpio_num_t gpio_num)
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].pullup);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
rtc_gpio_reg[gpio_num]->rue = 0x0;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//this is a digital pad
|
||||
if (rtc_gpio_desc[gpio_num].pulldown == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -326,12 +441,17 @@ esp_err_t rtc_gpio_pulldown_dis(gpio_num_t gpio_num)
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].pulldown);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
rtc_gpio_reg[gpio_num]->rde = 0x0;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// check if an RTC IO
|
||||
if (rtc_gpio_desc[gpio_num].pullup == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -339,11 +459,18 @@ esp_err_t rtc_gpio_hold_en(gpio_num_t gpio_num)
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SET_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].hold);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
RTCCNTL.pad_hold.val |= BIT(gpio_num);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// check if an RTC IO
|
||||
if (rtc_gpio_desc[gpio_num].pullup == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -351,15 +478,24 @@ esp_err_t rtc_gpio_hold_dis(gpio_num_t gpio_num)
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
CLEAR_PERI_REG_MASK(rtc_gpio_desc[gpio_num].reg, rtc_gpio_desc[gpio_num].hold);
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
RTCCNTL.pad_hold.val &= ~(BIT(gpio_num));
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (rtc_gpio_desc[gpio_num].reg == 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
rtc_gpio_pullup_dis(gpio_num);
|
||||
rtc_gpio_pulldown_dis(gpio_num);
|
||||
rtc_gpio_set_direction(gpio_num, RTC_GPIO_MODE_DISABLED);
|
||||
@ -370,16 +506,23 @@ esp_err_t rtc_gpio_isolate(gpio_num_t gpio_num)
|
||||
|
||||
void rtc_gpio_force_hold_dis_all(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
for (int gpio = 0; gpio < GPIO_PIN_COUNT; ++gpio) {
|
||||
const rtc_gpio_desc_t* desc = &rtc_gpio_desc[gpio];
|
||||
if (desc->hold_force != 0) {
|
||||
REG_CLR_BIT(RTC_CNTL_HOLD_FORCE_REG, desc->hold_force);
|
||||
}
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
RTCCNTL.rtc_pwc.rtc_pad_force_hold = 0;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int rtc_num = rtc_gpio_desc[gpio_num].rtc_num;
|
||||
if (rtc_num < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -392,11 +535,21 @@ esp_err_t rtc_gpio_wakeup_enable(gpio_num_t gpio_num, gpio_int_type_t intr_type)
|
||||
/* each pin has its own register, spinlock not needed */
|
||||
REG_SET_BIT(reg, RTC_GPIO_PIN0_WAKEUP_ENABLE);
|
||||
REG_SET_FIELD(reg, RTC_GPIO_PIN0_INT_TYPE, intr_type);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
if (( intr_type != GPIO_INTR_LOW_LEVEL ) && ( intr_type != GPIO_INTR_HIGH_LEVEL )) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
/* each pin has its own register, spinlock not needed */
|
||||
RTCIO.pin[gpio_num].wakeup_enable = 1;
|
||||
RTCIO.pin[gpio_num].int_type = intr_type;
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int rtc_num = rtc_gpio_desc[gpio_num].rtc_num;
|
||||
if (rtc_num < 0) {
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
@ -406,10 +559,25 @@ esp_err_t rtc_gpio_wakeup_disable(gpio_num_t gpio_num)
|
||||
/* each pin has its own register, spinlock not needed */
|
||||
REG_CLR_BIT(reg, RTC_GPIO_PIN0_WAKEUP_ENABLE);
|
||||
REG_SET_FIELD(reg, RTC_GPIO_PIN0_INT_TYPE, 0);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
RTC_MODULE_CHECK(rtc_gpio_is_valid_gpio(gpio_num), "RTC_GPIO number error", ESP_ERR_INVALID_ARG);
|
||||
/* each pin has its own register, spinlock not needed */
|
||||
RTCIO.pin[gpio_num].wakeup_enable = 0;
|
||||
RTCIO.pin[gpio_num].int_type = 0;
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
esp_err_t rtc_gpio_force_hold_all()
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
RTCCNTL.rtc_pwc.rtc_pad_force_hold = 1;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
/*---------------------------------------------------------------
|
||||
Touch Pad
|
||||
---------------------------------------------------------------*/
|
||||
@ -429,10 +597,24 @@ inline static touch_pad_t touch_pad_num_wrap(touch_pad_t touch_num)
|
||||
return touch_num;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_isr_handler_register(void (*fn)(void *), void *arg, int no_use, intr_handle_t *handle_no_use)
|
||||
{
|
||||
RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
|
||||
#else
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_isr_register(intr_handler_t fn, void* arg)
|
||||
{
|
||||
RTC_MODULE_CHECK(fn, "Touch_Pad ISR null", ESP_ERR_INVALID_ARG);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return rtc_isr_register(fn, arg, RTC_CNTL_TOUCH_INT_ST_M);
|
||||
#else
|
||||
return ESP_FAIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_isr_deregister(intr_handler_t fn, void *arg)
|
||||
@ -560,7 +742,7 @@ esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, t
|
||||
ESP_ERR_INVALID_ARG);
|
||||
RTC_MODULE_CHECK(((atten < TOUCH_HVOLT_ATTEN_MAX) && (refh >= (int )TOUCH_HVOLT_ATTEN_KEEP)), "touch atten error",
|
||||
ESP_ERR_INVALID_ARG);
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (refh > TOUCH_HVOLT_KEEP) {
|
||||
RTCIO.touch_cfg.drefh = refh;
|
||||
@ -572,11 +754,13 @@ esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, t
|
||||
RTCIO.touch_cfg.drange = atten;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
if (refh) {
|
||||
*refh = RTCIO.touch_cfg.drefh;
|
||||
@ -588,6 +772,7 @@ esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl,
|
||||
*atten = RTCIO.touch_cfg.drange;
|
||||
}
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -774,9 +959,7 @@ uint32_t IRAM_ATTR touch_pad_get_status(void)
|
||||
|
||||
esp_err_t IRAM_ATTR touch_pad_clear_status(void)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
SENS.sar_touch_ctrl2.touch_meas_en_clr = 1;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -1043,13 +1226,28 @@ esp_err_t touch_pad_get_wakeup_status(touch_pad_t *pad_num)
|
||||
*pad_num = touch_pad_num_wrap((touch_pad_t)(__builtin_ffs(touch_mask) - 1));
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
/*---------------------------------------------------------------
|
||||
ADC Common
|
||||
---------------------------------------------------------------*/
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define SENS_FORCE_XPD_AMP_FSM 0 // Use FSM to control power down
|
||||
#define SENS_FORCE_XPD_AMP_PD 2 // Force power down
|
||||
#define SENS_FORCE_XPD_AMP_PU 3 // Force power up
|
||||
|
||||
#define SENS_SAR1_ATTEN_VAL_MASK 0x3
|
||||
#define SENS_SAR2_ATTEN_VAL_MASK 0x3
|
||||
|
||||
#define SENS_FORCE_XPD_SAR_SW_M (BIT(1))
|
||||
#define SENS_FORCE_XPD_SAR_FSM 0 // Use FSM to control power down
|
||||
#define SENS_FORCE_XPD_SAR_PD 2 // Force power down
|
||||
#define SENS_FORCE_XPD_SAR_PU 3 // Force power up
|
||||
#endif
|
||||
|
||||
static esp_err_t adc_set_fsm_time(int rst_wait, int start_wait, int standby_wait, int sample_cycle)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
// Internal FSM reset wait time
|
||||
if (rst_wait >= 0) {
|
||||
SYSCON.saradc_fsm.rstb_wait = rst_wait;
|
||||
@ -1062,6 +1260,20 @@ static esp_err_t adc_set_fsm_time(int rst_wait, int start_wait, int standby_wait
|
||||
if (standby_wait >= 0) {
|
||||
SYSCON.saradc_fsm.standby_wait = standby_wait;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
// Internal FSM reset wait time
|
||||
if (rst_wait >= 0) {
|
||||
SYSCON.saradc_fsm_wait.rstb_wait = rst_wait;
|
||||
}
|
||||
// Internal FSM start wait time
|
||||
if (start_wait >= 0) {
|
||||
SYSCON.saradc_fsm_wait.xpd_wait = start_wait;
|
||||
}
|
||||
// Internal FSM standby wait time
|
||||
if (standby_wait >= 0) {
|
||||
SYSCON.saradc_fsm_wait.standby_wait = standby_wait;
|
||||
}
|
||||
#endif
|
||||
// Internal FSM standby sample cycle
|
||||
if (sample_cycle >= 0) {
|
||||
SYSCON.saradc_fsm.sample_cycle = sample_cycle;
|
||||
@ -1140,13 +1352,18 @@ static esp_err_t adc_set_atten(adc_unit_t adc_unit, adc_channel_t channel, adc_a
|
||||
void adc_power_always_on(void)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
void adc_power_on(void)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//The power FSM controlled mode saves more power, while the ADC noise may get increased.
|
||||
#ifndef CONFIG_ADC_FORCE_XPD_FSM
|
||||
//Set the power always on to increase precision.
|
||||
@ -1158,6 +1375,20 @@ void adc_power_on(void)
|
||||
} else {
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
}
|
||||
#endif
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//The power FSM controlled mode saves more power, while the ADC noise may get increased.
|
||||
#ifndef CONFIG_ADC_FORCE_XPD_FSM
|
||||
//Set the power always on to increase precision.
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
#else
|
||||
//Use the FSM to turn off the power while not used to save power.
|
||||
if (SENS.sar_power_xpd_sar.force_xpd_sar & SENS_FORCE_XPD_SAR_SW_M) {
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
} else {
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_FSM;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
@ -1165,9 +1396,14 @@ void adc_power_on(void)
|
||||
void adc_power_off(void)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//Bit1 0:Fsm 1: SW mode
|
||||
//Bit0 0:SW mode power down 1: SW mode power on
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PD;
|
||||
#endif
|
||||
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
}
|
||||
|
||||
@ -1208,6 +1444,7 @@ esp_err_t adc_gpio_init(adc_unit_t adc_unit, adc_channel_t channel)
|
||||
esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
// Enable ADC data invert
|
||||
SENS.sar_read_ctrl.sar1_data_inv = inv_en;
|
||||
@ -1216,6 +1453,16 @@ esp_err_t adc_set_data_inv(adc_unit_t adc_unit, bool inv_en)
|
||||
// Enable ADC data invert
|
||||
SENS.sar_read_ctrl2.sar2_data_inv = inv_en;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
// Enable ADC data invert
|
||||
SENS.sar_reader1_ctrl.sar1_data_inv = inv_en;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
// Enable ADC data invert
|
||||
SENS.sar_reader2_ctrl.sar2_data_inv = inv_en;
|
||||
}
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -1225,6 +1472,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
ADC_CHECK_UNIT(adc_unit);
|
||||
RTC_MODULE_CHECK(bits < ADC_WIDTH_MAX, "ADC bit width error", ESP_ERR_INVALID_ARG);
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
SENS.sar_start_force.sar1_bit_width = bits;
|
||||
SENS.sar_read_ctrl.sar1_sample_bit = bits;
|
||||
@ -1233,6 +1481,16 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
SENS.sar_start_force.sar2_bit_width = bits;
|
||||
SENS.sar_read_ctrl2.sar2_sample_bit = bits;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (adc_unit & ADC_UNIT_1) {
|
||||
SENS.sar_meas1_ctrl1.sar1_bit_width = bits;
|
||||
SENS.sar_reader1_ctrl.sar1_sample_bit = bits;
|
||||
}
|
||||
if (adc_unit & ADC_UNIT_2) {
|
||||
SENS.sar_meas2_ctrl1.sar2_bit_width = bits;
|
||||
SENS.sar_reader2_ctrl.sar2_sample_bit = bits;
|
||||
}
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -1240,6 +1498,7 @@ esp_err_t adc_set_data_width(adc_unit_t adc_unit, adc_bits_width_t bits)
|
||||
// this function should be called in the critical section
|
||||
static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl )
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ( unit == ADC_UNIT_1 ) {
|
||||
switch( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
@ -1306,12 +1565,69 @@ static void adc_set_controller(adc_unit_t unit, adc_controller_t ctrl )
|
||||
ESP_LOGE(TAG, "invalid adc unit");
|
||||
assert(0);
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if ( unit == ADC_UNIT_1 ) {
|
||||
switch( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = false; //RTC controller controls the ADC, not digital controller
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
|
||||
SENS.sar_hall_ctrl.xpd_hall_force = true; // RTC controller controls the hall sensor power,not ulp coprocessor
|
||||
SENS.sar_hall_ctrl.hall_phase_force = true; // RTC controller controls the hall sensor phase,not ulp coprocessor
|
||||
break;
|
||||
case ADC_CTRL_ULP:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = false;
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = false;
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = false;
|
||||
SENS.sar_hall_ctrl.xpd_hall_force = false;
|
||||
SENS.sar_hall_ctrl.hall_phase_force = false;
|
||||
break;
|
||||
case ADC_CTRL_DIG:
|
||||
SENS.sar_meas1_mux.sar1_dig_force = true;
|
||||
SENS.sar_meas1_ctrl2.meas1_start_force = true;
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad_force = true;
|
||||
SENS.sar_hall_ctrl.xpd_hall_force = true;
|
||||
SENS.sar_hall_ctrl.hall_phase_force = true;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "adc1 selects invalid controller");
|
||||
break;
|
||||
}
|
||||
} else if ( unit == ADC_UNIT_2) {
|
||||
switch( ctrl ) {
|
||||
case ADC_CTRL_RTC:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = true; //RTC controller controls the ADC,not ulp coprocessor
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = true; //RTC controller controls the data port, not ulp coprocessor
|
||||
break;
|
||||
case ADC_CTRL_ULP:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = false;
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = false;
|
||||
break;
|
||||
case ADC_CTRL_DIG:
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = true;
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = true;
|
||||
break;
|
||||
case ADC2_CTRL_PWDET:
|
||||
//currently only used by Wi-Fi
|
||||
SENS.sar_meas2_ctrl2.meas2_start_force = true;
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad_force = true;
|
||||
break;
|
||||
default:
|
||||
ESP_LOGE(TAG, "adc2 selects invalid controller");
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ESP_LOGE(TAG, "invalid adc unit");
|
||||
assert(0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// this function should be called in the critical section
|
||||
static int adc_convert( adc_unit_t unit, int channel)
|
||||
{
|
||||
uint16_t adc_value;
|
||||
uint16_t adc_value = 0;
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ( unit == ADC_UNIT_1 ) {
|
||||
SENS.sar_meas_start1.sar1_en_pad = (1 << channel); //only one channel is selected.
|
||||
while (SENS.sar_slave_addr1.meas_status != 0);
|
||||
@ -1330,6 +1646,26 @@ static int adc_convert( adc_unit_t unit, int channel)
|
||||
ESP_LOGE(TAG, "invalid adc unit");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if ( unit == ADC_UNIT_1 ) {
|
||||
SENS.sar_meas1_ctrl2.sar1_en_pad = (1 << channel); //only one channel is selected.
|
||||
while (SENS.sar_slave_addr1.meas_status != 0);
|
||||
SENS.sar_meas1_ctrl2.meas1_start_sar = 0;
|
||||
SENS.sar_meas1_ctrl2.meas1_start_sar = 1;
|
||||
while (SENS.sar_meas1_ctrl2.meas1_done_sar == 0);
|
||||
adc_value = SENS.sar_meas1_ctrl2.meas1_data_sar;
|
||||
} else if ( unit == ADC_UNIT_2 ) {
|
||||
SENS.sar_meas2_ctrl2.sar2_en_pad = (1 << channel); //only one channel is selected.
|
||||
|
||||
SENS.sar_meas2_ctrl2.meas2_start_sar = 0; //start force 0
|
||||
SENS.sar_meas2_ctrl2.meas2_start_sar = 1; //start force 1
|
||||
while (SENS.sar_meas2_ctrl2.meas2_done_sar == 0) {}; //read done
|
||||
adc_value = SENS.sar_meas2_ctrl2.meas2_data_sar;
|
||||
} else {
|
||||
ESP_LOGE(TAG, "invalid adc unit");
|
||||
return ESP_ERR_INVALID_ARG;
|
||||
}
|
||||
#endif
|
||||
return adc_value;
|
||||
}
|
||||
|
||||
@ -1470,6 +1806,7 @@ esp_err_t adc1_config_width(adc_bits_width_t width_bit)
|
||||
|
||||
static inline void adc1_fsm_disable(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//channel is set in the convert function
|
||||
SENS.sar_meas_wait2.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
|
||||
//disable FSM, it's only used by the LNA.
|
||||
@ -1479,6 +1816,17 @@ static inline void adc1_fsm_disable(void)
|
||||
SENS.sar_meas_wait1.sar_amp_wait1 = 1;
|
||||
SENS.sar_meas_wait1.sar_amp_wait2 = 1;
|
||||
SENS.sar_meas_wait2.sar_amp_wait3 = 1;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//channel is set in the convert function
|
||||
SENS.sar_meas1_ctrl1.force_xpd_amp = SENS_FORCE_XPD_AMP_PD;
|
||||
//disable FSM, it's only used by the LNA.
|
||||
SENS.sar_amp_ctrl3.amp_rst_fb_fsm = 0;
|
||||
SENS.sar_amp_ctrl3.amp_short_ref_fsm = 0;
|
||||
SENS.sar_amp_ctrl3.amp_short_ref_gnd_fsm = 0;
|
||||
SENS.sar_amp_ctrl1.sar_amp_wait1 = 1;
|
||||
SENS.sar_amp_ctrl1.sar_amp_wait2 = 1;
|
||||
SENS.sar_amp_ctrl2.sar_amp_wait3 = 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
esp_err_t adc1_i2s_mode_acquire(void)
|
||||
@ -1488,9 +1836,15 @@ esp_err_t adc1_i2s_mode_acquire(void)
|
||||
_lock_acquire( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "i2s mode takes adc1 lock." );
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SENS.sar_meas_wait2.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
//switch SARADC into DIG channel
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 1;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SENS.sar_power_xpd_sar.force_xpd_sar = SENS_FORCE_XPD_SAR_PU;
|
||||
//switch SARADC into DIG channel
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 1;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -1500,13 +1854,18 @@ esp_err_t adc1_adc_mode_acquire(void)
|
||||
//lazy initialization
|
||||
//for adc1, block until acquire the lock
|
||||
_lock_acquire( &adc1_i2s_lock );
|
||||
ESP_LOGD( RTC_MODULE_TAG, "adc mode takes adc1 lock." );
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
// for now the WiFi would use ADC2 and set xpd_sar force on.
|
||||
// so we can not reset xpd_sar to fsm mode directly.
|
||||
// We should handle this after the synchronization mechanism is established.
|
||||
|
||||
//switch SARADC into RTC channel
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
SENS.sar_read_ctrl.sar1_dig_force = 0;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SENS.sar_meas1_mux.sar1_dig_force = 0;
|
||||
#endif
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -1654,6 +2013,7 @@ esp_err_t adc2_config_channel_atten(adc2_channel_t channel, adc_atten_t atten)
|
||||
static inline void adc2_config_width(adc_bits_width_t width_bit)
|
||||
{
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
//sar_start_force shared with ADC1
|
||||
SENS.sar_start_force.sar2_bit_width = width_bit;
|
||||
//cct set to the same value with PHY
|
||||
@ -1664,15 +2024,34 @@ static inline void adc2_config_width(adc_bits_width_t width_bit)
|
||||
SENS.sar_read_ctrl2.sar2_data_inv = 1;
|
||||
//Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3
|
||||
SENS.sar_read_ctrl2.sar2_sample_bit = width_bit;
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
//sar_start_force shared with ADC1
|
||||
SENS.sar_meas2_ctrl1.sar2_bit_width = width_bit;
|
||||
//cct set to the same value with PHY
|
||||
SENS.sar_meas2_mux.sar2_pwdet_cct = 4;
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
//Invert the adc value,the Output value is invert
|
||||
SENS.sar_reader2_ctrl.sar2_data_inv = 1;
|
||||
//Set The adc sample width,invert adc value,must digital sar2_bit_width[1:0]=3
|
||||
SENS.sar_reader2_ctrl.sar2_sample_bit = width_bit;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void adc2_dac_disable( adc2_channel_t channel)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ( channel == ADC2_CHANNEL_8 ) { // the same as DAC channel 1
|
||||
dac_output_set_enable( DAC_CHANNEL_1, false );
|
||||
} else if ( channel == ADC2_CHANNEL_9 ) {
|
||||
dac_output_set_enable( DAC_CHANNEL_2, false );
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if ( channel == ADC2_CHANNEL_6 ) { // the same as DAC channel 1
|
||||
dac_output_set_enable( DAC_CHANNEL_1, false );
|
||||
} else if ( channel == ADC2_CHANNEL_7 ) {
|
||||
dac_output_set_enable( DAC_CHANNEL_2, false );
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//registers in critical section with adc1:
|
||||
@ -1714,6 +2093,7 @@ esp_err_t adc2_get_raw(adc2_channel_t channel, adc_bits_width_t width_bit, int*
|
||||
|
||||
esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int channel;
|
||||
if(gpio == GPIO_NUM_25){
|
||||
channel = 8; //Channel 8 bit
|
||||
@ -1745,7 +2125,7 @@ esp_err_t adc2_vref_to_gpio(gpio_num_t gpio)
|
||||
SENS.sar_meas_start2.sar2_en_pad_force = 1; //Pad bitmap controlled by SW
|
||||
//set en_pad for channels 7,8,9 (bits 0x380)
|
||||
SENS.sar_meas_start2.sar2_en_pad = 1<<channel;
|
||||
|
||||
#endif
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
@ -1860,19 +2240,22 @@ esp_err_t dac_i2s_disable(void)
|
||||
|
||||
static inline void adc1_hall_enable(bool enable)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
RTCIO.hall_sens.xpd_hall = enable;
|
||||
#endif
|
||||
}
|
||||
|
||||
static int hall_sensor_get_value(void) //hall sensor without LNA
|
||||
{
|
||||
int hall_value = 0;
|
||||
|
||||
adc_power_on();
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int Sens_Vp0;
|
||||
int Sens_Vn0;
|
||||
int Sens_Vp1;
|
||||
int Sens_Vn1;
|
||||
int hall_value;
|
||||
|
||||
adc_power_on();
|
||||
|
||||
portENTER_CRITICAL(&rtc_spinlock);
|
||||
//disable other peripherals
|
||||
adc1_fsm_disable();//currently the LNA is not open, close it by default
|
||||
@ -1888,7 +2271,7 @@ static int hall_sensor_get_value(void) //hall sensor without LNA
|
||||
Sens_Vn1 = adc_convert( ADC_UNIT_1, ADC1_CHANNEL_3 );
|
||||
portEXIT_CRITICAL(&rtc_spinlock);
|
||||
hall_value = (Sens_Vp1 - Sens_Vp0) - (Sens_Vn1 - Sens_Vn0);
|
||||
|
||||
#endif
|
||||
return hall_value;
|
||||
}
|
||||
|
||||
|
@ -636,3 +636,4 @@ esp_err_t sdmmc_host_pullup_en(int slot, int width)
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
#include "sys/lock.h"
|
||||
#include "driver/sdmmc_types.h"
|
||||
#include "driver/sdmmc_defs.h"
|
||||
#include "driver/sdmmc_host.h"
|
||||
#include "driver/sdmmc_types.h"
|
||||
#include "sdspi_private.h"
|
||||
#include "sdspi_crc.h"
|
||||
|
||||
|
@ -14,9 +14,9 @@
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
@ -55,6 +55,9 @@ typedef struct spi_device_t spi_device_t;
|
||||
|
||||
//Periph 1 is 'claimed' by SPI flash code.
|
||||
static atomic_bool spi_periph_claimed[SOC_SPI_PERIPH_NUM] = { ATOMIC_VAR_INIT(true), ATOMIC_VAR_INIT(false), ATOMIC_VAR_INIT(false),
|
||||
#if SOC_SPI_PERIPH_NUM >= 4
|
||||
ATOMIC_VAR_INIT(false),
|
||||
#endif
|
||||
};
|
||||
static const char* spi_claiming_func[3] = {NULL, NULL, NULL};
|
||||
static uint8_t spi_dma_chan_enabled = 0;
|
||||
@ -102,7 +105,20 @@ int spicommon_irqdma_source_for_host(spi_host_device_t host)
|
||||
|
||||
static inline uint32_t get_dma_periph(int dma_chan)
|
||||
{
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (dma_chan==1) {
|
||||
return PERIPH_SPI2_DMA_MODULE;
|
||||
} else if (dma_chan==2) {
|
||||
return PERIPH_SPI3_DMA_MODULE;
|
||||
} else if (dma_chan==3) {
|
||||
return PERIPH_SPI_SHARED_DMA_MODULE;
|
||||
} else {
|
||||
abort();
|
||||
return -1;
|
||||
}
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32)
|
||||
return PERIPH_SPI_DMA_MODULE;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool spicommon_dma_chan_claim (int dma_chan)
|
||||
@ -116,7 +132,18 @@ bool spicommon_dma_chan_claim (int dma_chan)
|
||||
spi_dma_chan_enabled |= DMA_CHANNEL_ENABLED(dma_chan);
|
||||
ret = true;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
periph_module_enable(get_dma_periph(dma_chan));
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (dma_chan==1) {
|
||||
periph_module_enable(PERIPH_SPI2_DMA_MODULE);
|
||||
} else if (dma_chan==2) {
|
||||
periph_module_enable(PERIPH_SPI3_DMA_MODULE);
|
||||
} else if (dma_chan==3) {
|
||||
periph_module_enable(PERIPH_SPI_SHARED_DMA_MODULE);
|
||||
}
|
||||
#endif
|
||||
portEXIT_CRITICAL(&spi_dma_spinlock);
|
||||
|
||||
return ret;
|
||||
@ -135,10 +162,20 @@ bool spicommon_dma_chan_free(int dma_chan)
|
||||
|
||||
portENTER_CRITICAL(&spi_dma_spinlock);
|
||||
spi_dma_chan_enabled &= ~DMA_CHANNEL_ENABLED(dma_chan);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
if ( spi_dma_chan_enabled == 0 ) {
|
||||
//disable the DMA only when all the channels are freed.
|
||||
periph_module_disable(get_dma_periph(dma_chan));
|
||||
}
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
if (dma_chan==1) {
|
||||
periph_module_disable(PERIPH_SPI2_DMA_MODULE);
|
||||
} else if (dma_chan==2) {
|
||||
periph_module_disable(PERIPH_SPI3_DMA_MODULE);
|
||||
} else if (dma_chan==3) {
|
||||
periph_module_disable(PERIPH_SPI_SHARED_DMA_MODULE);
|
||||
}
|
||||
#endif
|
||||
portEXIT_CRITICAL(&spi_dma_spinlock);
|
||||
|
||||
return true;
|
||||
@ -238,23 +275,43 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
|
||||
ESP_LOGD(SPI_TAG, "SPI%d use iomux pins.", host+1);
|
||||
if (bus_config->mosi_io_num >= 0) {
|
||||
gpio_iomux_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
gpio_iomux_out(bus_config->mosi_io_num, spi_periph_signal[host].func, false);
|
||||
#endif
|
||||
}
|
||||
if (bus_config->miso_io_num >= 0) {
|
||||
gpio_iomux_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
gpio_iomux_out(bus_config->miso_io_num, spi_periph_signal[host].func, false);
|
||||
#endif
|
||||
}
|
||||
if (bus_config->quadwp_io_num >= 0) {
|
||||
gpio_iomux_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
gpio_iomux_out(bus_config->quadwp_io_num, spi_periph_signal[host].func, false);
|
||||
#endif
|
||||
}
|
||||
if (bus_config->quadhd_io_num >= 0) {
|
||||
gpio_iomux_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
gpio_iomux_out(bus_config->quadhd_io_num, spi_periph_signal[host].func, false);
|
||||
#endif
|
||||
}
|
||||
if (bus_config->sclk_io_num >= 0) {
|
||||
gpio_iomux_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
gpio_iomux_out(bus_config->sclk_io_num, spi_periph_signal[host].func, false);
|
||||
#endif
|
||||
}
|
||||
temp_flag |= SPICOMMON_BUSFLAG_IOMUX_PINS;
|
||||
} else {
|
||||
@ -268,6 +325,9 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
|
||||
gpio_set_direction(bus_config->mosi_io_num, GPIO_MODE_INPUT);
|
||||
}
|
||||
gpio_matrix_in(bus_config->mosi_io_num, spi_periph_signal[host].spid_in, false);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->mosi_io_num]);
|
||||
#endif
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->mosi_io_num], FUNC_GPIO);
|
||||
}
|
||||
if (bus_config->miso_io_num >= 0) {
|
||||
@ -278,18 +338,27 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
|
||||
gpio_set_direction(bus_config->miso_io_num, GPIO_MODE_INPUT);
|
||||
}
|
||||
gpio_matrix_in(bus_config->miso_io_num, spi_periph_signal[host].spiq_in, false);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->miso_io_num]);
|
||||
#endif
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->miso_io_num], FUNC_GPIO);
|
||||
}
|
||||
if (bus_config->quadwp_io_num >= 0) {
|
||||
gpio_set_direction(bus_config->quadwp_io_num, GPIO_MODE_INPUT_OUTPUT);
|
||||
gpio_matrix_out(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_out, false, false);
|
||||
gpio_matrix_in(bus_config->quadwp_io_num, spi_periph_signal[host].spiwp_in, false);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num]);
|
||||
#endif
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadwp_io_num], FUNC_GPIO);
|
||||
}
|
||||
if (bus_config->quadhd_io_num >= 0) {
|
||||
gpio_set_direction(bus_config->quadhd_io_num, GPIO_MODE_INPUT_OUTPUT);
|
||||
gpio_matrix_out(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_out, false, false);
|
||||
gpio_matrix_in(bus_config->quadhd_io_num, spi_periph_signal[host].spihd_in, false);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num]);
|
||||
#endif
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->quadhd_io_num], FUNC_GPIO);
|
||||
}
|
||||
if (bus_config->sclk_io_num >= 0) {
|
||||
@ -300,12 +369,21 @@ esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_conf
|
||||
gpio_set_direction(bus_config->sclk_io_num, GPIO_MODE_INPUT);
|
||||
}
|
||||
gpio_matrix_in(bus_config->sclk_io_num, spi_periph_signal[host].spiclk_in, false);
|
||||
#if CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[bus_config->sclk_io_num]);
|
||||
#endif
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[bus_config->sclk_io_num], FUNC_GPIO);
|
||||
}
|
||||
}
|
||||
|
||||
//Select DMA channel.
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 3, dma_chan, (host * 2));
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2BETA)
|
||||
if (dma_chan==VSPI_HOST) {
|
||||
DPORT_SET_PERI_REG_MASK(DPORT_SPI_DMA_CHAN_SEL_REG, DPORT_SPI_SHARED_DMA_SEL_M);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (flags_o) *flags_o = temp_flag;
|
||||
return ESP_OK;
|
||||
@ -332,7 +410,11 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
|
||||
if (!force_gpio_matrix && cs_io_num == spi_periph_signal[host].spics0_iomux_pin && cs_num == 0) {
|
||||
//The cs0s for all SPI peripherals map to pin mux source 1, so we use that instead of a define.
|
||||
gpio_iomux_in(cs_io_num, spi_periph_signal[host].spics_in);
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
gpio_iomux_out(cs_io_num, spi_periph_signal[host].func, false);
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
gpio_iomux_out(cs_io_num, spi_periph_signal[host].func, false);
|
||||
#endif
|
||||
} else {
|
||||
//Use GPIO matrix
|
||||
if (GPIO_IS_VALID_OUTPUT_GPIO(cs_io_num)) {
|
||||
@ -342,6 +424,7 @@ void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num,
|
||||
gpio_set_direction(cs_io_num, GPIO_MODE_INPUT);
|
||||
}
|
||||
if (cs_num == 0) gpio_matrix_in(cs_io_num, spi_periph_signal[host].spics_in, false);
|
||||
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[cs_io_num]);
|
||||
PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[cs_io_num], FUNC_GPIO);
|
||||
}
|
||||
}
|
||||
@ -366,16 +449,17 @@ bool spicommon_bus_using_iomux(spi_host_device_t host)
|
||||
/*
|
||||
Code for workaround for DMA issue in ESP32 v0/v1 silicon
|
||||
*/
|
||||
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
static volatile int dmaworkaround_channels_busy[2] = {0, 0};
|
||||
static dmaworkaround_cb_t dmaworkaround_cb;
|
||||
static void *dmaworkaround_cb_arg;
|
||||
static portMUX_TYPE dmaworkaround_mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
static int dmaworkaround_waiting_for_chan = 0;
|
||||
#endif
|
||||
|
||||
bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
int otherchan = (dmachan == 1) ? 2 : 1;
|
||||
bool ret;
|
||||
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
@ -392,15 +476,24 @@ bool IRAM_ATTR spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
return ret;
|
||||
#else
|
||||
//no need to reset
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool IRAM_ATTR spicommon_dmaworkaround_reset_in_progress(void)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
return (dmaworkaround_waiting_for_chan != 0);
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
dmaworkaround_channels_busy[dmachan-1] = 0;
|
||||
if (dmaworkaround_waiting_for_chan == dmachan) {
|
||||
@ -412,13 +505,14 @@ void IRAM_ATTR spicommon_dmaworkaround_idle(int dmachan)
|
||||
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
#endif
|
||||
}
|
||||
|
||||
void IRAM_ATTR spicommon_dmaworkaround_transfer_active(int dmachan)
|
||||
{
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
portENTER_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
dmaworkaround_channels_busy[dmachan-1] = 1;
|
||||
portEXIT_CRITICAL_ISR(&dmaworkaround_mux);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
@ -122,7 +122,6 @@ We have two bits to control the interrupt:
|
||||
#include "driver/spi_common_internal.h"
|
||||
#include "driver/spi_master.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
@ -134,12 +133,10 @@ We have two bits to control the interrupt:
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp32/rom/lldesc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "stdatomic.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "hal/spi_hal.h"
|
||||
|
||||
typedef struct spi_device_t spi_device_t;
|
||||
@ -221,7 +218,11 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
|
||||
SPI_CHECK(host!=SPI_HOST, "SPI1 is not supported", ESP_ERR_NOT_SUPPORTED);
|
||||
|
||||
SPI_CHECK(host>=SPI_HOST && host<=VSPI_HOST, "invalid host", ESP_ERR_INVALID_ARG);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG );
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
SPI_CHECK( dma_chan == 0 || dma_chan == host, "invalid dma channel", ESP_ERR_INVALID_ARG );
|
||||
#endif
|
||||
SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH|ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_INTRDISABLED))==0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
|
||||
#ifndef CONFIG_SPI_MASTER_ISR_IN_IRAM
|
||||
SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM)==0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_MASTER_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
|
||||
@ -245,6 +246,7 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
|
||||
}
|
||||
memset(spihost[host], 0, sizeof(spi_host_t));
|
||||
memcpy( &spihost[host]->bus_cfg, bus_config, sizeof(spi_bus_config_t));
|
||||
|
||||
#ifdef CONFIG_PM_ENABLE
|
||||
err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "spi_master",
|
||||
&spihost[host]->pm_lock);
|
||||
@ -259,7 +261,6 @@ esp_err_t spi_bus_initialize(spi_host_device_t host, const spi_bus_config_t *bus
|
||||
ret = err;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
int dma_desc_ct=0;
|
||||
spihost[host]->dma_chan=dma_chan;
|
||||
if (dma_chan == 0) {
|
||||
@ -379,10 +380,12 @@ esp_err_t spi_bus_add_device(spi_host_device_t host, const spi_device_interface_
|
||||
if (atomic_compare_exchange_strong(&spihost[host]->device[freecs], &null, (spi_device_t *)1)) break;
|
||||
}
|
||||
SPI_CHECK(freecs!=NO_CS, "no free cs pins for host", ESP_ERR_NOT_FOUND);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
//The hardware looks like it would support this, but actually setting cs_ena_pretrans when transferring in full
|
||||
//duplex mode does absolutely nothing on the ESP32.
|
||||
SPI_CHECK( dev_config->cs_ena_pretrans <= 1 || (dev_config->address_bits == 0 && dev_config->command_bits == 0) ||
|
||||
(dev_config->flags & SPI_DEVICE_HALFDUPLEX), "In full-duplex mode, only support cs pretrans delay = 1 and without address_bits and command_bits", ESP_ERR_INVALID_ARG);
|
||||
#endif
|
||||
|
||||
duty_cycle = (dev_config->duty_cycle_pos==0) ? 128 : dev_config->duty_cycle_pos;
|
||||
|
||||
@ -804,8 +807,12 @@ static SPI_MASTER_ISR_ATTR esp_err_t check_trans_valid(spi_device_handle_t handl
|
||||
//check working mode
|
||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (handle->cfg.flags & SPI_DEVICE_3WIRE)), "incompatible iface params", ESP_ERR_INVALID_ARG);
|
||||
SPI_CHECK(!((trans_desc->flags & (SPI_TRANS_MODE_DIO|SPI_TRANS_MODE_QIO)) && (!(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX))), "incompatible iface params", ESP_ERR_INVALID_ARG);
|
||||
#ifdef CONFIG_IDF_TARGET_ESP32
|
||||
SPI_CHECK( !(handle->cfg.flags & SPI_DEVICE_HALFDUPLEX) || host->dma_chan == 0 || !(trans_desc->flags & SPI_TRANS_USE_RXDATA || trans_desc->rx_buffer != NULL)
|
||||
|| !(trans_desc->flags & SPI_TRANS_USE_TXDATA || trans_desc->tx_buffer!=NULL), "SPI half duplex mode does not support using DMA with both MOSI and MISO phases.", ESP_ERR_INVALID_ARG );
|
||||
#else
|
||||
(void)host;
|
||||
#endif
|
||||
//MOSI phase is skipped only when both tx_buffer and SPI_TRANS_USE_TXDATA are not set.
|
||||
SPI_CHECK(trans_desc->length != 0 || (trans_desc->tx_buffer == NULL && !(trans_desc->flags & SPI_TRANS_USE_TXDATA)),
|
||||
"trans tx_buffer should be NULL and SPI_TRANS_USE_TXDATA should be cleared to skip MOSI phase.", ESP_ERR_INVALID_ARG);
|
||||
@ -1086,4 +1093,3 @@ esp_err_t SPI_MASTER_ISR_ATTR spi_device_polling_transmit(spi_device_handle_t ha
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
|
||||
|
@ -13,13 +13,13 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <string.h>
|
||||
#include "sdkconfig.h"
|
||||
#include <hal/spi_ll.h>
|
||||
#include <hal/spi_slave_hal.h>
|
||||
#include <soc/lldesc.h>
|
||||
#include "driver/spi_common_internal.h"
|
||||
#include "driver/spi_slave.h"
|
||||
#include "soc/spi_periph.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "esp_types.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_intr_alloc.h"
|
||||
@ -31,7 +31,6 @@
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "esp32/rom/lldesc.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "esp_heap_caps.h"
|
||||
|
||||
@ -104,7 +103,11 @@ esp_err_t spi_slave_initialize(spi_host_device_t host, const spi_bus_config_t *b
|
||||
esp_err_t err;
|
||||
//We only support HSPI/VSPI, period.
|
||||
SPI_CHECK(VALID_HOST(host), "invalid host", ESP_ERR_INVALID_ARG);
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32)
|
||||
SPI_CHECK( dma_chan >= 0 && dma_chan <= 2, "invalid dma channel", ESP_ERR_INVALID_ARG );
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S2BETA)
|
||||
SPI_CHECK( dma_chan == 0 || dma_chan == host, "invalid dma channel", ESP_ERR_INVALID_ARG );
|
||||
#endif
|
||||
SPI_CHECK((bus_config->intr_flags & (ESP_INTR_FLAG_HIGH|ESP_INTR_FLAG_EDGE|ESP_INTR_FLAG_INTRDISABLED))==0, "intr flag not allowed", ESP_ERR_INVALID_ARG);
|
||||
#ifndef CONFIG_SPI_SLAVE_ISR_IN_IRAM
|
||||
SPI_CHECK((bus_config->intr_flags & ESP_INTR_FLAG_IRAM)==0, "ESP_INTR_FLAG_IRAM should be disabled when CONFIG_SPI_SLAVE_ISR_IN_IRAM is not set.", ESP_ERR_INVALID_ARG);
|
||||
@ -394,4 +397,3 @@ static void SPI_SLAVE_ISR_ATTR spi_intr(void *arg)
|
||||
if (do_yield) portYIELD_FROM_ISR();
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
idf_component_register(SRC_DIRS "." "param_test"
|
||||
INCLUDE_DIRS "include" "param_test/include"
|
||||
REQUIRES unity test_utils driver nvs_flash)
|
||||
set(srcdirs . param_test)
|
||||
if(IDF_TARGET STREQUAL "esp32")
|
||||
list(APPEND srcdirs "esp32")
|
||||
endif()
|
||||
|
||||
idf_component_register(SRC_DIRS ${srcdirs}
|
||||
INCLUDE_DIRS include param_test/include
|
||||
REQUIRES unity test_utils driver nvs_flash
|
||||
)
|
||||
|
@ -2,6 +2,7 @@
|
||||
#Component Makefile
|
||||
#
|
||||
|
||||
COMPONENT_SRCDIRS += esp32
|
||||
COMPONENT_SRCDIRS += param_test
|
||||
COMPONENT_PRIV_INCLUDEDIRS += param_test/include
|
||||
|
||||
|
@ -4,7 +4,7 @@
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "esp32/rom/uart.h"
|
||||
|
||||
#include "esp_system.h"
|
||||
#include "esp_sleep.h"
|
||||
#include "unity.h"
|
||||
@ -12,6 +12,13 @@
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/queue.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/uart.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#include "esp32s2beta/rom/uart.h"
|
||||
#endif
|
||||
|
||||
#define WAKE_UP_IGNORE 1 // gpio_wakeup function development is not completed yet, set it deprecated.
|
||||
#define GPIO_OUTPUT_IO 18 // default output GPIO
|
356
components/driver/test/esp32/test_i2c.c
Normal file
356
components/driver/test/esp32/test_i2c.c
Normal file
@ -0,0 +1,356 @@
|
||||
/**
|
||||
* test environment UT_T2_I2C:
|
||||
* please prepare two ESP32-WROVER-KIT board.
|
||||
* Then connect GPIO18 and GPIO18, GPIO19 and GPIO19 between these two boards.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "unity.h"
|
||||
#include "test_utils.h"
|
||||
#include "unity_config.h"
|
||||
#include "driver/i2c.h"
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "soc/i2c_periph.h"
|
||||
#include "esp_system.h"
|
||||
#include "driver/pcnt.h"
|
||||
|
||||
|
||||
#define DATA_LENGTH 512 /*!<Data buffer length for test buffer*/
|
||||
#define RW_TEST_LENGTH 129 /*!<Data length for r/w test, any value from 0-DATA_LENGTH*/
|
||||
#define DELAY_TIME_BETWEEN_ITEMS_MS 1234 /*!< delay time between different test items */
|
||||
|
||||
#define I2C_SLAVE_SCL_IO 19 /*!<gpio number for i2c slave clock */
|
||||
#define I2C_SLAVE_SDA_IO 18 /*!<gpio number for i2c slave data */
|
||||
#define I2C_SLAVE_NUM I2C_NUM_0 /*!<I2C port number for slave dev */
|
||||
#define I2C_SLAVE_TX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave tx buffer size */
|
||||
#define I2C_SLAVE_RX_BUF_LEN (2*DATA_LENGTH) /*!<I2C slave rx buffer size */
|
||||
|
||||
#define I2C_MASTER_SCL_IO 19 /*!< gpio number for I2C master clock */
|
||||
#define I2C_MASTER_SDA_IO 18 /*!< gpio number for I2C master data */
|
||||
#define I2C_MASTER_NUM I2C_NUM_1 /*!< I2C port number for master dev */
|
||||
#define I2C_MASTER_TX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||
#define I2C_MASTER_RX_BUF_DISABLE 0 /*!< I2C master do not need buffer */
|
||||
#define I2C_MASTER_FREQ_HZ 100000 /*!< I2C master clock frequency */
|
||||
|
||||
#define ESP_SLAVE_ADDR 0x28 /*!< ESP32 slave address, you can set any 7bit value */
|
||||
#define WRITE_BIT I2C_MASTER_WRITE /*!< I2C master write */
|
||||
#define READ_BIT I2C_MASTER_READ /*!< I2C master read */
|
||||
#define ACK_CHECK_EN 0x1 /*!< I2C master will check ack from slave*/
|
||||
#define ACK_CHECK_DIS 0x0 /*!< I2C master will not check ack from slave */
|
||||
#define ACK_VAL 0x0 /*!< I2C ack value */
|
||||
#define NACK_VAL 0x1 /*!< I2C nack value */
|
||||
|
||||
#define PULSE_IO 19
|
||||
#define PCNT_INPUT_IO 4
|
||||
#define PCNT_CTRL_FLOATING_IO 5
|
||||
#define HIGHEST_LIMIT 10000
|
||||
#define LOWEST_LIMIT -10000
|
||||
|
||||
|
||||
static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, size_t size)
|
||||
{
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
TEST_ESP_OK(i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | WRITE_BIT, ACK_CHECK_EN));
|
||||
TEST_ESP_OK(i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN));
|
||||
TEST_ESP_OK(i2c_master_stop(cmd));
|
||||
esp_err_t ret = i2c_master_cmd_begin(i2c_num, cmd, 5000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static i2c_config_t i2c_master_init(void)
|
||||
{
|
||||
i2c_config_t conf_master = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = I2C_MASTER_FREQ_HZ,
|
||||
.sda_io_num = I2C_MASTER_SDA_IO,
|
||||
.scl_io_num = I2C_MASTER_SCL_IO,
|
||||
};
|
||||
return conf_master;
|
||||
}
|
||||
|
||||
// print the reading buffer
|
||||
static void disp_buf(uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
printf("%02x ", buf[i]);
|
||||
if (( i + 1 ) % 16 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static i2c_config_t i2c_slave_init(void)
|
||||
{
|
||||
i2c_config_t conf_slave = {
|
||||
.mode = I2C_MODE_SLAVE,
|
||||
.sda_io_num = I2C_SLAVE_SDA_IO,
|
||||
.scl_io_num = I2C_SLAVE_SCL_IO,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.slave.addr_10bit_en = 0,
|
||||
.slave.slave_addr = ESP_SLAVE_ADDR,
|
||||
};
|
||||
return conf_slave;
|
||||
}
|
||||
|
||||
static void i2c_master_write_test(void)
|
||||
{
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int i;
|
||||
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
|
||||
unity_send_signal("master write");
|
||||
for (i = 0; i < DATA_LENGTH / 2; i++) {
|
||||
data_wr[i] = i;
|
||||
}
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, DATA_LENGTH / 2);
|
||||
disp_buf(data_wr, i + 1);
|
||||
free(data_wr);
|
||||
unity_wait_for_signal("ready to delete");
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM));
|
||||
}
|
||||
|
||||
static void i2c_slave_read_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int size_rd = 0;
|
||||
int len = 0;
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
|
||||
unity_wait_for_signal("master write");
|
||||
while (1) {
|
||||
len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, DATA_LENGTH, 10000 / portTICK_RATE_MS);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
size_rd += len;
|
||||
}
|
||||
disp_buf(data_rd, size_rd);
|
||||
for (int i = 0; i < size_rd; i++) {
|
||||
TEST_ASSERT(data_rd[i] == i);
|
||||
}
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C master write slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_test, i2c_slave_read_test);
|
||||
|
||||
static void master_read_slave_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
memset(data_rd, 0, DATA_LENGTH);
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||
|
||||
unity_send_signal("slave write");
|
||||
unity_wait_for_signal("master read");
|
||||
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH-1, ACK_VAL);
|
||||
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH-1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
printf("%d\n", data_rd[i]);
|
||||
TEST_ASSERT(data_rd[i]==i);
|
||||
}
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
static void slave_write_buffer_test(void)
|
||||
{
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int size_rd;
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
|
||||
unity_wait_for_signal("slave write");
|
||||
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
||||
data_wr[i] = i;
|
||||
}
|
||||
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
||||
disp_buf(data_wr, size_rd);
|
||||
unity_send_signal("master read");
|
||||
unity_wait_for_signal("ready to delete");
|
||||
free(data_wr);
|
||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C master read slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", master_read_slave_test, slave_write_buffer_test);
|
||||
|
||||
static void i2c_master_write_read_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
memset(data_rd, 0, DATA_LENGTH);
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||
|
||||
unity_send_signal("slave write");
|
||||
unity_wait_for_signal("master read and write");
|
||||
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH, ACK_VAL);
|
||||
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
disp_buf(data_rd, RW_TEST_LENGTH);
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
TEST_ASSERT(data_rd[i] == i/2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||
data_wr[i] = i % 3;
|
||||
}
|
||||
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||
free(data_wr);
|
||||
free(data_rd);
|
||||
unity_send_signal("slave read");
|
||||
unity_wait_for_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
static void i2c_slave_read_write_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
memset(data_rd, 0, DATA_LENGTH);
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int size_rd;
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
unity_wait_for_signal("slave write");
|
||||
|
||||
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
||||
data_wr[i] = i/2;
|
||||
}
|
||||
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
||||
disp_buf(data_wr, size_rd);
|
||||
unity_send_signal("master read and write");
|
||||
unity_wait_for_signal("slave read");
|
||||
size_rd = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
|
||||
printf("slave read data is:\n");
|
||||
disp_buf(data_rd, size_rd);
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
TEST_ASSERT(data_rd[i] == i % 3);
|
||||
}
|
||||
free(data_wr);
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C read and write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_read_test, i2c_slave_read_write_test);
|
||||
|
||||
static void i2c_master_repeat_write(void)
|
||||
{
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int times = 3;
|
||||
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
|
||||
for (int j = 0; j < times; j++) {
|
||||
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||
data_wr[i] = j + i;
|
||||
}
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||
disp_buf(data_wr, RW_TEST_LENGTH);
|
||||
}
|
||||
free(data_wr);
|
||||
unity_send_signal("master write");
|
||||
unity_wait_for_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
static void i2c_slave_repeat_read(void)
|
||||
{
|
||||
int size_rd = 0;
|
||||
int times = 3;
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH * 3);
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
unity_wait_for_signal("master write");
|
||||
|
||||
while (1) {
|
||||
int len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, RW_TEST_LENGTH * 3, 10000 / portTICK_RATE_MS);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
size_rd += len;
|
||||
}
|
||||
disp_buf(data_rd, size_rd);
|
||||
for (int j = 0; j < times; j++) {
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
printf("data: %d, %d\n", data_rd[j * RW_TEST_LENGTH + i], (i % 129 + j));
|
||||
TEST_ASSERT(data_rd[j * RW_TEST_LENGTH + i] == (i % 129 + j));
|
||||
}
|
||||
}
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read);
|
@ -13,7 +13,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
@ -22,7 +22,6 @@
|
||||
#include "esp_log.h"
|
||||
#include "soc/gpio_periph.h"
|
||||
#include "unity.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#define PULSE_IO 18
|
||||
#define PCNT_INPUT_IO 4
|
@ -25,7 +25,6 @@
|
||||
#include "esp_attr.h"
|
||||
#include "esp_log.h"
|
||||
#include "soc/rtc.h"
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
|
||||
#define GPIO_PWMA_OUT 4
|
||||
#define GPIO_PWMB_OUT 13
|
281
components/driver/test/esp32/test_rs485.c
Normal file
281
components/driver/test/esp32/test_rs485.c
Normal file
@ -0,0 +1,281 @@
|
||||
/* This file is from test_uart.c, but mainly about RS485 */
|
||||
|
||||
|
||||
#include <string.h>
|
||||
#include <sys/param.h>
|
||||
#include "unity.h"
|
||||
#include "test_utils.h" // unity_send_signal
|
||||
#include "driver/uart.h" // for the uart driver access
|
||||
#include "esp_log.h"
|
||||
#include "esp_system.h" // for uint32_t esp_random()
|
||||
|
||||
#define UART_TAG "Uart"
|
||||
#define UART_NUM1 (UART_NUM_1)
|
||||
#define BUF_SIZE (100)
|
||||
#define UART1_RX_PIN (22)
|
||||
#define UART1_TX_PIN (23)
|
||||
#define UART_BAUD_11520 (11520)
|
||||
#define UART_BAUD_115200 (115200)
|
||||
#define TOLERANCE (0.02) //baud rate error tolerance 2%.
|
||||
|
||||
#define UART_TOLERANCE_CHECK(val, uper_limit, lower_limit) ( (val) <= (uper_limit) && (val) >= (lower_limit) )
|
||||
|
||||
// RTS for RS485 Half-Duplex Mode manages DE/~RE
|
||||
#define UART1_RTS_PIN (18)
|
||||
|
||||
// Number of packets to be send during test
|
||||
#define PACKETS_NUMBER (10)
|
||||
|
||||
// Wait timeout for uart driver
|
||||
#define PACKET_READ_TICS (1000 / portTICK_RATE_MS)
|
||||
|
||||
// The table for fast CRC16 calculation
|
||||
static const uint8_t crc_hi[] = {
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81,
|
||||
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81,
|
||||
0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x01,
|
||||
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01,
|
||||
0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81,
|
||||
0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80,
|
||||
0x41, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01,
|
||||
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00,
|
||||
0xC1, 0x81, 0x40,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81,
|
||||
0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
||||
0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1,
|
||||
0x81, 0x40, 0x01,
|
||||
0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
||||
0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81,
|
||||
0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81,
|
||||
0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0,
|
||||
0x80, 0x41, 0x01,
|
||||
0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01,
|
||||
0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
|
||||
0x00, 0xC1, 0x81,
|
||||
0x40
|
||||
};
|
||||
|
||||
static const uint8_t crc_low[] = {
|
||||
0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
|
||||
0x05, 0xC5, 0xC4,
|
||||
0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB,
|
||||
0x0B, 0xC9, 0x09,
|
||||
0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE,
|
||||
0xDF, 0x1F, 0xDD,
|
||||
0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2,
|
||||
0x12, 0x13, 0xD3,
|
||||
0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
|
||||
0x36, 0xF6, 0xF7,
|
||||
0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E,
|
||||
0xFE, 0xFA, 0x3A,
|
||||
0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B,
|
||||
0x2A, 0xEA, 0xEE,
|
||||
0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27,
|
||||
0xE7, 0xE6, 0x26,
|
||||
0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
|
||||
0x63, 0xA3, 0xA2,
|
||||
0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD,
|
||||
0x6D, 0xAF, 0x6F,
|
||||
0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8,
|
||||
0xB9, 0x79, 0xBB,
|
||||
0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4,
|
||||
0x74, 0x75, 0xB5,
|
||||
0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
|
||||
0x50, 0x90, 0x91,
|
||||
0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94,
|
||||
0x54, 0x9C, 0x5C,
|
||||
0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59,
|
||||
0x58, 0x98, 0x88,
|
||||
0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D,
|
||||
0x4D, 0x4C, 0x8C,
|
||||
0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
|
||||
0x41, 0x81, 0x80,
|
||||
0x40
|
||||
};
|
||||
|
||||
|
||||
// Calculate buffer checksum using tables
|
||||
// The checksum CRC16 algorithm is specific
|
||||
// for Modbus standard and uses polynomial value = 0xA001
|
||||
static uint16_t get_buffer_crc16( uint8_t * frame_ptr, uint16_t length )
|
||||
{
|
||||
TEST_ASSERT( frame_ptr != NULL);
|
||||
|
||||
uint8_t crc_hi_byte = 0xFF;
|
||||
uint8_t crc_low_byte = 0xFF;
|
||||
int index;
|
||||
|
||||
while ( length-- )
|
||||
{
|
||||
index = crc_low_byte ^ *(frame_ptr++);
|
||||
crc_low_byte = crc_hi_byte ^ crc_hi[index];
|
||||
crc_hi_byte = crc_low[index];
|
||||
}
|
||||
return ((crc_hi_byte << 8) | crc_low_byte);
|
||||
}
|
||||
|
||||
// Fill the buffer with random numbers and apply CRC16 at the end
|
||||
static uint16_t buffer_fill_random(uint8_t *buffer, size_t length)
|
||||
{
|
||||
TEST_ASSERT( buffer != NULL);
|
||||
// Packet is too short
|
||||
if (length < 4) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < length; i += 4) {
|
||||
uint32_t random = esp_random();
|
||||
memcpy(buffer + i, &random, MIN(length - i, 4));
|
||||
}
|
||||
// Get checksum of the buffer
|
||||
uint16_t crc = get_buffer_crc16((uint8_t*)buffer, (length - 2));
|
||||
// Apply checksum bytes into packet
|
||||
buffer[length - 2] = (uint8_t)(crc & 0xFF); // Set Low byte CRC
|
||||
buffer[length - 1] = (uint8_t)(crc >> 8); // Set High byte CRC
|
||||
return crc;
|
||||
}
|
||||
|
||||
static void rs485_init(void)
|
||||
{
|
||||
uart_config_t uart_config = {
|
||||
.baud_rate = UART_BAUD_115200,
|
||||
.data_bits = UART_DATA_8_BITS,
|
||||
.parity = UART_PARITY_DISABLE,
|
||||
.stop_bits = UART_STOP_BITS_1,
|
||||
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
|
||||
.rx_flow_ctrl_thresh = 122,
|
||||
};
|
||||
printf("RS485 port initialization...\r\n");
|
||||
// Configure UART1 parameters
|
||||
uart_param_config(UART_NUM1, &uart_config);
|
||||
// Set UART1 pins(TX: IO4, RX: I05, RTS: IO18, CTS: IO19)
|
||||
uart_set_pin(UART_NUM1, UART1_TX_PIN, UART1_RX_PIN, UART1_RTS_PIN, UART_PIN_NO_CHANGE);
|
||||
// Install UART driver (we don't need an event queue here)
|
||||
uart_driver_install(UART_NUM1, BUF_SIZE * 2, 0, 0, NULL, 0);
|
||||
// Setup rs485 half duplex mode
|
||||
//uart_set_rs485_hd_mode(uart_num, true);
|
||||
uart_set_mode(UART_NUM1, UART_MODE_RS485_HALF_DUPLEX);
|
||||
}
|
||||
|
||||
static esp_err_t print_packet_data(const char *str, uint8_t *buffer, uint16_t buffer_size)
|
||||
{
|
||||
TEST_ASSERT( buffer != NULL);
|
||||
TEST_ASSERT( str != NULL);
|
||||
|
||||
// Calculate the checksum of the buffer
|
||||
uint16_t crc16_calc = get_buffer_crc16(buffer, (buffer_size - 2));
|
||||
uint16_t crc16_in = ((uint16_t)(buffer[buffer_size - 1]) << 8) | buffer[buffer_size - 2];
|
||||
const char* state_str = (crc16_in != crc16_calc) ? "incorrect " : "correct ";
|
||||
// Print an array of data
|
||||
printf("%s%s RS485 packet = [ ", str, state_str);
|
||||
for (int i = 0; i < buffer_size; i++) {
|
||||
printf("0x%.2X ", (uint8_t)buffer[i]);
|
||||
}
|
||||
printf(" ]\r\n");
|
||||
printf("crc_in = 0x%.4X\r\n", (uint16_t)crc16_in);
|
||||
printf("crc_calc = 0x%.4X\r\n", (uint16_t)crc16_calc);
|
||||
esp_err_t result = (crc16_in != crc16_calc) ? ESP_ERR_INVALID_CRC : ESP_OK;
|
||||
return result;
|
||||
}
|
||||
|
||||
// Slave test case for multi device
|
||||
static void rs485_slave(void)
|
||||
{
|
||||
rs485_init();
|
||||
uint8_t* slave_data = (uint8_t*) malloc(BUF_SIZE);
|
||||
uint16_t err_count = 0, good_count = 0;
|
||||
printf("Start recieve loop.\r\n");
|
||||
unity_send_signal("Slave_ready");
|
||||
unity_wait_for_signal("Master_started");
|
||||
for(int pack_count = 0; pack_count < PACKETS_NUMBER; pack_count++) {
|
||||
//Read slave_data from UART
|
||||
int len = uart_read_bytes(UART_NUM1, slave_data, BUF_SIZE, (PACKET_READ_TICS * 2));
|
||||
//Write slave_data back to UART
|
||||
if (len > 2) {
|
||||
esp_err_t status = print_packet_data("Received ", slave_data, len);
|
||||
|
||||
// If received packet is correct then send it back
|
||||
if (status == ESP_OK) {
|
||||
uart_write_bytes(UART_NUM1, (char*)slave_data, len);
|
||||
good_count++;
|
||||
} else {
|
||||
printf("Incorrect packet received.\r\n");
|
||||
err_count++;
|
||||
}
|
||||
} else {
|
||||
printf("Incorrect data packet[%d] received.\r\n", pack_count);
|
||||
err_count++;
|
||||
}
|
||||
}
|
||||
printf("Test completed. Received packets = %d, errors = %d\r\n", good_count, err_count);
|
||||
// Wait for packet to be sent
|
||||
uart_wait_tx_done(UART_NUM1, PACKET_READ_TICS);
|
||||
free(slave_data);
|
||||
uart_driver_delete(UART_NUM1);
|
||||
TEST_ASSERT(err_count < 2);
|
||||
}
|
||||
|
||||
// Master test of multi device test case.
|
||||
// It forms packet with random data, apply generated CRC16 and sends to slave.
|
||||
// If response recieved correctly from slave means RS485 channel works.
|
||||
static void rs485_master(void)
|
||||
{
|
||||
uint16_t err_count = 0, good_count = 0;
|
||||
rs485_init();
|
||||
uint8_t* master_buffer = (uint8_t*) malloc(BUF_SIZE);
|
||||
uint8_t* slave_buffer = (uint8_t*) malloc(BUF_SIZE);
|
||||
// The master test case should be synchronized with slave
|
||||
unity_wait_for_signal("Slave_ready");
|
||||
unity_send_signal("Master_started");
|
||||
printf("Start recieve loop.\r\n");
|
||||
for(int i = 0; i < PACKETS_NUMBER; i++) {
|
||||
// Form random buffer with CRC16
|
||||
buffer_fill_random(master_buffer, BUF_SIZE);
|
||||
// Print created packet for debugging
|
||||
esp_err_t status = print_packet_data("Send ", master_buffer, BUF_SIZE);
|
||||
TEST_ASSERT(status == ESP_OK);
|
||||
uart_write_bytes(UART_NUM1, (char*)master_buffer, BUF_SIZE);
|
||||
// Read translated packet from slave
|
||||
int len = uart_read_bytes(UART_NUM1, slave_buffer, BUF_SIZE, (PACKET_READ_TICS * 2));
|
||||
// Check if the received packet is too short
|
||||
if (len > 2) {
|
||||
// Print received packet and check checksum
|
||||
esp_err_t status = print_packet_data("Received ", slave_buffer, len);
|
||||
if (status == ESP_OK) {
|
||||
good_count++;
|
||||
printf("Received: %d\r\n", good_count);
|
||||
} else {
|
||||
err_count++;
|
||||
printf("Errors: %d\r\n", err_count);
|
||||
}
|
||||
}
|
||||
else {
|
||||
printf("Incorrect answer from slave.\r\n");
|
||||
err_count++;
|
||||
}
|
||||
}
|
||||
// Free the buffer and delete driver at the end
|
||||
free(master_buffer);
|
||||
uart_driver_delete(UART_NUM1);
|
||||
TEST_ASSERT(err_count <= 1);
|
||||
printf("Test completed. Received packets = %d, errors = %d\r\n", (uint16_t)good_count, (uint16_t)err_count);
|
||||
}
|
||||
|
||||
/*
|
||||
* This multi devices test case verifies RS485 mode of the uart driver and checks
|
||||
* correctness of RS485 interface channel communication. It requires
|
||||
* RS485 bus driver hardware to be connected to boards.
|
||||
*/
|
||||
TEST_CASE_MULTIPLE_DEVICES("RS485 half duplex uart multiple devices test.", "[driver_RS485][test_env=UT_T2_RS485]", rs485_master, rs485_slave);
|
@ -7,7 +7,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "freertos/semphr.h"
|
||||
@ -55,10 +54,12 @@ static void check_spi_pre_n_for(int clk, int pre, int n)
|
||||
t.tx_buffer=sendbuf;
|
||||
ret=spi_device_transmit(handle, &t);
|
||||
|
||||
printf("Checking clk rate %dHz. expect pre %d n %d, got pre %d n %d\n", clk, pre, n, SPI2.clock.clkdiv_pre+1, SPI2.clock.clkcnt_n+1);
|
||||
spi_dev_t* hw = spi_periph_signal[TEST_SPI_HOST].hw;
|
||||
|
||||
TEST_ASSERT(SPI2.clock.clkcnt_n+1==n);
|
||||
TEST_ASSERT(SPI2.clock.clkdiv_pre+1==pre);
|
||||
printf("Checking clk rate %dHz. expect pre %d n %d, got pre %d n %d\n", clk, pre, n, hw->clock.clkdiv_pre+1, hw->clock.clkcnt_n+1);
|
||||
|
||||
TEST_ASSERT(hw->clock.clkcnt_n+1==n);
|
||||
TEST_ASSERT(hw->clock.clkdiv_pre+1==pre);
|
||||
|
||||
ret=spi_bus_remove_device(handle);
|
||||
TEST_ASSERT(ret==ESP_OK);
|
||||
@ -331,7 +332,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
|
||||
ESP_LOGI(TAG, "test 6 iomux output pins...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_IOMUX_PINS | SPICOMMON_BUSFLAG_QUAD;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
@ -340,7 +341,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
|
||||
ESP_LOGI(TAG, "test 4 iomux output pins...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_IOMUX_PINS | SPICOMMON_BUSFLAG_DUAL;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
@ -350,7 +351,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
ESP_LOGI(TAG, "test 6 output pins...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_QUAD;
|
||||
//swap MOSI and MISO
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
@ -360,7 +361,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
ESP_LOGI(TAG, "test 4 output pins...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_DUAL;
|
||||
//swap MOSI and MISO
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
@ -369,14 +370,14 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
|
||||
ESP_LOGI(TAG, "test master 5 output pins and MOSI on input-only pin...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = 34, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
|
||||
ESP_LOGI(TAG, "test slave 5 output pins and MISO on input-only pin...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO | SPICOMMON_BUSFLAG_WPHD;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
@ -384,14 +385,14 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
ESP_LOGI(TAG, "test master 3 output pins and MOSI on input-only pin...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO;
|
||||
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = 34, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
|
||||
ESP_LOGI(TAG, "test slave 3 output pins and MISO on input-only pin...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK | SPICOMMON_BUSFLAG_MOSI | SPICOMMON_BUSFLAG_MISO;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ESP_OK(spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
TEST_ASSERT_EQUAL_HEX32( flags_expected, flags_o );
|
||||
@ -399,7 +400,7 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
ESP_LOGI(TAG, "check native flag for 6 output pins...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_IOMUX_PINS;
|
||||
//swap MOSI and MISO
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
@ -407,61 +408,61 @@ TEST_CASE("spi bus setting with different pin configs", "[spi]")
|
||||
ESP_LOGI(TAG, "check native flag for 4 output pins...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_IOMUX_PINS;
|
||||
//swap MOSI and MISO
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MISO, .miso_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
|
||||
ESP_LOGI(TAG, "check dual flag for master 5 output pins and MISO/MOSI on input-only pin...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_DUAL;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = 34, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
|
||||
ESP_LOGI(TAG, "check dual flag for master 3 output pins and MISO/MOSI on input-only pin...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_DUAL;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = 34, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = 34, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = 34, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
|
||||
ESP_LOGI(TAG, "check sclk flag...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_SCLK;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = -1, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = -1, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
|
||||
ESP_LOGI(TAG, "check mosi flag...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_MOSI;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = -1, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = -1, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
|
||||
ESP_LOGI(TAG, "check miso flag...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_MISO;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = -1, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = -1, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
|
||||
ESP_LOGI(TAG, "check quad flag...");
|
||||
flags_expected = SPICOMMON_BUSFLAG_QUAD;
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = -1, .quadwp_io_num = HSPI_IOMUX_PIN_NUM_WP,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = -1, .quadwp_io_num = spi_periph_signal[HSPI_HOST].spiwp_iomux_pin,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = HSPI_IOMUX_PIN_NUM_MOSI, .miso_io_num = HSPI_IOMUX_PIN_NUM_MISO, .sclk_io_num = HSPI_IOMUX_PIN_NUM_CLK, .quadhd_io_num = HSPI_IOMUX_PIN_NUM_HD, .quadwp_io_num = -1,
|
||||
cfg = (spi_bus_config_t){.mosi_io_num = spi_periph_signal[HSPI_HOST].spid_iomux_pin, .miso_io_num = spi_periph_signal[HSPI_HOST].spiq_iomux_pin, .sclk_io_num = spi_periph_signal[HSPI_HOST].spiclk_iomux_pin, .quadhd_io_num = spi_periph_signal[HSPI_HOST].spihd_iomux_pin, .quadwp_io_num = -1,
|
||||
.max_transfer_sz = 8, .flags = flags_expected};
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_MASTER, &flags_o));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, spicommon_bus_initialize_io(TEST_SPI_HOST, &cfg, 0, flags_expected|SPICOMMON_BUSFLAG_SLAVE, &flags_o));
|
||||
@ -544,7 +545,7 @@ static const uint8_t data_drom[320+3] = {
|
||||
|
||||
TEST_CASE("SPI Master DMA test, TX and RX in different regions", "[spi]")
|
||||
{
|
||||
#ifdef CONFIG_ESP32_SPIRAM_SUPPORT
|
||||
#ifdef CONFIG_SPIRAM
|
||||
//test psram if enabled
|
||||
ESP_LOGI(TAG, "testing PSRAM...");
|
||||
uint32_t* data_malloc = (uint32_t*)heap_caps_malloc(324, MALLOC_CAP_SPIRAM);
|
@ -11,7 +11,7 @@
|
||||
#include "sdkconfig.h"
|
||||
#include "test/test_common_spi.h"
|
||||
|
||||
#ifndef CONFIG_ESP32_SPIRAM_SUPPORT
|
||||
#ifndef CONFIG_SPIRAM
|
||||
//This test should be removed once the timing test is merged.
|
||||
|
||||
|
||||
@ -88,10 +88,10 @@ TEST_CASE("test slave send unaligned","[spi]")
|
||||
slave_init();
|
||||
|
||||
//do internal connection
|
||||
int_connect( PIN_NUM_MOSI, HSPID_OUT_IDX, VSPIQ_IN_IDX );
|
||||
int_connect( PIN_NUM_MISO, VSPIQ_OUT_IDX, HSPID_IN_IDX );
|
||||
int_connect( PIN_NUM_CS, HSPICS0_OUT_IDX, VSPICS0_IN_IDX );
|
||||
int_connect( PIN_NUM_CLK, HSPICLK_OUT_IDX, VSPICLK_IN_IDX );
|
||||
int_connect( PIN_NUM_MOSI, spi_periph_signal[TEST_SPI_HOST].spid_out, spi_periph_signal[TEST_SLAVE_HOST].spiq_in );
|
||||
int_connect( PIN_NUM_MISO, spi_periph_signal[TEST_SLAVE_HOST].spiq_out, spi_periph_signal[TEST_SPI_HOST].spid_in );
|
||||
int_connect( PIN_NUM_CS, spi_periph_signal[TEST_SPI_HOST].spics_out[0], spi_periph_signal[TEST_SLAVE_HOST].spics_in );
|
||||
int_connect( PIN_NUM_CLK, spi_periph_signal[TEST_SPI_HOST].spiclk_out, spi_periph_signal[TEST_SLAVE_HOST].spiclk_in );
|
||||
|
||||
for ( int i = 0; i < 4; i ++ ) {
|
||||
//slave send
|
||||
@ -140,4 +140,4 @@ TEST_CASE("test slave send unaligned","[spi]")
|
||||
ESP_LOGI(MASTER_TAG, "test passed.");
|
||||
}
|
||||
|
||||
#endif // !CONFIG_ESP32_SPIRAM_SUPPORT
|
||||
#endif // !CONFIG_SPIRAM
|
@ -13,9 +13,43 @@
|
||||
|
||||
// All the tests using the header should use this definition as much as possible,
|
||||
// so that the working host can be changed easily in the future.
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#define TEST_SPI_HOST HSPI_HOST
|
||||
#define TEST_SLAVE_HOST VSPI_HOST
|
||||
|
||||
#define PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO
|
||||
#define PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI
|
||||
#define PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK
|
||||
#define PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS
|
||||
#define PIN_NUM_WP HSPI_IOMUX_PIN_NUM_WP
|
||||
#define PIN_NUM_HD HSPI_IOMUX_PIN_NUM_HD
|
||||
|
||||
#define SLAVE_PIN_NUM_MISO VSPI_IOMUX_PIN_NUM_MISO
|
||||
#define SLAVE_PIN_NUM_MOSI VSPI_IOMUX_PIN_NUM_MOSI
|
||||
#define SLAVE_PIN_NUM_CLK VSPI_IOMUX_PIN_NUM_CLK
|
||||
#define SLAVE_PIN_NUM_CS VSPI_IOMUX_PIN_NUM_CS
|
||||
#define SLAVE_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP
|
||||
#define SLAVE_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2BETA
|
||||
#define TEST_SPI_HOST FSPI_HOST
|
||||
#define TEST_SLAVE_HOST HSPI_HOST
|
||||
|
||||
#define PIN_NUM_MISO FSPI_IOMUX_PIN_NUM_MISO
|
||||
#define PIN_NUM_MOSI FSPI_IOMUX_PIN_NUM_MOSI
|
||||
#define PIN_NUM_CLK FSPI_IOMUX_PIN_NUM_CLK
|
||||
#define PIN_NUM_CS FSPI_IOMUX_PIN_NUM_CS
|
||||
#define PIN_NUM_WP FSPI_IOMUX_PIN_NUM_WP
|
||||
#define PIN_NUM_HD FSPI_IOMUX_PIN_NUM_HD
|
||||
|
||||
#define SLAVE_PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO
|
||||
#define SLAVE_PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI
|
||||
#define SLAVE_PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK
|
||||
#define SLAVE_PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS
|
||||
#define SLAVE_PIN_NUM_WP HSPI_IOMUX_PIN_NUM_WP
|
||||
#define SLAVE_PIN_NUM_HD HSPI_IOMUX_PIN_NUM_HD
|
||||
#endif
|
||||
|
||||
|
||||
#define FUNC_SPI 1
|
||||
#define FUNC_GPIO 2
|
||||
|
||||
@ -52,11 +86,6 @@
|
||||
0,\
|
||||
}
|
||||
|
||||
#define PIN_NUM_MISO HSPI_IOMUX_PIN_NUM_MISO
|
||||
#define PIN_NUM_MOSI HSPI_IOMUX_PIN_NUM_MOSI
|
||||
#define PIN_NUM_CLK HSPI_IOMUX_PIN_NUM_CLK
|
||||
#define PIN_NUM_CS HSPI_IOMUX_PIN_NUM_CS
|
||||
|
||||
//default bus config for tests
|
||||
#define SPI_BUS_TEST_DEFAULT_CONFIG() {\
|
||||
.miso_io_num=PIN_NUM_MISO, \
|
||||
|
@ -62,19 +62,6 @@ static esp_err_t i2c_master_write_slave(i2c_port_t i2c_num, uint8_t *data_wr, si
|
||||
return ret;
|
||||
}
|
||||
|
||||
// print the reading buffer
|
||||
static void disp_buf(uint8_t *buf, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; i++) {
|
||||
printf("%02x ", buf[i]);
|
||||
if (( i + 1 ) % 16 == 0) {
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static i2c_config_t i2c_master_init(void)
|
||||
{
|
||||
i2c_config_t conf_master = {
|
||||
@ -252,260 +239,6 @@ TEST_CASE("I2C driver memory leaking check", "[i2c]")
|
||||
TEST_ASSERT_INT_WITHIN(100, size, esp_get_free_heap_size());
|
||||
}
|
||||
|
||||
static void i2c_master_write_test(void)
|
||||
{
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int i;
|
||||
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
|
||||
unity_send_signal("master write");
|
||||
for (i = 0; i < DATA_LENGTH / 2; i++) {
|
||||
data_wr[i] = i;
|
||||
}
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, DATA_LENGTH / 2);
|
||||
disp_buf(data_wr, i + 1);
|
||||
free(data_wr);
|
||||
unity_wait_for_signal("ready to delete");
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_MASTER_NUM));
|
||||
}
|
||||
|
||||
static void i2c_slave_read_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int size_rd = 0;
|
||||
int len = 0;
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
|
||||
unity_wait_for_signal("master write");
|
||||
while (1) {
|
||||
len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, DATA_LENGTH, 10000 / portTICK_RATE_MS);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
size_rd += len;
|
||||
}
|
||||
disp_buf(data_rd, size_rd);
|
||||
for (int i = 0; i < size_rd; i++) {
|
||||
TEST_ASSERT(data_rd[i] == i);
|
||||
}
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
TEST_ESP_OK(i2c_driver_delete(I2C_SLAVE_NUM));
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C master write slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_test, i2c_slave_read_test);
|
||||
|
||||
static void master_read_slave_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
memset(data_rd, 0, DATA_LENGTH);
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||
|
||||
unity_send_signal("slave write");
|
||||
unity_wait_for_signal("master read");
|
||||
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH-1, ACK_VAL);
|
||||
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH-1, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
printf("%d\n", data_rd[i]);
|
||||
TEST_ASSERT(data_rd[i]==i);
|
||||
}
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
static void slave_write_buffer_test(void)
|
||||
{
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int size_rd;
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
|
||||
unity_wait_for_signal("slave write");
|
||||
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
||||
data_wr[i] = i;
|
||||
}
|
||||
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
||||
disp_buf(data_wr, size_rd);
|
||||
unity_send_signal("master read");
|
||||
unity_wait_for_signal("ready to delete");
|
||||
free(data_wr);
|
||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C master read slave test", "[i2c][test_env=UT_T2_I2C][timeout=150]", master_read_slave_test, slave_write_buffer_test);
|
||||
|
||||
static void i2c_master_write_read_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
memset(data_rd, 0, DATA_LENGTH);
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
|
||||
i2c_master_start(cmd);
|
||||
i2c_master_write_byte(cmd, ( ESP_SLAVE_ADDR << 1 ) | READ_BIT, ACK_CHECK_EN);
|
||||
|
||||
unity_send_signal("slave write");
|
||||
unity_wait_for_signal("master read and write");
|
||||
i2c_master_read(cmd, data_rd, RW_TEST_LENGTH, ACK_VAL);
|
||||
i2c_master_read_byte(cmd, data_rd + RW_TEST_LENGTH, NACK_VAL);
|
||||
i2c_master_stop(cmd);
|
||||
i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 5000 / portTICK_RATE_MS);
|
||||
i2c_cmd_link_delete(cmd);
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
disp_buf(data_rd, RW_TEST_LENGTH);
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
TEST_ASSERT(data_rd[i] == i/2);
|
||||
}
|
||||
|
||||
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||
data_wr[i] = i % 3;
|
||||
}
|
||||
|
||||
vTaskDelay(100 / portTICK_RATE_MS);
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||
free(data_wr);
|
||||
free(data_rd);
|
||||
unity_send_signal("slave read");
|
||||
unity_wait_for_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
static void i2c_slave_read_write_test(void)
|
||||
{
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH);
|
||||
memset(data_rd, 0, DATA_LENGTH);
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int size_rd;
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
unity_wait_for_signal("slave write");
|
||||
|
||||
for (int i = 0; i < DATA_LENGTH / 2; i++) {
|
||||
data_wr[i] = i/2;
|
||||
}
|
||||
size_rd = i2c_slave_write_buffer(I2C_SLAVE_NUM, data_wr, RW_TEST_LENGTH, 2000 / portTICK_RATE_MS);
|
||||
disp_buf(data_wr, size_rd);
|
||||
unity_send_signal("master read and write");
|
||||
unity_wait_for_signal("slave read");
|
||||
size_rd = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd, RW_TEST_LENGTH, 1000 / portTICK_RATE_MS);
|
||||
printf("slave read data is:\n");
|
||||
disp_buf(data_rd, size_rd);
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
TEST_ASSERT(data_rd[i] == i % 3);
|
||||
}
|
||||
free(data_wr);
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C read and write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_write_read_test, i2c_slave_read_write_test);
|
||||
|
||||
static void i2c_master_repeat_write(void)
|
||||
{
|
||||
uint8_t *data_wr = (uint8_t *) malloc(DATA_LENGTH);
|
||||
int times = 3;
|
||||
|
||||
i2c_config_t conf_master = i2c_master_init();
|
||||
TEST_ESP_OK(i2c_param_config(I2C_MASTER_NUM, &conf_master));
|
||||
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_MASTER_NUM, I2C_MODE_MASTER,
|
||||
I2C_MASTER_RX_BUF_DISABLE,
|
||||
I2C_MASTER_TX_BUF_DISABLE, 0));
|
||||
unity_wait_for_signal("i2c slave init finish");
|
||||
|
||||
for (int j = 0; j < times; j++) {
|
||||
for (int i = 0; i < DATA_LENGTH; i++) {
|
||||
data_wr[i] = j + i;
|
||||
}
|
||||
i2c_master_write_slave(I2C_MASTER_NUM, data_wr, RW_TEST_LENGTH);
|
||||
disp_buf(data_wr, RW_TEST_LENGTH);
|
||||
}
|
||||
free(data_wr);
|
||||
unity_send_signal("master write");
|
||||
unity_wait_for_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_MASTER_NUM);
|
||||
}
|
||||
|
||||
static void i2c_slave_repeat_read(void)
|
||||
{
|
||||
int size_rd = 0;
|
||||
int times = 3;
|
||||
uint8_t *data_rd = (uint8_t *) malloc(DATA_LENGTH * 3);
|
||||
|
||||
i2c_config_t conf_slave = i2c_slave_init();
|
||||
TEST_ESP_OK(i2c_param_config( I2C_SLAVE_NUM, &conf_slave));
|
||||
TEST_ESP_OK(i2c_driver_install(I2C_SLAVE_NUM, I2C_MODE_SLAVE,
|
||||
I2C_SLAVE_RX_BUF_LEN,
|
||||
I2C_SLAVE_TX_BUF_LEN, 0));
|
||||
unity_send_signal("i2c slave init finish");
|
||||
unity_wait_for_signal("master write");
|
||||
|
||||
while (1) {
|
||||
int len = i2c_slave_read_buffer( I2C_SLAVE_NUM, data_rd + size_rd, RW_TEST_LENGTH * 3, 10000 / portTICK_RATE_MS);
|
||||
if (len == 0) {
|
||||
break;
|
||||
}
|
||||
size_rd += len;
|
||||
}
|
||||
disp_buf(data_rd, size_rd);
|
||||
for (int j = 0; j < times; j++) {
|
||||
for (int i = 0; i < RW_TEST_LENGTH; i++) {
|
||||
printf("data: %d, %d\n", data_rd[j * RW_TEST_LENGTH + i], (i % 129 + j));
|
||||
TEST_ASSERT(data_rd[j * RW_TEST_LENGTH + i] == (i % 129 + j));
|
||||
}
|
||||
}
|
||||
free(data_rd);
|
||||
unity_send_signal("ready to delete");
|
||||
i2c_driver_delete(I2C_SLAVE_NUM);
|
||||
}
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("I2C repeat write test", "[i2c][test_env=UT_T2_I2C][timeout=150]", i2c_master_repeat_write, i2c_slave_repeat_read);
|
||||
|
||||
static volatile bool exit_flag;
|
||||
static bool test_read_func;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user