diff --git a/cpu/esp32/vendor/Makefile b/cpu/esp32/vendor/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..ff4d2e4a970851278703feba4b43eee3133f2986
--- /dev/null
+++ b/cpu/esp32/vendor/Makefile
@@ -0,0 +1,5 @@
+# Add a list of subdirectories, that should also be built:
+DIRS += esp-idf
+DIRS += xtensa
+
+include $(RIOTBASE)/Makefile.base
diff --git a/cpu/esp32/vendor/README.md b/cpu/esp32/vendor/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..a8fdb6214e2aa6355df0926b188c16eb6d68211f
--- /dev/null
+++ b/cpu/esp32/vendor/README.md
@@ -0,0 +1,12 @@
+The subdirectories here contain third-party software components used by the RIOT port for ESP32.
+
+### esp
+
+The files that are part of [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). The files in this directory are under the copyright of their respective owners. Please note the copyright notice in these files. All of these files are BSD Licensed as described in the file [LICENSE](https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE).
+
+### esp-idf
+
+The files in this directory and all subdirectories are from the Espressif IoT Development Framework[ESP-IDF](https://github.com/espressif/esp-idf.git), the official development framework for ESP32. All of these files are copyright of Espressif Systems (Shanghai) PTE LTD or their respective owners and licensed under the Apache License, Version 2.0. Please refer the copyright notice in these files for details.
+
+### xtensa
+The files in this directory are from the [FreeRTOS port for Xtensa](https://github.com/tensilica/freertos) configurable processors and Diamond processors. All of these files are copyright of Cadence Design Systems Inc. and licensed under the MIT license.
diff --git a/cpu/esp32/vendor/esp-idf/Makefile b/cpu/esp32/vendor/esp-idf/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..31d86057e75e437f5f0361a1ec0fbd31ee4ce037
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/Makefile
@@ -0,0 +1,19 @@
+MODULE=esp_idf
+
+DIRS += driver
+DIRS += esp32
+DIRS += heap
+DIRS += soc
+DIRS += spi_flash
+DIRS += wpa_supplicant
+
+ifneq (,$(filter esp_wifi_any,$(USEMODULE)))
+    DIRS += nvs_flash
+    INCLUDES += -I$(ESP32_SDK_DIR)/components/smartconfig_ack/include
+endif
+
+ifneq (,$(filter esp_eth,$(USEMODULE)))
+    DIRS += ethernet
+endif
+
+include $(RIOTBASE)/Makefile.base
diff --git a/cpu/esp32/vendor/esp-idf/README.md b/cpu/esp32/vendor/esp-idf/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..42806a0d43c1a22559f6c0fca13cc62af87e3cc6
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/README.md
@@ -0,0 +1 @@
+The files in this directory and all subdirectories are from the Espressif IoT Development Framework[ESP-IDF](https://github.com/espressif/esp-idf.git), the official development framework for ESP32. All of these files are copyright of Espressif Systems (Shanghai) PTE LTD or their respective owners and licensed under the Apache License, Version 2.0. Please refer the copyright notice in these files for details.
diff --git a/cpu/esp32/vendor/esp-idf/driver/Makefile b/cpu/esp32/vendor/esp-idf/driver/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..dacce02269da578831f80bb7e00525f96d95f5d7
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/driver/Makefile
@@ -0,0 +1,5 @@
+MODULE=esp_idf_driver
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
diff --git a/cpu/esp32/vendor/esp-idf/driver/periph_ctrl.c b/cpu/esp32/vendor/esp-idf/driver/periph_ctrl.c
new file mode 100644
index 0000000000000000000000000000000000000000..b4b3f7f7568d24b964b7d2a127e1efc9f56b0700
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/driver/periph_ctrl.c
@@ -0,0 +1,220 @@
+// 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 <esp_types.h>
+#include "esp_intr.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+#include "freertos/xtensa_api.h"
+#include "soc/dport_reg.h"
+#include "driver/periph_ctrl.h"
+
+static portMUX_TYPE periph_spinlock = portMUX_INITIALIZER_UNLOCKED;
+
+/* Static functions to return register address & mask for clk_en / rst of each peripheral */
+static uint32_t get_clk_en_mask(periph_module_t periph);
+static uint32_t get_rst_en_mask(periph_module_t periph);
+static uint32_t get_clk_en_reg(periph_module_t periph);
+static uint32_t get_rst_en_reg(periph_module_t periph);
+
+void periph_module_enable(periph_module_t periph)
+{
+    portENTER_CRITICAL(&periph_spinlock);
+    DPORT_SET_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
+    DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
+    portEXIT_CRITICAL(&periph_spinlock);
+}
+
+void periph_module_disable(periph_module_t periph)
+{
+    portENTER_CRITICAL(&periph_spinlock);
+    DPORT_CLEAR_PERI_REG_MASK(get_clk_en_reg(periph), get_clk_en_mask(periph));
+    DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
+    portEXIT_CRITICAL(&periph_spinlock);
+}
+
+void periph_module_reset(periph_module_t periph)
+{
+    portENTER_CRITICAL(&periph_spinlock);
+    DPORT_SET_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
+    DPORT_CLEAR_PERI_REG_MASK(get_rst_en_reg(periph), get_rst_en_mask(periph));
+    portEXIT_CRITICAL(&periph_spinlock);
+}
+
+static uint32_t get_clk_en_mask(periph_module_t periph)
+{
+    switch(periph) {
+        case PERIPH_RMT_MODULE:
+            return DPORT_RMT_CLK_EN;
+        case PERIPH_LEDC_MODULE:
+            return DPORT_LEDC_CLK_EN;
+        case PERIPH_UART0_MODULE:
+            return DPORT_UART_CLK_EN;
+        case PERIPH_UART1_MODULE:
+            return DPORT_UART1_CLK_EN;
+        case PERIPH_UART2_MODULE:
+            return DPORT_UART2_CLK_EN;
+        case PERIPH_I2C0_MODULE:
+            return DPORT_I2C_EXT0_CLK_EN;
+        case PERIPH_I2C1_MODULE:
+            return DPORT_I2C_EXT1_CLK_EN;
+        case PERIPH_I2S0_MODULE:
+            return DPORT_I2S0_CLK_EN;
+        case PERIPH_I2S1_MODULE:
+            return DPORT_I2S1_CLK_EN;
+        case PERIPH_TIMG0_MODULE:
+            return DPORT_TIMERGROUP_CLK_EN;
+        case PERIPH_TIMG1_MODULE:
+            return DPORT_TIMERGROUP1_CLK_EN;
+        case PERIPH_PWM0_MODULE:
+            return DPORT_PWM0_CLK_EN;
+        case PERIPH_PWM1_MODULE:
+            return DPORT_PWM1_CLK_EN;
+        case PERIPH_PWM2_MODULE:
+            return DPORT_PWM2_CLK_EN;
+        case PERIPH_PWM3_MODULE:
+            return DPORT_PWM3_CLK_EN;
+        case PERIPH_UHCI0_MODULE:
+            return DPORT_UHCI0_CLK_EN;
+        case PERIPH_UHCI1_MODULE:
+            return DPORT_UHCI1_CLK_EN;
+        case PERIPH_PCNT_MODULE:
+            return DPORT_PCNT_CLK_EN;
+        case PERIPH_SPI_MODULE:
+            return DPORT_SPI01_CLK_EN;
+        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;
+        case PERIPH_SDMMC_MODULE:
+            return DPORT_WIFI_CLK_SDIO_HOST_EN;
+        case PERIPH_SDIO_SLAVE_MODULE:
+            return DPORT_WIFI_CLK_SDIOSLAVE_EN;
+        case PERIPH_CAN_MODULE:
+            return DPORT_CAN_CLK_EN;
+        case PERIPH_EMAC_MODULE:
+            return DPORT_WIFI_CLK_EMAC_EN;
+        case PERIPH_RNG_MODULE:
+            return DPORT_WIFI_CLK_RNG_EN;
+        case PERIPH_WIFI_MODULE:
+            return DPORT_WIFI_CLK_WIFI_EN_M;
+        case PERIPH_BT_MODULE:
+            return DPORT_WIFI_CLK_BT_EN_M;
+        case PERIPH_WIFI_BT_COMMON_MODULE:
+            return DPORT_WIFI_CLK_WIFI_BT_COMMON_M;
+        case PERIPH_BT_BASEBAND_MODULE:
+            return DPORT_BT_BASEBAND_EN;
+        case PERIPH_BT_LC_MODULE:
+            return DPORT_BT_LC_EN;
+        default:
+            return 0;
+    }
+}
+
+static uint32_t get_rst_en_mask(periph_module_t periph)
+{
+    switch(periph) {
+        case PERIPH_RMT_MODULE:
+            return DPORT_RMT_RST;
+        case PERIPH_LEDC_MODULE:
+            return DPORT_LEDC_RST;
+        case PERIPH_UART0_MODULE:
+            return DPORT_UART_RST;
+        case PERIPH_UART1_MODULE:
+            return DPORT_UART1_RST;
+        case PERIPH_UART2_MODULE:
+            return DPORT_UART2_RST;
+        case PERIPH_I2C0_MODULE:
+            return DPORT_I2C_EXT0_RST;
+        case PERIPH_I2C1_MODULE:
+            return DPORT_I2C_EXT1_RST;
+        case PERIPH_I2S0_MODULE:
+            return DPORT_I2S0_RST;
+        case PERIPH_I2S1_MODULE:
+            return DPORT_I2S1_RST;
+        case PERIPH_TIMG0_MODULE:
+            return DPORT_TIMERGROUP_RST;
+        case PERIPH_TIMG1_MODULE:
+            return DPORT_TIMERGROUP1_RST;
+        case PERIPH_PWM0_MODULE:
+            return DPORT_PWM0_RST;
+        case PERIPH_PWM1_MODULE:
+            return DPORT_PWM1_RST;
+        case PERIPH_PWM2_MODULE:
+            return DPORT_PWM2_RST;
+        case PERIPH_PWM3_MODULE:
+            return DPORT_PWM3_RST;
+        case PERIPH_UHCI0_MODULE:
+            return DPORT_UHCI0_RST;
+        case PERIPH_UHCI1_MODULE:
+            return DPORT_UHCI1_RST;
+        case PERIPH_PCNT_MODULE:
+            return DPORT_PCNT_RST;
+        case PERIPH_SPI_MODULE:
+            return DPORT_SPI01_RST;
+        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;
+        case PERIPH_SDMMC_MODULE:
+            return DPORT_SDIO_HOST_RST;
+        case PERIPH_SDIO_SLAVE_MODULE:
+            return DPORT_SDIO_RST;
+        case PERIPH_CAN_MODULE:
+            return DPORT_CAN_RST;
+        case PERIPH_EMAC_MODULE:
+            return DPORT_EMAC_RST;
+        case PERIPH_WIFI_MODULE:
+        case PERIPH_BT_MODULE:
+        case PERIPH_WIFI_BT_COMMON_MODULE:
+        case PERIPH_BT_BASEBAND_MODULE:
+        case PERIPH_BT_LC_MODULE:
+            return 0;
+        default:
+            return 0;
+    }
+}
+
+static bool is_wifi_clk_peripheral(periph_module_t periph)
+{
+    /* A small subset of peripherals use WIFI_CLK_EN_REG and
+       CORE_RST_EN_REG for their clock & reset registers */
+    switch(periph) {
+    case PERIPH_SDMMC_MODULE:
+    case PERIPH_SDIO_SLAVE_MODULE:
+    case PERIPH_EMAC_MODULE:
+    case PERIPH_RNG_MODULE:
+    case PERIPH_WIFI_MODULE:
+    case PERIPH_BT_MODULE:
+    case PERIPH_WIFI_BT_COMMON_MODULE:
+    case PERIPH_BT_BASEBAND_MODULE:
+    case PERIPH_BT_LC_MODULE:
+        return true;
+    default:
+        return false;
+    }
+}
+
+static uint32_t get_clk_en_reg(periph_module_t periph)
+{
+    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)
+{
+    return is_wifi_clk_peripheral(periph) ? DPORT_CORE_RST_EN_REG : DPORT_PERIP_RST_EN_REG;
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/Makefile b/cpu/esp32/vendor/esp-idf/esp32/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..c31048fb5b7d218f20c5e931ff5450be8e1153d3
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/Makefile
@@ -0,0 +1,14 @@
+MODULE=esp_idf_esp32
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/wpa_supplicant/port/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/esp32
+INCLUDES += -I$(ESP32_SDK_DIR)/components/esp32/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/nvs_flash/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/soc/esp32/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/smartconfig_ack/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/include/crypto
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/port/include
diff --git a/cpu/esp32/vendor/esp-idf/esp32/clk.c b/cpu/esp32/vendor/esp-idf/esp32/clk.c
new file mode 100644
index 0000000000000000000000000000000000000000..881ba392b1befc495604c16fa68aebf5e7d9601a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/clk.c
@@ -0,0 +1,334 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+/*
+ * PLEASE NOTE: This file is an excerpt of the original ESP-IDF file
+ *
+ *     /path/to/esp-idf/components/esp32/clk.c
+ *
+ * with a few minor changes or adjustments.
+ */
+
+#define ENABLE_DEBUG  0
+#include "debug.h"
+#include "esp_common.h"
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/time.h>
+#include <sys/param.h>
+#include "sdk_conf.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_clk.h"
+#ifndef RIOT_VERSION
+#include "esp_clk_internal.h"
+#endif
+#include "rom/ets_sys.h"
+#include "rom/uart.h"
+#include "rom/rtc.h"
+#include "soc/soc.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/i2s_reg.h"
+#include "driver/periph_ctrl.h"
+#include "xtensa/core-macros.h"
+
+/* Number of cycles to wait from the 32k XTAL oscillator to consider it running.
+ * Larger values increase startup delay. Smaller values may cause false positive
+ * detection (i.e. oscillator runs for a few cycles and then stops).
+ */
+#define SLOW_CLK_CAL_CYCLES     CONFIG_ESP32_RTC_CLK_CAL_CYCLES
+
+#define MHZ (1000000)
+
+void select_rtc_slow_clk(rtc_slow_freq_t slow_clk);
+
+// g_ticks_us defined in ROMs for PRO and APP CPU
+extern uint32_t g_ticks_per_us_pro;
+extern uint32_t g_ticks_per_us_app;
+
+static const char* TAG = "clk";
+
+void IRAM_ATTR esp_clk_slowclk_cal_set(uint32_t new_cal)
+{
+#ifdef WITH_RTC
+    /* To force monotonic time values even when clock calibration value changes,
+     * we adjust boot time, given current time and the new calibration value:
+     *      T = boot_time_old + cur_cal * ticks / 2^19
+     *      T = boot_time_adj + new_cal * ticks / 2^19
+     * which results in:
+     *      boot_time_adj = boot_time_old + ticks * (cur_cal - new_cal) / 2^19
+     */
+    const int64_t ticks = (int64_t) rtc_time_get();
+    const uint32_t cur_cal = REG_READ(RTC_SLOW_CLK_CAL_REG);
+    int32_t cal_diff = (int32_t) (cur_cal - new_cal);
+    int64_t boot_time_diff = ticks * cal_diff / (1LL << RTC_CLK_CAL_FRACT);
+    uint64_t boot_time_adj = get_boot_time() + boot_time_diff;
+    set_boot_time(boot_time_adj);
+#endif
+    REG_WRITE(RTC_SLOW_CLK_CAL_REG, new_cal);
+}
+
+uint32_t esp_clk_slowclk_cal_get(void)
+{
+    return REG_READ(RTC_SLOW_CLK_CAL_REG);
+}
+
+void esp_clk_init(void)
+{
+    rtc_config_t cfg = RTC_CONFIG_DEFAULT();
+    rtc_init_module(cfg);
+
+#ifdef CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS
+    /* Check the bootloader set the XTAL frequency.
+
+       Bootloaders pre-v2.1 don't do this.
+    */
+    rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
+    if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
+        ESP_EARLY_LOGW(TAG, "RTC domain not initialised by bootloader");
+        bootloader_clock_configure();
+    }
+#else
+    /* If this assertion fails, either upgrade the bootloader or enable CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS */
+    assert(rtc_clk_xtal_freq_get() != RTC_XTAL_FREQ_AUTO);
+#endif
+
+    rtc_clk_fast_freq_set(RTC_FAST_FREQ_8M);
+
+#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
+    select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
+#else
+    select_rtc_slow_clk(RTC_SLOW_FREQ_RTC);
+#endif
+
+    uint32_t freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
+    rtc_cpu_freq_t freq = RTC_CPU_FREQ_80M;
+    switch(freq_mhz) {
+        case 240:
+            freq = RTC_CPU_FREQ_240M;
+            break;
+        case 160:
+            freq = RTC_CPU_FREQ_160M;
+            break;
+        case 80:
+            freq = RTC_CPU_FREQ_160M;
+            break;
+        case 40:
+            freq = RTC_CPU_FREQ_XTAL;
+            break;
+        case 2:
+            freq = RTC_CPU_FREQ_2M;
+            break;
+        default:
+            freq = RTC_CPU_FREQ_80M;
+            break;
+    }
+
+    // Wait for UART TX to finish, otherwise some UART output will be lost
+    // when switching APB frequency
+    uart_tx_wait_idle(CONFIG_CONSOLE_UART_NUM);
+
+    uint32_t freq_before = rtc_clk_cpu_freq_value(rtc_clk_cpu_freq_get()) / MHZ ;
+
+    rtc_clk_cpu_freq_set(freq);
+
+    // Re calculate the ccount to make time calculation correct.
+    uint32_t freq_after = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
+    XTHAL_SET_CCOUNT( XTHAL_GET_CCOUNT() * freq_after / freq_before );
+}
+
+int IRAM_ATTR esp_clk_cpu_freq(void)
+{
+    return g_ticks_per_us_pro * 1000000;
+}
+
+int IRAM_ATTR esp_clk_apb_freq(void)
+{
+    return MIN(g_ticks_per_us_pro, 80) * 1000000;
+}
+
+void IRAM_ATTR ets_update_cpu_frequency(uint32_t ticks_per_us)
+{
+    /* Update scale factors used by ets_delay_us */
+    g_ticks_per_us_pro = ticks_per_us;
+    g_ticks_per_us_app = ticks_per_us;
+}
+
+void select_rtc_slow_clk(rtc_slow_freq_t slow_clk)
+{
+    uint32_t cal_val = 0;
+    uint32_t wait = 0;
+    const uint32_t warning_timeout = 3 /* sec */ * 32768 /* Hz */ / (2 * SLOW_CLK_CAL_CYCLES);
+    bool changing_clock_to_150k = false;
+    #ifndef QEMU
+    do {
+    #endif
+        if (slow_clk == RTC_SLOW_FREQ_32K_XTAL) {
+            /* 32k XTAL oscillator needs to be enabled and running before it can
+             * be used. Hardware doesn't have a direct way of checking if the
+             * oscillator is running. Here we use rtc_clk_cal function to count
+             * the number of main XTAL cycles in the given number of 32k XTAL
+             * oscillator cycles. If the 32k XTAL has not started up, calibration
+             * will time out, returning 0.
+             */
+            ESP_EARLY_LOGD(TAG, "waiting for 32k oscillator to start up");
+            rtc_clk_32k_enable(true);
+            cal_val = rtc_clk_cal(RTC_CAL_32K_XTAL, SLOW_CLK_CAL_CYCLES);
+            if(cal_val == 0 || cal_val < 15000000L){
+                ESP_EARLY_LOGE(TAG, "RTC: Not found External 32 kHz XTAL. Switching to Internal 150 kHz RC chain");
+                slow_clk = RTC_SLOW_FREQ_RTC;
+                changing_clock_to_150k = true;
+            }
+        }
+        rtc_clk_slow_freq_set(slow_clk);
+        if (changing_clock_to_150k == true && wait > 1){
+            // This helps when there are errors when switching the clock from External 32 kHz XTAL to Internal 150 kHz RC chain.
+            rtc_clk_32k_enable(false);
+            uint32_t min_bootstrap = 5; // Min bootstrapping for continue switching the clock.
+            rtc_clk_32k_bootstrap(min_bootstrap);
+            rtc_clk_32k_enable(true);
+        }
+
+        if (SLOW_CLK_CAL_CYCLES > 0) {
+            /* TODO: 32k XTAL oscillator has some frequency drift at startup.
+             * Improve calibration routine to wait until the frequency is stable.
+             */
+            cal_val = rtc_clk_cal(RTC_CAL_RTC_MUX, SLOW_CLK_CAL_CYCLES);
+        } else {
+            const uint64_t cal_dividend = (1ULL << RTC_CLK_CAL_FRACT) * 1000000ULL;
+            cal_val = (uint32_t) (cal_dividend / rtc_clk_slow_freq_get_hz());
+        }
+        if (++wait % warning_timeout == 0) {
+            ESP_EARLY_LOGW(TAG, "still waiting for source selection RTC");
+        }
+    #ifndef QEMU
+    } while (cal_val == 0);
+    #endif
+    ESP_EARLY_LOGD(TAG, "RTC_SLOW_CLK calibration value: %d", cal_val);
+    esp_clk_slowclk_cal_set(cal_val);
+}
+
+void rtc_clk_select_rtc_slow_clk(void)
+{
+    select_rtc_slow_clk(RTC_SLOW_FREQ_32K_XTAL);
+}
+
+/* This function is not exposed as an API at this point.
+ * All peripheral clocks are default enabled after chip is powered on.
+ * This function disables some peripheral clocks when cpu starts.
+ * These peripheral clocks are enabled when the peripherals are initialized
+ * and disabled when they are de-initialized.
+ */
+void esp_perip_clk_init(void)
+{
+    uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
+
+#if CONFIG_FREERTOS_UNICORE
+    RESET_REASON rst_reas[1];
+#else
+    RESET_REASON rst_reas[2];
+#endif
+
+    rst_reas[0] = rtc_get_reset_reason(0);
+
+#if !CONFIG_FREERTOS_UNICORE
+    rst_reas[1] = rtc_get_reset_reason(1);
+#endif
+
+    /* For reason that only reset CPU, do not disable the clocks
+     * that have been enabled before reset.
+     */
+    if ((rst_reas[0] >= TGWDT_CPU_RESET && rst_reas[0] <= RTCWDT_CPU_RESET)
+#if !CONFIG_FREERTOS_UNICORE
+        || (rst_reas[1] >= TGWDT_CPU_RESET && rst_reas[1] <= RTCWDT_CPU_RESET)
+#endif
+    ) {
+        common_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERIP_CLK_EN_REG);
+        hwcrypto_perip_clk = ~DPORT_READ_PERI_REG(DPORT_PERI_CLK_EN_REG);
+        wifi_bt_sdio_clk = ~DPORT_READ_PERI_REG(DPORT_WIFI_CLK_EN_REG);
+    }
+    else {
+        common_perip_clk = DPORT_WDG_CLK_EN |
+                              DPORT_PCNT_CLK_EN |
+                              DPORT_LEDC_CLK_EN |
+                              DPORT_TIMERGROUP1_CLK_EN |
+                              DPORT_PWM0_CLK_EN |
+                              DPORT_CAN_CLK_EN |
+                              DPORT_PWM1_CLK_EN |
+                              DPORT_PWM2_CLK_EN |
+                              DPORT_PWM3_CLK_EN;
+        hwcrypto_perip_clk = DPORT_PERI_EN_AES |
+                                DPORT_PERI_EN_SHA |
+                                DPORT_PERI_EN_RSA |
+                                DPORT_PERI_EN_SECUREBOOT;
+        wifi_bt_sdio_clk = DPORT_WIFI_CLK_WIFI_EN |
+                              DPORT_WIFI_CLK_BT_EN_M |
+                              DPORT_WIFI_CLK_UNUSED_BIT5 |
+                              DPORT_WIFI_CLK_UNUSED_BIT12 |
+                              DPORT_WIFI_CLK_SDIOSLAVE_EN |
+                              DPORT_WIFI_CLK_SDIO_HOST_EN |
+                              DPORT_WIFI_CLK_EMAC_EN;
+    }
+
+    //Reset the communication peripherals like I2C, SPI, UART, I2S and bring them to known state.
+    common_perip_clk |= DPORT_I2S0_CLK_EN |
+#if CONFIG_CONSOLE_UART_NUM != 0
+                        DPORT_UART_CLK_EN |
+#endif
+#if CONFIG_CONSOLE_UART_NUM != 1
+                        DPORT_UART1_CLK_EN |
+#endif
+#if CONFIG_CONSOLE_UART_NUM != 2
+                        DPORT_UART2_CLK_EN |
+#endif
+                        DPORT_SPI2_CLK_EN |
+                        DPORT_I2C_EXT0_CLK_EN |
+                        DPORT_UHCI0_CLK_EN |
+                        DPORT_RMT_CLK_EN |
+                        DPORT_UHCI1_CLK_EN |
+                        DPORT_SPI3_CLK_EN |
+                        DPORT_I2C_EXT1_CLK_EN |
+                        DPORT_I2S1_CLK_EN |
+                        DPORT_SPI_DMA_CLK_EN;
+
+#if CONFIG_SPIRAM_SPEED_80M
+//80MHz SPIRAM uses SPI3 as well; it's initialized before this is called. Because it is used in
+//a weird mode where clock to the peripheral is disabled but reset is also disabled, it 'hangs'
+//in a state where it outputs a continuous 80MHz signal. Mask its bit here because we should
+//not modify that state, regardless of what we calculated earlier.
+    common_perip_clk &= ~DPORT_SPI3_CLK_EN;
+#endif
+
+    /* Change I2S clock to audio PLL first. Because if I2S uses 160MHz clock,
+     * the current is not reduced when disable I2S clock.
+     */
+    DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(0), I2S_CLKA_ENA);
+    DPORT_SET_PERI_REG_MASK(I2S_CLKM_CONF_REG(1), I2S_CLKA_ENA);
+
+    /* Disable some peripheral clocks. */
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
+    DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
+
+    /* Disable hardware crypto clocks. */
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERI_CLK_EN_REG, hwcrypto_perip_clk);
+    DPORT_SET_PERI_REG_MASK(DPORT_PERI_RST_EN_REG, hwcrypto_perip_clk);
+
+    /* Disable WiFi/BT/SDIO clocks. */
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_WIFI_CLK_EN_REG, wifi_bt_sdio_clk);
+
+    /* Enable RNG clock. */
+    periph_module_enable(PERIPH_RNG_MODULE);
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/dport_access.c b/cpu/esp32/vendor/esp-idf/esp32/dport_access.c
new file mode 100644
index 0000000000000000000000000000000000000000..d87940837ccf46641efb091cc01feb3501117e78
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/dport_access.c
@@ -0,0 +1,318 @@
+// Copyright 2010-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.
+
+/*
+ * DPORT access is used for do protection when dual core access DPORT internal register and APB register via DPORT simultaneously
+ * This function will be initialize after FreeRTOS startup.
+ * When cpu0 want to access DPORT register, it should notify cpu1 enter in high-priority interrupt for be mute. When cpu1 already in high-priority interrupt,
+ * cpu0 can access DPORT register. Currently, cpu1 will wait for cpu0 finish access and exit high-priority interrupt.
+ */
+
+#ifdef RIOT_OS
+#include "esp_common.h"
+#endif /* RIOT_OS */
+
+#include <stdint.h>
+#include <string.h>
+
+#include <sdk_conf.h>
+#include "esp_attr.h"
+#include "esp_err.h"
+#include "esp_intr.h"
+#include "rom/ets_sys.h"
+#include "rom/uart.h"
+
+#include "soc/cpu.h"
+#include "soc/dport_reg.h"
+#include "soc/spi_reg.h"
+
+#ifndef CONFIG_FREERTOS_UNICORE
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/semphr.h"
+#include "freertos/queue.h"
+#include "freertos/portmacro.h"
+#endif
+
+#include "xtensa/core-macros.h"
+
+#ifndef CONFIG_FREERTOS_UNICORE
+static portMUX_TYPE g_dport_mux = portMUX_INITIALIZER_UNLOCKED;
+
+#define DPORT_CORE_STATE_IDLE        0
+#define DPORT_CORE_STATE_RUNNING     1
+static uint32_t volatile dport_core_state[portNUM_PROCESSORS];      //cpu is already run
+
+/* these global variables are accessed from interrupt vector, hence not declared as static */
+uint32_t volatile dport_access_start[portNUM_PROCESSORS];      //dport register could be accessed
+uint32_t volatile dport_access_end[portNUM_PROCESSORS];        //dport register is accessed over
+
+static uint32_t volatile dport_access_ref[portNUM_PROCESSORS];        //dport access reference
+
+#ifdef DPORT_ACCESS_BENCHMARK
+#define DPORT_ACCESS_BENCHMARK_STORE_NUM
+static uint32_t ccount_start[portNUM_PROCESSORS];
+static uint32_t ccount_end[portNUM_PROCESSORS];
+static uint32_t ccount_margin[portNUM_PROCESSORS][DPORT_ACCESS_BENCHMARK_STORE_NUM];
+static uint32_t ccount_margin_cnt;
+#endif
+
+
+static BaseType_t oldInterruptLevel[2];
+#endif // CONFIG_FREERTOS_UNICORE
+
+/* stall other cpu that this cpu is pending to access dport register start */
+void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void)
+{
+#ifndef CONFIG_FREERTOS_UNICORE
+    if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
+        || dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
+        return;
+    }
+
+    BaseType_t intLvl = portENTER_CRITICAL_NESTED();
+
+    int cpu_id = xPortGetCoreID();
+
+#ifdef DPORT_ACCESS_BENCHMARK
+    ccount_start[cpu_id] = XTHAL_GET_CCOUNT();
+#endif
+
+    if (dport_access_ref[cpu_id] == 0) {
+        portENTER_CRITICAL_ISR(&g_dport_mux);
+
+        oldInterruptLevel[cpu_id]=intLvl;
+
+        dport_access_start[cpu_id] = 0;
+        dport_access_end[cpu_id] = 0;
+
+        if (cpu_id == 0) {
+            _DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_3_REG, DPORT_CPU_INTR_FROM_CPU_3); //interrupt on cpu1
+        } else {
+            _DPORT_REG_WRITE(DPORT_CPU_INTR_FROM_CPU_2_REG, DPORT_CPU_INTR_FROM_CPU_2); //interrupt on cpu0
+        }
+
+        while (!dport_access_start[cpu_id]) {};
+
+        REG_READ(SPI_DATE_REG(3));  //just read a APB register sure that the APB-bus is idle
+    }
+
+    dport_access_ref[cpu_id]++;
+
+    if (dport_access_ref[cpu_id] > 1) {
+        /* Interrupts are already disabled by the parent, we're nested here. */
+        portEXIT_CRITICAL_NESTED(intLvl);
+    }
+#endif /* CONFIG_FREERTOS_UNICORE */
+}
+
+/* stall other cpu that this cpu is pending to access dport register end */
+void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void)
+{
+#ifndef CONFIG_FREERTOS_UNICORE
+    int cpu_id = xPortGetCoreID();
+
+    if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
+            || dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
+        return;
+    }
+
+    if (dport_access_ref[cpu_id] == 0) {
+        assert(0);
+    }
+
+    dport_access_ref[cpu_id]--;
+
+    if (dport_access_ref[cpu_id] == 0) {
+        dport_access_end[cpu_id] = 1;
+
+        portEXIT_CRITICAL_ISR(&g_dport_mux);
+
+        portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]);
+    }
+
+#ifdef DPORT_ACCESS_BENCHMARK
+    ccount_end[cpu_id] = XTHAL_GET_CCOUNT();
+    ccount_margin[cpu_id][ccount_margin_cnt] = ccount_end[cpu_id] - ccount_start[cpu_id];
+    ccount_margin_cnt = (ccount_margin_cnt + 1)&(DPORT_ACCESS_BENCHMARK_STORE_NUM - 1);
+#endif
+#endif /* CONFIG_FREERTOS_UNICORE */
+}
+
+void IRAM_ATTR esp_dport_access_stall_other_cpu_start_wrap(void)
+{
+    DPORT_STALL_OTHER_CPU_START();
+}
+
+void IRAM_ATTR esp_dport_access_stall_other_cpu_end_wrap(void)
+{
+    DPORT_STALL_OTHER_CPU_END();
+}
+
+#ifndef CONFIG_FREERTOS_UNICORE
+static void dport_access_init_core(void *arg)
+{
+    int core_id = 0;
+    uint32_t intr_source = ETS_FROM_CPU_INTR2_SOURCE;
+
+
+    core_id = xPortGetCoreID();
+    if (core_id == 1) {
+        intr_source = ETS_FROM_CPU_INTR3_SOURCE;
+    }
+
+    ESP_INTR_DISABLE(ETS_DPORT_INUM);
+    intr_matrix_set(core_id, intr_source, ETS_DPORT_INUM);
+    ESP_INTR_ENABLE(ETS_DPORT_INUM);
+
+    dport_access_ref[core_id] = 0;
+    dport_access_start[core_id] = 0;
+    dport_access_end[core_id] = 0;
+    dport_core_state[core_id] = DPORT_CORE_STATE_RUNNING;
+
+    vTaskDelete(NULL);
+}
+#endif
+
+/*  Defer initialisation until after scheduler is running */
+void esp_dport_access_int_init(void)
+{
+#ifndef CONFIG_FREERTOS_UNICORE
+    portBASE_TYPE res = xTaskCreatePinnedToCore(&dport_access_init_core, "dport", configMINIMAL_STACK_SIZE, NULL, 5, NULL, xPortGetCoreID());
+    assert(res == pdTRUE);
+#endif
+}
+
+void IRAM_ATTR esp_dport_access_int_pause(void)
+{
+#ifndef CONFIG_FREERTOS_UNICORE
+    portENTER_CRITICAL_ISR(&g_dport_mux);
+    dport_core_state[0] = DPORT_CORE_STATE_IDLE;
+    dport_core_state[1] = DPORT_CORE_STATE_IDLE;
+    portEXIT_CRITICAL_ISR(&g_dport_mux);
+#endif
+}
+
+//Used in panic code: the enter_critical stuff may be messed up so we just stop everything without checking the mux.
+void IRAM_ATTR esp_dport_access_int_abort(void)
+{
+#ifndef CONFIG_FREERTOS_UNICORE
+    dport_core_state[0] = DPORT_CORE_STATE_IDLE;
+    dport_core_state[1] = DPORT_CORE_STATE_IDLE;
+#endif
+}
+
+void IRAM_ATTR esp_dport_access_int_resume(void)
+{
+#ifndef CONFIG_FREERTOS_UNICORE
+    portENTER_CRITICAL_ISR(&g_dport_mux);
+    dport_core_state[0] = DPORT_CORE_STATE_RUNNING;
+    dport_core_state[1] = DPORT_CORE_STATE_RUNNING;
+    portEXIT_CRITICAL_ISR(&g_dport_mux);
+#endif
+}
+
+/**
+ * @brief Read a sequence of DPORT registers to the buffer, SMP-safe version.
+ *
+ * This implementation uses a method of the pre-reading of the APB register
+ * before reading the register of the DPORT, without stall other CPU.
+ * There is disable/enable interrupt.
+ *
+ * @param[out] buff_out  Contains the read data.
+ * @param[in]  address   Initial address for reading registers.
+ * @param[in]  num_words The number of words.
+ */
+void IRAM_ATTR esp_dport_access_read_buffer(uint32_t *buff_out, uint32_t address, uint32_t num_words)
+{
+    DPORT_INTERRUPT_DISABLE();
+    for (uint32_t i = 0;  i < num_words; ++i) {
+        buff_out[i] = DPORT_SEQUENCE_REG_READ(address + i * 4);
+    }
+    DPORT_INTERRUPT_RESTORE();
+}
+
+/**
+ * @brief Read value from register, SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * This implementation is useful for reading DORT registers for single reading without stall other CPU.
+ * There is disable/enable interrupt.
+ *
+ * @param reg Register address
+ * @return Value
+ */
+uint32_t IRAM_ATTR esp_dport_access_reg_read(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    uint32_t apb;
+    unsigned int intLvl;
+    __asm__ __volatile__ (\
+                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
+                  "rsil %[LVL], "XTSTR(3)"\n"\
+                  "l32i %[APB], %[APB], 0\n"\
+                  "l32i %[REG], %[REG], 0\n"\
+                  "wsr  %[LVL], "XTSTR(PS)"\n"\
+                  "rsync\n"\
+                  : [APB]"=a"(apb), [REG]"+a"(reg), [LVL]"=a"(intLvl)\
+                  : \
+                  : "memory" \
+                  );
+    return reg;
+#endif
+}
+
+/**
+ * @brief Read value from register, NOT SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * There is not disable/enable interrupt.
+ * The difference from DPORT_REG_READ() is that the user himself must disable interrupts while DPORT reading.
+ * This implementation is useful for reading DORT registers in loop without stall other CPU. Note the usage example.
+ * The recommended way to read registers sequentially without stall other CPU
+ * is to use the method esp_dport_read_buffer(buff_out, address, num_words). It allows you to read registers in the buffer.
+ *
+ * \code{c}
+ * // This example shows how to use it.
+ * { // Use curly brackets to limit the visibility of variables in macros DPORT_INTERRUPT_DISABLE/RESTORE.
+ *     DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
+ *     for (i = 0; i < max; ++i) {
+ *        array[i] = esp_dport_access_sequence_reg_read(Address + i * 4); // reading DPORT registers
+ *     }
+ *     DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
+ * }
+ * \endcode
+ *
+ * @param reg Register address
+ * @return Value
+ */
+uint32_t IRAM_ATTR esp_dport_access_sequence_reg_read(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    uint32_t apb;
+    __asm__ __volatile__ (\
+                  "movi %[APB], "XTSTR(0x3ff40078)"\n"\
+                  "l32i %[APB], %[APB], 0\n"\
+                  "l32i %[REG], %[REG], 0\n"\
+                  : [APB]"=a"(apb), [REG]"+a"(reg)\
+                  : \
+                  : "memory" \
+                  );
+    return reg;
+#endif
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/event_default_handlers.c b/cpu/esp32/vendor/esp-idf/esp32/event_default_handlers.c
new file mode 100644
index 0000000000000000000000000000000000000000..b2b0e35d733145024ee4823dfb3a5c93a68f06a4
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/event_default_handlers.c
@@ -0,0 +1,506 @@
+// 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.
+
+#ifdef RIOT_VERSION
+#define ENABLE_DEBUG 0
+#include "debug.h"
+#include "esp_common.h"
+#endif
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "esp_err.h"
+#include "esp_wifi.h"
+#include "esp_wifi_internal.h"
+#include "esp_event.h"
+#include "esp_event_loop.h"
+#include "esp_task.h"
+#ifndef RIOT_VERSION
+#include "esp_eth.h"
+#endif
+#include "esp_system.h"
+
+#include "rom/ets_sys.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+
+#include "tcpip_adapter.h"
+#include "esp_log.h"
+
+static const char* TAG = "event";
+
+#define WIFI_API_CALL_CHECK(info, api_call, ret) \
+do{\
+    esp_err_t __err = (api_call);\
+    if ((ret) != __err) {\
+        ESP_LOGE(TAG, "%s %d %s ret=0x%X", __FUNCTION__, __LINE__, (info), __err);\
+        return __err;\
+    }\
+} while(0)
+
+typedef esp_err_t (*system_event_handler_t)(system_event_t *e);
+
+static esp_err_t system_event_ap_start_handle_default(system_event_t *event);
+static esp_err_t system_event_ap_stop_handle_default(system_event_t *event);
+static esp_err_t system_event_sta_start_handle_default(system_event_t *event);
+static esp_err_t system_event_sta_stop_handle_default(system_event_t *event);
+static esp_err_t system_event_sta_connected_handle_default(system_event_t *event);
+static esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event);
+static esp_err_t system_event_sta_got_ip_default(system_event_t *event);
+static esp_err_t system_event_sta_lost_ip_default(system_event_t *event);
+
+static esp_err_t system_event_eth_start_handle_default(system_event_t *event);
+static esp_err_t system_event_eth_stop_handle_default(system_event_t *event);
+static esp_err_t system_event_eth_connected_handle_default(system_event_t *event);
+static esp_err_t system_event_eth_disconnected_handle_default(system_event_t *event);
+static esp_err_t system_event_eth_got_ip_default(system_event_t *event);
+
+/* Default event handler functions
+
+   Any entry in this table which is disabled by config will have a NULL handler.
+*/
+static system_event_handler_t default_event_handlers[SYSTEM_EVENT_MAX] = { 0 };
+
+esp_err_t system_event_eth_start_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_ip_info_t eth_ip;
+    uint8_t eth_mac[6];
+
+    esp_eth_get_mac(eth_mac);
+    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &eth_ip);
+    tcpip_adapter_eth_start(eth_mac, &eth_ip);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_eth_stop_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_stop(TCPIP_ADAPTER_IF_ETH);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+    return ESP_OK;
+}
+
+esp_err_t system_event_eth_connected_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_dhcp_status_t status;
+
+    tcpip_adapter_up(TCPIP_ADAPTER_IF_ETH);
+
+    tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_ETH, &status);
+
+    if (status == TCPIP_ADAPTER_DHCP_INIT) {
+        tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_ETH);
+    } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) {
+        tcpip_adapter_ip_info_t eth_ip;
+
+        tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_ETH, &eth_ip);
+
+        if (!(ip4_addr_isany_val(eth_ip.ip) || ip4_addr_isany_val(eth_ip.netmask) || ip4_addr_isany_val(eth_ip.gw))) {
+            system_event_t evt;
+
+            //notify event
+            evt.event_id = SYSTEM_EVENT_ETH_GOT_IP;
+            memcpy(&evt.event_info.got_ip.ip_info, &eth_ip, sizeof(tcpip_adapter_ip_info_t));
+
+            esp_event_send(&evt);
+        } else {
+            ESP_LOGE(TAG, "invalid static ip");
+        }
+    }
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_eth_disconnected_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_down(TCPIP_ADAPTER_IF_ETH);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+    return ESP_OK;
+}
+
+static esp_err_t system_event_eth_got_ip_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    ESP_LOGI(TAG, "eth ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
+           IP2STR(&event->event_info.got_ip.ip_info.ip),
+           IP2STR(&event->event_info.got_ip.ip_info.netmask),
+           IP2STR(&event->event_info.got_ip.ip_info.gw));
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+static esp_err_t system_event_sta_got_ip_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    WIFI_API_CALL_CHECK("esp_wifi_internal_set_sta_ip", esp_wifi_internal_set_sta_ip(), ESP_OK);
+
+    ESP_LOGI(TAG, "sta ip: " IPSTR ", mask: " IPSTR ", gw: " IPSTR,
+           IP2STR(&event->event_info.got_ip.ip_info.ip),
+           IP2STR(&event->event_info.got_ip.ip_info.netmask),
+           IP2STR(&event->event_info.got_ip.ip_info.gw));
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+static esp_err_t system_event_sta_lost_ip_default(system_event_t *event)
+{
+    ESP_LOGI(TAG, "station ip lost");
+    return ESP_OK;
+}
+
+esp_err_t system_event_ap_start_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_ip_info_t ap_ip;
+    uint8_t ap_mac[6];
+
+    WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, (wifi_rxcb_t)tcpip_adapter_ap_input), ESP_OK);
+    WIFI_API_CALL_CHECK("esp_wifi_mac_get",  esp_wifi_get_mac(ESP_IF_WIFI_AP, ap_mac), ESP_OK);
+
+    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, &ap_ip);
+    tcpip_adapter_ap_start(ap_mac, &ap_ip);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_ap_stop_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_AP, NULL), ESP_OK);
+
+    tcpip_adapter_stop(TCPIP_ADAPTER_IF_AP);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_sta_start_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_ip_info_t sta_ip;
+    uint8_t sta_mac[6];
+
+    WIFI_API_CALL_CHECK("esp_wifi_mac_get",  esp_wifi_get_mac(ESP_IF_WIFI_STA, sta_mac), ESP_OK);
+    tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip);
+    tcpip_adapter_sta_start(sta_mac, &sta_ip);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_sta_stop_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_stop(TCPIP_ADAPTER_IF_STA);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_sta_connected_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_dhcp_status_t status;
+
+    WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, (wifi_rxcb_t)tcpip_adapter_sta_input), ESP_OK);
+
+    tcpip_adapter_up(TCPIP_ADAPTER_IF_STA);
+
+    tcpip_adapter_dhcpc_get_status(TCPIP_ADAPTER_IF_STA, &status);
+
+    if (status == TCPIP_ADAPTER_DHCP_INIT) {
+        tcpip_adapter_dhcpc_start(TCPIP_ADAPTER_IF_STA);
+    } else if (status == TCPIP_ADAPTER_DHCP_STOPPED) {
+        tcpip_adapter_ip_info_t sta_ip;
+        tcpip_adapter_ip_info_t sta_old_ip;
+
+        tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip);
+        tcpip_adapter_get_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_old_ip);
+
+        if (!(ip4_addr_isany_val(sta_ip.ip) || ip4_addr_isany_val(sta_ip.netmask) || ip4_addr_isany_val(sta_ip.gw))) {
+            system_event_t evt;
+
+            evt.event_id = SYSTEM_EVENT_STA_GOT_IP;
+            evt.event_info.got_ip.ip_changed = false;
+
+            if (memcmp(&sta_ip, &sta_old_ip, sizeof(sta_ip))) {
+                evt.event_info.got_ip.ip_changed = true;
+            }
+
+            memcpy(&evt.event_info.got_ip.ip_info, &sta_ip, sizeof(tcpip_adapter_ip_info_t));
+            tcpip_adapter_set_old_ip_info(TCPIP_ADAPTER_IF_STA, &sta_ip);
+
+            esp_event_send(&evt);
+            ESP_LOGD(TAG, "static ip: ip changed=%d", evt.event_info.got_ip.ip_changed);
+        } else {
+            ESP_LOGE(TAG, "invalid static ip");
+        }
+    }
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+
+    return ESP_OK;
+}
+
+esp_err_t system_event_sta_disconnected_handle_default(system_event_t *event)
+{
+    #if 0 /* TODO IMPLEMENT */
+    tcpip_adapter_down(TCPIP_ADAPTER_IF_STA);
+    WIFI_API_CALL_CHECK("esp_wifi_internal_reg_rxcb", esp_wifi_internal_reg_rxcb(ESP_IF_WIFI_STA, NULL), ESP_OK);
+    #else
+    ESP_LOGI(TAG, "%s", __func__);
+    #endif
+    return ESP_OK;
+}
+
+static esp_err_t esp_system_event_debug(system_event_t *event)
+{
+    if (event == NULL) {
+        ESP_LOGE(TAG, "event is null!");
+        return ESP_FAIL;
+    }
+
+    switch (event->event_id) {
+    case SYSTEM_EVENT_WIFI_READY: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_WIFI_READY");
+        break;
+    }
+    case SYSTEM_EVENT_SCAN_DONE: {
+        system_event_sta_scan_done_t *scan_done = &event->event_info.scan_done;
+        (void)scan_done; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_SCAN_DONE, status:%d, number:%d",  scan_done->status, scan_done->number);
+        break;
+    }
+    case SYSTEM_EVENT_STA_START: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_START");
+        break;
+    }
+    case SYSTEM_EVENT_STA_STOP: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_STOP");
+        break;
+    }
+    case SYSTEM_EVENT_STA_CONNECTED: {
+        system_event_sta_connected_t *connected = &event->event_info.connected;
+        (void)connected; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG,
+                 "SYSTEM_EVENT_STA_CONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", channel:%d, authmode:%d", \
+                   connected->ssid, connected->ssid_len, MAC2STR(connected->bssid), connected->channel, connected->authmode);
+        break;
+    }
+    case SYSTEM_EVENT_STA_DISCONNECTED: {
+        system_event_sta_disconnected_t *disconnected = &event->event_info.disconnected;
+        (void)disconnected; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_DISCONNECTED, ssid:%s, ssid_len:%d, bssid:" MACSTR ", reason:%d", \
+                   disconnected->ssid, disconnected->ssid_len, MAC2STR(disconnected->bssid), disconnected->reason);
+        break;
+    }
+    case SYSTEM_EVENT_STA_AUTHMODE_CHANGE: {
+        system_event_sta_authmode_change_t *auth_change = &event->event_info.auth_change;
+        (void)auth_change; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_AUTHMODE_CHNAGE, old_mode:%d, new_mode:%d", auth_change->old_mode, auth_change->new_mode);
+        break;
+    }
+    case SYSTEM_EVENT_STA_GOT_IP: {
+        system_event_sta_got_ip_t *got_ip = &event->event_info.got_ip;
+        (void)got_ip; /* to avoid compile error: unused variable */
+        #if 0 /* TODO IMPLEMENT */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP, ip:" IPSTR ", mask:" IPSTR ", gw:" IPSTR,
+            IP2STR(&got_ip->ip_info.ip),
+            IP2STR(&got_ip->ip_info.netmask),
+            IP2STR(&got_ip->ip_info.gw));
+        #else
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_GOT_IP");
+        #endif
+        break;
+    }
+    case SYSTEM_EVENT_STA_LOST_IP: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_LOST_IP");
+        break;
+    }
+    case SYSTEM_EVENT_STA_WPS_ER_SUCCESS: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_SUCCESS");
+        break;
+    }
+    case SYSTEM_EVENT_STA_WPS_ER_FAILED: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_FAILED");
+        break;
+    }
+    case SYSTEM_EVENT_STA_WPS_ER_TIMEOUT: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_TIMEOUT");
+        break;
+    }
+    case SYSTEM_EVENT_STA_WPS_ER_PIN: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_STA_WPS_ER_PIN");
+        break;
+    }
+    case SYSTEM_EVENT_AP_START: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_START");
+        break;
+    }
+    case SYSTEM_EVENT_AP_STOP: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STOP");
+        break;
+    }
+    case SYSTEM_EVENT_AP_STACONNECTED: {
+        system_event_ap_staconnected_t *staconnected = &event->event_info.sta_connected;
+        (void)staconnected; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STACONNECTED, mac:" MACSTR ", aid:%d", \
+                   MAC2STR(staconnected->mac), staconnected->aid);
+        break;
+    }
+    case SYSTEM_EVENT_AP_STADISCONNECTED: {
+        system_event_ap_stadisconnected_t *stadisconnected = &event->event_info.sta_disconnected;
+        (void)stadisconnected; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STADISCONNECTED, mac:" MACSTR ", aid:%d", \
+                   MAC2STR(stadisconnected->mac), stadisconnected->aid);
+        break;
+    }
+    case SYSTEM_EVENT_AP_STAIPASSIGNED: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STAIPASSIGNED");
+        break;
+    }
+    case SYSTEM_EVENT_AP_PROBEREQRECVED: {
+        system_event_ap_probe_req_rx_t *ap_probereqrecved = &event->event_info.ap_probereqrecved;
+        (void)ap_probereqrecved; /* to avoid compile error: unused variable */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_PROBEREQRECVED, rssi:%d, mac:" MACSTR, \
+                   ap_probereqrecved->rssi, \
+                   MAC2STR(ap_probereqrecved->mac));
+        break;
+    }
+    case SYSTEM_EVENT_GOT_IP6: {
+        ip6_addr_t *addr = &event->event_info.got_ip6.ip6_info.ip;
+        (void)addr; /* to avoid compile error: unused variable */
+        #if 0 /* TODO IMPLEMENT */
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address "
+                 "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
+                 IP6_ADDR_BLOCK1(addr),
+                 IP6_ADDR_BLOCK2(addr),
+                 IP6_ADDR_BLOCK3(addr),
+                 IP6_ADDR_BLOCK4(addr),
+                 IP6_ADDR_BLOCK5(addr),
+                 IP6_ADDR_BLOCK6(addr),
+                 IP6_ADDR_BLOCK7(addr),
+                 IP6_ADDR_BLOCK8(addr));
+        #else
+        ESP_LOGD(TAG, "SYSTEM_EVENT_AP_STA_GOT_IP6 address ");
+        #endif
+        break;
+    }
+    case SYSTEM_EVENT_ETH_START: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_ETH_START");
+        break;
+    }
+    case SYSTEM_EVENT_ETH_STOP: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_ETH_STOP");
+        break;
+    }
+    case SYSTEM_EVENT_ETH_CONNECTED: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_ETH_CONNECETED");
+        break;
+    }
+    case SYSTEM_EVENT_ETH_DISCONNECTED: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_ETH_DISCONNECETED");
+        break;
+    }
+    case SYSTEM_EVENT_ETH_GOT_IP: {
+        ESP_LOGD(TAG, "SYSTEM_EVENT_ETH_GOT_IP");
+        break;
+    }
+    default: {
+        ESP_LOGW(TAG, "unexpected system event %d!", event->event_id);
+        break;
+    }
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_event_process_default(system_event_t *event)
+{
+    if (event == NULL) {
+        ESP_LOGE(TAG, "Error: event is null!");
+        return ESP_FAIL;
+    }
+
+    esp_system_event_debug(event);
+    if ((event->event_id < SYSTEM_EVENT_MAX)) {
+        if (default_event_handlers[event->event_id] != NULL) {
+            ESP_LOGV(TAG, "enter default callback");
+            default_event_handlers[event->event_id](event);
+            ESP_LOGV(TAG, "exit default callback");
+        }
+    } else {
+        ESP_LOGE(TAG, "mismatch or invalid event, id=%d", event->event_id);
+        return ESP_FAIL;
+    }
+    return ESP_OK;
+}
+
+void esp_event_set_default_wifi_handlers(void)
+{
+     default_event_handlers[SYSTEM_EVENT_STA_START]        = system_event_sta_start_handle_default;
+     default_event_handlers[SYSTEM_EVENT_STA_STOP]         = system_event_sta_stop_handle_default;
+     default_event_handlers[SYSTEM_EVENT_STA_CONNECTED]    = system_event_sta_connected_handle_default;
+     default_event_handlers[SYSTEM_EVENT_STA_DISCONNECTED] = system_event_sta_disconnected_handle_default;
+     default_event_handlers[SYSTEM_EVENT_STA_GOT_IP]       = system_event_sta_got_ip_default;
+     default_event_handlers[SYSTEM_EVENT_STA_LOST_IP]      = system_event_sta_lost_ip_default;
+     default_event_handlers[SYSTEM_EVENT_AP_START]         = system_event_ap_start_handle_default;
+     default_event_handlers[SYSTEM_EVENT_AP_STOP]          = system_event_ap_stop_handle_default;
+
+     /* TODO esp_register_shutdown_handler((shutdown_handler_t)esp_wifi_stop); */
+}
+
+void esp_event_set_default_eth_handlers(void)
+{
+     default_event_handlers[SYSTEM_EVENT_ETH_START]           = system_event_eth_start_handle_default;
+     default_event_handlers[SYSTEM_EVENT_ETH_STOP]            = system_event_eth_stop_handle_default;
+     default_event_handlers[SYSTEM_EVENT_ETH_CONNECTED]       = system_event_eth_connected_handle_default;
+     default_event_handlers[SYSTEM_EVENT_ETH_DISCONNECTED]    = system_event_eth_disconnected_handle_default;
+     default_event_handlers[SYSTEM_EVENT_ETH_GOT_IP]          = system_event_eth_got_ip_default;
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/event_loop.c b/cpu/esp32/vendor/esp-idf/esp32/event_loop.c
new file mode 100644
index 0000000000000000000000000000000000000000..b1f04e9d251e33f8385b162f345d59abb593bc6b
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/event_loop.c
@@ -0,0 +1,125 @@
+// 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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "esp_err.h"
+#include "esp_wifi.h"
+#include "esp_event.h"
+#include "esp_event_loop.h"
+#include "esp_task.h"
+#include "esp_mesh.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+
+#include "esp_log.h"
+#include "sdk_conf.h"
+
+
+static const char* TAG = "event";
+static bool s_event_init_flag = false;
+static QueueHandle_t s_event_queue = NULL;
+static system_event_cb_t s_event_handler_cb = NULL;
+static void *s_event_ctx = NULL;
+
+static esp_err_t esp_event_post_to_user(system_event_t *event)
+{
+    if (s_event_handler_cb) {
+        return (*s_event_handler_cb)(s_event_ctx, event);
+    }
+    return ESP_OK;
+}
+
+static void esp_event_loop_task(void *pvParameters)
+{
+    while (1) {
+        system_event_t evt;
+        if (xQueueReceive(s_event_queue, &evt, portMAX_DELAY) == pdPASS) {
+           esp_err_t ret = esp_event_process_default(&evt);
+            if (ret != ESP_OK) {
+                ESP_LOGE(TAG, "default event handler failed!");
+            }
+            ret = esp_event_post_to_user(&evt);
+            if (ret != ESP_OK) {
+                ESP_LOGE(TAG, "post event to user fail!");
+            }
+        }
+    }
+}
+
+system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx)
+{
+    system_event_cb_t old_cb = s_event_handler_cb;
+    s_event_handler_cb = cb;
+    s_event_ctx = ctx;
+    return old_cb;
+}
+
+esp_err_t esp_event_send(system_event_t *event)
+{
+    if (s_event_queue == NULL) {
+        ESP_LOGE(TAG, "Event loop not initialized via esp_event_loop_init, but esp_event_send called");
+        return ESP_ERR_INVALID_STATE;
+    }
+    #if MODULE_ESP_WIFI_ANY
+    if (event->event_id == SYSTEM_EVENT_STA_GOT_IP || event->event_id == SYSTEM_EVENT_STA_LOST_IP) {
+        if (g_mesh_event_cb) {
+            mesh_event_t mevent;
+            if (event->event_id == SYSTEM_EVENT_STA_GOT_IP) {
+                mevent.id = MESH_EVENT_ROOT_GOT_IP;
+                memcpy(&mevent.info.got_ip, &event->event_info.got_ip, sizeof(system_event_sta_got_ip_t));
+            } else {
+                mevent.id = MESH_EVENT_ROOT_LOST_IP;
+            }
+            g_mesh_event_cb(mevent);
+        }
+    }
+    #endif
+    portBASE_TYPE ret = xQueueSendToBack(s_event_queue, event, 0);
+    if (ret != pdPASS) {
+        if (event) {
+            ESP_LOGE(TAG, "e=%d f", event->event_id);
+        } else {
+            ESP_LOGE(TAG, "e null");
+        }
+        return ESP_FAIL;
+    }
+    return ESP_OK;
+}
+
+QueueHandle_t esp_event_loop_get_queue(void)
+{
+    return s_event_queue;
+}
+
+esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx)
+{
+    if (s_event_init_flag) {
+        return ESP_FAIL;
+    }
+    s_event_handler_cb = cb;
+    s_event_ctx = ctx;
+    s_event_queue = xQueueCreate(CONFIG_SYSTEM_EVENT_QUEUE_SIZE, sizeof(system_event_t));
+
+    xTaskCreatePinnedToCore(esp_event_loop_task, "wifi-event-loop",
+            ESP_TASKD_EVENT_STACK, NULL, ESP_TASKD_EVENT_PRIO, NULL, 0);
+
+    s_event_init_flag = true;
+    return ESP_OK;
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/fast_crypto_ops.c b/cpu/esp32/vendor/esp-idf/esp32/fast_crypto_ops.c
new file mode 100644
index 0000000000000000000000000000000000000000..c6673b82fcbc1fe725d91de8186b3b1bf658459f
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/fast_crypto_ops.c
@@ -0,0 +1,224 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include "crypto/common.h"
+#include "crypto/aes_wrap.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#ifndef RIOT_VERSION
+#include "crypto/aes.h"
+#endif
+#include "crypto/dh_group5.h"
+#include "wps/wps.h"
+#include "wps/wps_i.h"
+#include "wpa2/eap_peer/eap.h"
+#include "wpa2/tls/tls.h"
+#include "wpa2/eap_peer/eap_methods.h"
+#include "wpa2/eap_peer/eap_i.h"
+#include "wpa2/eap_peer/eap_common.h"
+#include "esp_wifi_crypto_types.h"
+
+#ifndef RIOT_VERSION
+/*
+ * The parameters is used to set the cyrpto callback function for station connect when in security mode,
+ * every callback function can register as fast_xxx or normal one, i.e, fast_aes_wrap or aes_wrap, the
+ * difference between them is the normal API is calculate by software, the fast one use the hardware
+ * crypto in it, can be faster than the normal one, so the callback function register in default is which
+ * we recommend, so as the API in WPS default and WPA2 default.
+ */
+const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = {
+    .size = sizeof(wpa_crypto_funcs_t),
+    .version = ESP_WIFI_CRYPTO_VERSION,
+    .aes_wrap = (esp_aes_wrap_t)fast_aes_wrap,
+    .aes_unwrap = (esp_aes_unwrap_t)fast_aes_unwrap,
+    .hmac_sha256_vector = (esp_hmac_sha256_vector_t)fast_hmac_sha256_vector,
+    .sha256_prf = (esp_sha256_prf_t)fast_sha256_prf,
+    .hmac_md5 = (esp_hmac_md5_t)hmac_md5,
+    .hamc_md5_vector = (esp_hmac_md5_vector_t)hmac_md5_vector,
+    .hmac_sha1 = (esp_hmac_sha1_t)hmac_sha1,
+    .hmac_sha1_vector = (esp_hmac_sha1_vector_t)hmac_sha1_vector,
+    .sha1_prf = (esp_sha1_prf_t)sha1_prf,
+    .sha1_vector = (esp_sha1_vector_t)sha1_vector,
+    .pbkdf2_sha1 = (esp_pbkdf2_sha1_t)pbkdf2_sha1,
+    .rc4_skip = (esp_rc4_skip_t)rc4_skip,
+    .md5_vector = (esp_md5_vector_t)md5_vector,
+    .aes_encrypt = (esp_aes_encrypt_t)aes_encrypt,
+    .aes_encrypt_init = (esp_aes_encrypt_init_t)aes_encrypt_init,
+    .aes_encrypt_deinit = (esp_aes_encrypt_deinit_t)aes_encrypt_deinit,
+    .aes_decrypt = (esp_aes_decrypt_t)aes_decrypt,
+    .aes_decrypt_init = (esp_aes_decrypt_init_t)aes_decrypt_init,
+    .aes_decrypt_deinit = (esp_aes_decrypt_deinit_t)aes_decrypt_deinit
+};
+
+const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = {
+    .size = sizeof(wps_crypto_funcs_t),
+    .version = ESP_WIFI_CRYPTO_VERSION,
+    .aes_128_encrypt = (esp_aes_128_encrypt_t)fast_aes_128_cbc_encrypt,
+    .aes_128_decrypt = (esp_aes_128_decrypt_t)fast_aes_128_cbc_decrypt,
+    .crypto_mod_exp = (esp_crypto_mod_exp_t)fast_crypto_mod_exp,
+    .hmac_sha256 = (esp_hmac_sha256_t)fast_hmac_sha256,
+    .hmac_sha256_vector = (esp_hmac_sha256_vector_t)fast_hmac_sha256_vector,
+    .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector,
+    .uuid_gen_mac_addr = (esp_uuid_gen_mac_addr_t)uuid_gen_mac_addr,
+    .dh5_free = (esp_dh5_free_t)dh5_free,
+    .wps_build_assoc_req_ie = (esp_wps_build_assoc_req_ie_t)wps_build_assoc_req_ie,
+    .wps_build_assoc_resp_ie = (esp_wps_build_assoc_resp_ie_t)wps_build_assoc_resp_ie,
+    .wps_build_probe_req_ie = (esp_wps_build_probe_req_ie_t)wps_build_probe_req_ie,
+    .wps_build_public_key = (esp_wps_build_public_key_t)wps_build_public_key,
+    .wps_enrollee_get_msg = (esp_wps_enrollee_get_msg_t)wps_enrollee_get_msg,
+    .wps_enrollee_process_msg = (esp_wps_enrollee_process_msg_t)wps_enrollee_process_msg,
+    .wps_generate_pin = (esp_wps_generate_pin_t)wps_generate_pin,
+    .wps_is_selected_pin_registrar = (esp_wps_is_selected_pin_registrar_t)wps_is_selected_pin_registrar,
+    .wps_is_selected_pbc_registrar = (esp_wps_is_selected_pbc_registrar_t)wps_is_selected_pbc_registrar,
+    .eap_msg_alloc = (esp_eap_msg_alloc_t)eap_msg_alloc
+};
+
+/*
+ * What should notice is that the cyrpto hash type function and crypto cipher type function can not register
+ * as different, i.e, if you use fast_crypto_hash_init, you should use fast_crypto_hash_update and
+ * fast_crypto_hash_finish for finish hash calculate, rather than call crypto_hash_update and
+ * crypto_hash_finish, so do crypto_cipher.
+ */
+const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs = {
+    .size = sizeof(wpa2_crypto_funcs_t),
+    .version = ESP_WIFI_CRYPTO_VERSION,
+    .crypto_hash_init = (esp_crypto_hash_init_t)fast_crypto_hash_init,
+    .crypto_hash_update = (esp_crypto_hash_update_t)fast_crypto_hash_update,
+    .crypto_hash_finish = (esp_crypto_hash_finish_t)fast_crypto_hash_finish,
+    .crypto_cipher_init = (esp_crypto_cipher_init_t)fast_crypto_cipher_init,
+    .crypto_cipher_encrypt = (esp_crypto_cipher_encrypt_t)fast_crypto_cipher_encrypt,
+    .crypto_cipher_decrypt = (esp_crypto_cipher_decrypt_t)fast_crypto_cipher_decrypt,
+    .crypto_cipher_deinit = (esp_crypto_cipher_deinit_t)fast_crypto_cipher_deinit,
+    .crypto_mod_exp = (esp_crypto_mod_exp_t)crypto_mod_exp,
+    .sha256_vector = (esp_sha256_vector_t)fast_sha256_vector,
+    .tls_init = (esp_tls_init_t)tls_init,
+    .tls_deinit = (esp_tls_deinit_t)tls_deinit,
+    .eap_peer_blob_init = (esp_eap_peer_blob_init_t)eap_peer_blob_init,
+    .eap_peer_blob_deinit = (esp_eap_peer_blob_deinit_t)eap_peer_blob_deinit,
+    .eap_peer_config_init = (esp_eap_peer_config_init_t)eap_peer_config_init,
+    .eap_peer_config_deinit = (esp_eap_peer_config_deinit_t)eap_peer_config_deinit,
+    .eap_peer_register_methods = (esp_eap_peer_register_methods_t)eap_peer_register_methods,
+    .eap_peer_unregister_methods = (esp_eap_peer_unregister_methods_t)eap_peer_unregister_methods,
+    .eap_deinit_prev_method = (esp_eap_deinit_prev_method_t)eap_deinit_prev_method,
+    .eap_peer_get_eap_method = (esp_eap_peer_get_eap_method_t)eap_peer_get_eap_method,
+    .eap_sm_abort = (esp_eap_sm_abort_t)eap_sm_abort,
+    .eap_sm_build_nak = (esp_eap_sm_build_nak_t)eap_sm_build_nak,
+    .eap_sm_build_identity_resp = (esp_eap_sm_build_identity_resp_t)eap_sm_build_identity_resp,
+    .eap_msg_alloc = (esp_eap_msg_alloc_t)eap_msg_alloc
+};
+
+const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = {
+    .aes_128_encrypt = (esp_aes_128_encrypt_t)fast_aes_128_cbc_encrypt,
+    .aes_128_decrypt = (esp_aes_128_decrypt_t)fast_aes_128_cbc_decrypt,
+};
+#else
+/* TODO fast versions */
+/*
+ * The parameters is used to set the cyrpto callback function for station connect when in security mode,
+ * every callback function can register as fast_xxx or normal one, i.e, fast_aes_wrap or aes_wrap, the
+ * difference between them is the normal API is calculate by software, the fast one use the hardware
+ * crypto in it, can be faster than the normal one, so the callback function register in default is which
+ * we recommend, so as the API in WPS default and WPA2 default.
+ */
+const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs = {
+    .size = sizeof(wpa_crypto_funcs_t),
+    .version = ESP_WIFI_CRYPTO_VERSION,
+    .aes_wrap = (esp_aes_wrap_t)aes_wrap,
+    .aes_unwrap = (esp_aes_unwrap_t)aes_unwrap,
+    .hmac_sha256_vector = (esp_hmac_sha256_vector_t)hmac_sha256_vector,
+    .sha256_prf = (esp_sha256_prf_t)sha256_prf,
+    .hmac_md5 = (esp_hmac_md5_t)hmac_md5,
+    .hamc_md5_vector = (esp_hmac_md5_vector_t)hmac_md5_vector,
+    .hmac_sha1 = (esp_hmac_sha1_t)hmac_sha1,
+    .hmac_sha1_vector = (esp_hmac_sha1_vector_t)hmac_sha1_vector,
+    .sha1_prf = (esp_sha1_prf_t)sha1_prf,
+    .sha1_vector = (esp_sha1_vector_t)sha1_vector,
+    .pbkdf2_sha1 = (esp_pbkdf2_sha1_t)pbkdf2_sha1,
+    .rc4_skip = (esp_rc4_skip_t)rc4_skip,
+    .md5_vector = (esp_md5_vector_t)md5_vector,
+    .aes_encrypt = (esp_aes_encrypt_t)aes_encrypt,
+    .aes_encrypt_init = (esp_aes_encrypt_init_t)aes_encrypt_init,
+    .aes_encrypt_deinit = (esp_aes_encrypt_deinit_t)aes_encrypt_deinit,
+    .aes_decrypt = (esp_aes_decrypt_t)aes_decrypt,
+    .aes_decrypt_init = (esp_aes_decrypt_init_t)aes_decrypt_init,
+    .aes_decrypt_deinit = (esp_aes_decrypt_deinit_t)aes_decrypt_deinit
+};
+#if 0 /* WPS not supported at the moment */
+const wps_crypto_funcs_t g_wifi_default_wps_crypto_funcs = {
+    .size = sizeof(wps_crypto_funcs_t),
+    .version = ESP_WIFI_CRYPTO_VERSION,
+    .aes_128_encrypt = (esp_aes_128_encrypt_t)aes_128_cbc_encrypt,
+    .aes_128_decrypt = (esp_aes_128_decrypt_t)aes_128_cbc_decrypt,
+    .crypto_mod_exp = (esp_crypto_mod_exp_t)crypto_mod_exp,
+    .hmac_sha256 = (esp_hmac_sha256_t)hmac_sha256,
+    .hmac_sha256_vector = (esp_hmac_sha256_vector_t)hmac_sha256_vector,
+    .sha256_vector = (esp_sha256_vector_t)sha256_vector,
+    .uuid_gen_mac_addr = (esp_uuid_gen_mac_addr_t)uuid_gen_mac_addr,
+    .dh5_free = (esp_dh5_free_t)dh5_free,
+    .wps_build_assoc_req_ie = (esp_wps_build_assoc_req_ie_t)wps_build_assoc_req_ie,
+    .wps_build_assoc_resp_ie = (esp_wps_build_assoc_resp_ie_t)wps_build_assoc_resp_ie,
+    .wps_build_probe_req_ie = (esp_wps_build_probe_req_ie_t)wps_build_probe_req_ie,
+    .wps_build_public_key = (esp_wps_build_public_key_t)wps_build_public_key,
+    .wps_enrollee_get_msg = (esp_wps_enrollee_get_msg_t)wps_enrollee_get_msg,
+    .wps_enrollee_process_msg = (esp_wps_enrollee_process_msg_t)wps_enrollee_process_msg,
+    .wps_generate_pin = (esp_wps_generate_pin_t)wps_generate_pin,
+    .wps_is_selected_pin_registrar = (esp_wps_is_selected_pin_registrar_t)wps_is_selected_pin_registrar,
+    .wps_is_selected_pbc_registrar = (esp_wps_is_selected_pbc_registrar_t)wps_is_selected_pbc_registrar,
+    .eap_msg_alloc = (esp_eap_msg_alloc_t)eap_msg_alloc
+};
+#endif
+
+/*
+ * What should notice is that the cyrpto hash type function and crypto cipher type function can not register
+ * as different, i.e, if you use fast_crypto_hash_init, you should use fast_crypto_hash_update and
+ * fast_crypto_hash_finish for finish hash calculate, rather than call crypto_hash_update and
+ * crypto_hash_finish, so do crypto_cipher.
+ */
+#if 0 /* WPA2 enterprise not supported at the moment */
+const wpa2_crypto_funcs_t g_wifi_default_wpa2_crypto_funcs = {
+    .size = sizeof(wpa2_crypto_funcs_t),
+    .version = ESP_WIFI_CRYPTO_VERSION,
+    .crypto_hash_init = (esp_crypto_hash_init_t)crypto_hash_init,
+    .crypto_hash_update = (esp_crypto_hash_update_t)crypto_hash_update,
+    .crypto_hash_finish = (esp_crypto_hash_finish_t)crypto_hash_finish,
+    .crypto_cipher_init = (esp_crypto_cipher_init_t)crypto_cipher_init,
+    .crypto_cipher_encrypt = (esp_crypto_cipher_encrypt_t)crypto_cipher_encrypt,
+    .crypto_cipher_decrypt = (esp_crypto_cipher_decrypt_t)crypto_cipher_decrypt,
+    .crypto_cipher_deinit = (esp_crypto_cipher_deinit_t)crypto_cipher_deinit,
+    .crypto_mod_exp = (esp_crypto_mod_exp_t)crypto_mod_exp,
+    .sha256_vector = (esp_sha256_vector_t)sha256_vector,
+    .tls_init = (esp_tls_init_t)tls_init,
+    .tls_deinit = (esp_tls_deinit_t)tls_deinit,
+    .eap_peer_blob_init = (esp_eap_peer_blob_init_t)eap_peer_blob_init,
+    .eap_peer_blob_deinit = (esp_eap_peer_blob_deinit_t)eap_peer_blob_deinit,
+    .eap_peer_config_init = (esp_eap_peer_config_init_t)eap_peer_config_init,
+    .eap_peer_config_deinit = (esp_eap_peer_config_deinit_t)eap_peer_config_deinit,
+    .eap_peer_register_methods = (esp_eap_peer_register_methods_t)eap_peer_register_methods,
+    .eap_peer_unregister_methods = (esp_eap_peer_unregister_methods_t)eap_peer_unregister_methods,
+    .eap_deinit_prev_method = (esp_eap_deinit_prev_method_t)eap_deinit_prev_method,
+    .eap_peer_get_eap_method = (esp_eap_peer_get_eap_method_t)eap_peer_get_eap_method,
+    .eap_sm_abort = (esp_eap_sm_abort_t)eap_sm_abort,
+    .eap_sm_build_nak = (esp_eap_sm_build_nak_t)eap_sm_build_nak,
+    .eap_sm_build_identity_resp = (esp_eap_sm_build_identity_resp_t)eap_sm_build_identity_resp,
+    .eap_msg_alloc = (esp_eap_msg_alloc_t)eap_msg_alloc
+};
+#endif
+
+const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs = {
+    .aes_128_encrypt = (esp_aes_128_encrypt_t)aes_128_cbc_encrypt,
+    .aes_128_decrypt = (esp_aes_128_decrypt_t)aes_128_cbc_decrypt,
+};
+#endif
diff --git a/cpu/esp32/vendor/esp-idf/esp32/gdbstub.c b/cpu/esp32/vendor/esp-idf/esp32/gdbstub.c
new file mode 100644
index 0000000000000000000000000000000000000000..eaeb14cd311b2e7a3f304bfe67bf5a688f6ab3a2
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/gdbstub.c
@@ -0,0 +1,371 @@
+// 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.
+
+/*
+ * PLEASE NOTE: This file is an excerpt of the original ESP-IDF file
+ *
+ *     /path/to/esp-idf/components/esp32/gdbstub.c
+ *
+ * with a few minor changes to make it compilable with RIOT.
+ */
+
+/******************************************************************************
+ * Description: A stub to make the ESP32 debuggable by GDB over the serial
+ * port, at least enough to do a backtrace on panic. This gdbstub is read-only:
+ * it allows inspecting the ESP32 state
+ *******************************************************************************/
+
+#ifdef MODULE_ESP_GDBSTUB
+
+#include "rom/ets_sys.h"
+#include "soc/uart_reg.h"
+#include "soc/io_mux_reg.h"
+#include "esp_gdbstub.h"
+#include "driver/gpio.h"
+
+//Length of buffer used to reserve GDB commands. Has to be at least able to fit the G command, which
+//implies a minimum size of about 320 bytes.
+#define PBUFLEN 512
+
+static unsigned char cmd[PBUFLEN];        //GDB command input buffer
+static char chsum;                        //Running checksum of the output packet
+
+#define ATTR_GDBFN
+
+//Receive a char from the uart. Uses polling and feeds the watchdog.
+static int ATTR_GDBFN gdbRecvChar(void) {
+    int i;
+    while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_RXFIFO_CNT_S)&UART_RXFIFO_CNT)==0) ;
+    i=READ_PERI_REG(UART_FIFO_REG(0));
+    return i;
+}
+
+//Send a char to the uart.
+static void ATTR_GDBFN gdbSendChar(char c) {
+    while (((READ_PERI_REG(UART_STATUS_REG(0))>>UART_TXFIFO_CNT_S)&UART_TXFIFO_CNT)>=126) ;
+    WRITE_PERI_REG(UART_FIFO_REG(0), c);
+}
+
+//Send the start of a packet; reset checksum calculation.
+static void ATTR_GDBFN gdbPacketStart(void) {
+    chsum=0;
+    gdbSendChar('$');
+}
+
+//Send a char as part of a packet
+static void ATTR_GDBFN gdbPacketChar(char c) {
+    if (c=='#' || c=='$' || c=='}' || c=='*') {
+        gdbSendChar('}');
+        gdbSendChar(c^0x20);
+        chsum+=(c^0x20)+'}';
+    } else {
+        gdbSendChar(c);
+        chsum+=c;
+    }
+}
+
+//Send a string as part of a packet
+static void ATTR_GDBFN gdbPacketStr(const char *c) {
+    while (*c!=0) {
+        gdbPacketChar(*c);
+        c++;
+    }
+}
+
+//Send a hex val as part of a packet. 'bits'/4 dictates the number of hex chars sent.
+static void ATTR_GDBFN gdbPacketHex(int val, int bits) {
+    char hexChars[]="0123456789abcdef";
+    int i;
+    for (i=bits; i>0; i-=4) {
+        gdbPacketChar(hexChars[(val>>(i-4))&0xf]);
+    }
+}
+
+//Finish sending a packet.
+static void ATTR_GDBFN gdbPacketEnd(void) {
+    gdbSendChar('#');
+    gdbPacketHex(chsum, 8);
+}
+
+//Error states used by the routines that grab stuff from the incoming gdb packet
+#define ST_ENDPACKET -1
+#define ST_ERR -2
+#define ST_OK -3
+#define ST_CONT -4
+
+//Grab a hex value from the gdb packet. Ptr will get positioned on the end
+//of the hex string, as far as the routine has read into it. Bits/4 indicates
+//the max amount of hex chars it gobbles up. Bits can be -1 to eat up as much
+//hex chars as possible.
+static long ATTR_GDBFN gdbGetHexVal(unsigned char **ptr, int bits) {
+    int i;
+    int no;
+    unsigned int v=0;
+    no=bits/4;
+    if (bits==-1) no=64;
+    for (i=0; i<no; i++) {
+        char c;
+        c=**ptr;
+        (*ptr)++;
+        if (c>='0' && c<='9') {
+            v<<=4;
+            v|=(c-'0');
+        } else if (c>='A' && c<='F') {
+            v<<=4;
+            v|=(c-'A')+10;
+        } else if (c>='a' && c<='f') {
+            v<<=4;
+            v|=(c-'a')+10;
+        } else if (c=='#') {
+            if (bits==-1) {
+                (*ptr)--;
+                return v;
+            }
+            return ST_ENDPACKET;
+        } else {
+            if (bits==-1) {
+                (*ptr)--;
+                return v;
+            }
+            return ST_ERR;
+        }
+    }
+    return v;
+}
+
+//Swap an int into the form gdb wants it
+static int ATTR_GDBFN iswap(int i) {
+    int r;
+    r=((i>>24)&0xff);
+    r|=((i>>16)&0xff)<<8;
+    r|=((i>>8)&0xff)<<16;
+    r|=((i>>0)&0xff)<<24;
+    return r;
+}
+
+//Read a byte from ESP32 memory.
+static unsigned char ATTR_GDBFN readbyte(unsigned int p) {
+    int *i=(int*)(p&(~3));
+    if (p<0x20000000 || p>=0x80000000) return -1;
+    return *i>>((p&3)*8);
+}
+
+
+//Register file in the format exp108 gdb port expects it.
+//Inspired by gdb/regformats/reg-xtensa.dat
+typedef struct {
+    uint32_t pc;
+    uint32_t a[64];
+    uint32_t lbeg;
+    uint32_t lend;
+    uint32_t lcount;
+    uint32_t sar;
+    uint32_t windowbase;
+    uint32_t windowstart;
+    uint32_t configid0;
+    uint32_t configid1;
+    uint32_t ps;
+    uint32_t threadptr;
+    uint32_t br;
+    uint32_t scompare1;
+    uint32_t acclo;
+    uint32_t acchi;
+    uint32_t m0;
+    uint32_t m1;
+    uint32_t m2;
+    uint32_t m3;
+    uint32_t expstate;  //I'm going to assume this is exccause...
+    uint32_t f64r_lo;
+    uint32_t f64r_hi;
+    uint32_t f64s;
+    uint32_t f[16];
+    uint32_t fcr;
+    uint32_t fsr;
+} GdbRegFile;
+
+
+GdbRegFile gdbRegFile;
+
+/*
+//Register format as the Xtensa HAL has it:
+STRUCT_FIELD (long, 4, XT_STK_EXIT,     exit)
+STRUCT_FIELD (long, 4, XT_STK_PC,       pc)
+STRUCT_FIELD (long, 4, XT_STK_PS,       ps)
+STRUCT_FIELD (long, 4, XT_STK_A0,       a0)
+[..]
+STRUCT_FIELD (long, 4, XT_STK_A15,      a15)
+STRUCT_FIELD (long, 4, XT_STK_SAR,      sar)
+STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
+STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
+STRUCT_FIELD (long, 4, XT_STK_LBEG,   lbeg)
+STRUCT_FIELD (long, 4, XT_STK_LEND,   lend)
+STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
+// Temporary space for saving stuff during window spill
+STRUCT_FIELD (long, 4, XT_STK_TMP0,   tmp0)
+STRUCT_FIELD (long, 4, XT_STK_TMP1,   tmp1)
+STRUCT_FIELD (long, 4, XT_STK_TMP2,   tmp2)
+STRUCT_FIELD (long, 4, XT_STK_VPRI,   vpri)
+STRUCT_FIELD (long, 4, XT_STK_OVLY,   ovly)
+#endif
+STRUCT_END(XtExcFrame)
+*/
+
+
+static void dumpHwToRegfile(XtExcFrame *frame) {
+    int i;
+    long *frameAregs=&frame->a0;
+    gdbRegFile.pc=frame->pc;
+    for (i=0; i<16; i++) gdbRegFile.a[i]=frameAregs[i];
+    for (i=16; i<64; i++) gdbRegFile.a[i]=0xDEADBEEF;
+    gdbRegFile.lbeg=frame->lbeg;
+    gdbRegFile.lend=frame->lend;
+    gdbRegFile.lcount=frame->lcount;
+    gdbRegFile.sar=frame->sar;
+    //All windows have been spilled to the stack by the ISR routines. The following values should indicate that.
+    gdbRegFile.sar=frame->sar;
+    gdbRegFile.windowbase=0; //0
+    gdbRegFile.windowstart=0x1; //1
+    gdbRegFile.configid0=0xdeadbeef; //ToDo
+    gdbRegFile.configid1=0xdeadbeef; //ToDo
+    gdbRegFile.ps=frame->ps-PS_EXCM_MASK;
+    gdbRegFile.threadptr=0xdeadbeef; //ToDo
+    gdbRegFile.br=0xdeadbeef; //ToDo
+    gdbRegFile.scompare1=0xdeadbeef; //ToDo
+    gdbRegFile.acclo=0xdeadbeef; //ToDo
+    gdbRegFile.acchi=0xdeadbeef; //ToDo
+    gdbRegFile.m0=0xdeadbeef; //ToDo
+    gdbRegFile.m1=0xdeadbeef; //ToDo
+    gdbRegFile.m2=0xdeadbeef; //ToDo
+    gdbRegFile.m3=0xdeadbeef; //ToDo
+    gdbRegFile.expstate=frame->exccause; //ToDo
+}
+
+
+//Send the reason execution is stopped to GDB.
+static void sendReason(void) {
+    //exception-to-signal mapping
+    char exceptionSignal[]={4,31,11,11,2,6,8,0,6,7,0,0,7,7,7,7};
+    unsigned int i=0;
+    gdbPacketStart();
+    gdbPacketChar('T');
+    i=gdbRegFile.expstate&0x7f;
+    if (i<sizeof(exceptionSignal)) {
+        gdbPacketHex(exceptionSignal[i], 8);
+    } else {
+        gdbPacketHex(11, 8);
+    }
+    gdbPacketEnd();
+}
+
+//Handle a command as received from GDB.
+static int gdbHandleCommand(unsigned char *cmd, int len) {
+    //Handle a command
+    unsigned int i;
+    unsigned char *data=cmd+1;
+    if (cmd[0]=='g') {        //send all registers to gdb
+        int *p=(int*)&gdbRegFile;
+        gdbPacketStart();
+        for (i=0; i<sizeof(GdbRegFile)/4; i++) gdbPacketHex(iswap(*p++), 32);
+        gdbPacketEnd();
+    } else if (cmd[0]=='G') {    //receive content for all registers from gdb
+        int *p=(int*)&gdbRegFile;
+        for (i=0; i<sizeof(GdbRegFile)/4; i++) *p++=iswap(gdbGetHexVal(&data, 32));;
+        gdbPacketStart();
+        gdbPacketStr("OK");
+        gdbPacketEnd();
+    } else if (cmd[0]=='m') {    //read memory to gdb
+        unsigned int j;
+        i=gdbGetHexVal(&data, -1);
+        data++;
+        j=gdbGetHexVal(&data, -1);
+        gdbPacketStart();
+        for (unsigned k=0; k<j; k++) {
+            gdbPacketHex(readbyte(i++), 8);
+        }
+        gdbPacketEnd();
+    } else if (cmd[0]=='?') {    //Reply with stop reason
+        sendReason();
+    } else {
+        //We don't recognize or support whatever GDB just sent us.
+        gdbPacketStart();
+        gdbPacketEnd();
+        return ST_ERR;
+    }
+    return ST_OK;
+}
+
+
+//Lower layer: grab a command packet and check the checksum
+//Calls gdbHandleCommand on the packet if the checksum is OK
+//Returns ST_OK on success, ST_ERR when checksum fails, a
+//character if it is received instead of the GDB packet
+//start char.
+static int gdbReadCommand(void) {
+    unsigned char c;
+    unsigned char chsum=0, rchsum;
+    unsigned char sentchs[2];
+    int p=0;
+    unsigned char *ptr;
+    c=gdbRecvChar();
+    if (c!='$') return c;
+    while(1) {
+        c=gdbRecvChar();
+        if (c=='#') {    //end of packet, checksum follows
+            cmd[p]=0;
+            break;
+        }
+        chsum+=c;
+        if (c=='$') {
+            //Wut, restart packet?
+            chsum=0;
+            p=0;
+            continue;
+        }
+        if (c=='}') {        //escape the next char
+            c=gdbRecvChar();
+            chsum+=c;
+            c^=0x20;
+        }
+        cmd[p++]=c;
+        if (p>=PBUFLEN) return ST_ERR;
+    }
+    //A # has been received. Get and check the received chsum.
+    sentchs[0]=gdbRecvChar();
+    sentchs[1]=gdbRecvChar();
+    ptr=&sentchs[0];
+    rchsum=gdbGetHexVal(&ptr, 8);
+    if (rchsum!=chsum) {
+        gdbSendChar('-');
+        return ST_ERR;
+    } else {
+        gdbSendChar('+');
+        return gdbHandleCommand(cmd, p);
+    }
+}
+
+
+
+void esp_gdbstub_panic_handler(XtExcFrame *frame) {
+    dumpHwToRegfile(frame);
+    //Make sure txd/rxd are enabled
+    gpio_pullup_dis(1);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, FUNC_U0RXD_U0RXD);
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, FUNC_U0TXD_U0TXD);
+
+    sendReason();
+    while(gdbReadCommand()!=ST_CONT);
+    while(1);
+}
+
+#endif /* MODULE_ESP_GDBSTUB */
diff --git a/cpu/esp32/vendor/esp-idf/esp32/lib_printf.c b/cpu/esp32/vendor/esp-idf/esp32/lib_printf.c
new file mode 100644
index 0000000000000000000000000000000000000000..ed7a537fe7d286b908274e3e47c7cc19fd9d39b0
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/lib_printf.c
@@ -0,0 +1,140 @@
+// Copyright 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.
+
+/**
+ * @file lib_printf.c
+ *
+ * This file contains library-specific printf functions
+ * used by WiFi libraries in the `lib` directory.
+ * These function are used to catch any output which gets printed
+ * by libraries, and redirect it to ESP_LOG macros.
+ *
+ * Eventually WiFi libraries will use ESP_LOG functions internally
+ * and these definitions will be removed.
+ */
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "esp_log.h"
+#include "esp_attr.h"
+
+#define VPRINTF_STACK_BUFFER_SIZE 80
+
+static int lib_printf(const char* tag, const char* format, va_list arg)
+{
+    char temp[VPRINTF_STACK_BUFFER_SIZE];
+    int len = vsnprintf(temp, sizeof(temp) - 1, format, arg);
+    temp[sizeof(temp) - 1] = 0;
+    int i;
+    for (i = len - 1; i >= 0; --i) {
+        if (temp[i] != '\n' && temp[i] != '\r' && temp[i] != ' ') {
+            break;
+        }
+        temp[i] = 0;
+    }
+    if (i > 0) {
+        ESP_EARLY_LOGI(tag, "%s", temp);
+    }
+    va_end(arg);
+    return len;
+}
+
+int phy_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("phy", format, arg);
+    va_end(arg);
+    return res;
+}
+
+
+int rtc_printf(const char* format, ...)
+{
+    // librtc.a printf temporary disabled due to UART baud rate switching bug.
+    return 0;
+}
+
+int wpa_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("wpa", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int wpa2_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("wpa2", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int wps_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("wps", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int pp_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("pp", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int sc_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("smartconfig", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int core_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("core", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int net80211_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("net80211", format, arg);
+    va_end(arg);
+    return res;
+}
+
+int coexist_printf(const char* format, ...)
+{
+    va_list arg;
+    va_start(arg, format);
+    int res = lib_printf("coexist", format, arg);
+    va_end(arg);
+    return res;
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/phy_init.c b/cpu/esp32/vendor/esp-idf/esp32/phy_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..60c1af2556a5f77ae0cf9ddbbc4562c3a4daa5e5
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/phy_init.c
@@ -0,0 +1,572 @@
+// 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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+#include <sys/lock.h>
+
+#include "rom/ets_sys.h"
+#include "rom/rtc.h"
+#include "soc/rtc.h"
+#include "soc/dport_reg.h"
+
+#include "esp_err.h"
+#include "esp_phy_init.h"
+#include "esp_system.h"
+#include "esp_log.h"
+#include "nvs.h"
+#include "nvs_flash.h"
+#include "sdk_conf.h"
+
+#include "phy.h"
+#include "phy_init_data.h"
+#include "coexist_internal.h"
+#include "driver/periph_ctrl.h"
+#include "esp_wifi_internal.h"
+
+static const char* TAG = "phy_init";
+
+static _lock_t s_phy_rf_init_lock;
+
+/* Bit mask of modules needing to call phy_rf_init */
+static uint32_t s_module_phy_rf_init = 0;
+
+/* Whether modern sleep in turned on */
+static volatile bool s_is_phy_rf_en = false;
+
+/* Bit mask of modules needing to enter modem sleep mode */
+static uint32_t s_modem_sleep_module_enter = 0;
+
+/* Bit mask of modules which might use RF, system can enter modem
+ * sleep mode only when all modules registered require to enter
+ * modem sleep*/
+static uint32_t s_modem_sleep_module_register = 0;
+
+/* Whether modern sleep is turned on */
+static volatile bool s_is_modem_sleep_en = false;
+
+static _lock_t s_modem_sleep_lock;
+
+uint32_t IRAM_ATTR phy_enter_critical(void)
+{
+    return portENTER_CRITICAL_NESTED();
+}
+
+void IRAM_ATTR phy_exit_critical(uint32_t level)
+{
+    portEXIT_CRITICAL_NESTED(level);
+}
+
+esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibration_mode_t mode,
+                          esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module)
+{
+    /* 3 modules may call phy_init: Wi-Fi, BT, Modem Sleep */
+    if (module >= PHY_MODULE_COUNT){
+        ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \
+                 module count(%d)", __func__, module, PHY_MODULE_COUNT);
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    _lock_acquire(&s_phy_rf_init_lock);
+    uint32_t s_module_phy_rf_init_old = s_module_phy_rf_init;
+    bool is_wifi_or_bt_enabled = !!(s_module_phy_rf_init_old & (BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE)));
+    esp_err_t status = ESP_OK;
+    s_module_phy_rf_init |= BIT(module);
+
+    if ((is_wifi_or_bt_enabled == false) && (module == PHY_MODEM_MODULE)){
+        status = ESP_FAIL;
+    }
+    else if (s_is_phy_rf_en == true) {
+    }
+    else {
+        /* If Wi-Fi, BT all disabled, modem sleep should not take effect;
+         * If either Wi-Fi or BT is enabled, should allow modem sleep requires
+         * to enter sleep;
+         * If Wi-Fi, BT co-exist, it is disallowed that only one module
+         * support modem sleep, E,g. BT support modem sleep but Wi-Fi not
+         * support modem sleep;
+         */
+        if (is_wifi_or_bt_enabled == false){
+            if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){
+                s_is_phy_rf_en = true;
+            }
+        }
+        else {
+            if (module == PHY_MODEM_MODULE){
+                s_is_phy_rf_en = true;
+            }
+            else if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){
+                /* New module (BT or Wi-Fi) can init RF according to modem_sleep_exit */
+            }
+        }
+        if (s_is_phy_rf_en == true){
+            // Enable WiFi/BT common peripheral clock
+            periph_module_enable(PERIPH_WIFI_BT_COMMON_MODULE);
+            phy_set_wifi_mode_only(0);
+
+            if (ESP_CAL_DATA_CHECK_FAIL == register_chipv7_phy(init_data, calibration_data, mode)) {
+                ESP_LOGW(TAG, "saving new calibration data because of checksum failure, mode(%d)", mode);
+#ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
+                if (mode != PHY_RF_CAL_FULL) {
+                    esp_phy_store_cal_data_to_nvs(calibration_data);
+                }
+#endif
+            }
+
+extern esp_err_t wifi_osi_funcs_register(wifi_osi_funcs_t *osi_funcs);
+            status = wifi_osi_funcs_register(&g_wifi_osi_funcs);
+            if(status != ESP_OK) {
+                ESP_LOGE(TAG, "failed to register wifi os adapter, ret(%d)", status);
+                _lock_release(&s_phy_rf_init_lock);
+                return ESP_FAIL;
+            }
+            coex_bt_high_prio();
+        }
+    }
+
+#if CONFIG_SW_COEXIST_ENABLE
+    if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){
+        uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE);
+        if ((s_module_phy_rf_init & phy_bt_wifi_mask) == phy_bt_wifi_mask) { //both wifi & bt enabled
+            coex_init();
+            coex_preference_set(CONFIG_SW_COEXIST_PREFERENCE_VALUE);
+            coex_resume();
+        }
+    }
+#endif
+
+    _lock_release(&s_phy_rf_init_lock);
+    return status;
+}
+
+esp_err_t esp_phy_rf_deinit(phy_rf_module_t module)
+{
+    /* 3 modules may call phy_init: Wi-Fi, BT, Modem Sleep */
+    if (module >= PHY_MODULE_COUNT){
+        ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \
+                 module count(%d)", __func__, module, PHY_MODULE_COUNT);
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    _lock_acquire(&s_phy_rf_init_lock);
+    uint32_t s_module_phy_rf_init_old = s_module_phy_rf_init;
+    uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE);
+    bool is_wifi_or_bt_enabled = !!(s_module_phy_rf_init_old & phy_bt_wifi_mask);
+    bool is_both_wifi_bt_enabled = ((s_module_phy_rf_init_old & phy_bt_wifi_mask) == phy_bt_wifi_mask);
+    s_module_phy_rf_init &= ~BIT(module);
+    esp_err_t status = ESP_OK;
+
+#if CONFIG_SW_COEXIST_ENABLE
+    if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){
+        if (is_both_wifi_bt_enabled == true) {
+            coex_deinit();
+        }
+    }
+#endif
+
+    if ((is_wifi_or_bt_enabled == false) && (module == PHY_MODEM_MODULE)){
+        /* Modem sleep should not take effect in this case */
+        status = ESP_FAIL;
+    }
+    else if (s_is_phy_rf_en == false) {
+        //do nothing
+    }
+    else {
+        if (is_wifi_or_bt_enabled == false){
+            if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){
+                s_is_phy_rf_en = false;
+                ESP_LOGE(TAG, "%s, RF should not be in enabled state if both Wi-Fi and BT are disabled", __func__);
+            }
+        }
+        else {
+            if (module == PHY_MODEM_MODULE){
+                s_is_phy_rf_en = false;
+            }
+            else if ((module == PHY_BT_MODULE) || (module == PHY_WIFI_MODULE)){
+                s_is_phy_rf_en = is_both_wifi_bt_enabled ? true : false;
+            }
+        }
+
+        if (s_is_phy_rf_en == false) {
+            // Disable PHY and RF.
+            phy_close_rf();
+            // Disable WiFi/BT common peripheral clock. Do not disable clock for hardware RNG
+            periph_module_disable(PERIPH_WIFI_BT_COMMON_MODULE);
+        }
+    }
+
+    _lock_release(&s_phy_rf_init_lock);
+    return status;
+}
+
+
+
+esp_err_t esp_modem_sleep_enter(modem_sleep_module_t module)
+{
+#if CONFIG_SW_COEXIST_ENABLE
+    uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE);
+#endif
+
+    if (module >= MODEM_MODULE_COUNT){
+        ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \
+                 module count(%d)", __func__, module, MODEM_MODULE_COUNT);
+        return ESP_ERR_INVALID_ARG;
+    }
+    else if (!(s_modem_sleep_module_register & BIT(module))){
+        ESP_LOGW(TAG, "%s, module (%d) has not been registered", __func__, module);
+        return ESP_ERR_INVALID_ARG;
+    }
+    else {
+        _lock_acquire(&s_modem_sleep_lock);
+        s_modem_sleep_module_enter |= BIT(module);
+#if CONFIG_SW_COEXIST_ENABLE
+        _lock_acquire(&s_phy_rf_init_lock);
+        if (((s_module_phy_rf_init & phy_bt_wifi_mask) == phy_bt_wifi_mask)  //both wifi & bt enabled
+                && (s_modem_sleep_module_enter & (MODEM_BT_MASK | MODEM_WIFI_MASK)) != 0){
+            coex_pause();
+        }
+        _lock_release(&s_phy_rf_init_lock);
+#endif
+        if (!s_is_modem_sleep_en && (s_modem_sleep_module_enter == s_modem_sleep_module_register)){
+            esp_err_t status = esp_phy_rf_deinit(PHY_MODEM_MODULE);
+            if (status == ESP_OK){
+                s_is_modem_sleep_en = true;
+            }
+        }
+        _lock_release(&s_modem_sleep_lock);
+        return ESP_OK;
+    }
+}
+
+esp_err_t esp_modem_sleep_exit(modem_sleep_module_t module)
+{
+#if CONFIG_SW_COEXIST_ENABLE
+    uint32_t phy_bt_wifi_mask = BIT(PHY_BT_MODULE) | BIT(PHY_WIFI_MODULE);
+#endif
+
+    if (module >= MODEM_MODULE_COUNT){
+        ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \
+                 module count(%d)", __func__, module, MODEM_MODULE_COUNT);
+        return ESP_ERR_INVALID_ARG;
+    }
+    else if (!(s_modem_sleep_module_register & BIT(module))){
+        ESP_LOGW(TAG, "%s, module (%d) has not been registered", __func__, module);
+        return ESP_ERR_INVALID_ARG;
+    }
+    else {
+        _lock_acquire(&s_modem_sleep_lock);
+        s_modem_sleep_module_enter &= ~BIT(module);
+        if (s_is_modem_sleep_en){
+            esp_err_t status = esp_phy_rf_init(NULL,PHY_RF_CAL_NONE,NULL, PHY_MODEM_MODULE);
+            if (status == ESP_OK){
+                s_is_modem_sleep_en = false;
+            }
+        }
+#if CONFIG_SW_COEXIST_ENABLE
+        _lock_acquire(&s_phy_rf_init_lock);
+        if (((s_module_phy_rf_init & phy_bt_wifi_mask) == phy_bt_wifi_mask)  //both wifi & bt enabled
+                && (s_modem_sleep_module_enter & (MODEM_BT_MASK | MODEM_WIFI_MASK)) == 0){
+            coex_resume();
+        }
+        _lock_release(&s_phy_rf_init_lock);
+#endif
+        _lock_release(&s_modem_sleep_lock);
+        return ESP_OK;
+    }
+    return ESP_OK;
+}
+
+esp_err_t esp_modem_sleep_register(modem_sleep_module_t module)
+{
+    if (module >= MODEM_MODULE_COUNT){
+        ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \
+                 module count(%d)", __func__, module, MODEM_MODULE_COUNT);
+        return ESP_ERR_INVALID_ARG;
+    }
+    else if (s_modem_sleep_module_register & BIT(module)){
+        ESP_LOGI(TAG, "%s, multiple registration of module (%d)", __func__, module);
+        return ESP_OK;
+    }
+    else{
+        _lock_acquire(&s_modem_sleep_lock);
+        s_modem_sleep_module_register |= BIT(module);
+        /* The module is set to enter modem sleep by default, otherwise will prevent
+         * other modules from entering sleep mode if this module never call enter sleep function
+         * in the future */
+        s_modem_sleep_module_enter |= BIT(module);
+        _lock_release(&s_modem_sleep_lock);
+        return ESP_OK;
+    }
+}
+
+esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module)
+{
+    if (module >= MODEM_MODULE_COUNT){
+        ESP_LOGE(TAG, "%s, invalid module parameter(%d), should be smaller than \
+                 module count(%d)", __func__, module, MODEM_MODULE_COUNT);
+        return ESP_ERR_INVALID_ARG;
+    }
+    else if (!(s_modem_sleep_module_register & BIT(module))){
+        ESP_LOGI(TAG, "%s, module (%d) has not been registered", __func__, module);
+        return ESP_OK;
+    }
+    else{
+        _lock_acquire(&s_modem_sleep_lock);
+        s_modem_sleep_module_enter &= ~BIT(module);
+        s_modem_sleep_module_register &= ~BIT(module);
+        if (s_modem_sleep_module_register == 0){
+            s_modem_sleep_module_enter = 0;
+            /* Once all module are de-registered and current state
+             * is modem sleep mode, we need to turn off modem sleep
+             */
+            if (s_is_modem_sleep_en == true){
+               s_is_modem_sleep_en = false;
+               esp_phy_rf_init(NULL,PHY_RF_CAL_NONE,NULL, PHY_MODEM_MODULE);
+            }
+        }
+        _lock_release(&s_modem_sleep_lock);
+        return ESP_OK;
+    }
+}
+
+
+// PHY init data handling functions
+#if CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
+#include "esp_partition.h"
+
+const esp_phy_init_data_t* esp_phy_get_init_data()
+{
+    const esp_partition_t* partition = esp_partition_find_first(
+            ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_PHY, NULL);
+    if (partition == NULL) {
+        ESP_LOGE(TAG, "PHY data partition not found");
+        return NULL;
+    }
+    ESP_LOGD(TAG, "loading PHY init data from partition at offset 0x%x", partition->address);
+    size_t init_data_store_length = sizeof(phy_init_magic_pre) +
+            sizeof(esp_phy_init_data_t) + sizeof(phy_init_magic_post);
+    uint8_t* init_data_store = (uint8_t*) malloc(init_data_store_length);
+    if (init_data_store == NULL) {
+        ESP_LOGE(TAG, "failed to allocate memory for PHY init data");
+        return NULL;
+    }
+    esp_err_t err = esp_partition_read(partition, 0, init_data_store, init_data_store_length);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "failed to read PHY data partition (0x%x)", err);
+        return NULL;
+    }
+    if (memcmp(init_data_store, PHY_INIT_MAGIC, sizeof(phy_init_magic_pre)) != 0 ||
+        memcmp(init_data_store + init_data_store_length - sizeof(phy_init_magic_post),
+                PHY_INIT_MAGIC, sizeof(phy_init_magic_post)) != 0) {
+        ESP_LOGE(TAG, "failed to validate PHY data partition");
+        return NULL;
+    }
+    ESP_LOGD(TAG, "PHY data partition validated");
+    return (const esp_phy_init_data_t*) (init_data_store + sizeof(phy_init_magic_pre));
+}
+
+void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
+{
+    free((uint8_t*) init_data - sizeof(phy_init_magic_pre));
+}
+
+#else // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
+
+// phy_init_data.h will declare static 'phy_init_data' variable initialized with default init data
+
+const esp_phy_init_data_t* esp_phy_get_init_data(void)
+{
+    ESP_LOGD(TAG, "loading PHY init data from application binary");
+    return &phy_init_data;
+}
+
+void esp_phy_release_init_data(const esp_phy_init_data_t* init_data)
+{
+    // no-op
+}
+#endif // CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION
+
+
+// PHY calibration data handling functions
+static const char* PHY_NAMESPACE = "phy";
+static const char* PHY_CAL_VERSION_KEY = "cal_version";
+static const char* PHY_CAL_MAC_KEY = "cal_mac";
+static const char* PHY_CAL_DATA_KEY = "cal_data";
+
+static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
+        esp_phy_calibration_data_t* out_cal_data);
+
+static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
+        const esp_phy_calibration_data_t* cal_data);
+
+esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data)
+{
+    nvs_handle handle;
+    esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READONLY, &handle);
+    if (err == ESP_ERR_NVS_NOT_INITIALIZED) {
+        ESP_LOGE(TAG, "%s: NVS has not been initialized. "
+                "Call nvs_flash_init before starting WiFi/BT.", __func__);
+    } else if (err != ESP_OK) {
+        ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
+        return err;
+    }
+    err = load_cal_data_from_nvs_handle(handle, out_cal_data);
+    nvs_close(handle);
+    return err;
+}
+
+esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data)
+{
+    nvs_handle handle;
+    esp_err_t err = nvs_open(PHY_NAMESPACE, NVS_READWRITE, &handle);
+    if (err != ESP_OK) {
+        ESP_LOGD(TAG, "%s: failed to open NVS namespace (0x%x)", __func__, err);
+        return err;
+    }
+    else {
+        err = store_cal_data_to_nvs_handle(handle, cal_data);
+        nvs_close(handle);
+        return err;
+    }
+}
+
+static esp_err_t load_cal_data_from_nvs_handle(nvs_handle handle,
+        esp_phy_calibration_data_t* out_cal_data)
+{
+    esp_err_t err;
+    uint32_t cal_data_version;
+    err = nvs_get_u32(handle, PHY_CAL_VERSION_KEY, &cal_data_version);
+    if (err != ESP_OK) {
+        ESP_LOGD(TAG, "%s: failed to get cal_version (0x%x)", __func__, err);
+        return err;
+    }
+    uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
+    ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
+    if (cal_data_version != cal_format_version) {
+        ESP_LOGD(TAG, "%s: expected calibration data format %d, found %d",
+                __func__, cal_format_version, cal_data_version);
+        return ESP_FAIL;
+    }
+    uint8_t cal_data_mac[6];
+    size_t length = sizeof(cal_data_mac);
+    err = nvs_get_blob(handle, PHY_CAL_MAC_KEY, cal_data_mac, &length);
+    if (err != ESP_OK) {
+        ESP_LOGD(TAG, "%s: failed to get cal_mac (0x%x)", __func__, err);
+        return err;
+    }
+    if (length != sizeof(cal_data_mac)) {
+        ESP_LOGD(TAG, "%s: invalid length of cal_mac (%d)", __func__, length);
+        return ESP_ERR_INVALID_SIZE;
+    }
+    uint8_t sta_mac[6];
+    esp_efuse_mac_get_default(sta_mac);
+    if (memcmp(sta_mac, cal_data_mac, sizeof(sta_mac)) != 0) {
+        ESP_LOGE(TAG, "%s: calibration data MAC check failed: expected " \
+                MACSTR ", found " MACSTR,
+                __func__, MAC2STR(sta_mac), MAC2STR(cal_data_mac));
+        return ESP_FAIL;
+    }
+    length = sizeof(*out_cal_data);
+    err = nvs_get_blob(handle, PHY_CAL_DATA_KEY, out_cal_data, &length);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "%s: failed to get cal_data(0x%x)", __func__, err);
+        return err;
+    }
+    if (length != sizeof(*out_cal_data)) {
+        ESP_LOGD(TAG, "%s: invalid length of cal_data (%d)", __func__, length);
+        return ESP_ERR_INVALID_SIZE;
+    }
+    return ESP_OK;
+}
+
+static esp_err_t store_cal_data_to_nvs_handle(nvs_handle handle,
+        const esp_phy_calibration_data_t* cal_data)
+{
+    esp_err_t err;
+
+    err = nvs_set_blob(handle, PHY_CAL_DATA_KEY, cal_data, sizeof(*cal_data));
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "%s: store calibration data failed(0x%x)\n", __func__, err);
+        return err;
+    }
+
+    uint8_t sta_mac[6];
+    esp_efuse_mac_get_default(sta_mac);
+    err = nvs_set_blob(handle, PHY_CAL_MAC_KEY, sta_mac, sizeof(sta_mac));
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "%s: store calibration mac failed(0x%x)\n", __func__, err);
+        return err;
+    }
+
+    uint32_t cal_format_version = phy_get_rf_cal_version() & (~BIT(16));
+    ESP_LOGV(TAG, "phy_get_rf_cal_version: %d\n", cal_format_version);
+    err = nvs_set_u32(handle, PHY_CAL_VERSION_KEY, cal_format_version);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "%s: store calibration version failed(0x%x)\n", __func__, err);
+        return err;
+    }
+
+    err = nvs_commit(handle);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "%s: store calibration nvs commit failed(0x%x)\n", __func__, err);
+    }
+
+    return err;
+}
+
+void esp_phy_load_cal_and_init(phy_rf_module_t module)
+{
+    esp_phy_calibration_data_t* cal_data =
+            (esp_phy_calibration_data_t*) calloc(sizeof(esp_phy_calibration_data_t), 1);
+    if (cal_data == NULL) {
+        ESP_LOGE(TAG, "failed to allocate memory for RF calibration data");
+        abort();
+    }
+
+    const esp_phy_init_data_t* init_data = esp_phy_get_init_data();
+    if (init_data == NULL) {
+        ESP_LOGE(TAG, "failed to obtain PHY init data");
+        abort();
+    }
+
+#ifdef CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE
+    esp_phy_calibration_mode_t calibration_mode = PHY_RF_CAL_PARTIAL;
+    uint8_t sta_mac[6];
+    if (rtc_get_reset_reason(0) == DEEPSLEEP_RESET) {
+        calibration_mode = PHY_RF_CAL_NONE;
+    }
+    esp_err_t err = esp_phy_load_cal_data_from_nvs(cal_data);
+    if (err != ESP_OK) {
+        ESP_LOGW(TAG, "failed to load RF calibration data (0x%x), falling back to full calibration", err);
+        calibration_mode = PHY_RF_CAL_FULL;
+    }
+
+    esp_efuse_mac_get_default(sta_mac);
+    memcpy(cal_data->mac, sta_mac, 6);
+    esp_phy_rf_init(init_data, calibration_mode, cal_data, module);
+
+    if (calibration_mode != PHY_RF_CAL_NONE && err != ESP_OK) {
+        esp_phy_store_cal_data_to_nvs(cal_data);
+    }
+#else
+    esp_phy_rf_init(init_data, PHY_RF_CAL_FULL, cal_data, module);
+#endif
+
+    esp_phy_release_init_data(init_data);
+
+    free(cal_data); // PHY maintains a copy of calibration data, so we can free this
+}
diff --git a/cpu/esp32/vendor/esp-idf/esp32/spiram.c b/cpu/esp32/vendor/esp-idf/esp32/spiram.c
new file mode 100644
index 0000000000000000000000000000000000000000..83319c29498cdbf60107d8b7e3c8aeee5ab308f0
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/spiram.c
@@ -0,0 +1,209 @@
+/*
+Abstraction layer for spi-ram. For now, it's no more than a stub for the spiram_psram functions, but if
+we add more types of external RAM memory, this can be made into a more intelligent dispatcher.
+*/
+
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+#include <string.h>
+
+#include "sdk_conf.h"
+#include "esp_attr.h"
+#include "esp_err.h"
+#include "spiram_psram.h"
+#include "esp_log.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/xtensa_api.h"
+#include "soc/soc.h"
+#include "esp_heap_caps_init.h"
+#include "soc/soc_memory_layout.h"
+#include "soc/dport_reg.h"
+#include "rom/cache.h"
+
+#if CONFIG_FREERTOS_UNICORE
+#define PSRAM_MODE PSRAM_VADDR_MODE_NORMAL
+#else
+#if CONFIG_MEMMAP_SPIRAM_CACHE_EVENODD
+#define PSRAM_MODE PSRAM_VADDR_MODE_EVENODD
+#else
+#define PSRAM_MODE PSRAM_VADDR_MODE_LOWHIGH
+#endif
+#endif
+
+#if CONFIG_SPIRAM_SUPPORT
+
+static const char* TAG = "spiram";
+
+#if CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_40M
+#define PSRAM_SPEED PSRAM_CACHE_F40M_S40M
+#elif CONFIG_SPIRAM_SPEED_40M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
+#define PSRAM_SPEED PSRAM_CACHE_F80M_S40M
+#elif CONFIG_SPIRAM_SPEED_80M && CONFIG_ESPTOOLPY_FLASHFREQ_80M
+#define PSRAM_SPEED PSRAM_CACHE_F80M_S80M
+#else
+#error "FLASH speed can only be equal to or higher than SRAM speed while SRAM is enabled!"
+#endif
+
+
+static bool spiram_inited=false;
+
+
+/*
+ Simple RAM test. Writes a word every 32 bytes. Takes about a second to complete for 4MiB. Returns
+ true when RAM seems OK, false when test fails. WARNING: Do not run this before the 2nd cpu has been
+ initialized (in a two-core system) or after the heap allocator has taken ownership of the memory.
+*/
+bool esp_spiram_test(void)
+{
+    volatile int *spiram=(volatile int*)SOC_EXTRAM_DATA_LOW;
+    size_t p;
+    size_t s=CONFIG_SPIRAM_SIZE;
+    int errct=0;
+    int initial_err=-1;
+    for (p=0; p<(s/sizeof(int)); p+=8) {
+        spiram[p]=p^0xAAAAAAAA;
+    }
+    for (p=0; p<(s/sizeof(int)); p+=8) {
+        if ((unsigned)(spiram[p])!=(p^0xAAAAAAAA)) {
+            errct++;
+            if (errct==1) initial_err=p*4;
+        }
+    }
+    if (errct) {
+        ESP_EARLY_LOGE(TAG, "SPI SRAM memory test fail. %d/%d writes failed, first @ %X\n", errct, s/32, initial_err+SOC_EXTRAM_DATA_LOW);
+        return false;
+    } else {
+        ESP_EARLY_LOGI(TAG, "SPI SRAM memory test OK");
+        return true;
+    }
+}
+
+void IRAM_ATTR esp_spiram_init_cache(void)
+{
+    //Enable external RAM in MMU
+    cache_sram_mmu_set( 0, 0, SOC_EXTRAM_DATA_LOW, 0, 32, 128 );
+    //Flush and enable icache for APP CPU
+#if !CONFIG_FREERTOS_UNICORE
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1);
+    cache_sram_mmu_set( 1, 0, SOC_EXTRAM_DATA_LOW, 0, 32, 128 );
+#endif
+}
+
+
+esp_err_t esp_spiram_init(void)
+{
+    esp_err_t r;
+    r = psram_enable(PSRAM_SPEED, PSRAM_MODE);
+    if (r != ESP_OK) {
+#if CONFIG_SPIRAM_IGNORE_NOTFOUND
+        ESP_EARLY_LOGE(TAG, "SPI RAM enabled but initialization failed. Bailing out.");
+#endif
+        return r;
+    }
+
+    ESP_EARLY_LOGI(TAG, "SPI RAM mode: %s", PSRAM_SPEED == PSRAM_CACHE_F40M_S40M ? "flash 40m sram 40m" : \
+                                          PSRAM_SPEED == PSRAM_CACHE_F80M_S40M ? "flash 80m sram 40m" : \
+                                          PSRAM_SPEED == PSRAM_CACHE_F80M_S80M ? "flash 80m sram 80m" : "ERROR");
+    ESP_EARLY_LOGI(TAG, "PSRAM initialized, cache is in %s mode.", \
+                                          (PSRAM_MODE==PSRAM_VADDR_MODE_EVENODD)?"even/odd (2-core)": \
+                                          (PSRAM_MODE==PSRAM_VADDR_MODE_LOWHIGH)?"low/high (2-core)": \
+                                          (PSRAM_MODE==PSRAM_VADDR_MODE_NORMAL)?"normal (1-core)":"ERROR");
+    spiram_inited=true;
+    return ESP_OK;
+}
+
+
+esp_err_t esp_spiram_add_to_heapalloc(void)
+{
+    ESP_EARLY_LOGI(TAG, "Adding pool of %dK of external SPI memory to heap allocator", CONFIG_SPIRAM_SIZE/1024);
+    //Add entire external RAM region to heap allocator. Heap allocator knows the capabilities of this type of memory, so there's
+    //no need to explicitly specify them.
+    return heap_caps_add_region((intptr_t)SOC_EXTRAM_DATA_LOW, (intptr_t)SOC_EXTRAM_DATA_LOW + CONFIG_SPIRAM_SIZE-1);
+}
+
+
+static uint8_t *dma_heap;
+
+esp_err_t esp_spiram_reserve_dma_pool(size_t size) {
+    if (size==0) return ESP_OK; //no-op
+    ESP_EARLY_LOGI(TAG, "Reserving pool of %dK of internal memory for DMA/internal allocations", size/1024);
+    dma_heap=heap_caps_malloc(size, MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL);
+    if (!dma_heap) return ESP_ERR_NO_MEM;
+    uint32_t caps[]={MALLOC_CAP_DMA|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT};
+    return heap_caps_add_region_with_caps(caps, (intptr_t) dma_heap, (intptr_t) dma_heap+size-1);
+}
+
+size_t esp_spiram_get_size(void)
+{
+    return CONFIG_SPIRAM_SIZE;
+}
+
+/*
+ Before flushing the cache, if psram is enabled as a memory-mapped thing, we need to write back the data in the cache to the psram first,
+ otherwise it will get lost. For now, we just read 64/128K of random PSRAM memory to do this.
+*/
+void IRAM_ATTR esp_spiram_writeback_cache(void)
+{
+    int x;
+    volatile int i=0;
+    volatile uint8_t *psram=(volatile uint8_t*)SOC_EXTRAM_DATA_LOW;
+    int cache_was_disabled=0;
+
+    if (!spiram_inited) return;
+
+    //We need cache enabled for this to work. Re-enable it if needed; make sure we
+    //disable it again on exit as well.
+    if (DPORT_REG_GET_BIT(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_CACHE_ENABLE)==0) {
+        cache_was_disabled|=(1<<0);
+        DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 1, DPORT_PRO_CACHE_ENABLE_S);
+    }
+#ifndef CONFIG_FREERTOS_UNICORE
+    if (DPORT_REG_GET_BIT(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_CACHE_ENABLE)==0) {
+        cache_was_disabled|=(1<<1);
+        DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 1, DPORT_APP_CACHE_ENABLE_S);
+    }
+#endif
+
+#if CONFIG_FREERTOS_UNICORE
+    for (x=0; x<1024*64; x+=32) {
+        i+=psram[x];
+    }
+#else
+    /*
+    Note: this assumes the amount of external RAM is >2M. If it is 2M or less, what this code does is undefined. If
+    we ever support external RAM chips of 2M or smaller, this may need adjusting.
+    */
+    for (x=0; x<1024*64; x+=32) {
+        i+=psram[x];
+        i+=psram[x+(1024*1024*2)+(1024*64)]; //address picked to also clear cache of app cpu in low/high mode
+    }
+#endif
+
+    if (cache_was_disabled&(1<<0)) {
+        while (DPORT_GET_PERI_REG_BITS2(DPORT_PRO_DCACHE_DBUG0_REG, DPORT_PRO_CACHE_STATE, DPORT_PRO_CACHE_STATE_S) != 1) ;
+        DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL_REG, 1, 0, DPORT_PRO_CACHE_ENABLE_S);
+    }
+#ifndef CONFIG_FREERTOS_UNICORE
+    if (cache_was_disabled&(1<<1)) {
+        while (DPORT_GET_PERI_REG_BITS2(DPORT_APP_DCACHE_DBUG0_REG, DPORT_APP_CACHE_STATE, DPORT_APP_CACHE_STATE_S) != 1);
+        DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL_REG, 1, 0, DPORT_APP_CACHE_ENABLE_S);
+    }
+#endif
+}
+
+
+
+#endif
diff --git a/cpu/esp32/vendor/esp-idf/esp32/spiram_psram.c b/cpu/esp32/vendor/esp-idf/esp32/spiram_psram.c
new file mode 100644
index 0000000000000000000000000000000000000000..91cb79f053f71d4e1bb2acdb7c3b9c65fcb805c5
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/spiram_psram.c
@@ -0,0 +1,705 @@
+/*
+ Driver bits for PSRAM chips (at the moment only the ESP-PSRAM32 chip).
+*/
+
+// Copyright 2013-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+#include "sdk_conf.h"
+#include "string.h"
+#include "esp_attr.h"
+#include "esp_err.h"
+#include "esp_types.h"
+#include "esp_log.h"
+#include "spiram_psram.h"
+#include "rom/ets_sys.h"
+#include "rom/spi_flash.h"
+#include "rom/cache.h"
+#include "soc/io_mux_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/gpio_reg.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/efuse_reg.h"
+#include "driver/gpio.h"
+#include "driver/spi_common.h"
+#include "driver/periph_ctrl.h"
+
+#if CONFIG_SPIRAM_SUPPORT
+#include "soc/rtc.h"
+
+//Commands for PSRAM chip
+#define PSRAM_READ              0x03
+#define PSRAM_FAST_READ         0x0B
+#define PSRAM_FAST_READ_DUMMY   0x3
+#define PSRAM_FAST_READ_QUAD    0xEB
+#define PSRAM_WRITE             0x02
+#define PSRAM_QUAD_WRITE        0x38
+#define PSRAM_ENTER_QMODE       0x35
+#define PSRAM_EXIT_QMODE        0xF5
+#define PSRAM_RESET_EN          0x66
+#define PSRAM_RESET             0x99
+#define PSRAM_SET_BURST_LEN     0xC0
+#define PSRAM_DEVICE_ID         0x9F
+
+#if CONFIG_SPIRAM_TYPE_ESPPSRAM32
+
+#define PSRAM_MFG_ID_M          0xff
+#define PSRAM_MFG_ID_S             8
+#define PSRAM_MFG_ID_V          0x5d
+
+#endif
+
+// IO-pins for PSRAM. These need to be in the VDD_SIO power domain because all chips we
+// currently support are 1.8V parts.
+// WARNING: PSRAM shares all but the CS and CLK pins with the flash, so these defines
+// hardcode the flash pins as well, making this code incompatible with either a setup
+// that has the flash on non-standard pins or ESP32s with built-in flash.
+#define FLASH_CLK_IO      6  //Psram clock is a delayed version of this in 40MHz mode
+#define FLASH_CS_IO       11
+#define PSRAM_CLK_IO      17
+#define PSRAM_CS_IO       16
+#define PSRAM_SPIQ_IO     7
+#define PSRAM_SPID_IO     8
+#define PSRAM_SPIWP_IO    10
+#define PSRAM_SPIHD_IO    9
+
+#define PSRAM_INTERNAL_IO_28       28
+#define PSRAM_INTERNAL_IO_29       29
+#define PSRAM_IO_MATRIX_DUMMY_40M   1
+#define PSRAM_IO_MATRIX_DUMMY_80M   2
+
+#define _SPI_CACHE_PORT   0
+#define _SPI_FLASH_PORT   1
+#define _SPI_80M_CLK_DIV  1
+#define _SPI_40M_CLK_DIV  2
+
+static const char* TAG = "psram";
+typedef enum {
+    PSRAM_SPI_1  = 0x1,
+    PSRAM_SPI_2,
+    PSRAM_SPI_3,
+    PSRAM_SPI_MAX ,
+} psram_spi_num_t;
+
+static psram_cache_mode_t s_psram_mode = PSRAM_CACHE_MAX;
+
+/* dummy_len_plus values defined in ROM for SPI flash configuration */
+extern uint8_t g_rom_spiflash_dummy_len_plus[];
+
+static int extra_dummy = 0;
+
+typedef enum {
+    PSRAM_CMD_QPI,
+    PSRAM_CMD_SPI,
+} psram_cmd_mode_t;
+
+typedef struct {
+    uint16_t cmd;                /*!< Command value */
+    uint16_t cmdBitLen;          /*!< Command byte length*/
+    uint32_t *addr;              /*!< Point to address value*/
+    uint16_t addrBitLen;         /*!< Address byte length*/
+    uint32_t *txData;            /*!< Point to send data buffer*/
+    uint16_t txDataBitLen;       /*!< Send data byte length.*/
+    uint32_t *rxData;            /*!< Point to recevie data buffer*/
+    uint16_t rxDataBitLen;       /*!< Recevie Data byte length.*/
+    uint32_t dummyBitLen;
+} psram_cmd_t;
+
+static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode);
+
+static void psram_clear_spi_fifo(psram_spi_num_t spi_num)
+{
+    int i;
+    for (i = 0; i < 16; i++) {
+        WRITE_PERI_REG(SPI_W0_REG(spi_num)+i*4, 0);
+    }
+}
+
+//set basic SPI write mode
+static void psram_set_basic_write_mode(psram_spi_num_t spi_num)
+{
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QIO);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DIO);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QUAD);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DUAL);
+}
+//set QPI write mode
+static void psram_set_qio_write_mode(psram_spi_num_t spi_num)
+{
+    SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QIO);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DIO);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_QUAD);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_FWRITE_DUAL);
+}
+//set QPI read mode
+static void psram_set_qio_read_mode(psram_spi_num_t spi_num)
+{
+    SET_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QIO);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QUAD);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DUAL);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DIO);
+}
+//set SPI read mode
+static void psram_set_basic_read_mode(psram_spi_num_t spi_num)
+{
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QIO);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_QUAD);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DUAL);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_FREAD_DIO);
+}
+
+
+//start sending cmd/addr and optionally, receiving data
+static void IRAM_ATTR psram_cmd_recv_start(psram_spi_num_t spi_num, uint32_t* pRxData, uint16_t rxByteLen,
+        psram_cmd_mode_t cmd_mode)
+{
+    //get cs1
+    CLEAR_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS1_DIS_M);
+    SET_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS0_DIS_M);
+
+    uint32_t mode_backup = (READ_PERI_REG(SPI_USER_REG(spi_num)) >> SPI_FWRITE_DUAL_S) & 0xf;
+    uint32_t rd_mode_backup = READ_PERI_REG(SPI_CTRL_REG(spi_num)) & (SPI_FREAD_DIO_M | SPI_FREAD_DUAL_M | SPI_FREAD_QUAD_M | SPI_FREAD_QIO_M);
+    if (cmd_mode == PSRAM_CMD_SPI) {
+        psram_set_basic_write_mode(spi_num);
+        psram_set_basic_read_mode(spi_num);
+    } else if (cmd_mode == PSRAM_CMD_QPI) {
+        psram_set_qio_write_mode(spi_num);
+        psram_set_qio_read_mode(spi_num);
+    }
+
+    //Wait for SPI0 to idle
+    while ( READ_PERI_REG(SPI_EXT2_REG(0)) != 0);
+    DPORT_SET_PERI_REG_MASK(DPORT_HOST_INF_SEL_REG, 1 << 14);
+
+    // Start send data
+    SET_PERI_REG_MASK(SPI_CMD_REG(spi_num), SPI_USR);
+    while ((READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR));
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_HOST_INF_SEL_REG, 1 << 14);
+
+    //recover spi mode
+    SET_PERI_REG_BITS(SPI_USER_REG(spi_num), (pRxData?SPI_FWRITE_DUAL_M:0xf), mode_backup, SPI_FWRITE_DUAL_S);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), (SPI_FREAD_DIO_M|SPI_FREAD_DUAL_M|SPI_FREAD_QUAD_M|SPI_FREAD_QIO_M));
+    SET_PERI_REG_MASK(SPI_CTRL_REG(spi_num), rd_mode_backup);
+
+    //return cs to cs0
+    SET_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS1_DIS_M);
+    CLEAR_PERI_REG_MASK(SPI_PIN_REG(PSRAM_SPI_1), SPI_CS0_DIS_M);
+
+    if (pRxData) {
+        int idx = 0;
+        // Read data out
+        do {
+            *pRxData++ = READ_PERI_REG(SPI_W0_REG(spi_num) + (idx << 2));
+        } while (++idx < ((rxByteLen / 4) + ((rxByteLen % 4) ? 1 : 0)));
+    }
+}
+
+static uint32_t backup_usr[3];
+static uint32_t backup_usr1[3];
+static uint32_t backup_usr2[3];
+
+
+
+//setup spi command/addr/data/dummy in user mode
+static int psram_cmd_config(psram_spi_num_t spi_num, psram_cmd_t* pInData)
+{
+    while (READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR);
+    backup_usr[spi_num]=READ_PERI_REG(SPI_USER_REG(spi_num));
+    backup_usr1[spi_num]=READ_PERI_REG(SPI_USER1_REG(spi_num));
+    backup_usr2[spi_num]=READ_PERI_REG(SPI_USER2_REG(spi_num));
+    // Set command by user.
+    if (pInData->cmdBitLen != 0) {
+        // Max command length 16 bits.
+        SET_PERI_REG_BITS(SPI_USER2_REG(spi_num), SPI_USR_COMMAND_BITLEN, pInData->cmdBitLen - 1,
+                SPI_USR_COMMAND_BITLEN_S);
+        // Enable command
+        SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_COMMAND);
+        // Load command,bit15-0 is cmd value.
+        SET_PERI_REG_BITS(SPI_USER2_REG(spi_num), SPI_USR_COMMAND_VALUE, pInData->cmd, SPI_USR_COMMAND_VALUE_S);
+    } else {
+        CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_COMMAND);
+        SET_PERI_REG_BITS(SPI_USER2_REG(spi_num), SPI_USR_COMMAND_BITLEN, 0, SPI_USR_COMMAND_BITLEN_S);
+    }
+    // Set Address by user.
+    if (pInData->addrBitLen != 0) {
+        SET_PERI_REG_BITS(SPI_USER1_REG(spi_num), SPI_USR_ADDR_BITLEN, (pInData->addrBitLen - 1), SPI_USR_ADDR_BITLEN_S);
+        // Enable address
+        SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_ADDR);
+        // Set address
+        WRITE_PERI_REG(SPI_ADDR_REG(spi_num), *pInData->addr);
+    } else {
+        CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_ADDR);
+        SET_PERI_REG_BITS(SPI_USER1_REG(spi_num), SPI_USR_ADDR_BITLEN, 0, SPI_USR_ADDR_BITLEN_S);
+    }
+    // Set data by user.
+    uint32_t* p_tx_val = pInData->txData;
+    if (pInData->txDataBitLen != 0) {
+        // Enable MOSI
+        SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MOSI);
+        // Load send buffer
+        int len = (pInData->txDataBitLen + 31) / 32;
+        if (p_tx_val != NULL) {
+            memcpy((void*)SPI_W0_REG(spi_num), p_tx_val, len * 4);
+        }
+        // Set data send buffer length.Max data length 64 bytes.
+        SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spi_num), SPI_USR_MOSI_DBITLEN, (pInData->txDataBitLen - 1),
+                SPI_USR_MOSI_DBITLEN_S);
+    } else {
+        CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MOSI);
+        SET_PERI_REG_BITS(SPI_MOSI_DLEN_REG(spi_num), SPI_USR_MOSI_DBITLEN, 0, SPI_USR_MOSI_DBITLEN_S);
+    }
+    // Set rx data by user.
+    if (pInData->rxDataBitLen != 0) {
+        // Enable MOSI
+        SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MISO);
+        // Set data send buffer length.Max data length 64 bytes.
+        SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spi_num), SPI_USR_MISO_DBITLEN, (pInData->rxDataBitLen - 1),
+                SPI_USR_MISO_DBITLEN_S);
+    } else {
+        CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_USR_MISO);
+        SET_PERI_REG_BITS(SPI_MISO_DLEN_REG(spi_num), SPI_USR_MISO_DBITLEN, 0, SPI_USR_MISO_DBITLEN_S);
+    }
+    if (pInData->dummyBitLen != 0) {
+        SET_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_USR_DUMMY); // dummy en
+        SET_PERI_REG_BITS(SPI_USER1_REG(PSRAM_SPI_1), SPI_USR_DUMMY_CYCLELEN_V, pInData->dummyBitLen - 1,
+                SPI_USR_DUMMY_CYCLELEN_S);  //DUMMY
+    } else {
+        CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_USR_DUMMY); // dummy en
+        SET_PERI_REG_BITS(SPI_USER1_REG(PSRAM_SPI_1), SPI_USR_DUMMY_CYCLELEN_V, 0, SPI_USR_DUMMY_CYCLELEN_S);  //DUMMY
+    }
+    return 0;
+}
+
+void psram_cmd_end(int spi_num) {
+    while (READ_PERI_REG(SPI_CMD_REG(spi_num)) & SPI_USR);
+    WRITE_PERI_REG(SPI_USER_REG(spi_num), backup_usr[spi_num]);
+    WRITE_PERI_REG(SPI_USER1_REG(spi_num), backup_usr1[spi_num]);
+    WRITE_PERI_REG(SPI_USER2_REG(spi_num), backup_usr2[spi_num]);
+}
+
+//exit QPI mode(set back to SPI mode)
+static void psram_disable_qio_mode(psram_spi_num_t spi_num)
+{
+    psram_cmd_t ps_cmd;
+    uint32_t cmd_exit_qpi;
+    switch (s_psram_mode) {
+        case PSRAM_CACHE_F80M_S80M:
+            cmd_exit_qpi = PSRAM_EXIT_QMODE;
+            ps_cmd.txDataBitLen = 8;
+            break;
+        case PSRAM_CACHE_F80M_S40M:
+        case PSRAM_CACHE_F40M_S40M:
+        default:
+            cmd_exit_qpi = PSRAM_EXIT_QMODE << 8;
+            ps_cmd.txDataBitLen = 16;
+            break;
+    }
+    ps_cmd.txData = &cmd_exit_qpi;
+    ps_cmd.cmd = 0;
+    ps_cmd.cmdBitLen = 0;
+    ps_cmd.addr = 0;
+    ps_cmd.addrBitLen = 0;
+    ps_cmd.rxData = NULL;
+    ps_cmd.rxDataBitLen = 0;
+    ps_cmd.dummyBitLen = 0;
+    psram_cmd_config(spi_num, &ps_cmd);
+    psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_QPI);
+    psram_cmd_end(spi_num);
+}
+
+//read psram id
+static void psram_read_id(uint32_t* dev_id)
+{
+    psram_spi_num_t spi_num = PSRAM_SPI_1;
+    psram_disable_qio_mode(spi_num);
+    uint32_t addr = (PSRAM_DEVICE_ID << 24) | 0;
+    uint32_t dummy_bits = 0;
+    psram_cmd_t ps_cmd;
+    switch (s_psram_mode) {
+        case PSRAM_CACHE_F80M_S80M:
+            dummy_bits = 0 + extra_dummy;
+            ps_cmd.cmdBitLen = 0;
+            break;
+        case PSRAM_CACHE_F80M_S40M:
+        case PSRAM_CACHE_F40M_S40M:
+        default:
+            dummy_bits = 0 + extra_dummy;
+            ps_cmd.cmdBitLen = 2;   //this two bits is used to delay 2 clock cycle
+            break;
+    }
+    ps_cmd.cmd = 0;
+    ps_cmd.addr = &addr;
+    ps_cmd.addrBitLen = 4 * 8;
+    ps_cmd.txDataBitLen = 0;
+    ps_cmd.txData = NULL;
+    ps_cmd.rxDataBitLen = 4 * 8;
+    ps_cmd.rxData = dev_id;
+    ps_cmd.dummyBitLen = dummy_bits;
+    psram_cmd_config(spi_num, &ps_cmd);
+    psram_clear_spi_fifo(spi_num);
+    psram_cmd_recv_start(spi_num, ps_cmd.rxData, ps_cmd.rxDataBitLen / 8, PSRAM_CMD_SPI);
+    psram_cmd_end(spi_num);
+}
+
+//enter QPI mode
+static esp_err_t IRAM_ATTR psram_enable_qio_mode(psram_spi_num_t spi_num)
+{
+    psram_cmd_t ps_cmd;
+    uint32_t addr = (PSRAM_ENTER_QMODE << 24) | 0;
+    switch (s_psram_mode) {
+        case PSRAM_CACHE_F80M_S80M:
+            ps_cmd.cmdBitLen = 0;
+            break;
+        case PSRAM_CACHE_F80M_S40M:
+        case PSRAM_CACHE_F40M_S40M:
+        default:
+            ps_cmd.cmdBitLen = 2;
+            break;
+    }
+    ps_cmd.cmd = 0;
+    ps_cmd.addr = &addr;
+    ps_cmd.addrBitLen = 8;
+    ps_cmd.txData = NULL;
+    ps_cmd.txDataBitLen = 0;
+    ps_cmd.rxData = NULL;
+    ps_cmd.rxDataBitLen = 0;
+    ps_cmd.dummyBitLen = 0;
+    psram_cmd_config(spi_num, &ps_cmd);
+    psram_cmd_recv_start(spi_num, NULL, 0, PSRAM_CMD_SPI);
+    psram_cmd_end(spi_num);
+    return ESP_OK;
+}
+
+//spi param init for psram
+void IRAM_ATTR psram_spi_init(psram_spi_num_t spi_num, psram_cache_mode_t mode)
+{
+    uint8_t i, k;
+    CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_TRANS_DONE << 5);
+    SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CS_SETUP);
+    // SPI_CPOL & SPI_CPHA
+    CLEAR_PERI_REG_MASK(SPI_PIN_REG(spi_num), SPI_CK_IDLE_EDGE);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CK_OUT_EDGE);
+    // SPI bit order
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_WR_BIT_ORDER);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(spi_num), SPI_RD_BIT_ORDER);
+    // SPI bit order
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_DOUTDIN);
+    // May be not must to do.
+    WRITE_PERI_REG(SPI_USER1_REG(spi_num), 0);
+    // SPI mode type
+    CLEAR_PERI_REG_MASK(SPI_SLAVE_REG(spi_num), SPI_SLAVE_MODE);
+    // Set SPI speed for non-80M mode. (80M mode uses APB clock directly.)
+    if (mode!=PSRAM_CACHE_F80M_S80M) {
+        i = 1;      //Pre-divider
+        k = 2;      //Main divider. Divide by 2 so we get 40MHz
+         //clear bit 31, set SPI clock div
+        CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(spi_num), SPI_CLK_EQU_SYSCLK);
+        WRITE_PERI_REG(SPI_CLOCK_REG(spi_num),
+                (((i - 1) & SPI_CLKDIV_PRE) << SPI_CLKDIV_PRE_S) |
+                (((k - 1) & SPI_CLKCNT_N) << SPI_CLKCNT_N_S) |
+                ((((k + 1) / 2 - 1) & SPI_CLKCNT_H) << SPI_CLKCNT_H_S) | //50% duty cycle
+                (((k - 1) & SPI_CLKCNT_L) << SPI_CLKCNT_L_S));
+    }
+    // Enable MOSI
+    SET_PERI_REG_MASK(SPI_USER_REG(spi_num), SPI_CS_SETUP | SPI_CS_HOLD | SPI_USR_MOSI);
+    memset((void*)SPI_W0_REG(spi_num), 0, 16 * 4);
+}
+
+/*
+ * Psram mode init will overwrite original flash speed mode, so that it is possible to change psram and flash speed after OTA.
+ * Flash read mode(QIO/QOUT/DIO/DOUT) will not be changed in app bin. It is decided by bootloader, OTA can not change this mode.
+ */
+static void IRAM_ATTR psram_gpio_config(psram_cache_mode_t mode)
+{
+    int spi_cache_dummy = 0;
+    uint32_t rd_mode_reg = READ_PERI_REG(SPI_CTRL_REG(0));
+    if (rd_mode_reg & (SPI_FREAD_QIO_M | SPI_FREAD_DIO_M)) {
+        spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN;
+    } else {
+        spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN;
+    }
+    // In bootloader, all the signals are already configured,
+    // We keep the following code in case the bootloader is some older version.
+    gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0);
+    gpio_matrix_out(PSRAM_SPIQ_IO, SPIQ_OUT_IDX, 0, 0);
+    gpio_matrix_in(PSRAM_SPIQ_IO, SPIQ_IN_IDX, 0);
+    gpio_matrix_out(PSRAM_SPID_IO, SPID_OUT_IDX, 0, 0);
+    gpio_matrix_in(PSRAM_SPID_IO, SPID_IN_IDX, 0);
+    gpio_matrix_out(PSRAM_SPIWP_IO, SPIWP_OUT_IDX, 0, 0);
+    gpio_matrix_in(PSRAM_SPIWP_IO, SPIWP_IN_IDX, 0);
+    gpio_matrix_out(PSRAM_SPIHD_IO, SPIHD_OUT_IDX, 0, 0);
+    gpio_matrix_in(PSRAM_SPIHD_IO, SPIHD_IN_IDX, 0);
+
+    switch (mode) {
+        case PSRAM_CACHE_F80M_S40M:
+            extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
+            g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M;
+            g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_40M;
+            SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S);  //DUMMY
+            esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
+            esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
+            //set drive ability for clock
+            SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S);
+            break;
+        case PSRAM_CACHE_F80M_S80M:
+            extra_dummy = PSRAM_IO_MATRIX_DUMMY_80M;
+            g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_80M;
+            g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_80M;
+            SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S);  //DUMMY
+            esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_CACHE_PORT);
+            esp_rom_spiflash_config_clk(_SPI_80M_CLK_DIV, _SPI_FLASH_PORT);
+            //set drive ability for clock
+            SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 3, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S);
+            break;
+        case PSRAM_CACHE_F40M_S40M:
+            extra_dummy = PSRAM_IO_MATRIX_DUMMY_40M;
+            g_rom_spiflash_dummy_len_plus[_SPI_CACHE_PORT] = PSRAM_IO_MATRIX_DUMMY_40M;
+            g_rom_spiflash_dummy_len_plus[_SPI_FLASH_PORT] = PSRAM_IO_MATRIX_DUMMY_40M;
+            SET_PERI_REG_BITS(SPI_USER1_REG(_SPI_CACHE_PORT), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + PSRAM_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S);  //DUMMY
+            esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_CACHE_PORT);
+            esp_rom_spiflash_config_clk(_SPI_40M_CLK_DIV, _SPI_FLASH_PORT);
+            //set drive ability for clock
+            SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, 2, FUN_DRV_S);
+            SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 2, FUN_DRV_S);
+            break;
+        default:
+            break;
+    }
+    SET_PERI_REG_MASK(SPI_USER_REG(0), SPI_USR_DUMMY); // dummy en
+
+    //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.
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK);
+}
+
+//psram gpio init , different working frequency we have different solutions
+esp_err_t IRAM_ATTR psram_enable(psram_cache_mode_t mode, psram_vaddr_mode_t vaddrmode)   //psram init
+{
+    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) {
+        ESP_EARLY_LOGE(TAG, "ESP32D2WD do not support psram yet");
+        return ESP_FAIL;
+    } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) {
+        ESP_EARLY_LOGE(TAG, "ESP32PICOD2 do not support psram yet");
+        return ESP_FAIL;
+    } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) {
+        ESP_EARLY_LOGE(TAG, "ESP32PICOD4  do not support psram yet");
+        return ESP_FAIL;
+    }
+
+    /*   note: If the third mode(80Mhz+80Mhz) is enabled, VSPI port will be occupied by the system,
+         Application code should never touch VSPI hardware in this case.  We try to stop applications
+         from doing this using the drivers by claiming the port for ourselves*/
+    #if CONFIG_SPIRAM_SPEED_80M
+    if (mode == PSRAM_CACHE_F80M_S80M) {
+        periph_module_enable(PERIPH_VSPI_MODULE);
+        bool r=spicommon_periph_claim(VSPI_HOST);
+        if (!r) {
+            return ESP_ERR_INVALID_STATE;
+        }
+    }
+    #endif
+
+    WRITE_PERI_REG(GPIO_ENABLE_W1TC_REG, BIT(PSRAM_CLK_IO) | BIT(PSRAM_CS_IO));   //DISABLE OUPUT FOR IO16/17
+    assert(mode < PSRAM_CACHE_MAX && "we don't support any other mode for now.");
+    s_psram_mode = mode;
+
+    periph_module_enable(PERIPH_SPI_MODULE);
+
+    WRITE_PERI_REG(SPI_EXT3_REG(0), 0x1);
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_USR_PREP_HOLD_M);
+
+    switch (mode) {
+        case PSRAM_CACHE_F80M_S80M:
+            psram_spi_init(PSRAM_SPI_1, mode);
+            CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_HOLD);
+            gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0);
+            gpio_matrix_out(PSRAM_CLK_IO, VSPICLK_OUT_IDX, 0, 0);
+            //use spi3 clock,but use spi1 data/cs wires
+            //We get a solid 80MHz clock from SPI3 by setting it up, starting a transaction, waiting until it
+            //is in progress, then cutting the clock (but not the reset!) to that peripheral.
+            WRITE_PERI_REG(SPI_ADDR_REG(PSRAM_SPI_3), 32 << 24);
+            WRITE_PERI_REG(SPI_CLOCK_REG(PSRAM_SPI_3), SPI_CLK_EQU_SYSCLK_M);   //SET 80M AND CLEAR OTHERS
+            SET_PERI_REG_MASK(SPI_CMD_REG(PSRAM_SPI_3), SPI_FLASH_READ_M);
+            uint32_t spi_status;
+            while (1) {
+                spi_status = READ_PERI_REG(SPI_EXT2_REG(PSRAM_SPI_3));
+                if (spi_status != 0 && spi_status != 1) {
+                    DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, DPORT_SPI3_CLK_EN);
+                    break;
+                }
+            }
+            break;
+        case PSRAM_CACHE_F80M_S40M:
+        case PSRAM_CACHE_F40M_S40M:
+        default:
+            psram_spi_init(PSRAM_SPI_1, mode);
+            CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_HOLD);
+            gpio_matrix_out(PSRAM_CS_IO, SPICS1_OUT_IDX, 0, 0);
+            /* We need to delay CLK to the PSRAM with respect to the clock signal as output by the SPI peripheral.
+            We do this by routing it signal to signal 224/225, which are used as a loopback; the extra run through
+            the GPIO matrix causes the delay. We use GPIO20 (which is not in any package but has pad logic in
+            silicon) as a temporary pad for this. So the signal path is:
+            SPI CLK --> GPIO28 --> signal224(in then out) --> internal GPIO29 --> signal225(in then out) --> GPIO17(PSRAM CLK)
+            */
+            gpio_matrix_out(PSRAM_INTERNAL_IO_28, SPICLK_OUT_IDX, 0, 0);
+            gpio_matrix_in(PSRAM_INTERNAL_IO_28, SIG_IN_FUNC224_IDX, 0);
+            gpio_matrix_out(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC224_IDX, 0, 0);
+            gpio_matrix_in(PSRAM_INTERNAL_IO_29, SIG_IN_FUNC225_IDX, 0);
+            gpio_matrix_out(PSRAM_CLK_IO, SIG_IN_FUNC225_IDX, 0, 0);
+            break;
+    }
+    #if CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V
+        // For flash 80Mhz, we must update ldo voltage in case older version of bootloader didn't do this.
+        rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config();
+        if (cfg.enable == 1 && cfg.tieh == RTC_VDDSDIO_TIEH_1_8V) {    // VDDSDIO regulator is enabled @ 1.8V
+            cfg.drefh = 3;
+            cfg.drefm = 3;
+            cfg.drefl = 3;
+            cfg.force = 1;
+            rtc_vddsdio_set_config(cfg);
+            ets_delay_us(10);                     // wait for regulator to become stable
+        }
+    #endif
+    CLEAR_PERI_REG_MASK(SPI_USER_REG(PSRAM_SPI_1), SPI_CS_SETUP_M);
+    psram_gpio_config(mode);
+    WRITE_PERI_REG(GPIO_ENABLE_W1TS_REG, BIT(PSRAM_CS_IO)| BIT(PSRAM_CLK_IO));
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CS_IO], PIN_FUNC_GPIO);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], PIN_FUNC_GPIO);
+
+    uint32_t flash_id = g_rom_flashchip.device_id;
+    if (flash_id == FLASH_ID_GD25LQ32C) {
+        #if CONFIG_SPIRAM_TYPE_ESPPSRAM32
+        // 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);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CS_IO], FUN_DRV, 3, FUN_DRV_S);
+        SET_PERI_REG_BITS(GPIO_PIN_MUX_REG[PSRAM_CLK_IO], FUN_DRV, 3, FUN_DRV_S);
+        #endif
+    }
+    uint32_t id;
+    psram_read_id(&id);
+    if (((id >> PSRAM_MFG_ID_S) & PSRAM_MFG_ID_M) != PSRAM_MFG_ID_V) {
+        return ESP_FAIL;
+    }
+    psram_enable_qio_mode(PSRAM_SPI_1);
+
+    psram_cache_init(mode, vaddrmode);
+    return ESP_OK;
+}
+
+//register initialization for sram cache params and r/w commands
+static void IRAM_ATTR psram_cache_init(psram_cache_mode_t psram_cache_mode, psram_vaddr_mode_t vaddrmode)
+{
+    CLEAR_PERI_REG_MASK(SPI_CLOCK_REG(0), SPI_CLK_EQU_SYSCLK_M);
+    SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKDIV_PRE_V, 0, SPI_CLKDIV_PRE_S);
+    SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKCNT_N, 1, SPI_CLKCNT_N_S);
+    SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKCNT_H, 0, SPI_CLKCNT_H_S);
+    SET_PERI_REG_BITS(SPI_CLOCK_REG(0), SPI_CLKCNT_L, 1, SPI_CLKCNT_L_S);
+
+    switch (psram_cache_mode) {
+        case PSRAM_CACHE_F80M_S80M:
+            CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31));   //flash 1 div clk,80+40;
+            CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0. FLASH DIV 2+SRAM DIV4
+            WRITE_PERI_REG(SPI_CLOCK_REG(0), SPI_CLK_EQU_SYSCLK_M);   //SET 1DIV CLOCK AND RESET OTHER PARAMS
+            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M);   //enable cache read dummy
+            SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
+                    SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
+            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
+            break;
+        case PSRAM_CACHE_F80M_S40M:
+            SET_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
+            CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div , ONLY IF SPI/SRAM@ DIFFERENT SPEED,JUST FOR SPI0.
+            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
+            SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
+                    SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
+            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
+            break;
+        case PSRAM_CACHE_F40M_S40M:
+        default:
+            CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(31)); //flash 1 div clk
+            CLEAR_PERI_REG_MASK(SPI_DATE_REG(0), BIT(30)); //pre clk div
+            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_RD_SRAM_DUMMY_M); //enable cache read dummy
+            SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_DUMMY_CYCLELEN_V, PSRAM_FAST_READ_DUMMY + extra_dummy,
+                    SPI_SRAM_DUMMY_CYCLELEN_S); //dummy, psram cache :  40m--+1dummy,80m--+2dummy
+            SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_RCMD_M); //enable user mode for cache read command
+            break;
+    }
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_CACHE_SRAM_USR_WCMD_M);     // cache write command enable
+    SET_PERI_REG_BITS(SPI_CACHE_SCTRL_REG(0), SPI_SRAM_ADDR_BITLEN_V, 23, SPI_SRAM_ADDR_BITLEN_S); //write address for cache command.
+    SET_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_QIO_M);     //enable qio mode for cache command
+    CLEAR_PERI_REG_MASK(SPI_CACHE_SCTRL_REG(0), SPI_USR_SRAM_DIO_M);     //disable dio mode for cache command
+
+
+    //config sram cache r/w command
+    switch (psram_cache_mode) {
+        case PSRAM_CACHE_F80M_S80M: //in this mode , no delay is needed
+            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 7,
+                    SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S);
+            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, PSRAM_QUAD_WRITE,
+                    SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38
+            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 7,
+                    SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S);
+            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, PSRAM_FAST_READ,
+                    SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b
+            break;
+        case PSRAM_CACHE_F80M_S40M: //is sram is @40M, need 2 cycles of delay
+        case PSRAM_CACHE_F40M_S40M:
+        default:
+            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_V, 15,
+                    SPI_CACHE_SRAM_USR_RD_CMD_BITLEN_S); //read command length, 2 bytes(1byte for delay),sending in qio mode in cache
+            SET_PERI_REG_BITS(SPI_SRAM_DRD_CMD_REG(0), SPI_CACHE_SRAM_USR_RD_CMD_VALUE_V, ((PSRAM_FAST_READ) << 8),
+                    SPI_CACHE_SRAM_USR_RD_CMD_VALUE_S); //0x0b, read command value,(0x00 for delay,0x0b for cmd)
+            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_BITLEN, 15,
+                    SPI_CACHE_SRAM_USR_WR_CMD_BITLEN_S); //write command length,2 bytes(1byte for delay,send in qio mode in cache)
+            SET_PERI_REG_BITS(SPI_SRAM_DWR_CMD_REG(0), SPI_CACHE_SRAM_USR_WR_CMD_VALUE, ((PSRAM_QUAD_WRITE) << 8),
+                    SPI_CACHE_SRAM_USR_WR_CMD_VALUE_S); //0x38, write command value,(0x00 for delay)
+            break;
+    }
+
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL|DPORT_PRO_DRAM_SPLIT);
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL|DPORT_APP_DRAM_SPLIT);
+    if (vaddrmode == PSRAM_VADDR_MODE_LOWHIGH) {
+        DPORT_SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_HL);
+        DPORT_SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_HL);
+    } else if (vaddrmode == PSRAM_VADDR_MODE_EVENODD) {
+        DPORT_SET_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL_REG, DPORT_PRO_DRAM_SPLIT);
+        DPORT_SET_PERI_REG_MASK(DPORT_APP_CACHE_CTRL_REG, DPORT_APP_DRAM_SPLIT);
+    }
+
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CACHE_MASK_DRAM1|DPORT_PRO_CACHE_MASK_OPSDRAM); //use Dram1 to visit ext sram.
+    //cache page mode : 1 -->16k  4 -->2k  0-->32k,(accord with the settings in cache_sram_mmu_set)
+    DPORT_SET_PERI_REG_BITS(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CMMU_SRAM_PAGE_MODE, 0, DPORT_PRO_CMMU_SRAM_PAGE_MODE_S);
+    DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CACHE_MASK_DRAM1|DPORT_APP_CACHE_MASK_OPSDRAM); //use Dram1 to visit ext sram.
+    //cache page mode : 1 -->16k  4 -->2k  0-->32k,(accord with the settings in cache_sram_mmu_set)
+    DPORT_SET_PERI_REG_BITS(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CMMU_SRAM_PAGE_MODE, 0, DPORT_APP_CMMU_SRAM_PAGE_MODE_S);
+
+    CLEAR_PERI_REG_MASK(SPI_PIN_REG(0), SPI_CS1_DIS_M); //ENABLE SPI0 CS1 TO PSRAM(CS0--FLASH; CS1--SRAM)
+
+}
+
+#endif // CONFIG_SPIRAM_SUPPORT
diff --git a/cpu/esp32/vendor/esp-idf/esp32/wifi_init.c b/cpu/esp32/vendor/esp-idf/esp32/wifi_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..4af4a83df871a30cb0cd3fdaeb3878c5cb70e81d
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/wifi_init.c
@@ -0,0 +1,73 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#if MODULE_ESP_WIFI_ANY
+
+#include <esp_event.h>
+#include <esp_wifi.h>
+#include "esp_log.h"
+#include "esp_wifi_internal.h"
+#include "esp_pm.h"
+#include "soc/rtc.h"
+#include "esp_mesh.h"
+
+/* mesh event callback handler */
+mesh_event_cb_t g_mesh_event_cb = NULL;
+
+#ifdef CONFIG_PM_ENABLE
+static esp_pm_lock_handle_t s_wifi_modem_sleep_lock;
+#endif
+
+static void __attribute__((constructor)) s_set_default_wifi_log_level(void)
+{
+    /* WiFi libraries aren't compiled to know CONFIG_LOG_DEFAULT_LEVEL,
+       so set it at runtime startup. Done here not in esp_wifi_init() to allow
+       the user to set the level again before esp_wifi_init() is called.
+    */
+    esp_log_level_set("wifi", CONFIG_LOG_DEFAULT_LEVEL);
+}
+
+esp_err_t esp_wifi_init(const wifi_init_config_t *config)
+{
+#ifdef CONFIG_PM_ENABLE
+    if (s_wifi_modem_sleep_lock == NULL) {
+        esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "wifi",
+                &s_wifi_modem_sleep_lock);
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+#endif
+    esp_event_set_default_wifi_handlers();
+    return esp_wifi_init_internal(config);
+}
+
+#ifdef CONFIG_PM_ENABLE
+void wifi_apb80m_request(void)
+{
+    assert(s_wifi_modem_sleep_lock);
+    esp_pm_lock_acquire(s_wifi_modem_sleep_lock);
+    if (rtc_clk_apb_freq_get() != APB_CLK_FREQ) {
+        ESP_LOGE(__func__, "WiFi needs 80MHz APB frequency to work, but got %dHz", rtc_clk_apb_freq_get());
+    }
+}
+
+void wifi_apb80m_release(void)
+{
+    assert(s_wifi_modem_sleep_lock);
+    esp_pm_lock_release(s_wifi_modem_sleep_lock);
+}
+#endif //CONFIG_PM_ENABLE
+
+#endif /* MODULE_ESP_WIFI_ANY */
diff --git a/cpu/esp32/vendor/esp-idf/esp32/wifi_os_adapter.c b/cpu/esp32/vendor/esp-idf/esp32/wifi_os_adapter.c
new file mode 100644
index 0000000000000000000000000000000000000000..d4a7fb97ef79a0f9a1bd08eeb90e022863a8e048
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp32/wifi_os_adapter.c
@@ -0,0 +1,513 @@
+// 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 <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <assert.h>
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "freertos/event_groups.h"
+#include "freertos/portmacro.h"
+#ifdef RIOT_VERSION
+#include "xtensa/xtensa_api.h"
+#else
+#include "freertos/xtensa_api.h"
+#endif
+#include "esp_types.h"
+#include "esp_system.h"
+#include "esp_task.h"
+#include "esp_intr.h"
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_heap_caps.h"
+#include "esp_wifi_os_adapter.h"
+#include "esp_wifi_internal.h"
+#include "esp_phy_init.h"
+#include "crypto/md5.h"
+#include "crypto/sha1.h"
+#include "crypto/crypto.h"
+#ifndef RIOT_VERSION
+#include "crypto/aes.h"
+#endif
+#include "crypto/dh_group5.h"
+#include "driver/periph_ctrl.h"
+#include "nvs.h"
+#include "os.h"
+#include "esp_smartconfig.h"
+#include "smartconfig_ack.h"
+
+
+extern void esp_dport_access_stall_other_cpu_start_wrap(void);
+extern void esp_dport_access_stall_other_cpu_end_wrap(void);
+
+/*
+ If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
+ If failed, try to allocate it in internal memory then.
+ */
+IRAM_ATTR void *wifi_malloc( size_t size )
+{
+#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
+    return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+#else
+    return malloc(size);
+#endif
+}
+
+/*
+ If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
+ If failed, try to allocate it in internal memory then.
+ */
+IRAM_ATTR void *wifi_realloc( void *ptr, size_t size )
+{
+#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
+    return heap_caps_realloc_prefer(ptr, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+#else
+    return realloc(ptr, size);
+#endif
+}
+
+/*
+ If CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST is enabled. Prefer to allocate a chunk of memory in SPIRAM firstly.
+ If failed, try to allocate it in internal memory then.
+ */
+IRAM_ATTR void *wifi_calloc( size_t n, size_t size )
+{
+#if CONFIG_WIFI_LWIP_ALLOCATION_FROM_SPIRAM_FIRST
+    return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_DEFAULT|MALLOC_CAP_SPIRAM, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+#else
+    return calloc(n, size);
+#endif
+}
+
+static void * IRAM_ATTR wifi_zalloc_wrapper(size_t size)
+{
+    void *ptr = wifi_calloc(1, size);
+    if (ptr) {
+        memset(ptr, 0, size);
+    }
+    return ptr;
+}
+
+wifi_static_queue_t* wifi_create_queue( int queue_len, int item_size)
+{
+    wifi_static_queue_t *queue = NULL;
+
+    queue = (wifi_static_queue_t*)heap_caps_malloc(sizeof(wifi_static_queue_t), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+    if (!queue) {
+        return NULL;
+    }
+
+#if 0 /* TODO: CONFIG_SPIRAM_USE_MALLOC */
+
+    queue->storage = heap_caps_calloc(1, sizeof(StaticQueue_t) + (queue_len*item_size), MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
+    if (!queue->storage) {
+        goto _error;
+    }
+
+    queue->handle = xQueueCreateStatic( queue_len, item_size, ((uint8_t*)(queue->storage)) + sizeof(StaticQueue_t), (StaticQueue_t*)(queue->storage));
+
+    if (!queue->handle) {
+        goto _error;
+    }
+
+    return queue;
+
+_error:
+    if (queue) {
+        if (queue->storage) {
+            free(queue->storage);
+        }
+
+        free(queue);
+    }
+
+    return NULL;
+#else
+    queue->handle = xQueueCreate( queue_len, item_size);
+    return queue;
+#endif
+}
+
+void wifi_delete_queue(wifi_static_queue_t *queue)
+{
+    if (queue) {
+        vQueueDelete(queue->handle);
+
+#if 0 /* TODO: CONFIG_SPIRAM_USE_MALLOC */
+        if (queue->storage) {
+            free(queue->storage);
+        }
+#endif
+
+        free(queue);
+    }
+}
+
+static void * IRAM_ATTR wifi_create_queue_wrapper(int queue_len, int item_size)
+{
+    return wifi_create_queue(queue_len, item_size);
+}
+
+static void IRAM_ATTR wifi_delete_queue_wrapper(void *queue)
+{
+    wifi_delete_queue(queue);
+}
+
+static void IRAM_ATTR set_isr_wrapper(int32_t n, void *f, void *arg)
+{
+    xt_set_interrupt_handler(n, (xt_handler)f, arg);
+}
+
+static void * IRAM_ATTR spin_lock_create_wrapper(void)
+{
+    portMUX_TYPE tmp = portMUX_INITIALIZER_UNLOCKED;
+    void *mux = malloc(sizeof(portMUX_TYPE));
+
+    if (mux) {
+        memcpy(mux,&tmp,sizeof(portMUX_TYPE));
+        return mux;
+    }
+    return NULL;
+}
+
+static uint32_t IRAM_ATTR wifi_int_disable_wrapper(void *wifi_int_mux)
+{
+    if (xPortInIsrContext()) {
+        portENTER_CRITICAL_ISR(wifi_int_mux);
+    } else {
+        portENTER_CRITICAL(wifi_int_mux);
+    }
+
+    return 0;
+}
+
+static void IRAM_ATTR wifi_int_restore_wrapper(void *wifi_int_mux, uint32_t tmp)
+{
+    if (xPortInIsrContext()) {
+        portEXIT_CRITICAL_ISR(wifi_int_mux);
+    } else {
+        portEXIT_CRITICAL(wifi_int_mux);
+    }
+}
+
+static void IRAM_ATTR task_yield_from_isr_wrapper(void)
+{
+    portYIELD_FROM_ISR();
+}
+
+static void *IRAM_ATTR semphr_create_wrapper(uint32_t max, uint32_t init)
+{
+    return (void *)xSemaphoreCreateCounting(max, init);
+}
+
+static void IRAM_ATTR semphr_delete_wrapper(void *semphr)
+{
+    vSemaphoreDelete(semphr);
+}
+
+static int32_t IRAM_ATTR semphr_take_from_isr_wrapper(void *semphr, void *hptw)
+{
+    return (int32_t)xSemaphoreTakeFromISR(semphr, hptw);
+}
+
+static int32_t IRAM_ATTR semphr_give_from_isr_wrapper(void *semphr, void *hptw)
+{
+    return (int32_t)xSemaphoreGiveFromISR(semphr, hptw);
+}
+
+static int32_t IRAM_ATTR semphr_take_wrapper(void *semphr, uint32_t block_time_tick)
+{
+    if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
+        return (int32_t)xSemaphoreTake(semphr, portMAX_DELAY);
+    } else {
+        return (int32_t)xSemaphoreTake(semphr, block_time_tick);
+    }
+}
+
+static int32_t IRAM_ATTR semphr_give_wrapper(void *semphr)
+{
+    return (int32_t)xSemaphoreGive(semphr);
+}
+
+static void *IRAM_ATTR recursive_mutex_create_wrapper(void)
+{
+    return (void *)xSemaphoreCreateRecursiveMutex();
+}
+
+static void *IRAM_ATTR mutex_create_wrapper(void)
+{
+    return (void *)xSemaphoreCreateMutex();
+}
+
+static void IRAM_ATTR mutex_delete_wrapper(void *mutex)
+{
+    vSemaphoreDelete(mutex);
+}
+
+static int32_t IRAM_ATTR mutex_lock_wrapper(void *mutex)
+{
+    return (int32_t)xSemaphoreTakeRecursive(mutex, portMAX_DELAY);
+}
+
+static int32_t IRAM_ATTR mutex_unlock_wrapper(void *mutex)
+{
+    return (int32_t)xSemaphoreGiveRecursive(mutex);
+}
+
+static void *IRAM_ATTR queue_create_wrapper(uint32_t queue_len, uint32_t item_size)
+{
+    return (void *)xQueueCreate(queue_len, item_size);
+}
+
+static int32_t IRAM_ATTR queue_send_wrapper(void *queue, void *item, uint32_t block_time_tick)
+{
+    if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
+        return (int32_t)xQueueSend(queue, item, portMAX_DELAY);
+    } else {
+        return (int32_t)xQueueSend(queue, item, block_time_tick);
+    }
+}
+
+static int32_t IRAM_ATTR queue_send_from_isr_wrapper(void *queue, void *item, void *hptw)
+{
+    return (int32_t)xQueueSendFromISR(queue, item, hptw);
+}
+
+static int32_t IRAM_ATTR queue_send_to_back_wrapper(void *queue, void *item, uint32_t block_time_tick)
+{
+    return (int32_t)xQueueGenericSend(queue, item, block_time_tick, queueSEND_TO_BACK);
+}
+
+static int32_t IRAM_ATTR queue_send_to_front_wrapper(void *queue, void *item, uint32_t block_time_tick)
+{
+    return (int32_t)xQueueGenericSend(queue, item, block_time_tick, queueSEND_TO_FRONT);
+}
+
+static int32_t IRAM_ATTR queue_recv_wrapper(void *queue, void *item, uint32_t block_time_tick)
+{
+    if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
+        return (int32_t)xQueueReceive(queue, item, portMAX_DELAY);
+    } else {
+        return (int32_t)xQueueReceive(queue, item, block_time_tick);
+    }
+}
+
+static uint32_t IRAM_ATTR event_group_wait_bits_wrapper(void *event, uint32_t bits_to_wait_for, int clear_on_exit, int wait_for_all_bits, uint32_t block_time_tick)
+{
+    if (block_time_tick == OSI_FUNCS_TIME_BLOCKING) {
+        return (uint32_t)xEventGroupWaitBits(event, bits_to_wait_for, clear_on_exit, wait_for_all_bits, portMAX_DELAY);
+    } else {
+        return (uint32_t)xEventGroupWaitBits(event, bits_to_wait_for, clear_on_exit, wait_for_all_bits, block_time_tick);
+    }
+}
+
+static int32_t IRAM_ATTR task_create_pinned_to_core_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle, uint32_t core_id)
+{
+    return (uint32_t)xTaskCreatePinnedToCore(task_func, name, stack_depth, param, prio, task_handle, (core_id < portNUM_PROCESSORS ? core_id : tskNO_AFFINITY));
+}
+
+static int32_t IRAM_ATTR task_create_wrapper(void *task_func, const char *name, uint32_t stack_depth, void *param, uint32_t prio, void *task_handle)
+{
+    return (uint32_t)xTaskCreate(task_func, name, stack_depth, param, prio, task_handle);
+}
+
+static int32_t IRAM_ATTR task_ms_to_tick_wrapper(uint32_t ms)
+{
+    return (int32_t)(ms / portTICK_PERIOD_MS);
+}
+
+
+static int32_t IRAM_ATTR task_get_max_priority_wrapper(void)
+{
+    return (int32_t)(configMAX_PRIORITIES);
+}
+
+static int32_t IRAM_ATTR phy_rf_init_wrapper(const void* init_data, uint32_t mode, void* calibration_data, uint32_t module)
+{
+    return esp_phy_rf_init( init_data, mode, calibration_data, module);
+}
+
+static void IRAM_ATTR timer_arm_wrapper(void *timer, uint32_t tmout, bool repeat)
+{
+    ets_timer_arm(timer, tmout, repeat);
+}
+
+static void IRAM_ATTR timer_disarm_wrapper(void *timer)
+{
+    ets_timer_disarm(timer);
+}
+
+static void IRAM_ATTR timer_done_wrapper(void *ptimer)
+{
+    ets_timer_done(ptimer);
+}
+
+static void IRAM_ATTR timer_setfn_wrapper(void *ptimer, void *pfunction, void *parg)
+{
+    ets_timer_setfn(ptimer, pfunction, parg);
+}
+
+static void IRAM_ATTR timer_arm_us_wrapper(void *ptimer, uint32_t us, bool repeat)
+{
+    ets_timer_arm_us(ptimer, us, repeat);
+}
+
+static int IRAM_ATTR get_time_wrapper(void *t)
+{
+    return os_get_time(t);
+}
+
+static void * IRAM_ATTR malloc_internal_wrapper(size_t size)
+{
+    return heap_caps_malloc(size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+}
+
+static void * IRAM_ATTR realloc_internal_wrapper(void *ptr, size_t size)
+{
+    return heap_caps_realloc(ptr, size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+}
+
+static void * IRAM_ATTR calloc_internal_wrapper(size_t n, size_t size)
+{
+    return heap_caps_calloc(n, size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+}
+
+static void * IRAM_ATTR zalloc_internal_wrapper(size_t size)
+{
+    void *ptr = heap_caps_calloc(1, size, MALLOC_CAP_DEFAULT|MALLOC_CAP_INTERNAL);
+    if (ptr) {
+        memset(ptr, 0, size);
+    }
+    return ptr;
+}
+
+static void IRAM_ATTR sc_ack_send_wrapper(void *param)
+{
+    return sc_ack_send((sc_ack_t *)param);
+}
+
+#ifdef RIOT_VERSION
+extern void vPortYield(void);
+extern int64_t esp_timer_get_time(void);
+#endif
+
+wifi_osi_funcs_t g_wifi_osi_funcs = {
+    ._version = ESP_WIFI_OS_ADAPTER_VERSION,
+    ._set_isr = set_isr_wrapper,
+#ifdef RIOT_VERSION
+    ._ints_on = (void (*)(unsigned int))xt_ints_on,
+    ._ints_off = (void (*)(unsigned int))xt_ints_off,
+#else
+    ._ints_on = xt_ints_on,
+    ._ints_off = xt_ints_off,
+#endif
+    ._spin_lock_create = spin_lock_create_wrapper,
+    ._spin_lock_delete = free,
+    ._wifi_int_disable = wifi_int_disable_wrapper,
+    ._wifi_int_restore = wifi_int_restore_wrapper,
+    ._task_yield = vPortYield,
+    ._task_yield_from_isr = task_yield_from_isr_wrapper,
+    ._semphr_create = semphr_create_wrapper,
+    ._semphr_delete = semphr_delete_wrapper,
+    ._semphr_take_from_isr = semphr_take_from_isr_wrapper,
+    ._semphr_give_from_isr = semphr_give_from_isr_wrapper,
+    ._semphr_take = semphr_take_wrapper,
+    ._semphr_give = semphr_give_wrapper,
+    ._mutex_create = mutex_create_wrapper,
+    ._recursive_mutex_create = recursive_mutex_create_wrapper,
+    ._mutex_delete = mutex_delete_wrapper,
+    ._mutex_lock = mutex_lock_wrapper,
+    ._mutex_unlock = mutex_unlock_wrapper,
+    ._queue_create = queue_create_wrapper,
+    ._queue_delete = vQueueDelete,
+    ._queue_send = queue_send_wrapper,
+    ._queue_send_from_isr = queue_send_from_isr_wrapper,
+    ._queue_send_to_back = queue_send_to_back_wrapper,
+    ._queue_send_to_front = queue_send_to_front_wrapper,
+    ._queue_recv = queue_recv_wrapper,
+    ._queue_recv_from_isr = xQueueReceiveFromISR,
+    ._queue_msg_waiting = uxQueueMessagesWaiting,
+    ._event_group_create = xEventGroupCreate,
+    ._event_group_delete = vEventGroupDelete,
+    ._event_group_set_bits = xEventGroupSetBits,
+    ._event_group_clear_bits = xEventGroupClearBits,
+    ._event_group_wait_bits = event_group_wait_bits_wrapper,
+    ._task_create_pinned_to_core = task_create_pinned_to_core_wrapper,
+    ._task_create = task_create_wrapper,
+    ._task_delete = vTaskDelete,
+    ._task_delay = vTaskDelay,
+    ._task_ms_to_tick = task_ms_to_tick_wrapper,
+    ._task_get_current_task = xTaskGetCurrentTaskHandle,
+    ._task_get_max_priority = task_get_max_priority_wrapper,
+    ._is_in_isr = xPortInIsrContext,
+    ._malloc = malloc,
+    ._free = free,
+    ._get_free_heap_size = esp_get_free_heap_size,
+    ._rand = esp_random,
+    ._dport_access_stall_other_cpu_start_wrap = esp_dport_access_stall_other_cpu_start_wrap,
+    ._dport_access_stall_other_cpu_end_wrap = esp_dport_access_stall_other_cpu_end_wrap,
+    ._phy_rf_init = phy_rf_init_wrapper,
+    ._phy_rf_deinit = esp_phy_rf_deinit,
+    ._phy_load_cal_and_init = esp_phy_load_cal_and_init,
+    ._read_mac = esp_read_mac,
+    ._timer_init = ets_timer_init,
+    ._timer_deinit = ets_timer_deinit,
+    ._timer_arm = timer_arm_wrapper,
+    ._timer_disarm = timer_disarm_wrapper,
+    ._timer_done = timer_done_wrapper,
+    ._timer_setfn = timer_setfn_wrapper,
+    ._timer_arm_us = timer_arm_us_wrapper,
+    ._periph_module_enable = periph_module_enable,
+    ._periph_module_disable = periph_module_disable,
+    ._esp_timer_get_time = esp_timer_get_time,
+    ._nvs_set_i8 = nvs_set_i8,
+    ._nvs_get_i8 = nvs_get_i8,
+    ._nvs_set_u8 = nvs_set_u8,
+    ._nvs_get_u8 = nvs_get_u8,
+    ._nvs_set_u16 = nvs_set_u16,
+    ._nvs_get_u16 = nvs_get_u16,
+    ._nvs_open = nvs_open,
+    ._nvs_close = nvs_close,
+    ._nvs_commit = nvs_commit,
+    ._nvs_set_blob = nvs_set_blob,
+    ._nvs_get_blob = nvs_get_blob,
+    ._nvs_erase_key = nvs_erase_key,
+    ._get_random = os_get_random,
+    ._get_time = get_time_wrapper,
+    ._random = os_random,
+    ._log_write = esp_log_write,
+    ._log_timestamp = esp_log_timestamp,
+    ._malloc_internal =  malloc_internal_wrapper,
+    ._realloc_internal = realloc_internal_wrapper,
+    ._calloc_internal = calloc_internal_wrapper,
+    ._zalloc_internal = zalloc_internal_wrapper,
+    ._wifi_malloc = wifi_malloc,
+    ._wifi_realloc = wifi_realloc,
+    ._wifi_calloc = wifi_calloc,
+    ._wifi_zalloc = wifi_zalloc_wrapper,
+    ._wifi_create_queue = wifi_create_queue_wrapper,
+    ._wifi_delete_queue = wifi_delete_queue_wrapper,
+    ._modem_sleep_enter = esp_modem_sleep_enter,
+    ._modem_sleep_exit = esp_modem_sleep_exit,
+    ._modem_sleep_register = esp_modem_sleep_register,
+    ._modem_sleep_deregister = esp_modem_sleep_deregister,
+    ._sc_ack_send = sc_ack_send_wrapper,
+    ._sc_ack_send_stop = sc_ack_send_stop,
+    ._magic = ESP_WIFI_OS_ADAPTER_MAGIC,
+};
diff --git a/cpu/esp32/vendor/esp-idf/esp_funcs.c b/cpu/esp32/vendor/esp-idf/esp_funcs.c
new file mode 100644
index 0000000000000000000000000000000000000000..fbc5dd3a93ae2d931b848dae084d1cc742b9a5fe
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/esp_funcs.c
@@ -0,0 +1,547 @@
+// 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.
+
+/* PLEASE NOTE: This file is a collection of required functions from
+   different files in ESP-IDF */
+
+#define ENABLE_DEBUG  0
+#include "debug.h"
+#include "esp_common.h"
+#include "log.h"
+
+#include <stdarg.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "esp_attr.h"
+#include "sdk_conf.h"
+
+#include "driver/periph_ctrl.h"
+#include "esp32/esp_spiram.h"
+#include "esp32/esp_system.h"
+#include "freertos/FreeRTOS.h"
+#include "heap/esp_heap_caps_init.h"
+#include "log/esp_log.h"
+#include "periph/hwrng.h"
+#include "rom/rtc.h"
+#include "rom/cache.h"
+#include "rom/efuse.h"
+#include "rom/uart.h"
+#include "soc/cpu.h"
+#include "soc/efuse_reg.h"
+#include "soc/gpio_reg.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/timer_group_reg.h"
+#include "soc/timer_group_struct.h"
+#include "xtensa/core-macros.h"
+#include "xtensa/xtensa_api.h"
+
+#include "syscalls.h"
+
+/* This function is not part on newlib API, it is defined in libc/stdio/local.h
+ * There is no nice way to get __cleanup member populated while avoiding __sinit,
+ * so extern declaration is used here.
+ */
+extern void _cleanup_r(struct _reent* r);
+
+/**
+ * This is the replacement for newlib's _REENT_INIT_PTR and __sinit.
+ * The problem with __sinit is that it allocates three FILE structures
+ * (stdin, stdout, stderr). Having individual standard streams for each task
+ * is a bit too much on a small embedded system. So we point streams
+ * to the streams of the global struct _reent, which are initialized in
+ * startup code.
+ */
+void IRAM_ATTR esp_reent_init(struct _reent* r)
+{
+    memset(r, 0, sizeof(*r));
+    r->_stdout = _GLOBAL_REENT->_stdout;
+    r->_stderr = _GLOBAL_REENT->_stderr;
+    r->_stdin  = _GLOBAL_REENT->_stdin;
+    r->__cleanup = &_cleanup_r;
+    r->__sdidinit = 1;
+    r->__sglue._next = NULL;
+    r->__sglue._niobs = 0;
+    r->__sglue._iobs = NULL;
+    r->_current_locale = "C";
+}
+
+/* source: /path/to/esp-idf/components/esp32/panic.c */
+void IRAM_ATTR esp_panic_wdt_stop (void)
+{
+    WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    WRITE_PERI_REG(RTC_CNTL_WDTFEED_REG, 1);
+    REG_SET_FIELD(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_STG0, RTC_WDT_STG_SEL_OFF);
+    REG_CLR_BIT(RTC_CNTL_WDTCONFIG0_REG, RTC_CNTL_WDT_EN);
+    WRITE_PERI_REG(RTC_CNTL_WDTWPROTECT_REG, 0);
+}
+
+/* source: /path/to/esp-idf/components/esp32/panic.c */
+void _esp_error_check_failed(esp_err_t rc, const char *file, int line,
+                             const char *function, const char *expression)
+{
+    ets_printf("ESP_ERROR_CHECK failed: esp_err_t 0x%x at 0x%08x\n",
+               rc, (intptr_t)__builtin_return_address(0) - 3);
+    #if 0 /* TODO */
+    if (spi_flash_cache_enabled()) { /* strings may be in flash cache */
+        ets_printf("file: \"%s\" line %d\nfunc: %s\nexpression: %s\n",
+                   file, line, function, expression);
+    }
+    invoke_abort();
+    #endif
+    exit(1);
+
+    while (1) {}
+}
+
+/*
+ * provided by: /path/to/esp-idf/component/log/log.c
+ */
+uint32_t IRAM_ATTR esp_log_timestamp(void)
+{
+    return system_get_time() / USEC_PER_MSEC;
+}
+
+/*
+ * provided by: /path/to/esp-idf/component/log/log.c
+ */
+void IRAM_ATTR esp_log_write(esp_log_level_t level,
+                             const char* tag, const char* format, ...)
+{
+    if ((unsigned)level > CONFIG_LOG_DEFAULT_LEVEL) {
+        return;
+    }
+
+    char _printf_buf[PRINTF_BUFSIZ];
+
+    const char* prefix = (strchr (format, ':') + 2);
+
+    char lc = 'U';
+    switch (level) {
+        case LOG_NONE   : return;
+        case LOG_ERROR  : lc = 'E'; break;
+        case LOG_WARNING: lc = 'W'; break;
+        case LOG_INFO   : lc = 'I'; break;
+        case LOG_DEBUG  : lc = 'D'; break;
+        case LOG_ALL    : lc = 'V'; break;
+    }
+    #ifdef LOG_TAG_IN_BRACKETS
+    ets_printf("%c (%u) [%10s]: ", lc, system_get_time_ms(), tag);
+    #else
+    ets_printf("%c (%u) %10s: ", lc, system_get_time_ms(), tag);
+    #endif
+
+    va_list arglist;
+    va_start(arglist, format);
+
+    /* remove time and tag argument from argument list */
+    va_arg(arglist, unsigned);
+    va_arg(arglist, const char*);
+
+    int ret = vsnprintf(_printf_buf, PRINTF_BUFSIZ, prefix, arglist);
+
+    if (ret > 0) {
+        ets_printf (_printf_buf);
+    }
+
+    va_end(arglist);
+}
+
+/*
+ * provided by: /path/to/esp-idf/component/log/log.c
+ */
+void esp_log_level_set(const char* tag, esp_log_level_t level)
+{
+    /* TODO implementation */
+}
+
+static bool _spi_ram_initialized = false;
+
+/*
+ * source: /path/to/esp-idf/component/esp32/cpu_start.c
+ */
+void spi_ram_init(void)
+{
+    _spi_ram_initialized = false;
+
+    #if CONFIG_SPIRAM_SUPPORT
+    esp_spiram_init_cache();
+    if (esp_spiram_init() == ESP_OK) {
+        _spi_ram_initialized = true;
+    }
+    else {
+        ets_printf("Failed to init external SPI RAM\n");
+        _spi_ram_initialized = false;
+    }
+    #else
+    ets_printf("External SPI RAM functions not enabled\n");
+    #endif
+}
+
+/*
+ * source: /path/to/esp-idf/component/esp32/cpu_start.c
+ */
+void spi_ram_heap_init(void)
+{
+    #if CONFIG_SPIRAM_SUPPORT
+
+    #if CONFIG_SPIRAM_MEMTEST
+    if (!esp_spiram_test()) {
+        return;
+    }
+    #endif /* CONFIG_SPIRAM_MEMTEST */
+
+    #if CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC
+    esp_err_t r=esp_spiram_add_to_heapalloc();
+    if (r != ESP_OK) {
+        ets_printf("External SPI RAM could not be added to heap!\n");
+        abort();
+    }
+
+    #if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
+    r=esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
+    if (r != ESP_OK) {
+        ets_printf("Could not reserve internal/DMA pool!\n");
+        abort();
+    }
+    #endif /* CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL */
+
+    #if CONFIG_SPIRAM_USE_MALLOC
+    heap_caps_malloc_extmem_enable(CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL);
+    #endif /* CONFIG_SPIRAM_USE_MALLOC */
+
+    #endif /* CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC */
+
+    #else  /* CONFIG_SPIRAM_SUPPORT */
+    ets_printf("External SPI RAM functions not enabled\n");
+    #endif /* CONFIG_SPIRAM_SUPPORT */
+}
+
+static const char* TAG = "system_api";
+static uint8_t base_mac_addr[6] = { 0 };
+
+/*
+ * source: /path/to/esp-idf/component/esp32/system_api.c
+ */
+esp_err_t esp_efuse_mac_get_default(uint8_t* mac)
+{
+    uint32_t mac_low;
+    uint32_t mac_high;
+    uint8_t efuse_crc;
+    uint8_t calc_crc;
+
+    mac_low = REG_READ(EFUSE_BLK0_RDATA1_REG);
+    mac_high = REG_READ(EFUSE_BLK0_RDATA2_REG);
+
+    mac[0] = mac_high >> 8;
+    mac[1] = mac_high;
+    mac[2] = mac_low >> 24;
+    mac[3] = mac_low >> 16;
+    mac[4] = mac_low >> 8;
+    mac[5] = mac_low;
+
+    efuse_crc = mac_high >> 16;
+
+    calc_crc = esp_crc8(mac, 6);
+
+    if (efuse_crc != calc_crc) {
+         // Small range of MAC addresses are accepted even if CRC is invalid.
+         // These addresses are reserved for Espressif internal use.
+        if ((mac_high & 0xFFFF) == 0x18fe) {
+            if ((mac_low >= 0x346a85c7) && (mac_low <= 0x346a85f8)) {
+                return ESP_OK;
+            }
+        } else {
+            ESP_LOGE(TAG, "Base MAC address from BLK0 of EFUSE CRC error, efuse_crc = 0x%02x; calc_crc = 0x%02x", efuse_crc, calc_crc);
+            abort();
+        }
+    }
+    return ESP_OK;
+}
+
+/*
+ * source: /path/to/esp-idf/component/esp32/system_api.c
+ */
+esp_err_t esp_derive_mac(uint8_t* local_mac, const uint8_t* universal_mac)
+{
+    uint8_t idx;
+
+    if (local_mac == NULL || universal_mac == NULL) {
+        ESP_LOGE(TAG, "mac address param is NULL");
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    memcpy(local_mac, universal_mac, 6);
+    for (idx = 0; idx < 64; idx++) {
+        local_mac[0] = universal_mac[0] | 0x02;
+        local_mac[0] ^= idx << 2;
+
+        if (memcmp(local_mac, universal_mac, 6)) {
+            break;
+        }
+    }
+
+    return ESP_OK;
+}
+
+/*
+ * source: /path/to/esp-idf/component/esp32/system_api.c
+ */
+esp_err_t esp_base_mac_addr_get(uint8_t *mac)
+{
+    uint8_t null_mac[6] = {0};
+
+    if (memcmp(base_mac_addr, null_mac, 6) == 0) {
+        ESP_LOGI(TAG, "Base MAC address is not set, read default base MAC address from BLK0 of EFUSE");
+        return ESP_ERR_INVALID_MAC;
+    }
+
+    memcpy(mac, base_mac_addr, 6);
+
+    return ESP_OK;
+}
+
+/*
+ * source: /path/to/esp-idf/component/esp32/system_api.c
+ */
+esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type)
+{
+    uint8_t efuse_mac[6];
+
+    if (mac == NULL) {
+        ESP_LOGE(TAG, "mac address param is NULL");
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    if (type < ESP_MAC_WIFI_STA || type > ESP_MAC_ETH) {
+        ESP_LOGE(TAG, "mac type is incorrect");
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    _Static_assert(UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR \
+            || UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR, \
+            "incorrect NUM_MAC_ADDRESS_FROM_EFUSE value");
+
+    if (esp_base_mac_addr_get(efuse_mac) != ESP_OK) {
+        esp_efuse_mac_get_default(efuse_mac);
+    }
+
+    switch (type) {
+    case ESP_MAC_WIFI_STA:
+        memcpy(mac, efuse_mac, 6);
+        break;
+    case ESP_MAC_WIFI_SOFTAP:
+        if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
+            memcpy(mac, efuse_mac, 6);
+            mac[5] += 1;
+        }
+        else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
+            esp_derive_mac(mac, efuse_mac);
+        }
+        break;
+    case ESP_MAC_BT:
+        memcpy(mac, efuse_mac, 6);
+        if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
+            mac[5] += 2;
+        }
+        else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
+            mac[5] += 1;
+        }
+        break;
+    case ESP_MAC_ETH:
+        if (UNIVERSAL_MAC_ADDR_NUM == FOUR_UNIVERSAL_MAC_ADDR) {
+            memcpy(mac, efuse_mac, 6);
+            mac[5] += 3;
+        }
+        else if (UNIVERSAL_MAC_ADDR_NUM == TWO_UNIVERSAL_MAC_ADDR) {
+            efuse_mac[5] += 1;
+            esp_derive_mac(mac, efuse_mac);
+        }
+        break;
+    default:
+        ESP_LOGW(TAG, "incorrect mac type");
+        break;
+    }
+
+    return ESP_OK;
+}
+
+/*
+ * source: /path/to/esp-idf/component/esp32/system_api.c
+ */
+/* "inner" restart function for after RTOS, interrupts & anything else on this
+ * core are already stopped. Stalls other core, resets hardware,
+ * triggers restart.
+*/
+void IRAM_ATTR esp_restart_noos(void)
+{
+    // Disable interrupts
+    xt_ints_off(0xFFFFFFFF);
+
+    // Enable RTC watchdog for 1 second
+    REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE);
+    REG_WRITE(RTC_CNTL_WDTCONFIG0_REG,
+            RTC_CNTL_WDT_FLASHBOOT_MOD_EN_M |
+            (RTC_WDT_STG_SEL_RESET_SYSTEM << RTC_CNTL_WDT_STG0_S) |
+            (RTC_WDT_STG_SEL_RESET_RTC << RTC_CNTL_WDT_STG1_S) |
+            (1 << RTC_CNTL_WDT_SYS_RESET_LENGTH_S) |
+            (1 << RTC_CNTL_WDT_CPU_RESET_LENGTH_S) );
+    REG_WRITE(RTC_CNTL_WDTCONFIG1_REG, rtc_clk_slow_freq_get_hz() * 1);
+
+    // Reset and stall the other CPU.
+    // CPU must be reset before stalling, in case it was running a s32c1i
+    // instruction. This would cause memory pool to be locked by arbiter
+    // to the stalled CPU, preventing current CPU from accessing this pool.
+    const uint32_t core_id = 0;
+    const uint32_t other_core_id = (core_id == 0) ? 1 : 0;
+    esp_cpu_reset(other_core_id);
+    esp_cpu_stall(other_core_id);
+
+    // Other core is now stalled, can access DPORT registers directly
+    esp_dport_access_int_abort();
+
+    // Disable TG0/TG1 watchdogs
+    TIMERG0.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+    TIMERG0.wdt_config0.en = 0;
+    TIMERG0.wdt_wprotect=0;
+    TIMERG1.wdt_wprotect=TIMG_WDT_WKEY_VALUE;
+    TIMERG1.wdt_config0.en = 0;
+    TIMERG1.wdt_wprotect=0;
+
+    // Flush any data left in UART FIFOs
+    uart_tx_wait_idle(0);
+    uart_tx_wait_idle(1);
+    uart_tx_wait_idle(2);
+
+    // Disable cache
+    Cache_Read_Disable(0);
+    Cache_Read_Disable(1);
+
+    // 2nd stage bootloader reconfigures SPI flash signals.
+    // Reset them to the defaults expected by ROM.
+    WRITE_PERI_REG(GPIO_FUNC0_IN_SEL_CFG_REG, 0x30);
+    WRITE_PERI_REG(GPIO_FUNC1_IN_SEL_CFG_REG, 0x30);
+    WRITE_PERI_REG(GPIO_FUNC2_IN_SEL_CFG_REG, 0x30);
+    WRITE_PERI_REG(GPIO_FUNC3_IN_SEL_CFG_REG, 0x30);
+    WRITE_PERI_REG(GPIO_FUNC4_IN_SEL_CFG_REG, 0x30);
+    WRITE_PERI_REG(GPIO_FUNC5_IN_SEL_CFG_REG, 0x30);
+
+    // Reset wifi/bluetooth/ethernet/sdio (bb/mac)
+    DPORT_SET_PERI_REG_MASK(DPORT_CORE_RST_EN_REG,
+         DPORT_BB_RST | DPORT_FE_RST | DPORT_MAC_RST |
+         DPORT_BT_RST | DPORT_BTMAC_RST | DPORT_SDIO_RST |
+         DPORT_SDIO_HOST_RST | DPORT_EMAC_RST | DPORT_MACPWR_RST |
+         DPORT_RW_BTMAC_RST | DPORT_RW_BTLP_RST);
+    DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
+
+    // Reset timer/spi/uart
+    DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
+            DPORT_TIMERS_RST | DPORT_SPI_RST_1 | DPORT_UART_RST);
+    DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
+
+    // Set CPU back to XTAL source, no PLL, same as hard reset
+    rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL);
+
+    // Clear entry point for APP CPU
+    DPORT_REG_WRITE(DPORT_APPCPU_CTRL_D_REG, 0);
+
+    // Reset CPUs
+    if (core_id == 0) {
+        // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs.
+        esp_cpu_reset(1);
+        esp_cpu_reset(0);
+    } else {
+        // Running on APP CPU: need to reset PRO CPU and unstall it,
+        // then reset APP CPU
+        esp_cpu_reset(0);
+        esp_cpu_unstall(0);
+        esp_cpu_reset(1);
+    }
+    while(true) {
+        ;
+    }
+}
+
+/*
+ * source: /path/to/esp-idf/components/wpa_supplicant/port/os_xtensa.c
+ */
+typedef long os_time_t;
+struct os_time {
+    os_time_t sec;
+    os_time_t usec;
+};
+
+int os_get_time(struct os_time *t)
+{
+    return gettimeofday((struct timeval*) t, NULL);
+}
+
+/*
+ * source: /path/to/esp-idf/components/wpa_supplicant/port/os_xtensa.c
+ */
+unsigned long os_random(void)
+{
+    return esp_random();
+}
+
+/*
+ * provided by: /path/to/esp-idf/components/wpa_supplicant/port/os_xtensa.c
+ */
+int os_get_random(unsigned char *buf, size_t len)
+{
+    hwrng_read((void*)buf, len);
+    return 0;
+}
+
+uint32_t esp_random(void)
+{
+    uint32_t tmp;
+    hwrng_read((void*)&tmp, sizeof(uint32_t));
+    return tmp;
+}
+
+/*
+ * source: /path/to/esp-idf/components/lwip/netif/ethernet.c
+ */
+#define ETH_HWADDR_LEN    6
+
+struct eth_addr {
+   uint8_t addr[ETH_HWADDR_LEN];
+};
+
+#ifndef MODULE_LWIP_ETHERNET
+const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}};
+#endif
+
+#if MODULE_ESP_WIFI_ANY
+/*
+ * source: /path/to/esp-idf/components/smartconfig_ack.c
+ */
+#include "esp_smartconfig.h"
+#include "smartconfig_ack.h"
+
+void sc_ack_send(sc_ack_t *param)
+{
+    NOT_SUPPORTED();
+}
+
+/*
+ * source: /path/to/esp-idf/components/smartconfig_ack.c
+ */
+void sc_ack_send_stop(void)
+{
+    NOT_SUPPORTED();
+}
+#endif
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/Makefile b/cpu/esp32/vendor/esp-idf/ethernet/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f368972db79290319750565085149df8cd3b28eb
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/Makefile
@@ -0,0 +1,11 @@
+MODULE=esp_idf_eth
+
+DIRS += eth_phy
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/esp32
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/ethernet
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(ESP32_SDK_DIR)/components/ethernet
+INCLUDES += -I$(ESP32_SDK_DIR)/components/ethernet/include
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/emac_common.h b/cpu/esp32/vendor/esp-idf/ethernet/emac_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..da26ea534bc1ff9ee9d7590adc90758aeec69c97
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/emac_common.h
@@ -0,0 +1,127 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMAC_COMMON_H
+#define EMAC_COMMON_H
+
+#include <stdint.h>
+
+#include "esp_err.h"
+#include "emac_dev.h"
+#include "esp_eth.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint32_t emac_sig_t;
+typedef uint32_t emac_par_t;
+
+typedef struct {
+    emac_sig_t sig;
+    emac_par_t par;
+} emac_event_t;
+
+enum emac_runtime_status {
+    EMAC_RUNTIME_NOT_INIT = 0,
+    EMAC_RUNTIME_INIT,
+    EMAC_RUNTIME_START,
+    EMAC_RUNTIME_STOP,
+};
+
+enum {
+    SIG_EMAC_RX_UNAVAIL,
+    SIG_EMAC_TX_DONE,
+    SIG_EMAC_RX_DONE,
+    SIG_EMAC_START,
+    SIG_EMAC_STOP,
+    SIG_EMAC_CHECK_LINK,
+    SIG_EMAC_MAX
+};
+
+struct emac_config_data {
+    eth_phy_base_t phy_addr;
+    eth_mode_t mac_mode;
+    eth_clock_mode_t clock_mode;
+    struct dma_extended_desc *dma_etx;
+    uint32_t cur_tx;
+    uint32_t dirty_tx;
+    int32_t cnt_tx;
+    struct dma_extended_desc *dma_erx;
+    uint32_t cur_rx;
+    uint32_t dirty_rx;
+    int32_t cnt_rx;
+    uint32_t rx_need_poll;
+    bool phy_link_up;
+    enum emac_runtime_status emac_status;
+    uint8_t macaddr[6];
+    eth_phy_func phy_init;
+    eth_tcpip_input_func emac_tcpip_input;
+    eth_gpio_config_func emac_gpio_config;
+    eth_phy_check_link_func emac_phy_check_link;
+    eth_phy_check_init_func emac_phy_check_init;
+    eth_phy_get_speed_mode_func emac_phy_get_speed_mode;
+    eth_phy_get_duplex_mode_func emac_phy_get_duplex_mode;
+    bool emac_flow_ctrl_enable;
+    bool emac_flow_ctrl_partner_support;
+    eth_phy_get_partner_pause_enable_func  emac_phy_get_partner_pause_enable;
+    eth_phy_power_enable_func  emac_phy_power_enable;
+};
+
+enum emac_post_type {
+    EMAC_POST_ASYNC,
+    EMAC_POST_SYNC,
+};
+
+struct emac_post_cmd {
+    void *cmd;
+    enum emac_post_type post_type;
+};
+
+struct emac_tx_cmd {
+    uint8_t *buf;
+    uint16_t size;
+    int8_t err;
+};
+
+struct emac_open_cmd {
+    int8_t err;
+};
+
+struct emac_close_cmd {
+    int8_t err;
+};
+
+#define DMA_RX_BUF_NUM CONFIG_DMA_RX_BUF_NUM
+#define DMA_TX_BUF_NUM CONFIG_DMA_TX_BUF_NUM
+#define EMAC_TASK_PRIORITY CONFIG_EMAC_TASK_PRIORITY
+
+#define DMA_RX_BUF_SIZE 1600
+#define DMA_TX_BUF_SIZE 1600
+
+//rest buf num
+#define FLOW_CONTROL_HIGH_WATERMARK 3
+//used buf num
+#define FLOW_CONTROL_LOW_WATERMARK  6
+
+#define PHY_LINK_CHECK_NUM  5
+
+#define EMAC_CMD_OK 0
+#define EMAC_CMD_FAIL -1
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EMAC_COMMON_H */
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/emac_dev.c b/cpu/esp32/vendor/esp-idf/ethernet/emac_dev.c
new file mode 100644
index 0000000000000000000000000000000000000000..894da7f2449b826ec843730b0e2207320aef9159
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/emac_dev.c
@@ -0,0 +1,121 @@
+// 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.
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "rom/ets_sys.h"
+#ifndef RIOT_VERSION
+#include "rom/gpio.h"
+#endif
+
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/gpio_reg.h"
+#include "soc/gpio_sig_map.h"
+#include "soc/emac_reg_v2.h"
+#include "soc/emac_ex_reg.h"
+
+#include "esp_log.h"
+#include "driver/gpio.h"
+#include "sdk_conf.h"
+
+#include "emac_common.h"
+
+static const char *TAG = "emac";
+
+void emac_enable_flowctrl(void)
+{
+    REG_SET_BIT(EMAC_GMACFC_REG, EMAC_TFCE);
+    REG_SET_BIT(EMAC_GMACFC_REG, EMAC_RFCE);
+    REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_DZPQ);
+    REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PAUSE_TIME, 0x1648);
+    REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PLT, 0x1);
+}
+
+void emac_disable_flowctrl(void)
+{
+    REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_TFCE);
+    REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_RFCE);
+    REG_CLR_BIT(EMAC_GMACFC_REG, EMAC_DZPQ);
+    REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PAUSE_TIME, 0);
+    REG_SET_FIELD(EMAC_GMACFC_REG, EMAC_PLT, 0);
+}
+
+void emac_enable_dma_tx(void)
+{
+    REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND);
+}
+
+void emac_enable_dma_rx(void)
+{
+    REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RX);
+}
+
+void emac_disable_dma_tx(void)
+{
+    REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_TRANSMISSION_COMMAND);
+}
+
+void emac_disable_dma_rx(void)
+{
+    REG_CLR_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_START_STOP_RX);
+}
+
+void emac_reset(void)
+{
+    REG_SET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST);
+
+    while (REG_GET_BIT(EMAC_DMABUSMODE_REG, EMAC_SW_RST) == 1) {
+        //nothing to do ,if stop here,maybe emac have not clk input.
+        ESP_LOGI(TAG, "emac resetting ....");
+    }
+
+    ESP_LOGI(TAG, "emac reset done");
+}
+
+void emac_enable_clk(bool enable)
+{
+    if (enable == true) {
+        DPORT_REG_SET_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
+    } else {
+        DPORT_REG_CLR_BIT(EMAC_CLK_EN_REG, EMAC_CLK_EN);
+    }
+}
+
+void emac_dma_init(void)
+{
+    REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_FWD_UNDER_GF);
+    REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_OPT_SECOND_FRAME);
+    REG_SET_FIELD(EMAC_DMABUSMODE_REG, EMAC_PROG_BURST_LEN, 4);
+    REG_SET_BIT(EMAC_DMAOPERATION_MODE_REG, EMAC_DMAOPERATION_MODE_REG);
+}
+
+void emac_mac_enable_txrx(void)
+{
+    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACRX);
+    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACTX);
+}
+
+void emac_mac_init(void)
+{
+    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX);
+    REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACMII);
+    REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
+    REG_SET_BIT(EMAC_GMACFF_REG, EMAC_PMODE);
+}
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/emac_dev.h b/cpu/esp32/vendor/esp-idf/ethernet/emac_dev.h
new file mode 100644
index 0000000000000000000000000000000000000000..e4962bc214cfe0025acee6de0ebc968088b131e0
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/emac_dev.h
@@ -0,0 +1,113 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef EMAC_DEV_H
+#define EMAC_DEV_H
+
+#include <stdint.h>
+#include "soc/emac_reg_v2.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define EMAC_INTR_ENABLE_BIT (EMAC_DMAIN_TIE | EMAC_DMAIN_RIE | EMAC_DMAIN_RBUE | EMAC_DMAIN_NISE)
+
+struct dma_desc {
+    uint32_t desc0;
+    uint32_t desc1;
+    uint32_t desc2;
+    uint32_t desc3;
+};
+
+struct dma_extended_desc {
+    struct dma_desc basic;
+    uint32_t desc4;
+    uint32_t desc5;
+    uint32_t desc6;
+    uint32_t desc7;
+};
+
+void emac_enable_clk(bool enable);
+void emac_reset(void);
+void emac_set_gpio_pin_rmii(void);
+void emac_set_gpio_pin_mii(void);
+uint32_t emac_read_mac_version(void);
+void emac_dma_init(void);
+void emac_mac_init(void);
+void emac_enable_dma_tx(void);
+void emac_enable_dma_rx(void);
+void emac_disable_dma_tx(void);
+void emac_disable_dma_rx(void);
+void emac_enable_flowctrl(void);
+void emac_disable_flowctrl(void);
+void emac_mac_enable_txrx(void);
+
+inline uint32_t emac_read_tx_cur_reg(void)
+{
+    return REG_READ(EMAC_DMATXCURRDESC_REG);
+}
+
+inline uint32_t emac_read_rx_cur_reg(void)
+{
+    return REG_READ(EMAC_DMARXCURRDESC_REG);
+}
+
+inline void emac_poll_tx_cmd(void)
+{
+    //write any to wake up dma
+    REG_WRITE(EMAC_DMATXPOLLDEMAND_REG, 1);
+}
+
+inline void emac_poll_rx_cmd(void)
+{
+    //write any to wake up dma
+    REG_WRITE(EMAC_DMARXPOLLDEMAND_REG, 1);
+}
+
+inline void emac_disable_rx_intr(void)
+{
+    REG_CLR_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RIE);
+}
+
+inline void emac_enable_rx_intr(void)
+{
+    REG_SET_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RIE);
+}
+
+inline void emac_disable_rx_unavail_intr(void)
+{
+    REG_CLR_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RBUE);
+}
+
+inline void emac_enable_rx_unavail_intr(void)
+{
+    REG_SET_BIT(EMAC_DMAIN_EN_REG, EMAC_DMAIN_RBUE);
+}
+
+inline void IRAM_ATTR emac_send_pause_frame_enable(void)
+{
+    REG_SET_BIT(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_SBD_FLOWCTRL);
+}
+
+inline void emac_send_pause_zero_frame_enable(void)
+{
+    REG_CLR_BIT(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_SBD_FLOWCTRL);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* EMAC_DEV_H */
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/emac_main.c b/cpu/esp32/vendor/esp-idf/ethernet/emac_main.c
new file mode 100644
index 0000000000000000000000000000000000000000..c83400f046a51dbb6d55a718d90f91d9c97e8bcd
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/emac_main.c
@@ -0,0 +1,1163 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "driver/periph_ctrl.h"
+#include "rom/ets_sys.h"
+#ifndef RIOT_VERSION
+#include "rom/gpio.h"
+#endif
+#include "soc/dport_reg.h"
+#include "soc/io_mux_reg.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/gpio_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/emac_ex_reg.h"
+#include "soc/emac_reg_v2.h"
+#include "soc/soc.h"
+
+#include "tcpip_adapter.h"
+#include "sdk_conf.h"
+
+#include "esp_task_wdt.h"
+#include "esp_event.h"
+#include "esp_system.h"
+#include "esp_err.h"
+#include "esp_log.h"
+#include "esp_eth.h"
+#include "esp_intr_alloc.h"
+#include "esp_pm.h"
+
+#include "driver/periph_ctrl.h"
+
+#include "emac_common.h"
+#include "emac_desc.h"
+
+#include "freertos/xtensa_api.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "freertos/queue.h"
+#include "freertos/semphr.h"
+#include "freertos/timers.h"
+
+#ifndef RIOT_VERSION
+#include "lwip/err.h"
+#else
+#define ERR_IF         -12   /* Low-level netif error    */
+#define ERR_MEM        -1    /* Out of memory error.     */
+#endif
+
+#define EMAC_EVT_QNUM 200
+#define EMAC_SIG_MAX 50
+
+static struct emac_config_data emac_config;
+
+static uint8_t emac_dma_rx_chain_buf[sizeof(struct dma_extended_desc) * DMA_RX_BUF_NUM];
+static uint8_t emac_dma_tx_chain_buf[sizeof(struct dma_extended_desc) * DMA_TX_BUF_NUM];
+static uint8_t emac_dma_rx_buf[DMA_RX_BUF_SIZE * DMA_RX_BUF_NUM];
+static uint8_t emac_dma_tx_buf[DMA_TX_BUF_SIZE * DMA_TX_BUF_NUM];
+
+static SemaphoreHandle_t emac_g_sem;
+static portMUX_TYPE g_emac_mux = portMUX_INITIALIZER_UNLOCKED;
+static xTaskHandle emac_task_hdl;
+static xQueueHandle emac_xqueue;
+static uint8_t emac_sig_cnt[EMAC_SIG_MAX] = {0};
+static TimerHandle_t emac_timer = NULL;
+static SemaphoreHandle_t emac_rx_xMutex = NULL;
+static SemaphoreHandle_t emac_tx_xMutex = NULL;
+static const char *TAG = "emac";
+static bool pause_send = false;
+#ifdef CONFIG_PM_ENABLE
+static esp_pm_lock_handle_t s_pm_lock;
+#endif
+
+static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par);
+esp_err_t emac_post(emac_sig_t sig, emac_par_t par);
+
+static void emac_macaddr_init(void)
+{
+    esp_read_mac(&(emac_config.macaddr[0]), ESP_MAC_ETH);
+}
+
+void esp_eth_get_mac(uint8_t mac[6])
+{
+    memcpy(mac, &(emac_config.macaddr[0]), 6);
+}
+
+esp_err_t esp_eth_set_mac(const uint8_t mac[6])
+{
+    if((mac[0] & 0x01) == 0) {
+        memcpy(&(emac_config.macaddr[0]),mac, 6);
+        return ESP_OK;
+    } else {
+        return ESP_ERR_INVALID_MAC;
+    }
+}
+
+static void emac_setup_tx_desc(struct dma_extended_desc *tx_desc , uint32_t size)
+{
+    tx_desc->basic.desc1 = size & 0xfff;
+    tx_desc->basic.desc0 = EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
+    tx_desc->basic.desc0 = EMAC_DESC_TX_OWN | EMAC_DESC_INT_COMPL | EMAC_DESC_LAST_SEGMENT | EMAC_DESC_FIRST_SEGMENT | EMAC_DESC_SECOND_ADDR_CHAIN;
+}
+
+static void emac_clean_tx_desc(struct dma_extended_desc *tx_desc)
+{
+    tx_desc->basic.desc1 = 0;
+    tx_desc->basic.desc0 = 0;
+}
+
+static void emac_clean_rx_desc(struct dma_extended_desc *rx_desc , uint32_t buf_ptr)
+{
+    if (buf_ptr != 0) {
+        rx_desc->basic.desc2 = buf_ptr;
+    }
+    rx_desc->basic.desc1 = EMAC_DESC_RX_SECOND_ADDR_CHAIN | DMA_RX_BUF_SIZE;
+    rx_desc->basic.desc0 = EMAC_DESC_RX_OWN;
+}
+
+static void emac_set_tx_base_reg(void)
+{
+    REG_WRITE(EMAC_DMATXBASEADDR_REG, (uint32_t)(emac_config.dma_etx));
+}
+
+static void emac_set_rx_base_reg(void)
+{
+    REG_WRITE(EMAC_DMARXBASEADDR_REG, (uint32_t)(emac_config.dma_erx));
+}
+
+/*
+* dirty_rx indicates the hardware has been fed with data packets and is the first node software needs to handle;
+*
+* cur_rx indicates the completion of software handling and is the last node hardware could use;
+*
+* cnt_rx is to count the numbers of packets handled by software, passed to protocol stack and not been freed.
+*
+* (1) Initializing the Linked List. Connect the numerable nodes to a circular linked list, appoint one of the nodes as the head node, mark* the dirty_rx and cur_rx into the node, and mount the node on the hardware base address. Initialize cnt_rx into 0.
+*
+* (2) When hardware receives packets, nodes of linked lists will be fed with data packets from the base address by turns, marks the node
+* of linked lists as “HARDWARE UNUSABLE” and reports interrupts.
+*
+* (3) When the software receives the interrupts, it will handle the linked lists by turns from dirty_rx, send data packets to protocol
+* stack. dirty_rx will deviate backwards by turns and cnt_rx will by turns ++.
+*
+* (4) After the protocol stack handles all the data and calls the free function, it will deviate backwards by turns from cur_rx, mark the * node of linked lists as “HARDWARE USABLE” and cnt_rx will by turns --.
+*
+* (5) Cycle from Step 2 to Step 4 without break and build up circular linked list handling.
+*/
+static void emac_reset_dma_chain(void)
+{
+    DEBUG("%s", __func__);
+    emac_config.cnt_tx = 0;
+    emac_config.cur_tx = 0;
+    emac_config.dirty_tx = 0;
+
+    emac_config.cnt_rx = 0;
+    emac_config.cur_rx = 0;
+    emac_config.dirty_rx = 0;
+}
+
+static void emac_init_dma_chain(void)
+{
+    DEBUG("%s", __func__);
+    int i;
+    uint32_t dma_phy;
+    struct dma_extended_desc *p = NULL;
+
+    //init tx chain
+    emac_config.dma_etx = (struct dma_extended_desc *)(&emac_dma_tx_chain_buf[0]);
+    emac_config.cnt_tx = 0;
+    emac_config.cur_tx = 0;
+    emac_config.dirty_tx = 0;
+
+    dma_phy = (uint32_t)(emac_config.dma_etx);
+    p = emac_config.dma_etx;
+
+    for (i = 0; i < (DMA_TX_BUF_NUM - 1); i++ ) {
+        dma_phy += sizeof(struct dma_extended_desc);
+        emac_clean_tx_desc(p);
+        p->basic.desc3 = dma_phy;
+        p->basic.desc2 = (uint32_t)(&emac_dma_tx_buf[0]) + (i * DMA_TX_BUF_SIZE);
+        p++;
+    }
+    p->basic.desc3 = (uint32_t)(emac_config.dma_etx);
+    p->basic.desc2 = (uint32_t)(&emac_dma_tx_buf[0]) + (i * DMA_TX_BUF_SIZE);
+
+    //init desc0 desc1
+    emac_clean_tx_desc(p);
+
+    //init rx chain
+    emac_config.dma_erx = (struct dma_extended_desc *)(&emac_dma_rx_chain_buf[0]);
+    emac_config.cnt_rx = 0;
+    emac_config.cur_rx = 0;
+    emac_config.dirty_rx = 0;
+
+    dma_phy = (uint32_t)(emac_config.dma_erx);
+    p = emac_config.dma_erx;
+
+    for (i = 0; i < (DMA_RX_BUF_NUM - 1); i++ ) {
+        dma_phy += sizeof(struct dma_extended_desc);
+        emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
+        p->basic.desc3 = dma_phy;
+        p++;
+    }
+
+    emac_clean_rx_desc(p, (uint32_t)(&emac_dma_rx_buf[0]) + (i * DMA_RX_BUF_SIZE));
+    p->basic.desc3 = (uint32_t)(emac_config.dma_erx);
+}
+
+void esp_eth_smi_write(uint32_t reg_num, uint16_t value)
+{
+    uint32_t phy_num = emac_config.phy_addr;
+
+    while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
+    }
+
+    REG_WRITE(EMAC_MIIDATA_REG, value);
+    REG_WRITE(EMAC_GMIIADDR_REG, 0x3 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | ((0x3) << 2));
+
+    while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
+    }
+}
+
+uint16_t esp_eth_smi_read(uint32_t reg_num)
+{
+    uint32_t phy_num = emac_config.phy_addr;
+    uint16_t value = 0;
+
+    while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
+    }
+
+    REG_WRITE(EMAC_GMIIADDR_REG, 0x1 | ((reg_num & 0x1f) << 6) | ((phy_num & 0x1f) << 11) | (0x3 << 2));
+    while (REG_GET_BIT(EMAC_GMIIADDR_REG, EMAC_MIIBUSY) == 1 ) {
+    }
+    value = (REG_READ(EMAC_MIIDATA_REG) & 0xffff);
+
+    return value;
+}
+
+esp_err_t esp_eth_smi_wait_value(uint32_t reg_num, uint16_t value, uint16_t value_mask, int timeout_ms)
+{
+    unsigned start = xTaskGetTickCount();
+    unsigned timeout_ticks = (timeout_ms + portTICK_PERIOD_MS - 1) / portTICK_PERIOD_MS;
+    uint16_t current_value = 0;
+
+    while (timeout_ticks == 0 || (xTaskGetTickCount() - start < timeout_ticks)) {
+        current_value = esp_eth_smi_read(reg_num);
+        if ((current_value & value_mask) == (value & value_mask)) {
+            return ESP_OK;
+        }
+        vTaskDelay(1);
+    }
+    ESP_LOGE(TAG, "Timed out waiting for PHY register 0x%x to have value 0x%04x (mask 0x%04x). Current value 0x%04x",
+             reg_num, value, value_mask, current_value);
+    return ESP_ERR_TIMEOUT;
+}
+
+
+static void emac_set_user_config_data(eth_config_t *config )
+{
+    DEBUG("%s", __func__);
+    emac_config.phy_addr = config->phy_addr;
+    emac_config.mac_mode = config->mac_mode;
+    emac_config.clock_mode = config->clock_mode;
+    emac_config.phy_init = config->phy_init;
+    emac_config.emac_tcpip_input = config->tcpip_input;
+    emac_config.emac_gpio_config = config->gpio_config;
+    emac_config.emac_phy_check_link = config->phy_check_link;
+    emac_config.emac_phy_check_init = config->phy_check_init;
+    emac_config.emac_phy_get_speed_mode = config->phy_get_speed_mode;
+    emac_config.emac_phy_get_duplex_mode = config->phy_get_duplex_mode;
+#if DMA_RX_BUF_NUM > 9
+    emac_config.emac_flow_ctrl_enable = config->flow_ctrl_enable;
+#else
+    if(config->flow_ctrl_enable == true) {
+        ESP_LOGE(TAG, "eth flow ctrl init err!!! Please run make menuconfig and make sure DMA_RX_BUF_NUM > 9 .");
+    }
+    emac_config.emac_flow_ctrl_enable = false;
+#endif
+    emac_config.emac_phy_get_partner_pause_enable = config->phy_get_partner_pause_enable;
+    emac_config.emac_phy_power_enable = config->phy_power_enable;
+}
+
+static void emac_enable_intr(void)
+{
+    DEBUG("%s", __func__);
+    REG_WRITE(EMAC_DMAIN_EN_REG, EMAC_INTR_ENABLE_BIT);
+}
+
+static void emac_disable_intr(void)
+{
+    DEBUG("%s", __func__);
+    REG_WRITE(EMAC_DMAIN_EN_REG, 0);
+}
+
+static esp_err_t emac_verify_args(void)
+{
+    DEBUG("%s", __func__);
+    esp_err_t ret = ESP_OK;
+
+    if (emac_config.phy_addr > PHY31) {
+        ESP_LOGE(TAG, "phy addr err");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.mac_mode != ETH_MODE_RMII) {
+        ESP_LOGE(TAG, "mac mode err, currently only support for RMII");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.clock_mode > ETH_CLOCK_GPIO17_OUT) {
+        ESP_LOGE(TAG, "emac clock mode err");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.phy_init == NULL) {
+        ESP_LOGE(TAG, "phy_init func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_tcpip_input == NULL) {
+        ESP_LOGE(TAG, "tcpip_input func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_gpio_config == NULL) {
+        ESP_LOGE(TAG, "gpio config func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_check_link == NULL) {
+        ESP_LOGE(TAG, "phy check link func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_check_init == NULL) {
+        ESP_LOGE(TAG, "phy check init func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_get_speed_mode == NULL) {
+        ESP_LOGE(TAG, "phy get speed mode func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_phy_get_duplex_mode == NULL) {
+        ESP_LOGE(TAG, "phy get duplex mode func is null");
+        ret = ESP_FAIL;
+    }
+
+    if (emac_config.emac_flow_ctrl_enable == true && emac_config.emac_phy_get_partner_pause_enable == NULL) {
+        ESP_LOGE(TAG, "phy get partner pause enable func is null");
+        ret = ESP_FAIL;
+    }
+
+    if(emac_config.emac_phy_power_enable == NULL) {
+        ESP_LOGE(TAG, "phy power enable func is null");
+        ret = ESP_FAIL;
+    }
+
+    return ret;
+}
+
+static void emac_process_tx(void)
+{
+    DEBUG("%s", __func__);
+    uint32_t cur_tx_desc = emac_read_tx_cur_reg();
+
+    if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    while (((uint32_t) & (emac_config.dma_etx[emac_config.dirty_tx].basic.desc0) != cur_tx_desc)) {
+        emac_clean_tx_desc(&(emac_config.dma_etx[emac_config.dirty_tx]));
+        emac_config.dirty_tx = (emac_config.dirty_tx + 1) % DMA_TX_BUF_NUM;
+        emac_config.cnt_tx --;
+
+        if (emac_config.cnt_tx < 0) {
+            ESP_LOGE(TAG, "emac tx chain err");
+        }
+        cur_tx_desc = emac_read_tx_cur_reg();
+    }
+
+    xSemaphoreGiveRecursive( emac_tx_xMutex );
+}
+
+void esp_eth_free_rx_buf(void *buf)
+{
+    DEBUG("%s", __func__);
+    xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.cur_rx]), (uint32_t) buf);
+    emac_config.cur_rx = (emac_config.cur_rx + 1) % DMA_RX_BUF_NUM;
+    emac_config.cnt_rx--;
+    if (emac_config.cnt_rx < 0) {
+        ESP_LOGE(TAG, "emac rx buf err!!\n");
+    }
+    emac_poll_rx_cmd();
+
+    xSemaphoreGiveRecursive( emac_rx_xMutex );
+
+    if (emac_config.emac_flow_ctrl_partner_support == true) {
+        portENTER_CRITICAL(&g_emac_mux);
+        if (pause_send == true && emac_config.cnt_rx < FLOW_CONTROL_LOW_WATERMARK) {
+            emac_send_pause_zero_frame_enable();
+            pause_send = false;
+        }
+        portEXIT_CRITICAL(&g_emac_mux);
+    }
+}
+
+static uint32_t IRAM_ATTR emac_get_rxbuf_count_in_intr(void)
+{
+    DEBUG("%s", __func__);
+    uint32_t cnt = 0;
+    uint32_t cur_rx_desc = emac_read_rx_cur_reg();
+    struct dma_extended_desc *cur_desc = (struct dma_extended_desc *)cur_rx_desc;
+
+    while (cur_desc->basic.desc0 == EMAC_DESC_RX_OWN && cnt < DMA_RX_BUF_NUM) {
+        cnt++;
+        cur_desc = (struct dma_extended_desc *)cur_desc->basic.desc3;
+    }
+    return cnt;
+}
+
+#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
+static void emac_process_rx(void)
+{
+    DEBUG("%s", __func__);
+    if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+    uint32_t cur_rx_desc = emac_read_rx_cur_reg();
+
+    while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
+        //copy data to lwip
+        emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
+                                     (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+        emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]), (emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
+        emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+
+        //if open this ,one intr can do many intrs ?
+        cur_rx_desc = emac_read_rx_cur_reg();
+    }
+
+    emac_enable_rx_intr();
+}
+
+static void emac_process_rx_unavail(void)
+{
+    DEBUG("%s", __func__);
+    if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    uint32_t dirty_cnt = 0;
+    while (dirty_cnt < DMA_RX_BUF_NUM) {
+
+        if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
+            break;
+        }
+
+        dirty_cnt ++;
+        //copy data to lwip
+        emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[emac_config.dirty_rx].basic.desc2),
+                                     (((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+        emac_clean_rx_desc(&(emac_config.dma_erx[emac_config.dirty_rx]), (emac_config.dma_erx[emac_config.dirty_rx].basic.desc2));
+        emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+    }
+    emac_enable_rx_intr();
+    emac_enable_rx_unavail_intr();
+    emac_poll_rx_cmd();
+}
+
+#else
+static void emac_process_rx_unavail(void)
+{
+    DEBUG("%s", __func__);
+    if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
+
+        if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
+            break;
+        }
+
+        emac_config.cnt_rx++;
+        if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
+            ESP_LOGE(TAG, "emac rx unavail buf err !!\n");
+        }
+        uint32_t tmp_dirty = emac_config.dirty_rx;
+        emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+
+        //copy data to lwip
+        emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
+                                     (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+   }
+    emac_enable_rx_intr();
+    emac_enable_rx_unavail_intr();
+    xSemaphoreGiveRecursive( emac_rx_xMutex );
+}
+
+static void emac_process_rx(void)
+{
+    DEBUG("%s", __func__);
+    if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        return;
+    }
+
+    uint32_t cur_rx_desc = emac_read_rx_cur_reg();
+
+    xSemaphoreTakeRecursive( emac_rx_xMutex, ( TickType_t ) portMAX_DELAY );
+
+    if (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc)) {
+
+        while (((uint32_t) & (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0) != cur_rx_desc) && emac_config.cnt_rx < DMA_RX_BUF_NUM ) {
+            emac_config.cnt_rx++;
+            if (emac_config.cnt_rx > DMA_RX_BUF_NUM ) {
+                ESP_LOGE(TAG, "emac rx buf err!!\n");
+            }
+            uint32_t tmp_dirty = emac_config.dirty_rx;
+            emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+
+
+            //copy data to lwip
+            emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
+                                         (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+            cur_rx_desc = emac_read_rx_cur_reg();
+        }
+    } else {
+        if (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
+            if ((emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 & EMAC_DESC_RX_OWN) == 0) {
+                while (emac_config.cnt_rx < DMA_RX_BUF_NUM) {
+
+                    if (emac_config.dma_erx[emac_config.dirty_rx].basic.desc0 == EMAC_DESC_RX_OWN) {
+                        break;
+                    }
+
+                    emac_config.cnt_rx++;
+                    if (emac_config.cnt_rx > DMA_RX_BUF_NUM) {
+                        ESP_LOGE(TAG, "emac rx buf err!!!\n");
+                    }
+                    uint32_t tmp_dirty = emac_config.dirty_rx;
+                    emac_config.dirty_rx = (emac_config.dirty_rx + 1) % DMA_RX_BUF_NUM;
+
+                    //copy data to lwip
+                    emac_config.emac_tcpip_input((void *)(emac_config.dma_erx[tmp_dirty].basic.desc2),
+                                                 (((emac_config.dma_erx[tmp_dirty].basic.desc0) >> EMAC_DESC_FRAME_LENGTH_S) & EMAC_DESC_FRAME_LENGTH) , NULL);
+
+               }
+            }
+        }
+    }
+    emac_enable_rx_intr();
+    xSemaphoreGiveRecursive( emac_rx_xMutex );
+}
+#endif
+
+//TODO other events need to do something
+static void IRAM_ATTR emac_process_intr(void *arg)
+{
+    uint32_t event;
+    event = REG_READ(EMAC_DMASTATUS_REG);
+
+    //clr intrs
+    REG_WRITE(EMAC_DMASTATUS_REG, event);
+
+    if (event & EMAC_RECV_INT) {
+        emac_disable_rx_intr();
+        if (emac_config.emac_flow_ctrl_partner_support == true) {
+            if (emac_get_rxbuf_count_in_intr() < FLOW_CONTROL_HIGH_WATERMARK && pause_send == false ) {
+                pause_send = true;
+                emac_send_pause_frame_enable();
+            }
+        }
+        DEBUG("%s SIG_EMAC_RX_DONE", __func__);
+        emac_post(SIG_EMAC_RX_DONE, 0);
+    }
+
+    if (event & EMAC_RECV_BUF_UNAVAIL) {
+        emac_disable_rx_unavail_intr();
+        DEBUG("%s SIG_EMAC_RX_UNAVAIL", __func__);
+        emac_post(SIG_EMAC_RX_UNAVAIL, 0);
+    }
+
+    if (event & EMAC_TRANS_INT) {
+        DEBUG("%s SIG_EMAC_TX_DONE", __func__);
+        emac_post(SIG_EMAC_TX_DONE, 0);
+    }
+}
+
+static void emac_set_macaddr_reg(void)
+{
+    DEBUG("%s", __func__);
+    REG_SET_FIELD(EMAC_ADDR0HIGH_REG, EMAC_ADDRESS0_HI, (emac_config.macaddr[0] << 8) | (emac_config.macaddr[1]));
+    REG_WRITE(EMAC_ADDR0LOW_REG, (emac_config.macaddr[2] << 24) |  (emac_config.macaddr[3] << 16) | (emac_config.macaddr[4] << 8) | (emac_config.macaddr[5]));
+}
+
+static void emac_check_phy_init(void)
+{
+    DEBUG("%s", __func__);
+    emac_config.emac_phy_check_init();
+    if (emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
+        REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX);
+    } else {
+        REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACDUPLEX);
+    }
+    if (emac_config.emac_phy_get_speed_mode() == ETH_SPEED_MODE_100M) {
+        REG_SET_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
+    } else {
+        REG_CLR_BIT(EMAC_GMACCONFIG_REG, EMAC_EMACFESPEED);
+    }
+#if CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE
+    emac_disable_flowctrl();
+    emac_config.emac_flow_ctrl_partner_support = false;
+#else
+    if (emac_config.emac_flow_ctrl_enable == true) {
+        if (emac_config.emac_phy_get_partner_pause_enable() == true && emac_config.emac_phy_get_duplex_mode() == ETH_MODE_FULLDUPLEX) {
+            emac_enable_flowctrl();
+            emac_config.emac_flow_ctrl_partner_support = true;
+        } else {
+            emac_disable_flowctrl();
+            emac_config.emac_flow_ctrl_partner_support = false;
+        }
+    } else {
+        emac_disable_flowctrl();
+        emac_config.emac_flow_ctrl_partner_support = false;
+    }
+#endif
+    emac_mac_enable_txrx();
+}
+
+static void emac_process_link_updown(bool link_status)
+{
+    DEBUG("%s", __func__);
+    system_event_t evt;
+    uint8_t i = 0;
+
+    emac_config.phy_link_up = link_status;
+
+    if (link_status == true) {
+        emac_check_phy_init();
+        ESP_LOGI(TAG, "eth link_up!!!");
+        emac_enable_dma_tx();
+        emac_enable_dma_rx();
+        for (i = 0; i < PHY_LINK_CHECK_NUM; i++) {
+            emac_check_phy_init();
+        }
+
+        evt.event_id = SYSTEM_EVENT_ETH_CONNECTED;
+    } else {
+        ESP_LOGI(TAG, "eth link_down!!!");
+        emac_disable_dma_tx();
+        emac_disable_dma_rx();
+        evt.event_id = SYSTEM_EVENT_ETH_DISCONNECTED;
+    }
+
+    esp_event_send(&evt);
+}
+
+static void emac_hw_init(void)
+{
+    DEBUG("%s", __func__);
+    //init chain
+    emac_init_dma_chain();
+
+    //get hw features TODO
+
+    //ipc TODO
+}
+
+esp_err_t esp_eth_tx(uint8_t *buf, uint16_t size)
+{
+    DEBUG("%s: buf=%p size=%d", __func__, buf, size);
+    esp_err_t ret = ESP_OK;
+
+    if (emac_config.emac_status != EMAC_RUNTIME_START || emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
+        ESP_LOGI(TAG, "tx netif close");
+        ret = ERR_IF;
+        return ret;
+    }
+
+    xSemaphoreTakeRecursive( emac_tx_xMutex, ( TickType_t ) portMAX_DELAY );
+    if (emac_config.cnt_tx == DMA_TX_BUF_NUM - 1) {
+        ESP_LOGD(TAG, "tx buf full");
+        ret = ERR_MEM;
+        goto _exit;
+    }
+
+    memcpy((uint8_t *)(emac_config.dma_etx[emac_config.cur_tx].basic.desc2), (uint8_t *)buf, size);
+
+    emac_setup_tx_desc(&(emac_config.dma_etx[emac_config.cur_tx]), size);
+
+    emac_config.cnt_tx ++;
+    emac_config.cur_tx = (emac_config.cur_tx + 1) % DMA_TX_BUF_NUM ;
+
+    emac_poll_tx_cmd();
+
+_exit:
+
+    xSemaphoreGiveRecursive( emac_tx_xMutex );
+
+    return ret;
+}
+
+static void emac_init_default_data(void)
+{
+    DEBUG("%s", __func__);
+    memset((uint8_t *)&emac_config, 0, sizeof(struct emac_config_data));
+}
+
+void emac_process_link_check(void)
+{
+    DEBUG("%s", __func__);
+    if (emac_config.emac_status != EMAC_RUNTIME_START ||
+            emac_config.emac_status == EMAC_RUNTIME_NOT_INIT) {
+        return;
+    }
+
+    if (emac_config.emac_phy_check_link() == true ) {
+        if (emac_config.phy_link_up == false) {
+            emac_process_link_updown(true);
+        }
+    } else {
+        if (emac_config.phy_link_up == true) {
+            emac_process_link_updown(false);
+        }
+    }
+}
+
+void emac_link_check_func(void *pv_parameters)
+{
+    DEBUG("%s", __func__);
+    emac_post(SIG_EMAC_CHECK_LINK, 0);
+}
+
+static bool emac_link_check_timer_init(void)
+{
+    DEBUG("%s", __func__);
+    emac_timer = xTimerCreate("emac_timer", (2000 / portTICK_PERIOD_MS),
+                              pdTRUE, (void *)rand(), emac_link_check_func);
+    if (emac_timer == NULL) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+static bool emac_link_check_timer_start(void)
+{
+    DEBUG("%s", __func__);
+    if (xTimerStart(emac_timer, portMAX_DELAY) != pdPASS) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+static bool emac_link_check_timer_stop(void)
+{
+    DEBUG("%s", __func__);
+    if (xTimerStop(emac_timer, portMAX_DELAY) != pdPASS) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+static bool emac_link_check_timer_delete(void)
+{
+    DEBUG("%s", __func__);
+    xTimerDelete(emac_timer, portMAX_DELAY);
+    emac_timer = NULL;
+    return true;
+}
+
+static void emac_start(void *param)
+{
+    DEBUG("%s", __func__);
+    struct emac_post_cmd  *post_cmd = (struct emac_post_cmd *)param;
+    struct emac_open_cmd *cmd = (struct emac_open_cmd *)(post_cmd->cmd);
+
+    ESP_LOGI(TAG , "emac start !!!\n");
+    cmd->err = EMAC_CMD_OK;
+    emac_enable_clk(true);
+
+    emac_reset();
+
+    emac_set_macaddr_reg();
+
+    emac_set_tx_base_reg();
+    emac_set_rx_base_reg();
+
+    emac_mac_init();
+
+    emac_config.phy_init();
+
+    //ptp TODO
+
+    emac_enable_intr();
+
+    emac_config.emac_status = EMAC_RUNTIME_START;
+
+    system_event_t evt;
+    evt.event_id = SYSTEM_EVENT_ETH_START;
+    esp_event_send(&evt);
+
+    //set a timer to check link up status
+    if (emac_link_check_timer_init() == true) {
+        if (emac_link_check_timer_start() != true) {
+            cmd->err = EMAC_CMD_FAIL;
+            emac_link_check_timer_delete();
+        }
+    } else {
+        cmd->err = EMAC_CMD_FAIL;
+    }
+
+    if (post_cmd->post_type == EMAC_POST_SYNC) {
+        xSemaphoreGive(emac_g_sem);
+    }
+
+    ESP_LOGI(TAG, "emac start success !!!");
+}
+
+esp_err_t esp_eth_enable(void)
+{
+    DEBUG("%s", __func__);
+    struct emac_post_cmd post_cmd;
+    struct emac_open_cmd open_cmd;
+
+    post_cmd.cmd = (void *)(&open_cmd);
+    open_cmd.err = EMAC_CMD_OK;
+
+    if (emac_config.emac_status == EMAC_RUNTIME_START) {
+        open_cmd.err = EMAC_CMD_OK;
+        return open_cmd.err;
+    }
+
+#ifdef CONFIG_PM_ENABLE
+    esp_err_t err = esp_pm_lock_create(ESP_PM_APB_FREQ_MAX, 0, "ethernet", &s_pm_lock);
+    if (err != ESP_OK) {
+        return err;
+    }
+    esp_pm_lock_acquire(s_pm_lock);
+#endif //CONFIG_PM_ENABLE
+
+    if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
+        if (emac_ioctl(SIG_EMAC_START, (emac_par_t)(&post_cmd)) != 0) {
+            open_cmd.err = EMAC_CMD_FAIL;
+            goto cleanup;
+        }
+    } else {
+        open_cmd.err = EMAC_CMD_FAIL;
+        goto cleanup;
+    }
+    return EMAC_CMD_OK;
+
+cleanup:
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_release(s_pm_lock);
+    esp_pm_lock_delete(s_pm_lock);
+    s_pm_lock = NULL;
+#endif //CONFIG_PM_ENABLE
+    return open_cmd.err;
+}
+
+static void emac_stop(void *param)
+{
+    DEBUG("%s", __func__);
+    struct emac_post_cmd  *post_cmd = (struct emac_post_cmd *)param;
+    ESP_LOGI(TAG, "emac stop");
+
+    emac_link_check_timer_stop();
+    emac_link_check_timer_delete();
+
+    emac_process_link_updown(false);
+
+    emac_disable_intr();
+    emac_reset_dma_chain();
+    emac_reset();
+    emac_enable_clk(false);
+
+    emac_config.emac_status = EMAC_RUNTIME_STOP;
+    system_event_t evt;
+    evt.event_id = SYSTEM_EVENT_ETH_STOP;
+    esp_event_send(&evt);
+
+    if (post_cmd->post_type == EMAC_POST_SYNC) {
+        xSemaphoreGive(emac_g_sem);
+    }
+
+    ESP_LOGI(TAG, "emac stop success !!!");
+}
+
+esp_err_t esp_eth_disable(void)
+{
+    DEBUG("%s", __func__);
+    struct emac_post_cmd post_cmd;
+    struct emac_close_cmd close_cmd;
+
+    post_cmd.cmd = (void *)(&close_cmd);
+    close_cmd.err = EMAC_CMD_OK;
+
+    if (emac_config.emac_status == EMAC_RUNTIME_STOP) {
+        close_cmd.err = EMAC_CMD_OK;
+        return close_cmd.err;
+    }
+
+#ifdef CONFIG_PM_ENABLE
+    esp_pm_lock_release(s_pm_lock);
+    esp_pm_lock_delete(s_pm_lock);
+    s_pm_lock = NULL;
+#endif // CONFIG_PM_ENABLE
+
+    if (emac_config.emac_status == EMAC_RUNTIME_START) {
+        if (emac_ioctl(SIG_EMAC_STOP, (emac_par_t)(&post_cmd)) != 0) {
+            close_cmd.err = EMAC_CMD_FAIL;
+        }
+    } else {
+        close_cmd.err = EMAC_CMD_FAIL;
+    }
+    return close_cmd.err;
+}
+
+static esp_err_t emac_ioctl(emac_sig_t sig, emac_par_t par)
+{
+    DEBUG("%s sig=%d par=%08x", __func__, sig, par);
+    esp_err_t ret = ESP_OK;
+    struct emac_post_cmd  *post_cmd = (struct emac_post_cmd *)par;
+    xTaskHandle task_hdl = xTaskGetCurrentTaskHandle();
+
+    if (emac_task_hdl != task_hdl) {
+        post_cmd->post_type = EMAC_POST_SYNC;
+        if (emac_post(sig, par) != ESP_OK) {
+            ret = ESP_FAIL;
+            return ret;
+        };
+
+        if (xSemaphoreTake(emac_g_sem, portMAX_DELAY) == pdTRUE) {
+            return ret;
+        }
+    } else {
+        post_cmd->post_type = EMAC_POST_ASYNC;
+        switch (sig) {
+        case SIG_EMAC_RX_DONE:
+            emac_process_rx();
+            break;
+        case SIG_EMAC_TX_DONE:
+            emac_process_tx();
+            break;
+        case SIG_EMAC_START:
+            emac_start((void *)par);
+            break;
+        case SIG_EMAC_STOP:
+            emac_stop((void *)par);
+            break;
+        default:
+            ESP_LOGE(TAG, "unexpect sig %d", sig);
+            break;
+        }
+    }
+
+    return ret;
+}
+
+void emac_task(void *pv)
+{
+    emac_event_t e;
+
+    for (;;) {
+        if (xQueueReceive(emac_xqueue, &e, (portTickType)portMAX_DELAY) == pdTRUE) {
+            portENTER_CRITICAL(&g_emac_mux);
+            emac_sig_cnt[e.sig]--;
+            portEXIT_CRITICAL(&g_emac_mux);
+            DEBUG("%s sig=%d par=%08x", __func__, e.sig, e.par);
+            switch (e.sig) {
+            case SIG_EMAC_RX_DONE:
+                emac_process_rx();
+                break;
+            case SIG_EMAC_RX_UNAVAIL:
+                emac_process_rx_unavail();
+                break;
+            case SIG_EMAC_TX_DONE:
+                emac_process_tx();
+                break;
+            case SIG_EMAC_START:
+                emac_start((void *)e.par);
+                break;
+            case SIG_EMAC_STOP:
+                emac_stop((void *)e.par);
+                break;
+            case SIG_EMAC_CHECK_LINK:
+                emac_process_link_check();
+                break;
+            default:
+                ESP_LOGE(TAG, "unexpect sig %d", e.sig);
+                break;
+            }
+        }
+    }
+}
+
+esp_err_t IRAM_ATTR emac_post(emac_sig_t sig, emac_par_t par)
+{
+    DEBUG("%s sig=%d par=%08x", __func__, sig, par);
+    if (sig <= SIG_EMAC_RX_DONE) {
+        if (emac_sig_cnt[sig]) {
+            return ESP_OK;
+        } else {
+            emac_sig_cnt[sig]++;
+            emac_event_t evt;
+            portBASE_TYPE ret;
+            evt.sig = sig;
+            evt.par = par;
+            portBASE_TYPE tmp;
+
+            ret = xQueueSendFromISR(emac_xqueue, &evt, &tmp);
+
+            if (tmp != pdFALSE) {
+                portYIELD_FROM_ISR();
+            }
+
+            if (ret != pdPASS) {
+                return ESP_FAIL;
+            }
+        }
+    } else {
+        portENTER_CRITICAL(&g_emac_mux);
+        emac_sig_cnt[sig]++;
+        portEXIT_CRITICAL(&g_emac_mux);
+        emac_event_t evt;
+        evt.sig = sig;
+        evt.par = par;
+
+        if (xQueueSend(emac_xqueue, &evt, 10 / portTICK_PERIOD_MS) != pdTRUE) {
+            return ESP_FAIL;
+        }
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t esp_eth_init(eth_config_t *config)
+{
+     DEBUG("%s", __func__);
+     esp_event_set_default_eth_handlers();
+     return esp_eth_init_internal(config);
+}
+
+esp_err_t esp_eth_init_internal(eth_config_t *config)
+{
+    DEBUG("%s", __func__);
+    esp_err_t ret = ESP_OK;
+    if (emac_config.emac_status != EMAC_RUNTIME_NOT_INIT) {
+        goto _exit;
+    }
+
+    emac_init_default_data();
+
+    if (config != NULL ) {
+        emac_set_user_config_data(config);
+    }
+
+    ret = emac_verify_args();
+
+    if (ret != ESP_OK) {
+        goto _exit;
+    }
+
+    emac_config.emac_phy_power_enable(true);
+
+    //before set emac reg must enable clk
+    periph_module_enable(PERIPH_EMAC_MODULE);
+
+    if (emac_config.clock_mode != ETH_CLOCK_GPIO0_IN) {
+        // 50 MHz = 40MHz * (6 + 4) / (2 * (2 + 2) = 400MHz / 8
+        rtc_clk_apll_enable(1, 0, 0, 6, 2);
+        // the next to values have to be set AFTER "periph_module_enable" is called
+        REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_H_DIV_NUM, 0);
+        REG_SET_FIELD(EMAC_EX_CLKOUT_CONF_REG, EMAC_EX_CLK_OUT_DIV_NUM, 0);
+
+        if (emac_config.clock_mode == ETH_CLOCK_GPIO0_OUT) {
+            PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO0_U, FUNC_GPIO0_CLK_OUT1);
+            REG_WRITE(PIN_CTRL, 6);
+            ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO0");
+        } else if (emac_config.clock_mode == ETH_CLOCK_GPIO16_OUT) {
+            PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO16_U, FUNC_GPIO16_EMAC_CLK_OUT);
+            ESP_LOGD(TAG, "EMAC 50MHz clock output on GPIO16");
+        } else if (emac_config.clock_mode == ETH_CLOCK_GPIO17_OUT) {
+            PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO17_U, FUNC_GPIO17_EMAC_CLK_OUT_180);
+            ESP_LOGD(TAG, "EMAC 50MHz inverted clock output on GPIO17");
+        }
+    }
+
+    emac_enable_clk(true);
+    REG_SET_FIELD(EMAC_EX_PHYINF_CONF_REG, EMAC_EX_PHY_INTF_SEL, EMAC_EX_PHY_INTF_RMII);
+    emac_dma_init();
+
+    if (emac_config.clock_mode == ETH_CLOCK_GPIO0_IN) {
+        // external clock on GPIO0
+        REG_SET_BIT(EMAC_EX_CLK_CTRL_REG,    EMAC_EX_EXT_OSC_EN);
+        REG_CLR_BIT(EMAC_EX_CLK_CTRL_REG,    EMAC_EX_INT_OSC_EN);
+        REG_SET_BIT(EMAC_EX_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
+        ESP_LOGD(TAG, "External clock input 50MHz on GPIO0");
+        if (emac_config.mac_mode == ETH_MODE_MII) {
+            REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_MII_CLK_RX_EN);
+            REG_SET_BIT(EMAC_EX_CLK_CTRL_REG, EMAC_EX_MII_CLK_TX_EN);
+        }
+    } else {
+        // internal clock by APLL
+        REG_CLR_BIT(EMAC_EX_CLK_CTRL_REG,    EMAC_EX_EXT_OSC_EN);
+        REG_SET_BIT(EMAC_EX_CLK_CTRL_REG,    EMAC_EX_INT_OSC_EN);
+        REG_CLR_BIT(EMAC_EX_OSCCLK_CONF_REG, EMAC_EX_OSC_CLK_SEL);
+    }
+
+    emac_config.emac_gpio_config();
+
+    emac_hw_init();
+    emac_macaddr_init();
+
+    //watchdog  TODO
+
+    //init task for emac
+    emac_g_sem = xSemaphoreCreateBinary();
+    emac_rx_xMutex = xSemaphoreCreateRecursiveMutex();
+    emac_tx_xMutex = xSemaphoreCreateRecursiveMutex();
+    emac_xqueue = xQueueCreate(EMAC_EVT_QNUM, sizeof(emac_event_t));
+    xTaskCreate(emac_task, "emac", 2048, NULL, EMAC_TASK_PRIORITY, &emac_task_hdl);
+
+    emac_enable_clk(false);
+    esp_intr_alloc(ETS_ETH_MAC_INTR_SOURCE, 0, emac_process_intr, NULL, NULL);
+
+    emac_config.emac_status = EMAC_RUNTIME_INIT;
+
+_exit:
+    return ret;
+}
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/Makefile b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..eca16e3db64013fbe9d21537208a8b32a770da84
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/Makefile
@@ -0,0 +1,7 @@
+MODULE=esp_idf_eth_phy
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/esp32
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(ESP32_SDK_DIR)/components/ethernet/include
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_common.c b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..f4567229f6f6c12a0509d3054ba8b54bc20a83bf
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_common.c
@@ -0,0 +1,99 @@
+// 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.
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+#include "eth_phy/phy.h"
+#include "eth_phy/phy_reg.h"
+#include "driver/gpio.h"
+#include "gpio_arch.h"
+#include "esp_log.h"
+
+static const char *TAG = "phy_common";
+
+void phy_rmii_configure_data_interface_pins(void)
+{
+    // CRS_DRV to GPIO27
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO27_U, FUNC_GPIO27_EMAC_RX_DV);
+    // TXD0 to GPIO19
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO19_U, FUNC_GPIO19_EMAC_TXD0);
+    // TX_EN to GPIO21
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO21_U, FUNC_GPIO21_EMAC_TX_EN);
+    // TXD1 to GPIO22
+    PIN_FUNC_SELECT(PERIPHS_IO_MUX_GPIO22_U, FUNC_GPIO22_EMAC_TXD1);
+    // RXD0 to GPIO25
+    gpio_set_direction(25, GPIO_MODE_INPUT);
+    // RXD1 to GPIO26
+    gpio_set_direction(26, GPIO_MODE_INPUT);
+    // RMII CLK to GPIO0
+    gpio_set_direction(0, GPIO_MODE_INPUT);
+
+    #ifndef RIOT_VERSION
+    _gpio_pin_usage[GPIO27] = _EMAC;
+    _gpio_pin_usage[GPIO19] = _EMAC;
+    _gpio_pin_usage[GPIO21] = _EMAC;
+    _gpio_pin_usage[GPIO22] = _EMAC;
+    _gpio_pin_usage[GPIO25] = _EMAC;
+    _gpio_pin_usage[GPIO26] = _EMAC;
+    _gpio_pin_usage[GPIO0]  = _EMAC;
+    #endif /* RIOT_VERSION */
+}
+
+void phy_rmii_smi_configure_pins(uint8_t mdc_gpio, uint8_t mdio_gpio)
+{
+    // setup SMI MDC pin
+    gpio_set_direction(mdc_gpio, GPIO_MODE_OUTPUT);
+    gpio_matrix_out(mdc_gpio, EMAC_MDC_O_IDX, 0, 0);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[mdc_gpio], PIN_FUNC_GPIO);
+    // setup SMI MDIO pin
+    gpio_set_direction(mdio_gpio, GPIO_MODE_INPUT_OUTPUT);
+    gpio_matrix_out(mdio_gpio, EMAC_MDO_O_IDX, 0, 0);
+    gpio_matrix_in(mdio_gpio, EMAC_MDI_I_IDX, 0);
+    PIN_FUNC_SELECT(GPIO_PIN_MUX_REG[mdio_gpio], PIN_FUNC_GPIO);
+
+    #ifndef RIOT_VERSION
+    _gpio_pin_usage[mdc_gpio]  = _EMAC;
+    _gpio_pin_usage[mdio_gpio] = _EMAC;
+    #endif
+}
+
+void phy_mii_enable_flow_ctrl(void)
+{
+    uint32_t data = esp_eth_smi_read(MII_AUTO_NEG_ADVERTISEMENT_REG);
+    data |= MII_ASM_DIR | MII_PAUSE;
+    esp_eth_smi_write(MII_AUTO_NEG_ADVERTISEMENT_REG, data);
+}
+
+bool phy_mii_check_link_status(void)
+{
+    if ((esp_eth_smi_read(MII_BASIC_MODE_STATUS_REG) & MII_LINK_STATUS)) {
+        ESP_LOGD(TAG, "phy_mii_check_link_status(UP)");
+        return true;
+    } else {
+        ESP_LOGD(TAG, "phy_mii_check_link_status(DOWN)");
+        return false;
+    }
+}
+
+bool phy_mii_get_partner_pause_enable(void)
+{
+    if((esp_eth_smi_read(MII_PHY_LINK_PARTNER_ABILITY_REG) & MII_PARTNER_PAUSE)) {
+        ESP_LOGD(TAG, "phy_mii_get_partner_pause_enable(TRUE)");
+        return true;
+    } else {
+        ESP_LOGD(TAG, "phy_mii_get_partner_pause_enable(FALSE)");
+        return false;
+    }
+}
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_lan8720.c b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_lan8720.c
new file mode 100644
index 0000000000000000000000000000000000000000..f38a6f3e819a7dc8bae0c039826cf213ed2fa5e5
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_lan8720.c
@@ -0,0 +1,154 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_eth.h"
+
+#include "eth_phy/phy_lan8720.h"
+#include "eth_phy/phy_reg.h"
+
+/* Value of MII_PHY_IDENTIFIER_REGs for Microchip LAN8720
+ * (Except for bottom 4 bits of ID2, used for model revision)
+ */
+#define LAN8720_PHY_ID1 0x0007
+#define LAN8720_PHY_ID2 0xc0f0
+#define LAN8720_PHY_ID2_MASK 0xFFF0
+
+/* LAN8720-specific registers */
+#define SW_STRAP_CONTROL_REG       (0x9)
+#define SW_STRAP_CONFIG_DONE               BIT(15)
+#define AUTO_MDIX_ENABLE                   BIT(14)
+#define AUTO_NEGOTIATION_ENABLE            BIT(13)
+#define AN_1                               BIT(12)
+#define AN_0                               BIT(11)
+#define LED_CFG                            BIT(10)
+#define RMII_ENHANCED_MODE                 BIT(9)
+
+#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
+
+#define PHY_SPECIAL_CONTROL_STATUS_REG    (0x1f)
+#define AUTO_NEGOTIATION_DONE              BIT(12)
+#define SPEED_DUPLEX_INDICATION_10T_HALF   0x04
+#define SPEED_DUPLEX_INDICATION_10T_FULL   0x14
+#define SPEED_DUPLEX_INDICATION_100T_HALF  0x08
+#define SPEED_DUPLEX_INDICATION_100T_FULL  0x18
+#define SPEED_INDICATION_100T              BIT(3)
+#define SPEED_INDICATION_10T               BIT(2)
+#define DUPLEX_INDICATION_FULL             BIT(4)
+
+static const char *TAG = "lan8720";
+
+void phy_lan8720_check_phy_init(void)
+{
+    phy_lan8720_dump_registers();
+
+    esp_eth_smi_wait_set(MII_BASIC_MODE_STATUS_REG, MII_AUTO_NEGOTIATION_COMPLETE, 0);
+    esp_eth_smi_wait_set(PHY_SPECIAL_CONTROL_STATUS_REG, AUTO_NEGOTIATION_DONE, 0);
+}
+
+eth_speed_mode_t phy_lan8720_get_speed_mode(void)
+{
+    if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & SPEED_INDICATION_100T) {
+        ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(100)");
+        return ETH_SPEED_MODE_100M;
+    } else {
+        ESP_LOGD(TAG, "phy_lan8720_get_speed_mode(10)");
+        return ETH_SPEED_MODE_10M;
+    }
+}
+
+eth_duplex_mode_t phy_lan8720_get_duplex_mode(void)
+{
+    if(esp_eth_smi_read(PHY_SPECIAL_CONTROL_STATUS_REG) & DUPLEX_INDICATION_FULL) {
+        ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(FULL)");
+        return ETH_MODE_FULLDUPLEX;
+    } else {
+        ESP_LOGD(TAG, "phy_lan8720_get_duplex_mode(HALF)");
+        return ETH_MODE_HALFDUPLEX;
+    }
+}
+
+void phy_lan8720_power_enable(bool enable)
+{
+    if (enable) {
+        esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
+        // TODO: only enable if config.flow_ctrl_enable == true
+        phy_mii_enable_flow_ctrl();
+    }
+}
+
+void phy_lan8720_init(void)
+{
+    ESP_LOGD(TAG, "phy_lan8720_init()");
+    phy_lan8720_dump_registers();
+
+    esp_eth_smi_write(MII_BASIC_MODE_CONTROL_REG, MII_SOFTWARE_RESET);
+
+    esp_err_t res1, res2;
+    do {
+        // Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically
+        res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, LAN8720_PHY_ID1, UINT16_MAX, 1000);
+        res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, LAN8720_PHY_ID2, LAN8720_PHY_ID2_MASK, 1000);
+    } while(res1 != ESP_OK || res2 != ESP_OK);
+
+    esp_eth_smi_write(SW_STRAP_CONTROL_REG,
+                      DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
+
+
+    ets_delay_us(300);
+
+    // TODO: only enable if config.flow_ctrl_enable == true
+    phy_mii_enable_flow_ctrl();
+}
+
+const eth_config_t phy_lan8720_default_ethernet_config = {
+    // By default, the PHY address is 0 or 1 based on PHYAD0
+    // pin. Can also be overriden in software. See datasheet
+    // for defaults.
+    .phy_addr = 0,
+    .mac_mode = ETH_MODE_RMII,
+    .clock_mode = ETH_CLOCK_GPIO0_IN,
+    //Only FULLDUPLEX mode support flow ctrl now!
+    .flow_ctrl_enable = true,
+    .phy_init = phy_lan8720_init,
+    .phy_check_init = phy_lan8720_check_phy_init,
+    .phy_power_enable = phy_lan8720_power_enable,
+    .phy_check_link = phy_mii_check_link_status,
+    .phy_get_speed_mode = phy_lan8720_get_speed_mode,
+    .phy_get_duplex_mode = phy_lan8720_get_duplex_mode,
+    .phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
+};
+
+void phy_lan8720_dump_registers(void)
+{
+    ESP_LOGD(TAG, "LAN8720 Registers:");
+    ESP_LOGD(TAG, "BCR    0x%04x", esp_eth_smi_read(0x0));
+    ESP_LOGD(TAG, "BSR    0x%04x", esp_eth_smi_read(0x1));
+    ESP_LOGD(TAG, "PHY1   0x%04x", esp_eth_smi_read(0x2));
+    ESP_LOGD(TAG, "PHY2   0x%04x", esp_eth_smi_read(0x3));
+    ESP_LOGD(TAG, "ANAR   0x%04x", esp_eth_smi_read(0x4));
+    ESP_LOGD(TAG, "ANLPAR 0x%04x", esp_eth_smi_read(0x5));
+    ESP_LOGD(TAG, "ANER   0x%04x", esp_eth_smi_read(0x6));
+    ESP_LOGD(TAG, "MCSR   0x%04x", esp_eth_smi_read(0x17));
+    ESP_LOGD(TAG, "SM     0x%04x", esp_eth_smi_read(0x18));
+    ESP_LOGD(TAG, "SECR   0x%04x", esp_eth_smi_read(0x26));
+    ESP_LOGD(TAG, "CSIR   0x%04x", esp_eth_smi_read(0x27));
+    ESP_LOGD(TAG, "ISR    0x%04x", esp_eth_smi_read(0x29));
+    ESP_LOGD(TAG, "IMR    0x%04x", esp_eth_smi_read(0x30));
+    ESP_LOGD(TAG, "PSCSR  0x%04x", esp_eth_smi_read(0x31));
+}
diff --git a/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_tlk110.c b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_tlk110.c
new file mode 100644
index 0000000000000000000000000000000000000000..665dd8903ae2f27622625dc38527b6a475109000
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/ethernet/eth_phy/phy_tlk110.c
@@ -0,0 +1,178 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#define ENABLE_DEBUG (0)
+#include "debug.h"
+
+#include "esp_attr.h"
+#include "esp_log.h"
+#include "esp_eth.h"
+
+#include "eth_phy/phy_tlk110.h"
+#include "eth_phy/phy_reg.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+/* Value of MII_PHY_IDENTIFIER_REG for TI TLK110,
+   Excluding bottom 4 bytes of ID2, used for model revision
+ */
+#define TLK110_PHY_ID1 0x2000
+#define TLK110_PHY_ID2 0xa210
+#define TLK110_PHY_ID2_MASK 0xFFF0
+
+/* TLK110-specific registers */
+#define SW_STRAP_CONTROL_REG            (0x9)
+#define SW_STRAP_CONFIG_DONE               BIT(15)
+#define AUTO_MDIX_ENABLE                   BIT(14)
+#define AUTO_NEGOTIATION_ENABLE            BIT(13)
+#define AN_1                               BIT(12)
+#define AN_0                               BIT(11)
+#define LED_CFG                            BIT(10)
+#define RMII_ENHANCED_MODE                 BIT(9)
+
+#define DEFAULT_STRAP_CONFIG (AUTO_MDIX_ENABLE|AUTO_NEGOTIATION_ENABLE|AN_1|AN_0|LED_CFG)
+
+#define PHY_STATUS_REG                  (0x10)
+#define AUTO_NEGOTIATION_STATUS             BIT(4)
+#define DUPLEX_STATUS                      BIT(2)
+#define SPEED_STATUS                       BIT(1)
+
+#define CABLE_DIAGNOSTIC_CONTROL_REG    (0x1e)
+#define DIAGNOSTIC_DONE                    BIT(1)
+
+#define PHY_RESET_CONTROL_REG           (0x1f)
+#define SOFTWARE_RESET                     BIT(15)
+
+static const char *TAG = "tlk110";
+
+void phy_tlk110_check_phy_init(void)
+{
+    phy_tlk110_dump_registers();
+
+    esp_eth_smi_wait_set(MII_BASIC_MODE_STATUS_REG, MII_AUTO_NEGOTIATION_COMPLETE, 0);
+    esp_eth_smi_wait_set(PHY_STATUS_REG, AUTO_NEGOTIATION_STATUS, 0);
+    esp_eth_smi_wait_set(CABLE_DIAGNOSTIC_CONTROL_REG, DIAGNOSTIC_DONE, 0);
+}
+
+eth_speed_mode_t phy_tlk110_get_speed_mode(void)
+{
+    if((esp_eth_smi_read(PHY_STATUS_REG) & SPEED_STATUS ) != SPEED_STATUS) {
+        ESP_LOGD(TAG, "phy_tlk110_get_speed_mode(100)");
+        return ETH_SPEED_MODE_100M;
+    } else {
+        ESP_LOGD(TAG, "phy_tlk110_get_speed_mode(10)");
+        return ETH_SPEED_MODE_10M;
+    }
+}
+
+eth_duplex_mode_t phy_tlk110_get_duplex_mode(void)
+{
+    if((esp_eth_smi_read(PHY_STATUS_REG) & DUPLEX_STATUS ) == DUPLEX_STATUS) {
+        ESP_LOGD(TAG, "phy_tlk110_get_duplex_mode(FULL)");
+        return ETH_MODE_FULLDUPLEX;
+    } else {
+        ESP_LOGD(TAG, "phy_tlk110_get_duplex_mode(HALF)");
+        return ETH_MODE_HALFDUPLEX;
+    }
+}
+
+void phy_tlk110_power_enable(bool enable)
+{
+    if (enable) {
+        esp_eth_smi_write(SW_STRAP_CONTROL_REG, DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
+
+        // TODO: only do this if config.flow_ctrl_enable == true
+        phy_mii_enable_flow_ctrl();
+    }
+}
+
+void phy_tlk110_init(void)
+{
+    ESP_LOGD(TAG, "phy_tlk110_init()");
+    phy_tlk110_dump_registers();
+
+    esp_eth_smi_write(PHY_RESET_CONTROL_REG, SOFTWARE_RESET);
+
+    esp_err_t res1, res2;
+    do {
+        // Call esp_eth_smi_wait_value() with a timeout so it prints an error periodically
+        res1 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_1_REG, TLK110_PHY_ID1, UINT16_MAX, 1000);
+        res2 = esp_eth_smi_wait_value(MII_PHY_IDENTIFIER_2_REG, TLK110_PHY_ID2, TLK110_PHY_ID2_MASK, 1000);
+    } while(res1 != ESP_OK || res2 != ESP_OK);
+
+    esp_eth_smi_write(SW_STRAP_CONTROL_REG,
+                      DEFAULT_STRAP_CONFIG | SW_STRAP_CONFIG_DONE);
+
+    ets_delay_us(300);
+
+    // TODO: only do this if config.flow_ctrl_enable == true
+    phy_mii_enable_flow_ctrl();
+}
+
+const eth_config_t phy_tlk110_default_ethernet_config = {
+    // PHY address configured by PHYADx pins. Default value of 0x1
+    // is used if all pins are unconnected.
+    .phy_addr = 0x1,
+    .mac_mode = ETH_MODE_RMII,
+    .clock_mode = ETH_CLOCK_GPIO0_IN,
+    //Only FULLDUPLEX mode support flow ctrl now!
+    .flow_ctrl_enable = true,
+    .phy_init = phy_tlk110_init,
+    .phy_check_init = phy_tlk110_check_phy_init,
+    .phy_check_link = phy_mii_check_link_status,
+    .phy_get_speed_mode = phy_tlk110_get_speed_mode,
+    .phy_get_duplex_mode = phy_tlk110_get_duplex_mode,
+    .phy_get_partner_pause_enable = phy_mii_get_partner_pause_enable,
+    .phy_power_enable = phy_tlk110_power_enable,
+};
+
+void phy_tlk110_dump_registers(void)
+{
+    ESP_LOGD(TAG, "TLK110 Registers:");
+    ESP_LOGD(TAG, "BMCR     0x%04x", esp_eth_smi_read(0x0));
+    ESP_LOGD(TAG, "BMSR     0x%04x", esp_eth_smi_read(0x1));
+    ESP_LOGD(TAG, "PHYIDR1  0x%04x", esp_eth_smi_read(0x2));
+    ESP_LOGD(TAG, "PHYIDR2  0x%04x", esp_eth_smi_read(0x3));
+    ESP_LOGD(TAG, "ANAR     0x%04x", esp_eth_smi_read(0x4));
+    ESP_LOGD(TAG, "ANLPAR   0x%04x", esp_eth_smi_read(0x5));
+    ESP_LOGD(TAG, "ANER     0x%04x", esp_eth_smi_read(0x6));
+    ESP_LOGD(TAG, "ANNPTR   0x%04x", esp_eth_smi_read(0x7));
+    ESP_LOGD(TAG, "ANLNPTR  0x%04x", esp_eth_smi_read(0x8));
+    ESP_LOGD(TAG, "SWSCR1   0x%04x", esp_eth_smi_read(0x9));
+    ESP_LOGD(TAG, "SWSCR2   0x%04x", esp_eth_smi_read(0xa));
+    ESP_LOGD(TAG, "SWSCR3   0x%04x", esp_eth_smi_read(0xb));
+    ESP_LOGD(TAG, "REGCR    0x%04x", esp_eth_smi_read(0xd));
+    ESP_LOGD(TAG, "ADDAR    0x%04x", esp_eth_smi_read(0xe));
+    ESP_LOGD(TAG, "PHYSTS   0x%04x", esp_eth_smi_read(0x10));
+    ESP_LOGD(TAG, "PHYSCR   0x%04x", esp_eth_smi_read(0x11));
+    ESP_LOGD(TAG, "MISR1    0x%04x", esp_eth_smi_read(0x12));
+    ESP_LOGD(TAG, "MISR2    0x%04x", esp_eth_smi_read(0x13));
+    ESP_LOGD(TAG, "FCSCR    0x%04x", esp_eth_smi_read(0x14));
+    ESP_LOGD(TAG, "RECR     0x%04x", esp_eth_smi_read(0x15));
+    ESP_LOGD(TAG, "BISCR    0x%04x", esp_eth_smi_read(0x16));
+    ESP_LOGD(TAG, "RBR      0x%04x", esp_eth_smi_read(0x17));
+    ESP_LOGD(TAG, "LEDCR    0x%04x", esp_eth_smi_read(0x18));
+    ESP_LOGD(TAG, "PHYCR    0x%04x", esp_eth_smi_read(0x19));
+    ESP_LOGD(TAG, "10BTSCR  0x%04x", esp_eth_smi_read(0x1a));
+    ESP_LOGD(TAG, "BICSR1   0x%04x", esp_eth_smi_read(0x1b));
+    ESP_LOGD(TAG, "BICSR2   0x%04x", esp_eth_smi_read(0x1c));
+    ESP_LOGD(TAG, "CDCR     0x%04x", esp_eth_smi_read(0x1e));
+    ESP_LOGD(TAG, "TRXCPSR  0x%04x", esp_eth_smi_read(0x42));
+    ESP_LOGD(TAG, "PWRBOCR  0x%04x", esp_eth_smi_read(0xae));
+    ESP_LOGD(TAG, "VRCR     0x%04x", esp_eth_smi_read(0xD0));
+    ESP_LOGD(TAG, "ALCDRR1  0x%04x", esp_eth_smi_read(0x155));
+    ESP_LOGD(TAG, "CDSCR1   0x%04x", esp_eth_smi_read(0x170));
+    ESP_LOGD(TAG, "CDSCR2   0x%04x", esp_eth_smi_read(0x171));
+}
diff --git a/cpu/esp32/vendor/esp-idf/heap/Makefile b/cpu/esp32/vendor/esp-idf/heap/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..91f915057be252c986827339d1b37128ea31b59d
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/heap/Makefile
@@ -0,0 +1,6 @@
+MODULE=esp_idf_heap
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(ESP32_SDK_DIR)/components/heap
diff --git a/cpu/esp32/vendor/esp-idf/heap/heap_caps.c b/cpu/esp32/vendor/esp-idf/heap/heap_caps.c
new file mode 100644
index 0000000000000000000000000000000000000000..a242713a57cb4854084caf3ed6ef67acb4d46702
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/heap/heap_caps.c
@@ -0,0 +1,437 @@
+// 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 <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+#include "multi_heap.h"
+#include "esp_log.h"
+#include "heap_private.h"
+
+/*
+This file, combined with a region allocator that supports multiple heaps, solves the problem that the ESP32 has RAM
+that's slightly heterogeneous. Some RAM can be byte-accessed, some allows only 32-bit accesses, some can execute memory,
+some can be remapped by the MMU to only be accessed by a certain PID etc. In order to allow the most flexible memory
+allocation possible, this code makes it possible to request memory that has certain capabilities. The code will then use
+its knowledge of how the memory is configured along with a priority scheme to allocate that memory in the most sane way
+possible. This should optimize the amount of RAM accessible to the code without hardwiring addresses.
+*/
+
+/*
+  This takes a memory chunk in a region that can be addressed as both DRAM as well as IRAM. It will convert it to
+  IRAM in such a way that it can be later freed. It assumes both the address as wel as the length to be word-aligned.
+  It returns a region that's 1 word smaller than the region given because it stores the original Dram address there.
+
+  In theory, we can also make this work by prepending a struct that looks similar to the block link struct used by the
+  heap allocator itself, which will allow inspection tools relying on any block returned from any sort of malloc to
+  have such a block in front of it, work. We may do this later, if/when there is demand for it. For now, a simple
+  pointer is used.
+*/
+IRAM_ATTR static void *dram_alloc_to_iram_addr(void *addr, size_t len)
+{
+    uint32_t dstart = (int)addr; //First word
+    uint32_t dend = ((int)addr) + len - 4; //Last word
+    assert(dstart >= SOC_DIRAM_DRAM_LOW);
+    assert(dend <= SOC_DIRAM_DRAM_HIGH);
+    assert((dstart & 3) == 0);
+    assert((dend & 3) == 0);
+    uint32_t istart = SOC_DIRAM_IRAM_LOW + (SOC_DIRAM_DRAM_HIGH - dend);
+    uint32_t *iptr = (uint32_t *)istart;
+    *iptr = dstart;
+    return (void *)(iptr + 1);
+}
+
+bool heap_caps_match(const heap_t *heap, uint32_t caps)
+{
+    return heap->heap != NULL && ((get_all_caps(heap) & caps) == caps);
+}
+
+/*
+Routine to allocate a bit of memory with certain capabilities. caps is a bitfield of MALLOC_CAP_* bits.
+*/
+IRAM_ATTR void *heap_caps_malloc( size_t size, uint32_t caps )
+{
+    void *ret = NULL;
+
+    if (caps & MALLOC_CAP_EXEC) {
+        //MALLOC_CAP_EXEC forces an alloc from IRAM. There is a region which has both this as well as the following
+        //caps, but the following caps are not possible for IRAM.  Thus, the combination is impossible and we return
+        //NULL directly, even although our heap capabilities (based on soc_memory_tags & soc_memory_regions) would
+        //indicate there is a tag for this.
+        if ((caps & MALLOC_CAP_8BIT) || (caps & MALLOC_CAP_DMA)) {
+            return NULL;
+        }
+        //If any, EXEC memory should be 32-bit aligned, so round up to the next multiple of 4.
+        size = (size + 3) & (~3);
+    }
+    for (int prio = 0; prio < SOC_MEMORY_TYPE_NO_PRIOS; prio++) {
+        //Iterate over heaps and check capabilities at this priority
+        heap_t *heap;
+        SLIST_FOREACH(heap, &registered_heaps, next) {
+            if (heap->heap == NULL) {
+                continue;
+            }
+            if ((heap->caps[prio] & caps) != 0) {
+                //Heap has at least one of the caps requested. If caps has other bits set that this prio
+                //doesn't cover, see if they're available in other prios.
+                if ((get_all_caps(heap) & caps) == caps) {
+                    //This heap can satisfy all the requested capabilities. See if we can grab some memory using it.
+                    if ((caps & MALLOC_CAP_EXEC) && heap->start >= SOC_DIRAM_DRAM_LOW && heap->start < SOC_DIRAM_DRAM_HIGH) {
+                        //This is special, insofar that what we're going to get back is a DRAM address. If so,
+                        //we need to 'invert' it (lowest address in DRAM == highest address in IRAM and vice-versa) and
+                        //add a pointer to the DRAM equivalent before the address we're going to return.
+                        ret = multi_heap_malloc(heap->heap, size + 4);
+                        if (ret != NULL) {
+                            return dram_alloc_to_iram_addr(ret, size + 4);
+                        }
+                    } else {
+                        //Just try to alloc, nothing special.
+                        ret = multi_heap_malloc(heap->heap, size);
+                        if (ret != NULL) {
+                            return ret;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    //Nothing usable found.
+    return NULL;
+}
+
+
+#define MALLOC_DISABLE_EXTERNAL_ALLOCS -1
+//Dual-use: -1 (=MALLOC_DISABLE_EXTERNAL_ALLOCS) disables allocations in external memory, >=0 sets the limit for allocations preferring internal memory.
+static int malloc_alwaysinternal_limit=MALLOC_DISABLE_EXTERNAL_ALLOCS;
+
+void heap_caps_malloc_extmem_enable(size_t limit)
+{
+    malloc_alwaysinternal_limit=limit;
+}
+
+/*
+ Default memory allocation implementation. Should return standard 8-bit memory. malloc() essentially resolves to this function.
+*/
+IRAM_ATTR void *heap_caps_malloc_default( size_t size )
+{
+    if (malloc_alwaysinternal_limit==MALLOC_DISABLE_EXTERNAL_ALLOCS) {
+        return heap_caps_malloc( size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL);
+    } else {
+        void *r;
+        if ((int)size <= malloc_alwaysinternal_limit) {
+            r=heap_caps_malloc( size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL );
+        } else {
+            r=heap_caps_malloc( size, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM );
+        }
+        if (r==NULL) {
+            //try again while being less picky
+            r=heap_caps_malloc( size, MALLOC_CAP_DEFAULT );
+        }
+        return r;
+    }
+}
+
+/*
+ Same for realloc()
+ Note: keep the logic in here the same as in heap_caps_malloc_default (or merge the two as soon as this gets more complex...)
+ */
+IRAM_ATTR void *heap_caps_realloc_default( void *ptr, size_t size )
+{
+    if (malloc_alwaysinternal_limit==MALLOC_DISABLE_EXTERNAL_ALLOCS) {
+        return heap_caps_realloc( ptr, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL );
+    } else {
+        void *r;
+        if ((int)size <= malloc_alwaysinternal_limit) {
+            r=heap_caps_realloc( ptr, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL );
+        } else {
+            r=heap_caps_realloc( ptr, size, MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM );
+        }
+        if (r==NULL && size>0) {
+            //We needed to allocate memory, but we didn't. Try again while being less picky.
+            r=heap_caps_realloc( ptr, size, MALLOC_CAP_DEFAULT );
+        }
+        return r;
+    }
+}
+
+/*
+ Memory allocation as preference in decreasing order.
+ */
+IRAM_ATTR void *heap_caps_malloc_prefer( size_t size, size_t num, ... )
+{
+    va_list argp;
+    va_start( argp, num );
+    void *r = NULL;
+    while (num--) {
+        uint32_t caps = va_arg( argp, uint32_t );
+        r = heap_caps_malloc( size, caps );
+        if (r != NULL) {
+            break;
+        }
+    }
+    va_end( argp );
+    return r;
+}
+
+/*
+ Memory reallocation as preference in decreasing order.
+ */
+IRAM_ATTR void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... )
+{
+    va_list argp;
+    va_start( argp, num );
+    void *r = NULL;
+    while (num--) {
+        uint32_t caps = va_arg( argp, uint32_t );
+        r = heap_caps_realloc( ptr, size, caps );
+        if (r != NULL || size == 0) {
+            break;
+        }
+    }
+    va_end( argp );
+    return r;
+}
+
+/*
+ Memory callocation as preference in decreasing order.
+ */
+IRAM_ATTR void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... )
+{
+    va_list argp;
+    va_start( argp, num );
+    void *r = NULL;
+    while (num--) {
+        uint32_t caps = va_arg( argp, uint32_t );
+        r = heap_caps_calloc( n, size, caps );
+        if (r != NULL) break;
+    }
+    va_end( argp );
+    return r;
+}
+
+/* Find the heap which belongs to ptr, or return NULL if it's
+   not in any heap.
+
+   (This confirms if ptr is inside the heap's region, doesn't confirm if 'ptr'
+   is an allocated block or is some other random address inside the heap.)
+*/
+IRAM_ATTR static heap_t *find_containing_heap(void *ptr )
+{
+    intptr_t p = (intptr_t)ptr;
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap->heap != NULL && p >= heap->start && p < heap->end) {
+            return heap;
+        }
+    }
+    return NULL;
+}
+
+IRAM_ATTR void heap_caps_free( void *ptr)
+{
+    intptr_t p = (intptr_t)ptr;
+
+    if (ptr == NULL) {
+        return;
+    }
+
+    if ((p >= SOC_DIRAM_IRAM_LOW) && (p <= SOC_DIRAM_IRAM_HIGH)) {
+        //Memory allocated here is actually allocated in the DRAM alias region and
+        //cannot be de-allocated as usual. dram_alloc_to_iram_addr stores a pointer to
+        //the equivalent DRAM address, though; free that.
+        uint32_t *dramAddrPtr = (uint32_t *)ptr;
+        ptr = (void *)dramAddrPtr[-1];
+    }
+
+    heap_t *heap = find_containing_heap(ptr);
+    assert(heap != NULL && "free() target pointer is outside heap areas");
+    multi_heap_free(heap->heap, ptr);
+}
+
+IRAM_ATTR void *heap_caps_realloc( void *ptr, size_t size, int caps)
+{
+    if (ptr == NULL) {
+        return heap_caps_malloc(size, caps);
+    }
+
+    if (size == 0) {
+        heap_caps_free(ptr);
+        return NULL;
+    }
+
+    heap_t *heap = find_containing_heap(ptr);
+
+    assert(heap != NULL && "realloc() pointer is outside heap areas");
+
+    // are the existing heap's capabilities compatible with the
+    // requested ones?
+    bool compatible_caps = (caps & (int)get_all_caps(heap)) == caps;
+
+    if (compatible_caps) {
+        // try to reallocate this memory within the same heap
+        // (which will resize the block if it can)
+        void *r = multi_heap_realloc(heap->heap, ptr, size);
+        if (r != NULL) {
+            return r;
+        }
+    }
+
+    // if we couldn't do that, try to see if we can reallocate
+    // in a different heap with requested capabilities.
+    void *new_p = heap_caps_malloc(size, caps);
+    if (new_p != NULL) {
+        size_t old_size = multi_heap_get_allocated_size(heap->heap, ptr);
+        assert(old_size > 0);
+        memcpy(new_p, ptr, MIN(size, old_size));
+        heap_caps_free(ptr);
+        return new_p;
+    }
+    return NULL;
+}
+
+IRAM_ATTR void *heap_caps_calloc( size_t n, size_t size, uint32_t caps)
+{
+    void *r;
+    r = heap_caps_malloc(n*size, caps);
+    if (r != NULL) {
+        bzero(r, n*size);
+    }
+    return r;
+}
+
+size_t heap_caps_get_free_size( uint32_t caps )
+{
+    size_t ret = 0;
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap_caps_match(heap, caps)) {
+            ret += multi_heap_free_size(heap->heap);
+        }
+    }
+    return ret;
+}
+
+size_t heap_caps_get_minimum_free_size( uint32_t caps )
+{
+    size_t ret = 0;
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap_caps_match(heap, caps)) {
+            ret += multi_heap_minimum_free_size(heap->heap);
+        }
+    }
+    return ret;
+}
+
+size_t heap_caps_get_largest_free_block( uint32_t caps )
+{
+    multi_heap_info_t info;
+    heap_caps_get_info(&info, caps);
+    return info.largest_free_block;
+}
+
+void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps )
+{
+    bzero(info, sizeof(multi_heap_info_t));
+
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap_caps_match(heap, caps)) {
+            multi_heap_info_t hinfo;
+            multi_heap_get_info(heap->heap, &hinfo);
+
+            info->total_free_bytes += hinfo.total_free_bytes;
+            info->total_allocated_bytes += hinfo.total_allocated_bytes;
+            info->largest_free_block = MAX(info->largest_free_block,
+                                           hinfo.largest_free_block);
+            info->minimum_free_bytes += hinfo.minimum_free_bytes;
+            info->allocated_blocks += hinfo.allocated_blocks;
+            info->free_blocks += hinfo.free_blocks;
+            info->total_blocks += hinfo.total_blocks;
+        }
+    }
+}
+
+void heap_caps_print_heap_info( uint32_t caps )
+{
+    multi_heap_info_t info;
+    printf("Heap summary for capabilities 0x%08X:\n", caps);
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap_caps_match(heap, caps)) {
+            multi_heap_get_info(heap->heap, &info);
+
+            printf("  At 0x%08x len %d free %d allocated %d min_free %d\n",
+                   heap->start, heap->end - heap->start, info.total_free_bytes, info.total_allocated_bytes, info.minimum_free_bytes);
+            printf("    largest_free_block %d alloc_blocks %d free_blocks %d total_blocks %d\n",
+                   info.largest_free_block, info.allocated_blocks,
+                   info.free_blocks, info.total_blocks);
+        }
+    }
+    printf("  Totals:\n");
+    heap_caps_get_info(&info, caps);
+
+    printf("    free %d allocated %d min_free %d largest_free_block %d\n", info.total_free_bytes, info.total_allocated_bytes, info.minimum_free_bytes, info.largest_free_block);
+}
+
+bool heap_caps_check_integrity(uint32_t caps, bool print_errors)
+{
+    bool all_heaps = caps & MALLOC_CAP_INVALID;
+    bool valid = true;
+
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap->heap != NULL
+            && (all_heaps || (get_all_caps(heap) & caps) == caps)) {
+            valid = multi_heap_check(heap->heap, print_errors) && valid;
+        }
+    }
+
+    return valid;
+}
+
+bool heap_caps_check_integrity_all(bool print_errors)
+{
+    return heap_caps_check_integrity(MALLOC_CAP_INVALID, print_errors);
+}
+
+bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors)
+{
+    heap_t *heap = find_containing_heap((void *)addr);
+    if (heap == NULL) {
+        return false;
+    }
+    return multi_heap_check(heap->heap, print_errors);
+}
+
+void heap_caps_dump(uint32_t caps)
+{
+    bool all_heaps = caps & MALLOC_CAP_INVALID;
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if (heap->heap != NULL
+            && (all_heaps || (get_all_caps(heap) & caps) == caps)) {
+            multi_heap_dump(heap->heap);
+        }
+    }
+}
+
+void heap_caps_dump_all(void)
+{
+    heap_caps_dump(MALLOC_CAP_INVALID);
+}
diff --git a/cpu/esp32/vendor/esp-idf/heap/heap_caps_init.c b/cpu/esp32/vendor/esp-idf/heap/heap_caps_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..d6c3c034051839293cc847469bfd3ba41d997bf7
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/heap/heap_caps_init.c
@@ -0,0 +1,294 @@
+// 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 "heap_private.h"
+#include <assert.h>
+#include <string.h>
+#include <sys/lock.h>
+
+#include "esp_log.h"
+#include "multi_heap.h"
+#include "esp_heap_caps_init.h"
+#include "soc/soc_memory_layout.h"
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+static const char *TAG = "heap_init";
+
+/* Linked-list of registered heaps */
+struct registered_heap_ll registered_heaps;
+
+static void register_heap(heap_t *region)
+{
+    region->heap = multi_heap_register((void *)region->start, region->end - region->start);
+    if (region->heap != NULL) {
+        ESP_EARLY_LOGD(TAG, "New heap initialised at %p", region->heap);
+    }
+}
+
+void heap_caps_enable_nonos_stack_heaps(void)
+{
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        // Assume any not-yet-registered heap is
+        // a nonos-stack heap
+        if (heap->heap == NULL) {
+            register_heap(heap);
+            if (heap->heap != NULL) {
+                multi_heap_set_lock(heap->heap, &heap->heap_mux);
+            }
+        }
+    }
+}
+
+//Modify regions array to disable the given range of memory.
+static void disable_mem_region(soc_memory_region_t *regions, intptr_t from, intptr_t to)
+{
+    //Align from and to on word boundaries
+    from = from & ~3;
+    to = (to + 3) & ~3;
+
+    for (unsigned i = 0; i < soc_memory_region_count; i++) {
+        soc_memory_region_t *region = &regions[i];
+
+        intptr_t regStart = region->start;
+        intptr_t regEnd = region->start + region->size;
+        if (regStart >= from && regEnd <= to) {
+            //Entire region falls in the range. Disable entirely.
+            regions[i].type = -1;
+        } else if (regStart >= from && regEnd > to && regStart < to) {
+            //Start of the region falls in the range. Modify address/len.
+            intptr_t overlap = to - regStart;
+            region->start += overlap;
+            region->size -= overlap;
+            if (region->iram_address) {
+                region->iram_address += overlap;
+            }
+        } else if (regStart < from && regEnd > from && regEnd <= to) {
+            //End of the region falls in the range. Modify length.
+            region->size -= regEnd - from;
+        } else if (regStart < from && regEnd > to) {
+            //Range punches a hole in the region! We do not support this.
+            ESP_EARLY_LOGE(TAG, "region %d: hole punching is not supported!", i);
+            regions->type = -1; //Just disable memory region. That'll teach them!
+        }
+    }
+}
+
+/*
+Warning: These variables are assumed to have the start and end of the data and iram
+area used statically by the program, respectively. These variables are defined in the ld
+file.
+*/
+extern int _data_start, _heap_start, _init_start, _iram_text_end;
+
+/*
+Initialize the heap allocator. We pass it a bunch of region descriptors, but we need to modify those first to accommodate for
+the data as loaded by the bootloader.
+ToDo: The regions are different when stuff like trace memory, BT, ... is used. Modify the regions struct on the fly for this.
+Same with loading of apps. Same with using SPI RAM.
+*/
+void heap_caps_init(void)
+{
+    /* Copy the soc_memory_regions data to the stack, so we can
+       manipulate it. */
+    soc_memory_region_t regions[soc_memory_region_count];
+    memcpy(regions, soc_memory_regions, sizeof(soc_memory_region_t)*soc_memory_region_count);
+
+    //Disable the bits of memory where this code is loaded.
+    disable_mem_region(regions, (intptr_t)&_data_start, (intptr_t)&_heap_start);           //DRAM used by bss/data static variables
+    disable_mem_region(regions, (intptr_t)&_init_start, (intptr_t)&_iram_text_end);        //IRAM used by code
+
+    // Disable all regions reserved on this SoC
+    for (unsigned i = 0; i < soc_reserved_region_count; i++) {
+        disable_mem_region(regions, soc_reserved_regions[i].start,
+                           soc_reserved_regions[i].end);
+    }
+
+    //The heap allocator will treat every region given to it as separate. In order to get bigger ranges of contiguous memory,
+    //it's useful to coalesce adjacent regions that have the same type.
+
+    for (unsigned i = 1; i < soc_memory_region_count; i++) {
+        soc_memory_region_t *a = &regions[i - 1];
+        soc_memory_region_t *b = &regions[i];
+        if (b->start == (intptr_t)(a->start + a->size) && b->type == a->type ) {
+            a->type = -1;
+            b->start = a->start;
+            b->size += a->size;
+        }
+    }
+
+    /* Count the heaps left after merging */
+    size_t num_heaps = 0;
+    for (unsigned i = 0; i < soc_memory_region_count; i++) {
+        if (regions[i].type != 0xffffffff) {
+            num_heaps++;
+        }
+    }
+
+    /* Start by allocating the registered heap data on the stack.
+
+       Once we have a heap to copy it to, we will copy it to a heap buffer.
+    */
+    heap_t temp_heaps[num_heaps];
+    size_t heap_idx = 0;
+
+    ESP_EARLY_LOGI(TAG, "Initializing. RAM available for dynamic allocation:");
+    for (unsigned i = 0; i < soc_memory_region_count; i++) {
+        soc_memory_region_t *region = &regions[i];
+        const soc_memory_type_desc_t *type = &soc_memory_types[region->type];
+        heap_t *heap = &temp_heaps[heap_idx];
+        if (region->type == 0xffffffff) {
+            continue;
+        }
+        heap_idx++;
+        assert(heap_idx <= num_heaps);
+
+        memcpy(heap->caps, type->caps, sizeof(heap->caps));
+        heap->start = region->start;
+        heap->end = region->start + region->size;
+        vPortCPUInitializeMutex(&heap->heap_mux);
+        if (type->startup_stack) {
+            /* Will be registered when OS scheduler starts */
+            heap->heap = NULL;
+        } else {
+            register_heap(heap);
+        }
+        SLIST_NEXT(heap, next) = NULL;
+
+        ESP_EARLY_LOGI(TAG, "At %08X len %08X (%d KiB): %s",
+                       region->start, region->size, region->size / 1024, type->name);
+    }
+
+    assert(heap_idx == num_heaps);
+
+    /* Allocate the permanent heap data that we'll use as a linked list at runtime.
+
+       Allocate this part of data contiguously, even though it's a linked list... */
+    assert(SLIST_EMPTY(&registered_heaps));
+
+    heap_t *heaps_array = NULL;
+    for (unsigned i = 0; i < num_heaps; i++) {
+        if (heap_caps_match(&temp_heaps[i], MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL)) {
+            /* use the first DRAM heap which can fit the data */
+            heaps_array = multi_heap_malloc(temp_heaps[i].heap, sizeof(heap_t) * num_heaps);
+            if (heaps_array != NULL) {
+                break;
+            }
+        }
+    }
+    assert(heaps_array != NULL); /* if NULL, there's not enough free startup heap space */
+
+    memcpy(heaps_array, temp_heaps, sizeof(heap_t)*num_heaps);
+
+    /* Iterate the heaps and set their locks, also add them to the linked list. */
+    for (unsigned i = 0; i < num_heaps; i++) {
+        if (heaps_array[i].heap != NULL) {
+            multi_heap_set_lock(heaps_array[i].heap, &heaps_array[i].heap_mux);
+        }
+        if (i == 0) {
+            SLIST_INSERT_HEAD(&registered_heaps, &heaps_array[0], next);
+        } else {
+            SLIST_INSERT_AFTER(&heaps_array[i-1], &heaps_array[i], next);
+        }
+    }
+}
+
+esp_err_t heap_caps_add_region(intptr_t start, intptr_t end)
+{
+    if (start == 0) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    for (unsigned i = 0; i < soc_memory_region_count; i++) {
+        const soc_memory_region_t *region = &soc_memory_regions[i];
+        // Test requested start only as 'end' may be in a different region entry, assume 'end' has same caps
+        if (region->start <= start && (intptr_t)(region->start + region->size) > start) {
+            const uint32_t *caps = soc_memory_types[region->type].caps;
+            return heap_caps_add_region_with_caps(caps, start, end);
+        }
+    }
+
+    return ESP_ERR_NOT_FOUND;
+}
+
+esp_err_t heap_caps_add_region_with_caps(const uint32_t caps[], intptr_t start, intptr_t end)
+{
+    esp_err_t err = ESP_FAIL;
+    if (caps == NULL || start == 0 || end == 0 || end <= start) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    //Check if region overlaps the start and/or end of an existing region. If so, the
+    //region is invalid (or maybe added twice)
+    /*
+     *  assume that in on region, start must be less than end (cannot equal to) !!
+     *  Specially, the 4th scenario can be allowed. For example, allocate memory from heap,
+     *  then change the capability and call this function to create a new region for special
+     *  application.
+     *  In the following chart, 'start = start' and 'end = end' is contained in 3rd scenario.
+     *  This all equal scenario is incorrect because the same region cannot be add twice. For example,
+     *  add the .bss memory to region twice, if not do the check, it will cause exception.
+     *
+     *  the existing heap region                                  s(tart)                e(nd)
+     *                                                            |----------------------|
+     *  1.add region  [Correct]   (s1<s && e1<=s)           |-----|
+     *  2.add region  [Incorrect] (s2<=s && s<e2<=e)        |---------------|
+     *  3.add region  [Incorrect] (s3<=s && e<e3)           |-------------------------------------|
+     *  4 add region  [Correct]   (s<s4<e && s<e4<=e)                  |-------|
+     *  5.add region  [Incorrect] (s<s5<e && e<e5)                     |----------------------------|
+     *  6.add region  [Correct]   (e<=s6 && e<e6)                                        |----|
+     */
+
+    heap_t *heap;
+    SLIST_FOREACH(heap, &registered_heaps, next) {
+        if ((start <= heap->start && end > heap->start)
+                || (start < heap->end && end > heap->end)) {
+            return ESP_FAIL;
+        }
+    }
+
+    heap_t *p_new = malloc(sizeof(heap_t));
+    if (p_new == NULL) {
+        err = ESP_ERR_NO_MEM;
+        goto done;
+    }
+    memcpy(p_new->caps, caps, sizeof(p_new->caps));
+    p_new->start = start;
+    p_new->end = end;
+    vPortCPUInitializeMutex(&p_new->heap_mux);
+    p_new->heap = multi_heap_register((void *)start, end - start);
+    SLIST_NEXT(p_new, next) = NULL;
+    if (p_new->heap == NULL) {
+        err = ESP_FAIL;
+        goto done;
+    }
+    multi_heap_set_lock(p_new->heap, &p_new->heap_mux);
+
+    /* (This insertion is atomic to registered_heaps, so
+       we don't need to worry about thread safety for readers,
+       only for writers. */
+    static _lock_t registered_heaps_write_lock;
+    _lock_acquire(&registered_heaps_write_lock);
+    SLIST_INSERT_HEAD(&registered_heaps, p_new, next);
+    _lock_release(&registered_heaps_write_lock);
+
+    err = ESP_OK;
+
+ done:
+    if (err != ESP_OK) {
+        free(p_new);
+    }
+    return err;
+}
diff --git a/cpu/esp32/vendor/esp-idf/heap/heap_trace.c b/cpu/esp32/vendor/esp-idf/heap/heap_trace.c
new file mode 100644
index 0000000000000000000000000000000000000000..de703f5f4c091b4a3fdf3a6fe962fc87f5b9ddf6
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/heap/heap_trace.c
@@ -0,0 +1,438 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#include <string.h>
+#include <sys/param.h>
+#include <sdk_conf.h>
+
+#define HEAP_TRACE_SRCFILE /* don't warn on inclusion here */
+#include "esp_heap_trace.h"
+#undef HEAP_TRACE_SRCFILE
+
+#include "esp_heap_caps.h"
+#include "esp_attr.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "soc/soc_memory_layout.h"
+#include "xtensa/hal.h"
+
+#include "heap_private.h"
+
+#define STACK_DEPTH CONFIG_HEAP_TRACING_STACK_DEPTH
+
+static portMUX_TYPE trace_mux = portMUX_INITIALIZER_UNLOCKED;
+static bool tracing;
+static heap_trace_mode_t mode;
+
+/* Buffer used for records, starting at offset 0
+*/
+static heap_trace_record_t *buffer;
+static size_t total_records;
+
+/* Count of entries logged in the buffer.
+
+   Maximum total_records
+*/
+static size_t count;
+
+/* Actual number of allocations logged */
+static size_t total_allocations;
+
+/* Actual number of frees logged */
+static size_t total_frees;
+
+/* Has the buffer overflowed and lost trace entries? */
+static bool has_overflowed = false;
+
+esp_err_t heap_trace_init_standalone(heap_trace_record_t *record_buffer, size_t num_records)
+{
+#ifndef CONFIG_HEAP_TRACING
+    return ESP_ERR_NOT_SUPPORTED;
+#endif
+
+    if (tracing) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    buffer = record_buffer;
+    total_records = num_records;
+    memset(buffer, 0, num_records * sizeof(heap_trace_record_t));
+    return ESP_OK;
+}
+
+esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
+{
+#ifndef CONFIG_HEAP_TRACING
+    return ESP_ERR_NOT_SUPPORTED;
+#endif
+
+    if (buffer == NULL || total_records == 0) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    portENTER_CRITICAL(&trace_mux);
+
+    tracing = false;
+    mode = mode_param;
+    count = 0;
+    total_allocations = 0;
+    total_frees = 0;
+    has_overflowed = false;
+    heap_trace_resume();
+
+    portEXIT_CRITICAL(&trace_mux);
+    return ESP_OK;
+}
+
+static esp_err_t set_tracing(bool enable)
+{
+#ifndef CONFIG_HEAP_TRACING
+    return ESP_ERR_NOT_SUPPORTED;
+#endif
+    if (tracing == enable) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    tracing = enable;
+    return ESP_OK;
+}
+
+esp_err_t heap_trace_stop(void)
+{
+    return set_tracing(false);
+}
+
+esp_err_t heap_trace_resume(void)
+{
+    return set_tracing(true);
+}
+
+size_t heap_trace_get_count(void)
+{
+    return count;
+}
+
+esp_err_t heap_trace_get(size_t index, heap_trace_record_t *record)
+{
+#ifndef CONFIG_HEAP_TRACING
+    return ESP_ERR_NOT_SUPPORTED;
+#endif
+    if (record == NULL) {
+        return ESP_ERR_INVALID_STATE;
+    }
+    esp_err_t result = ESP_OK;
+
+    portENTER_CRITICAL(&trace_mux);
+    if (index >= count) {
+        result = ESP_ERR_INVALID_ARG; /* out of range for 'count' */
+    } else {
+        memcpy(record, &buffer[index], sizeof(heap_trace_record_t));
+    }
+    portEXIT_CRITICAL(&trace_mux);
+    return result;
+}
+
+
+void heap_trace_dump(void)
+{
+#ifndef CONFIG_HEAP_TRACING
+    printf("no data, heap tracing is disabled.\n");
+    return;
+#endif
+    size_t delta_size = 0;
+    size_t delta_allocs = 0;
+    printf("%u allocations trace (%u entry buffer)\n",
+           count, total_records);
+    size_t start_count = count;
+    for (unsigned i = 0; i < count; i++) {
+        heap_trace_record_t *rec = &buffer[i];
+
+        if (rec->address != NULL) {
+            printf("%d bytes (@ %p) allocated CPU %d ccount 0x%08x caller ",
+                   rec->size, rec->address, rec->ccount & 1, rec->ccount & ~3);
+            for (int j = 0; j < STACK_DEPTH && rec->alloced_by[j] != 0; j++) {
+                printf("%p%s", rec->alloced_by[j],
+                       (j < STACK_DEPTH - 1) ? ":" : "");
+            }
+
+            if (mode != HEAP_TRACE_ALL || STACK_DEPTH == 0 || rec->freed_by[0] == NULL) {
+                delta_size += rec->size;
+                delta_allocs++;
+                printf("\n");
+            } else {
+                printf("\nfreed by ");
+                for (int j = 0; j < STACK_DEPTH; j++) {
+                    printf("%p%s", rec->freed_by[j],
+                           (j < STACK_DEPTH - 1) ? ":" : "\n");
+                }
+            }
+        }
+    }
+    if (mode == HEAP_TRACE_ALL) {
+        printf("%u bytes alive in trace (%u/%u allocations)\n",
+               delta_size, delta_allocs, heap_trace_get_count());
+    } else {
+        printf("%u bytes 'leaked' in trace (%u allocations)\n", delta_size, delta_allocs);
+    }
+    printf("total allocations %u total frees %u\n", total_allocations, total_frees);
+    if (start_count != count) { // only a problem if trace isn't stopped before dumping
+        printf("(NB: New entries were traced while dumping, so trace dump may have duplicate entries.)\n");
+    }
+    if (has_overflowed) {
+        printf("(NB: Buffer has overflowed, so trace data is incomplete.)\n");
+    }
+}
+
+/* Add a new allocation to the heap trace records */
+static IRAM_ATTR void record_allocation(const heap_trace_record_t *record)
+{
+    portENTER_CRITICAL(&trace_mux);
+    if (tracing) {
+        if (count == total_records) {
+            has_overflowed = true;
+            /* Move the whole buffer back one slot.
+
+               This is a bit slow, compared to treating this buffer as a ringbuffer and rotating a head pointer.
+
+               However, ringbuffer code gets tricky when we remove elements in mid-buffer (for leak trace mode) while
+               trying to keep track of an item count that may overflow.
+            */
+            memmove(&buffer[0], &buffer[1], sizeof(heap_trace_record_t) * (total_records -1));
+            count--;
+        }
+        // Copy new record into place
+        memcpy(&buffer[count], record, sizeof(heap_trace_record_t));
+        count++;
+        total_allocations++;
+    }
+    portEXIT_CRITICAL(&trace_mux);
+}
+
+// remove a record, used when freeing
+static void remove_record(int index);
+
+/* record a free event in the heap trace log
+
+   For HEAP_TRACE_ALL, this means filling in the freed_by pointer.
+   For HEAP_TRACE_LEAKS, this means removing the record from the log.
+*/
+static IRAM_ATTR void record_free(void *p, void **callers)
+{
+    portENTER_CRITICAL(&trace_mux);
+    if (tracing && count > 0) {
+        total_frees++;
+        /* search backwards for the allocation record matching this free */
+        int i;
+        for (i = count - 1; i >= 0; i--) {
+            if (buffer[i].address == p) {
+                break;
+            }
+        }
+
+        if (i >= 0) {
+            if (mode == HEAP_TRACE_ALL) {
+                memcpy(buffer[i].freed_by, callers, sizeof(void *) * STACK_DEPTH);
+            } else { // HEAP_TRACE_LEAKS
+                // Leak trace mode, once an allocation is freed we remove it from the list
+                remove_record(i);
+            }
+        }
+    }
+    portEXIT_CRITICAL(&trace_mux);
+}
+
+/* remove the entry at 'index' from the ringbuffer of saved records */
+static IRAM_ATTR void remove_record(int index)
+{
+    if ((unsigned)index < count - 1) {
+        // Remove the buffer entry from the list
+        memmove(&buffer[index], &buffer[index+1],
+                sizeof(heap_trace_record_t) * (total_records - index - 1));
+    } else {
+        // For last element, just zero it out to avoid ambiguity
+        memset(&buffer[index], 0, sizeof(heap_trace_record_t));
+    }
+    count--;
+}
+
+/* Encode the CPU ID in the LSB of the ccount value */
+inline static uint32_t get_ccount(void)
+{
+    uint32_t ccount = xthal_get_ccount() & ~3;
+#ifndef CONFIG_FREERTOS_UNICORE
+    ccount |= xPortGetCoreID();
+#endif
+    return ccount;
+}
+
+#define TEST_STACK(N) do {                                              \
+        if (STACK_DEPTH == N) {                                         \
+            return;                                                     \
+        }                                                               \
+        callers[N] = __builtin_return_address(N+offset);                \
+        if (!esp_ptr_executable(callers[N])) {                          \
+            return;                                                     \
+        }                                                               \
+    } while(0);
+
+/* Static function to read the call stack for a traced heap call.
+
+   Calls to __builtin_return_address are "unrolled" via TEST_STACK macro as gcc requires the
+   argument to be a compile-time constant.
+*/
+static IRAM_ATTR __attribute__((noinline)) void get_call_stack(void **callers)
+{
+    const int offset = 2; // Caller is 2 stack frames deeper than we care about
+    bzero(callers, sizeof(void *) * STACK_DEPTH);
+    TEST_STACK(0);
+    TEST_STACK(1);
+    TEST_STACK(2);
+    TEST_STACK(3);
+    TEST_STACK(4);
+    TEST_STACK(5);
+    TEST_STACK(6);
+    TEST_STACK(7);
+    TEST_STACK(8);
+    TEST_STACK(9);
+}
+
+_Static_assert(STACK_DEPTH >= 0 && STACK_DEPTH <= 10, "CONFIG_HEAP_TRACING_STACK_DEPTH must be in range 0-10");
+
+
+typedef enum {
+    TRACE_MALLOC_CAPS,
+    TRACE_MALLOC_DEFAULT
+} trace_malloc_mode_t;
+
+
+void *__real_heap_caps_malloc(size_t size, uint32_t caps);
+void *__real_heap_caps_malloc_default( size_t size );
+void *__real_heap_caps_realloc_default( void *ptr, size_t size );
+
+/* trace any 'malloc' event */
+static IRAM_ATTR __attribute__((noinline)) void *trace_malloc(size_t size, uint32_t caps, trace_malloc_mode_t mode)
+{
+    uint32_t ccount = get_ccount();
+    void *p;
+    if ( mode == TRACE_MALLOC_CAPS ) {
+        p = __real_heap_caps_malloc(size, caps);
+    } else { //TRACE_MALLOC_DEFAULT
+        p = __real_heap_caps_malloc_default(size);
+    }
+
+    if (tracing && p != NULL) {
+        heap_trace_record_t rec = {
+            .address = p,
+            .ccount = ccount,
+            .size = size,
+        };
+        get_call_stack(rec.alloced_by);
+        record_allocation(&rec);
+    }
+    return p;
+}
+
+void __real_heap_caps_free(void *p);
+
+/* trace any 'free' event */
+static IRAM_ATTR __attribute__((noinline)) void trace_free(void *p)
+{
+    if (tracing && p != NULL) {
+        void *callers[STACK_DEPTH];
+        get_call_stack(callers);
+        record_free(p, callers);
+    }
+    __real_heap_caps_free(p);
+}
+
+void * __real_heap_caps_realloc(void *p, size_t size, uint32_t caps);
+
+/* trace any 'realloc' event */
+static IRAM_ATTR __attribute__((noinline)) void *trace_realloc(void *p, size_t size, uint32_t caps, trace_malloc_mode_t mode)
+{
+    void *callers[STACK_DEPTH];
+    uint32_t ccount = get_ccount();
+    if (tracing && p != NULL && size == 0) {
+        get_call_stack(callers);
+        record_free(p, callers);
+    }
+    void *r;
+    if (mode == TRACE_MALLOC_CAPS ) {
+        r = __real_heap_caps_realloc(p, size, caps);
+    } else { //TRACE_MALLOC_DEFAULT
+        r = __real_heap_caps_realloc_default(p, size);
+    }
+    if (tracing && r != NULL) {
+        get_call_stack(callers);
+        if (p != NULL) {
+            /* trace realloc as free-then-alloc */
+            record_free(p, callers);
+        }
+        heap_trace_record_t rec = {
+            .address = r,
+            .ccount = ccount,
+            .size = size,
+        };
+        memcpy(rec.alloced_by, callers, sizeof(void *) * STACK_DEPTH);
+        record_allocation(&rec);
+    }
+    return r;
+}
+
+/* Note: this changes the behaviour of libc malloc/realloc/free a bit,
+   as they no longer go via the libc functions in ROM. But more or less
+   the same in the end. */
+
+IRAM_ATTR void *__wrap_malloc(size_t size)
+{
+    return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
+}
+
+IRAM_ATTR void __wrap_free(void *p)
+{
+    trace_free(p);
+}
+
+IRAM_ATTR void *__wrap_realloc(void *p, size_t size)
+{
+    return trace_realloc(p, size, 0, TRACE_MALLOC_DEFAULT);
+}
+
+IRAM_ATTR void *__wrap_calloc(size_t nmemb, size_t size)
+{
+    size = size * nmemb;
+    void *result = trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
+    if (result != NULL) {
+        memset(result, 0, size);
+    }
+    return result;
+}
+
+IRAM_ATTR void *__wrap_heap_caps_malloc(size_t size, uint32_t caps)
+{
+    return trace_malloc(size, caps, TRACE_MALLOC_CAPS);
+}
+
+IRAM_ATTR void __wrap_heap_caps_free(void *p) __attribute__((alias("__wrap_free")));
+
+IRAM_ATTR void *__wrap_heap_caps_realloc(void *p, size_t size, uint32_t caps)
+{
+    return trace_realloc(p, size, caps, TRACE_MALLOC_CAPS);
+}
+
+IRAM_ATTR void *__wrap_heap_caps_malloc_default( size_t size )
+{
+    return trace_malloc(size, 0, TRACE_MALLOC_DEFAULT);
+}
+
+IRAM_ATTR void *__wrap_heap_caps_realloc_default( void *ptr, size_t size )
+{
+    return trace_realloc(ptr, size, 0, TRACE_MALLOC_DEFAULT);
+}
diff --git a/cpu/esp32/vendor/esp-idf/heap/multi_heap.c b/cpu/esp32/vendor/esp-idf/heap/multi_heap.c
new file mode 100644
index 0000000000000000000000000000000000000000..06950ea70db8648f12ed49ec1670f648ad927f84
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/heap/multi_heap.c
@@ -0,0 +1,745 @@
+// 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 <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <multi_heap.h>
+#include "multi_heap_internal.h"
+
+/* Note: Keep platform-specific parts in this header, this source
+   file should depend on libc only */
+#include "multi_heap_platform.h"
+
+/* Defines compile-time configuration macros */
+#include "multi_heap_config.h"
+
+#ifndef MULTI_HEAP_POISONING
+/* if no heap poisoning, public API aliases directly to these implementations */
+void *multi_heap_malloc(multi_heap_handle_t heap, size_t size)
+    __attribute__((alias("multi_heap_malloc_impl")));
+
+void multi_heap_free(multi_heap_handle_t heap, void *p)
+    __attribute__((alias("multi_heap_free_impl")));
+
+void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size)
+    __attribute__((alias("multi_heap_realloc_impl")));
+
+size_t multi_heap_get_allocated_size(multi_heap_handle_t heap, void *p)
+    __attribute__((alias("multi_heap_get_allocated_size_impl")));
+
+multi_heap_handle_t multi_heap_register(void *start, size_t size)
+    __attribute__((alias("multi_heap_register_impl")));
+
+void multi_heap_get_info(multi_heap_handle_t heap, multi_heap_info_t *info)
+    __attribute__((alias("multi_heap_get_info_impl")));
+
+size_t multi_heap_free_size(multi_heap_handle_t heap)
+    __attribute__((alias("multi_heap_free_size_impl")));
+
+size_t multi_heap_minimum_free_size(multi_heap_handle_t heap)
+    __attribute__((alias("multi_heap_minimum_free_size_impl")));
+
+void *multi_heap_get_block_address(multi_heap_block_handle_t block)
+    __attribute__((alias("multi_heap_get_block_address_impl")));
+
+void *multi_heap_get_block_owner(multi_heap_block_handle_t block)
+{
+    return NULL;
+}
+
+#endif
+
+#define ALIGN(X) ((X) & ~(sizeof(void *)-1))
+#define ALIGN_UP(X) ALIGN((X)+sizeof(void *)-1)
+
+struct heap_block;
+
+/* Block in the heap
+
+   Heap implementation uses two single linked lists, a block list (all blocks) and a free list (free blocks).
+
+   'header' holds a pointer to the next block (used or free) ORed with a free flag (the LSB of the pointer.) is_free() and get_next_block() utility functions allow typed access to these values.
+
+   'next_free' is valid if the block is free and is a pointer to the next block in the free list.
+*/
+typedef struct heap_block {
+    intptr_t header;                  /* Encodes next block in heap (used or unused) and also free/used flag */
+    union {
+        uint8_t data[1];              /* First byte of data, valid if block is used. Actual size of data is 'block_data_size(block)' */
+        struct heap_block *next_free; /* Pointer to next free block, valid if block is free */
+    };
+} heap_block_t;
+
+/* These masks apply to the 'header' field of heap_block_t */
+#define BLOCK_FREE_FLAG 0x1  /* If set, this block is free & next_free pointer is valid */
+#define NEXT_BLOCK_MASK (~3) /* AND header with this mask to get pointer to next block (free or used) */
+
+/* Metadata header for the heap, stored at the beginning of heap space.
+
+   'first_block' is a "fake" first block, minimum length, used to provide a pointer to the first used & free block in
+   the heap. This block is never allocated or merged into an adjacent block.
+
+   'last_block' is a pointer to a final free block of length 0, which is added at the end of the heap when it is
+   registered. This block is also never allocated or merged into an adjacent block.
+ */
+typedef struct multi_heap_info {
+    void *lock;
+    size_t free_bytes;
+    size_t minimum_free_bytes;
+    heap_block_t *last_block;
+    heap_block_t first_block; /* initial 'free block', never allocated */
+} heap_t;
+
+/* Given a pointer to the 'data' field of a block (ie the previous malloc/realloc result), return a pointer to the
+   containing block.
+*/
+static inline heap_block_t *get_block(const void *data_ptr)
+{
+    return (heap_block_t *)((char *)data_ptr - offsetof(heap_block_t, data));
+}
+
+/* Return the next sequential block in the heap.
+ */
+static inline heap_block_t *get_next_block(const heap_block_t *block)
+{
+    intptr_t next = block->header & NEXT_BLOCK_MASK;
+    if (next == 0) {
+        return NULL; /* last_block */
+    }
+    assert(next > (intptr_t)block);
+    return (heap_block_t *)next;
+}
+
+/* Return true if this block is free. */
+static inline bool is_free(const heap_block_t *block)
+{
+    return block->header & BLOCK_FREE_FLAG;
+}
+
+/* Return true if this block is the first in the heap */
+static inline bool is_first_block(const heap_t *heap, const heap_block_t *block)
+{
+    return (block == &heap->first_block);
+}
+
+/* Return true if this block is the last_block in the heap
+   (the only block with no next pointer) */
+static inline bool is_last_block(const heap_block_t *block)
+{
+    return (block->header & NEXT_BLOCK_MASK) == 0;
+}
+
+/* Data size of the block (excludes this block's header) */
+static inline size_t block_data_size(const heap_block_t *block)
+{
+    intptr_t next = (intptr_t)block->header & NEXT_BLOCK_MASK;
+    intptr_t this = (intptr_t)block;
+    if (next == 0) {
+        return 0; /* this is the last block in the heap */
+    }
+    return next - this - sizeof(block->header);
+}
+
+/* Check a block is valid for this heap. Used to verify parameters. */
+static void assert_valid_block(const heap_t *heap, const heap_block_t *block)
+{
+    MULTI_HEAP_ASSERT(block >= &heap->first_block && block <= heap->last_block,
+                      block); // block not in heap
+    if (heap < (const heap_t *)heap->last_block) {
+        const heap_block_t *next = get_next_block(block);
+        MULTI_HEAP_ASSERT(next >= &heap->first_block && next <= heap->last_block, block); // Next block not in heap
+        if (is_free(block)) {
+            // Check block->next_free is valid
+            MULTI_HEAP_ASSERT(block->next_free >= &heap->first_block && block->next_free <= heap->last_block, &block->next_free);
+        }
+    }
+}
+
+/* Get the first free block before 'block' in the heap. 'block' can be a free block or in use.
+
+   Result is always the closest free block to 'block' in the heap, that is located before 'block'. There may be multiple
+   allocated blocks between the result and 'block'.
+
+   If 'block' is free, the result's 'next_free' pointer will already point to 'block'.
+
+   Result will never be NULL, but it may be the header block heap->first_block.
+*/
+static heap_block_t *get_prev_free_block(heap_t *heap, const heap_block_t *block)
+{
+    assert(!is_first_block(heap, block)); /* can't look for a block before first_block */
+
+    for (heap_block_t *b = &heap->first_block; b != NULL && b < block; b = b->next_free) {
+        MULTI_HEAP_ASSERT(is_free(b), b); // Block should be free
+        if (b->next_free == NULL || b->next_free >= block) {
+            if (is_free(block)) {
+                 /* if block is on freelist, 'b' should be the item before it. */
+                MULTI_HEAP_ASSERT(b->next_free == block, &b->next_free);
+            }
+            return b; /* b is the last free block before 'block' */
+        }
+    }
+    abort(); /* There should always be a previous free block, even if it's heap->first_block */
+}
+
+/* Merge some block 'a' into the following block 'b'.
+
+   If both blocks are free, resulting block is marked free.
+   If only one block is free, resulting block is marked in use. No data is moved.
+
+   This operation may fail if block 'a' is the first block or 'b' is the last block,
+   the caller should check block_data_size() to know if anything happened here or not.
+*/
+static heap_block_t *merge_adjacent(heap_t *heap, heap_block_t *a, heap_block_t *b)
+{
+    assert(a < b);
+
+    /* Can't merge header blocks, just return the non-header block as-is */
+    if (is_last_block(b)) {
+        return a;
+    }
+    if (is_first_block(heap, a)) {
+        return b;
+    }
+
+    MULTI_HEAP_ASSERT(get_next_block(a) == b, a); // Blocks should be in order
+
+    bool free = is_free(a) && is_free(b); /* merging two free blocks creates a free block */
+    if (!free && (is_free(a) || is_free(b))) {
+        /* only one of these blocks is free, so resulting block will be a used block.
+           means we need to take the free block out of the free list
+         */
+        heap_block_t *free_block = is_free(a) ? a : b;
+        heap_block_t *prev_free = get_prev_free_block(heap, free_block);
+        MULTI_HEAP_ASSERT(free_block->next_free > prev_free, &free_block->next_free); // Next free block should be after prev one
+        prev_free->next_free = free_block->next_free;
+
+        heap->free_bytes -= block_data_size(free_block);
+    }
+
+    a->header = b->header & NEXT_BLOCK_MASK;
+    MULTI_HEAP_ASSERT(a->header != 0, a);
+    if (free) {
+        a->header |= BLOCK_FREE_FLAG;
+        if (b->next_free != NULL) {
+            MULTI_HEAP_ASSERT(b->next_free > a, &b->next_free);
+            MULTI_HEAP_ASSERT(b->next_free > b, &b->next_free);
+        }
+        a->next_free = b->next_free;
+
+        /* b's header can be put into the pool of free bytes */
+        heap->free_bytes += sizeof(a->header);
+    }
+
+#ifdef MULTI_HEAP_POISONING_SLOW
+    /* b's former block header needs to be replaced with a fill pattern */
+    multi_heap_internal_poison_fill_region(b, sizeof(heap_block_t), free);
+#endif
+
+    return a;
+}
+
+/* Split a block so it can hold at least 'size' bytes of data, making any spare
+   space into a new free block.
+
+   'block' should be marked in-use when this function is called (implementation detail, this function
+   doesn't set the next_free pointer).
+
+   'prev_free_block' is the free block before 'block', if already known. Can be NULL if not yet known.
+   (This is a performance optimisation to avoid walking the freelist twice when possible.)
+*/
+static void split_if_necessary(heap_t *heap, heap_block_t *block, size_t size, heap_block_t *prev_free_block)
+{
+    const size_t block_size = block_data_size(block);
+    MULTI_HEAP_ASSERT(!is_free(block), block); // split block shouldn't be free
+    MULTI_HEAP_ASSERT(size <= block_size, block); // size should be valid
+    size = ALIGN_UP(size);
+
+    /* can't split the head or tail block */
+    assert(!is_first_block(heap, block));
+    assert(!is_last_block(block));
+
+    heap_block_t *new_block = (heap_block_t *)(block->data + size);
+    heap_block_t *next_block = get_next_block(block);
+
+    if (is_free(next_block) && !is_last_block(next_block)) {
+        /* The next block is free, just extend it upwards. */
+        new_block->header = next_block->header;
+        new_block->next_free = next_block->next_free;
+        if (prev_free_block == NULL) {
+            prev_free_block = get_prev_free_block(heap, block);
+        }
+        /* prev_free_block should point to the next block (which we found to be free). */
+        MULTI_HEAP_ASSERT(prev_free_block->next_free == next_block,
+                          &prev_free_block->next_free); // free blocks should be in order
+        /* Note: We have not introduced a new block header, hence the simple math. */
+        heap->free_bytes += block_size - size;
+#ifdef MULTI_HEAP_POISONING_SLOW
+        /* next_block header needs to be replaced with a fill pattern */
+        multi_heap_internal_poison_fill_region(next_block, sizeof(heap_block_t), true /* free */);
+#endif
+    } else {
+        /* Insert a free block between the current and the next one. */
+        if (block_data_size(block) < size + sizeof(heap_block_t)) {
+            /* Can't split 'block' if we're not going to get a usable free block afterwards */
+            return;
+        }
+        if (prev_free_block == NULL) {
+            prev_free_block = get_prev_free_block(heap, block);
+        }
+        new_block->header = block->header | BLOCK_FREE_FLAG;
+        new_block->next_free = prev_free_block->next_free;
+        /* prev_free_block should point to a free block after new_block */
+        MULTI_HEAP_ASSERT(prev_free_block->next_free > new_block,
+                          &prev_free_block->next_free); // free blocks should be in order
+        heap->free_bytes += block_data_size(new_block);
+    }
+    block->header = (intptr_t)new_block;
+    prev_free_block->next_free = new_block;
+}
+
+void *multi_heap_get_block_address_impl(multi_heap_block_handle_t block)
+{
+    return ((char *)block + offsetof(heap_block_t, data));
+}
+
+size_t multi_heap_get_allocated_size_impl(multi_heap_handle_t heap, void *p)
+{
+    heap_block_t *pb = get_block(p);
+
+    assert_valid_block(heap, pb);
+    MULTI_HEAP_ASSERT(!is_free(pb), pb); // block shouldn't be free
+    return block_data_size(pb);
+}
+
+multi_heap_handle_t multi_heap_register_impl(void *start, size_t size)
+{
+    heap_t *heap = (heap_t *)ALIGN_UP((intptr_t)start);
+    uintptr_t end = ALIGN((uintptr_t)start + size);
+    if (end - (uintptr_t)start < sizeof(heap_t) + 2*sizeof(heap_block_t)) {
+        return NULL; /* 'size' is too small to fit a heap here */
+    }
+    heap->lock = NULL;
+    heap->last_block = (heap_block_t *)(end - sizeof(heap_block_t));
+
+    /* first 'real' (allocatable) free block goes after the heap structure */
+    heap_block_t *first_free_block = (heap_block_t *)((intptr_t)start + sizeof(heap_t));
+    first_free_block->header = (intptr_t)heap->last_block | BLOCK_FREE_FLAG;
+    first_free_block->next_free = heap->last_block;
+
+    /* last block is 'free' but has a NULL next pointer */
+    heap->last_block->header = BLOCK_FREE_FLAG;
+    heap->last_block->next_free = NULL;
+
+    /* first block also 'free' but has legitimate length,
+       malloc will never allocate into this block. */
+    heap->first_block.header = (intptr_t)first_free_block | BLOCK_FREE_FLAG;
+    heap->first_block.next_free = first_free_block;
+
+    /* free bytes is:
+       - total bytes in heap
+       - minus heap_t header at top (includes heap->first_block)
+       - minus header of first_free_block
+       - minus whole block at heap->last_block
+    */
+    heap->free_bytes = ALIGN(size) - sizeof(heap_t) - sizeof(first_free_block->header) - sizeof(heap_block_t);
+    heap->minimum_free_bytes = heap->free_bytes;
+
+    return heap;
+}
+
+void multi_heap_set_lock(multi_heap_handle_t heap, void *lock)
+{
+    heap->lock = lock;
+}
+
+inline void multi_heap_internal_lock(multi_heap_handle_t heap)
+{
+    MULTI_HEAP_LOCK(heap->lock);
+}
+
+inline void multi_heap_internal_unlock(multi_heap_handle_t heap)
+{
+    MULTI_HEAP_UNLOCK(heap->lock);
+}
+
+multi_heap_block_handle_t multi_heap_get_first_block(multi_heap_handle_t heap)
+{
+    return &heap->first_block;
+}
+
+multi_heap_block_handle_t multi_heap_get_next_block(multi_heap_handle_t heap, multi_heap_block_handle_t block)
+{
+    heap_block_t *next = get_next_block(block);
+    /* check for valid free last block to avoid assert in assert_valid_block */
+    if (next == heap->last_block && is_last_block(next) && is_free(next)) {
+        return NULL;
+    }
+    assert_valid_block(heap, next);
+    return next;
+}
+
+bool multi_heap_is_free(multi_heap_block_handle_t block)
+{
+    return is_free(block);
+}
+
+void *multi_heap_malloc_impl(multi_heap_handle_t heap, size_t size)
+{
+    heap_block_t *best_block = NULL;
+    heap_block_t *prev_free = NULL;
+    heap_block_t *prev = NULL;
+    size_t best_size = SIZE_MAX;
+    size = ALIGN_UP(size);
+
+    if (size == 0 || heap == NULL) {
+        return NULL;
+    }
+
+    multi_heap_internal_lock(heap);
+
+    /* Note: this check must be done while holding the lock as both
+       malloc & realloc may temporarily shrink the free_bytes value
+       before they split a large block. This can result in false negatives,
+       especially if the heap is unfragmented.
+    */
+    if (heap->free_bytes < size) {
+        MULTI_HEAP_UNLOCK(heap->lock);
+        return NULL;
+    }
+
+    /* Find best free block to perform the allocation in */
+    prev = &heap->first_block;
+    for (heap_block_t *b = heap->first_block.next_free; b != NULL; b = b->next_free) {
+        MULTI_HEAP_ASSERT(b > prev, &prev->next_free); // free blocks should be ascending in address
+        MULTI_HEAP_ASSERT(is_free(b), b); // block should be free
+        size_t bs = block_data_size(b);
+        if (bs >= size && bs < best_size) {
+            best_block = b;
+            best_size = bs;
+            prev_free = prev;
+            if (bs == size) {
+                break; /* we've found a perfect sized block */
+            }
+        }
+        prev = b;
+    }
+
+    if (best_block == NULL) {
+        multi_heap_internal_unlock(heap);
+        return NULL; /* No room in heap */
+    }
+
+    prev_free->next_free = best_block->next_free;
+    best_block->header &= ~BLOCK_FREE_FLAG;
+
+    heap->free_bytes -= block_data_size(best_block);
+
+    split_if_necessary(heap, best_block, size, prev_free);
+
+    if (heap->free_bytes < heap->minimum_free_bytes) {
+        heap->minimum_free_bytes = heap->free_bytes;
+    }
+
+    multi_heap_internal_unlock(heap);
+
+    return best_block->data;
+}
+
+void multi_heap_free_impl(multi_heap_handle_t heap, void *p)
+{
+    heap_block_t *pb = get_block(p);
+
+    if (heap == NULL || p == NULL) {
+        return;
+    }
+
+    multi_heap_internal_lock(heap);
+
+    assert_valid_block(heap, pb);
+    MULTI_HEAP_ASSERT(!is_free(pb), pb); // block should not be free
+    MULTI_HEAP_ASSERT(!is_last_block(pb), pb); // block should not be last block
+    MULTI_HEAP_ASSERT(!is_first_block(heap, pb), pb); // block should not be first block
+
+    heap_block_t *next = get_next_block(pb);
+
+    /* Update freelist pointers */
+    heap_block_t *prev_free = get_prev_free_block(heap, pb);
+    // freelist validity check
+    MULTI_HEAP_ASSERT(prev_free->next_free == NULL || prev_free->next_free > pb, &prev_free->next_free);
+    pb->next_free = prev_free->next_free;
+    prev_free->next_free = pb;
+
+    /* Mark this block as free */
+    pb->header |= BLOCK_FREE_FLAG;
+
+    heap->free_bytes += block_data_size(pb);
+
+    /* Try and merge previous free block into this one */
+    if (get_next_block(prev_free) == pb) {
+        pb = merge_adjacent(heap, prev_free, pb);
+    }
+
+    /* If next block is free, try to merge the two */
+    if (is_free(next)) {
+        pb = merge_adjacent(heap, pb, next);
+    }
+
+    multi_heap_internal_unlock(heap);
+}
+
+
+void *multi_heap_realloc_impl(multi_heap_handle_t heap, void *p, size_t size)
+{
+    heap_block_t *pb = get_block(p);
+    void *result;
+    size = ALIGN_UP(size);
+
+    assert(heap != NULL);
+
+    if (p == NULL) {
+        return multi_heap_malloc_impl(heap, size);
+    }
+
+    assert_valid_block(heap, pb);
+    // non-null realloc arg should be allocated
+    MULTI_HEAP_ASSERT(!is_free(pb), pb);
+
+    if (size == 0) {
+        /* note: calling multi_free_impl() here as we've already been
+           through any poison-unwrapping */
+        multi_heap_free_impl(heap, p);
+        return NULL;
+    }
+
+    if (heap == NULL) {
+        return NULL;
+    }
+
+    multi_heap_internal_lock(heap);
+    result = NULL;
+
+    if (size <= block_data_size(pb)) {
+        // Shrinking....
+        split_if_necessary(heap, pb, size, NULL);
+        result = pb->data;
+    }
+    else if (heap->free_bytes < size - block_data_size(pb)) {
+        // Growing, but there's not enough total free space in the heap
+        multi_heap_internal_unlock(heap);
+        return NULL;
+    }
+
+    // New size is larger than existing block
+    if (result == NULL) {
+        // See if we can grow into one or both adjacent blocks
+        heap_block_t *orig_pb = pb;
+        size_t orig_size = block_data_size(orig_pb);
+        heap_block_t *next = get_next_block(pb);
+        heap_block_t *prev = get_prev_free_block(heap, pb);
+
+        // Can only grow into the previous free block if it's adjacent
+        size_t prev_grow_size = (get_next_block(prev) == pb) ? block_data_size(prev) : 0;
+
+        // Can grow into next block? (we may also need to grow into 'prev' to get to our desired size)
+        if (is_free(next) && (block_data_size(pb) + block_data_size(next) + prev_grow_size >= size)) {
+            pb = merge_adjacent(heap, pb, next);
+        }
+
+        // Can grow into previous block?
+        // (try this even if we're already big enough from growing into 'next', as it reduces fragmentation)
+        if (prev_grow_size > 0 && (block_data_size(pb) + prev_grow_size >= size)) {
+            pb = merge_adjacent(heap, prev, pb);
+            // this doesn't guarantee we'll be left with a big enough block, as it's
+            // possible for the merge to fail if prev == heap->first_block
+        }
+
+        if (block_data_size(pb) >= size) {
+            memmove(pb->data, orig_pb->data, orig_size);
+            split_if_necessary(heap, pb, size, NULL);
+            result = pb->data;
+        }
+    }
+
+    if (result == NULL) {
+        // Need to allocate elsewhere and copy data over
+        //
+        // (Calling _impl versions here as we've already been through any
+        // unwrapping for heap poisoning features.)
+        result = multi_heap_malloc_impl(heap, size);
+        if (result != NULL) {
+            memcpy(result, pb->data, block_data_size(pb));
+            multi_heap_free_impl(heap, pb->data);
+        }
+    }
+
+    if (heap->free_bytes < heap->minimum_free_bytes) {
+        heap->minimum_free_bytes = heap->free_bytes;
+    }
+
+    multi_heap_internal_unlock(heap);
+    return result;
+}
+
+#define FAIL_PRINT(MSG, ...) do {                                       \
+        if (print_errors) {                                             \
+            MULTI_HEAP_STDERR_PRINTF(MSG, __VA_ARGS__);                 \
+        }                                                               \
+        valid = false;                                                  \
+    }                                                                   \
+    while(0)
+
+bool multi_heap_check(multi_heap_handle_t heap, bool print_errors)
+{
+    bool valid = true;
+    size_t total_free_bytes = 0;
+    assert(heap != NULL);
+
+    multi_heap_internal_lock(heap);
+
+    heap_block_t *prev = NULL;
+    heap_block_t *prev_free = NULL;
+    heap_block_t *expected_free = NULL;
+
+    /* note: not using get_next_block() in loop, so that assertions aren't checked here */
+    for(heap_block_t *b = &heap->first_block; b != NULL; b = (heap_block_t *)(b->header & NEXT_BLOCK_MASK)) {
+        if (b == prev) {
+            FAIL_PRINT("CORRUPT HEAP: Block %p points to itself\n", b);
+            goto done;
+        }
+        if (b < prev) {
+            FAIL_PRINT("CORRUPT HEAP: Block %p is before prev block %p\n", b, prev);
+            goto done;
+        }
+        if (b > heap->last_block || b < &heap->first_block) {
+            FAIL_PRINT("CORRUPT HEAP: Block %p is outside heap (last valid block %p)\n", b, prev);
+            goto done;
+        }
+        if (is_free(b)) {
+            if (prev != NULL && is_free(prev) && !is_first_block(heap, prev) && !is_last_block(b)) {
+                FAIL_PRINT("CORRUPT HEAP: Two adjacent free blocks found, %p and %p\n", prev, b);
+            }
+            if (expected_free != NULL && expected_free != b) {
+                FAIL_PRINT("CORRUPT HEAP: Prev free block %p pointed to next free %p but this free block is %p\n",
+                       prev_free, expected_free, b);
+            }
+            prev_free = b;
+            expected_free = b->next_free;
+            if (!is_first_block(heap, b)) {
+                total_free_bytes += block_data_size(b);
+            }
+        }
+        prev = b;
+
+#ifdef MULTI_HEAP_POISONING
+        if (!is_last_block(b)) {
+            /* For slow heap poisoning, any block should contain correct poisoning patterns and/or fills */
+            bool poison_ok;
+            if (is_free(b) && b != heap->last_block) {
+                uint32_t block_len = (intptr_t)get_next_block(b) - (intptr_t)b - sizeof(heap_block_t);
+                poison_ok = multi_heap_internal_check_block_poisoning(&b[1], block_len, true, print_errors);
+            }
+            else {
+                poison_ok = multi_heap_internal_check_block_poisoning(b->data, block_data_size(b), false, print_errors);
+            }
+            valid = poison_ok && valid;
+        }
+#endif
+
+    } /* for(heap_block_t b = ... */
+
+    if (prev != heap->last_block) {
+        FAIL_PRINT("CORRUPT HEAP: Last block %p not %p\n", prev, heap->last_block);
+    }
+    if (!is_free(heap->last_block)) {
+        FAIL_PRINT("CORRUPT HEAP: Expected prev block %p to be free\n", heap->last_block);
+    }
+
+    if (heap->free_bytes != total_free_bytes) {
+        FAIL_PRINT("CORRUPT HEAP: Expected %u free bytes counted %u\n", (unsigned)heap->free_bytes, (unsigned)total_free_bytes);
+    }
+
+ done:
+    multi_heap_internal_unlock(heap);
+
+    return valid;
+}
+
+void multi_heap_dump(multi_heap_handle_t heap)
+{
+    assert(heap != NULL);
+
+    multi_heap_internal_lock(heap);
+    MULTI_HEAP_STDERR_PRINTF("Heap start %p end %p\nFirst free block %p\n", &heap->first_block, heap->last_block, heap->first_block.next_free);
+    for(heap_block_t *b = &heap->first_block; b != NULL; b = get_next_block(b)) {
+        MULTI_HEAP_STDERR_PRINTF("Block %p data size 0x%08x bytes next block %p", b, block_data_size(b), get_next_block(b));
+        if (is_free(b)) {
+            MULTI_HEAP_STDERR_PRINTF(" FREE. Next free %p\n", b->next_free);
+        } else {
+            MULTI_HEAP_STDERR_PRINTF("%s", "\n"); /* C macros & optional __VA_ARGS__ */
+        }
+    }
+    multi_heap_internal_unlock(heap);
+}
+
+size_t multi_heap_free_size_impl(multi_heap_handle_t heap)
+{
+    if (heap == NULL) {
+        return 0;
+    }
+    return heap->free_bytes;
+}
+
+size_t multi_heap_minimum_free_size_impl(multi_heap_handle_t heap)
+{
+    if (heap == NULL) {
+        return 0;
+    }
+    return heap->minimum_free_bytes;
+}
+
+void multi_heap_get_info_impl(multi_heap_handle_t heap, multi_heap_info_t *info)
+{
+    memset(info, 0, sizeof(multi_heap_info_t));
+
+    if (heap == NULL) {
+        return;
+    }
+
+    multi_heap_internal_lock(heap);
+    for(heap_block_t *b = get_next_block(&heap->first_block); !is_last_block(b); b = get_next_block(b)) {
+        info->total_blocks++;
+        if (is_free(b)) {
+            size_t s = block_data_size(b);
+            info->total_free_bytes += s;
+            if (s > info->largest_free_block) {
+                info->largest_free_block = s;
+            }
+            info->free_blocks++;
+        } else {
+            info->total_allocated_bytes += block_data_size(b);
+            info->allocated_blocks++;
+        }
+    }
+
+    info->minimum_free_bytes = heap->minimum_free_bytes;
+    // heap has wrong total size (address printed here is not indicative of the real error)
+    MULTI_HEAP_ASSERT(info->total_free_bytes == heap->free_bytes, heap);
+
+    multi_heap_internal_unlock(heap);
+
+}
diff --git a/cpu/esp32/vendor/esp-idf/heap/multi_heap_poisoning.c b/cpu/esp32/vendor/esp-idf/heap/multi_heap_poisoning.c
new file mode 100644
index 0000000000000000000000000000000000000000..aa50bc59e7549ef2d4525325b06122f002458fd8
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/heap/multi_heap_poisoning.c
@@ -0,0 +1,368 @@
+// 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 <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <sys/param.h>
+#include <multi_heap.h>
+#include "multi_heap_internal.h"
+
+/* Note: Keep platform-specific parts in this header, this source
+   file should depend on libc only */
+#include "multi_heap_platform.h"
+
+/* Defines compile-time configuration macros */
+#include "multi_heap_config.h"
+
+#ifdef MULTI_HEAP_POISONING
+
+/* Alias MULTI_HEAP_POISONING_SLOW to SLOW for better readabilty */
+#ifdef SLOW
+#error "external header has defined SLOW"
+#endif
+#ifdef MULTI_HEAP_POISONING_SLOW
+#define SLOW 1
+#endif
+
+#define MALLOC_FILL_PATTERN 0xce
+#define FREE_FILL_PATTERN 0xfe
+
+#define HEAD_CANARY_PATTERN 0xABBA1234
+#define TAIL_CANARY_PATTERN 0xBAAD5678
+
+typedef struct {
+    uint32_t head_canary;
+    MULTI_HEAP_BLOCK_OWNER
+    size_t alloc_size;
+} poison_head_t;
+
+typedef struct {
+    uint32_t tail_canary;
+} poison_tail_t;
+
+#define POISON_OVERHEAD (sizeof(poison_head_t) + sizeof(poison_tail_t))
+
+/* Given a "poisoned" region with pre-data header 'head', and actual data size 'alloc_size', fill in the head and tail
+   region checks.
+
+   Returns the pointer to the actual usable data buffer (ie after 'head')
+*/
+static uint8_t *poison_allocated_region(poison_head_t *head, size_t alloc_size)
+{
+    uint8_t *data = (uint8_t *)(&head[1]); /* start of data ie 'real' allocated buffer */
+    poison_tail_t *tail = (poison_tail_t *)(data + alloc_size);
+    head->alloc_size = alloc_size;
+    head->head_canary = HEAD_CANARY_PATTERN;
+    MULTI_HEAP_SET_BLOCK_OWNER(head);
+
+    uint32_t tail_canary = TAIL_CANARY_PATTERN;
+    if ((intptr_t)tail % sizeof(void *) == 0) {
+        tail->tail_canary = tail_canary;
+    } else {
+        /* unaligned tail_canary */
+        memcpy(&tail->tail_canary, &tail_canary, sizeof(uint32_t));
+    }
+
+    return data;
+}
+
+/* Given a pointer to some allocated data, check the head & tail poison structures (before & after it) that were
+   previously injected by poison_allocated_region().
+
+   Returns a pointer to the poison header structure, or NULL if the poison structures are corrupt.
+*/
+static poison_head_t *verify_allocated_region(void *data, bool print_errors)
+{
+    poison_head_t *head = (poison_head_t *)((intptr_t)data - sizeof(poison_head_t));
+    poison_tail_t *tail = (poison_tail_t *)((intptr_t)data + head->alloc_size);
+
+    /* check if the beginning of the data was overwritten */
+    if (head->head_canary != HEAD_CANARY_PATTERN) {
+        if (print_errors) {
+            MULTI_HEAP_STDERR_PRINTF("CORRUPT HEAP: Bad head at %p. Expected 0x%08x got 0x%08x\n", &head->head_canary,
+                   HEAD_CANARY_PATTERN, head->head_canary);
+        }
+        return NULL;
+    }
+
+    /* check if the end of the data was overrun */
+    uint32_t canary;
+    if ((intptr_t)tail % sizeof(void *) == 0) {
+        canary = tail->tail_canary;
+    } else {
+        /* tail is unaligned */
+        memcpy(&canary, &tail->tail_canary, sizeof(canary));
+    }
+    if (canary != TAIL_CANARY_PATTERN) {
+        if (print_errors) {
+            printf("CORRUPT HEAP: Bad tail at %p. Expected 0x%08x got 0x%08x\n", &tail->tail_canary,
+                   TAIL_CANARY_PATTERN, canary);
+        }
+        return NULL;
+    }
+
+    return head;
+}
+
+#ifdef SLOW
+/* Go through a region that should have the specified fill byte 'pattern',
+   verify it.
+
+   if expect_free is true, expect FREE_FILL_PATTERN otherwise MALLOC_FILL_PATTERN.
+
+   if swap_pattern is true, swap patterns in the buffer (ie replace MALLOC_FILL_PATTERN with FREE_FILL_PATTERN, and vice versa.)
+
+   Returns true if verification checks out.
+*/
+static bool verify_fill_pattern(void *data, size_t size, bool print_errors, bool expect_free, bool swap_pattern)
+{
+    const uint32_t FREE_FILL_WORD = (FREE_FILL_PATTERN << 24) | (FREE_FILL_PATTERN << 16) | (FREE_FILL_PATTERN << 8) | FREE_FILL_PATTERN;
+    const uint32_t MALLOC_FILL_WORD = (MALLOC_FILL_PATTERN << 24) | (MALLOC_FILL_PATTERN << 16) | (MALLOC_FILL_PATTERN << 8) | MALLOC_FILL_PATTERN;
+
+    const uint32_t EXPECT_WORD = expect_free ? FREE_FILL_WORD : MALLOC_FILL_WORD;
+    const uint32_t REPLACE_WORD = expect_free ? MALLOC_FILL_WORD : FREE_FILL_WORD;
+    bool valid = true;
+
+    /* Use 4-byte operations as much as possible */
+    if ((intptr_t)data % 4 == 0) {
+        uint32_t *p = data;
+        while (size >= 4) {
+            if (*p != EXPECT_WORD) {
+                if (print_errors) {
+                    MULTI_HEAP_STDERR_PRINTF("CORRUPT HEAP: Invalid data at %p. Expected 0x%08x got 0x%08x\n", p, EXPECT_WORD, *p);
+                }
+                valid = false;
+            }
+            if (swap_pattern) {
+                *p = REPLACE_WORD;
+            }
+            p++;
+            size -= 4;
+        }
+        data = p;
+    }
+
+    uint8_t *p = data;
+    for (int i = 0; i < size; i++) {
+        if (p[i] != (uint8_t)EXPECT_WORD) {
+            if (print_errors) {
+                MULTI_HEAP_STDERR_PRINTF("CORRUPT HEAP: Invalid data at %p. Expected 0x%02x got 0x%02x\n", p, (uint8_t)EXPECT_WORD, *p);
+            }
+            valid = false;
+        }
+        if (swap_pattern) {
+            p[i] = (uint8_t)REPLACE_WORD;
+        }
+    }
+    return valid;
+}
+#endif
+
+void *multi_heap_malloc(multi_heap_handle_t heap, size_t size)
+{
+    multi_heap_internal_lock(heap);
+    poison_head_t *head = multi_heap_malloc_impl(heap, size + POISON_OVERHEAD);
+    uint8_t *data = NULL;
+    if (head != NULL) {
+        data = poison_allocated_region(head, size);
+#ifdef SLOW
+        /* check everything we got back is FREE_FILL_PATTERN & swap for MALLOC_FILL_PATTERN */
+        bool ret = verify_fill_pattern(data, size, true, true, true);
+        assert( ret );
+#endif
+    }
+
+    multi_heap_internal_unlock(heap);
+    return data;
+}
+
+void multi_heap_free(multi_heap_handle_t heap, void *p)
+{
+    if (p == NULL) {
+        return;
+    }
+    multi_heap_internal_lock(heap);
+
+    poison_head_t *head = verify_allocated_region(p, true);
+    assert(head != NULL);
+
+    #ifdef SLOW
+    /* replace everything with FREE_FILL_PATTERN, including the poison head/tail */
+    memset(head, FREE_FILL_PATTERN,
+           head->alloc_size + POISON_OVERHEAD);
+    #endif
+    multi_heap_free_impl(heap, head);
+
+    multi_heap_internal_unlock(heap);
+}
+
+void *multi_heap_realloc(multi_heap_handle_t heap, void *p, size_t size)
+{
+    poison_head_t *head = NULL;
+    poison_head_t *new_head;
+    void *result = NULL;
+
+    if (p == NULL) {
+        return multi_heap_malloc(heap, size);
+    }
+    if (size == 0) {
+        multi_heap_free(heap, p);
+        return NULL;
+    }
+
+    /* p != NULL, size != 0 */
+    head = verify_allocated_region(p, true);
+    assert(head != NULL);
+
+    multi_heap_internal_lock(heap);
+
+#ifndef SLOW
+    new_head = multi_heap_realloc_impl(heap, head, size + POISON_OVERHEAD);
+    if (new_head != NULL) {
+        /* For "fast" poisoning, we only overwrite the head/tail of the new block so it's safe
+           to poison, so no problem doing this even if realloc resized in place.
+        */
+        result = poison_allocated_region(new_head, size);
+    }
+#else // SLOW
+    /* When slow poisoning is enabled, it becomes very fiddly to try and correctly fill memory when resizing in place
+       (where the buffer may be moved (including to an overlapping address with the old buffer), grown, or shrunk in
+       place.)
+
+       For now we just malloc a new buffer, copy, and free. :|
+
+       Note: If this ever changes, multi_heap defrag realloc test should be enabled.
+    */
+    size_t orig_alloc_size = head->alloc_size;
+
+    new_head = multi_heap_malloc_impl(heap, size + POISON_OVERHEAD);
+    if (new_head != NULL) {
+        result = poison_allocated_region(new_head, size);
+        memcpy(result, p, MIN(size, orig_alloc_size));
+        multi_heap_free(heap, p);
+    }
+#endif
+
+    multi_heap_internal_unlock(heap);
+
+    return result;
+}
+
+void *multi_heap_get_block_address(multi_heap_block_handle_t block)
+{
+    char *head = multi_heap_get_block_address_impl(block);
+    return head + sizeof(poison_head_t);
+}
+
+size_t multi_heap_get_allocated_size(multi_heap_handle_t heap, void *p)
+{
+    poison_head_t *head = verify_allocated_region(p, true);
+    assert(head != NULL);
+    size_t result = multi_heap_get_allocated_size_impl(heap, head);
+    if (result > 0) {
+        return result - POISON_OVERHEAD;
+    }
+    return 0;
+}
+
+void *multi_heap_get_block_owner(multi_heap_block_handle_t block)
+{
+    return MULTI_HEAP_GET_BLOCK_OWNER((poison_head_t*)multi_heap_get_block_address_impl(block));
+}
+
+multi_heap_handle_t multi_heap_register(void *start, size_t size)
+{
+    if (start != NULL) {
+        memset(start, FREE_FILL_PATTERN, size);
+    }
+    return multi_heap_register_impl(start, size);
+}
+
+static inline void subtract_poison_overhead(size_t *arg) {
+    if (*arg > POISON_OVERHEAD) {
+        *arg -= POISON_OVERHEAD;
+    } else {
+        *arg = 0;
+    }
+}
+
+void multi_heap_get_info(multi_heap_handle_t heap, multi_heap_info_t *info)
+{
+    multi_heap_get_info_impl(heap, info);
+    /* don't count the heap poison head & tail overhead in the allocated bytes size */
+    info->total_allocated_bytes -= info->allocated_blocks * POISON_OVERHEAD;
+    /* trim largest_free_block to account for poison overhead */
+    subtract_poison_overhead(&info->largest_free_block);
+    /* similarly, trim total_free_bytes so there's no suggestion that
+       a block this big may be available. */
+    subtract_poison_overhead(&info->total_free_bytes);
+    subtract_poison_overhead(&info->minimum_free_bytes);
+}
+
+size_t multi_heap_free_size(multi_heap_handle_t heap)
+{
+    size_t r = multi_heap_free_size_impl(heap);
+    subtract_poison_overhead(&r);
+    return r;
+}
+
+size_t multi_heap_minimum_free_size(multi_heap_handle_t heap)
+{
+    size_t r = multi_heap_minimum_free_size_impl(heap);
+    subtract_poison_overhead(&r);
+    return r;
+}
+
+/* Internal hooks used by multi_heap to manage poisoning, while keeping some modularity */
+
+bool multi_heap_internal_check_block_poisoning(void *start, size_t size, bool is_free, bool print_errors)
+{
+    if (is_free) {
+#ifdef SLOW
+        return verify_fill_pattern(start, size, print_errors, true, false);
+#else
+        return true; /* can only verify empty blocks in SLOW mode */
+#endif
+    } else {
+        void *data = (void *)((intptr_t)start + sizeof(poison_head_t));
+        poison_head_t *head = verify_allocated_region(data, print_errors);
+        if (head != NULL && head->alloc_size > size - POISON_OVERHEAD) {
+            /* block can be bigger than alloc_size, for reasons of alignment & fragmentation,
+               but block can never be smaller than head->alloc_size... */
+            if (print_errors) {
+                MULTI_HEAP_STDERR_PRINTF("CORRUPT HEAP: Size at %p expected <=0x%08x got 0x%08x\n", &head->alloc_size,
+                       size - POISON_OVERHEAD, head->alloc_size);
+            }
+            return false;
+        }
+        return head != NULL;
+    }
+}
+
+void multi_heap_internal_poison_fill_region(void *start, size_t size, bool is_free)
+{
+    memset(start, is_free ? FREE_FILL_PATTERN : MALLOC_FILL_PATTERN, size);
+}
+
+#else // !MULTI_HEAP_POISONING
+
+#ifdef MULTI_HEAP_POISONING_SLOW
+#error "MULTI_HEAP_POISONING_SLOW requires MULTI_HEAP_POISONING"
+#endif
+
+#endif  // MULTI_HEAP_POISONING
diff --git a/cpu/esp32/vendor/esp-idf/include/driver/gpio.h b/cpu/esp32/vendor/esp-idf/include/driver/gpio.h
new file mode 100644
index 0000000000000000000000000000000000000000..609808817932c0682fe923f73a8e65493aa0b8d1
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/driver/gpio.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2018 Gunar Schorcht
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+/* This file is just a mapper for source code compatibility with ESP-IDF */
+
+#ifndef DRIVER_GPIO_H
+#define DRIVER_GPIO_H
+
+#ifndef DOXYGEN
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* the order of these includes is important */
+#include "periph_conf.h"
+#include "gpio_arch.h"
+
+#define GPIO_NUM_MAX        (40)
+
+#define gpio_num_t          gpio_t
+#define gpio_pull_mode_t    uint32_t
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DOXYGEN */
+#endif /* DRIVER_GPIO_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/driver/spi_common.h b/cpu/esp32/vendor/esp-idf/include/driver/spi_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..b3fd68de363d7023516572e8bb910fa168a1c07c
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/driver/spi_common.h
@@ -0,0 +1,290 @@
+// 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.
+
+
+#ifndef DRIVER_SPI_COMMON_H
+#define DRIVER_SPI_COMMON_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+#include "rom/lldesc.h"
+#include "soc/spi_periph.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+//Maximum amount of bytes that can be put in one DMA descriptor
+#define SPI_MAX_DMA_LEN (4096-4)
+
+
+/**
+ * @brief Enum with the three SPI peripherals that are software-accessible in it
+ */
+typedef enum {
+    SPI_HOST=0,                     ///< SPI1, SPI
+    HSPI_HOST=1,                    ///< SPI2, HSPI
+    VSPI_HOST=2                     ///< SPI3, VSPI
+} spi_host_device_t;
+
+/**
+ * @brief This is a configuration structure for a SPI bus.
+ *
+ * You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the
+ * GPIO matrix to route the signals. An exception is made when all signals either can be routed through
+ * the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds.
+ *
+ * @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized.
+ */
+typedef struct {
+    int mosi_io_num;                ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
+    int miso_io_num;                ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
+    int sclk_io_num;                ///< GPIO pin for Spi CLocK signal, or -1 if not used.
+    int quadwp_io_num;              ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used.
+    int quadhd_io_num;              ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used.
+    int max_transfer_sz;            ///< Maximum transfer size, in bytes. Defaults to 4094 if 0.
+    uint32_t flags;                 ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
+} spi_bus_config_t;
+
+
+/**
+ * @brief Try to claim a SPI peripheral
+ *
+ * Call this if your driver wants to manage a SPI peripheral.
+ *
+ * @param host Peripheral to claim
+ * @return True if peripheral is claimed successfully; false if peripheral already is claimed.
+ */
+bool spicommon_periph_claim(spi_host_device_t host);
+
+/**
+ * @brief Return the SPI peripheral so another driver can claim it.
+ *
+ * @param host Peripheral to return
+ * @return True if peripheral is returned successfully; false if peripheral was free to claim already.
+ */
+bool spicommon_periph_free(spi_host_device_t host);
+
+/**
+ * @brief Try to claim a SPI DMA channel
+ *
+ *  Call this if your driver wants to use SPI with a DMA channnel.
+ *
+ * @param dma_chan channel to claim
+ *
+ * @return True if success; false otherwise.
+ */
+bool spicommon_dma_chan_claim(int dma_chan);
+
+/**
+ * @brief Return the SPI DMA channel so other driver can claim it, or just to power down DMA.
+ *
+ * @param dma_chan channel to return
+ *
+ * @return True if success; false otherwise.
+ */
+bool spicommon_dma_chan_free(int dma_chan);
+
+#define SPICOMMON_BUSFLAG_SLAVE         0          ///< Initialize I/O in slave mode
+#define SPICOMMON_BUSFLAG_MASTER        (1<<0)     ///< Initialize I/O in master mode
+#define SPICOMMON_BUSFLAG_NATIVE_PINS   (1<<1)     ///< Check using iomux pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix.
+#define SPICOMMON_BUSFLAG_SCLK          (1<<2)     ///< Check existing of SCLK pin. Or indicates CLK line initialized.
+#define SPICOMMON_BUSFLAG_MISO          (1<<3)     ///< Check existing of MISO pin. Or indicates MISO line initialized.
+#define SPICOMMON_BUSFLAG_MOSI          (1<<4)     ///< Check existing of MOSI pin. Or indicates CLK line initialized.
+#define SPICOMMON_BUSFLAG_DUAL          (1<<5)     ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode.
+#define SPICOMMON_BUSFLAG_WPHD          (1<<6)     ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized.
+#define SPICOMMON_BUSFLAG_QUAD          (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD)     ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode.
+
+/**
+ * @brief Connect a SPI peripheral to GPIO pins
+ *
+ * This routine is used to connect a SPI peripheral to the IO-pads and DMA channel given in
+ * the arguments. Depending on the IO-pads requested, the routing is done either using the
+ * IO_mux or using the GPIO matrix.
+ *
+ * @param host SPI peripheral to be routed
+ * @param bus_config Pointer to a spi_bus_config struct detailing the GPIO pins
+ * @param dma_chan DMA-channel (1 or 2) to use, or 0 for no DMA.
+ * @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions:
+ *              - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode
+ *              - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode
+ *              - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: Pins set should match the iomux pins of the controller.
+ *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``:
+ *                  Make sure SCLK/MISO/MOSI is/are set to a valid GPIO. Also check output capability according to the mode.
+ *              - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable.
+ *              - ``SPICOMMON_BUSFLAG_WPHD`` Make sure WP and HD are set to valid output GPIOs.
+ *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
+ * @param[out] flags_o A SPICOMMON_BUSFLAG_* flag combination of bus abilities will be written to this address.
+ *              Leave to NULL if not needed.
+ *              - ``SPICOMMON_BUSFLAG_NATIVE_PINS``: The bus is connected to iomux pins.
+ *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: The bus has
+ *                  CLK/MISO/MOSI connected.
+ *              - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode.
+ *              - ``SPICOMMON_BUSFLAG_WPHD`` The bus has WP and HD connected.
+ *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
+ * @return
+ *         - ESP_ERR_INVALID_ARG   if parameter is invalid
+ *         - ESP_OK                on success
+ */
+esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, int dma_chan, uint32_t flags, uint32_t *flags_o);
+
+/**
+ * @brief Free the IO used by a SPI peripheral
+ * @deprecated Use spicommon_bus_free_io_cfg instead.
+ *
+ * @param host SPI peripheral to be freed
+ *
+ * @return
+ *         - ESP_ERR_INVALID_ARG   if parameter is invalid
+ *         - ESP_OK                on success
+ */
+esp_err_t spicommon_bus_free_io(spi_host_device_t host) __attribute__((deprecated));
+
+/**
+ * @brief Free the IO used by a SPI peripheral
+ *
+ * @param bus_cfg Bus config struct which defines which pins to be used.
+ *
+ * @return
+ *         - ESP_ERR_INVALID_ARG   if parameter is invalid
+ *         - ESP_OK                on success
+ */
+esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg);
+
+/**
+ * @brief Initialize a Chip Select pin for a specific SPI peripheral
+ *
+ *
+ * @param host SPI peripheral
+ * @param cs_io_num GPIO pin to route
+ * @param cs_num CS id to route
+ * @param force_gpio_matrix If true, CS will always be routed through the GPIO matrix. If false,
+ *                          if the GPIO number allows it, the routing will happen through the IO_mux.
+ */
+
+void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix);
+
+/**
+ * @brief Free a chip select line
+ * @deprecated Use spicommon_cs_io, which inputs the gpio num rather than the cs id instead.
+ *
+ * @param host SPI peripheral
+ * @param cs_num CS id to free
+ */
+void spicommon_cs_free(spi_host_device_t host, int cs_num) __attribute__((deprecated));
+
+/**
+ * @brief Free a chip select line
+ *
+ * @param cs_gpio_num CS gpio num to free
+ */
+void spicommon_cs_free_io(int cs_gpio_num);
+
+/**
+ * @brief Setup a DMA link chain
+ *
+ * This routine will set up a chain of linked DMA descriptors in the array pointed to by
+ * ``dmadesc``. Enough DMA descriptors will be used to fit the buffer of ``len`` bytes in, and the
+ * descriptors will point to the corresponding positions in ``buffer`` and linked together. The
+ * end result is that feeding ``dmadesc[0]`` into DMA hardware results in the entirety ``len`` bytes
+ * of ``data`` being read or written.
+ *
+ * @param dmadesc Pointer to array of DMA descriptors big enough to be able to convey ``len`` bytes
+ * @param len Length of buffer
+ * @param data Data buffer to use for DMA transfer
+ * @param isrx True if data is to be written into ``data``, false if it's to be read from ``data``.
+ */
+void spicommon_setup_dma_desc_links(lldesc_t *dmadesc, int len, const uint8_t *data, bool isrx);
+
+/**
+ * @brief Get the position of the hardware registers for a specific SPI host
+ *
+ * @param host The SPI host
+ *
+ * @return A register descriptor stuct pointer, pointed at the hardware registers
+ */
+spi_dev_t *spicommon_hw_for_host(spi_host_device_t host);
+
+/**
+ * @brief Get the IRQ source for a specific SPI host
+ *
+ * @param host The SPI host
+ *
+ * @return The hosts IRQ source
+ */
+int spicommon_irqsource_for_host(spi_host_device_t host);
+
+/**
+ * Callback, to be called when a DMA engine reset is completed
+*/
+typedef void(*dmaworkaround_cb_t)(void *arg);
+
+
+/**
+ * @brief Request a reset for a certain DMA channel
+ *
+ * @note In some (well-defined) cases in the ESP32 (at least rev v.0 and v.1), a SPI DMA channel will get confused. This can be remedied
+ * by resetting the SPI DMA hardware in case this happens. Unfortunately, the reset knob used for thsi will reset _both_ DMA channels, and
+ * as such can only done safely when both DMA channels are idle. These functions coordinate this.
+ *
+ * Essentially, when a reset is needed, a driver can request this using spicommon_dmaworkaround_req_reset. This is supposed to be called
+ * with an user-supplied function as an argument. If both DMA channels are idle, this call will reset the DMA subsystem and return true.
+ * If the other DMA channel is still busy, it will return false; as soon as the other DMA channel is done, however, it will reset the
+ * DMA subsystem and call the callback. The callback is then supposed to be used to continue the SPI drivers activity.
+ *
+ * @param dmachan DMA channel associated with the SPI host that needs a reset
+ * @param cb Callback to call in case DMA channel cannot be reset immediately
+ * @param arg Argument to the callback
+ *
+ * @return True when a DMA reset could be executed immediately. False when it could not; in this
+ *         case the callback will be called with the specified argument when the logic can execute
+ *         a reset, after that reset.
+ */
+bool spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg);
+
+
+/**
+ * @brief Check if a DMA reset is requested but has not completed yet
+ *
+ * @return True when a DMA reset is requested but hasn't completed yet. False otherwise.
+ */
+bool spicommon_dmaworkaround_reset_in_progress(void);
+
+
+/**
+ * @brief Mark a DMA channel as idle.
+ *
+ * A call to this function tells the workaround logic that this channel will
+ * not be affected by a global SPI DMA reset.
+ */
+void spicommon_dmaworkaround_idle(int dmachan);
+
+/**
+ * @brief Mark a DMA channel as active.
+ *
+ * A call to this function tells the workaround logic that this channel will
+ * be affected by a global SPI DMA reset, and a reset like that should not be attempted.
+ */
+void spicommon_dmaworkaround_transfer_active(int dmachan);
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DRIVER_SPI_COMMON_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/driver/touch_pad.h b/cpu/esp32/vendor/esp-idf/include/driver/touch_pad.h
new file mode 100644
index 0000000000000000000000000000000000000000..c9ce63c82764f40165c2b79ebfbbf12ac1495e63
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/driver/touch_pad.h
@@ -0,0 +1,559 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef DRIVER_TOUCH_PAD_H
+#define DRIVER_TOUCH_PAD_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "esp_intr.h"
+#include "esp_err.h"
+#include "esp_intr_alloc.h"
+#include "soc/touch_channel.h"
+
+typedef enum {
+    TOUCH_PAD_NUM0 = 0, /*!< Touch pad channel 0 is GPIO4 */
+    TOUCH_PAD_NUM1,     /*!< Touch pad channel 1 is GPIO0 */
+    TOUCH_PAD_NUM2,     /*!< Touch pad channel 2 is GPIO2 */
+    TOUCH_PAD_NUM3,     /*!< Touch pad channel 3 is GPIO15*/
+    TOUCH_PAD_NUM4,     /*!< Touch pad channel 4 is GPIO13*/
+    TOUCH_PAD_NUM5,     /*!< Touch pad channel 5 is GPIO12*/
+    TOUCH_PAD_NUM6,     /*!< Touch pad channel 6 is GPIO14*/
+    TOUCH_PAD_NUM7,     /*!< Touch pad channel 7 is GPIO27*/
+    TOUCH_PAD_NUM8,     /*!< Touch pad channel 8 is GPIO33*/
+    TOUCH_PAD_NUM9,     /*!< Touch pad channel 9 is GPIO32*/
+    TOUCH_PAD_MAX,
+} touch_pad_t;
+
+typedef enum {
+    TOUCH_HVOLT_KEEP = -1, /*!<Touch sensor high reference voltage, no change  */
+    TOUCH_HVOLT_2V4 = 0,   /*!<Touch sensor high reference voltage, 2.4V  */
+    TOUCH_HVOLT_2V5,       /*!<Touch sensor high reference voltage, 2.5V  */
+    TOUCH_HVOLT_2V6,       /*!<Touch sensor high reference voltage, 2.6V  */
+    TOUCH_HVOLT_2V7,       /*!<Touch sensor high reference voltage, 2.7V  */
+    TOUCH_HVOLT_MAX,
+} touch_high_volt_t;
+
+typedef enum {
+    TOUCH_LVOLT_KEEP = -1, /*!<Touch sensor low reference voltage, no change  */
+    TOUCH_LVOLT_0V5 = 0,   /*!<Touch sensor low reference voltage, 0.5V  */
+    TOUCH_LVOLT_0V6,       /*!<Touch sensor low reference voltage, 0.6V  */
+    TOUCH_LVOLT_0V7,       /*!<Touch sensor low reference voltage, 0.7V  */
+    TOUCH_LVOLT_0V8,       /*!<Touch sensor low reference voltage, 0.8V  */
+    TOUCH_LVOLT_MAX,
+} touch_low_volt_t;
+
+typedef enum {
+    TOUCH_HVOLT_ATTEN_KEEP = -1,  /*!<Touch sensor high reference voltage attenuation, no change  */
+    TOUCH_HVOLT_ATTEN_1V5 = 0,    /*!<Touch sensor high reference voltage attenuation, 1.5V attenuation  */
+    TOUCH_HVOLT_ATTEN_1V,         /*!<Touch sensor high reference voltage attenuation, 1.0V attenuation  */
+    TOUCH_HVOLT_ATTEN_0V5,        /*!<Touch sensor high reference voltage attenuation, 0.5V attenuation  */
+    TOUCH_HVOLT_ATTEN_0V,         /*!<Touch sensor high reference voltage attenuation,   0V attenuation  */
+    TOUCH_HVOLT_ATTEN_MAX,
+} touch_volt_atten_t;
+
+typedef enum {
+    TOUCH_PAD_SLOPE_0 = 0,       /*!<Touch sensor charge / discharge speed, always zero  */
+    TOUCH_PAD_SLOPE_1 = 1,       /*!<Touch sensor charge / discharge speed, slowest  */
+    TOUCH_PAD_SLOPE_2 = 2,       /*!<Touch sensor charge / discharge speed */
+    TOUCH_PAD_SLOPE_3 = 3,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_4 = 4,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_5 = 5,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_6 = 6,       /*!<Touch sensor charge / discharge speed  */
+    TOUCH_PAD_SLOPE_7 = 7,       /*!<Touch sensor charge / discharge speed, fast  */
+    TOUCH_PAD_SLOPE_MAX,
+} touch_cnt_slope_t;
+
+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.*/
+    TOUCH_TRIGGER_MAX,
+} touch_trigger_mode_t;
+
+typedef enum {
+    TOUCH_TRIGGER_SOURCE_BOTH = 0,  /*!< wakeup interrupt is generated if both SET1 and SET2 are "touched"*/
+    TOUCH_TRIGGER_SOURCE_SET1 = 1,  /*!< wakeup interrupt is generated if SET1 is "touched"*/
+    TOUCH_TRIGGER_SOURCE_MAX,
+} touch_trigger_src_t;
+
+typedef enum {
+    TOUCH_PAD_TIE_OPT_LOW = 0,    /*!<Initial level of charging voltage, low level */
+    TOUCH_PAD_TIE_OPT_HIGH = 1,   /*!<Initial level of charging voltage, high level */
+    TOUCH_PAD_TIE_OPT_MAX,
+} touch_tie_opt_t;
+
+typedef enum {
+    TOUCH_FSM_MODE_TIMER = 0,   /*!<To start touch FSM by timer */
+    TOUCH_FSM_MODE_SW,          /*!<To start touch FSM by software trigger */
+    TOUCH_FSM_MODE_MAX,
+} touch_fsm_mode_t;
+
+
+typedef intr_handle_t touch_isr_handle_t;
+
+#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 */
+#define TOUCH_FSM_MODE_DEFAULT          (TOUCH_FSM_MODE_SW)  /*!<The touch FSM my be started by the software or timer */
+#define TOUCH_TRIGGER_MODE_DEFAULT      (TOUCH_TRIGGER_BELOW)   /*!<Interrupts can be triggered if sensor value gets below or above threshold */
+#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)
+
+/**
+ * @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'.
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_FAIL Touch pad init error
+ */
+esp_err_t touch_pad_init(void);
+
+/**
+ * @brief Un-install touch pad driver.
+ * @return
+ *     - ESP_OK   Success
+ *     - ESP_FAIL Touch pad driver not initialized
+ */
+esp_err_t touch_pad_deinit(void);
+
+/**
+ * @brief Configure touch pad interrupt threshold.
+ *
+ * @note  If FSM mode is set to TOUCH_FSM_MODE_TIMER, this function will be blocked for one measurement cycle and wait for data to be valid.
+ *
+ * @param touch_num touch pad index
+ * @param threshold interrupt threshold,
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG if argument wrong
+ *     - ESP_FAIL if touch pad not initialized
+ */
+esp_err_t touch_pad_config(touch_pad_t touch_num, uint16_t threshold);
+
+/**
+ * @brief get touch sensor counter value.
+ *        Each touch sensor has a counter to count the number of charge/discharge cycles.
+ *        When the pad is not 'touched', we can get a number of the counter.
+ *        When the pad is 'touched', the value in counter will get smaller because of the larger equivalent capacitance.
+ *
+ * @note This API requests hardware measurement once. If IIR filter mode is enabled,
+ *       please use 'touch_pad_read_raw_data' interface instead.
+ *
+ * @param touch_num touch pad index
+ * @param touch_value pointer to accept touch sensor value
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Touch pad parameter error
+ *     - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0.
+ *     - ESP_FAIL Touch pad not initialized
+ */
+esp_err_t touch_pad_read(touch_pad_t touch_num, uint16_t * touch_value);
+
+/**
+ * @brief get filtered touch sensor counter value by IIR filter.
+ *
+ * @note touch_pad_filter_start has to be called before calling touch_pad_read_filtered.
+ *       This function can be called from ISR
+ *
+ * @param touch_num touch pad index
+ * @param touch_value pointer to accept touch sensor value
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Touch pad parameter error
+ *     - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0.
+ *     - ESP_FAIL Touch pad not initialized
+ */
+esp_err_t touch_pad_read_filtered(touch_pad_t touch_num, uint16_t *touch_value);
+
+/**
+ * @brief get raw data (touch sensor counter value) from IIR filter process.
+ *        Need not request hardware measurements.
+ *
+ * @note touch_pad_filter_start has to be called before calling touch_pad_read_raw_data.
+ *       This function can be called from ISR
+ *
+ * @param touch_num touch pad index
+ * @param touch_value pointer to accept touch sensor value
+ *
+ * @return
+ *     - ESP_OK Success
+ *     - ESP_ERR_INVALID_ARG Touch pad parameter error
+ *     - ESP_ERR_INVALID_STATE This touch pad hardware connection is error, the value of "touch_value" is 0.
+ *     - ESP_FAIL Touch pad not initialized
+ */
+esp_err_t touch_pad_read_raw_data(touch_pad_t touch_num, uint16_t *touch_value);
+
+/**
+  * @brief Callback function that is called after each IIR filter calculation.
+  * @note This callback is called in timer task in each filtering cycle.
+  * @note This callback should not be blocked.
+  * @param raw_value  The latest raw data(touch sensor counter value) that
+  *        points to all channels(raw_value[0..TOUCH_PAD_MAX-1]).
+  * @param filtered_value  The latest IIR filtered data(calculated from raw data) that
+  *        points to all channels(filtered_value[0..TOUCH_PAD_MAX-1]).
+  *
+  */
+typedef void (* filter_cb_t)(uint16_t *raw_value, uint16_t *filtered_value);
+
+/**
+ * @brief Register the callback function that is called after each IIR filter calculation.
+ * @note The 'read_cb' callback is called in timer task in each filtering cycle.
+ * @param read_cb  Pointer to filtered callback function.
+ *                 If the argument passed in is NULL, the callback will stop.
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_ARG set error
+ */
+esp_err_t touch_pad_set_filter_read_cb(filter_cb_t read_cb);
+
+/**
+ * @brief   Register touch-pad ISR,
+ * @note Deprecated function, users should replace this with touch_pad_isr_register,
+ *       because RTC modules share a same interrupt index.
+ * @param fn  Pointer to ISR handler
+ * @param arg  Parameter for ISR
+ * @param unused Reserved, not used
+ * @param handle_unused Reserved, not used
+ * @return
+ *     - ESP_OK Success ;
+ *     - ESP_ERR_INVALID_ARG GPIO error
+ *     - ESP_ERR_NO_MEM No memory
+ */
+esp_err_t touch_pad_isr_handler_register(void(*fn)(void *), void *arg, int unused, intr_handle_t *handle_unused) __attribute__ ((deprecated));
+
+/**
+ * @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);
+
+/**
+ * @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.
+ *                     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_cycle The duration of the touch sensor measurement.
+ *                   t_meas = meas_cycle / 8M, the maximum measure time is 0xffff / 8M = 8.19 ms
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_set_meas_time(uint16_t sleep_cycle, uint16_t meas_cycle);
+
+/**
+ * @brief Get touch sensor measurement and sleep time
+ * @param sleep_cycle  Pointer to accept sleep cycle number
+ * @param meas_cycle Pointer to accept measurement cycle count.
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_meas_time(uint16_t *sleep_cycle, uint16_t *meas_cycle);
+
+/**
+ * @brief Set touch sensor reference voltage, if the voltage gap between high and low reference voltage get less,
+ *        the charging and discharging time would be faster, accordingly, the counter value would be larger.
+ *        In the case of detecting very slight change of capacitance, we can narrow down the gap so as to increase
+ *        the sensitivity. On the other hand, narrow voltage gap would also introduce more noise, but we can use a
+ *        software filter to pre-process the counter value.
+ * @param refh the value of DREFH
+ * @param refl the value of DREFL
+ * @param atten the attenuation on DREFH
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_voltage(touch_high_volt_t refh, touch_low_volt_t refl, touch_volt_atten_t atten);
+
+/**
+ * @brief Get touch sensor reference voltage,
+ * @param refh pointer to accept DREFH value
+ * @param refl pointer to accept DREFL value
+ * @param atten pointer to accept the attenuation on DREFH
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_voltage(touch_high_volt_t *refh, touch_low_volt_t *refl, touch_volt_atten_t *atten);
+
+/**
+ * @brief Set touch sensor charge/discharge speed for each pad.
+ *        If the slope is 0, the counter would always be zero.
+ *        If the slope is 1, the charging and discharging would be slow, accordingly, the counter value would be small.
+ *        If the slope is set 7, which is the maximum value, the charging and discharging would be fast, accordingly, the
+ *        counter value would be larger.
+ * @param touch_num touch pad index
+ * @param slope touch pad charge/discharge speed
+ * @param opt the initial voltage
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t slope, touch_tie_opt_t opt);
+
+/**
+ * @brief Get touch sensor charge/discharge speed for each pad
+ * @param touch_num touch pad index
+ * @param slope pointer to accept touch pad charge/discharge slope
+ * @param opt pointer to accept the initial voltage
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_get_cnt_mode(touch_pad_t touch_num, touch_cnt_slope_t *slope, touch_tie_opt_t *opt);
+
+/**
+ * @brief Initialize touch pad GPIO
+ * @param touch_num touch pad index
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+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
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_sw_start(void);
+
+/**
+ * @brief Set touch sensor interrupt threshold
+ * @param touch_num touch pad index
+ * @param threshold threshold of touchpad count, refer to touch_pad_set_trigger_mode to see how to set trigger mode.
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_thresh(touch_pad_t touch_num, uint16_t threshold);
+
+/**
+ * @brief Get touch sensor interrupt 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, uint16_t *threshold);
+
+/**
+ * @brief Set touch sensor interrupt trigger mode.
+ *        Interrupt can be triggered either when counter result is less than
+ *        threshold or when counter result is more than threshold.
+ * @param mode touch sensor interrupt trigger mode
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_trigger_mode(touch_trigger_mode_t mode);
+
+/**
+ * @brief Get touch sensor interrupt trigger mode
+ * @param mode pointer to accept touch sensor interrupt trigger mode
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_trigger_mode(touch_trigger_mode_t *mode);
+
+/**
+ * @brief Set touch sensor interrupt trigger source. There are two sets of touch signals.
+ *        Set1 and set2 can be mapped to several touch signals. Either set will be triggered
+ *        if at least one of its touch signal is 'touched'. The interrupt can be configured to be generated
+ *        if set1 is triggered, or only if both sets are triggered.
+ * @param src touch sensor interrupt trigger source
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_trigger_source(touch_trigger_src_t src);
+
+/**
+ * @brief Get touch sensor interrupt trigger source
+ * @param src pointer to accept touch sensor interrupt trigger source
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_trigger_source(touch_trigger_src_t *src);
+
+/**
+ * @brief Set touch sensor group mask.
+ *        Touch pad module has two sets of signals, 'Touched' signal is triggered only if
+ *        at least one of touch pad in this group is "touched".
+ *        This function will set the register bits according to the given bitmask.
+ * @param set1_mask bitmask of touch sensor signal group1, it's a 10-bit value
+ * @param set2_mask bitmask of touch sensor signal group2, it's a 10-bit value
+ * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_set_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask);
+
+/**
+ * @brief Get touch sensor group mask.
+ * @param set1_mask pointer to accept bitmask of touch sensor signal group1, it's a 10-bit value
+ * @param set2_mask pointer to accept bitmask of touch sensor signal group2, it's a 10-bit value
+ * @param en_mask pointer to accept bitmask of touch sensor work enable, it's a 10-bit value
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_get_group_mask(uint16_t *set1_mask, uint16_t *set2_mask, uint16_t *en_mask);
+
+/**
+ * @brief Clear touch sensor group mask.
+ *        Touch pad module has two sets of signals, Interrupt is triggered only if
+ *        at least one of touch pad in this group is "touched".
+ *        This function will clear the register bits according to the given bitmask.
+ * @param set1_mask bitmask touch sensor signal group1, it's a 10-bit value
+ * @param set2_mask bitmask touch sensor signal group2, it's a 10-bit value
+ * @param en_mask bitmask of touch sensor work enable, it's a 10-bit value
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if argument is wrong
+ */
+esp_err_t touch_pad_clear_group_mask(uint16_t set1_mask, uint16_t set2_mask, uint16_t en_mask);
+
+/**
+ * @brief To clear the touch status register, usually use this function in touch ISR to clear status.
+ * @return
+ *      - ESP_OK on success
+ */
+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
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_intr_enable(void);
+
+/**
+ * @brief To disable touch pad interrupt
+ * @return
+ *      - ESP_OK on success
+ */
+esp_err_t touch_pad_intr_disable(void);
+
+/**
+ * @brief set touch pad filter calibration period, in ms.
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @param new_period_ms filter period, in ms
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ *      - ESP_ERR_INVALID_ARG parameter error
+ */
+esp_err_t touch_pad_set_filter_period(uint32_t new_period_ms);
+
+/**
+ * @brief get touch pad filter calibration period, in ms
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @param p_period_ms pointer to accept period
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ *      - ESP_ERR_INVALID_ARG parameter error
+ */
+esp_err_t touch_pad_get_filter_period(uint32_t* p_period_ms);
+
+/**
+ * @brief start touch pad filter function
+ *      This API will start a filter to process the noise in order to prevent false triggering
+ *      when detecting slight change of capacitance.
+ *      Need to call touch_pad_filter_start before all touch filter APIs
+ *
+ * @note This filter uses FreeRTOS timer, which is dispatched from a task with
+ *       priority 1 by default on CPU 0. So if some application task with higher priority
+ *       takes a lot of CPU0 time, then the quality of data obtained from this filter will be affected.
+ *       You can adjust FreeRTOS timer task priority in menuconfig.
+ * @param filter_period_ms filter calibration period, in ms
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_ARG parameter error
+ *      - ESP_ERR_NO_MEM No memory for driver
+ *      - ESP_ERR_INVALID_STATE driver state error
+ */
+esp_err_t touch_pad_filter_start(uint32_t filter_period_ms);
+
+/**
+ * @brief stop touch pad filter function
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ */
+esp_err_t touch_pad_filter_stop(void);
+
+/**
+ * @brief delete touch pad filter driver and release the memory
+ *        Need to call touch_pad_filter_start before all touch filter APIs
+ * @return
+ *      - ESP_OK Success
+ *      - ESP_ERR_INVALID_STATE driver state error
+ */
+esp_err_t touch_pad_filter_delete(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DRIVER_TOUCH_PAD_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_clk.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_clk.h
new file mode 100644
index 0000000000000000000000000000000000000000..c7209ad074d4709e438f30712160b1268f6d6da2
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_clk.h
@@ -0,0 +1,86 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_CLK_H
+#define ESP32_ESP_CLK_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file esp_clk.h
+ *
+ * This file contains declarations of clock related functions.
+ */
+
+/**
+ * @brief Get the calibration value of RTC slow clock
+ *
+ * The value is in the same format as returned by rtc_clk_cal (microseconds,
+ * in Q13.19 fixed-point format).
+ *
+ * @return the calibration value obtained using rtc_clk_cal, at startup time
+ */
+uint32_t esp_clk_slowclk_cal_get(void);
+
+/**
+ * @brief Update the calibration value of RTC slow clock
+ *
+ * The value has to be in the same format as returned by rtc_clk_cal (microseconds,
+ * in Q13.19 fixed-point format).
+ * This value is used by timekeeping functions (such as gettimeofday) to
+ * calculate current time based on RTC counter value.
+ * @param value calibration value obtained using rtc_clk_cal
+ */
+void esp_clk_slowclk_cal_set(uint32_t value);
+
+/**
+ * @brief Return current CPU clock frequency
+ * When frequency switching is performed, this frequency may change.
+ * However it is guaranteed that the frequency never changes with a critical
+ * section.
+ *
+ * @return CPU clock frequency, in Hz
+ */
+int esp_clk_cpu_freq(void);
+
+/**
+ * @brief Return current APB clock frequency
+ *
+ * When frequency switching is performed, this frequency may change.
+ * However it is guaranteed that the frequency never changes with a critical
+ * section.
+ *
+ * @return APB clock frequency, in Hz
+ */
+int esp_clk_apb_freq(void);
+
+
+/**
+ * @brief Read value of RTC counter, converting it to microseconds
+ * @attention The value returned by this function may change abruptly when
+ * calibration value of RTC counter is updated via esp_clk_slowclk_cal_set
+ * function. This should not happen unless application calls esp_clk_slowclk_cal_set.
+ * In ESP-IDF, esp_clk_slowclk_cal_set is only called in startup code.
+ *
+ * @return Value or RTC counter, expressed in microseconds
+ */
+uint64_t esp_clk_rtc_time(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_CLK_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_event.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_event.h
new file mode 100644
index 0000000000000000000000000000000000000000..9d3aee56b6fda00659d9f0e7c41145fd2cec9f8b
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_event.h
@@ -0,0 +1,188 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_EVENT_H
+#define ESP32_ESP_EVENT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_err.h"
+#include "esp_wifi_types.h"
+#include "tcpip_adapter.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    SYSTEM_EVENT_WIFI_READY = 0,           /**< ESP32 WiFi ready */
+    SYSTEM_EVENT_SCAN_DONE,                /**< ESP32 finish scanning AP */
+    SYSTEM_EVENT_STA_START,                /**< ESP32 station start */
+    SYSTEM_EVENT_STA_STOP,                 /**< ESP32 station stop */
+    SYSTEM_EVENT_STA_CONNECTED,            /**< ESP32 station connected to AP */
+    SYSTEM_EVENT_STA_DISCONNECTED,         /**< ESP32 station disconnected from AP */
+    SYSTEM_EVENT_STA_AUTHMODE_CHANGE,      /**< the auth mode of AP connected by ESP32 station changed */
+    SYSTEM_EVENT_STA_GOT_IP,               /**< ESP32 station got IP from connected AP */
+    SYSTEM_EVENT_STA_LOST_IP,              /**< ESP32 station lost IP and the IP is reset to 0 */
+    SYSTEM_EVENT_STA_WPS_ER_SUCCESS,       /**< ESP32 station wps succeeds in enrollee mode */
+    SYSTEM_EVENT_STA_WPS_ER_FAILED,        /**< ESP32 station wps fails in enrollee mode */
+    SYSTEM_EVENT_STA_WPS_ER_TIMEOUT,       /**< ESP32 station wps timeout in enrollee mode */
+    SYSTEM_EVENT_STA_WPS_ER_PIN,           /**< ESP32 station wps pin code in enrollee mode */
+    SYSTEM_EVENT_AP_START,                 /**< ESP32 soft-AP start */
+    SYSTEM_EVENT_AP_STOP,                  /**< ESP32 soft-AP stop */
+    SYSTEM_EVENT_AP_STACONNECTED,          /**< a station connected to ESP32 soft-AP */
+    SYSTEM_EVENT_AP_STADISCONNECTED,       /**< a station disconnected from ESP32 soft-AP */
+    SYSTEM_EVENT_AP_STAIPASSIGNED,         /**< ESP32 soft-AP assign an IP to a connected station */
+    SYSTEM_EVENT_AP_PROBEREQRECVED,        /**< Receive probe request packet in soft-AP interface */
+    SYSTEM_EVENT_GOT_IP6,                  /**< ESP32 station or ap or ethernet interface v6IP addr is preferred */
+    SYSTEM_EVENT_ETH_START,                /**< ESP32 ethernet start */
+    SYSTEM_EVENT_ETH_STOP,                 /**< ESP32 ethernet stop */
+    SYSTEM_EVENT_ETH_CONNECTED,            /**< ESP32 ethernet phy link up */
+    SYSTEM_EVENT_ETH_DISCONNECTED,         /**< ESP32 ethernet phy link down */
+    SYSTEM_EVENT_ETH_GOT_IP,               /**< ESP32 ethernet got IP from connected AP */
+    SYSTEM_EVENT_MAX
+} system_event_id_t;
+
+/* add this macro define for compatible with old IDF version */
+#ifndef SYSTEM_EVENT_AP_STA_GOT_IP6
+#define SYSTEM_EVENT_AP_STA_GOT_IP6 SYSTEM_EVENT_GOT_IP6
+#endif
+
+typedef enum {
+    WPS_FAIL_REASON_NORMAL = 0,                   /**< ESP32 WPS normal fail reason */
+    WPS_FAIL_REASON_RECV_M2D,                       /**< ESP32 WPS receive M2D frame */
+    WPS_FAIL_REASON_MAX
+}system_event_sta_wps_fail_reason_t;
+
+typedef struct {
+    uint32_t status;          /**< status of scanning APs */
+    uint8_t  number;
+    uint8_t  scan_id;
+} system_event_sta_scan_done_t;
+
+typedef struct {
+    uint8_t ssid[32];         /**< SSID of connected AP */
+    uint8_t ssid_len;         /**< SSID length of connected AP */
+    uint8_t bssid[6];         /**< BSSID of connected AP*/
+    uint8_t channel;          /**< channel of connected AP*/
+    wifi_auth_mode_t authmode;
+} system_event_sta_connected_t;
+
+typedef struct {
+    uint8_t ssid[32];         /**< SSID of disconnected AP */
+    uint8_t ssid_len;         /**< SSID length of disconnected AP */
+    uint8_t bssid[6];         /**< BSSID of disconnected AP */
+    uint8_t reason;           /**< reason of disconnection */
+} system_event_sta_disconnected_t;
+
+typedef struct {
+    wifi_auth_mode_t old_mode;         /**< the old auth mode of AP */
+    wifi_auth_mode_t new_mode;         /**< the new auth mode of AP */
+} system_event_sta_authmode_change_t;
+
+typedef struct {
+    tcpip_adapter_ip_info_t ip_info;
+    bool ip_changed;
+} system_event_sta_got_ip_t;
+
+typedef struct {
+    uint8_t pin_code[8];         /**< PIN code of station in enrollee mode */
+} system_event_sta_wps_er_pin_t;
+
+typedef struct {
+    tcpip_adapter_if_t if_index;
+    tcpip_adapter_ip6_info_t ip6_info;
+} system_event_got_ip6_t;
+
+typedef struct {
+    uint8_t mac[6];           /**< MAC address of the station connected to ESP32 soft-AP */
+    uint8_t aid;              /**< the aid that ESP32 soft-AP gives to the station connected to  */
+} system_event_ap_staconnected_t;
+
+typedef struct {
+    uint8_t mac[6];           /**< MAC address of the station disconnects to ESP32 soft-AP */
+    uint8_t aid;              /**< the aid that ESP32 soft-AP gave to the station disconnects to  */
+} system_event_ap_stadisconnected_t;
+
+typedef struct {
+    int rssi;                 /**< Received probe request signal strength */
+    uint8_t mac[6];           /**< MAC address of the station which send probe request */
+} system_event_ap_probe_req_rx_t;
+
+typedef union {
+    system_event_sta_connected_t               connected;          /**< ESP32 station connected to AP */
+    system_event_sta_disconnected_t            disconnected;       /**< ESP32 station disconnected to AP */
+    system_event_sta_scan_done_t               scan_done;          /**< ESP32 station scan (APs) done */
+    system_event_sta_authmode_change_t         auth_change;        /**< the auth mode of AP ESP32 station connected to changed */
+    system_event_sta_got_ip_t                  got_ip;             /**< ESP32 station got IP, first time got IP or when IP is changed */
+    system_event_sta_wps_er_pin_t              sta_er_pin;         /**< ESP32 station WPS enrollee mode PIN code received */
+    system_event_sta_wps_fail_reason_t         sta_er_fail_reason;/**< ESP32 station WPS enrollee mode failed reason code received */
+    system_event_ap_staconnected_t             sta_connected;      /**< a station connected to ESP32 soft-AP */
+    system_event_ap_stadisconnected_t          sta_disconnected;   /**< a station disconnected to ESP32 soft-AP */
+    system_event_ap_probe_req_rx_t             ap_probereqrecved;  /**< ESP32 soft-AP receive probe request packet */
+    system_event_got_ip6_t                     got_ip6;            /**< ESP32 station or ap or ethernet ipv6 addr state change to preferred */
+} system_event_info_t;
+
+typedef struct {
+    system_event_id_t     event_id;      /**< event ID */
+    system_event_info_t   event_info;    /**< event information */
+} system_event_t;
+
+typedef esp_err_t (*system_event_handler_t)(system_event_t *event);
+
+/**
+  * @brief  Send a event to event task
+  *
+  * @attention 1. Other task/modules, such as the TCPIP module, can call this API to send an event to event task
+  *
+  * @param  system_event_t * event : event
+  *
+  * @return ESP_OK : succeed
+  * @return others : fail
+  */
+esp_err_t esp_event_send(system_event_t *event);
+
+/**
+  * @brief  Default event handler for system events
+  *
+  * This function performs default handling of system events.
+  * When using esp_event_loop APIs, it is called automatically before invoking the user-provided
+  * callback function.
+  *
+  * Applications which implement a custom event loop must call this function
+  * as part of event processing.
+  *
+  * @param  event pointer to event to be handled
+  * @return ESP_OK if an event was handled successfully
+  */
+esp_err_t esp_event_process_default(system_event_t *event);
+
+/**
+  * @brief  Install default event handlers for Ethernet interface
+  *
+  */
+void esp_event_set_default_eth_handlers(void);
+
+/**
+  * @brief  Install default event handlers for Wi-Fi interfaces (station and AP)
+  *
+  */
+void esp_event_set_default_wifi_handlers(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_EVENT_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_event_loop.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_event_loop.h
new file mode 100644
index 0000000000000000000000000000000000000000..3783664163ca2c198883b87d7d8a6bc6e0615f4a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_event_loop.h
@@ -0,0 +1,81 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_EVENT_LOOP_H
+#define ESP32_ESP_EVENT_LOOP_H
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "esp_err.h"
+#include "esp_event.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+  * @brief  Application specified event callback function
+  *
+  * @param  void *ctx : reserved for user
+  * @param  system_event_t *event : event type defined in this file
+  *
+  * @return ESP_OK : succeed
+  * @return others : fail
+  */
+typedef esp_err_t (*system_event_cb_t)(void *ctx, system_event_t *event);
+
+/**
+  * @brief  Initialize event loop
+  *         Create the event handler and task
+  *
+  * @param  system_event_cb_t cb : application specified event callback, it can be modified by call esp_event_set_cb
+  * @param  void *ctx : reserved for user
+  *
+  * @return ESP_OK : succeed
+  * @return others : fail
+  */
+esp_err_t esp_event_loop_init(system_event_cb_t cb, void *ctx);
+
+/**
+  * @brief  Set application specified event callback function
+  *
+  * @attention 1. If cb is NULL, means application don't need to handle
+  *               If cb is not NULL, it will be call when an event is received, after the default event callback is completed
+  *
+  * @param  system_event_cb_t cb : callback
+  * @param  void *ctx : reserved for user
+  *
+  * @return system_event_cb_t : old callback
+  */
+system_event_cb_t esp_event_loop_set_cb(system_event_cb_t cb, void *ctx);
+
+/**
+  * @brief  Get the queue used by event loop
+  *
+  * @attention : currently this API is used to initialize "q" parameter
+  * of wifi_init structure.
+  *
+  * @return QueueHandle_t : event queue handle
+  */
+QueueHandle_t esp_event_loop_get_queue(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_EVENT_LOOP_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_intr_alloc.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_intr_alloc.h
new file mode 100644
index 0000000000000000000000000000000000000000..3b385909905f83cad9a4e1b59b2880dc3e0c455b
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_intr_alloc.h
@@ -0,0 +1,295 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_INTR_ALLOC_H
+#define ESP32_ESP_INTR_ALLOC_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/** @addtogroup Intr_Alloc
+  * @{
+  */
+
+
+/** @brief Interrupt allocation flags
+ *
+ * These flags can be used to specify which interrupt qualities the
+ * code calling esp_intr_alloc* needs.
+ *
+ */
+
+//Keep the LEVELx values as they are here; they match up with (1<<level)
+#define ESP_INTR_FLAG_LEVEL1        (1<<1)    ///< Accept a Level 1 interrupt vector (lowest priority)
+#define ESP_INTR_FLAG_LEVEL2        (1<<2)    ///< Accept a Level 2 interrupt vector
+#define ESP_INTR_FLAG_LEVEL3        (1<<3)    ///< Accept a Level 3 interrupt vector
+#define ESP_INTR_FLAG_LEVEL4        (1<<4)    ///< Accept a Level 4 interrupt vector
+#define ESP_INTR_FLAG_LEVEL5        (1<<5)    ///< Accept a Level 5 interrupt vector
+#define ESP_INTR_FLAG_LEVEL6        (1<<6)    ///< Accept a Level 6 interrupt vector
+#define ESP_INTR_FLAG_NMI            (1<<7)    ///< Accept a Level 7 interrupt vector (highest priority)
+#define ESP_INTR_FLAG_SHARED        (1<<8)    ///< Interrupt can be shared between ISRs
+#define ESP_INTR_FLAG_EDGE            (1<<9)    ///< Edge-triggered interrupt
+#define ESP_INTR_FLAG_IRAM            (1<<10)    ///< ISR can be called if cache is disabled
+#define ESP_INTR_FLAG_INTRDISABLED    (1<<11)    ///< Return with this interrupt disabled
+
+#define ESP_INTR_FLAG_LOWMED    (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3) ///< Low and medium prio interrupts. These can be handled in C.
+#define ESP_INTR_FLAG_HIGH        (ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6|ESP_INTR_FLAG_NMI) ///< High level interrupts. Need to be handled in assembly.
+
+#define ESP_INTR_FLAG_LEVELMASK    (ESP_INTR_FLAG_LEVEL1|ESP_INTR_FLAG_LEVEL2|ESP_INTR_FLAG_LEVEL3| \
+                                 ESP_INTR_FLAG_LEVEL4|ESP_INTR_FLAG_LEVEL5|ESP_INTR_FLAG_LEVEL6| \
+                                 ESP_INTR_FLAG_NMI) ///< Mask for all level flags
+/**@}*/
+
+
+/** @addtogroup Intr_Alloc_Pseudo_Src
+  * @{
+  */
+
+/**
+ * The esp_intr_alloc* functions can allocate an int for all ETS_*_INTR_SOURCE interrupt sources that
+ * are routed through the interrupt mux. Apart from these sources, each core also has some internal
+ * sources that do not pass through the interrupt mux. To allocate an interrupt for these sources,
+ * pass these pseudo-sources to the functions.
+ */
+#define ETS_INTERNAL_TIMER0_INTR_SOURCE        -1 ///< Xtensa timer 0 interrupt source
+#define ETS_INTERNAL_TIMER1_INTR_SOURCE        -2 ///< Xtensa timer 1 interrupt source
+#define ETS_INTERNAL_TIMER2_INTR_SOURCE        -3 ///< Xtensa timer 2 interrupt source
+#define ETS_INTERNAL_SW0_INTR_SOURCE        -4 ///< Software int source 1
+#define ETS_INTERNAL_SW1_INTR_SOURCE        -5 ///< Software int source 2
+#define ETS_INTERNAL_PROFILING_INTR_SOURCE    -6 ///< Int source for profiling
+
+/**@}*/
+
+// This is used to provide SystemView with positive IRQ IDs, otherwise sheduler events are not shown properly
+#define ETS_INTERNAL_INTR_SOURCE_OFF        (-ETS_INTERNAL_PROFILING_INTR_SOURCE)
+
+typedef void (*intr_handler_t)(void *arg);
+
+
+typedef struct intr_handle_data_t intr_handle_data_t;
+typedef intr_handle_data_t* intr_handle_t ;
+
+/**
+ * @brief Mark an interrupt as a shared interrupt
+ *
+ * This will mark a certain interrupt on the specified CPU as
+ * an interrupt that can be used to hook shared interrupt handlers
+ * to.
+ *
+ * @param intno The number of the interrupt (0-31)
+ * @param cpu CPU on which the interrupt should be marked as shared (0 or 1)
+ * @param is_in_iram Shared interrupt is for handlers that reside in IRAM and
+ *                   the int can be left enabled while the flash cache is disabled.
+ *
+ * @return ESP_ERR_INVALID_ARG if cpu or intno is invalid
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_mark_shared(int intno, int cpu, bool is_in_iram);
+
+/**
+ * @brief Reserve an interrupt to be used outside of this framework
+ *
+ * This will mark a certain interrupt on the specified CPU as
+ * reserved, not to be allocated for any reason.
+ *
+ * @param intno The number of the interrupt (0-31)
+ * @param cpu CPU on which the interrupt should be marked as shared (0 or 1)
+ *
+ * @return ESP_ERR_INVALID_ARG if cpu or intno is invalid
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_reserve(int intno, int cpu);
+
+/**
+ * @brief Allocate an interrupt with the given parameters.
+ *
+ * This finds an interrupt that matches the restrictions as given in the flags
+ * parameter, maps the given interrupt source to it and hooks up the given
+ * interrupt handler (with optional argument) as well. If needed, it can return
+ * a handle for the interrupt as well.
+ *
+ * The interrupt will always be allocated on the core that runs this function.
+ *
+ * If ESP_INTR_FLAG_IRAM flag is used, and handler address is not in IRAM or
+ * RTC_FAST_MEM, then ESP_ERR_INVALID_ARG is returned.
+ *
+ * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux
+ *               sources, as defined in soc/soc.h, or one of the internal
+ *               ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.
+ * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the
+ *               choice of interrupts that this routine can choose from. If this value
+ *               is 0, it will default to allocating a non-shared interrupt of level
+ *               1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
+ *               interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
+ *               from this function with the interrupt disabled.
+ * @param handler The interrupt handler. Must be NULL when an interrupt of level >3
+ *               is requested, because these types of interrupts aren't C-callable.
+ * @param arg    Optional argument for passed to the interrupt handler
+ * @param ret_handle Pointer to an intr_handle_t to store a handle that can later be
+ *               used to request details or free the interrupt. Can be NULL if no handle
+ *               is required.
+ *
+ * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
+ *         ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_alloc(int source, int flags, intr_handler_t handler, void *arg, intr_handle_t *ret_handle);
+
+
+/**
+ * @brief Allocate an interrupt with the given parameters.
+ *
+ *
+ * This essentially does the same as esp_intr_alloc, but allows specifying a register and mask
+ * combo. For shared interrupts, the handler is only called if a read from the specified
+ * register, ANDed with the mask, returns non-zero. By passing an interrupt status register
+ * address and a fitting mask, this can be used to accelerate interrupt handling in the case
+ * a shared interrupt is triggered; by checking the interrupt statuses first, the code can
+ * decide which ISRs can be skipped
+ *
+ * @param source The interrupt source. One of the ETS_*_INTR_SOURCE interrupt mux
+ *               sources, as defined in soc/soc.h, or one of the internal
+ *               ETS_INTERNAL_*_INTR_SOURCE sources as defined in this header.
+ * @param flags An ORred mask of the ESP_INTR_FLAG_* defines. These restrict the
+ *               choice of interrupts that this routine can choose from. If this value
+ *               is 0, it will default to allocating a non-shared interrupt of level
+ *               1, 2 or 3. If this is ESP_INTR_FLAG_SHARED, it will allocate a shared
+ *               interrupt of level 1. Setting ESP_INTR_FLAG_INTRDISABLED will return
+ *               from this function with the interrupt disabled.
+ * @param intrstatusreg The address of an interrupt status register
+ * @param intrstatusmask A mask. If a read of address intrstatusreg has any of the bits
+ *               that are 1 in the mask set, the ISR will be called. If not, it will be
+ *               skipped.
+ * @param handler The interrupt handler. Must be NULL when an interrupt of level >3
+ *               is requested, because these types of interrupts aren't C-callable.
+ * @param arg    Optional argument for passed to the interrupt handler
+ * @param ret_handle Pointer to an intr_handle_t to store a handle that can later be
+ *               used to request details or free the interrupt. Can be NULL if no handle
+ *               is required.
+ *
+ * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
+ *         ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusreg, uint32_t intrstatusmask, intr_handler_t handler, void *arg, intr_handle_t *ret_handle);
+
+
+/**
+ * @brief Disable and free an interrupt.
+ *
+ * Use an interrupt handle to disable the interrupt and release the resources
+ * associated with it.
+ *
+ * @note
+ * When the handler shares its source with other handlers, the interrupt status
+ * bits it's responsible for should be managed properly before freeing it. see
+ * ``esp_intr_disable`` for more details.
+ *
+ * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
+ *
+ * @return ESP_ERR_INVALID_ARG if handle is invalid, or esp_intr_free runs on another core than
+ *                             where the interrupt is allocated on.
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_free(intr_handle_t handle);
+
+
+/**
+ * @brief Get CPU number an interrupt is tied to
+ *
+ * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
+ *
+ * @return The core number where the interrupt is allocated
+ */
+int esp_intr_get_cpu(intr_handle_t handle);
+
+/**
+ * @brief Get the allocated interrupt for a certain handle
+ *
+ * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
+ *
+ * @return The interrupt number
+ */
+int esp_intr_get_intno(intr_handle_t handle);
+
+/**
+ * @brief Disable the interrupt associated with the handle
+ *
+ * @note
+ * 1. For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the
+ * CPU the interrupt is allocated on. Other interrupts have no such restriction.
+ * 2. When several handlers sharing a same interrupt source, interrupt status bits, which are
+ * handled in the handler to be disabled, should be masked before the disabling, or handled
+ * in other enabled interrupts properly. Miss of interrupt status handling will cause infinite
+ * interrupt calls and finally system crash.
+ *
+ * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
+ *
+ * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_disable(intr_handle_t handle);
+
+/**
+ * @brief Enable the interrupt associated with the handle
+ *
+ * @note For local interrupts (ESP_INTERNAL_* sources), this function has to be called on the
+ *       CPU the interrupt is allocated on. Other interrupts have no such restriction.
+ *
+ * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
+ *
+ * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_enable(intr_handle_t handle);
+
+/**
+ * @brief Set the "in IRAM" status of the handler.
+ *
+ * @note Does not work on shared interrupts.
+ *
+ * @param handle The handle, as obtained by esp_intr_alloc or esp_intr_alloc_intrstatus
+ * @param is_in_iram Whether the handler associated with this handle resides in IRAM.
+ *                   Handlers residing in IRAM can be called when cache is disabled.
+ *
+ * @return ESP_ERR_INVALID_ARG if the combination of arguments is invalid.
+ *         ESP_OK otherwise
+ */
+esp_err_t esp_intr_set_in_iram(intr_handle_t handle, bool is_in_iram);
+
+/**
+ * @brief Disable interrupts that aren't specifically marked as running from IRAM
+ */
+void esp_intr_noniram_disable(void);
+
+
+/**
+ * @brief Re-enable interrupts disabled by esp_intr_noniram_disable
+ */
+void esp_intr_noniram_enable(void);
+
+/**@}*/
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_INTR_ALLOC_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh.h
new file mode 100644
index 0000000000000000000000000000000000000000..e9431db97479c7b51ea294b27f0b161e36c4b772
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh.h
@@ -0,0 +1,1318 @@
+// Copyright 2017-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.
+
+/*
+ *   Software Stack demonstrated:
+ *  |------------------------------------------------------------------------------|
+ *  |            |                                                                 |
+ *  |            |                          Application                            |
+ *  |            |-----------------------------------------------------------------|
+ *  |            |               | Protocols: |      |      |               |      |
+ *  |            |   Mesh Stack  | HTTP, DNS, |      |      |     Other     |      |
+ *  |   RTOS:    | (Networking,  | DHCP, ...  |      |      |   Components  |      |
+ *  | (freeRTOS) | self-healing, |------------|      |      |               |      |
+ *  |            | flow control, |  Network Stack:   |      |               |      |
+ *  |            | ...)          |      (LwIP)       |      |               |      |
+ *  |            |-----------------------------------|      |---------------|      |
+ *  |            |                                                  |              |
+ *  |            |                       WiFi Driver                |              |
+ *  |            |--------------------------------------------------|              |
+ *  |            |                                                                 |
+ *  |            |                       Platform HAL                              |
+ *  |------------------------------------------------------------------------------|
+ *
+ *   System Events delivery:
+ *
+ *  |---------------|
+ *  |               |                    default handler
+ *  |  WiFi stack   |     events     |---------------------|
+ *  |               | -------------> |                     |
+ *  |---------------|                |                     |
+ *                                   |      event task     |
+ *  |---------------|     events     |                     |
+ *  |               | -------------> |                     |
+ *  |  LwIP stack   |                |---------------------|
+ *  |               |--------|
+ *  |---------------|        |
+ *                           |         mesh event callback handler
+ *                           |       |----------------------------|
+ *                           |-----> |                            |
+ *  |---------------|                |        application         |
+ *  |               |     events     |            task            |
+ *  |  mesh stack   | -------------> |                            |
+ *  |               |                |----------------------------|
+ *  |---------------|
+ *
+ *
+ *  Mesh Stack
+ *
+ *  Mesh event defines almost all system events applications tasks need.
+ *  Mesh event contains WiFi connection states on station interface, children connection states on softAP interface and etc..
+ *  Applications need to register a mesh event callback handler by API esp_mesh_set_config() firstly.
+ *  This handler is to receive events posted from mesh stack and LwIP stack.
+ *  Applications could add relative handler for each event.
+ *  Examples:
+ *  (1)Applications could use WiFi station connect states to decide when to send data to its parent, to root or to external IP network;
+ *  (2)Applications could use WiFi softAP states to decide when to send data to its children.
+ *
+ *  In present implementation, applications are able to access mesh stack directly without having to go through LwIP stack.
+ *  Applications use esp_mesh_send() and esp_mesh_recv() to send and receive messages over the mesh network.
+ *  In mesh stack design, normal devices don't require LwIP stack. But since IDF hasn't supported system without initializing LwIP stack yet,
+ *  applications still need to do LwIP initialization and two more things are required to be done
+ *  (1)stop DHCP server on softAP interface by default
+ *  (2)stop DHCP client on station interface by default.
+ *  Examples:
+ *  tcpip_adapter_init();
+ *  tcpip_adapter_dhcps_stop(TCPIP_ADAPTER_IF_AP)ï¼›
+ *  tcpip_adapter_dhcpc_stop(TCPIP_ADAPTER_IF_STA)ï¼›
+ *
+ *  Over the mesh network, only root is able to access external IP network.
+ *  In application mesh event handler, once a device becomes a root, start DHCP client immediately if DHCP is chosen.
+ */
+
+#ifndef ESP32_ESP_MESH_H
+#define ESP32_ESP_MESH_H
+
+#include "esp_err.h"
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+#include "esp_mesh_internal.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************
+ *                Constants
+ *******************************************************/
+#define MESH_ROOT_LAYER                   (1)       /**< root layer value */
+#define MESH_MTU                          (1500)    /**< max transmit unit(in bytes) */
+#define MESH_MPS                          (1472)    /**< max payload size(in bytes) */
+/**
+ * @brief mesh error code definition
+ */
+#define ESP_ERR_MESH_WIFI_NOT_START       (ESP_ERR_MESH_BASE + 1)    /**< WiFi isn't started */
+#define ESP_ERR_MESH_NOT_INIT             (ESP_ERR_MESH_BASE + 2)    /**< mesh isn't initialized */
+#define ESP_ERR_MESH_NOT_CONFIG           (ESP_ERR_MESH_BASE + 3)    /**< mesh isn't configured */
+#define ESP_ERR_MESH_NOT_START            (ESP_ERR_MESH_BASE + 4)    /**< mesh isn't started */
+#define ESP_ERR_MESH_NOT_SUPPORT          (ESP_ERR_MESH_BASE + 5)    /**< not supported yet */
+#define ESP_ERR_MESH_NOT_ALLOWED          (ESP_ERR_MESH_BASE + 6)    /**< operation is not allowed */
+#define ESP_ERR_MESH_NO_MEMORY            (ESP_ERR_MESH_BASE + 7)    /**< out of memory */
+#define ESP_ERR_MESH_ARGUMENT             (ESP_ERR_MESH_BASE + 8)    /**< illegal argument */
+#define ESP_ERR_MESH_EXCEED_MTU           (ESP_ERR_MESH_BASE + 9)    /**< packet size exceeds MTU */
+#define ESP_ERR_MESH_TIMEOUT              (ESP_ERR_MESH_BASE + 10)   /**< timeout */
+#define ESP_ERR_MESH_DISCONNECTED         (ESP_ERR_MESH_BASE + 11)   /**< disconnected with parent on station interface */
+#define ESP_ERR_MESH_QUEUE_FAIL           (ESP_ERR_MESH_BASE + 12)   /**< queue fail */
+#define ESP_ERR_MESH_QUEUE_FULL           (ESP_ERR_MESH_BASE + 13)   /**< queue full */
+#define ESP_ERR_MESH_NO_PARENT_FOUND      (ESP_ERR_MESH_BASE + 14)   /**< no parent found to join the mesh network */
+#define ESP_ERR_MESH_NO_ROUTE_FOUND       (ESP_ERR_MESH_BASE + 15)   /**< no route found to forward the packet */
+#define ESP_ERR_MESH_OPTION_NULL          (ESP_ERR_MESH_BASE + 16)   /**< no option found */
+#define ESP_ERR_MESH_OPTION_UNKNOWN       (ESP_ERR_MESH_BASE + 17)   /**< unknown option */
+#define ESP_ERR_MESH_XON_NO_WINDOW        (ESP_ERR_MESH_BASE + 18)   /**< no window for software flow control on upstream */
+#define ESP_ERR_MESH_INTERFACE            (ESP_ERR_MESH_BASE + 19)   /**< low-level WiFi interface error */
+#define ESP_ERR_MESH_DISCARD_DUPLICATE    (ESP_ERR_MESH_BASE + 20)   /**< discard the packet due to the duplicate sequence number */
+#define ESP_ERR_MESH_DISCARD              (ESP_ERR_MESH_BASE + 21)   /**< discard the packet */
+#define ESP_ERR_MESH_VOTING               (ESP_ERR_MESH_BASE + 22)   /**< vote in progress */
+
+/**
+ * @brief flags used with esp_mesh_send() and esp_mesh_recv()
+ */
+#define MESH_DATA_ENC           (0x01)  /**< data encrypted(Unimplemented) */
+#define MESH_DATA_P2P           (0x02)  /**< point-to-point delivery over the mesh network */
+#define MESH_DATA_FROMDS        (0x04)  /**< receive from external IP network */
+#define MESH_DATA_TODS          (0x08)  /**< identify this packet is target to external IP network */
+#define MESH_DATA_NONBLOCK      (0x10)  /**< esp_mesh_send() non-block */
+#define MESH_DATA_DROP          (0x20)  /**< in the situation of root having been changed, identify this packet can be dropped by new root */
+#define MESH_DATA_GROUP         (0x40)  /**< identify this packet is target to a group address */
+
+/**
+ * @brief option definitions for esp_mesh_send() and esp_mesh_recv()
+ */
+#define MESH_OPT_SEND_GROUP     (7)     /**< data transmission by group; used with esp_mesh_send() and shall have payload */
+#define MESH_OPT_RECV_DS_ADDR   (8)     /**< return a remote IP address; used with esp_mesh_send() and esp_mesh_recv() */
+
+/**
+ * @brief flag of mesh networking IE
+ */
+#define MESH_ASSOC_FLAG_VOTE_IN_PROGRESS    (0x02)     /**< vote in progress */
+#define MESH_ASSOC_FLAG_NETWORK_FREE        (0x08)     /**< no root in current network */
+#define MESH_ASSOC_FLAG_ROOTS_FOUND         (0x20)     /**< root conflict is found */
+#define MESH_ASSOC_FLAG_ROOT_FIXED          (0x40)     /**< root is fixed */
+
+/*******************************************************
+ *                Enumerations
+ *******************************************************/
+/**
+ * @brief enumerated list of mesh event id
+ */
+typedef enum {
+    MESH_EVENT_STARTED,                 /**< mesh is started */
+    MESH_EVENT_STOPPED,                 /**< mesh is stopped */
+    MESH_EVENT_CHANNEL_SWITCH,          /**< channel switch */
+    MESH_EVENT_CHILD_CONNECTED,         /**< a child is connected on softAP interface */
+    MESH_EVENT_CHILD_DISCONNECTED,      /**< a child is disconnected on softAP interface */
+    MESH_EVENT_ROUTING_TABLE_ADD,       /**< routing table is changed by adding newly joined children */
+    MESH_EVENT_ROUTING_TABLE_REMOVE,    /**< routing table is changed by removing leave children */
+    MESH_EVENT_PARENT_CONNECTED,        /**< parent is connected on station interface */
+    MESH_EVENT_PARENT_DISCONNECTED,     /**< parent is disconnected on station interface */
+    MESH_EVENT_NO_PARNET_FOUND,         /**< no parent found */
+    MESH_EVENT_LAYER_CHANGE,            /**< layer changes over the mesh network */
+    MESH_EVENT_TODS_STATE,              /**< state represents if root is able to access external IP network */
+    MESH_EVENT_VOTE_STARTED,            /**< the process of voting a new root is started either by children or by root */
+    MESH_EVENT_VOTE_STOPPED,            /**< the process of voting a new root is stopped */
+    MESH_EVENT_ROOT_ADDRESS,            /**< the root address is obtained. It is posted by mesh stack automatically. */
+    MESH_EVENT_ROOT_SWITCH_REQ,         /**< root switch request sent from a new voted root candidate */
+    MESH_EVENT_ROOT_SWITCH_ACK,         /**< root switch acknowledgment responds the above request sent from current root */
+    MESH_EVENT_ROOT_GOT_IP,             /**< root obtains the IP address. It is posted by LwIP stack automatically */
+    MESH_EVENT_ROOT_LOST_IP,            /**< root loses the IP address. It is posted by LwIP stack automatically */
+    MESH_EVENT_ROOT_ASKED_YIELD,        /**< root is asked yield by a more powerful existing root. If self organized is disabled
+                                             and this device is specified to be a root by users, users should set a new parent
+                                             for this device. if self organized is enabled, this device will find a new parent
+                                             by itself, users could ignore this event. */
+    MESH_EVENT_ROOT_FIXED,              /**< when devices join a network, if the setting of Fixed Root for one device is different
+                                             from that of its parent, the device will update the setting the same as its parent's.
+                                             Fixed Root setting of each device is variable as that setting changes of root. */
+    MESH_EVENT_SCAN_DONE,               /**< if self-organized networking is disabled, user can call esp_wifi_scan_start() to trigger
+                                             this event, and add the corresponding scan done handler in this event. */
+    MESH_EVENT_MAX,
+} mesh_event_id_t;
+
+/**
+ * @brief device type
+ */
+typedef enum {
+    MESH_IDLE,    /**< hasn't joined the mesh network yet */
+    MESH_ROOT,    /**< the only sink of the mesh network. Has the ability to access external IP network */
+    MESH_NODE,    /**< intermediate device. Has the ability to forward packets over the mesh network */
+    MESH_LEAF,    /**< has no forwarding ability */
+} mesh_type_t;
+
+/**
+ * @brief protocol of transmitted application data
+ */
+typedef enum {
+    MESH_PROTO_BIN,     /**< binary */
+    MESH_PROTO_HTTP,    /**< HTTP protocol */
+    MESH_PROTO_JSON,    /**< JSON format */
+    MESH_PROTO_MQTT,    /**< MQTT protocol */
+} mesh_proto_t;
+
+/**
+ * @brief for reliable transmission, mesh stack provides three type of services
+ */
+typedef enum {
+    MESH_TOS_P2P,    /**< provide P2P(point-to-point) retransmission on mesh stack by default */
+    MESH_TOS_E2E,    /**< provide E2E(end-to-end) retransmission on mesh stack (Unimplemented) */
+    MESH_TOS_DEF,    /**< no retransmission on mesh stack */
+} mesh_tos_t;
+
+/**
+ * @brief vote reason
+ */
+typedef enum {
+    MESH_VOTE_REASON_ROOT_INITIATED = 1,    /**< vote is initiated by root */
+    MESH_VOTE_REASON_CHILD_INITIATED,       /**< vote is initiated by children */
+} mesh_vote_reason_t;
+
+/**
+ * @brief mesh disconnect reason code
+ */
+typedef enum {
+    MESH_REASON_CYCLIC = 100,      /**< cyclic is detected */
+    MESH_REASON_PARENT_IDLE,       /**< parent is idle */
+    MESH_REASON_LEAF,              /**< the connected device is changed to a leaf */
+    MESH_REASON_DIFF_ID,           /**< in different mesh ID */
+    MESH_REASON_ROOTS,             /**< root conflict is detected */
+    MESH_REASON_PARENT_STOPPED,    /**< parent has stopped the mesh */
+    MESH_REASON_SCAN_FAIL,         /**< scan fail */
+} mesh_disconnect_reason_t;
+
+/*******************************************************
+ *                Structures
+ *******************************************************/
+/**
+ * @brief IP address and port
+ */
+typedef struct {
+    ip4_addr_t ip4;    /**< IP address */
+    uint16_t port;     /**< port */
+} __attribute__((packed)) mip_t;
+
+/**
+ * @brief mesh address
+ */
+typedef union {
+    uint8_t addr[6];    /**< mac address */
+    mip_t mip;          /**< mip address */
+} mesh_addr_t;
+
+/**
+ * @brief channel switch information
+ */
+typedef struct {
+    uint8_t channel;    /**< new channel */
+} mesh_event_channel_switch_t;
+
+/**
+ * @brief parent connected information
+ */
+typedef struct {
+    system_event_sta_connected_t connected; /**< parent information, same as WiFi event SYSTEM_EVENT_STA_CONNECTED does */
+    uint8_t self_layer;                     /**< layer */
+} mesh_event_connected_t;
+
+/**
+ * @brief no parent found information
+ */
+typedef struct {
+    int scan_times;    /**< scan times being through */
+} mesh_event_no_parent_found_t;
+
+/**
+ * @brief layer change information
+ */
+typedef struct {
+    uint8_t new_layer; /**< new layer */
+} mesh_event_layer_change_t;
+
+/**
+ * @brief the reachability of root to a DS(distribute system)
+ */
+typedef enum {
+    MESH_TODS_UNREACHABLE,    /**< root isn't able to access external IP network */
+    MESH_TODS_REACHABLE,      /**< root is able to access external IP network */
+} mesh_event_toDS_state_t;
+
+/**
+ * @brief vote started information
+ */
+typedef struct {
+    int reason;             /**< vote reason, vote could be initiated by children or by root itself */
+    int attempts;           /**< max vote attempts before stopped */
+    mesh_addr_t rc_addr;    /**< root address specified by users via API esp_mesh_waive_root() */
+} mesh_event_vote_started_t;
+
+/**
+ * @brief IP settings from LwIP stack
+ */
+typedef system_event_sta_got_ip_t mesh_event_root_got_ip_t;
+
+/**
+ * @brief root address
+ */
+typedef mesh_addr_t mesh_event_root_address_t;
+
+/**
+ * @brief parent disconnected information
+ */
+typedef system_event_sta_disconnected_t mesh_event_disconnected_t;
+
+/**
+ * @brief child connected information
+ */
+typedef system_event_ap_staconnected_t mesh_event_child_connected_t;
+
+/**
+ * @brief child disconnected information
+ */
+typedef system_event_ap_stadisconnected_t mesh_event_child_disconnected_t;
+
+/**
+ * @brief root switch request information
+ */
+typedef struct {
+    int reason;             /**< root switch reason, generally root switch is initialized by users via API esp_mesh_waive_root() */
+    mesh_addr_t rc_addr;    /**< the address of root switch requester */
+} mesh_event_root_switch_req_t;
+
+/**
+ * @brief other powerful root address
+ */
+typedef struct {
+    int8_t rssi;           /**< rssi with router */
+    uint16_t capacity;     /**< the number of devices in current network */
+    uint8_t addr[6];       /**< other powerful root address */
+} mesh_event_root_conflict_t;
+
+/**
+ * @brief routing table change
+ */
+typedef struct {
+    uint16_t rt_size_new;      /**< the new value */
+    uint16_t rt_size_change;   /**< the changed value */
+} mesh_event_routing_table_change_t;
+
+/**
+ * @brief root fixed
+ */
+typedef struct {
+    bool is_fixed;     /**< status */
+} mesh_event_root_fixed_t;
+
+/**
+ * @brief scan done event information
+ */
+typedef struct {
+    uint8_t  number;     /**< the number of scanned APs */
+} mesh_event_scan_done_t;
+
+/**
+ * @brief mesh event information
+ */
+typedef union {
+    mesh_event_channel_switch_t channel_switch;            /**< channel switch */
+    mesh_event_child_connected_t child_connected;          /**< child connected */
+    mesh_event_child_disconnected_t child_disconnected;    /**< child disconnected */
+    mesh_event_routing_table_change_t routing_table;       /**< routing table change */
+    mesh_event_connected_t connected;                      /**< parent connected */
+    mesh_event_disconnected_t disconnected;                /**< parent disconnected */
+    mesh_event_no_parent_found_t no_parent;                /**< no parent found */
+    mesh_event_layer_change_t layer_change;                /**< layer change */
+    mesh_event_toDS_state_t toDS_state;                    /**< toDS state, devices shall check this state firstly before trying to send packets to
+                                                                external IP network. This state indicates right now if root is capable of sending
+                                                                packets out. If not, devices had better to wait until this state changes to be
+                                                                MESH_TODS_REACHABLE. */
+    mesh_event_vote_started_t vote_started;                /**< vote started */
+    mesh_event_root_got_ip_t got_ip;                       /**< root obtains IP address */
+    mesh_event_root_address_t root_addr;                   /**< root address */
+    mesh_event_root_switch_req_t switch_req;               /**< root switch request */
+    mesh_event_root_conflict_t root_conflict;              /**< other powerful root */
+    mesh_event_root_fixed_t root_fixed;                    /**< root fixed */
+    mesh_event_scan_done_t scan_done;                      /**< scan done */
+} mesh_event_info_t;
+
+/**
+ * @brief mesh event
+ */
+typedef struct {
+    mesh_event_id_t id;        /**< mesh event id */
+    mesh_event_info_t info;    /**< mesh event info */
+} mesh_event_t;
+
+/**
+ * @brief  mesh event callback handler prototype definition
+ *
+ * @param  event  mesh_event_t
+ */
+typedef void (*mesh_event_cb_t)(mesh_event_t event);
+
+/**
+ * @brief mesh option
+ */
+typedef struct {
+    uint8_t type;    /**< option type */
+    uint16_t len;    /**< option length */
+    uint8_t *val;    /**< option value */
+} __attribute__((packed)) mesh_opt_t;
+
+/**
+ * @brief mesh data for esp_mesh_send() and esp_mesh_recv()
+ */
+typedef struct {
+    uint8_t *data;         /**< data */
+    uint16_t size;         /**< data size */
+    mesh_proto_t proto;    /**< data protocol */
+    mesh_tos_t tos;        /**< data type of service */
+} mesh_data_t;
+
+/**
+ * @brief router configuration
+ */
+typedef struct {
+    uint8_t ssid[32];        /**< SSID */
+    uint8_t ssid_len;        /**< length of SSID */
+    uint8_t bssid[6];        /**< BSSID, if router is hidden, this value is mandatory */
+    uint8_t password[64];    /**< password */
+} mesh_router_t;
+
+/**
+ * @brief mesh softAP configuration
+ */
+typedef struct {
+    uint8_t password[64];      /**< mesh softAP password */
+    uint8_t max_connection;    /**< max number of stations allowed to connect in, max 10 */
+} mesh_ap_cfg_t;
+
+/**
+ * @brief mesh initialization configuration
+ */
+typedef struct {
+    uint8_t channel;                            /**< channel, the mesh network on */
+    mesh_event_cb_t event_cb;                   /**< mesh event callback */
+    mesh_addr_t mesh_id;                        /**< mesh network identification */
+    mesh_router_t router;                       /**< router configuration */
+    mesh_ap_cfg_t mesh_ap;                      /**< mesh softAP configuration */
+    const mesh_crypto_funcs_t *crypto_funcs;    /**< crypto functions */
+} mesh_cfg_t;
+
+/**
+ * @brief vote address configuration
+ */
+typedef union {
+    int attempts;           /**< max vote attempts before a new root is elected automatically by mesh network. (min:15, 15 by default) */
+    mesh_addr_t rc_addr;    /**< a new root address specified by users for API esp_mesh_waive_root() */
+} mesh_rc_config_t;
+
+/**
+ * @brief vote
+ */
+typedef struct {
+    float percentage;           /**< vote percentage threshold for approval of being a root */
+    bool is_rc_specified;       /**< if true, rc_addr shall be specified(Unimplemented).
+                                     if false, attempts value shall be specified to make network start root election. */
+    mesh_rc_config_t config;    /**< vote address configuration */
+} mesh_vote_t;
+
+/**
+ * @brief the number of packets pending in the queue waiting to be sent by the mesh stack
+ */
+typedef struct {
+    int to_parent;        /**< to parent queue */
+    int to_parent_p2p;    /**< to parent(P2P) queue */
+    int to_child;         /**< to child queue */
+    int to_child_p2p;     /**< to child(P2P) queue */
+    int mgmt;             /**< management queue */
+    int broadcast;        /**< broadcast and multicast queue */
+} mesh_tx_pending_t;
+
+/**
+ * @brief the number of packets available in the queue waiting to be received by applications
+ */
+typedef struct {
+    int toDS;      /**< to external DS */
+    int toSelf;    /**< to self */
+} mesh_rx_pending_t;
+
+/*******************************************************
+ *                Variable Declaration
+ *******************************************************/
+/* mesh vendor IE crypto callback function */
+extern const mesh_crypto_funcs_t g_wifi_default_mesh_crypto_funcs;
+
+/* mesh event callback handler */
+extern mesh_event_cb_t g_mesh_event_cb;
+
+#define MESH_INIT_CONFIG_DEFAULT() { \
+    .crypto_funcs = &g_wifi_default_mesh_crypto_funcs, \
+}
+
+/*******************************************************
+ *                Function Definitions
+ *******************************************************/
+/**
+ * @brief     mesh initialization
+ *            Check if WiFi is started.
+ *            Initialize mesh global variables with default values.
+ *
+ * @attention This API shall be called after WiFi is started.
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_init(void);
+
+/**
+ * @brief     mesh de-initialization
+ *            Release resources and stop the mesh
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_deinit(void);
+
+/**
+ * @brief     start mesh
+ *            Initialize mesh vendor IE
+ *            Start mesh network management service
+ *            Create TX and RX queues according to the configuration
+ *            Register mesh packets receive callback
+ *
+ * @attention This API shall be called after esp_mesh_init() and esp_mesh_set_config().
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ *    - ESP_ERR_MESH_NOT_INIT
+ *    - ESP_ERR_MESH_NOT_CONFIG
+ *    - ESP_ERR_MESH_NO_MEMORY
+ */
+esp_err_t esp_mesh_start(void);
+
+/**
+ * @brief     stop mesh
+ *            Deinitialize mesh vendor IE
+ *            Disconnect with current parent
+ *            Disassociate all currently associated children
+ *            Stop mesh network management service
+ *            Unregister mesh packets receive callback
+ *            Delete TX and RX queues
+ *            Release resources
+ *            Restore WiFi softAP to default settings if WiFi dual mode is enabled
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_stop(void);
+
+/**
+ * @brief     send a packet over the mesh network
+ *            Send a packet to any device in the mesh network.
+ *            Send a packet to external IP network.
+ *
+ * @attention This API is not reentrant.
+ *
+ * @param     to  the address of the final destination of the packet
+ *            (1)if the packet is to root, just set "to" to NULL and set flag to zero.
+ *            (2)if the packet is outgoing to external IP network such as an IP server address, translate IPv4:PORT known as "to".
+ *               This packet will be delivered to root firstly, then root will forward this packet to the final IP server address.
+ * @param     data  pointer to a sending mesh packet
+ *            Should specify the data protocol applications used, binary by default.
+ *            Should specify the transmission tos(type of service), P2P reliable by default.
+ * @param     flag
+ *            (1)used to speed up the route selection
+ *              if the packet is target to an internal device, MESH_DATA_P2P should be set.
+ *              if the packet is outgoing to root or to external IP network, MESH_DATA_TODS should be set.
+ *              if the packet is from root to an internal device, MESH_DATA_FROMDS should be set.
+ *            (2)specify if this API is block or non-block, block by default
+ *              if needs non-block, MESH_DATA_NONBLOCK should be set.
+ *            (3)in the situation of root having been changed, MESH_DATA_DROP identifies this packet can be dropped by new root
+ *              for upstream data to external IP network, we try our best to avoid data loss caused by root having been changed, but
+ *              there is a risk that new root is running out of memory because most of memory is occupied by the pending data which
+ *              isn't read out in time by esp_mesh_recv_toDS().
+ *              Generally, we suggest esp_mesh_recv_toDS() is called after a connection with IP network is created. Thus data outgoing
+ *              to external IP network via socket is just from reading esp_mesh_recv_toDS() which avoids unnecessary memory copy.
+ *
+ * @param     opt  options
+ *            (1)in case of sending a packet to a specified group, MESH_OPT_SEND_GROUP is a good choice.
+ *               In this option, the value field should specify the target receiver addresses in this group.
+ *            (2)root sends a packet to an internal device, this packet is from external IP network in case the receiver device responds
+ *            this packet, MESH_OPT_RECV_DS_ADDR is required to attach the target DS address.
+ * @param     opt_count  option count
+ *            Currently, this API only takes one option, so opt_count is only supported to be 1.
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_START
+ *    - ESP_ERR_MESH_DISCONNECTED
+ *    - ESP_ERR_MESH_OPT_UNKNOWN
+ *    - ESP_ERR_MESH_EXCEED_MTU
+ *    - ESP_ERR_MESH_NO_MEMORY
+ *    - ESP_ERR_MESH_TIMEOUT
+ *    - ESP_ERR_MESH_QUEUE_FULL
+ *    - ESP_ERR_MESH_NO_ROUTE_FOUND
+ *    - ESP_ERR_MESH_DISCARD
+ */
+esp_err_t esp_mesh_send(const mesh_addr_t *to, const mesh_data_t *data,
+                        int flag, const mesh_opt_t opt[],  int opt_count);
+
+/**
+ * @brief     receive a packet targeted to self over the mesh network
+ *            Use esp_mesh_get_rx_pending() to check the number of packets available in the queue waiting
+ *            to be received by applications in case of running out of memory.
+ *
+ * @param     from  the address of the original source of the packet
+ * @param     data  pointer to the received mesh packet
+ *            Contain the protocol and applications should follow it to parse the data.
+ * @param     timeout_ms  wait time if a packet isn't immediately available(0:no wait, portMAX_DELAY:wait forever)
+ * @param     flag
+ *            MESH_DATA_FROMDS represents data from external IP network
+ *            MESH_DATA_TODS represents data directed upward within the mesh network
+ * @param     opt  options desired to receive
+ *            MESH_OPT_RECV_DS_ADDR attaches the DS address
+ * @param     opt_count  option count desired to receive
+ *            Currently, this API only takes one option, so opt_count is only supported to be 1.
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_START
+ *    - ESP_ERR_MESH_TIMEOUT
+ *    - ESP_ERR_MESH_DISCARD
+ */
+esp_err_t esp_mesh_recv(mesh_addr_t *from, mesh_data_t *data, int timeout_ms,
+                        int *flag, mesh_opt_t opt[], int opt_count);
+
+/**
+ * @brief     receive a packet targeted to external IP network
+ *            root uses this API to receive packets destined to external IP network
+ *            root forwards the received packets to the final destination via socket.
+ *            if no socket connection is ready to send out the received packets and this esp_mesh_recv_toDS()
+ *            hasn't been called by applications, packets from the whole mesh network will be pending in toDS queue.
+ *            Use esp_mesh_get_rx_pending() to check the number of packets available in the queue waiting
+ *            to be received by applications in case of running out of memory in root.
+ *            Use esp_mesh_set_xon_qsize() could configure the RX queue size, default:72. If this size is too large,
+ *            and esp_mesh_recv_toDS() isn't called in time, there is a risk that a great deal of memory is occupied
+ *            by the pending packets. If this size is too small, it will impact the efficiency on upstream. How to
+ *            decide this value depends on the specific application scenarios.
+ *
+ * @attention This API is only called by root.
+ *
+ * @param     from  the address of the original source of the packet
+ * @param     to  the address contains remote IP address and port(IPv4:PORT)
+ * @param     data  pointer to the received packet
+ *            Contain the protocol and applications should follow it to parse the data.
+ * @param     timeout_ms  wait time if a packet isn't immediately available(0:no wait, portMAX_DELAY:wait forever)
+ * @param     flag
+ *            MESH_DATA_TODS represents data to external IP network
+ * @param     opt  options desired to receive
+ * @param     opt_count  option count desired to receive
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_START
+ *    - ESP_ERR_MESH_TIMEOUT
+ *    - ESP_ERR_MESH_DISCARD
+ */
+esp_err_t esp_mesh_recv_toDS(mesh_addr_t *from, mesh_addr_t *to,
+                             mesh_data_t *data, int timeout_ms, int *flag, mesh_opt_t opt[],
+                             int opt_count);
+
+/**
+ * @brief     set mesh stack configuration
+ *            Use MESH_INIT_CONFIG_DEFAULT() to initialize the default values, mesh vendor IE is encrypted by default.
+ *            mesh network is established on a fixed channel(1-14).
+ *            mesh event callback is mandatory.
+ *            mesh ID is an identifier of an MBSS. Nodes with the same mesh ID can communicate with each other.
+ *            Regarding to the router configuration, if the router is hidden, BSSID field is mandatory.
+ *            If BSSID field isn't set and there exists more than one router with same SSID, there is a risk that more
+ *            roots than one connected with different BSSID will appear. It means more than one mesh network is established
+ *            with the same mesh ID.
+ *            Root conflict function could eliminate redundant roots connected with the same BSSID, but couldn't handle roots
+ *            connected with different BSSID. Because users might have such requirements of setting up routers with same SSID
+ *            for the future replacement. But in that case, if the above situations happen, please make sure applications
+ *            implement forward functions on root to guarantee devices in different mesh network can communicate with each other.
+ *            max_connection of mesh softAP is limited by the max number of WiFi softAP supported(max:10).
+ *
+ * @attention This API shall be called between esp_mesh_init() and esp_mesh_start().
+ *
+ * @param     config  pointer to mesh stack configuration
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ */
+esp_err_t esp_mesh_set_config(const mesh_cfg_t *config);
+
+/**
+ * @brief     get mesh stack configuration
+ *
+ * @param     config  pointer to mesh stack configuration
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_config(mesh_cfg_t *config);
+
+/**
+ * @brief     set router configuration
+ *
+ * @attention This API shall be called between esp_mesh_init() and esp_mesh_start().
+ *
+ * @param     router  pointer to router configuration
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_set_router(const mesh_router_t *router);
+
+/**
+ * @brief     get router configuration
+ *
+ * @param     router  pointer to router configuration
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_router(mesh_router_t *router);
+
+/**
+ * @brief     set mesh network ID
+ *
+ * @attention This API could be called either before esp_mesh_start() or after esp_mesh_start().
+ *
+ * @param     id  pointer to mesh network ID
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT: invalid argument
+ */
+esp_err_t esp_mesh_set_id(const mesh_addr_t *id);
+
+/**
+ * @brief     get mesh network ID
+ *
+ * @param     id  pointer to mesh network ID
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_id(mesh_addr_t *id);
+
+/**
+ * @brief     set device type over the mesh network(Unimplemented)
+ *
+ * @param     type  device type
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ */
+esp_err_t esp_mesh_set_type(mesh_type_t type);
+
+/**
+ * @brief     get device type over mesh network
+ *
+ * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
+ *
+ * @return    mesh type
+ *
+ */
+mesh_type_t esp_mesh_get_type(void);
+
+/**
+ * @brief     set max layer configuration(max:15, default:15)
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     max_layer  max layer value
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ */
+esp_err_t esp_mesh_set_max_layer(int max_layer);
+
+/**
+ * @brief     get max layer configuration
+ *
+ * @return    max layer value
+ */
+int esp_mesh_get_max_layer(void);
+
+/**
+ * @brief     set mesh softAP password
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     pwd  pointer to the password
+ * @param     len  password length
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ */
+esp_err_t esp_mesh_set_ap_password(const uint8_t *pwd, int len);
+
+/**
+ * @brief     set mesh softAP authentication mode value
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     authmode  authentication mode
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ */
+esp_err_t esp_mesh_set_ap_authmode(wifi_auth_mode_t authmode);
+
+/**
+ * @brief     get mesh softAP authentication mode
+ *
+ * @return    authentication mode
+ *
+ */
+wifi_auth_mode_t esp_mesh_get_ap_authmode(void);
+
+/**
+ * @brief     set mesh softAP max connection value
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     connections  the number of max connections
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_set_ap_connections(int connections);
+
+/**
+ * @brief     get mesh softAP max connection configuration
+ *
+ * @return    the number of max connections
+ *
+ */
+int esp_mesh_get_ap_connections(void);
+
+/**
+ * @brief     get current layer value over the mesh network
+ *
+ * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
+ *
+ * @return    layer value
+ *
+ */
+int esp_mesh_get_layer(void);
+
+/**
+ * @brief     get parent BSSID
+ *
+ * @attention This API shall be called after having received the event MESH_EVENT_PARENT_CONNECTED.
+ *
+ * @param     bssid  pointer to parent BSSID
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_get_parent_bssid(mesh_addr_t *bssid);
+
+/**
+ * @brief     return if the device is root
+ *
+ * @return    true/false
+ *
+ */
+bool esp_mesh_is_root(void);
+
+/**
+ * @brief     enable/disable mesh networking self-organized, self-organized by default
+ *            if self-organized is disabled, users should set a parent for this device via
+ *            esp_mesh_set_parent();
+ *
+ * @attention This API could be called either before esp_mesh_start() or after esp_mesh_start().
+ *
+ * @param     enable  enable or disable self-organized networking
+ * @param     select_parent  if enable self-organized networking, let the device select a new parent or
+ *            keep connecting to the previous parent.
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_set_self_organized(bool enable, bool select_parent);
+
+/**
+ * @brief     return if mesh networking is self-organized or not
+ *
+ * @return    true/false
+ *
+ */
+bool esp_mesh_get_self_organized(void);
+
+/**
+ * @brief     root waive itself
+ *            A device is elected to be a root during the networking mostly because it has a strong RSSI with router.
+ *            If such superior conditions change, users could call this API to perform a root switch.
+ *
+ *            In this API, users could specify a desired root address to replace itself or specify an attempts value
+ *            to ask current root to initiate a new round of voting. During the voting, a better root candidate would
+ *            be expected to find to replace the current one.
+ *            If no desired root candidate, the vote will try a specified attempts(at least 10 times), if no better
+ *            root candidate is found, keep the current one. If a better candidate is found, the new better one will
+ *            send a root switch request to the current root, current root will respond with a root switch acknowledgment.
+ *            After that, the new candidate will connect to the router to be a new root, the previous root will disconnect
+ *            with the router and choose another parent instead.
+ *            So far, root switch is completed with minimal disruption to the whole mesh network.
+ *
+ * @attention This API is only called by root.
+ *
+ * @param     vote  vote configuration
+ *            Specify a desired root address(Unimplemented)
+ *            Attempts should be at least 10 times.
+ *            if "vote" is set NULL, the vote will perform the default 10 times.
+ * @param     reason  only accept MESH_VOTE_REASON_ROOT_INITIATED for now
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_QUEUE_FULL
+ *    - ESP_ERR_MESH_DISCARD
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_waive_root(const mesh_vote_t *vote, int reason);
+
+/**
+ * @brief     set vote percentage threshold for approval of being a root
+ *            During the networking, only obtaining vote percentage reaches this threshold,
+ *            the device could be a root.
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     percentage  vote percentage threshold
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_set_vote_percentage(float percentage);
+
+/**
+ * @brief     get vote percentage threshold for approval of being a root
+ *
+ * @return    percentage threshold
+ */
+float esp_mesh_get_vote_percentage(void);
+
+/**
+ * @brief     set mesh softAP associate expired time
+ *            If mesh softAP hasn't received any data from an associated child within this time,
+ *            mesh softAP will take this child inactive and disassociate it.
+ *
+ * @param     seconds
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_set_ap_assoc_expire(int seconds);
+
+/**
+ * @brief     get mesh softAP associate expired time
+ *
+ * @return    seconds
+ */
+int esp_mesh_get_ap_assoc_expire(void);
+
+/**
+ * @brief     get total number of devices in current network(including root)
+ *
+ * @attention The returned value might be incorrect when the network is changing.
+ **
+ * @return    total number of devices(including root)
+ */
+int esp_mesh_get_total_node_num(void);
+
+/**
+ * @brief     get the number of devices in this device's sub-network(including self)
+ *
+ * @return    the number of devices over this device's sub-network(including self)
+ */
+int esp_mesh_get_routing_table_size(void);
+
+/**
+ * @brief     get routing table of this device's sub-network(including itself)
+ *
+ * @param     mac  pointer to routing table
+ * @param     len  routing table size(in bytes)
+ * @param     size  pointer to the number of devices in routing table(including itself)
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_routing_table(mesh_addr_t *mac, int len, int *size);
+
+/**
+ * @brief     post the toDS state to the mesh stack
+ *
+ * @attention This API is only for root.
+ *
+ * @param     reachable  this state represents if root is able to access external IP network
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_post_toDS_state(bool reachable);
+
+/**
+ * @brief     return the number of packets pending in the queue waiting to be sent by the mesh stack
+ *
+ * @param     pending  pointer to the TX pending
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_get_tx_pending(mesh_tx_pending_t *pending);
+
+/**
+ * @brief     return the number of packets available in the queue waiting to be received by applications
+ *
+ * @param     pending  pointer to the RX pending
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_get_rx_pending(mesh_rx_pending_t *pending);
+
+/**
+ * @brief     return the number of packets could be accepted from the specified address
+ *
+ * @param     addr  self address or an associate children address
+ * @param     xseqno_in  sequence number of the last received packet from the specified address
+ *
+ * @return    the number of upQ for a specified address
+ */
+int esp_mesh_available_txupQ_num(const mesh_addr_t *addr, uint32_t *xseqno_in);
+
+/**
+ * @brief     set queue size
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     qsize  default:32(min:16)
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_set_xon_qsize(int qsize);
+
+/**
+ * @brief     get queue size
+ *
+ * @return    qsize
+ */
+int esp_mesh_get_xon_qsize(void);
+
+/**
+ * @brief     set if allow more than one root existing in one network
+ *
+ * @param     allowed  allow or not
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_WIFI_ERR_NOT_INIT
+ *    - ESP_WIFI_ERR_NOT_START
+ */
+esp_err_t esp_mesh_allow_root_conflicts(bool allowed);
+
+/**
+ * @brief     check if allow more than one root to exist in one network
+ *
+ * @return    true/false
+ */
+bool esp_mesh_is_root_conflicts_allowed(void);
+
+/**
+ * @brief     set group ID addresses
+ *
+ * @param     addr  pointer to new group ID addresses
+ * @param     num  the number of group ID addresses
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_MESH_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_set_group_id(const mesh_addr_t *addr, int num);
+
+/**
+ * @brief     delete group ID addresses
+ *
+ * @param     addr  pointer to deleted group ID address
+ * @param     num  the number of group ID addresses
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_MESH_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_delete_group_id(const mesh_addr_t *addr, int num);
+
+/**
+ * @brief     get the number of group ID addresses
+ *
+ * @return    the number of group ID addresses
+ */
+int esp_mesh_get_group_num(void);
+
+/**
+ * @brief     get group ID addresses
+ *
+ * @param     addr  pointer to group ID addresses
+ * @param     num  the number of group ID addresses
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_MESH_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_get_group_list(mesh_addr_t *addr, int num);
+
+/**
+ * @brief     check if the specified group address is my group
+ *
+ * @return    true/false
+ */
+bool esp_mesh_is_my_group(const mesh_addr_t *addr);
+
+/**
+ * @brief     set mesh network capacity
+ *
+ * @attention This API shall be called before esp_mesh_start().
+ *
+ * @param     num  mesh network capacity
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ *    - ESP_MESH_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_set_capacity_num(int num);
+
+/**
+ * @brief    get mesh network capacity
+ *
+ * @return   mesh network capacity
+ */
+int esp_mesh_get_capacity_num(void);
+
+/**
+ * @brief    set mesh ie crypto functions
+ *
+ * @param     crypto_funcs  crypto functions for mesh ie
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_set_ie_crypto_funcs(const mesh_crypto_funcs_t *crypto_funcs);
+
+/**
+ * @brief    set mesh ie crypto key
+ *
+ * @attention This API shall be called after esp_mesh_set_config() and before esp_mesh_start().
+ *
+ * @param     key  ASCII crypto key
+ * @param     len  length in bytes, range:8~64
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_NOT_ALLOWED
+ *    - ESP_ERR_MESH_NOT_CONFIG
+ *    - ESP_MESH_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_set_ie_crypto_key(const char *key, int len);
+
+/**
+ * @brief    get mesh ie crypto key
+ *
+ * @param     key  ASCII crypto key
+ * @param     len  length in bytes, range:8~64
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_MESH_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_get_ie_crypto_key(char *key, int len);
+
+/**
+ * @brief    set delay time before starting root healing
+ *
+ * @param     delay_ms  delay time in milliseconds
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_set_root_healing_delay(int delay_ms);
+
+/**
+ * @brief    get delay time before starting root healing
+ *
+ * @return    delay time in milliseconds
+ */
+int esp_mesh_get_root_healing_delay(void);
+
+/**
+ * @brief    set mesh event callback
+ *
+ * @param     event_cb  mesh event call back
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_set_event_cb(const mesh_event_cb_t event_cb);
+
+/**
+ * @brief     set Fixed Root setting for the device
+ *            If Fixed Root setting of the device is enabled, it won't compete to be a root.
+ *            If a scenario needs a fixed root, all devices in this network shall enable this setting.
+ *
+ * @param     enable  enable or not
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_fix_root(bool enable);
+
+/**
+ * @brief     check if Fixed Root setting is enabled
+ *            Fixed Root setting can be changed by API esp_mesh_fix_root().
+ *            Fixed Root setting can also be changed by event MESH_EVENT_ROOT_FIXED.
+ *
+ * @return    true/false
+ */
+bool esp_mesh_is_root_fixed(void);
+
+/**
+ * @brief     set a specified parent
+ *
+ * @param     parent  parent configuration, the ssid and the channel of the parent are mandatory.
+ * @param     parent_mesh_id  parent mesh ID, if not set, use the device default one.
+ * @param     my_type  my mesh type
+ * @param     my_layer  my mesh layer
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_ARGUMENT
+ *    - ESP_ERR_MESH_NOT_CONFIG
+ */
+esp_err_t esp_mesh_set_parent(const wifi_config_t *parent, const mesh_addr_t *parent_mesh_id, mesh_type_t my_type, int my_layer);
+
+/**
+ * @brief     get mesh networking IE length of one AP
+ *
+ * @param     len  mesh networking IE length
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_WIFI_NOT_INIT
+ *    - ESP_ERR_WIFI_ARG
+ *    - ESP_ERR_WIFI_FAIL
+ */
+esp_err_t esp_mesh_scan_get_ap_ie_len(int *len);
+
+/**
+ * @brief     get AP record
+ *            Different from esp_wifi_scan_get_ap_records(), this API only gets one of scanned APs each time.
+ *
+ * @param     ap_record  pointer to the AP record
+ * @param     buffer  pointer to the mesh networking IE of this AP
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_WIFI_NOT_INIT
+ *    - ESP_ERR_WIFI_ARG
+ *    - ESP_ERR_WIFI_FAIL
+ */
+esp_err_t esp_mesh_scan_get_ap_record(wifi_ap_record_t *ap_record, void *buffer);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ESP32_ESP_MESH_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh_internal.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..cc53b1f940515f67c0a32d8435af6aa797bd9bb8
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_mesh_internal.h
@@ -0,0 +1,272 @@
+// Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_MESH_INTERNAL_H
+#define ESP32_ESP_MESH_INTERNAL_H
+
+#include "esp_err.h"
+#include "esp_wifi.h"
+#include "esp_wifi_types.h"
+#include "esp_wifi_internal.h"
+#include "esp_wifi_crypto_types.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*******************************************************
+ *                Constants
+ *******************************************************/
+
+/*******************************************************
+ *                Structures
+ *******************************************************/
+typedef struct {
+    int scan;          /**< minimum scan times before being a root, default:10 */
+    int vote;          /**< max vote times in self-healing, default:10000 */
+    int fail;          /**< parent selection fail times, if the scan times reach this value,
+                            will disconnect with associated children and join self-healing. default:60 */
+    int monitor_ie;    /**< acceptable times of parent ie change before update self ie, default:3 */
+} mesh_attempts_t;
+
+typedef struct {
+    int duration_ms;   /* parent weak RSSI monitor duration, if the RSSI continues to be weak during this duration_ms,
+                          will switch to a better parent */
+    int cnx_rssi;      /* RSSI threshold for keeping a good connection with parent.
+                          if set a value greater than -120 dBm, will arm a timer to monitor current RSSI at a period time of
+                          duration_ms. if keep the default value(-120 dBm), a timer at a random period(<3minutes) will
+                          be armed to switch a better parent if there does have one.
+                          The better parent must have RSSI greater than a high RSSI threshold(-78 dBm by default) and a top layer
+                          than current one. */
+    int select_rssi;   /* RSSI threshold for parent selection, should be a value greater than switch_rssi */
+    int switch_rssi;   /* Disassociate current parent and switch to a new parent when the RSSI is greater than this set threshold */
+    int backoff_rssi;  /* RSSI threshold for connecting to the root */
+} mesh_switch_parent_t;
+
+typedef struct {
+    int high;
+    int medium;
+    int low;
+} mesh_rssi_threshold_t;
+
+/**
+ * @brief mesh networking IE
+ */
+typedef struct {
+    /**< mesh networking IE head */
+    uint8_t eid;             /**< element ID */
+    uint8_t len;             /**< element length */
+    uint8_t oui[3];          /**< organization identifier */
+    /**< mesh networking IE content */
+    uint8_t type;            /** mesh networking IE type */
+    uint8_t encryped : 1;    /**< if mesh networking IE is encrypted */
+    uint8_t version : 7;     /**< mesh networking IE version */
+    /**< content */
+    uint8_t mesh_type;       /**< mesh device type */
+    uint8_t mesh_id[6];      /**< mesh ID */
+    uint8_t layer_cap;       /**< max layer */
+    uint8_t layer;           /**< current layer */
+    uint8_t assoc_cap;       /**< max connections of mesh AP */
+    uint8_t assoc;           /**< current connections */
+    uint8_t leaf_cap;        /**< leaf capacity */
+    uint8_t leaf_assoc;      /**< the number of current connected leaf */
+    uint16_t root_cap;       /**< root capacity */
+    uint16_t self_cap;       /**< self capacity */
+    uint16_t layer2_cap;     /**< layer2 capacity */
+    uint16_t scan_ap_num;    /**< the number of scanned APs */
+    int8_t rssi;             /**< RSSI of the parent */
+    int8_t router_rssi;      /**< RSSI of the router */
+    uint8_t flag;            /**< flag of networking */
+    uint8_t rc_addr[6];      /**< root address */
+    int8_t rc_rssi;          /**< root RSSI */
+    uint8_t vote_addr[6];    /**< voter address */
+    int8_t vote_rssi;        /**< vote RSSI of the router */
+    uint8_t vote_ttl;        /**< vote ttl */
+    uint16_t votes;          /**< votes */
+    uint16_t my_votes;       /**< my votes */
+    uint8_t reason;          /**< reason */
+    uint8_t child[6];        /**< child address */
+    uint8_t toDS;            /**< toDS state */
+} __attribute__((packed)) mesh_assoc_t;
+
+/*******************************************************
+ *                Function Definitions
+ *******************************************************/
+/**
+ * @brief     set mesh softAP beacon interval
+ *
+ * @param     interval  beacon interval(ms) (100ms ~ 60000ms)
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ *    - ESP_ERR_WIFI_ARG
+ */
+esp_err_t esp_mesh_set_beacon_interval(int interval_ms);
+
+/**
+ * @brief     get mesh softAP beacon interval
+ *
+ * @param     interval  beacon interval(ms)
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_get_beacon_interval(int *interval_ms);
+
+/**
+ * @brief    set attempts for mesh self-organized networking
+ *
+ * @param    attempts
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_set_attempts(mesh_attempts_t *attempts);
+
+/**
+ * @brief    get attempts for mesh self-organized networking
+ *
+ * @param    attempts
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_attempts(mesh_attempts_t *attempts);
+
+/**
+ * @brief     set parameters for parent switch
+ *
+ * @param     paras  parameters for parent switch
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_set_switch_parent_paras(mesh_switch_parent_t *paras);
+
+/**
+ * @brief     get parameters for parent switch
+ *
+ * @param     paras  parameters for parent switch
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_switch_parent_paras(mesh_switch_parent_t *paras);
+
+/**
+ * @brief     set RSSI threshold
+ *            The default high RSSI threshold value is -78 dBm.
+ *            The default medium RSSI threshold value is -82 dBm.
+ *            The default low RSSI threshold value is -85 dBm.
+ *
+ * @param     threshold  RSSI threshold
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_set_rssi_threshold(const mesh_rssi_threshold_t *threshold);
+
+/**
+ * @brief     get RSSI threshold
+ * @param     threshold  RSSI threshold
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_ERR_MESH_ARGUMENT
+ */
+esp_err_t esp_mesh_get_rssi_threshold(mesh_rssi_threshold_t *threshold);
+
+/**
+ * @brief     enable the minimum rate to 6Mbps
+ *
+ * @attention This API shall be called before WiFi start.
+ *
+ * @param     is_6m  enable or not
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_set_6m_rate(bool is_6m);
+
+/**
+ * @brief     print the number of txQ waiting
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_print_txQ_waiting(void);
+
+/**
+ * @brief     print the number of rxQ waiting
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ */
+esp_err_t esp_mesh_print_rxQ_waiting(void);
+
+/**
+ * @brief     set passive scan time
+ *
+ * @param     interval_ms  passive scan time(ms)
+ *
+ * @return
+ *    - ESP_OK
+ *    - ESP_FAIL
+ *    - ESP_ERR_ARGUMENT
+ */
+esp_err_t esp_mesh_set_passive_scan_time(int time_ms);
+
+/**
+ * @brief     get passive scan time
+ *
+ * @return    interval_ms  passive scan time(ms)
+ */
+int esp_mesh_get_passive_scan_time(void);
+
+/**
+ * @brief     set announce interval
+ *            The default short interval is 500 milliseconds.
+ *            The default long interval is 3000 milliseconds.
+ *
+ * @param     short_ms  shall be greater than the default value
+ * @param     long_ms  shall be greater than the default value
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_set_announce_interval(int short_ms, int long_ms);
+
+/**
+ * @brief     get announce interval
+ *
+ * @param     short_ms  short interval
+ * @param     long_ms  long interval
+ *
+ * @return
+ *    - ESP_OK
+ */
+esp_err_t esp_mesh_get_announce_interval(int *short_ms, int *long_ms);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* ESP32_ESP_MESH_INTERNAL_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_phy_init.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_phy_init.h
new file mode 100644
index 0000000000000000000000000000000000000000..08ac784adb3ad8cb94091853330cd899dc50d98b
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_phy_init.h
@@ -0,0 +1,219 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_PHY_INIT_H
+#define ESP32_ESP_PHY_INIT_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file PHY init parameters and API
+ */
+
+
+/**
+ * @brief Structure holding PHY init parameters
+ */
+typedef struct {
+    uint8_t params[128];                    /*!< opaque PHY initialization parameters */
+} esp_phy_init_data_t;
+
+/**
+ * @brief Opaque PHY calibration data
+ */
+typedef struct {
+    uint8_t version[4];                     /*!< PHY version */
+    uint8_t mac[6];                         /*!< The MAC address of the station */
+    uint8_t opaque[1894];                   /*!< calibration data */
+} esp_phy_calibration_data_t;
+
+typedef enum {
+    PHY_RF_CAL_PARTIAL = 0x00000000,        /*!< Do part of RF calibration. This should be used after power-on reset. */
+    PHY_RF_CAL_NONE    = 0x00000001,        /*!< Don't do any RF calibration. This mode is only suggested to be used after deep sleep reset. */
+    PHY_RF_CAL_FULL    = 0x00000002         /*!< Do full RF calibration. Produces best results, but also consumes a lot of time and current. Suggested to be used once. */
+} esp_phy_calibration_mode_t;
+
+
+/**
+ * @brief Modules for modem sleep
+ */
+typedef enum{
+    MODEM_BLE_MODULE,              //!< BLE controller used
+    MODEM_CLASSIC_BT_MODULE,       //!< Classic BT controller used
+    MODEM_WIFI_STATION_MODULE,     //!< Wi-Fi Station used
+    MODEM_WIFI_SOFTAP_MODULE,      //!< Wi-Fi SoftAP used
+    MODEM_WIFI_SNIFFER_MODULE,     //!< Wi-Fi Sniffer used
+    MODEM_WIFI_NULL_MODULE,        //!< Wi-Fi Null mode used
+    MODEM_USER_MODULE,             //!< User used
+    MODEM_MODULE_COUNT             //!< Number of items
+}modem_sleep_module_t;
+
+/**
+ * @brief Module WIFI mask for medem sleep
+ */
+#define MODEM_BT_MASK   ((1<<MODEM_BLE_MODULE)          |   \
+                         (1<<MODEM_CLASSIC_BT_MODULE))
+
+/**
+ * @brief Module WIFI mask for medem sleep
+ */
+#define MODEM_WIFI_MASK ((1<<MODEM_WIFI_STATION_MODULE) |   \
+                         (1<<MODEM_WIFI_SOFTAP_MODULE)  |   \
+                         (1<<MODEM_WIFI_SNIFFER_MODULE) |   \
+                         (1<<MODEM_WIFI_NULL_MODULE))
+
+/**
+ * @brief Modules needing to call phy_rf_init
+ */
+typedef enum{
+    PHY_BT_MODULE,          //!< Bluetooth used
+    PHY_WIFI_MODULE,        //!< Wi-Fi used
+    PHY_MODEM_MODULE,       //!< Modem sleep used
+    PHY_MODULE_COUNT        //!< Number of items
+}phy_rf_module_t;
+
+/**
+ * @brief Get PHY init data
+ *
+ * If "Use a partition to store PHY init data" option is set in menuconfig,
+ * This function will load PHY init data from a partition. Otherwise,
+ * PHY init data will be compiled into the application itself, and this function
+ * will return a pointer to PHY init data located in read-only memory (DROM).
+ *
+ * If "Use a partition to store PHY init data" option is enabled, this function
+ * may return NULL if the data loaded from flash is not valid.
+ *
+ * @note Call esp_phy_release_init_data to release the pointer obtained using
+ * this function after the call to esp_wifi_init.
+ *
+ * @return pointer to PHY init data structure
+ */
+const esp_phy_init_data_t* esp_phy_get_init_data(void);
+
+/**
+ * @brief Release PHY init data
+ * @param data  pointer to PHY init data structure obtained from
+ *              esp_phy_get_init_data function
+ */
+void esp_phy_release_init_data(const esp_phy_init_data_t* data);
+
+/**
+ * @brief Function called by esp_phy_init to load PHY calibration data
+ *
+ * This is a convenience function which can be used to load PHY calibration
+ * data from NVS. Data can be stored to NVS using esp_phy_store_cal_data_to_nvs
+ * function.
+ *
+ * If calibration data is not present in the NVS, or
+ * data is not valid (was obtained for a chip with a different MAC address,
+ * or obtained for a different version of software), this function will
+ * return an error.
+ *
+ * If "Initialize PHY in startup code" option is set in menuconfig, this
+ * function will be used to load calibration data. To provide a different
+ * mechanism for loading calibration data, disable
+ * "Initialize PHY in startup code" option in menuconfig and call esp_phy_init
+ * function from the application. For an example usage of esp_phy_init and
+ * this function, see esp_phy_store_cal_data_to_nvs function in cpu_start.c
+ *
+ * @param out_cal_data pointer to calibration data structure to be filled with
+ *                     loaded data.
+ * @return ESP_OK on success
+ */
+esp_err_t esp_phy_load_cal_data_from_nvs(esp_phy_calibration_data_t* out_cal_data);
+
+/**
+ * @brief Function called by esp_phy_init to store PHY calibration data
+ *
+ * This is a convenience function which can be used to store PHY calibration
+ * data to the NVS. Calibration data is returned by esp_phy_init function.
+ * Data saved using this function to the NVS can later be loaded using
+ * esp_phy_store_cal_data_to_nvs function.
+ *
+ * If "Initialize PHY in startup code" option is set in menuconfig, this
+ * function will be used to store calibration data. To provide a different
+ * mechanism for storing calibration data, disable
+ * "Initialize PHY in startup code" option in menuconfig and call esp_phy_init
+ * function from the application.
+ *
+ * @param cal_data pointer to calibration data which has to be saved.
+ * @return ESP_OK on success
+ */
+esp_err_t esp_phy_store_cal_data_to_nvs(const esp_phy_calibration_data_t* cal_data);
+
+/**
+ * @brief Initialize PHY and RF module
+ *
+ * PHY and RF module should be initialized in order to use WiFi or BT.
+ * Now PHY and RF initializing job is done automatically when start WiFi or BT. Users should not
+ * call this API in their application.
+ *
+ * @param init_data  PHY parameters. Default set of parameters can
+ *                   be obtained by calling esp_phy_get_default_init_data
+ *                   function.
+ * @param mode  Calibration mode (Full, partial, or no calibration)
+ * @param[inout] calibration_data
+ * @return ESP_OK on success.
+ * @return ESP_FAIL on fail.
+ */
+esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data,esp_phy_calibration_mode_t mode,
+        esp_phy_calibration_data_t* calibration_data, phy_rf_module_t module);
+
+/**
+ * @brief De-initialize PHY and RF module
+ *
+ * PHY module should be de-initialized in order to shutdown WiFi or BT.
+ * Now PHY and RF de-initializing job is done automatically when stop WiFi or BT. Users should not
+ * call this API in their application.
+ *
+ * @return ESP_OK on success.
+ */
+esp_err_t esp_phy_rf_deinit(phy_rf_module_t module);
+
+/**
+ * @brief Load calibration data from NVS and initialize PHY and RF module
+ */
+void esp_phy_load_cal_and_init(phy_rf_module_t module);
+
+/**
+ * @brief Module requires to enter modem sleep
+ */
+esp_err_t esp_modem_sleep_enter(modem_sleep_module_t module);
+
+/**
+ * @brief Module requires to exit modem sleep
+ */
+esp_err_t esp_modem_sleep_exit(modem_sleep_module_t module);
+
+/**
+ * @brief Register module to make it be able to require to enter/exit modem sleep
+ */
+esp_err_t esp_modem_sleep_register(modem_sleep_module_t module);
+
+/**
+ * @brief De-register module from modem sleep list
+ */
+esp_err_t esp_modem_sleep_deregister(modem_sleep_module_t module);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_PHY_INIT_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_sleep.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_sleep.h
new file mode 100644
index 0000000000000000000000000000000000000000..14a2a7c7fadaedb60bf1b90c534a22392d6148e9
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_sleep.h
@@ -0,0 +1,330 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_SLEEP_H
+#define ESP32_ESP_SLEEP_H
+
+#include <stdint.h>
+#include "esp_err.h"
+#include "periph/gpio.h"
+#include "driver/touch_pad.h"
+
+#define gpio_num_t gpio_t
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Logic function used for EXT1 wakeup mode.
+ */
+typedef enum {
+    ESP_EXT1_WAKEUP_ALL_LOW = 0,    //!< Wake the chip when all selected GPIOs go low
+    ESP_EXT1_WAKEUP_ANY_HIGH = 1    //!< Wake the chip when any of the selected GPIOs go high
+} esp_sleep_ext1_wakeup_mode_t;
+
+/**
+ * @brief Power domains which can be powered down in sleep mode
+ */
+typedef enum {
+    ESP_PD_DOMAIN_RTC_PERIPH,      //!< RTC IO, sensors and ULP co-processor
+    ESP_PD_DOMAIN_RTC_SLOW_MEM,    //!< RTC slow memory
+    ESP_PD_DOMAIN_RTC_FAST_MEM,    //!< RTC fast memory
+    ESP_PD_DOMAIN_XTAL,            //!< XTAL oscillator
+    ESP_PD_DOMAIN_MAX              //!< Number of domains
+} esp_sleep_pd_domain_t;
+
+/**
+ * @brief Power down options
+ */
+typedef enum {
+    ESP_PD_OPTION_OFF,      //!< Power down the power domain in sleep mode
+    ESP_PD_OPTION_ON,       //!< Keep power domain enabled during sleep mode
+    ESP_PD_OPTION_AUTO      //!< Keep power domain enabled in sleep mode, if it is needed by one of the wakeup options. Otherwise power it down.
+} esp_sleep_pd_option_t;
+
+/**
+ * @brief Sleep wakeup cause
+ */
+typedef enum {
+    ESP_SLEEP_WAKEUP_UNDEFINED,    //!< In case of deep sleep, reset was not caused by exit from deep sleep
+    ESP_SLEEP_WAKEUP_EXT0,         //!< Wakeup caused by external signal using RTC_IO
+    ESP_SLEEP_WAKEUP_EXT1,         //!< Wakeup caused by external signal using RTC_CNTL
+    ESP_SLEEP_WAKEUP_TIMER,        //!< Wakeup caused by timer
+    ESP_SLEEP_WAKEUP_TOUCHPAD,     //!< Wakeup caused by touchpad
+    ESP_SLEEP_WAKEUP_ULP,          //!< Wakeup caused by ULP program
+} esp_sleep_source_t;
+
+/* Leave this type define for compatibility */
+typedef esp_sleep_source_t esp_sleep_wakeup_cause_t;
+
+/**
+ * @brief Disable wakeup source
+ *
+ * This function is used to deactivate wake up trigger for source
+ * defined as parameter of the function.
+ *
+ * @note This function does not modify wake up configuration in RTC.
+ *       It will be performed in esp_sleep_start function.
+ *
+ * See docs/sleep-modes.rst for details.
+ *
+ * @param source - number of source to disable of type esp_sleep_source_t
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_STATE if trigger was not active
+ */
+esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source);
+
+/**
+ * @brief Enable wakeup by ULP coprocessor
+ * @note In revisions 0 and 1 of the ESP32, ULP wakeup source
+ *       can not be used when RTC_PERIPH power domain is forced
+ *       to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup
+ *       source is used.
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_STATE if ULP co-processor is not enabled or if wakeup triggers conflict
+ */
+esp_err_t esp_sleep_enable_ulp_wakeup(void);
+
+/**
+ * @brief Enable wakeup by timer
+ * @param time_in_us  time before wakeup, in microseconds
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if value is out of range (TBD)
+ */
+esp_err_t esp_sleep_enable_timer_wakeup(uint64_t time_in_us);
+
+/**
+ * @brief Enable wakeup by touch sensor
+ *
+ * @note In revisions 0 and 1 of the ESP32, touch wakeup source
+ *       can not be used when RTC_PERIPH power domain is forced
+ *       to be powered on (ESP_PD_OPTION_ON) or when ext0 wakeup
+ *       source is used.
+ *
+ * @note The FSM mode of the touch button should be configured
+ *       as the timer trigger mode.
+ *
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_STATE if wakeup triggers conflict
+ */
+esp_err_t esp_sleep_enable_touchpad_wakeup(void);
+
+/**
+ * @brief Get the touch pad which caused wakeup
+ *
+ * If wakeup was caused by another source, this function will return TOUCH_PAD_MAX;
+ *
+ * @return touch pad which caused wakeup
+ */
+touch_pad_t esp_sleep_get_touchpad_wakeup_status(void);
+
+/**
+ * @brief Enable wakeup using a pin
+ *
+ * This function uses external wakeup feature of RTC_IO peripheral.
+ * It will work only if RTC peripherals are kept on during sleep.
+ *
+ * This feature can monitor any pin which is an RTC IO. Once the pin transitions
+ * into the state given by level argument, the chip will be woken up.
+ *
+ * @note This function does not modify pin configuration. The pin is
+ *       configured in esp_sleep_start, immediately before entering sleep mode.
+ *
+ * @note In revisions 0 and 1 of the ESP32, ext0 wakeup source
+ *       can not be used together with touch or ULP wakeup sources.
+ *
+ * @param gpio_num  GPIO number used as wakeup source. Only GPIOs which are have RTC
+ *             functionality can be used: 0,2,4,12-15,25-27,32-39.
+ * @param level  input level which will trigger wakeup (0=low, 1=high)
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if the selected GPIO is not an RTC GPIO,
+ *        or the mode is invalid
+ *      - ESP_ERR_INVALID_STATE if wakeup triggers conflict
+ */
+esp_err_t esp_sleep_enable_ext0_wakeup(gpio_num_t gpio_num, int level);
+
+/**
+ * @brief Enable wakeup using multiple pins
+ *
+ * This function uses external wakeup feature of RTC controller.
+ * It will work even if RTC peripherals are shut down during sleep.
+ *
+ * This feature can monitor any number of pins which are in RTC IOs.
+ * Once any of the selected pins goes into the state given by mode argument,
+ * the chip will be woken up.
+ *
+ * @note This function does not modify pin configuration. The pins are
+ *       configured in esp_sleep_start, immediately before
+ *       entering sleep mode.
+ *
+ * @note internal pullups and pulldowns don't work when RTC peripherals are
+ *       shut down. In this case, external resistors need to be added.
+ *       Alternatively, RTC peripherals (and pullups/pulldowns) may be
+ *       kept enabled using esp_sleep_pd_config function.
+ *
+ * @param mask  bit mask of GPIO numbers which will cause wakeup. Only GPIOs
+ *              which are have RTC functionality can be used in this bit map:
+ *              0,2,4,12-15,25-27,32-39.
+ * @param mode select logic function used to determine wakeup condition:
+ *            - ESP_EXT1_WAKEUP_ALL_LOW: wake up when all selected GPIOs are low
+ *            - ESP_EXT1_WAKEUP_ANY_HIGH: wake up when any of the selected GPIOs is high
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if any of the selected GPIOs is not an RTC GPIO,
+ *        or mode is invalid
+ */
+esp_err_t esp_sleep_enable_ext1_wakeup(uint64_t mask, esp_sleep_ext1_wakeup_mode_t mode);
+
+
+/**
+ * @brief Get the bit mask of GPIOs which caused wakeup (ext1)
+ *
+ * If wakeup was caused by another source, this function will return 0.
+ *
+ * @return bit mask, if GPIOn caused wakeup, BIT(n) will be set
+ */
+uint64_t esp_sleep_get_ext1_wakeup_status(void);
+
+/**
+ * @brief Set power down mode for an RTC power domain in sleep mode
+ *
+ * If not set set using this API, all power domains default to ESP_PD_OPTION_AUTO.
+ *
+ * @param domain  power domain to configure
+ * @param option  power down option (ESP_PD_OPTION_OFF, ESP_PD_OPTION_ON, or ESP_PD_OPTION_AUTO)
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_INVALID_ARG if either of the arguments is out of range
+ */
+esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain,
+                                   esp_sleep_pd_option_t option);
+
+/**
+ * @brief Enter deep sleep with the configured wakeup options
+ *
+ * This function does not return.
+ */
+void esp_deep_sleep_start(void) __attribute__((noreturn));
+
+/**
+ * @brief Enter light sleep with the configured wakeup options
+ *
+ * @return
+ *  - ESP_OK on success (returned after wakeup)
+ *  - ESP_ERR_INVALID_STATE if WiFi or BT is not stopped
+ */
+esp_err_t esp_light_sleep_start(void);
+
+/**
+ * @brief Enter deep-sleep mode
+ *
+ * The device will automatically wake up after the deep-sleep time
+ * Upon waking up, the device calls deep sleep wake stub, and then proceeds
+ * to load application.
+ *
+ * Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup
+ * followed by a call to esp_deep_sleep_start.
+ *
+ * esp_deep_sleep does not shut down WiFi, BT, and higher level protocol
+ * connections gracefully.
+ * Make sure relevant WiFi and BT stack functions are called to close any
+ * connections and deinitialize the peripherals. These include:
+ *     - esp_bluedroid_disable
+ *     - esp_bt_controller_disable
+ *     - esp_wifi_stop
+ *
+ * This function does not return.
+ *
+ * @param time_in_us  deep-sleep time, unit: microsecond
+ */
+void esp_deep_sleep(uint64_t time_in_us) __attribute__((noreturn));
+
+/**
+ * @brief Enter deep-sleep mode
+ *
+ * Function has been renamed to esp_deep_sleep.
+ * This name is deprecated and will be removed in a future version.
+ *
+ * @param time_in_us  deep-sleep time, unit: microsecond
+ */
+void system_deep_sleep(uint64_t time_in_us) __attribute__((noreturn, deprecated));
+
+
+/**
+ * @brief Get the source which caused wakeup from sleep
+ *
+ * @return wakeup cause, or ESP_DEEP_SLEEP_WAKEUP_UNDEFINED if reset happened for reason other than deep sleep wakeup
+ */
+esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void);
+
+
+/**
+ * @brief Default stub to run on wake from deep sleep.
+ *
+ * Allows for executing code immediately on wake from sleep, before
+ * the software bootloader or ESP-IDF app has started up.
+ *
+ * This function is weak-linked, so you can implement your own version
+ * to run code immediately when the chip wakes from
+ * sleep.
+ *
+ * See docs/deep-sleep-stub.rst for details.
+ */
+void esp_wake_deep_sleep(void);
+
+/**
+ * @brief Function type for stub to run on wake from sleep.
+ *
+ */
+typedef void (*esp_deep_sleep_wake_stub_fn_t)(void);
+
+/**
+ * @brief Install a new stub at runtime to run on wake from deep sleep
+ *
+ * If implementing esp_wake_deep_sleep() then it is not necessary to
+ * call this function.
+ *
+ * However, it is possible to call this function to substitute a
+ * different deep sleep stub. Any function used as a deep sleep stub
+ * must be marked RTC_IRAM_ATTR, and must obey the same rules given
+ * for esp_wake_deep_sleep().
+ */
+void esp_set_deep_sleep_wake_stub(esp_deep_sleep_wake_stub_fn_t new_stub);
+
+/**
+ * @brief Get current wake from deep sleep stub
+ * @return Return current wake from deep sleep stub, or NULL if
+ *         no stub is installed.
+ */
+esp_deep_sleep_wake_stub_fn_t esp_get_deep_sleep_wake_stub(void);
+
+/**
+ *  @brief The default esp-idf-provided esp_wake_deep_sleep() stub.
+ *
+ *  See docs/deep-sleep-stub.rst for details.
+ */
+void esp_default_wake_deep_sleep(void);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_SLEEP_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_spiram.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_spiram.h
new file mode 100644
index 0000000000000000000000000000000000000000..ba0a200618f43a64feee3afdecc890a7d90c6a37
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_spiram.h
@@ -0,0 +1,97 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+#ifndef ESP32_ESP_SPIRAM_H
+#define ESP32_ESP_SPIRAM_H
+
+#include <stddef.h>
+#include <stdint.h>
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize spiram interface/hardware. Normally called from cpu_start.c.
+ *
+ * @return ESP_OK on success
+ */
+esp_err_t esp_spiram_init(void);
+
+/**
+ * @brief Configure Cache/MMU for access to external SPI RAM.
+ *
+ * Normally this function is called from cpu_start, if CONFIG_SPIRAM_BOOT_INIT
+ * option is enabled. Applications which need to enable SPI RAM at run time
+ * can disable CONFIG_SPIRAM_BOOT_INIT, and call this function later.
+ *
+ * @attention this function must be called with flash cache disabled.
+ */
+void esp_spiram_init_cache(void);
+
+
+/**
+ * @brief Memory test for SPI RAM. Should be called after SPI RAM is initialized and
+ * (in case of a dual-core system) the app CPU is online. This test overwrites the
+ * memory with crap, so do not call after e.g. the heap allocator has stored important
+ * stuff in SPI RAM.
+ *
+ * @return true on success, false on failed memory test
+ */
+bool esp_spiram_test(void);
+
+
+/**
+ * @brief Add the initialized SPI RAM to the heap allocator.
+ */
+esp_err_t esp_spiram_add_to_heapalloc(void);
+
+
+/**
+ * @brief Get the size of the attached SPI RAM chip selected in menuconfig
+ *
+ * @return Size in bytes, or 0 if no external RAM chip support compiled in.
+ */
+size_t esp_spiram_get_size(void);
+
+
+/**
+ * @brief Force a writeback of the data in the SPI RAM cache. This is to be called whenever
+ * cache is disabled, because disabling cache on the ESP32 discards the data in the SPI
+ * RAM cache.
+ *
+ * This is meant for use from within the SPI flash code.
+ */
+void esp_spiram_writeback_cache(void);
+
+
+
+/**
+ * @brief Reserve a pool of internal memory for specific DMA/internal allocations
+ *
+ * @param size Size of reserved pool in bytes
+ *
+ * @return
+ *          - ESP_OK on success
+ *          - ESP_ERR_NO_MEM when no memory available for pool
+ */
+esp_err_t esp_spiram_reserve_dma_pool(size_t size);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_SPIRAM_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_system.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_system.h
new file mode 100644
index 0000000000000000000000000000000000000000..f312409fe7821915a3fe5c9a2c2a77b11f6e234f
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_system.h
@@ -0,0 +1,295 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_SYSTEM_H
+#define ESP32_ESP_SYSTEM_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "esp_err.h"
+#include "esp_sleep.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef enum {
+    ESP_MAC_WIFI_STA,
+    ESP_MAC_WIFI_SOFTAP,
+    ESP_MAC_BT,
+    ESP_MAC_ETH,
+} esp_mac_type_t;
+
+#define TWO_UNIVERSAL_MAC_ADDR 2
+#define FOUR_UNIVERSAL_MAC_ADDR 4
+#define UNIVERSAL_MAC_ADDR_NUM CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS
+
+/**
+  * @attention  application don't need to call this function anymore. It do nothing and will
+  *             be removed in future version.
+  */
+void system_init(void) __attribute__ ((deprecated));
+
+/**
+  * @brief  Reset to default settings.
+  *
+  * Function has been deprecated, please use esp_wifi_restore instead.
+  * This name will be removed in a future release.
+  */
+void system_restore(void) __attribute__ ((deprecated));
+
+typedef void (*shutdown_handler_t)(void);
+/**
+  * @brief  Register shutdown handler
+  *
+  * This function allows you to register a handler that gets invoked before a
+  * systematic shutdown of the chip.
+  */
+esp_err_t esp_register_shutdown_handler(shutdown_handler_t handle);
+
+/**
+  * @brief  Restart PRO and APP CPUs.
+  *
+  * This function can be called both from PRO and APP CPUs.
+  * After successful restart, CPU reset reason will be SW_CPU_RESET.
+  * Peripherals (except for WiFi, BT, UART0, SPI1, and legacy timers) are not reset.
+  * This function does not return.
+  */
+void esp_restart(void) __attribute__ ((noreturn));
+
+/**
+  * @brief  Internal function to restart PRO and APP CPUs.
+  *
+  * @note This function should not be called from FreeRTOS applications.
+  *       Use esp_restart instead.
+  *
+  * This is an internal function called by esp_restart. It is called directly
+  * by the panic handler and brownout detector interrupt.
+  */
+void esp_restart_noos(void) __attribute__ ((noreturn));
+
+/**
+  * @brief  Restart system.
+  *
+  * Function has been renamed to esp_restart.
+  * This name will be removed in a future release.
+  */
+void system_restart(void) __attribute__ ((deprecated, noreturn));
+
+/**
+  * @brief  Get system time, unit: microsecond.
+  *
+  * This function is deprecated. Use 'gettimeofday' function for 64-bit precision.
+  * This definition will be removed in a future release.
+  */
+/* uint32_t system_get_time(void)  __attribute__ ((deprecated)); */
+
+/**
+  * @brief  Get the size of available heap.
+  *
+  * Note that the returned value may be larger than the maximum contiguous block
+  * which can be allocated.
+  *
+  * @return Available heap size, in bytes.
+  */
+uint32_t esp_get_free_heap_size(void);
+
+/**
+  * @brief  Get the size of available heap.
+  *
+  * Function has been renamed to esp_get_free_heap_size.
+  * This name will be removed in a future release.
+  *
+  * @return Available heap size, in bytes.
+  */
+uint32_t system_get_free_heap_size(void)  __attribute__ ((deprecated));
+
+/**
+  * @brief Get the minimum heap that has ever been available
+  *
+  * @return Minimum free heap ever available
+  */
+uint32_t esp_get_minimum_free_heap_size( void );
+
+/**
+ * @brief  Get one random 32-bit word from hardware RNG
+ *
+ * The hardware RNG is fully functional whenever an RF subsystem is running (ie Bluetooth or WiFi is enabled). For secure
+ * random values, call this function after WiFi or Bluetooth are started.
+ *
+ * When the app is running without an RF subsystem enabled, it should be considered a PRNG. To help improve this
+ * situation, the RNG is pre-seeded with entropy while the IDF bootloader is running. However no new entropy is
+ * available during the window of time between when the bootloader exits and an RF subsystem starts. It may be possible
+ * to discern a non-random pattern in a very large amount of output captured during this window of time.
+ *
+ * @return Random value between 0 and UINT32_MAX
+ */
+uint32_t esp_random(void);
+
+/**
+  * @brief  Set base MAC address with the MAC address which is stored in BLK3 of EFUSE or
+  *         external storage e.g. flash and EEPROM.
+  *
+  * Base MAC address is used to generate the MAC addresses used by the networking interfaces.
+  * If using base MAC address stored in BLK3 of EFUSE or external storage, call this API to set base MAC
+  * address with the MAC address which is stored in BLK3 of EFUSE or external storage before initializing
+  * WiFi/BT/Ethernet.
+  *
+  * @param  mac  base MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
+  */
+esp_err_t esp_base_mac_addr_set(uint8_t *mac);
+
+/**
+  * @brief  Return base MAC address which is set using esp_base_mac_addr_set.
+  *
+  * @param  mac  base MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
+  *         ESP_ERR_INVALID_MAC base MAC address has not been set
+  */
+esp_err_t esp_base_mac_addr_get(uint8_t *mac);
+
+/**
+  * @brief  Return base MAC address which was previously written to BLK3 of EFUSE.
+  *
+  * Base MAC address is used to generate the MAC addresses used by the networking interfaces.
+  * This API returns the custom base MAC address which was previously written to BLK3 of EFUSE.
+  * Writing this EFUSE allows setting of a different (non-Espressif) base MAC address. It is also
+  * possible to store a custom base MAC address elsewhere, see esp_base_mac_addr_set() for details.
+  *
+  * @param  mac  base MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
+  *         ESP_ERR_INVALID_VERSION An invalid MAC version field was read from BLK3 of EFUSE
+  *         ESP_ERR_INVALID_CRC An invalid MAC CRC was read from BLK3 of EFUSE
+  */
+esp_err_t esp_efuse_mac_get_custom(uint8_t *mac);
+
+/**
+  * @brief  Return base MAC address which is factory-programmed by Espressif in BLK0 of EFUSE.
+  *
+  * @param  mac  base MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
+  */
+esp_err_t esp_efuse_mac_get_default(uint8_t *mac);
+
+/**
+  * @brief  Read hardware MAC address from efuse.
+  *
+  * Function has been renamed to esp_efuse_mac_get_default.
+  * This name will be removed in a future release.
+  *
+  * @param  mac  hardware MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
+  */
+esp_err_t esp_efuse_read_mac(uint8_t *mac) __attribute__ ((deprecated));
+
+/**
+  * @brief  Read hardware MAC address.
+  *
+  * Function has been renamed to esp_efuse_mac_get_default.
+  * This name will be removed in a future release.
+  *
+  * @param  mac  hardware MAC address, length: 6 bytes.
+  * @return ESP_OK on success
+  */
+esp_err_t system_efuse_read_mac(uint8_t *mac) __attribute__ ((deprecated));
+
+/**
+  * @brief  Read base MAC address and set MAC address of the interface.
+  *
+  * This function first get base MAC address using esp_base_mac_addr_get or reads base MAC address
+  * from BLK0 of EFUSE. Then set the MAC address of the interface including wifi station, wifi softap,
+  * bluetooth and ethernet.
+  *
+  * @param  mac  MAC address of the interface, length: 6 bytes.
+  * @param  type  type of MAC address, 0:wifi station, 1:wifi softap, 2:bluetooth, 3:ethernet.
+  *
+  * @return ESP_OK on success
+  */
+esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type);
+
+/**
+  * @brief  Derive local MAC address from universal MAC address.
+  *
+  * This function derives a local MAC address from an universal MAC address.
+  * A `definition of local vs universal MAC address can be found on Wikipedia
+  * <https://en.wikipedia.org/wiki/MAC_address#Universal_vs._local>`.
+  * In ESP32, universal MAC address is generated from base MAC address in EFUSE or other external storage.
+  * Local MAC address is derived from the universal MAC address.
+  *
+  * @param  local_mac  Derived local MAC address, length: 6 bytes.
+  * @param  universal_mac  Source universal MAC address, length: 6 bytes.
+  *
+  * @return ESP_OK on success
+  */
+esp_err_t esp_derive_local_mac(uint8_t* local_mac, const uint8_t* universal_mac);
+
+/**
+ * Get SDK version
+ *
+ * This function is deprecated and will be removed in a future release.
+ *
+ * @return constant string "master"
+ */
+const char* system_get_sdk_version(void)  __attribute__ ((deprecated));
+
+/**
+ * Get IDF version
+ *
+ * @return constant string from IDF_VER
+ */
+const char* esp_get_idf_version(void);
+
+
+/**
+ * @brief Chip models
+ */
+typedef enum {
+    CHIP_ESP32 = 1, //!< ESP32
+} esp_chip_model_t;
+
+/**
+ * Chip feature flags, used in esp_chip_info_t
+ */
+#define CHIP_FEATURE_EMB_FLASH      BIT(0)
+#define CHIP_FEATURE_WIFI_BGN       BIT(1)
+#define CHIP_FEATURE_BLE            BIT(4)
+#define CHIP_FEATURE_BT             BIT(5)
+
+/**
+ * @brief The structure represents information about the chip
+ */
+typedef struct {
+    esp_chip_model_t model;  //!< chip model, one of esp_chip_model_t
+    uint32_t features;       //!< bit mask of CHIP_FEATURE_x feature flags
+    uint8_t cores;           //!< number of CPU cores
+    uint8_t revision;        //!< chip revision number
+} esp_chip_info_t;
+
+/**
+ * @brief Fill an esp_chip_info_t structure with information about the chip
+ * @param[out] out_info structure to be filled
+ */
+void esp_chip_info(esp_chip_info_t* out_info);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_SYSTEM_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_task_wdt.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_task_wdt.h
new file mode 100644
index 0000000000000000000000000000000000000000..22d7d4bd5d33c69117b92ded665ef075f0ec3bcc
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_task_wdt.h
@@ -0,0 +1,166 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_ESP_TASK_WDT_H
+#define ESP32_ESP_TASK_WDT_H
+
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+#include "esp_err.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+  * @brief  Initialize the Task Watchdog Timer (TWDT)
+  *
+  * This function configures and initializes the TWDT. If the TWDT is already
+  * initialized when this function is called, this function will update the
+  * TWDT's timeout period and panic configurations instead. After initializing
+  * the TWDT, any task can elect to be watched by the TWDT by subscribing to it
+  * using esp_task_wdt_add().
+  *
+  * @param[in]  timeout     Timeout period of TWDT in seconds
+  * @param[in]  panic       Flag that controls whether the panic handler will be
+  *                         executed when the TWDT times out
+  *
+  * @return
+  *     - ESP_OK: Initialization was successful
+  *     - ESP_ERR_NO_MEM: Initialization failed due to lack of memory
+  *
+  * @note   esp_task_wdt_init() must only be called after the scheduler
+  *         started
+  */
+esp_err_t esp_task_wdt_init(uint32_t timeout, bool panic);
+
+/**
+ * @brief   Deinitialize the Task Watchdog Timer (TWDT)
+ *
+ * This function will deinitialize the TWDT. Calling this function whilst tasks
+ * are still subscribed to the TWDT, or when the TWDT is already deinitialized,
+ * will result in an error code being returned.
+ *
+ * @return
+ *      - ESP_OK: TWDT successfully deinitialized
+ *      - ESP_ERR_INVALID_STATE: Error, tasks are still subscribed to the TWDT
+ *      - ESP_ERR_NOT_FOUND: Error, TWDT has already been deinitialized
+ */
+esp_err_t esp_task_wdt_deinit(void);
+
+/**
+  * @brief  Subscribe a task to the Task Watchdog Timer (TWDT)
+  *
+  * This function subscribes a task to the TWDT. Each subscribed task must
+  * periodically call esp_task_wdt_reset() to prevent the TWDT from elapsing its
+  * timeout period. Failure to do so will result in a TWDT timeout. If the task
+  * being subscribed is one of the Idle Tasks, this function will automatically
+  * enable esp_task_wdt_reset() to called from the Idle Hook of the Idle Task.
+  * Calling this function whilst the TWDT is uninitialized or attempting to
+  * subscribe an already subscribed task will result in an error code being
+  * returned.
+  *
+  * @param[in]  handle  Handle of the task. Input NULL to subscribe the current
+  *                     running task to the TWDT
+  *
+  * @return
+  *     - ESP_OK: Successfully subscribed the task to the TWDT
+  *     - ESP_ERR_INVALID_ARG: Error, the task is already subscribed
+  *     - ESP_ERR_NO_MEM: Error, could not subscribe the task due to lack of
+  *                       memory
+  *     - ESP_ERR_INVALID_STATE: Error, the TWDT has not been initialized yet
+  */
+esp_err_t esp_task_wdt_add(TaskHandle_t handle);
+
+/**
+  * @brief  Reset the Task Watchdog Timer (TWDT) on behalf of the currently
+  *         running task
+  *
+  * This function will reset the TWDT on behalf of the currently running task.
+  * Each subscribed task must periodically call this function to prevent the
+  * TWDT from timing out. If one or more subscribed tasks fail to reset the
+  * TWDT on their own behalf, a TWDT timeout will occur. If the IDLE tasks have
+  * been subscribed to the TWDT, they will automatically call this function from
+  * their idle hooks. Calling this function from a task that has not subscribed
+  * to the TWDT, or when the TWDT is uninitialized will result in an error code
+  * being returned.
+  *
+  * @return
+  *     - ESP_OK: Successfully reset the TWDT on behalf of the currently
+  *               running task
+  *     - ESP_ERR_NOT_FOUND: Error, the current running task has not subscribed
+  *                          to the TWDT
+  *     - ESP_ERR_INVALID_STATE: Error, the TWDT has not been initialized yet
+  */
+esp_err_t esp_task_wdt_reset(void);
+
+/**
+  * @brief  Unsubscribes a task from the Task Watchdog Timer (TWDT)
+  *
+  * This function will unsubscribe a task from the TWDT. After being
+  * unsubscribed, the task should no longer call esp_task_wdt_reset(). If the
+  * task is an IDLE task, this function will automatically disable the calling
+  * of esp_task_wdt_reset() from the Idle Hook. Calling this function whilst the
+  * TWDT is uninitialized or attempting to unsubscribe an already unsubscribed
+  * task from the TWDT will result in an error code being returned.
+  *
+  * @param[in]  handle  Handle of the task. Input NULL to unsubscribe the
+  *                     current running task.
+  *
+  * @return
+  *     - ESP_OK: Successfully unsubscribed the task from the TWDT
+  *     - ESP_ERR_INVALID_ARG: Error, the task is already unsubscribed
+  *     - ESP_ERR_INVALID_STATE: Error, the TWDT has not been initialized yet
+  */
+esp_err_t esp_task_wdt_delete(TaskHandle_t handle);
+
+/**
+  * @brief   Query whether a task is subscribed to the Task Watchdog Timer (TWDT)
+  *
+  * This function will query whether a task is currently subscribed to the TWDT,
+  * or whether the TWDT is initialized.
+  *
+  * @param[in]  handle  Handle of the task. Input NULL to query the current
+  *                     running task.
+  *
+  * @return:
+  *     - ESP_OK: The task is currently subscribed to the TWDT
+  *     - ESP_ERR_NOT_FOUND: The task is currently not subscribed to the TWDT
+  *     - ESP_ERR_INVALID_STATE: The TWDT is not initialized, therefore no tasks
+  *                              can be subscribed
+  */
+esp_err_t esp_task_wdt_status(TaskHandle_t handle);
+
+/**
+  * @brief      Reset the TWDT on behalf of the current running task, or
+  *             subscribe the TWDT to if it has not done so already
+  *
+  * @warning    This function is deprecated, use esp_task_wdt_add() and
+  *             esp_task_wdt_reset() instead
+  *
+  * This function is similar to esp_task_wdt_reset() and will reset the TWDT on
+  * behalf of the current running task. However if this task has not subscribed
+  * to the TWDT, this function will automatically subscribe the task. Therefore,
+  * an unsubscribed task will subscribe to the TWDT on its first call to this
+  * function, then proceed to reset the TWDT on subsequent calls of this
+  * function.
+  */
+void esp_task_wdt_feed(void) __attribute__ ((deprecated));
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_TASK_WDT_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_wifi.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_wifi.h
new file mode 100755
index 0000000000000000000000000000000000000000..ffd8c6935ac0d0c543de9392245b02de7928966a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_wifi.h
@@ -0,0 +1,1084 @@
+// 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.
+
+
+/*               Notes about WiFi Programming
+ *
+ *  The esp32 WiFi programming model can be depicted as following picture:
+ *
+ *
+ *                            default handler              user handler
+ *  -------------             ---------------             ---------------
+ *  |           |   event     |             | callback or |             |
+ *  |   tcpip   | --------->  |    event    | ----------> | application |
+ *  |   stack   |             |     task    |  event      |    task     |
+ *  |-----------|             |-------------|             |-------------|
+ *                                  /|\                          |
+ *                                   |                           |
+ *                            event  |                           |
+ *                                   |                           |
+ *                                   |                           |
+ *                             ---------------                   |
+ *                             |             |                   |
+ *                             | WiFi Driver |/__________________|
+ *                             |             |\     API call
+ *                             |             |
+ *                             |-------------|
+ *
+ * The WiFi driver can be consider as black box, it knows nothing about the high layer code, such as
+ * TCPIP stack, application task, event task etc, all it can do is to receive API call from high layer
+ * or post event queue to a specified Queue, which is initialized by API esp_wifi_init().
+ *
+ * The event task is a daemon task, which receives events from WiFi driver or from other subsystem, such
+ * as TCPIP stack, event task will call the default callback function on receiving the event. For example,
+ * on receiving event SYSTEM_EVENT_STA_CONNECTED, it will call tcpip_adapter_start() to start the DHCP
+ * client in it's default handler.
+ *
+ * Application can register it's own event callback function by API esp_event_init, then the application callback
+ * function will be called after the default callback. Also, if application doesn't want to execute the callback
+ * in the event task, what it needs to do is to post the related event to application task in the application callback function.
+ *
+ * The application task (code) generally mixes all these thing together, it calls APIs to init the system/WiFi and
+ * handle the events when necessary.
+ *
+ */
+
+#ifndef ESP32_ESP_WIFI_H
+#define ESP32_ESP_WIFI_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "rom/queue.h"
+#include "sdk_conf.h"
+#include "esp_err.h"
+#include "esp_wifi_types.h"
+#include "esp_wifi_crypto_types.h"
+#include "esp_event.h"
+#include "esp_wifi_os_adapter.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP_ERR_WIFI_NOT_INIT    (ESP_ERR_WIFI_BASE + 1)   /*!< WiFi driver was not installed by esp_wifi_init */
+#define ESP_ERR_WIFI_NOT_STARTED (ESP_ERR_WIFI_BASE + 2)   /*!< WiFi driver was not started by esp_wifi_start */
+#define ESP_ERR_WIFI_NOT_STOPPED (ESP_ERR_WIFI_BASE + 3)   /*!< WiFi driver was not stopped by esp_wifi_stop */
+#define ESP_ERR_WIFI_IF          (ESP_ERR_WIFI_BASE + 4)   /*!< WiFi interface error */
+#define ESP_ERR_WIFI_MODE        (ESP_ERR_WIFI_BASE + 5)   /*!< WiFi mode error */
+#define ESP_ERR_WIFI_STATE       (ESP_ERR_WIFI_BASE + 6)   /*!< WiFi internal state error */
+#define ESP_ERR_WIFI_CONN        (ESP_ERR_WIFI_BASE + 7)   /*!< WiFi internal control block of station or soft-AP error */
+#define ESP_ERR_WIFI_NVS         (ESP_ERR_WIFI_BASE + 8)   /*!< WiFi internal NVS module error */
+#define ESP_ERR_WIFI_MAC         (ESP_ERR_WIFI_BASE + 9)   /*!< MAC address is invalid */
+#define ESP_ERR_WIFI_SSID        (ESP_ERR_WIFI_BASE + 10)   /*!< SSID is invalid */
+#define ESP_ERR_WIFI_PASSWORD    (ESP_ERR_WIFI_BASE + 11)  /*!< Password is invalid */
+#define ESP_ERR_WIFI_TIMEOUT     (ESP_ERR_WIFI_BASE + 12)  /*!< Timeout error */
+#define ESP_ERR_WIFI_WAKE_FAIL   (ESP_ERR_WIFI_BASE + 13)  /*!< WiFi is in sleep state(RF closed) and wakeup fail */
+#define ESP_ERR_WIFI_WOULD_BLOCK (ESP_ERR_WIFI_BASE + 14)  /*!< The caller would block */
+#define ESP_ERR_WIFI_NOT_CONNECT (ESP_ERR_WIFI_BASE + 15)  /*!< Station still in disconnect status */
+
+/**
+ * @brief WiFi stack configuration parameters passed to esp_wifi_init call.
+ */
+typedef struct {
+    system_event_handler_t event_handler;          /**< WiFi event handler */
+    wifi_osi_funcs_t*      osi_funcs;              /**< WiFi OS functions */
+    wpa_crypto_funcs_t     wpa_crypto_funcs;       /**< WiFi station crypto functions when connect */
+    int                    static_rx_buf_num;      /**< WiFi static RX buffer number */
+    int                    dynamic_rx_buf_num;     /**< WiFi dynamic RX buffer number */
+    int                    tx_buf_type;            /**< WiFi TX buffer type */
+    int                    static_tx_buf_num;      /**< WiFi static TX buffer number */
+    int                    dynamic_tx_buf_num;     /**< WiFi dynamic TX buffer number */
+    int                    csi_enable;             /**< WiFi channel state information enable flag */
+    int                    ampdu_rx_enable;        /**< WiFi AMPDU RX feature enable flag */
+    int                    ampdu_tx_enable;        /**< WiFi AMPDU TX feature enable flag */
+    int                    nvs_enable;             /**< WiFi NVS flash enable flag */
+    int                    nano_enable;            /**< Nano option for printf/scan family enable flag */
+    int                    tx_ba_win;              /**< WiFi Block Ack TX window size */
+    int                    rx_ba_win;              /**< WiFi Block Ack RX window size */
+    int                    wifi_task_core_id;      /**< WiFi Task Core ID */
+    int                    magic;                  /**< WiFi init magic number, it should be the last field */
+} wifi_init_config_t;
+
+#ifdef CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM
+#define WIFI_STATIC_TX_BUFFER_NUM CONFIG_ESP32_WIFI_STATIC_TX_BUFFER_NUM
+#else
+#define WIFI_STATIC_TX_BUFFER_NUM 0
+#endif
+
+#ifdef CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
+#define WIFI_DYNAMIC_TX_BUFFER_NUM CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM
+#else
+#define WIFI_DYNAMIC_TX_BUFFER_NUM 0
+#endif
+
+#if CONFIG_ESP32_WIFI_CSI_ENABLED
+#define WIFI_CSI_ENABLED         1
+#else
+#define WIFI_CSI_ENABLED         0
+#endif
+
+#if CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED
+#define WIFI_AMPDU_RX_ENABLED        1
+#else
+#define WIFI_AMPDU_RX_ENABLED        0
+#endif
+
+#if CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED
+#define WIFI_AMPDU_TX_ENABLED        1
+#else
+#define WIFI_AMPDU_TX_ENABLED        0
+#endif
+
+#if CONFIG_ESP32_WIFI_NVS_ENABLED
+#define WIFI_NVS_ENABLED          1
+#else
+#define WIFI_NVS_ENABLED          0
+#endif
+
+#if CONFIG_NEWLIB_NANO_FORMAT
+#define WIFI_NANO_FORMAT_ENABLED  1
+#else
+#define WIFI_NANO_FORMAT_ENABLED  0
+#endif
+
+extern const wpa_crypto_funcs_t g_wifi_default_wpa_crypto_funcs;
+
+#define WIFI_INIT_CONFIG_MAGIC    0x1F2F3F4F
+
+#ifdef CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED
+#define WIFI_DEFAULT_TX_BA_WIN CONFIG_ESP32_WIFI_TX_BA_WIN
+#else
+#define WIFI_DEFAULT_TX_BA_WIN 0 /* unused if ampdu_tx_enable == false */
+#endif
+
+#ifdef CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED
+#define WIFI_DEFAULT_RX_BA_WIN CONFIG_ESP32_WIFI_RX_BA_WIN
+#else
+#define WIFI_DEFAULT_RX_BA_WIN 0 /* unused if ampdu_rx_enable == false */
+#endif
+
+#if CONFIG_ESP32_WIFI_TASK_PINNED_TO_CORE_1
+#define WIFI_TASK_CORE_ID 1
+#else
+#define WIFI_TASK_CORE_ID 0
+#endif
+
+#define WIFI_INIT_CONFIG_DEFAULT() { \
+    .event_handler = &esp_event_send, \
+    .osi_funcs = &g_wifi_osi_funcs, \
+    .wpa_crypto_funcs = g_wifi_default_wpa_crypto_funcs, \
+    .static_rx_buf_num = CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM,\
+    .dynamic_rx_buf_num = CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM,\
+    .tx_buf_type = CONFIG_ESP32_WIFI_TX_BUFFER_TYPE,\
+    .static_tx_buf_num = WIFI_STATIC_TX_BUFFER_NUM,\
+    .dynamic_tx_buf_num = WIFI_DYNAMIC_TX_BUFFER_NUM,\
+    .csi_enable = WIFI_CSI_ENABLED,\
+    .ampdu_rx_enable = WIFI_AMPDU_RX_ENABLED,\
+    .ampdu_tx_enable = WIFI_AMPDU_TX_ENABLED,\
+    .nvs_enable = WIFI_NVS_ENABLED,\
+    .nano_enable = WIFI_NANO_FORMAT_ENABLED,\
+    .tx_ba_win = WIFI_DEFAULT_TX_BA_WIN,\
+    .rx_ba_win = WIFI_DEFAULT_RX_BA_WIN,\
+    .wifi_task_core_id = WIFI_TASK_CORE_ID,\
+    .magic = WIFI_INIT_CONFIG_MAGIC\
+};
+
+/**
+  * @brief  Init WiFi
+  *         Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer,
+  *         WiFi NVS structure etc, this WiFi also start WiFi task
+  *
+  * @attention 1. This API must be called before all other WiFi API can be called
+  * @attention 2. Always use WIFI_INIT_CONFIG_DEFAULT macro to init the config to default values, this can
+  *               guarantee all the fields got correct value when more fields are added into wifi_init_config_t
+  *               in future release. If you want to set your owner initial values, overwrite the default values
+  *               which are set by WIFI_INIT_CONFIG_DEFAULT, please be notified that the field 'magic' of
+  *               wifi_init_config_t should always be WIFI_INIT_CONFIG_MAGIC!
+  *
+  * @param  config pointer to WiFi init configuration structure; can point to a temporary variable.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_NO_MEM: out of memory
+  *    - others: refer to error code esp_err.h
+  */
+esp_err_t esp_wifi_init(const wifi_init_config_t *config);
+
+/**
+  * @brief  Deinit WiFi
+  *         Free all resource allocated in esp_wifi_init and stop WiFi task
+  *
+  * @attention 1. This API should be called if you want to remove WiFi driver from the system
+  *
+  * @return ESP_OK: succeed
+  */
+esp_err_t esp_wifi_deinit(void);
+
+/**
+  * @brief     Set the WiFi operating mode
+  *
+  *            Set the WiFi operating mode as station, soft-AP or station+soft-AP,
+  *            The default mode is soft-AP mode.
+  *
+  * @param     mode  WiFi operating mode
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - others: refer to error code in esp_err.h
+  */
+esp_err_t esp_wifi_set_mode(wifi_mode_t mode);
+
+/**
+  * @brief  Get current operating mode of WiFi
+  *
+  * @param[out]  mode  store current WiFi mode
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_mode(wifi_mode_t *mode);
+
+/**
+  * @brief  Start WiFi according to current configuration
+  *         If mode is WIFI_MODE_STA, it create station control block and start station
+  *         If mode is WIFI_MODE_AP, it create soft-AP control block and start soft-AP
+  *         If mode is WIFI_MODE_APSTA, it create soft-AP and station control block and start soft-AP and station
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_NO_MEM: out of memory
+  *    - ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong
+  *    - ESP_FAIL: other WiFi internal errors
+  */
+esp_err_t esp_wifi_start(void);
+
+/**
+  * @brief  Stop WiFi
+  *         If mode is WIFI_MODE_STA, it stop station and free station control block
+  *         If mode is WIFI_MODE_AP, it stop soft-AP and free soft-AP control block
+  *         If mode is WIFI_MODE_APSTA, it stop station/soft-AP and free station/soft-AP control block
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_stop(void);
+
+/**
+ * @brief  Restore WiFi stack persistent settings to default values
+ *
+ * This function will reset settings made using the following APIs:
+ * - esp_wifi_get_auto_connect,
+ * - esp_wifi_set_protocol,
+ * - esp_wifi_set_config related
+ * - esp_wifi_set_mode
+ *
+ * @return
+ *    - ESP_OK: succeed
+ *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+ */
+esp_err_t esp_wifi_restore(void);
+
+/**
+  * @brief     Connect the ESP32 WiFi station to the AP.
+  *
+  * @attention 1. This API only impact WIFI_MODE_STA or WIFI_MODE_APSTA mode
+  * @attention 2. If the ESP32 is connected to an AP, call esp_wifi_disconnect to disconnect.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_CONN: WiFi internal error, station or soft-AP control block wrong
+  *    - ESP_ERR_WIFI_SSID: SSID of AP which station connects is invalid
+  */
+esp_err_t esp_wifi_connect(void);
+
+/**
+  * @brief     Disconnect the ESP32 WiFi station from the AP.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi was not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
+  *    - ESP_FAIL: other WiFi internal errors
+  */
+esp_err_t esp_wifi_disconnect(void);
+
+/**
+  * @brief     Currently this API is just an stub API
+  *
+
+  * @return
+  *    - ESP_OK: succeed
+  *    - others: fail
+  */
+esp_err_t esp_wifi_clear_fast_connect(void);
+
+/**
+  * @brief     deauthenticate all stations or associated id equals to aid
+  *
+  * @param     aid  when aid is 0, deauthenticate all stations, otherwise deauthenticate station whose associated id is aid
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_WIFI_MODE: WiFi mode is wrong
+  */
+esp_err_t esp_wifi_deauth_sta(uint16_t aid);
+
+/**
+  * @brief     Scan all available APs.
+  *
+  * @attention If this API is called, the found APs are stored in WiFi driver dynamic allocated memory and the
+  *            will be freed in esp_wifi_scan_get_ap_records, so generally, call esp_wifi_scan_get_ap_records to cause
+  *            the memory to be freed once the scan is done
+  * @attention The values of maximum active scan time and passive scan time per channel are limited to 1500 milliseconds.
+  *            Values above 1500ms may cause station to disconnect from AP and are not recommended.
+  *
+  * @param     config  configuration of scanning
+  * @param     block if block is true, this API will block the caller until the scan is done, otherwise
+  *                         it will return immediately
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi was not started by esp_wifi_start
+  *    - ESP_ERR_WIFI_TIMEOUT: blocking scan is timeout
+  *    - others: refer to error code in esp_err.h
+  */
+esp_err_t esp_wifi_scan_start(const wifi_scan_config_t *config, bool block);
+
+/**
+  * @brief     Stop the scan in process
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
+  */
+esp_err_t esp_wifi_scan_stop(void);
+
+/**
+  * @brief     Get number of APs found in last scan
+  *
+  * @param[out] number  store number of APIs found in last scan
+  *
+  * @attention This API can only be called when the scan is completed, otherwise it may get wrong value.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_scan_get_ap_num(uint16_t *number);
+
+/**
+  * @brief     Get AP list found in last scan
+  *
+  * @param[inout]  number As input param, it stores max AP number ap_records can hold.
+  *                As output param, it receives the actual AP number this API returns.
+  * @param         ap_records  wifi_ap_record_t array to hold the found APs
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_STARTED: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_NO_MEM: out of memory
+  */
+esp_err_t esp_wifi_scan_get_ap_records(uint16_t *number, wifi_ap_record_t *ap_records);
+
+
+/**
+  * @brief     Get information of AP which the ESP32 station is associated with
+  *
+  * @param     ap_info  the wifi_ap_record_t to hold AP information
+  *            sta can get the connected ap's phy mode info through the struct member
+  *            phy_11b,phy_11g,phy_11n,phy_lr in the wifi_ap_record_t struct.
+  *            For example, phy_11b = 1 imply that ap support 802.11b mode
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_CONN: The station interface don't initialized
+  *    - ESP_ERR_WIFI_NOT_CONNECT: The station is in disconnect status
+  */
+esp_err_t esp_wifi_sta_get_ap_info(wifi_ap_record_t *ap_info);
+
+/**
+  * @brief     Set current WiFi power save type
+  *
+  * @attention Default power save type is WIFI_PS_MIN_MODEM.
+  *
+  * @param     type  power save type
+  *
+  * @return    ESP_OK: succeed
+  */
+esp_err_t esp_wifi_set_ps(wifi_ps_type_t type);
+
+/**
+  * @brief     Get current WiFi power save type
+  *
+  * @attention Default power save type is WIFI_PS_MIN_MODEM.
+  *
+  * @param[out]  type: store current power save type
+  *
+  * @return    ESP_OK: succeed
+  */
+esp_err_t esp_wifi_get_ps(wifi_ps_type_t *type);
+
+/**
+  * @brief     Set protocol type of specified interface
+  *            The default protocol is (WIFI_PROTOCOL_11B|WIFI_PROTOCOL_11G|WIFI_PROTOCOL_11N)
+  *
+  * @attention Currently we only support 802.11b or 802.11bg or 802.11bgn mode
+  *
+  * @param     ifx  interfaces
+  * @param     protocol_bitmap  WiFi protocol bitmap
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - others: refer to error codes in esp_err.h
+  */
+esp_err_t esp_wifi_set_protocol(wifi_interface_t ifx, uint8_t protocol_bitmap);
+
+/**
+  * @brief     Get the current protocol bitmap of the specified interface
+  *
+  * @param     ifx  interface
+  * @param[out] protocol_bitmap  store current WiFi protocol bitmap of interface ifx
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - others: refer to error codes in esp_err.h
+  */
+esp_err_t esp_wifi_get_protocol(wifi_interface_t ifx, uint8_t *protocol_bitmap);
+
+/**
+  * @brief     Set the bandwidth of ESP32 specified interface
+  *
+  * @attention 1. API return false if try to configure an interface that is not enabled
+  * @attention 2. WIFI_BW_HT40 is supported only when the interface support 11N
+  *
+  * @param     ifx  interface to be configured
+  * @param     bw  bandwidth
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - others: refer to error codes in esp_err.h
+  */
+esp_err_t esp_wifi_set_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t bw);
+
+/**
+  * @brief     Get the bandwidth of ESP32 specified interface
+  *
+  * @attention 1. API return false if try to get a interface that is not enable
+  *
+  * @param     ifx interface to be configured
+  * @param[out] bw  store bandwidth of interface ifx
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw);
+
+/**
+  * @brief     Set primary/secondary channel of ESP32
+  *
+  * @attention 1. This is a special API for sniffer
+  * @attention 2. This API should be called after esp_wifi_start() or esp_wifi_set_promiscuous()
+  *
+  * @param     primary  for HT20, primary is the channel number, for HT40, primary is the primary channel
+  * @param     second   for HT20, second is ignored, for HT40, second is the second channel
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_set_channel(uint8_t primary, wifi_second_chan_t second);
+
+/**
+  * @brief     Get the primary/secondary channel of ESP32
+  *
+  * @attention 1. API return false if try to get a interface that is not enable
+  *
+  * @param     primary   store current primary channel
+  * @param[out]  second  store current second channel
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_channel(uint8_t *primary, wifi_second_chan_t *second);
+
+/**
+  * @brief     configure country info
+  *
+  * @attention 1. The default country is {.cc="CN", .schan=1, .nchan=13, policy=WIFI_COUNTRY_POLICY_AUTO}
+  * @attention 2. When the country policy is WIFI_COUNTRY_POLICY_AUTO, the country info of the AP to which
+  *               the station is connected is used. E.g. if the configured country info is {.cc="USA", .schan=1, .nchan=11}
+  *               and the country info of the AP to which the station is connected is {.cc="JP", .schan=1, .nchan=14}
+  *               then the country info that will be used is {.cc="JP", .schan=1, .nchan=14}. If the station disconnected
+  *               from the AP the country info is set back back to the country info of the station automatically,
+  *               {.cc="USA", .schan=1, .nchan=11} in the example.
+  * @attention 3. When the country policy is WIFI_COUNTRY_POLICY_MANUAL, always use the configured country info.
+  * @attention 4. When the country info is changed because of configuration or because the station connects to a different
+  *               external AP, the country IE in probe response/beacon of the soft-AP is changed also.
+  * @attention 5. The country configuration is not stored into flash
+  * @attention 6. This API doesn't validate the per-country rules, it's up to the user to fill in all fields according to
+  *               local regulations.
+  *
+  * @param     country   the configured country info
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_set_country(const wifi_country_t *country);
+
+/**
+  * @brief     get the current country info
+  *
+  * @param     country  country info
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_country(wifi_country_t *country);
+
+
+/**
+  * @brief     Set MAC address of the ESP32 WiFi station or the soft-AP interface.
+  *
+  * @attention 1. This API can only be called when the interface is disabled
+  * @attention 2. ESP32 soft-AP and station have different MAC addresses, do not set them to be the same.
+  * @attention 3. The bit 0 of the first byte of ESP32 MAC address can not be 1. For example, the MAC address
+  *      can set to be "1a:XX:XX:XX:XX:XX", but can not be "15:XX:XX:XX:XX:XX".
+  *
+  * @param     ifx  interface
+  * @param     mac  the MAC address
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_MAC: invalid mac address
+  *    - ESP_ERR_WIFI_MODE: WiFi mode is wrong
+  *    - others: refer to error codes in esp_err.h
+  */
+esp_err_t esp_wifi_set_mac(wifi_interface_t ifx, const uint8_t mac[6]);
+
+/**
+  * @brief     Get mac of specified interface
+  *
+  * @param      ifx  interface
+  * @param[out] mac  store mac of the interface ifx
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  */
+esp_err_t esp_wifi_get_mac(wifi_interface_t ifx, uint8_t mac[6]);
+
+/**
+  * @brief The RX callback function in the promiscuous mode.
+  *        Each time a packet is received, the callback function will be called.
+  *
+  * @param buf  Data received. Type of data in buffer (wifi_promiscuous_pkt_t or wifi_pkt_rx_ctrl_t) indicated by 'type' parameter.
+  * @param type  promiscuous packet type.
+  *
+  */
+typedef void (* wifi_promiscuous_cb_t)(void *buf, wifi_promiscuous_pkt_type_t type);
+
+/**
+  * @brief Register the RX callback function in the promiscuous mode.
+  *
+  * Each time a packet is received, the registered callback function will be called.
+  *
+  * @param cb  callback
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_set_promiscuous_rx_cb(wifi_promiscuous_cb_t cb);
+
+/**
+  * @brief     Enable the promiscuous mode.
+  *
+  * @param     en  false - disable, true - enable
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_set_promiscuous(bool en);
+
+/**
+  * @brief     Get the promiscuous mode.
+  *
+  * @param[out] en  store the current status of promiscuous mode
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_promiscuous(bool *en);
+
+/**
+  * @brief Enable the promiscuous mode packet type filter.
+  *
+  * @note The default filter is to filter all packets except WIFI_PKT_MISC
+  *
+  * @param filter the packet type filtered in promiscuous mode.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_set_promiscuous_filter(const wifi_promiscuous_filter_t *filter);
+
+/**
+  * @brief     Get the promiscuous filter.
+  *
+  * @param[out] filter  store the current status of promiscuous filter
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_promiscuous_filter(wifi_promiscuous_filter_t *filter);
+
+/**
+  * @brief Enable subtype filter of the control packet in promiscuous mode.
+  *
+  * @note The default filter is to filter none control packet.
+  *
+  * @param filter the subtype of the control packet filtered in promiscuous mode.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_set_promiscuous_ctrl_filter(const wifi_promiscuous_filter_t *filter);
+
+/**
+  * @brief     Get the subtype filter of the control packet in promiscuous mode.
+  *
+  * @param[out] filter  store the current status of subtype filter of the control packet in promiscuous mode
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_promiscuous_ctrl_filter(wifi_promiscuous_filter_t *filter);
+
+/**
+  * @brief     Set the configuration of the ESP32 STA or AP
+  *
+  * @attention 1. This API can be called only when specified interface is enabled, otherwise, API fail
+  * @attention 2. For station configuration, bssid_set needs to be 0; and it needs to be 1 only when users need to check the MAC address of the AP.
+  * @attention 3. ESP32 is limited to only one channel, so when in the soft-AP+station mode, the soft-AP will adjust its channel automatically to be the same as
+  *               the channel of the ESP32 station.
+  *
+  * @param     interface  interface
+  * @param     conf  station or soft-AP configuration
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  *    - ESP_ERR_WIFI_MODE: invalid mode
+  *    - ESP_ERR_WIFI_PASSWORD: invalid password
+  *    - ESP_ERR_WIFI_NVS: WiFi internal NVS error
+  *    - others: refer to the erro code in esp_err.h
+  */
+esp_err_t esp_wifi_set_config(wifi_interface_t interface, wifi_config_t *conf);
+
+/**
+  * @brief     Get configuration of specified interface
+  *
+  * @param     interface  interface
+  * @param[out]  conf  station or soft-AP configuration
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_WIFI_IF: invalid interface
+  */
+esp_err_t esp_wifi_get_config(wifi_interface_t interface, wifi_config_t *conf);
+
+/**
+  * @brief     Get STAs associated with soft-AP
+  *
+  * @attention SSC only API
+  *
+  * @param[out] sta  station list
+  *             ap can get the connected sta's phy mode info through the struct member
+  *             phy_11b,phy_11g,phy_11n,phy_lr in the wifi_sta_info_t struct.
+  *             For example, phy_11b = 1 imply that sta support 802.11b mode
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  *    - ESP_ERR_WIFI_MODE: WiFi mode is wrong
+  *    - ESP_ERR_WIFI_CONN: WiFi internal error, the station/soft-AP control block is invalid
+  */
+esp_err_t esp_wifi_ap_get_sta_list(wifi_sta_list_t *sta);
+
+
+/**
+  * @brief     Set the WiFi API configuration storage type
+  *
+  * @attention 1. The default value is WIFI_STORAGE_FLASH
+  *
+  * @param     storage : storage type
+  *
+  * @return
+  *   - ESP_OK: succeed
+  *   - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *   - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_set_storage(wifi_storage_t storage);
+
+/**
+  * @brief     Set auto connect
+  *            The default value is true
+  *
+  * @param     en : true - enable auto connect / false - disable auto connect
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_MODE: WiFi internal error, the station/soft-AP control block is invalid
+  *    - others: refer to error code in esp_err.h
+  */
+esp_err_t esp_wifi_set_auto_connect(bool en) __attribute__ ((deprecated));
+
+/**
+  * @brief     Get the auto connect flag
+  *
+  * @param[out] en  store current auto connect configuration
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_auto_connect(bool *en) __attribute__ ((deprecated));
+
+/**
+  * @brief     Set 802.11 Vendor-Specific Information Element
+  *
+  * @param     enable If true, specified IE is enabled. If false, specified IE is removed.
+  * @param     type Information Element type. Determines the frame type to associate with the IE.
+  * @param     idx  Index to set or clear. Each IE type can be associated with up to two elements (indices 0 & 1).
+  * @param     vnd_ie Pointer to vendor specific element data. First 6 bytes should be a header with fields matching vendor_ie_data_t.
+  *            If enable is false, this argument is ignored and can be NULL. Data does not need to remain valid after the function returns.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init()
+  *    - ESP_ERR_INVALID_ARG: Invalid argument, including if first byte of vnd_ie is not WIFI_VENDOR_IE_ELEMENT_ID (0xDD)
+  *      or second byte is an invalid length.
+  *    - ESP_ERR_NO_MEM: Out of memory
+  */
+esp_err_t esp_wifi_set_vendor_ie(bool enable, wifi_vendor_ie_type_t type, wifi_vendor_ie_id_t idx, const void *vnd_ie);
+
+/**
+  * @brief     Function signature for received Vendor-Specific Information Element callback.
+  * @param     ctx Context argument, as passed to esp_wifi_set_vendor_ie_cb() when registering callback.
+  * @param     type Information element type, based on frame type received.
+  * @param     sa Source 802.11 address.
+  * @param     vnd_ie Pointer to the vendor specific element data received.
+  * @param     rssi Received signal strength indication.
+  */
+typedef void (*esp_vendor_ie_cb_t) (void *ctx, wifi_vendor_ie_type_t type, const uint8_t sa[6], const vendor_ie_data_t *vnd_ie, int rssi);
+
+/**
+  * @brief     Register Vendor-Specific Information Element monitoring callback.
+  *
+  * @param     cb   Callback function
+  * @param     ctx  Context argument, passed to callback function.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_set_vendor_ie_cb(esp_vendor_ie_cb_t cb, void *ctx);
+
+/**
+  * @brief     Set maximum WiFi transmiting power
+  *
+  * @attention WiFi transmiting power is divided to six levels in phy init data.
+  *            Level0 represents highest transmiting power and level5 represents lowest
+  *            transmiting power. Packets of different rates are transmitted in
+  *            different powers according to the configuration in phy init data.
+  *            This API only sets maximum WiFi transmiting power. If this API is called,
+  *            the transmiting power of every packet will be less than or equal to the
+  *            value set by this API. If this API is not called, the value of maximum
+  *            transmitting power set in phy_init_data.bin or menuconfig (depend on
+  *            whether to use phy init data in partition or not) will be used. Default
+  *            value is level0. Values passed in power are mapped to transmit power
+  *            levels as follows:
+  *            - [78, 127]: level0
+  *            - [76, 77]: level1
+  *            - [74, 75]: level2
+  *            - [68, 73]: level3
+  *            - [60, 67]: level4
+  *            - [52, 59]: level5
+  *            - [44, 51]: level5 - 2dBm
+  *            - [34, 43]: level5 - 4.5dBm
+  *            - [28, 33]: level5 - 6dBm
+  *            - [20, 27]: level5 - 8dBm
+  *            - [8, 19]: level5 - 11dBm
+  *            - [-128, 7]: level5 - 14dBm
+  *
+  * @param     power  Maximum WiFi transmiting power.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  */
+esp_err_t esp_wifi_set_max_tx_power(int8_t power);
+
+/**
+  * @brief     Get maximum WiFi transmiting power
+  *
+  * @attention This API gets maximum WiFi transmiting power. Values got
+  *            from power are mapped to transmit power levels as follows:
+  *            - 78: 19.5dBm
+  *            - 76: 19dBm
+  *            - 74: 18.5dBm
+  *            - 68: 17dBm
+  *            - 60: 15dBm
+  *            - 52: 13dBm
+  *            - 44: 11dBm
+  *            - 34: 8.5dBm
+  *            - 28: 7dBm
+  *            - 20: 5dBm
+  *            - 8:  2dBm
+  *            - -4: -1dBm
+  *
+  * @param     power  Maximum WiFi transmiting power.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_max_tx_power(int8_t *power);
+
+/**
+  * @brief     Set mask to enable or disable some WiFi events
+  *
+  * @attention 1. Mask can be created by logical OR of various WIFI_EVENT_MASK_ constants.
+  *               Events which have corresponding bit set in the mask will not be delivered to the system event handler.
+  * @attention 2. Default WiFi event mask is WIFI_EVENT_MASK_AP_PROBEREQRECVED.
+  * @attention 3. There may be lots of stations sending probe request data around.
+  *               Don't unmask this event unless you need to receive probe request data.
+  *
+  * @param     mask  WiFi event mask.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+esp_err_t esp_wifi_set_event_mask(uint32_t mask);
+
+/**
+  * @brief     Get mask of WiFi events
+  *
+  * @param     mask  WiFi event mask.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument
+  */
+esp_err_t esp_wifi_get_event_mask(uint32_t *mask);
+
+/**
+  * @brief     Send raw ieee80211 data
+  *
+  * @attention Currently only support for sending beacon/probe request/probe response/action and non-QoS
+  *            data frame
+  *
+  * @param     ifx interface if the Wi-Fi mode is Station, the ifx should be WIFI_IF_STA. If the Wi-Fi
+  *            mode is SoftAP, the ifx should be WIFI_IF_AP. If the Wi-Fi mode is Station+SoftAP, the
+  *            ifx should be WIFI_IF_STA or WIFI_IF_AP. If the ifx is wrong, the API returns ESP_ERR_WIFI_IF.
+  * @param     buffer raw ieee80211 buffer
+  * @param     len the length of raw buffer, the len must be <= 1500 Bytes and >= 24 Bytes
+  * @param     en_sys_seq indicate whether use the internal sequence number. If en_sys_seq is false, the
+  *            sequence in raw buffer is unchanged, otherwise it will be overwritten by WiFi driver with
+  *            the system sequence number.
+  *            Generally, if esp_wifi_80211_tx is called before the Wi-Fi connection has been set up, both
+  *            en_sys_seq==true and en_sys_seq==false are fine. However, if the API is called after the Wi-Fi
+  *            connection has been set up, en_sys_seq must be true, otherwise ESP_ERR_WIFI_ARG is returned.
+  *
+  * @return
+  *    - ESP_OK: success
+  *    - ESP_ERR_WIFI_IF: Invalid interface
+  *    - ESP_ERR_INVALID_ARG: Invalid parameter
+  *    - ESP_ERR_WIFI_NO_MEM: out of memory
+  */
+
+esp_err_t esp_wifi_80211_tx(wifi_interface_t ifx, const void *buffer, int len, bool en_sys_seq);
+
+/**
+  * @brief The RX callback function of Channel State Information(CSI)  data.
+  *
+  *        Each time a CSI data is received, the callback function will be called.
+  *
+  * @param ctx context argument, passed to esp_wifi_set_csi_rx_cb() when registering callback function.
+  * @param data CSI data received. The memory that it points to will be deallocated after callback function returns.
+  *
+  */
+typedef void (* wifi_csi_cb_t)(void *ctx, wifi_csi_info_t *data);
+
+
+/**
+  * @brief Register the RX callback function of CSI data.
+  *
+  *        Each time a CSI data is received, the callback function will be called.
+  *
+  * @param cb  callback
+  * @param ctx context argument, passed to callback function
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  */
+
+esp_err_t esp_wifi_set_csi_rx_cb(wifi_csi_cb_t cb, void *ctx);
+
+/**
+  * @brief Set CSI data configuration
+  *
+  * @param config configuration
+  *
+  * return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start or promiscuous mode is not enabled
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_set_csi_config(const wifi_csi_config_t *config);
+
+/**
+  * @brief Enable or disable CSI
+  *
+  * @param en true - enable, false - disable
+  *
+  * return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_NOT_START: WiFi is not started by esp_wifi_start or promiscuous mode is not enabled
+  *    - ESP_ERR_INVALID_ARG: invalid argument
+  */
+esp_err_t esp_wifi_set_csi(bool en);
+
+/**
+  * @brief     Set antenna GPIO configuration
+  *
+  * @param     config  Antenna GPIO configuration.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_ARG: Invalid argument, e.g. parameter is NULL, invalid GPIO number etc
+  */
+esp_err_t esp_wifi_set_ant_gpio(const wifi_ant_gpio_config_t *config);
+
+/**
+  * @brief     Get current antenna GPIO configuration
+  *
+  * @param     config  Antenna GPIO configuration.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument, e.g. parameter is NULL
+  */
+esp_err_t esp_wifi_get_ant_gpio(wifi_ant_gpio_config_t *config);
+
+
+/**
+  * @brief     Set antenna configuration
+  *
+  * @param     config  Antenna configuration.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_ARG: Invalid argument, e.g. parameter is NULL, invalid antenna mode or invalid GPIO number
+  */
+esp_err_t esp_wifi_set_ant(const wifi_ant_config_t *config);
+
+/**
+  * @brief     Get current antenna configuration
+  *
+  * @param     config  Antenna configuration.
+  *
+  * @return
+  *    - ESP_OK: succeed
+  *    - ESP_ERR_WIFI_NOT_INIT: WiFi is not initialized by esp_wifi_init
+  *    - ESP_ERR_WIFI_ARG: invalid argument, e.g. parameter is NULL
+  */
+esp_err_t esp_wifi_get_ant(wifi_ant_config_t *config);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_WIFI_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/esp_wifi_internal.h b/cpu/esp32/vendor/esp-idf/include/esp32/esp_wifi_internal.h
new file mode 100644
index 0000000000000000000000000000000000000000..14025821f759ab63cbce20205c821aeb89f82ed6
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/esp_wifi_internal.h
@@ -0,0 +1,190 @@
+// 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.
+
+/*
+ * All the APIs declared here are internal only APIs, it can only be used by
+ * espressif internal modules, such as SSC, LWIP, TCPIP adapter etc, espressif
+ * customers are not recommended to use them.
+ *
+ * If someone really want to use specified APIs declared in here, please contact
+ * espressif AE/developer to make sure you know the limitations or risk of
+ * the API, otherwise you may get unexpected behavior!!!
+ *
+ */
+
+#ifndef ESP32_ESP_WIFI_INTERNAL_H
+#define ESP32_ESP_WIFI_INTERNAL_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include "freertos/FreeRTOS.h"
+#include "freertos/queue.h"
+#include "rom/queue.h"
+#include "esp_err.h"
+#include "esp_wifi_types.h"
+#include "esp_event.h"
+#include "esp_wifi.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    QueueHandle_t handle; /**< FreeRTOS queue handler */
+    void *storage;        /**< storage for FreeRTOS queue */
+} wifi_static_queue_t;
+
+/**
+ * @brief Initialize Wi-Fi Driver
+ *     Alloc resource for WiFi driver, such as WiFi control structure, RX/TX buffer,
+ *     WiFi NVS structure among others.
+ *
+ * For the most part, you need not call this function directly. It gets called
+ * from esp_wifi_init().
+ *
+ * This function may be called, if you only need to initialize the Wi-Fi driver
+ * without having to use the network stack on top.
+ *
+ * @param  config provide WiFi init configuration
+ *
+ * @return
+ *    - ESP_OK: succeed
+ *    - ESP_ERR_NO_MEM: out of memory
+ *    - others: refer to error code esp_err.h
+ */
+esp_err_t esp_wifi_init_internal(const wifi_init_config_t *config);
+
+/**
+  * @brief  get whether the wifi driver is allowed to transmit data or not
+  *
+  * @return
+  *     - true  : upper layer should stop to transmit data to wifi driver
+  *     - false : upper layer can transmit data to wifi driver
+  */
+bool esp_wifi_internal_tx_is_stop(void);
+
+/**
+  * @brief  free the rx buffer which allocated by wifi driver
+  *
+  * @param  void* buffer: rx buffer pointer
+  */
+void esp_wifi_internal_free_rx_buffer(void* buffer);
+
+/**
+  * @brief  transmit the buffer via wifi driver
+  *
+  * @param  wifi_interface_t wifi_if : wifi interface id
+  * @param  void *buffer : the buffer to be tansmit
+  * @param  uint16_t len : the length of buffer
+  *
+  * @return
+  *    - ERR_OK  : Successfully transmit the buffer to wifi driver
+  *    - ERR_MEM : Out of memory
+  *    - ERR_IF : WiFi driver error
+  *    - ERR_ARG : Invalid argument
+  */
+int esp_wifi_internal_tx(wifi_interface_t wifi_if, void *buffer, uint16_t len);
+
+/**
+  * @brief     The WiFi RX callback function
+  *
+  *            Each time the WiFi need to forward the packets to high layer, the callback function will be called
+  */
+typedef esp_err_t (*wifi_rxcb_t)(void *buffer, uint16_t len, void *eb);
+
+/**
+  * @brief     Set the WiFi RX callback
+  *
+  * @attention 1. Currently we support only one RX callback for each interface
+  *
+  * @param     wifi_interface_t ifx : interface
+  * @param     wifi_rxcb_t fn : WiFi RX callback
+  *
+  * @return
+  *     - ESP_OK : succeed
+  *     - others : fail
+  */
+esp_err_t esp_wifi_internal_reg_rxcb(wifi_interface_t ifx, wifi_rxcb_t fn);
+
+/**
+  * @brief     Notify WIFI driver that the station got ip successfully
+  *
+  * @return
+  *     - ESP_OK : succeed
+  *     - others : fail
+  */
+esp_err_t esp_wifi_internal_set_sta_ip(void);
+
+/**
+  * @brief     Check the MD5 values of the OS adapter header files in IDF and WiFi library
+  *
+  * @attention 1. It is used for internal CI version check
+  *
+  * @return
+  *     - ESP_OK : succeed
+  *     - ESP_WIFI_INVALID_ARG : MD5 check fail
+  */
+esp_err_t esp_wifi_internal_osi_funcs_md5_check(const char *md5);
+
+/**
+  * @brief     Check the MD5 values of the crypto types header files in IDF and WiFi library
+  *
+  * @attention 1. It is used for internal CI version check
+  *
+  * @return
+  *     - ESP_OK : succeed
+  *     - ESP_WIFI_INVALID_ARG : MD5 check fail
+  */
+esp_err_t esp_wifi_internal_crypto_funcs_md5_check(const char *md5);
+
+/**
+  * @brief     Allocate a chunk of memory for WiFi driver
+  *
+  * @attention This API is not used for DMA memory allocation.
+  *
+  * @param     size_t size : Size, in bytes, of the amount of memory to allocate
+  *
+  * @return    A pointer to the memory allocated on success, NULL on failure
+  */
+void *wifi_malloc( size_t size );
+
+/**
+  * @brief     Reallocate a chunk of memory for WiFi driver
+  *
+  * @attention This API is not used for DMA memory allocation.
+  *
+  * @param     void * ptr  : Pointer to previously allocated memory, or NULL for a new allocation.
+  * @param     size_t size : Size, in bytes, of the amount of memory to allocate
+  *
+  * @return    A pointer to the memory allocated on success, NULL on failure
+  */
+void *wifi_realloc( void *ptr, size_t size );
+
+/**
+  * @brief     Callocate memory for WiFi driver
+  *
+  * @attention This API is not used for DMA memory allocation.
+  *
+  * @param     size_t n    : Number of continuing chunks of memory to allocate
+  * @param     size_t size : Size, in bytes, of the amount of memory to allocate
+  *
+  * @return    A pointer to the memory allocated on success, NULL on failure
+  */
+void *wifi_calloc( size_t n, size_t size );
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_ESP_WIFI_INTERNAL_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/esp32/phy.h b/cpu/esp32/vendor/esp-idf/include/esp32/phy.h
new file mode 100644
index 0000000000000000000000000000000000000000..846fe1d23c00aff11d7e059775a0c2ade5749343
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/esp32/phy.h
@@ -0,0 +1,73 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ESP32_PHY_H
+#define ESP32_PHY_H
+
+#include "esp_phy_init.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP_CAL_DATA_CHECK_FAIL 1
+
+/**
+ * @file phy.h
+ * @brief Declarations for functions provided by libphy.a
+ */
+
+/**
+ * @brief Return ROM function pointer table from PHY library.
+ */
+void phy_get_romfunc_addr(void);
+
+/**
+ * @brief Initialize PHY module and do RF calibration
+ * @param[in] init_data Initialization parameters to be used by the PHY
+ * @param[inout] cal_data As input, calibration data previously obtained. As output, will contain new calibration data.
+ * @param[in] cal_mode  RF calibration mode
+ * @return ESP_CAL_DATA_CHECK_FAIL if calibration data checksum fails, other values are reserved for future use
+ */
+int register_chipv7_phy(const esp_phy_init_data_t* init_data, esp_phy_calibration_data_t *cal_data, esp_phy_calibration_mode_t cal_mode);
+
+/**
+ * @brief Get the format version of calibration data used by PHY library.
+ * @return Format version number, OR'ed with BIT(16) if PHY is in WIFI only mode.
+ */
+uint32_t phy_get_rf_cal_version(void);
+
+/**
+ * @brief Set RF/BB for only WIFI mode or coexist(WIFI & BT) mode
+ * @param[in] true is for only WIFI mode, false is for coexist mode. default is 0.
+ * @return NULL
+ */
+void phy_set_wifi_mode_only(bool wifi_only);
+
+/**
+ * @brief Set BT the highest priority in coexist mode.
+ * @return NULL
+ */
+void coex_bt_high_prio(void);
+
+/**
+ * @brief Shutdown PHY and RF.
+ */
+void phy_close_rf(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ESP32_PHY_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/ethernet/eth_phy/phy_lan8720.h b/cpu/esp32/vendor/esp-idf/include/ethernet/eth_phy/phy_lan8720.h
new file mode 100644
index 0000000000000000000000000000000000000000..b180b4c265eff4dfb756dcad2bf0347b8a007dc2
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/ethernet/eth_phy/phy_lan8720.h
@@ -0,0 +1,73 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ETHERNET_ETH_PHY_PHY_LAN8720_H
+#define ETHERNET_ETH_PHY_PHY_LAN8720_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef RIOT_VERSION
+#include "eth_phy/phy.h"
+#else
+#include "phy.h"
+#endif
+
+/** @brief Dump all LAN8720 PHY SMI configuration registers
+ *
+ * @note These registers are dumped at 'debug' level, so output
+ * may not be visible depending on default log levels.
+ */
+void phy_lan8720_dump_registers(void);
+
+/** @brief Default LAN8720 phy_check_init function.
+ */
+void phy_lan8720_check_phy_init(void);
+
+/** @brief Default LAN8720 phy_get_speed_mode function.
+ */
+eth_speed_mode_t phy_lan8720_get_speed_mode(void);
+
+/** @brief Default LAN8720 phy_get_duplex_mode function.
+ */
+eth_duplex_mode_t phy_lan8720_get_duplex_mode(void);
+
+/** @brief Default LAN8720 phy_power_enable function.
+ *
+ * @note This function may need to be replaced with a custom function
+ * if the PHY has a GPIO to enable power or start a clock.
+ *
+ * Consult the ethernet example to see how this is done.
+ */
+void phy_lan8720_power_enable(bool);
+
+/** @brief Default LAN8720 phy_init function.
+ */
+void phy_lan8720_init(void);
+
+/** @brief Default LAN8720 PHY configuration
+ *
+ * This configuration is not suitable for use as-is, it will need
+ * to be modified for your particular PHY hardware setup.
+ *
+ * Consult the Ethernet example to see how this is done.
+ */
+extern const eth_config_t phy_lan8720_default_ethernet_config;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ETHERNET_ETH_PHY_PHY_LAN8720_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/ethernet/eth_phy/phy_tlk110.h b/cpu/esp32/vendor/esp-idf/include/ethernet/eth_phy/phy_tlk110.h
new file mode 100644
index 0000000000000000000000000000000000000000..7821b451a64718af69f9260ac3f32254d607c758
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/ethernet/eth_phy/phy_tlk110.h
@@ -0,0 +1,73 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef ETHERNET_ETH_PHY_PHY_TLK110_H
+#define ETHERNET_ETH_PHY_PHY_TLK110_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef RIOT_VERSION
+#include "eth_phy/phy.h"
+#else
+#include "phy.h"
+#endif
+
+/** @brief Dump all TLK110 PHY SMI configuration registers
+ *
+ * @note These registers are dumped at 'debug' level, so output
+ * may not be visible depending on default log levels.
+ */
+void phy_tlk110_dump_registers(void);
+
+/** @brief Default TLK110 phy_check_init function.
+ */
+void phy_tlk110_check_phy_init(void);
+
+/** @brief Default TLK110 phy_get_speed_mode function.
+ */
+eth_speed_mode_t phy_tlk110_get_speed_mode(void);
+
+/** @brief Default TLK110 phy_get_duplex_mode function.
+ */
+eth_duplex_mode_t phy_tlk110_get_duplex_mode(void);
+
+/** @brief Default TLK110 phy_power_enable function.
+ *
+ * @note This function may need to be replaced with a custom function
+ * if the PHY has a GPIO to enable power or start a clock.
+ *
+ * Consult the ethernet example to see how this is done.
+ */
+void phy_tlk110_power_enable(bool);
+
+/** @brief Default TLK110 phy_init function.
+ */
+void phy_tlk110_init(void);
+
+/** @brief Default TLK110 PHY configuration
+ *
+ * This configuration is not suitable for use as-is, it will need
+ * to be modified for your particular PHY hardware setup.
+ *
+ * Consult the Ethernet example to see how this is done.
+ */
+extern const eth_config_t phy_tlk110_default_ethernet_config;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* ETHERNET_ETH_PHY_PHY_TLK110_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/heap/esp_heap_caps.h b/cpu/esp32/vendor/esp-idf/include/heap/esp_heap_caps.h
new file mode 100644
index 0000000000000000000000000000000000000000..dcedb188a5b139194b471e8ebe6e499f19e481c4
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/heap/esp_heap_caps.h
@@ -0,0 +1,319 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef HEAP_ESP_HEAP_CAPS_H
+#define HEAP_ESP_HEAP_CAPS_H
+
+#include <stdint.h>
+#include <stdlib.h>
+#include "multi_heap.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Flags to indicate the capabilities of the various memory systems
+ */
+#define MALLOC_CAP_EXEC             (1<<0)  ///< Memory must be able to run executable code
+#define MALLOC_CAP_32BIT            (1<<1)  ///< Memory must allow for aligned 32-bit data accesses
+#define MALLOC_CAP_8BIT             (1<<2)  ///< Memory must allow for 8/16/...-bit data accesses
+#define MALLOC_CAP_DMA              (1<<3)  ///< Memory must be able to accessed by DMA
+#define MALLOC_CAP_PID2             (1<<4)  ///< Memory must be mapped to PID2 memory space (PIDs are not currently used)
+#define MALLOC_CAP_PID3             (1<<5)  ///< Memory must be mapped to PID3 memory space (PIDs are not currently used)
+#define MALLOC_CAP_PID4             (1<<6)  ///< Memory must be mapped to PID4 memory space (PIDs are not currently used)
+#define MALLOC_CAP_PID5             (1<<7)  ///< Memory must be mapped to PID5 memory space (PIDs are not currently used)
+#define MALLOC_CAP_PID6             (1<<8)  ///< Memory must be mapped to PID6 memory space (PIDs are not currently used)
+#define MALLOC_CAP_PID7             (1<<9)  ///< Memory must be mapped to PID7 memory space (PIDs are not currently used)
+#define MALLOC_CAP_SPIRAM           (1<<10) ///< Memory must be in SPI RAM
+#define MALLOC_CAP_INTERNAL         (1<<11) ///< Memory must be internal; specifically it should not disappear when flash/spiram cache is switched off
+#define MALLOC_CAP_DEFAULT          (1<<12) ///< Memory can be returned in a non-capability-specific memory allocation (e.g. malloc(), calloc()) call
+#define MALLOC_CAP_INVALID          (1<<31) ///< Memory can't be used / list end marker
+
+/**
+ * @brief Allocate a chunk of memory which has the given capabilities
+ *
+ * Equivalent semantics to libc malloc(), for capability-aware memory.
+ *
+ * In IDF, ``malloc(p)`` is equivalent to ``heap_caps_malloc(p, MALLOC_CAP_8BIT)``.
+ *
+ * @param size Size, in bytes, of the amount of memory to allocate
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory to be returned
+ *
+ * @return A pointer to the memory allocated on success, NULL on failure
+ */
+void *heap_caps_malloc(size_t size, uint32_t caps);
+
+
+/**
+ * @brief Free memory previously allocated via heap_caps_malloc() or heap_caps_realloc().
+ *
+ * Equivalent semantics to libc free(), for capability-aware memory.
+ *
+ *  In IDF, ``free(p)`` is equivalent to ``heap_caps_free(p)``.
+ *
+ * @param ptr Pointer to memory previously returned from heap_caps_malloc() or heap_caps_realloc(). Can be NULL.
+ */
+void heap_caps_free( void *ptr);
+
+/**
+ * @brief Reallocate memory previously allocated via heap_caps_malloc() or heap_caps_realloc().
+ *
+ * Equivalent semantics to libc realloc(), for capability-aware memory.
+ *
+ * In IDF, ``realloc(p, s)`` is equivalent to ``heap_caps_realloc(p, s, MALLOC_CAP_8BIT)``.
+ *
+ * 'caps' parameter can be different to the capabilities that any original 'ptr' was allocated with. In this way,
+ * realloc can be used to "move" a buffer if necessary to ensure it meets a new set of capabilities.
+ *
+ * @param ptr Pointer to previously allocated memory, or NULL for a new allocation.
+ * @param size Size of the new buffer requested, or 0 to free the buffer.
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory desired for the new allocation.
+ *
+ * @return Pointer to a new buffer of size 'size' with capabilities 'caps', or NULL if allocation failed.
+ */
+void *heap_caps_realloc( void *ptr, size_t size, int caps);
+
+/**
+ * @brief Allocate a chunk of memory which has the given capabilities. The initialized value in the memory is set to zero.
+ *
+ * Equivalent semantics to libc calloc(), for capability-aware memory.
+ *
+ * In IDF, ``calloc(p)`` is equivalent to ``heap_caps_calloc(p, MALLOC_CAP_8BIT)``.
+ *
+ * @param n    Number of continuing chunks of memory to allocate
+ * @param size Size, in bytes, of a chunk of memory to allocate
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory to be returned
+ *
+ * @return A pointer to the memory allocated on success, NULL on failure
+ */
+void *heap_caps_calloc(size_t n, size_t size, uint32_t caps);
+
+/**
+ * @brief Get the total free size of all the regions that have the given capabilities
+ *
+ * This function takes all regions capable of having the given capabilities allocated in them
+ * and adds up the free space they have.
+ *
+ * Note that because of heap fragmentation it is probably not possible to allocate a single block of memory
+ * of this size. Use heap_caps_get_largest_free_block() for this purpose.
+
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ *
+ * @return Amount of free bytes in the regions
+ */
+size_t heap_caps_get_free_size( uint32_t caps );
+
+
+/**
+ * @brief Get the total minimum free memory of all regions with the given capabilities
+ *
+ * This adds all the low water marks of the regions capable of delivering the memory
+ * with the given capabilities.
+ *
+ * Note the result may be less than the global all-time minimum available heap of this kind, as "low water marks" are
+ * tracked per-region. Individual regions' heaps may have reached their "low water marks" at different points in time. However
+ * this result still gives a "worst case" indication for all-time minimum free heap.
+ *
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ *
+ * @return Amount of free bytes in the regions
+ */
+size_t heap_caps_get_minimum_free_size( uint32_t caps );
+
+/**
+ * @brief Get the largest free block of memory able to be allocated with the given capabilities.
+ *
+ * Returns the largest value of ``s`` for which ``heap_caps_malloc(s, caps)`` will succeed.
+ *
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ *
+ * @return Size of largest free block in bytes.
+ */
+size_t heap_caps_get_largest_free_block( uint32_t caps );
+
+
+/**
+ * @brief Get heap info for all regions with the given capabilities.
+ *
+ * Calls multi_heap_info() on all heaps which share the given capabilities.  The information returned is an aggregate
+ * across all matching heaps.  The meanings of fields are the same as defined for multi_heap_info_t, except that
+ * ``minimum_free_bytes`` has the same caveats described in heap_caps_get_minimum_free_size().
+ *
+ * @param info        Pointer to a structure which will be filled with relevant
+ *                    heap metadata.
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ *
+ */
+void heap_caps_get_info( multi_heap_info_t *info, uint32_t caps );
+
+
+/**
+ * @brief Print a summary of all memory with the given capabilities.
+ *
+ * Calls multi_heap_info on all heaps which share the given capabilities, and
+ * prints a two-line summary for each, then a total summary.
+ *
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ *
+ */
+void heap_caps_print_heap_info( uint32_t caps );
+
+/**
+ * @brief Check integrity of all heap memory in the system.
+ *
+ * Calls multi_heap_check on all heaps. Optionally print errors if heaps are corrupt.
+ *
+ * Calling this function is equivalent to calling heap_caps_check_integrity
+ * with the caps argument set to MALLOC_CAP_INVALID.
+ *
+ * @param print_errors Print specific errors if heap corruption is found.
+ *
+ * @return True if all heaps are valid, False if at least one heap is corrupt.
+ */
+bool heap_caps_check_integrity_all(bool print_errors);
+
+/**
+ * @brief Check integrity of all heaps with the given capabilities.
+ *
+ * Calls multi_heap_check on all heaps which share the given capabilities. Optionally
+ * print errors if the heaps are corrupt.
+ *
+ * See also heap_caps_check_integrity_all to check all heap memory
+ * in the system and heap_caps_check_integrity_addr to check memory
+ * around a single address.
+ *
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ * @param print_errors Print specific errors if heap corruption is found.
+ *
+ * @return True if all heaps are valid, False if at least one heap is corrupt.
+ */
+bool heap_caps_check_integrity(uint32_t caps, bool print_errors);
+
+/**
+ * @brief Check integrity of heap memory around a given address.
+ *
+ * This function can be used to check the integrity of a single region of heap memory,
+ * which contains the given address.
+ *
+ * This can be useful if debugging heap integrity for corruption at a known address,
+ * as it has a lower overhead than checking all heap regions. Note that if the corrupt
+ * address moves around between runs (due to timing or other factors) then this approach
+ * won't work and you should call heap_caps_check_integrity or
+ * heap_caps_check_integrity_all instead.
+ *
+ * @note The entire heap region around the address is checked, not only the adjacent
+ * heap blocks.
+ *
+ * @param addr Address in memory. Check for corruption in region containing this address.
+ * @param print_errors Print specific errors if heap corruption is found.
+ *
+ * @return True if the heap containing the specified address is valid,
+ * False if at least one heap is corrupt or the address doesn't belong to a heap region.
+ */
+bool heap_caps_check_integrity_addr(intptr_t addr, bool print_errors);
+
+/**
+ * @brief Enable malloc() in external memory and set limit below which
+ *        malloc() attempts are placed in internal memory.
+ *
+ * When external memory is in use, the allocation strategy is to initially try to
+ * satisfy smaller allocation requests with internal memory and larger requests
+ * with external memory. This sets the limit between the two, as well as generally
+ * enabling allocation in external memory.
+ *
+ * @param limit       Limit, in bytes.
+ */
+void heap_caps_malloc_extmem_enable(size_t limit);
+
+/**
+ * @brief Allocate a chunk of memory as preference in decreasing order.
+ *
+ * @attention The variable parameters are bitwise OR of MALLOC_CAP_* flags indicating the type of memory.
+ *            This API prefers to allocate memory with the first parameter. If failed, allocate memory with
+ *            the next parameter. It will try in this order until allocating a chunk of memory successfully
+ *            or fail to allocate memories with any of the parameters.
+ *
+ * @param size Size, in bytes, of the amount of memory to allocate
+ * @param num Number of variable paramters
+ *
+ * @return A pointer to the memory allocated on success, NULL on failure
+ */
+void *heap_caps_malloc_prefer( size_t size, size_t num, ... );
+
+/**
+ * @brief Allocate a chunk of memory as preference in decreasing order.
+ *
+ * @param ptr Pointer to previously allocated memory, or NULL for a new allocation.
+ * @param size Size of the new buffer requested, or 0 to free the buffer.
+ * @param num Number of variable paramters
+ *
+ * @return Pointer to a new buffer of size 'size', or NULL if allocation failed.
+ */
+void *heap_caps_realloc_prefer( void *ptr, size_t size, size_t num, ... );
+
+/**
+ * @brief Allocate a chunk of memory as preference in decreasing order.
+ *
+ * @param n    Number of continuing chunks of memory to allocate
+ * @param size Size, in bytes, of a chunk of memory to allocate
+ * @param num  Number of variable paramters
+ *
+ * @return A pointer to the memory allocated on success, NULL on failure
+ */
+void *heap_caps_calloc_prefer( size_t n, size_t size, size_t num, ... );
+
+/**
+ * @brief Dump the full structure of all heaps with matching capabilities.
+ *
+ * Prints a large amount of output to serial (because of locking limitations,
+ * the output bypasses stdout/stderr). For each (variable sized) block
+ * in each matching heap, the following output is printed on a single line:
+ *
+ * - Block address (the data buffer returned by malloc is 4 bytes after this
+ *   if heap debugging is set to Basic, or 8 bytes otherwise).
+ * - Data size (the data size may be larger than the size requested by malloc,
+ *   either due to heap fragmentation or because of heap debugging level).
+ * - Address of next block in the heap.
+ * - If the block is free, the address of the next free block is also printed.
+ *
+ * @param caps        Bitwise OR of MALLOC_CAP_* flags indicating the type
+ *                    of memory
+ */
+void heap_caps_dump(uint32_t caps);
+
+/**
+ * @brief Dump the full structure of all heaps.
+ *
+ * Covers all registered heaps. Prints a large amount of output to serial.
+ *
+ * Output is the same as for heap_caps_dump.
+ *
+ */
+void heap_caps_dump_all(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEAP_ESP_HEAP_CAPS_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/heap/esp_heap_caps_init.h b/cpu/esp32/vendor/esp-idf/include/heap/esp_heap_caps_init.h
new file mode 100644
index 0000000000000000000000000000000000000000..f6c2248520bb251d08a98ef9a9faba986013c94d
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/heap/esp_heap_caps_init.h
@@ -0,0 +1,95 @@
+// 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.
+
+#ifndef HEAP_ESP_HEAP_CAPS_INIT_H
+#define HEAP_ESP_HEAP_CAPS_INIT_H
+
+#include "esp_err.h"
+#include "esp_heap_caps.h"
+#include "soc/soc_memory_layout.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Initialize the capability-aware heap allocator.
+ *
+ * This is called once in the IDF startup code. Do not call it
+ * at other times.
+ */
+void heap_caps_init(void);
+
+/**
+ * @brief Enable heap(s) in memory regions where the startup stacks are located.
+ *
+ * On startup, the pro/app CPUs have a certain memory region they use as stack, so we
+ * cannot do allocations in the regions these stack frames are. When FreeRTOS is
+ * completely started, they do not use that memory anymore and heap(s) there can
+ * be enabled.
+ */
+void heap_caps_enable_nonos_stack_heaps(void);
+
+/**
+ * @brief Add a region of memory to the collection of heaps at runtime.
+ *
+ * Most memory regions are defined in soc_memory_layout.c for the SoC,
+ * and are registered via heap_caps_init(). Some regions can't be used
+ * immediately and are later enabled via heap_caps_enable_nonos_stack_heaps().
+ *
+ * Call this function to add a region of memory to the heap at some later time.
+ *
+ * This function does not consider any of the "reserved" regions or other data in soc_memory_layout, caller needs to
+ * consider this themselves.
+ *
+ * All memory within the region specified by start & end parameters must be otherwise unused.
+ *
+ * The capabilities of the newly registered memory will be determined by the start address, as looked up in the regions
+ * specified in soc_memory_layout.c.
+ *
+ * Use heap_caps_add_region_with_caps() to register a region with custom capabilities.
+ *
+ * @param start Start address of new region.
+ * @param end End address of new region.
+ *
+ * @return ESP_OK on success, ESP_ERR_INVALID_ARG if a parameter is invalid, ESP_ERR_NOT_FOUND if the
+ * specified start address doesn't reside in a known region, or any error returned by heap_caps_add_region_with_caps().
+ */
+esp_err_t heap_caps_add_region(intptr_t start, intptr_t end);
+
+
+/**
+ * @brief Add a region of memory to the collection of heaps at runtime, with custom capabilities.
+ *
+ * Similar to heap_caps_add_region(), only custom memory capabilities are specified by the caller.
+ *
+ * @param caps Ordered array of capability masks for the new region, in order of priority. Must have length
+ * SOC_MEMORY_TYPE_NO_PRIOS. Does not need to remain valid after the call returns.
+ * @param start Start address of new region.
+ * @param end End address of new region.
+ *
+ * @return
+ *         - ESP_OK on success
+ *         - ESP_ERR_INVALID_ARG if a parameter is invalid
+ *         - ESP_ERR_NO_MEM if no memory to register new heap.
+ *         - ESP_FAIL if region overlaps the start and/or end of an existing region
+ */
+esp_err_t heap_caps_add_region_with_caps(const uint32_t caps[], intptr_t start, intptr_t end);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HEAP_ESP_HEAP_CAPS_INIT_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/log/esp_log.h b/cpu/esp32/vendor/esp-idf/include/log/esp_log.h
new file mode 100644
index 0000000000000000000000000000000000000000..7743c05a7a88e9d03dee605b2bc8d4136655a40c
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/log/esp_log.h
@@ -0,0 +1,362 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef LOG_ESP_LOG_H
+#define LOG_ESP_LOG_H
+
+#include <stdint.h>
+#include <stdarg.h>
+#include "sdk_conf.h"
+#include <rom/ets_sys.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief Log level
+ *
+ */
+typedef enum {
+    ESP_LOG_NONE,       /*!< No log output */
+    ESP_LOG_ERROR,      /*!< Critical errors, software module can not recover on its own */
+    ESP_LOG_WARN,       /*!< Error conditions from which recovery measures have been taken */
+    ESP_LOG_INFO,       /*!< Information messages which describe normal flow of events */
+    ESP_LOG_DEBUG,      /*!< Extra information which is not necessary for normal use (values, pointers, sizes, etc). */
+    ESP_LOG_VERBOSE     /*!< Bigger chunks of debugging information, or frequent messages which can potentially flood the output. */
+} esp_log_level_t;
+
+typedef int (*vprintf_like_t)(const char *, va_list);
+
+/**
+ * @brief Set log level for given tag
+ *
+ * If logging for given component has already been enabled, changes previous setting.
+ *
+ * Note that this function can not raise log level above the level set using
+ * CONFIG_LOG_DEFAULT_LEVEL setting in menuconfig.
+ *
+ * To raise log level above the default one for a given file, define
+ * LOG_LOCAL_LEVEL to one of the ESP_LOG_* values, before including
+ * esp_log.h in this file.
+ *
+ * @param tag Tag of the log entries to enable. Must be a non-NULL zero terminated string.
+ *            Value "*" resets log level for all tags to the given value.
+ *
+ * @param level  Selects log level to enable. Only logs at this and lower verbosity
+ * levels will be shown.
+ */
+void esp_log_level_set(const char* tag, esp_log_level_t level);
+
+/**
+ * @brief Set function used to output log entries
+ *
+ * By default, log output goes to UART0. This function can be used to redirect log
+ * output to some other destination, such as file or network. Returns the original
+ * log handler, which may be necessary to return output to the previous destination.
+ *
+ * @param func new Function used for output. Must have same signature as vprintf.
+ *
+ * @return func old Function used for output.
+ */
+vprintf_like_t esp_log_set_vprintf(vprintf_like_t func);
+
+/**
+ * @brief Function which returns timestamp to be used in log output
+ *
+ * This function is used in expansion of ESP_LOGx macros.
+ * In the 2nd stage bootloader, and at early application startup stage
+ * this function uses CPU cycle counter as time source. Later when
+ * FreeRTOS scheduler start running, it switches to FreeRTOS tick count.
+ *
+ * For now, we ignore millisecond counter overflow.
+ *
+ * @return timestamp, in milliseconds
+ */
+uint32_t esp_log_timestamp(void);
+
+/**
+ * @brief Function which returns timestamp to be used in log output
+ *
+ * This function uses HW cycle counter and does not depend on OS,
+ * so it can be safely used after application crash.
+ *
+ * @return timestamp, in milliseconds
+ */
+uint32_t esp_log_early_timestamp(void);
+
+/**
+ * @brief Write message into the log
+ *
+ * This function is not intended to be used directly. Instead, use one of
+ * ESP_LOGE, ESP_LOGW, ESP_LOGI, ESP_LOGD, ESP_LOGV macros.
+ *
+ * This function or these macros should not be used from an interrupt.
+ */
+void esp_log_write(esp_log_level_t level, const char* tag, const char* format, ...) __attribute__ ((format (printf, 3, 4)));
+
+#ifndef RIOT_VERSION
+
+/** @cond */
+
+#include "esp_log_internal.h"
+
+#ifndef LOG_LOCAL_LEVEL
+#ifndef BOOTLOADER_BUILD
+#define LOG_LOCAL_LEVEL  CONFIG_LOG_DEFAULT_LEVEL
+#else
+#define LOG_LOCAL_LEVEL  CONFIG_LOG_BOOTLOADER_LEVEL
+#endif
+#endif
+
+/** @endcond */
+
+/**
+ * @brief Log a buffer of hex bytes at specified level, separated into 16 bytes each line.
+ *
+ * @param  tag      description tag
+ * @param  buffer   Pointer to the buffer array
+ * @param  buff_len length of buffer in bytes
+ * @param  level    level of the log
+ *
+ */
+#define ESP_LOG_BUFFER_HEX_LEVEL( tag, buffer, buff_len, level ) \
+    do {\
+        if ( LOG_LOCAL_LEVEL >= (level) ) { \
+            esp_log_buffer_hex_internal( tag, buffer, buff_len, level ); \
+        } \
+    } while(0)
+
+/**
+ * @brief Log a buffer of characters at specified level, separated into 16 bytes each line. Buffer should contain only printable characters.
+ *
+ * @param  tag      description tag
+ * @param  buffer   Pointer to the buffer array
+ * @param  buff_len length of buffer in bytes
+ * @param  level    level of the log
+ *
+ */
+#define ESP_LOG_BUFFER_CHAR_LEVEL( tag, buffer, buff_len, level ) \
+    do {\
+        if ( LOG_LOCAL_LEVEL >= (level) ) { \
+            esp_log_buffer_char_internal( tag, buffer, buff_len, level ); \
+        } \
+    } while(0)
+
+/**
+ * @brief Dump a buffer to the log at specified level.
+ *
+ * The dump log shows just like the one below:
+ *
+ *      W (195) log_example: 0x3ffb4280   45 53 50 33 32 20 69 73  20 67 72 65 61 74 2c 20  |ESP32 is great, |
+ *      W (195) log_example: 0x3ffb4290   77 6f 72 6b 69 6e 67 20  61 6c 6f 6e 67 20 77 69  |working along wi|
+ *      W (205) log_example: 0x3ffb42a0   74 68 20 74 68 65 20 49  44 46 2e 00              |th the IDF..|
+ *
+ * It is highly recommend to use terminals with over 102 text width.
+ *
+ * @param tag description tag
+ * @param buffer Pointer to the buffer array
+ * @param buff_len length of buffer in bytes
+ * @param level level of the log
+ */
+#define ESP_LOG_BUFFER_HEXDUMP( tag, buffer, buff_len, level ) \
+    do { \
+        if ( LOG_LOCAL_LEVEL >= (level) ) { \
+            esp_log_buffer_hexdump_internal( tag, buffer, buff_len, level); \
+        } \
+    } while(0)
+
+/**
+ * @brief Log a buffer of hex bytes at Info level
+ *
+ * @param  tag      description tag
+ * @param  buffer   Pointer to the buffer array
+ * @param  buff_len length of buffer in bytes
+ *
+ * @see ``esp_log_buffer_hex_level``
+ *
+ */
+#define ESP_LOG_BUFFER_HEX(tag, buffer, buff_len) \
+    do { \
+        if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { \
+            ESP_LOG_BUFFER_HEX_LEVEL( tag, buffer, buff_len, ESP_LOG_INFO ); \
+        }\
+    } while(0)
+
+/**
+ * @brief Log a buffer of characters at Info level. Buffer should contain only printable characters.
+ *
+ * @param  tag      description tag
+ * @param  buffer   Pointer to the buffer array
+ * @param  buff_len length of buffer in bytes
+ *
+ * @see ``esp_log_buffer_char_level``
+ *
+ */
+#define ESP_LOG_BUFFER_CHAR(tag, buffer, buff_len) \
+    do { \
+        if (LOG_LOCAL_LEVEL >= ESP_LOG_INFO) { \
+            ESP_LOG_BUFFER_CHAR_LEVEL( tag, buffer, buff_len, ESP_LOG_INFO ); \
+        }\
+    } while(0)
+
+/** @cond */
+
+//to be back compatible
+#define esp_log_buffer_hex      ESP_LOG_BUFFER_HEX
+#define esp_log_buffer_char     ESP_LOG_BUFFER_CHAR
+
+
+#if CONFIG_LOG_COLORS
+#define LOG_COLOR_BLACK   "30"
+#define LOG_COLOR_RED     "31"
+#define LOG_COLOR_GREEN   "32"
+#define LOG_COLOR_BROWN   "33"
+#define LOG_COLOR_BLUE    "34"
+#define LOG_COLOR_PURPLE  "35"
+#define LOG_COLOR_CYAN    "36"
+#define LOG_COLOR(COLOR)  "\033[0;" COLOR "m"
+#define LOG_BOLD(COLOR)   "\033[1;" COLOR "m"
+#define LOG_RESET_COLOR   "\033[0m"
+#define LOG_COLOR_E       LOG_COLOR(LOG_COLOR_RED)
+#define LOG_COLOR_W       LOG_COLOR(LOG_COLOR_BROWN)
+#define LOG_COLOR_I       LOG_COLOR(LOG_COLOR_GREEN)
+#define LOG_COLOR_D
+#define LOG_COLOR_V
+#else //CONFIG_LOG_COLORS
+#define LOG_COLOR_E
+#define LOG_COLOR_W
+#define LOG_COLOR_I
+#define LOG_COLOR_D
+#define LOG_COLOR_V
+#define LOG_RESET_COLOR
+#endif //CONFIG_LOG_COLORS
+
+#define LOG_FORMAT(letter, format)  LOG_COLOR_ ## letter #letter " (%d) %s: " format LOG_RESET_COLOR "\n"
+
+/** @endcond */
+
+/// macro to output logs in startup code, before heap allocator and syscalls have been initialized. log at ``ESP_LOG_ERROR`` level. @see ``printf``,``ESP_LOGE``
+#define ESP_EARLY_LOGE( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_ERROR,   E, ##__VA_ARGS__)
+/// macro to output logs in startup code at ``ESP_LOG_WARN`` level.  @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
+#define ESP_EARLY_LOGW( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_WARN,    W, ##__VA_ARGS__)
+/// macro to output logs in startup code at ``ESP_LOG_INFO`` level.  @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
+#define ESP_EARLY_LOGI( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_INFO,    I, ##__VA_ARGS__)
+/// macro to output logs in startup code at ``ESP_LOG_DEBUG`` level.  @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
+#define ESP_EARLY_LOGD( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_DEBUG,   D, ##__VA_ARGS__)
+/// macro to output logs in startup code at ``ESP_LOG_VERBOSE`` level.  @see ``ESP_EARLY_LOGE``,``ESP_LOGE``, ``printf``
+#define ESP_EARLY_LOGV( tag, format, ... ) ESP_LOG_EARLY_IMPL(tag, format, ESP_LOG_VERBOSE, V, ##__VA_ARGS__)
+
+#define ESP_LOG_EARLY_IMPL(tag, format, log_level, log_tag_letter, ...) do {                         \
+        if (LOG_LOCAL_LEVEL >= log_level) {                                                          \
+            ets_printf(LOG_FORMAT(log_tag_letter, format), esp_log_timestamp(), tag, ##__VA_ARGS__); \
+        }} while(0)
+
+#ifndef BOOTLOADER_BUILD
+#define ESP_LOGE( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_ERROR,   tag, format, ##__VA_ARGS__)
+#define ESP_LOGW( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_WARN,    tag, format, ##__VA_ARGS__)
+#define ESP_LOGI( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_INFO,    tag, format, ##__VA_ARGS__)
+#define ESP_LOGD( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_DEBUG,   tag, format, ##__VA_ARGS__)
+#define ESP_LOGV( tag, format, ... ) ESP_LOG_LEVEL_LOCAL(ESP_LOG_VERBOSE, tag, format, ##__VA_ARGS__)
+#else
+/**
+ * macro to output logs at ESP_LOG_ERROR level.
+ *
+ * @param tag tag of the log, which can be used to change the log level by ``esp_log_level_set`` at runtime.
+ *
+ * @see ``printf``
+ */
+#define ESP_LOGE( tag, format, ... )  ESP_EARLY_LOGE(tag, format, ##__VA_ARGS__)
+/// macro to output logs at ``ESP_LOG_WARN`` level.  @see ``ESP_LOGE``
+#define ESP_LOGW( tag, format, ... )  ESP_EARLY_LOGW(tag, format, ##__VA_ARGS__)
+/// macro to output logs at ``ESP_LOG_INFO`` level.  @see ``ESP_LOGE``
+#define ESP_LOGI( tag, format, ... )  ESP_EARLY_LOGI(tag, format, ##__VA_ARGS__)
+/// macro to output logs at ``ESP_LOG_DEBUG`` level.  @see ``ESP_LOGE``
+#define ESP_LOGD( tag, format, ... )  ESP_EARLY_LOGD(tag, format, ##__VA_ARGS__)
+/// macro to output logs at ``ESP_LOG_VERBOSE`` level.  @see ``ESP_LOGE``
+#define ESP_LOGV( tag, format, ... )  ESP_EARLY_LOGV(tag, format, ##__VA_ARGS__)
+#endif  // BOOTLOADER_BUILD
+
+/** runtime macro to output logs at a specified level.
+ *
+ * @param tag tag of the log, which can be used to change the log level by ``esp_log_level_set`` at runtime.
+ * @param level level of the output log.
+ * @param format format of the output log. see ``printf``
+ * @param ... variables to be replaced into the log. see ``printf``
+ *
+ * @see ``printf``
+ */
+#define ESP_LOG_LEVEL(level, tag, format, ...) do {                     \
+        if (level==ESP_LOG_ERROR )          { \
+            esp_log_write(ESP_LOG_ERROR,  tag, LOG_FORMAT(E, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
+        else if (level==ESP_LOG_WARN )      { esp_log_write(ESP_LOG_WARN,       tag, LOG_FORMAT(W, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
+        else if (level==ESP_LOG_DEBUG )     { esp_log_write(ESP_LOG_DEBUG,      tag, LOG_FORMAT(D, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
+        else if (level==ESP_LOG_VERBOSE )   { esp_log_write(ESP_LOG_VERBOSE,    tag, LOG_FORMAT(V, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
+        else                                { esp_log_write(ESP_LOG_INFO,       tag, LOG_FORMAT(I, format), esp_log_timestamp(), tag, ##__VA_ARGS__); } \
+    } while(0)
+
+/** runtime macro to output logs at a specified level. Also check the level with ``LOG_LOCAL_LEVEL``.
+ *
+ * @see ``printf``, ``ESP_LOG_LEVEL``
+ */
+#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...) do {               \
+        if ( LOG_LOCAL_LEVEL >= level ) ESP_LOG_LEVEL(level, tag, format, ##__VA_ARGS__); \
+    } while(0)
+
+#else /* RIOT_VERSION */
+
+#include "esp_common.h"
+
+#if 0 /* TODO */
+
+#define LOG_FORMAT(letter, format)  #letter " (%d) %s: " format "\n"
+
+#define ESP_LOG_LEVEL(level, tag, format, ...) do { \
+        if ((esp_log_level_t)level==ESP_LOG_ERROR ) { \
+            esp_log_write(ESP_LOG_ERROR, tag, LOG_FORMAT(E, format), \
+                          esp_log_timestamp(), tag, ##__VA_ARGS__);  \
+        } \
+        else if ((esp_log_level_t)level==ESP_LOG_WARN ) { \
+            esp_log_write(ESP_LOG_WARN,  tag, LOG_FORMAT(W, format), \
+                          esp_log_timestamp(), tag, ##__VA_ARGS__); \
+        } \
+        else if ((esp_log_level_t)level==ESP_LOG_DEBUG ) { \
+            esp_log_write(ESP_LOG_DEBUG, tag, LOG_FORMAT(D, format), \
+                          esp_log_timestamp(), tag, ##__VA_ARGS__); \
+        } \
+        else if ((esp_log_level_t)level==ESP_LOG_VERBOSE ) { \
+            esp_log_write(ESP_LOG_VERBOSE, tag, LOG_FORMAT(V, format), \
+                          esp_log_timestamp(), tag, ##__VA_ARGS__); \
+        } \
+        else {  \
+            esp_log_write(ESP_LOG_INFO, tag, LOG_FORMAT(I, format), \
+                          esp_log_timestamp(), tag, ##__VA_ARGS__); \
+        } \
+    } while(0)
+
+#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...) do {               \
+        if ( LOG_LOCAL_LEVEL >= level ) ESP_LOG_LEVEL(level, tag, format, ##__VA_ARGS__); \
+    } while(0)
+
+#else
+#define ESP_LOG_LEVEL_LOCAL(level, tag, format, ...)
+#endif
+
+#endif /* RIOT_VERSION */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LOG_ESP_LOG_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/sdkconfig.h b/cpu/esp32/vendor/esp-idf/include/sdkconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..c0965abeb170b78e38cce0a0bcda70303276fb7a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/sdkconfig.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2018 Gunar Schorcht
+ *
+ * This file is subject to the terms and conditions of the GNU Lesser
+ * General Public License v2.1. See the file LICENSE in the top level
+ * directory for more details.
+ */
+
+#ifndef SDKCONFIG_H
+#define SDKCONFIG_H
+
+#ifndef DOXYGEN
+
+#include "sdk_conf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DOXYGEN */
+#endif /* SDKCONFIG_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/soc/can_struct.h b/cpu/esp32/vendor/esp-idf/include/soc/can_struct.h
new file mode 100644
index 0000000000000000000000000000000000000000..3f566b135d5e7000a6e41ff7ce3a2a1c50c6f630
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/soc/can_struct.h
@@ -0,0 +1,211 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef _SOC_CAN_STRUCT_H_
+#define _SOC_CAN_STRUCT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* -------------------------- Register Definitions -------------------------- */
+
+/* The CAN peripheral's registers are 8bits, however the ESP32 can only access
+ * peripheral registers every 32bits. Therefore each CAN register is mapped to
+ * the least significant byte of every 32bits.
+ */
+typedef union {
+    struct {
+        uint32_t byte: 8;                                   /* LSB */
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_reg_t;
+
+typedef union {
+    struct {
+        uint32_t reset: 1;                                  /* MOD.0 Reset Mode */
+        uint32_t listen_only: 1;                            /* MOD.1 Listen Only Mode */
+        uint32_t self_test: 1;                              /* MOD.2 Self Test Mode */
+        uint32_t acceptance_filter: 1;                      /* MOD.3 Acceptance Filter Mode */
+        uint32_t reserved28: 28;                            /* Internal Reserved. MOD.4 Sleep Mode not supported */
+    };
+    uint32_t val;
+} can_mode_reg_t;
+
+typedef union {
+    struct {
+        uint32_t tx_req: 1;                                 /* CMR.0 Transmission Request */
+        uint32_t abort_tx: 1;                               /* CMR.1 Abort Transmission */
+        uint32_t release_rx_buff: 1;                        /* CMR.2 Release Receive Buffer */
+        uint32_t clear_data_overrun: 1;                     /* CMR.3 Clear Data Overrun */
+        uint32_t self_rx_req: 1;                            /* CMR.4 Self Reception Request */
+        uint32_t reserved27: 27;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_cmd_reg_t;
+
+typedef union {
+    struct {
+        uint32_t rx_buff: 1;                                /* SR.0 Receive Buffer Status */
+        uint32_t data_overrun: 1;                           /* SR.1 Data Overrun Status */
+        uint32_t tx_buff: 1;                                /* SR.2 Transmit Buffer Status */
+        uint32_t tx_complete: 1;                            /* SR.3 Transmission Complete Status */
+        uint32_t rx: 1;                                     /* SR.4 Receive Status */
+        uint32_t tx: 1;                                     /* SR.5 Transmit Status */
+        uint32_t error: 1;                                  /* SR.6 Error Status */
+        uint32_t bus: 1;                                    /* SR.7 Bus Status */
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_status_reg_t;
+
+typedef union {
+    struct {
+        uint32_t rx: 1;                                     /* IR.0 Receive Interrupt */
+        uint32_t tx: 1;                                     /* IR.1 Transmit Interrupt */
+        uint32_t err_warn: 1;                               /* IR.2 Error Interrupt */
+        uint32_t data_overrun: 1;                           /* IR.3 Data Overrun Interrupt */
+        uint32_t reserved1: 1;                              /* Internal Reserved (Wake-up not supported) */
+        uint32_t err_passive: 1;                            /* IR.5 Error Passive Interrupt */
+        uint32_t arb_lost: 1;                               /* IR.6 Arbitration Lost Interrupt */
+        uint32_t bus_err: 1;                                /* IR.7 Bus Error Interrupt */
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_intr_reg_t;
+
+typedef union {
+    struct {
+        uint32_t rx: 1;                                     /* IER.0 Receive Interrupt Enable */
+        uint32_t tx: 1;                                     /* IER.1 Transmit Interrupt Enable */
+        uint32_t err_warn: 1;                               /* IER.2 Error Interrupt Enable */
+        uint32_t data_overrun: 1;                           /* IER.3 Data Overrun Interrupt Enable */
+        uint32_t reserved1: 1;                              /* Internal Reserved (Wake-up not supported) */
+        uint32_t err_passive: 1;                            /* IER.5 Error Passive Interrupt Enable */
+        uint32_t arb_lost: 1;                               /* IER.6 Arbitration Lost Interrupt Enable */
+        uint32_t bus_err: 1;                                /* IER.7 Bus Error Interrupt Enable */
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_intr_en_reg_t;
+
+typedef union {
+    struct {
+        uint32_t baud_rate_prescaler: 6;                    /* BTR0[5:0] Baud Rate Prescaler */
+        uint32_t sync_jump_width: 2;                        /* BTR0[7:6] Synchronization Jump Width*/
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_bus_tim_0_reg_t;
+
+typedef union {
+    struct {
+        uint32_t time_seg_1: 4;                             /* BTR1[3:0] Timing Segment 1 */
+        uint32_t time_seg_2: 3;                             /* BTR1[6:4] Timing Segment 2 */
+        uint32_t sampling: 1;                               /* BTR1.7 Sampling*/
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_bus_tim_1_reg_t;
+
+typedef union {
+    struct {
+        uint32_t arbitration_lost_capture: 5;               /* ALC[4:0] Arbitration lost capture */
+        uint32_t reserved27: 27;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_arb_lost_cap_reg_t;
+
+typedef union {
+    struct {
+        uint32_t segment: 5;                                /* ECC[4:0] Error Code Segment 0 to 5 */
+        uint32_t direction: 1;                              /* ECC.5 Error Direction (TX/RX) */
+        uint32_t error_code: 2;                             /* ECC[7:6] Error Code */
+        uint32_t reserved24: 24;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_err_code_cap_reg_t;
+
+typedef struct {
+    can_reg_t code_reg[4];
+    can_reg_t mask_reg[4];
+    uint32_t reserved32[5];
+} can_acc_filter_t;
+
+typedef union {
+    struct {
+        uint32_t rx_message_counter: 5;                     /* RMC[4:0] RX Message Counter */
+        uint32_t reserved27: 27;                            /* Internal Reserved */
+    };
+    uint32_t val;
+} can_rx_msg_cnt_reg_t;
+
+typedef union {
+    struct {
+        uint32_t clock_divider: 3;                          /* CDR[2:0] CLKOUT frequency selector based of fOSC */
+        uint32_t clock_off: 1;                              /* CDR.3 CLKOUT enable/disable */
+        uint32_t reserved3: 3;                              /* Internal Reserved. RXINTEN and CBP not supported */
+        uint32_t can_mode: 1;                               /* CDR.7 BasicCAN:0 PeliCAN:1 */
+        uint32_t reserved24: 24;                            /* Internal Reserved  */
+    };
+    uint32_t val;
+} can_clk_div_reg_t;
+
+/* ---------------------------- Register Layout ------------------------------ */
+
+typedef volatile struct {
+    //Configuration and Control Registers
+    can_mode_reg_t mode_reg;                                /* Address 0 */
+    can_cmd_reg_t command_reg;                              /* Address 1 */
+    can_status_reg_t status_reg;                            /* Address 2 */
+    can_intr_reg_t interrupt_reg;                           /* Address 3 */
+    can_intr_en_reg_t interrupt_enable_reg;                 /* Address 4 */
+    uint32_t reserved_05;                                   /* Address 5 */
+    can_bus_tim_0_reg_t bus_timing_0_reg;                   /* Address 6 */
+    can_bus_tim_1_reg_t bus_timing_1_reg;                   /* Address 7 */
+    uint32_t reserved_08;                                   /* Address 8 (Output control not supported) */
+    uint32_t reserved_09;                                   /* Address 9 (Test Register not supported) */
+    uint32_t reserved_10;                                   /* Address 10 */
+
+    //Capture and Counter Registers
+    can_arb_lost_cap_reg_t arbitration_lost_captue_reg;     /* Address 11 */
+    can_err_code_cap_reg_t error_code_capture_reg;          /* Address 12 */
+    can_reg_t error_warning_limit_reg;                      /* EWLR[7:0] Error Warning Limit: Address 13 */
+    can_reg_t rx_error_counter_reg;                         /* RXERR[7:0] Receive Error Counter: Address 14 */
+    can_reg_t tx_error_counter_reg;                         /* TXERR[7:0] Transmit Error Counter: Address 15 */
+
+    //Shared Registers (TX Buff/RX Buff/Acc Filter)
+    union {
+        can_acc_filter_t acceptance_filter;
+        can_reg_t tx_rx_buffer[13];
+    };                                                      /* Address 16-28 TX/RX Buffer and Acc Filter*/;
+
+    //Misc Registers
+    can_rx_msg_cnt_reg_t rx_message_counter_reg;            /* Address 29 */
+    can_reg_t reserved_30;                                  /* Address 30 (RX Buffer Start Address not supported) */
+    can_clk_div_reg_t clock_divider_reg;                    /* Address 31 */
+
+    //Start of RX FIFO
+} can_dev_t;
+
+_Static_assert(sizeof(can_dev_t) == 128, "CAN registers should be 32 * 4 bytes");
+
+extern can_dev_t CAN;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif  /* _SOC_CAN_STRUCT_H_ */
+
diff --git a/cpu/esp32/vendor/esp-idf/include/soc/cpu.h b/cpu/esp32/vendor/esp-idf/include/soc/cpu.h
new file mode 100644
index 0000000000000000000000000000000000000000..2094768e4ff97d0b4dabef189291269045c3c1c6
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/soc/cpu.h
@@ -0,0 +1,112 @@
+// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOC_CPU_H
+#define SOC_CPU_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "xtensa/corebits.h"
+
+/* C macros for xtensa special register read/write/exchange */
+
+#define RSR(reg, curval)  asm volatile ("rsr %0, " #reg : "=r" (curval));
+#define WSR(reg, newval)  asm volatile ("wsr %0, " #reg : : "r" (newval));
+#define XSR(reg, swapval) asm volatile ("xsr %0, " #reg : "+r" (swapval));
+
+/** @brief Read current stack pointer address
+ *
+ */
+static inline void *get_sp(void)
+{
+    void *sp;
+    asm volatile ("mov %0, sp;" : "=r" (sp));
+    return sp;
+}
+
+/* Functions to set page attributes for Region Protection option in the CPU.
+ * See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
+ */
+
+static inline void cpu_write_dtlb(uint32_t vpn, unsigned attr)
+{
+    asm volatile ("wdtlb  %1, %0; dsync\n" :: "r" (vpn), "r" (attr));
+}
+
+
+static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
+{
+    asm volatile ("witlb  %1, %0; isync\n" :: "r" (vpn), "r" (attr));
+}
+
+/**
+ * @brief Configure memory region protection
+ *
+ * Make page 0 access raise an exception.
+ * Also protect some other unused pages so we can catch weirdness.
+ * Useful attribute values:
+ * 0 — cached, RW
+ * 2 — bypass cache, RWX (default value after CPU reset)
+ * 15 — no access, raise exception
+ */
+
+static inline void cpu_configure_region_protection(void)
+{
+    const uint32_t pages_to_protect[] = {0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000};
+    for (unsigned i = 0; i < sizeof(pages_to_protect)/sizeof(pages_to_protect[0]); ++i) {
+        cpu_write_dtlb(pages_to_protect[i], 0xf);
+        cpu_write_itlb(pages_to_protect[i], 0xf);
+    }
+    cpu_write_dtlb(0x20000000, 0);
+    cpu_write_itlb(0x20000000, 0);
+}
+
+/**
+ * @brief Stall CPU using RTC controller
+ * @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP)
+ */
+void esp_cpu_stall(int cpu_id);
+
+/**
+ * @brief Un-stall CPU using RTC controller
+ * @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP)
+ */
+void esp_cpu_unstall(int cpu_id);
+
+/**
+ * @brief Reset CPU using RTC controller
+ * @param cpu_id ID of the CPU to reset (0 = PRO, 1 = APP)
+ */
+void esp_cpu_reset(int cpu_id);
+
+
+/**
+ * @brief Returns true if a JTAG debugger is attached to CPU
+ * OCD (on chip debug) port.
+ *
+ * @note If "Make exception and panic handlers JTAG/OCD aware"
+ * is disabled, this function always returns false.
+ */
+bool esp_cpu_in_ocd_debug_mode(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOC_CPU_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/soc/dport_access.h b/cpu/esp32/vendor/esp-idf/include/soc/dport_access.h
new file mode 100644
index 0000000000000000000000000000000000000000..e5d43c45d4bbd81562d870370c01c993d3862a9d
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/soc/dport_access.h
@@ -0,0 +1,207 @@
+// Copyright 2010-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.
+
+#ifndef SOC_DPORT_ACCESS_H
+#define SOC_DPORT_ACCESS_H
+
+#include <stdint.h>
+#include "esp_attr.h"
+#include "esp_dport_access.h"
+#ifndef RIOT_VERSION
+#include "soc.h"
+#include "uart_reg.h"
+#include "xtensa/xtruntime.h"
+#else
+#include "soc/soc.h"
+#include "soc/uart_reg.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//Registers Operation {{
+
+// The _DPORT_xxx register read macros access DPORT memory directly (as opposed to
+// DPORT_REG_READ which applies SMP-safe protections).
+//
+// There are several ways to read the DPORT registers:
+// 1) Use DPORT_REG_READ versions to be SMP-safe in IDF apps.
+//    This method uses the pre-read APB implementation(*) without stall other CPU.
+//    This is beneficial for single readings.
+// 2) If you want to make a sequence of DPORT reads to buffer,
+//    use dport_read_buffer(buff_out, address, num_words),
+//    it is the faster method and it doesn't stop other CPU.
+// 3) If you want to make a sequence of DPORT reads, but you don't want to stop other CPU
+//    and you want to do it faster then you need use DPORT_SEQUENCE_REG_READ().
+//    The difference from the first is that the user himself must disable interrupts while DPORT reading.
+//    Note that disable interrupt need only if the chip has two cores.
+// 4) If you want to make a sequence of DPORT reads,
+//    use DPORT_STALL_OTHER_CPU_START() macro explicitly
+//    and then use _DPORT_REG_READ macro while other CPU is stalled.
+//    After completing read operations, use DPORT_STALL_OTHER_CPU_END().
+//    This method uses stall other CPU while reading DPORT registers.
+//    Useful for compatibility, as well as for large consecutive readings.
+//    This method is slower, but must be used if ROM functions or
+//    other code is called which accesses DPORT without any other workaround.
+// *) The pre-readable APB register before reading the DPORT register
+//    helps synchronize the operation of the two CPUs,
+//    so that reading on different CPUs no longer causes random errors APB register.
+
+// _DPORT_REG_WRITE & DPORT_REG_WRITE are equivalent.
+#define _DPORT_REG_READ(_r)        (*(volatile uint32_t *)(_r))
+#define _DPORT_REG_WRITE(_r, _v)   (*(volatile uint32_t *)(_r)) = (_v)
+
+// Write value to DPORT register (does not require protecting)
+#define DPORT_REG_WRITE(_r, _v)   _DPORT_REG_WRITE((_r), (_v))
+
+/**
+ * @brief Read value from register, SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * This implementation is useful for reading DORT registers for single reading without stall other CPU.
+ * There is disable/enable interrupt.
+ *
+ * @param reg Register address
+ * @return Value
+ */
+static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    return esp_dport_access_reg_read(reg);
+#endif
+}
+
+/**
+ * @brief Read value from register, NOT SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * There is not disable/enable interrupt.
+ * The difference from DPORT_REG_READ() is that the user himself must disable interrupts while DPORT reading.
+ * This implementation is useful for reading DORT registers in loop without stall other CPU. Note the usage example.
+ * The recommended way to read registers sequentially without stall other CPU
+ * is to use the method esp_dport_read_buffer(buff_out, address, num_words). It allows you to read registers in the buffer.
+ *
+ * \code{c}
+ * // This example shows how to use it.
+ * { // Use curly brackets to limit the visibility of variables in macros DPORT_INTERRUPT_DISABLE/RESTORE.
+ *     DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
+ *     for (i = 0; i < max; ++i) {
+ *        array[i] = DPORT_SEQUENCE_REG_READ(Address + i * 4); // reading DPORT registers
+ *     }
+ *     DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
+ * }
+ * \endcode
+ *
+ * @param reg Register address
+ * @return Value
+ */
+static inline uint32_t IRAM_ATTR DPORT_SEQUENCE_REG_READ(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    return esp_dport_access_sequence_reg_read(reg);
+#endif
+}
+
+//get bit or get bits from register
+#define DPORT_REG_GET_BIT(_r, _b)  (DPORT_REG_READ(_r) & (_b))
+
+//set bit or set bits to register
+#define DPORT_REG_SET_BIT(_r, _b)  DPORT_REG_WRITE((_r), (DPORT_REG_READ(_r)|(_b)))
+
+//clear bit or clear bits of register
+#define DPORT_REG_CLR_BIT(_r, _b)  DPORT_REG_WRITE((_r), (DPORT_REG_READ(_r) & (~(_b))))
+
+//set bits of register controlled by mask
+#define DPORT_REG_SET_BITS(_r, _b, _m) DPORT_REG_WRITE((_r), ((DPORT_REG_READ(_r) & (~(_m))) | ((_b) & (_m))))
+
+//get field from register, uses field _S & _V to determine mask
+#define DPORT_REG_GET_FIELD(_r, _f) ((DPORT_REG_READ(_r) >> (_f##_S)) & (_f##_V))
+
+//set field to register, used when _f is not left shifted by _f##_S
+#define DPORT_REG_SET_FIELD(_r, _f, _v) DPORT_REG_WRITE((_r), ((DPORT_REG_READ(_r) & (~((_f##_V) << (_f##_S))))|(((_v) & (_f##_V))<<(_f##_S))))
+
+//get field value from a variable, used when _f is not left shifted by _f##_S
+#define DPORT_VALUE_GET_FIELD(_r, _f) (((_r) >> (_f##_S)) & (_f))
+
+//get field value from a variable, used when _f is left shifted by _f##_S
+#define DPORT_VALUE_GET_FIELD2(_r, _f) (((_r) & (_f))>> (_f##_S))
+
+//set field value to a variable, used when _f is not left shifted by _f##_S
+#define DPORT_VALUE_SET_FIELD(_r, _f, _v) ((_r)=(((_r) & ~((_f) << (_f##_S)))|((_v)<<(_f##_S))))
+
+//set field value to a variable, used when _f is left shifted by _f##_S
+#define DPORT_VALUE_SET_FIELD2(_r, _f, _v) ((_r)=(((_r) & ~(_f))|((_v)<<(_f##_S))))
+
+//generate a value from a field value, used when _f is not left shifted by _f##_S
+#define DPORT_FIELD_TO_VALUE(_f, _v) (((_v)&(_f))<<_f##_S)
+
+//generate a value from a field value, used when _f is left shifted by _f##_S
+#define DPORT_FIELD_TO_VALUE2(_f, _v) (((_v)<<_f##_S) & (_f))
+
+//Register read macros with an underscore prefix access DPORT memory directly. In IDF apps, use the non-underscore versions to be SMP-safe.
+#define _DPORT_READ_PERI_REG(addr) (*((volatile uint32_t *)(addr)))
+#define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
+#define _DPORT_REG_SET_BIT(_r, _b)  _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r)|(_b)))
+#define _DPORT_REG_CLR_BIT(_r, _b)  _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r) & (~(_b))))
+
+/**
+ * @brief Read value from register, SMP-safe version.
+ *
+ * This method uses the pre-reading of the APB register before reading the register of the DPORT.
+ * This implementation is useful for reading DORT registers for single reading without stall other CPU.
+ *
+ * @param reg Register address
+ * @return Value
+ */
+static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t reg)
+{
+#if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM)
+    return _DPORT_REG_READ(reg);
+#else
+    return esp_dport_access_reg_read(reg);
+#endif
+}
+
+//write value to register
+#define DPORT_WRITE_PERI_REG(addr, val) _DPORT_WRITE_PERI_REG((addr), (val))
+
+//clear bits of register controlled by mask
+#define DPORT_CLEAR_PERI_REG_MASK(reg, mask) DPORT_WRITE_PERI_REG((reg), (DPORT_READ_PERI_REG(reg)&(~(mask))))
+
+//set bits of register controlled by mask
+#define DPORT_SET_PERI_REG_MASK(reg, mask)   DPORT_WRITE_PERI_REG((reg), (DPORT_READ_PERI_REG(reg)|(mask)))
+
+//get bits of register controlled by mask
+#define DPORT_GET_PERI_REG_MASK(reg, mask)   (DPORT_READ_PERI_REG(reg) & (mask))
+
+//get bits of register controlled by highest bit and lowest bit
+#define DPORT_GET_PERI_REG_BITS(reg, hipos,lowpos)     ((DPORT_READ_PERI_REG(reg)>>(lowpos))&((1<<((hipos)-(lowpos)+1))-1))
+
+//set bits of register controlled by mask and shift
+#define DPORT_SET_PERI_REG_BITS(reg,bit_map,value,shift) DPORT_WRITE_PERI_REG((reg), ((DPORT_READ_PERI_REG(reg)&(~((bit_map)<<(shift))))|(((value) & bit_map)<<(shift))))
+
+//get field of register
+#define DPORT_GET_PERI_REG_BITS2(reg, mask,shift)      ((DPORT_READ_PERI_REG(reg)>>(shift))&(mask))
+//}}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOC_DPORT_ACCESS_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/soc/dport_reg.h b/cpu/esp32/vendor/esp-idf/include/soc/dport_reg.h
new file mode 100644
index 0000000000000000000000000000000000000000..b92c8c93e51ce36074058207cc8bdb1fc9731eb2
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/soc/dport_reg.h
@@ -0,0 +1,4292 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOC_DPORT_REG_H
+#define SOC_DPORT_REG_H
+
+#include "soc/soc.h"
+
+#ifndef __ASSEMBLER__
+#include "dport_access.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Registers defined in this header file must be accessed using special macros,
+ * prefixed with DPORT_. See soc/dport_access.h file for details.
+ */
+
+#define DPORT_PRO_BOOT_REMAP_CTRL_REG          (DR_REG_DPORT_BASE + 0x000)
+/* DPORT_PRO_BOOT_REMAP : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_BOOT_REMAP  (BIT(0))
+#define DPORT_PRO_BOOT_REMAP_M  (BIT(0))
+#define DPORT_PRO_BOOT_REMAP_V  0x1
+#define DPORT_PRO_BOOT_REMAP_S  0
+
+#define DPORT_APP_BOOT_REMAP_CTRL_REG          (DR_REG_DPORT_BASE + 0x004)
+/* DPORT_APP_BOOT_REMAP : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_BOOT_REMAP  (BIT(0))
+#define DPORT_APP_BOOT_REMAP_M  (BIT(0))
+#define DPORT_APP_BOOT_REMAP_V  0x1
+#define DPORT_APP_BOOT_REMAP_S  0
+
+#define DPORT_ACCESS_CHECK_REG          (DR_REG_DPORT_BASE + 0x008)
+/* DPORT_ACCESS_CHECK_APP : RO ;bitpos:[8] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_ACCESS_CHECK_APP  (BIT(8))
+#define DPORT_ACCESS_CHECK_APP_M  (BIT(8))
+#define DPORT_ACCESS_CHECK_APP_V  0x1
+#define DPORT_ACCESS_CHECK_APP_S  8
+/* DPORT_ACCESS_CHECK_PRO : RO ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_ACCESS_CHECK_PRO  (BIT(0))
+#define DPORT_ACCESS_CHECK_PRO_M  (BIT(0))
+#define DPORT_ACCESS_CHECK_PRO_V  0x1
+#define DPORT_ACCESS_CHECK_PRO_S  0
+
+#define DPORT_PRO_DPORT_APB_MASK0_REG          (DR_REG_DPORT_BASE + 0x00C)
+/* DPORT_PRODPORT_APB_MASK0 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PRODPORT_APB_MASK0  0xFFFFFFFF
+#define DPORT_PRODPORT_APB_MASK0_M  ((DPORT_PRODPORT_APB_MASK0_V)<<(DPORT_PRODPORT_APB_MASK0_S))
+#define DPORT_PRODPORT_APB_MASK0_V  0xFFFFFFFF
+#define DPORT_PRODPORT_APB_MASK0_S  0
+
+#define DPORT_PRO_DPORT_APB_MASK1_REG          (DR_REG_DPORT_BASE + 0x010)
+/* DPORT_PRODPORT_APB_MASK1 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PRODPORT_APB_MASK1  0xFFFFFFFF
+#define DPORT_PRODPORT_APB_MASK1_M  ((DPORT_PRODPORT_APB_MASK1_V)<<(DPORT_PRODPORT_APB_MASK1_S))
+#define DPORT_PRODPORT_APB_MASK1_V  0xFFFFFFFF
+#define DPORT_PRODPORT_APB_MASK1_S  0
+
+#define DPORT_APP_DPORT_APB_MASK0_REG          (DR_REG_DPORT_BASE + 0x014)
+/* DPORT_APPDPORT_APB_MASK0 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_APPDPORT_APB_MASK0  0xFFFFFFFF
+#define DPORT_APPDPORT_APB_MASK0_M  ((DPORT_APPDPORT_APB_MASK0_V)<<(DPORT_APPDPORT_APB_MASK0_S))
+#define DPORT_APPDPORT_APB_MASK0_V  0xFFFFFFFF
+#define DPORT_APPDPORT_APB_MASK0_S  0
+
+#define DPORT_APP_DPORT_APB_MASK1_REG          (DR_REG_DPORT_BASE + 0x018)
+/* DPORT_APPDPORT_APB_MASK1 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_APPDPORT_APB_MASK1  0xFFFFFFFF
+#define DPORT_APPDPORT_APB_MASK1_M  ((DPORT_APPDPORT_APB_MASK1_V)<<(DPORT_APPDPORT_APB_MASK1_S))
+#define DPORT_APPDPORT_APB_MASK1_V  0xFFFFFFFF
+#define DPORT_APPDPORT_APB_MASK1_S  0
+
+#define DPORT_PERI_CLK_EN_REG          (DR_REG_DPORT_BASE + 0x01C)
+/* DPORT_PERI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PERI_CLK_EN  0xFFFFFFFF
+#define DPORT_PERI_CLK_EN_M  ((DPORT_PERI_CLK_EN_V)<<(DPORT_PERI_CLK_EN_S))
+#define DPORT_PERI_CLK_EN_V  0xFFFFFFFF
+#define DPORT_PERI_CLK_EN_S  0
+
+#define DPORT_PERI_RST_EN_REG          (DR_REG_DPORT_BASE + 0x020)
+/* DPORT_PERI_RST_EN : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PERI_RST_EN  0xFFFFFFFF
+#define DPORT_PERI_RST_EN_M  ((DPORT_PERI_RST_EN_V)<<(DPORT_PERI_RST_EN_S))
+#define DPORT_PERI_RST_EN_V  0xFFFFFFFF
+#define DPORT_PERI_RST_EN_S  0
+
+/* The following bits apply to DPORT_PERI_CLK_EN_REG, DPORT_PERI_RST_EN_REG
+ */
+#define DPORT_PERI_EN_AES (1<<0)
+#define DPORT_PERI_EN_SHA (1<<1)
+#define DPORT_PERI_EN_RSA (1<<2)
+/* NB: Secure boot reset will hold SHA & AES in reset */
+#define DPORT_PERI_EN_SECUREBOOT (1<<3)
+/* NB: Digital signature reset will hold AES & RSA in reset */
+#define DPORT_PERI_EN_DIGITAL_SIGNATURE (1<<4)
+
+#define DPORT_WIFI_BB_CFG_REG          (DR_REG_DPORT_BASE + 0x024)
+/* DPORT_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_WIFI_BB_CFG  0xFFFFFFFF
+#define DPORT_WIFI_BB_CFG_M  ((DPORT_WIFI_BB_CFG_V)<<(DPORT_WIFI_BB_CFG_S))
+#define DPORT_WIFI_BB_CFG_V  0xFFFFFFFF
+#define DPORT_WIFI_BB_CFG_S  0
+
+#define DPORT_WIFI_BB_CFG_2_REG          (DR_REG_DPORT_BASE + 0x028)
+/* DPORT_WIFI_BB_CFG_2 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_WIFI_BB_CFG_2  0xFFFFFFFF
+#define DPORT_WIFI_BB_CFG_2_M  ((DPORT_WIFI_BB_CFG_2_V)<<(DPORT_WIFI_BB_CFG_2_S))
+#define DPORT_WIFI_BB_CFG_2_V  0xFFFFFFFF
+#define DPORT_WIFI_BB_CFG_2_S  0
+
+#define DPORT_APPCPU_CTRL_A_REG          (DR_REG_DPORT_BASE + 0x02C)
+/* DPORT_APPCPU_RESETTING : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APPCPU_RESETTING  (BIT(0))
+#define DPORT_APPCPU_RESETTING_M  (BIT(0))
+#define DPORT_APPCPU_RESETTING_V  0x1
+#define DPORT_APPCPU_RESETTING_S  0
+
+#define DPORT_APPCPU_CTRL_B_REG          (DR_REG_DPORT_BASE + 0x030)
+/* DPORT_APPCPU_CLKGATE_EN : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APPCPU_CLKGATE_EN  (BIT(0))
+#define DPORT_APPCPU_CLKGATE_EN_M  (BIT(0))
+#define DPORT_APPCPU_CLKGATE_EN_V  0x1
+#define DPORT_APPCPU_CLKGATE_EN_S  0
+
+#define DPORT_APPCPU_CTRL_C_REG          (DR_REG_DPORT_BASE + 0x034)
+/* DPORT_APPCPU_RUNSTALL : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APPCPU_RUNSTALL  (BIT(0))
+#define DPORT_APPCPU_RUNSTALL_M  (BIT(0))
+#define DPORT_APPCPU_RUNSTALL_V  0x1
+#define DPORT_APPCPU_RUNSTALL_S  0
+
+#define DPORT_APPCPU_CTRL_D_REG          (DR_REG_DPORT_BASE + 0x038)
+/* DPORT_APPCPU_BOOT_ADDR : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_APPCPU_BOOT_ADDR  0xFFFFFFFF
+#define DPORT_APPCPU_BOOT_ADDR_M  ((DPORT_APPCPU_BOOT_ADDR_V)<<(DPORT_APPCPU_BOOT_ADDR_S))
+#define DPORT_APPCPU_BOOT_ADDR_V  0xFFFFFFFF
+#define DPORT_APPCPU_BOOT_ADDR_S  0
+
+#define DPORT_CPU_PER_CONF_REG          (DR_REG_DPORT_BASE + 0x03C)
+/* DPORT_FAST_CLK_RTC_SEL : R/W ;bitpos:[3] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_FAST_CLK_RTC_SEL  (BIT(3))
+#define DPORT_FAST_CLK_RTC_SEL_M  (BIT(3))
+#define DPORT_FAST_CLK_RTC_SEL_V  0x1
+#define DPORT_FAST_CLK_RTC_SEL_S  3
+/* DPORT_LOWSPEED_CLK_SEL : R/W ;bitpos:[2] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_LOWSPEED_CLK_SEL  (BIT(2))
+#define DPORT_LOWSPEED_CLK_SEL_M  (BIT(2))
+#define DPORT_LOWSPEED_CLK_SEL_V  0x1
+#define DPORT_LOWSPEED_CLK_SEL_S  2
+/* DPORT_CPUPERIOD_SEL : R/W ;bitpos:[1:0] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_CPUPERIOD_SEL  0x00000003
+#define DPORT_CPUPERIOD_SEL_M  ((DPORT_CPUPERIOD_SEL_V)<<(DPORT_CPUPERIOD_SEL_S))
+#define DPORT_CPUPERIOD_SEL_V  0x3
+#define DPORT_CPUPERIOD_SEL_S  0
+
+#define DPORT_PRO_CACHE_CTRL_REG          (DR_REG_DPORT_BASE + 0x040)
+/* DPORT_PRO_DRAM_HL : R/W ;bitpos:[16] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_DRAM_HL  (BIT(16))
+#define DPORT_PRO_DRAM_HL_M  (BIT(16))
+#define DPORT_PRO_DRAM_HL_V  0x1
+#define DPORT_PRO_DRAM_HL_S  16
+/* DPORT_SLAVE_REQ : RO ;bitpos:[15] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SLAVE_REQ  (BIT(15))
+#define DPORT_SLAVE_REQ_M  (BIT(15))
+#define DPORT_SLAVE_REQ_V  0x1
+#define DPORT_SLAVE_REQ_S  15
+/* DPORT_AHB_SPI_REQ : RO ;bitpos:[14] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_SPI_REQ  (BIT(14))
+#define DPORT_AHB_SPI_REQ_M  (BIT(14))
+#define DPORT_AHB_SPI_REQ_V  0x1
+#define DPORT_AHB_SPI_REQ_S  14
+/* DPORT_PRO_SLAVE_REQ : RO ;bitpos:[13] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_SLAVE_REQ  (BIT(13))
+#define DPORT_PRO_SLAVE_REQ_M  (BIT(13))
+#define DPORT_PRO_SLAVE_REQ_V  0x1
+#define DPORT_PRO_SLAVE_REQ_S  13
+/* DPORT_PRO_AHB_SPI_REQ : RO ;bitpos:[12] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_AHB_SPI_REQ  (BIT(12))
+#define DPORT_PRO_AHB_SPI_REQ_M  (BIT(12))
+#define DPORT_PRO_AHB_SPI_REQ_V  0x1
+#define DPORT_PRO_AHB_SPI_REQ_S  12
+/* DPORT_PRO_DRAM_SPLIT : R/W ;bitpos:[11] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_DRAM_SPLIT  (BIT(11))
+#define DPORT_PRO_DRAM_SPLIT_M  (BIT(11))
+#define DPORT_PRO_DRAM_SPLIT_V  0x1
+#define DPORT_PRO_DRAM_SPLIT_S  11
+/* DPORT_PRO_SINGLE_IRAM_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_SINGLE_IRAM_ENA  (BIT(10))
+#define DPORT_PRO_SINGLE_IRAM_ENA_M  (BIT(10))
+#define DPORT_PRO_SINGLE_IRAM_ENA_V  0x1
+#define DPORT_PRO_SINGLE_IRAM_ENA_S  10
+/* DPORT_PRO_CACHE_LOCK_3_EN : R/W ;bitpos:[9] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_3_EN  (BIT(9))
+#define DPORT_PRO_CACHE_LOCK_3_EN_M  (BIT(9))
+#define DPORT_PRO_CACHE_LOCK_3_EN_V  0x1
+#define DPORT_PRO_CACHE_LOCK_3_EN_S  9
+/* DPORT_PRO_CACHE_LOCK_2_EN : R/W ;bitpos:[8] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_2_EN  (BIT(8))
+#define DPORT_PRO_CACHE_LOCK_2_EN_M  (BIT(8))
+#define DPORT_PRO_CACHE_LOCK_2_EN_V  0x1
+#define DPORT_PRO_CACHE_LOCK_2_EN_S  8
+/* DPORT_PRO_CACHE_LOCK_1_EN : R/W ;bitpos:[7] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_1_EN  (BIT(7))
+#define DPORT_PRO_CACHE_LOCK_1_EN_M  (BIT(7))
+#define DPORT_PRO_CACHE_LOCK_1_EN_V  0x1
+#define DPORT_PRO_CACHE_LOCK_1_EN_S  7
+/* DPORT_PRO_CACHE_LOCK_0_EN : R/W ;bitpos:[6] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_0_EN  (BIT(6))
+#define DPORT_PRO_CACHE_LOCK_0_EN_M  (BIT(6))
+#define DPORT_PRO_CACHE_LOCK_0_EN_V  0x1
+#define DPORT_PRO_CACHE_LOCK_0_EN_S  6
+/* DPORT_PRO_CACHE_FLUSH_DONE : RO ;bitpos:[5] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_FLUSH_DONE  (BIT(5))
+#define DPORT_PRO_CACHE_FLUSH_DONE_M  (BIT(5))
+#define DPORT_PRO_CACHE_FLUSH_DONE_V  0x1
+#define DPORT_PRO_CACHE_FLUSH_DONE_S  5
+/* DPORT_PRO_CACHE_FLUSH_ENA : R/W ;bitpos:[4] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_FLUSH_ENA  (BIT(4))
+#define DPORT_PRO_CACHE_FLUSH_ENA_M  (BIT(4))
+#define DPORT_PRO_CACHE_FLUSH_ENA_V  0x1
+#define DPORT_PRO_CACHE_FLUSH_ENA_S  4
+/* DPORT_PRO_CACHE_ENABLE : R/W ;bitpos:[3] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_ENABLE  (BIT(3))
+#define DPORT_PRO_CACHE_ENABLE_M  (BIT(3))
+#define DPORT_PRO_CACHE_ENABLE_V  0x1
+#define DPORT_PRO_CACHE_ENABLE_S  3
+/* DPORT_PRO_CACHE_MODE : R/W ;bitpos:[2] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MODE  (BIT(2))
+#define DPORT_PRO_CACHE_MODE_M  (BIT(2))
+#define DPORT_PRO_CACHE_MODE_V  0x1
+#define DPORT_PRO_CACHE_MODE_S  2
+
+#define DPORT_PRO_CACHE_CTRL1_REG          (DR_REG_DPORT_BASE + 0x044)
+/* DPORT_PRO_CACHE_MMU_IA_CLR : R/W ;bitpos:[13] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MMU_IA_CLR  (BIT(13))
+#define DPORT_PRO_CACHE_MMU_IA_CLR_M  (BIT(13))
+#define DPORT_PRO_CACHE_MMU_IA_CLR_V  0x1
+#define DPORT_PRO_CACHE_MMU_IA_CLR_S  13
+/* DPORT_PRO_CMMU_PD : R/W ;bitpos:[12] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CMMU_PD  (BIT(12))
+#define DPORT_PRO_CMMU_PD_M  (BIT(12))
+#define DPORT_PRO_CMMU_PD_V  0x1
+#define DPORT_PRO_CMMU_PD_S  12
+/* DPORT_PRO_CMMU_FORCE_ON : R/W ;bitpos:[11] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CMMU_FORCE_ON  (BIT(11))
+#define DPORT_PRO_CMMU_FORCE_ON_M  (BIT(11))
+#define DPORT_PRO_CMMU_FORCE_ON_V  0x1
+#define DPORT_PRO_CMMU_FORCE_ON_S  11
+/* DPORT_PRO_CMMU_FLASH_PAGE_MODE : R/W ;bitpos:[10:9] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_PRO_CMMU_FLASH_PAGE_MODE  0x00000003
+#define DPORT_PRO_CMMU_FLASH_PAGE_MODE_M  ((DPORT_PRO_CMMU_FLASH_PAGE_MODE_V)<<(DPORT_PRO_CMMU_FLASH_PAGE_MODE_S))
+#define DPORT_PRO_CMMU_FLASH_PAGE_MODE_V  0x3
+#define DPORT_PRO_CMMU_FLASH_PAGE_MODE_S  9
+/* DPORT_PRO_CMMU_SRAM_PAGE_MODE : R/W ;bitpos:[8:6] ;default: 3'd3 ; */
+/*description: */
+#define DPORT_PRO_CMMU_SRAM_PAGE_MODE  0x00000007
+#define DPORT_PRO_CMMU_SRAM_PAGE_MODE_M  ((DPORT_PRO_CMMU_SRAM_PAGE_MODE_V)<<(DPORT_PRO_CMMU_SRAM_PAGE_MODE_S))
+#define DPORT_PRO_CMMU_SRAM_PAGE_MODE_V  0x7
+#define DPORT_PRO_CMMU_SRAM_PAGE_MODE_S  6
+/* DPORT_PRO_CACHE_MASK_OPSDRAM : R/W ;bitpos:[5] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MASK_OPSDRAM  (BIT(5))
+#define DPORT_PRO_CACHE_MASK_OPSDRAM_M  (BIT(5))
+#define DPORT_PRO_CACHE_MASK_OPSDRAM_V  0x1
+#define DPORT_PRO_CACHE_MASK_OPSDRAM_S  5
+/* DPORT_PRO_CACHE_MASK_DROM0 : R/W ;bitpos:[4] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MASK_DROM0  (BIT(4))
+#define DPORT_PRO_CACHE_MASK_DROM0_M  (BIT(4))
+#define DPORT_PRO_CACHE_MASK_DROM0_V  0x1
+#define DPORT_PRO_CACHE_MASK_DROM0_S  4
+/* DPORT_PRO_CACHE_MASK_DRAM1 : R/W ;bitpos:[3] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MASK_DRAM1  (BIT(3))
+#define DPORT_PRO_CACHE_MASK_DRAM1_M  (BIT(3))
+#define DPORT_PRO_CACHE_MASK_DRAM1_V  0x1
+#define DPORT_PRO_CACHE_MASK_DRAM1_S  3
+/* DPORT_PRO_CACHE_MASK_IROM0 : R/W ;bitpos:[2] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MASK_IROM0  (BIT(2))
+#define DPORT_PRO_CACHE_MASK_IROM0_M  (BIT(2))
+#define DPORT_PRO_CACHE_MASK_IROM0_V  0x1
+#define DPORT_PRO_CACHE_MASK_IROM0_S  2
+/* DPORT_PRO_CACHE_MASK_IRAM1 : R/W ;bitpos:[1] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MASK_IRAM1  (BIT(1))
+#define DPORT_PRO_CACHE_MASK_IRAM1_M  (BIT(1))
+#define DPORT_PRO_CACHE_MASK_IRAM1_V  0x1
+#define DPORT_PRO_CACHE_MASK_IRAM1_S  1
+/* DPORT_PRO_CACHE_MASK_IRAM0 : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MASK_IRAM0  (BIT(0))
+#define DPORT_PRO_CACHE_MASK_IRAM0_M  (BIT(0))
+#define DPORT_PRO_CACHE_MASK_IRAM0_V  0x1
+#define DPORT_PRO_CACHE_MASK_IRAM0_S  0
+
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_REG          (DR_REG_DPORT_BASE + 0x048)
+/* DPORT_PRO_CACHE_LOCK_0_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MAX  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MAX_M  ((DPORT_PRO_CACHE_LOCK_0_ADDR_MAX_V)<<(DPORT_PRO_CACHE_LOCK_0_ADDR_MAX_S))
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MAX_V  0xF
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MAX_S  18
+/* DPORT_PRO_CACHE_LOCK_0_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MIN  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MIN_M  ((DPORT_PRO_CACHE_LOCK_0_ADDR_MIN_V)<<(DPORT_PRO_CACHE_LOCK_0_ADDR_MIN_S))
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MIN_V  0xF
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_MIN_S  14
+/* DPORT_PRO_CACHE_LOCK_0_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_PRE  0x00003FFF
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_PRE_M  ((DPORT_PRO_CACHE_LOCK_0_ADDR_PRE_V)<<(DPORT_PRO_CACHE_LOCK_0_ADDR_PRE_S))
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_PRE_V  0x3FFF
+#define DPORT_PRO_CACHE_LOCK_0_ADDR_PRE_S  0
+
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_REG          (DR_REG_DPORT_BASE + 0x04C)
+/* DPORT_PRO_CACHE_LOCK_1_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MAX  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MAX_M  ((DPORT_PRO_CACHE_LOCK_1_ADDR_MAX_V)<<(DPORT_PRO_CACHE_LOCK_1_ADDR_MAX_S))
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MAX_V  0xF
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MAX_S  18
+/* DPORT_PRO_CACHE_LOCK_1_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MIN  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MIN_M  ((DPORT_PRO_CACHE_LOCK_1_ADDR_MIN_V)<<(DPORT_PRO_CACHE_LOCK_1_ADDR_MIN_S))
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MIN_V  0xF
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_MIN_S  14
+/* DPORT_PRO_CACHE_LOCK_1_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_PRE  0x00003FFF
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_PRE_M  ((DPORT_PRO_CACHE_LOCK_1_ADDR_PRE_V)<<(DPORT_PRO_CACHE_LOCK_1_ADDR_PRE_S))
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_PRE_V  0x3FFF
+#define DPORT_PRO_CACHE_LOCK_1_ADDR_PRE_S  0
+
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_REG          (DR_REG_DPORT_BASE + 0x050)
+/* DPORT_PRO_CACHE_LOCK_2_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MAX  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MAX_M  ((DPORT_PRO_CACHE_LOCK_2_ADDR_MAX_V)<<(DPORT_PRO_CACHE_LOCK_2_ADDR_MAX_S))
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MAX_V  0xF
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MAX_S  18
+/* DPORT_PRO_CACHE_LOCK_2_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MIN  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MIN_M  ((DPORT_PRO_CACHE_LOCK_2_ADDR_MIN_V)<<(DPORT_PRO_CACHE_LOCK_2_ADDR_MIN_S))
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MIN_V  0xF
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_MIN_S  14
+/* DPORT_PRO_CACHE_LOCK_2_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_PRE  0x00003FFF
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_PRE_M  ((DPORT_PRO_CACHE_LOCK_2_ADDR_PRE_V)<<(DPORT_PRO_CACHE_LOCK_2_ADDR_PRE_S))
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_PRE_V  0x3FFF
+#define DPORT_PRO_CACHE_LOCK_2_ADDR_PRE_S  0
+
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_REG          (DR_REG_DPORT_BASE + 0x054)
+/* DPORT_PRO_CACHE_LOCK_3_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MAX  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MAX_M  ((DPORT_PRO_CACHE_LOCK_3_ADDR_MAX_V)<<(DPORT_PRO_CACHE_LOCK_3_ADDR_MAX_S))
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MAX_V  0xF
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MAX_S  18
+/* DPORT_PRO_CACHE_LOCK_3_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MIN  0x0000000F
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MIN_M  ((DPORT_PRO_CACHE_LOCK_3_ADDR_MIN_V)<<(DPORT_PRO_CACHE_LOCK_3_ADDR_MIN_S))
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MIN_V  0xF
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_MIN_S  14
+/* DPORT_PRO_CACHE_LOCK_3_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_PRE  0x00003FFF
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_PRE_M  ((DPORT_PRO_CACHE_LOCK_3_ADDR_PRE_V)<<(DPORT_PRO_CACHE_LOCK_3_ADDR_PRE_S))
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_PRE_V  0x3FFF
+#define DPORT_PRO_CACHE_LOCK_3_ADDR_PRE_S  0
+
+#define DPORT_APP_CACHE_CTRL_REG          (DR_REG_DPORT_BASE + 0x058)
+/* DPORT_APP_DRAM_HL : R/W ;bitpos:[14] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_DRAM_HL  (BIT(14))
+#define DPORT_APP_DRAM_HL_M  (BIT(14))
+#define DPORT_APP_DRAM_HL_V  0x1
+#define DPORT_APP_DRAM_HL_S  14
+/* DPORT_APP_SLAVE_REQ : RO ;bitpos:[13] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_SLAVE_REQ  (BIT(13))
+#define DPORT_APP_SLAVE_REQ_M  (BIT(13))
+#define DPORT_APP_SLAVE_REQ_V  0x1
+#define DPORT_APP_SLAVE_REQ_S  13
+/* DPORT_APP_AHB_SPI_REQ : RO ;bitpos:[12] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_AHB_SPI_REQ  (BIT(12))
+#define DPORT_APP_AHB_SPI_REQ_M  (BIT(12))
+#define DPORT_APP_AHB_SPI_REQ_V  0x1
+#define DPORT_APP_AHB_SPI_REQ_S  12
+/* DPORT_APP_DRAM_SPLIT : R/W ;bitpos:[11] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_DRAM_SPLIT  (BIT(11))
+#define DPORT_APP_DRAM_SPLIT_M  (BIT(11))
+#define DPORT_APP_DRAM_SPLIT_V  0x1
+#define DPORT_APP_DRAM_SPLIT_S  11
+/* DPORT_APP_SINGLE_IRAM_ENA : R/W ;bitpos:[10] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_SINGLE_IRAM_ENA  (BIT(10))
+#define DPORT_APP_SINGLE_IRAM_ENA_M  (BIT(10))
+#define DPORT_APP_SINGLE_IRAM_ENA_V  0x1
+#define DPORT_APP_SINGLE_IRAM_ENA_S  10
+/* DPORT_APP_CACHE_LOCK_3_EN : R/W ;bitpos:[9] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_3_EN  (BIT(9))
+#define DPORT_APP_CACHE_LOCK_3_EN_M  (BIT(9))
+#define DPORT_APP_CACHE_LOCK_3_EN_V  0x1
+#define DPORT_APP_CACHE_LOCK_3_EN_S  9
+/* DPORT_APP_CACHE_LOCK_2_EN : R/W ;bitpos:[8] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_2_EN  (BIT(8))
+#define DPORT_APP_CACHE_LOCK_2_EN_M  (BIT(8))
+#define DPORT_APP_CACHE_LOCK_2_EN_V  0x1
+#define DPORT_APP_CACHE_LOCK_2_EN_S  8
+/* DPORT_APP_CACHE_LOCK_1_EN : R/W ;bitpos:[7] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_1_EN  (BIT(7))
+#define DPORT_APP_CACHE_LOCK_1_EN_M  (BIT(7))
+#define DPORT_APP_CACHE_LOCK_1_EN_V  0x1
+#define DPORT_APP_CACHE_LOCK_1_EN_S  7
+/* DPORT_APP_CACHE_LOCK_0_EN : R/W ;bitpos:[6] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_0_EN  (BIT(6))
+#define DPORT_APP_CACHE_LOCK_0_EN_M  (BIT(6))
+#define DPORT_APP_CACHE_LOCK_0_EN_V  0x1
+#define DPORT_APP_CACHE_LOCK_0_EN_S  6
+/* DPORT_APP_CACHE_FLUSH_DONE : RO ;bitpos:[5] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_FLUSH_DONE  (BIT(5))
+#define DPORT_APP_CACHE_FLUSH_DONE_M  (BIT(5))
+#define DPORT_APP_CACHE_FLUSH_DONE_V  0x1
+#define DPORT_APP_CACHE_FLUSH_DONE_S  5
+/* DPORT_APP_CACHE_FLUSH_ENA : R/W ;bitpos:[4] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_FLUSH_ENA  (BIT(4))
+#define DPORT_APP_CACHE_FLUSH_ENA_M  (BIT(4))
+#define DPORT_APP_CACHE_FLUSH_ENA_V  0x1
+#define DPORT_APP_CACHE_FLUSH_ENA_S  4
+/* DPORT_APP_CACHE_ENABLE : R/W ;bitpos:[3] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_ENABLE  (BIT(3))
+#define DPORT_APP_CACHE_ENABLE_M  (BIT(3))
+#define DPORT_APP_CACHE_ENABLE_V  0x1
+#define DPORT_APP_CACHE_ENABLE_S  3
+/* DPORT_APP_CACHE_MODE : R/W ;bitpos:[2] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_MODE  (BIT(2))
+#define DPORT_APP_CACHE_MODE_M  (BIT(2))
+#define DPORT_APP_CACHE_MODE_V  0x1
+#define DPORT_APP_CACHE_MODE_S  2
+
+#define DPORT_APP_CACHE_CTRL1_REG          (DR_REG_DPORT_BASE + 0x05C)
+/* DPORT_APP_CACHE_MMU_IA_CLR : R/W ;bitpos:[13] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_MMU_IA_CLR  (BIT(13))
+#define DPORT_APP_CACHE_MMU_IA_CLR_M  (BIT(13))
+#define DPORT_APP_CACHE_MMU_IA_CLR_V  0x1
+#define DPORT_APP_CACHE_MMU_IA_CLR_S  13
+/* DPORT_APP_CMMU_PD : R/W ;bitpos:[12] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CMMU_PD  (BIT(12))
+#define DPORT_APP_CMMU_PD_M  (BIT(12))
+#define DPORT_APP_CMMU_PD_V  0x1
+#define DPORT_APP_CMMU_PD_S  12
+/* DPORT_APP_CMMU_FORCE_ON : R/W ;bitpos:[11] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CMMU_FORCE_ON  (BIT(11))
+#define DPORT_APP_CMMU_FORCE_ON_M  (BIT(11))
+#define DPORT_APP_CMMU_FORCE_ON_V  0x1
+#define DPORT_APP_CMMU_FORCE_ON_S  11
+/* DPORT_APP_CMMU_FLASH_PAGE_MODE : R/W ;bitpos:[10:9] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_APP_CMMU_FLASH_PAGE_MODE  0x00000003
+#define DPORT_APP_CMMU_FLASH_PAGE_MODE_M  ((DPORT_APP_CMMU_FLASH_PAGE_MODE_V)<<(DPORT_APP_CMMU_FLASH_PAGE_MODE_S))
+#define DPORT_APP_CMMU_FLASH_PAGE_MODE_V  0x3
+#define DPORT_APP_CMMU_FLASH_PAGE_MODE_S  9
+/* DPORT_APP_CMMU_SRAM_PAGE_MODE : R/W ;bitpos:[8:6] ;default: 3'd3 ; */
+/*description: */
+#define DPORT_APP_CMMU_SRAM_PAGE_MODE  0x00000007
+#define DPORT_APP_CMMU_SRAM_PAGE_MODE_M  ((DPORT_APP_CMMU_SRAM_PAGE_MODE_V)<<(DPORT_APP_CMMU_SRAM_PAGE_MODE_S))
+#define DPORT_APP_CMMU_SRAM_PAGE_MODE_V  0x7
+#define DPORT_APP_CMMU_SRAM_PAGE_MODE_S  6
+/* DPORT_APP_CACHE_MASK_OPSDRAM : R/W ;bitpos:[5] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_MASK_OPSDRAM  (BIT(5))
+#define DPORT_APP_CACHE_MASK_OPSDRAM_M  (BIT(5))
+#define DPORT_APP_CACHE_MASK_OPSDRAM_V  0x1
+#define DPORT_APP_CACHE_MASK_OPSDRAM_S  5
+/* DPORT_APP_CACHE_MASK_DROM0 : R/W ;bitpos:[4] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_MASK_DROM0  (BIT(4))
+#define DPORT_APP_CACHE_MASK_DROM0_M  (BIT(4))
+#define DPORT_APP_CACHE_MASK_DROM0_V  0x1
+#define DPORT_APP_CACHE_MASK_DROM0_S  4
+/* DPORT_APP_CACHE_MASK_DRAM1 : R/W ;bitpos:[3] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_MASK_DRAM1  (BIT(3))
+#define DPORT_APP_CACHE_MASK_DRAM1_M  (BIT(3))
+#define DPORT_APP_CACHE_MASK_DRAM1_V  0x1
+#define DPORT_APP_CACHE_MASK_DRAM1_S  3
+/* DPORT_APP_CACHE_MASK_IROM0 : R/W ;bitpos:[2] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_MASK_IROM0  (BIT(2))
+#define DPORT_APP_CACHE_MASK_IROM0_M  (BIT(2))
+#define DPORT_APP_CACHE_MASK_IROM0_V  0x1
+#define DPORT_APP_CACHE_MASK_IROM0_S  2
+/* DPORT_APP_CACHE_MASK_IRAM1 : R/W ;bitpos:[1] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_MASK_IRAM1  (BIT(1))
+#define DPORT_APP_CACHE_MASK_IRAM1_M  (BIT(1))
+#define DPORT_APP_CACHE_MASK_IRAM1_V  0x1
+#define DPORT_APP_CACHE_MASK_IRAM1_S  1
+/* DPORT_APP_CACHE_MASK_IRAM0 : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_MASK_IRAM0  (BIT(0))
+#define DPORT_APP_CACHE_MASK_IRAM0_M  (BIT(0))
+#define DPORT_APP_CACHE_MASK_IRAM0_V  0x1
+#define DPORT_APP_CACHE_MASK_IRAM0_S  0
+
+#define DPORT_APP_CACHE_LOCK_0_ADDR_REG          (DR_REG_DPORT_BASE + 0x060)
+/* DPORT_APP_CACHE_LOCK_0_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MAX  0x0000000F
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MAX_M  ((DPORT_APP_CACHE_LOCK_0_ADDR_MAX_V)<<(DPORT_APP_CACHE_LOCK_0_ADDR_MAX_S))
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MAX_V  0xF
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MAX_S  18
+/* DPORT_APP_CACHE_LOCK_0_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MIN  0x0000000F
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MIN_M  ((DPORT_APP_CACHE_LOCK_0_ADDR_MIN_V)<<(DPORT_APP_CACHE_LOCK_0_ADDR_MIN_S))
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MIN_V  0xF
+#define DPORT_APP_CACHE_LOCK_0_ADDR_MIN_S  14
+/* DPORT_APP_CACHE_LOCK_0_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_0_ADDR_PRE  0x00003FFF
+#define DPORT_APP_CACHE_LOCK_0_ADDR_PRE_M  ((DPORT_APP_CACHE_LOCK_0_ADDR_PRE_V)<<(DPORT_APP_CACHE_LOCK_0_ADDR_PRE_S))
+#define DPORT_APP_CACHE_LOCK_0_ADDR_PRE_V  0x3FFF
+#define DPORT_APP_CACHE_LOCK_0_ADDR_PRE_S  0
+
+#define DPORT_APP_CACHE_LOCK_1_ADDR_REG          (DR_REG_DPORT_BASE + 0x064)
+/* DPORT_APP_CACHE_LOCK_1_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MAX  0x0000000F
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MAX_M  ((DPORT_APP_CACHE_LOCK_1_ADDR_MAX_V)<<(DPORT_APP_CACHE_LOCK_1_ADDR_MAX_S))
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MAX_V  0xF
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MAX_S  18
+/* DPORT_APP_CACHE_LOCK_1_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MIN  0x0000000F
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MIN_M  ((DPORT_APP_CACHE_LOCK_1_ADDR_MIN_V)<<(DPORT_APP_CACHE_LOCK_1_ADDR_MIN_S))
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MIN_V  0xF
+#define DPORT_APP_CACHE_LOCK_1_ADDR_MIN_S  14
+/* DPORT_APP_CACHE_LOCK_1_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_1_ADDR_PRE  0x00003FFF
+#define DPORT_APP_CACHE_LOCK_1_ADDR_PRE_M  ((DPORT_APP_CACHE_LOCK_1_ADDR_PRE_V)<<(DPORT_APP_CACHE_LOCK_1_ADDR_PRE_S))
+#define DPORT_APP_CACHE_LOCK_1_ADDR_PRE_V  0x3FFF
+#define DPORT_APP_CACHE_LOCK_1_ADDR_PRE_S  0
+
+#define DPORT_APP_CACHE_LOCK_2_ADDR_REG          (DR_REG_DPORT_BASE + 0x068)
+/* DPORT_APP_CACHE_LOCK_2_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MAX  0x0000000F
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MAX_M  ((DPORT_APP_CACHE_LOCK_2_ADDR_MAX_V)<<(DPORT_APP_CACHE_LOCK_2_ADDR_MAX_S))
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MAX_V  0xF
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MAX_S  18
+/* DPORT_APP_CACHE_LOCK_2_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MIN  0x0000000F
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MIN_M  ((DPORT_APP_CACHE_LOCK_2_ADDR_MIN_V)<<(DPORT_APP_CACHE_LOCK_2_ADDR_MIN_S))
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MIN_V  0xF
+#define DPORT_APP_CACHE_LOCK_2_ADDR_MIN_S  14
+/* DPORT_APP_CACHE_LOCK_2_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_2_ADDR_PRE  0x00003FFF
+#define DPORT_APP_CACHE_LOCK_2_ADDR_PRE_M  ((DPORT_APP_CACHE_LOCK_2_ADDR_PRE_V)<<(DPORT_APP_CACHE_LOCK_2_ADDR_PRE_S))
+#define DPORT_APP_CACHE_LOCK_2_ADDR_PRE_V  0x3FFF
+#define DPORT_APP_CACHE_LOCK_2_ADDR_PRE_S  0
+
+#define DPORT_APP_CACHE_LOCK_3_ADDR_REG          (DR_REG_DPORT_BASE + 0x06C)
+/* DPORT_APP_CACHE_LOCK_3_ADDR_MAX : R/W ;bitpos:[21:18] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MAX  0x0000000F
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MAX_M  ((DPORT_APP_CACHE_LOCK_3_ADDR_MAX_V)<<(DPORT_APP_CACHE_LOCK_3_ADDR_MAX_S))
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MAX_V  0xF
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MAX_S  18
+/* DPORT_APP_CACHE_LOCK_3_ADDR_MIN : R/W ;bitpos:[17:14] ;default: 4'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MIN  0x0000000F
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MIN_M  ((DPORT_APP_CACHE_LOCK_3_ADDR_MIN_V)<<(DPORT_APP_CACHE_LOCK_3_ADDR_MIN_S))
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MIN_V  0xF
+#define DPORT_APP_CACHE_LOCK_3_ADDR_MIN_S  14
+/* DPORT_APP_CACHE_LOCK_3_ADDR_PRE : R/W ;bitpos:[13:0] ;default: 14'h0 ; */
+/*description: */
+#define DPORT_APP_CACHE_LOCK_3_ADDR_PRE  0x00003FFF
+#define DPORT_APP_CACHE_LOCK_3_ADDR_PRE_M  ((DPORT_APP_CACHE_LOCK_3_ADDR_PRE_V)<<(DPORT_APP_CACHE_LOCK_3_ADDR_PRE_S))
+#define DPORT_APP_CACHE_LOCK_3_ADDR_PRE_V  0x3FFF
+#define DPORT_APP_CACHE_LOCK_3_ADDR_PRE_S  0
+
+#define DPORT_TRACEMEM_MUX_MODE_REG          (DR_REG_DPORT_BASE + 0x070)
+/* DPORT_TRACEMEM_MUX_MODE : R/W ;bitpos:[1:0] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_TRACEMEM_MUX_MODE  0x00000003
+#define DPORT_TRACEMEM_MUX_MODE_M  ((DPORT_TRACEMEM_MUX_MODE_V)<<(DPORT_TRACEMEM_MUX_MODE_S))
+#define DPORT_TRACEMEM_MUX_MODE_V  0x3
+#define DPORT_TRACEMEM_MUX_MODE_S  0
+
+#define DPORT_PRO_TRACEMEM_ENA_REG          (DR_REG_DPORT_BASE + 0x074)
+/* DPORT_PRO_TRACEMEM_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_TRACEMEM_ENA  (BIT(0))
+#define DPORT_PRO_TRACEMEM_ENA_M  (BIT(0))
+#define DPORT_PRO_TRACEMEM_ENA_V  0x1
+#define DPORT_PRO_TRACEMEM_ENA_S  0
+
+#define DPORT_APP_TRACEMEM_ENA_REG          (DR_REG_DPORT_BASE + 0x078)
+/* DPORT_APP_TRACEMEM_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_TRACEMEM_ENA  (BIT(0))
+#define DPORT_APP_TRACEMEM_ENA_M  (BIT(0))
+#define DPORT_APP_TRACEMEM_ENA_V  0x1
+#define DPORT_APP_TRACEMEM_ENA_S  0
+
+#define DPORT_CACHE_MUX_MODE_REG          (DR_REG_DPORT_BASE + 0x07C)
+/* DPORT_CACHE_MUX_MODE : R/W ;bitpos:[1:0] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_CACHE_MUX_MODE  0x00000003
+#define DPORT_CACHE_MUX_MODE_M  ((DPORT_CACHE_MUX_MODE_V)<<(DPORT_CACHE_MUX_MODE_S))
+#define DPORT_CACHE_MUX_MODE_V  0x3
+#define DPORT_CACHE_MUX_MODE_S  0
+
+#define DPORT_IMMU_PAGE_MODE_REG          (DR_REG_DPORT_BASE + 0x080)
+/* DPORT_IMMU_PAGE_MODE : R/W ;bitpos:[2:1] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_IMMU_PAGE_MODE  0x00000003
+#define DPORT_IMMU_PAGE_MODE_M  ((DPORT_IMMU_PAGE_MODE_V)<<(DPORT_IMMU_PAGE_MODE_S))
+#define DPORT_IMMU_PAGE_MODE_V  0x3
+#define DPORT_IMMU_PAGE_MODE_S  1
+/* DPORT_INTERNAL_SRAM_IMMU_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_INTERNAL_SRAM_IMMU_ENA  (BIT(0))
+#define DPORT_INTERNAL_SRAM_IMMU_ENA_M  (BIT(0))
+#define DPORT_INTERNAL_SRAM_IMMU_ENA_V  0x1
+#define DPORT_INTERNAL_SRAM_IMMU_ENA_S  0
+
+#define DPORT_DMMU_PAGE_MODE_REG          (DR_REG_DPORT_BASE + 0x084)
+/* DPORT_DMMU_PAGE_MODE : R/W ;bitpos:[2:1] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_DMMU_PAGE_MODE  0x00000003
+#define DPORT_DMMU_PAGE_MODE_M  ((DPORT_DMMU_PAGE_MODE_V)<<(DPORT_DMMU_PAGE_MODE_S))
+#define DPORT_DMMU_PAGE_MODE_V  0x3
+#define DPORT_DMMU_PAGE_MODE_S  1
+/* DPORT_INTERNAL_SRAM_DMMU_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_INTERNAL_SRAM_DMMU_ENA  (BIT(0))
+#define DPORT_INTERNAL_SRAM_DMMU_ENA_M  (BIT(0))
+#define DPORT_INTERNAL_SRAM_DMMU_ENA_V  0x1
+#define DPORT_INTERNAL_SRAM_DMMU_ENA_S  0
+
+#define DPORT_ROM_MPU_ENA_REG          (DR_REG_DPORT_BASE + 0x088)
+/* DPORT_APP_ROM_MPU_ENA : R/W ;bitpos:[2] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_ROM_MPU_ENA  (BIT(2))
+#define DPORT_APP_ROM_MPU_ENA_M  (BIT(2))
+#define DPORT_APP_ROM_MPU_ENA_V  0x1
+#define DPORT_APP_ROM_MPU_ENA_S  2
+/* DPORT_PRO_ROM_MPU_ENA : R/W ;bitpos:[1] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_ROM_MPU_ENA  (BIT(1))
+#define DPORT_PRO_ROM_MPU_ENA_M  (BIT(1))
+#define DPORT_PRO_ROM_MPU_ENA_V  0x1
+#define DPORT_PRO_ROM_MPU_ENA_S  1
+/* DPORT_SHARE_ROM_MPU_ENA : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SHARE_ROM_MPU_ENA  (BIT(0))
+#define DPORT_SHARE_ROM_MPU_ENA_M  (BIT(0))
+#define DPORT_SHARE_ROM_MPU_ENA_V  0x1
+#define DPORT_SHARE_ROM_MPU_ENA_S  0
+
+#define DPORT_MEM_PD_MASK_REG          (DR_REG_DPORT_BASE + 0x08C)
+/* DPORT_LSLP_MEM_PD_MASK : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_LSLP_MEM_PD_MASK  (BIT(0))
+#define DPORT_LSLP_MEM_PD_MASK_M  (BIT(0))
+#define DPORT_LSLP_MEM_PD_MASK_V  0x1
+#define DPORT_LSLP_MEM_PD_MASK_S  0
+
+#define DPORT_ROM_PD_CTRL_REG          (DR_REG_DPORT_BASE + 0x090)
+/* DPORT_SHARE_ROM_PD : R/W ;bitpos:[7:2] ;default: 6'h0 ; */
+/*description: */
+#define DPORT_SHARE_ROM_PD  0x0000003F
+#define DPORT_SHARE_ROM_PD_M  ((DPORT_SHARE_ROM_PD_V)<<(DPORT_SHARE_ROM_PD_S))
+#define DPORT_SHARE_ROM_PD_V  0x3F
+#define DPORT_SHARE_ROM_PD_S  2
+/* DPORT_APP_ROM_PD : R/W ;bitpos:[1] ;default: 1'h0 ; */
+/*description: */
+#define DPORT_APP_ROM_PD  (BIT(1))
+#define DPORT_APP_ROM_PD_M  (BIT(1))
+#define DPORT_APP_ROM_PD_V  0x1
+#define DPORT_APP_ROM_PD_S  1
+/* DPORT_PRO_ROM_PD : R/W ;bitpos:[0] ;default: 1'h0 ; */
+/*description: */
+#define DPORT_PRO_ROM_PD  (BIT(0))
+#define DPORT_PRO_ROM_PD_M  (BIT(0))
+#define DPORT_PRO_ROM_PD_V  0x1
+#define DPORT_PRO_ROM_PD_S  0
+
+#define DPORT_ROM_FO_CTRL_REG          (DR_REG_DPORT_BASE + 0x094)
+/* DPORT_SHARE_ROM_FO : R/W ;bitpos:[7:2] ;default: 6'h0 ; */
+/*description: */
+#define DPORT_SHARE_ROM_FO  0x0000003F
+#define DPORT_SHARE_ROM_FO_M  ((DPORT_SHARE_ROM_FO_V)<<(DPORT_SHARE_ROM_FO_S))
+#define DPORT_SHARE_ROM_FO_V  0x3F
+#define DPORT_SHARE_ROM_FO_S  2
+/* DPORT_APP_ROM_FO : R/W ;bitpos:[1] ;default: 1'h1 ; */
+/*description: */
+#define DPORT_APP_ROM_FO  (BIT(1))
+#define DPORT_APP_ROM_FO_M  (BIT(1))
+#define DPORT_APP_ROM_FO_V  0x1
+#define DPORT_APP_ROM_FO_S  1
+/* DPORT_PRO_ROM_FO : R/W ;bitpos:[0] ;default: 1'h1 ; */
+/*description: */
+#define DPORT_PRO_ROM_FO  (BIT(0))
+#define DPORT_PRO_ROM_FO_M  (BIT(0))
+#define DPORT_PRO_ROM_FO_V  0x1
+#define DPORT_PRO_ROM_FO_S  0
+
+#define DPORT_SRAM_PD_CTRL_0_REG          (DR_REG_DPORT_BASE + 0x098)
+/* DPORT_SRAM_PD_0 : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_SRAM_PD_0  0xFFFFFFFF
+#define DPORT_SRAM_PD_0_M  ((DPORT_SRAM_PD_0_V)<<(DPORT_SRAM_PD_0_S))
+#define DPORT_SRAM_PD_0_V  0xFFFFFFFF
+#define DPORT_SRAM_PD_0_S  0
+
+#define DPORT_SRAM_PD_CTRL_1_REG          (DR_REG_DPORT_BASE + 0x09C)
+/* DPORT_SRAM_PD_1 : R/W ;bitpos:[0] ;default: 1'h0 ; */
+/*description: */
+#define DPORT_SRAM_PD_1  (BIT(0))
+#define DPORT_SRAM_PD_1_M  (BIT(0))
+#define DPORT_SRAM_PD_1_V  0x1
+#define DPORT_SRAM_PD_1_S  0
+
+#define DPORT_SRAM_FO_CTRL_0_REG          (DR_REG_DPORT_BASE + 0x0A0)
+/* DPORT_SRAM_FO_0 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */
+/*description: */
+#define DPORT_SRAM_FO_0  0xFFFFFFFF
+#define DPORT_SRAM_FO_0_M  ((DPORT_SRAM_FO_0_V)<<(DPORT_SRAM_FO_0_S))
+#define DPORT_SRAM_FO_0_V  0xFFFFFFFF
+#define DPORT_SRAM_FO_0_S  0
+
+#define DPORT_SRAM_FO_CTRL_1_REG          (DR_REG_DPORT_BASE + 0x0A4)
+/* DPORT_SRAM_FO_1 : R/W ;bitpos:[0] ;default: 1'h1 ; */
+/*description: */
+#define DPORT_SRAM_FO_1  (BIT(0))
+#define DPORT_SRAM_FO_1_M  (BIT(0))
+#define DPORT_SRAM_FO_1_V  0x1
+#define DPORT_SRAM_FO_1_S  0
+
+#define DPORT_IRAM_DRAM_AHB_SEL_REG          (DR_REG_DPORT_BASE + 0x0A8)
+/* DPORT_MAC_DUMP_MODE : R/W ;bitpos:[6:5] ;default: 2'h0 ; */
+/*description: */
+#define DPORT_MAC_DUMP_MODE  0x00000003
+#define DPORT_MAC_DUMP_MODE_M  ((DPORT_MAC_DUMP_MODE_V)<<(DPORT_MAC_DUMP_MODE_S))
+#define DPORT_MAC_DUMP_MODE_V  0x3
+#define DPORT_MAC_DUMP_MODE_S  5
+/* DPORT_MASK_AHB : R/W ;bitpos:[4] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_MASK_AHB  (BIT(4))
+#define DPORT_MASK_AHB_M  (BIT(4))
+#define DPORT_MASK_AHB_V  0x1
+#define DPORT_MASK_AHB_S  4
+/* DPORT_MASK_APP_DRAM : R/W ;bitpos:[3] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_MASK_APP_DRAM  (BIT(3))
+#define DPORT_MASK_APP_DRAM_M  (BIT(3))
+#define DPORT_MASK_APP_DRAM_V  0x1
+#define DPORT_MASK_APP_DRAM_S  3
+/* DPORT_MASK_PRO_DRAM : R/W ;bitpos:[2] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_MASK_PRO_DRAM  (BIT(2))
+#define DPORT_MASK_PRO_DRAM_M  (BIT(2))
+#define DPORT_MASK_PRO_DRAM_V  0x1
+#define DPORT_MASK_PRO_DRAM_S  2
+/* DPORT_MASK_APP_IRAM : R/W ;bitpos:[1] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_MASK_APP_IRAM  (BIT(1))
+#define DPORT_MASK_APP_IRAM_M  (BIT(1))
+#define DPORT_MASK_APP_IRAM_V  0x1
+#define DPORT_MASK_APP_IRAM_S  1
+/* DPORT_MASK_PRO_IRAM : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_MASK_PRO_IRAM  (BIT(0))
+#define DPORT_MASK_PRO_IRAM_M  (BIT(0))
+#define DPORT_MASK_PRO_IRAM_V  0x1
+#define DPORT_MASK_PRO_IRAM_S  0
+
+#define DPORT_TAG_FO_CTRL_REG          (DR_REG_DPORT_BASE + 0x0AC)
+/* DPORT_APP_CACHE_TAG_PD : R/W ;bitpos:[9] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_TAG_PD  (BIT(9))
+#define DPORT_APP_CACHE_TAG_PD_M  (BIT(9))
+#define DPORT_APP_CACHE_TAG_PD_V  0x1
+#define DPORT_APP_CACHE_TAG_PD_S  9
+/* DPORT_APP_CACHE_TAG_FORCE_ON : R/W ;bitpos:[8] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CACHE_TAG_FORCE_ON  (BIT(8))
+#define DPORT_APP_CACHE_TAG_FORCE_ON_M  (BIT(8))
+#define DPORT_APP_CACHE_TAG_FORCE_ON_V  0x1
+#define DPORT_APP_CACHE_TAG_FORCE_ON_S  8
+/* DPORT_PRO_CACHE_TAG_PD : R/W ;bitpos:[1] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_TAG_PD  (BIT(1))
+#define DPORT_PRO_CACHE_TAG_PD_M  (BIT(1))
+#define DPORT_PRO_CACHE_TAG_PD_V  0x1
+#define DPORT_PRO_CACHE_TAG_PD_S  1
+/* DPORT_PRO_CACHE_TAG_FORCE_ON : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CACHE_TAG_FORCE_ON  (BIT(0))
+#define DPORT_PRO_CACHE_TAG_FORCE_ON_M  (BIT(0))
+#define DPORT_PRO_CACHE_TAG_FORCE_ON_V  0x1
+#define DPORT_PRO_CACHE_TAG_FORCE_ON_S  0
+
+#define DPORT_AHB_LITE_MASK_REG          (DR_REG_DPORT_BASE + 0x0B0)
+/* DPORT_AHB_LITE_SDHOST_PID_REG : R/W ;bitpos:[13:11] ;default: 3'b0 ; */
+/*description: */
+#define DPORT_AHB_LITE_SDHOST_PID_REG  0x00000007
+#define DPORT_AHB_LITE_SDHOST_PID_REG_M  ((DPORT_AHB_LITE_SDHOST_PID_REG_V)<<(DPORT_AHB_LITE_SDHOST_PID_REG_S))
+#define DPORT_AHB_LITE_SDHOST_PID_REG_V  0x7
+#define DPORT_AHB_LITE_SDHOST_PID_REG_S  11
+/* DPORT_AHB_LITE_MASK_APPDPORT : R/W ;bitpos:[10] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_LITE_MASK_APPDPORT  (BIT(10))
+#define DPORT_AHB_LITE_MASK_APPDPORT_M  (BIT(10))
+#define DPORT_AHB_LITE_MASK_APPDPORT_V  0x1
+#define DPORT_AHB_LITE_MASK_APPDPORT_S  10
+/* DPORT_AHB_LITE_MASK_PRODPORT : R/W ;bitpos:[9] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_LITE_MASK_PRODPORT  (BIT(9))
+#define DPORT_AHB_LITE_MASK_PRODPORT_M  (BIT(9))
+#define DPORT_AHB_LITE_MASK_PRODPORT_V  0x1
+#define DPORT_AHB_LITE_MASK_PRODPORT_S  9
+/* DPORT_AHB_LITE_MASK_SDIO : R/W ;bitpos:[8] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_LITE_MASK_SDIO  (BIT(8))
+#define DPORT_AHB_LITE_MASK_SDIO_M  (BIT(8))
+#define DPORT_AHB_LITE_MASK_SDIO_V  0x1
+#define DPORT_AHB_LITE_MASK_SDIO_S  8
+/* DPORT_AHB_LITE_MASK_APP : R/W ;bitpos:[4] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_LITE_MASK_APP  (BIT(4))
+#define DPORT_AHB_LITE_MASK_APP_M  (BIT(4))
+#define DPORT_AHB_LITE_MASK_APP_V  0x1
+#define DPORT_AHB_LITE_MASK_APP_S  4
+/* DPORT_AHB_LITE_MASK_PRO : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_LITE_MASK_PRO  (BIT(0))
+#define DPORT_AHB_LITE_MASK_PRO_M  (BIT(0))
+#define DPORT_AHB_LITE_MASK_PRO_V  0x1
+#define DPORT_AHB_LITE_MASK_PRO_S  0
+
+#define DPORT_AHB_MPU_TABLE_0_REG          (DR_REG_DPORT_BASE + 0x0B4)
+/* DPORT_AHB_ACCESS_GRANT_0 : R/W ;bitpos:[31:0] ;default: 32'hffffffff ; */
+/*description: */
+#define DPORT_AHB_ACCESS_GRANT_0  0xFFFFFFFF
+#define DPORT_AHB_ACCESS_GRANT_0_M  ((DPORT_AHB_ACCESS_GRANT_0_V)<<(DPORT_AHB_ACCESS_GRANT_0_S))
+#define DPORT_AHB_ACCESS_GRANT_0_V  0xFFFFFFFF
+#define DPORT_AHB_ACCESS_GRANT_0_S  0
+
+#define DPORT_AHB_MPU_TABLE_1_REG          (DR_REG_DPORT_BASE + 0x0B8)
+/* DPORT_AHB_ACCESS_GRANT_1 : R/W ;bitpos:[8:0] ;default: 9'h1ff ; */
+/*description: */
+#define DPORT_AHB_ACCESS_GRANT_1  0x000001FF
+#define DPORT_AHB_ACCESS_GRANT_1_M  ((DPORT_AHB_ACCESS_GRANT_1_V)<<(DPORT_AHB_ACCESS_GRANT_1_S))
+#define DPORT_AHB_ACCESS_GRANT_1_V  0x1FF
+#define DPORT_AHB_ACCESS_GRANT_1_S  0
+
+#define DPORT_HOST_INF_SEL_REG          (DR_REG_DPORT_BASE + 0x0BC)
+/* DPORT_LINK_DEVICE_SEL : R/W ;bitpos:[15:8] ;default: 8'h0 ; */
+/*description: */
+#define DPORT_LINK_DEVICE_SEL  0x000000FF
+#define DPORT_LINK_DEVICE_SEL_M  ((DPORT_LINK_DEVICE_SEL_V)<<(DPORT_LINK_DEVICE_SEL_S))
+#define DPORT_LINK_DEVICE_SEL_V  0xFF
+#define DPORT_LINK_DEVICE_SEL_S  8
+/* DPORT_PERI_IO_SWAP : R/W ;bitpos:[7:0] ;default: 8'h0 ; */
+/*description: */
+#define DPORT_PERI_IO_SWAP  0x000000FF
+#define DPORT_PERI_IO_SWAP_M  ((DPORT_PERI_IO_SWAP_V)<<(DPORT_PERI_IO_SWAP_S))
+#define DPORT_PERI_IO_SWAP_V  0xFF
+#define DPORT_PERI_IO_SWAP_S  0
+
+#define DPORT_PERIP_CLK_EN_REG          (DR_REG_DPORT_BASE + 0x0C0)
+/* DPORT_PERIP_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hf9c1e06f ; */
+/*description: */
+#define DPORT_PERIP_CLK_EN  0xFFFFFFFF
+#define DPORT_PERIP_CLK_EN_M  ((DPORT_PERIP_CLK_EN_V)<<(DPORT_PERIP_CLK_EN_S))
+#define DPORT_PERIP_CLK_EN_V  0xFFFFFFFF
+#define DPORT_PERIP_CLK_EN_S  0
+
+#define DPORT_PWM3_CLK_EN (BIT(26))
+#define DPORT_PWM2_CLK_EN (BIT(25))
+#define DPORT_UART_MEM_CLK_EN   (BIT(24))
+#define DPORT_UART2_CLK_EN   (BIT(23))
+#define DPORT_SPI_DMA_CLK_EN   (BIT(22))
+#define DPORT_I2S1_CLK_EN   (BIT(21))
+#define DPORT_PWM1_CLK_EN   (BIT(20))
+#define DPORT_CAN_CLK_EN   (BIT(19))
+#define DPORT_I2C_EXT1_CLK_EN   (BIT(18))
+#define DPORT_PWM0_CLK_EN   (BIT(17))
+#define DPORT_SPI_CLK_EN_2   (BIT(16)) /** Deprecated, please use DPORT_SPI3_CLK_EN **/
+#define DPORT_SPI3_CLK_EN   (BIT(16))
+#define DPORT_TIMERGROUP1_CLK_EN   (BIT(15))
+#define DPORT_EFUSE_CLK_EN   (BIT(14))
+#define DPORT_TIMERGROUP_CLK_EN   (BIT(13))
+#define DPORT_UHCI1_CLK_EN   (BIT(12))
+#define DPORT_LEDC_CLK_EN   (BIT(11))
+#define DPORT_PCNT_CLK_EN   (BIT(10))
+#define DPORT_RMT_CLK_EN   (BIT(9))
+#define DPORT_UHCI0_CLK_EN   (BIT(8))
+#define DPORT_I2C_EXT0_CLK_EN   (BIT(7))
+#define DPORT_SPI_CLK_EN   (BIT(6)) /** Deprecated, please use DPORT_SPI2_CLK_EN **/
+#define DPORT_SPI2_CLK_EN   (BIT(6))
+#define DPORT_UART1_CLK_EN   (BIT(5))
+#define DPORT_I2S0_CLK_EN   (BIT(4))
+#define DPORT_WDG_CLK_EN   (BIT(3))
+#define DPORT_UART_CLK_EN   (BIT(2))
+#define DPORT_SPI_CLK_EN_1   (BIT(1)) /** Deprecated, please use DPORT_SPI01_CLK_EN **/
+#define DPORT_SPI01_CLK_EN   (BIT(1))
+#define DPORT_TIMERS_CLK_EN   (BIT(0))
+#define DPORT_PERIP_RST_EN_REG          (DR_REG_DPORT_BASE + 0x0C4)
+/* DPORT_PERIP_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PERIP_RST  0xFFFFFFFF
+#define DPORT_PERIP_RST_M  ((DPORT_PERIP_RST_V)<<(DPORT_PERIP_RST_S))
+#define DPORT_PERIP_RST_V  0xFFFFFFFF
+#define DPORT_PERIP_RST_S  0
+#define DPORT_PWM3_RST (BIT(26))
+#define DPORT_PWM2_RST (BIT(25))
+#define DPORT_UART_MEM_RST   (BIT(24))
+#define DPORT_UART2_RST   (BIT(23))
+#define DPORT_SPI_DMA_RST   (BIT(22))
+#define DPORT_I2S1_RST   (BIT(21))
+#define DPORT_PWM1_RST   (BIT(20))
+#define DPORT_CAN_RST   (BIT(19))
+#define DPORT_I2C_EXT1_RST   (BIT(18))
+#define DPORT_PWM0_RST   (BIT(17))
+#define DPORT_SPI_RST_2   (BIT(16)) /** Deprecated, please use DPORT_SPI3_RST **/
+#define DPORT_SPI3_RST   (BIT(16))
+#define DPORT_TIMERGROUP1_RST   (BIT(15))
+#define DPORT_EFUSE_RST   (BIT(14))
+#define DPORT_TIMERGROUP_RST   (BIT(13))
+#define DPORT_UHCI1_RST   (BIT(12))
+#define DPORT_LEDC_RST   (BIT(11))
+#define DPORT_PCNT_RST   (BIT(10))
+#define DPORT_RMT_RST   (BIT(9))
+#define DPORT_UHCI0_RST   (BIT(8))
+#define DPORT_I2C_EXT0_RST   (BIT(7))
+#define DPORT_SPI_RST   (BIT(6)) /** Deprecated, please use DPORT_SPI2_RST **/
+#define DPORT_SPI2_RST   (BIT(6))
+#define DPORT_UART1_RST   (BIT(5))
+#define DPORT_I2S0_RST   (BIT(4))
+#define DPORT_WDG_RST   (BIT(3))
+#define DPORT_UART_RST   (BIT(2))
+#define DPORT_SPI_RST_1   (BIT(1)) /** Deprecated, please use DPORT_SPI01_RST **/
+#define DPORT_SPI01_RST   (BIT(1))
+#define DPORT_TIMERS_RST   (BIT(0))
+#define DPORT_SLAVE_SPI_CONFIG_REG          (DR_REG_DPORT_BASE + 0x0C8)
+/* DPORT_SPI_DECRYPT_ENABLE : R/W ;bitpos:[12] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SPI_DECRYPT_ENABLE  (BIT(12))
+#define DPORT_SPI_DECRYPT_ENABLE_M  (BIT(12))
+#define DPORT_SPI_DECRYPT_ENABLE_V  0x1
+#define DPORT_SPI_DECRYPT_ENABLE_S  12
+/* DPORT_SPI_ENCRYPT_ENABLE : R/W ;bitpos:[8] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SPI_ENCRYPT_ENABLE  (BIT(8))
+#define DPORT_SPI_ENCRYPT_ENABLE_M  (BIT(8))
+#define DPORT_SPI_ENCRYPT_ENABLE_V  0x1
+#define DPORT_SPI_ENCRYPT_ENABLE_S  8
+/* DPORT_SLAVE_SPI_MASK_APP : R/W ;bitpos:[4] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SLAVE_SPI_MASK_APP  (BIT(4))
+#define DPORT_SLAVE_SPI_MASK_APP_M  (BIT(4))
+#define DPORT_SLAVE_SPI_MASK_APP_V  0x1
+#define DPORT_SLAVE_SPI_MASK_APP_S  4
+/* DPORT_SLAVE_SPI_MASK_PRO : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SLAVE_SPI_MASK_PRO  (BIT(0))
+#define DPORT_SLAVE_SPI_MASK_PRO_M  (BIT(0))
+#define DPORT_SLAVE_SPI_MASK_PRO_V  0x1
+#define DPORT_SLAVE_SPI_MASK_PRO_S  0
+
+#define DPORT_WIFI_CLK_EN_REG          (DR_REG_DPORT_BASE + 0x0CC)
+/* DPORT_WIFI_CLK_EN : R/W ;bitpos:[31:0] ;default: 32'hfffce030 ; */
+/*description: */
+#define DPORT_WIFI_CLK_EN  0xFFFFFFFF
+#define DPORT_WIFI_CLK_EN_M  ((DPORT_WIFI_CLK_EN_V)<<(DPORT_WIFI_CLK_EN_S))
+#define DPORT_WIFI_CLK_EN_V  0xFFFFFFFF
+#define DPORT_WIFI_CLK_EN_S  0
+
+/* Mask for all Wifi clock bits - 1, 2, 10 */
+#define DPORT_WIFI_CLK_WIFI_EN  0x00000406
+#define DPORT_WIFI_CLK_WIFI_EN_M  ((DPORT_WIFI_CLK_WIFI_EN_V)<<(DPORT_WIFI_CLK_WIFI_EN_S))
+#define DPORT_WIFI_CLK_WIFI_EN_V  0x406
+#define DPORT_WIFI_CLK_WIFI_EN_S  0
+/* Mask for all Bluetooth clock bits - 11, 16, 17 */
+#define DPORT_WIFI_CLK_BT_EN  0x61
+#define DPORT_WIFI_CLK_BT_EN_M  ((DPORT_WIFI_CLK_BT_EN_V)<<(DPORT_WIFI_CLK_BT_EN_S))
+#define DPORT_WIFI_CLK_BT_EN_V  0x61
+#define DPORT_WIFI_CLK_BT_EN_S  11
+/* Mask for clock bits used by both WIFI and Bluetooth, bit 0, 3, 6, 7, 8, 9 */
+#define DPORT_WIFI_CLK_WIFI_BT_COMMON_M 0x000003c9
+//bluetooth baseband bit11
+#define DPORT_BT_BASEBAND_EN  BIT(11)
+//bluetooth LC bit16 and bit17
+#define DPORT_BT_LC_EN  (BIT(16)|BIT(17))
+
+/* Remaining single bit clock masks */
+#define DPORT_WIFI_CLK_SDIOSLAVE_EN  BIT(4)
+#define DPORT_WIFI_CLK_UNUSED_BIT5  BIT(5)
+#define DPORT_WIFI_CLK_UNUSED_BIT12  BIT(12)
+#define DPORT_WIFI_CLK_SDIO_HOST_EN  BIT(13)
+#define DPORT_WIFI_CLK_EMAC_EN  BIT(14)
+#define DPORT_WIFI_CLK_RNG_EN  BIT(15)
+
+#define DPORT_CORE_RST_EN_REG          (DR_REG_DPORT_BASE + 0x0D0)
+/* DPORT_CORE_RST : R/W ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_RW_BTLP_RST (BIT(10))
+#define DPORT_RW_BTMAC_RST (BIT(9))
+#define DPORT_MACPWR_RST (BIT(8))
+#define DPORT_EMAC_RST (BIT(7))
+#define DPORT_SDIO_HOST_RST (BIT(6))
+#define DPORT_SDIO_RST (BIT(5))
+#define DPORT_BTMAC_RST (BIT(4))
+#define DPORT_BT_RST (BIT(3))
+#define DPORT_MAC_RST (BIT(2))
+#define DPORT_FE_RST (BIT(1))
+#define DPORT_BB_RST (BIT(0))
+
+#define DPORT_BT_LPCK_DIV_INT_REG          (DR_REG_DPORT_BASE + 0x0D4)
+/* DPORT_BTEXTWAKEUP_REQ : R/W ;bitpos:[12] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_BTEXTWAKEUP_REQ  (BIT(12))
+#define DPORT_BTEXTWAKEUP_REQ_M  (BIT(12))
+#define DPORT_BTEXTWAKEUP_REQ_V  0x1
+#define DPORT_BTEXTWAKEUP_REQ_S  12
+/* DPORT_BT_LPCK_DIV_NUM : R/W ;bitpos:[11:0] ;default: 12'd255 ; */
+/*description: */
+#define DPORT_BT_LPCK_DIV_NUM  0x00000FFF
+#define DPORT_BT_LPCK_DIV_NUM_M  ((DPORT_BT_LPCK_DIV_NUM_V)<<(DPORT_BT_LPCK_DIV_NUM_S))
+#define DPORT_BT_LPCK_DIV_NUM_V  0xFFF
+#define DPORT_BT_LPCK_DIV_NUM_S  0
+
+#define DPORT_BT_LPCK_DIV_FRAC_REG          (DR_REG_DPORT_BASE + 0x0D8)
+/* DPORT_LPCLK_SEL_XTAL32K : R/W ;bitpos:[27] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_LPCLK_SEL_XTAL32K  (BIT(27))
+#define DPORT_LPCLK_SEL_XTAL32K_M  (BIT(27))
+#define DPORT_LPCLK_SEL_XTAL32K_V  0x1
+#define DPORT_LPCLK_SEL_XTAL32K_S  27
+/* DPORT_LPCLK_SEL_XTAL : R/W ;bitpos:[26] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_LPCLK_SEL_XTAL  (BIT(26))
+#define DPORT_LPCLK_SEL_XTAL_M  (BIT(26))
+#define DPORT_LPCLK_SEL_XTAL_V  0x1
+#define DPORT_LPCLK_SEL_XTAL_S  26
+/* DPORT_LPCLK_SEL_8M : R/W ;bitpos:[25] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_LPCLK_SEL_8M  (BIT(25))
+#define DPORT_LPCLK_SEL_8M_M  (BIT(25))
+#define DPORT_LPCLK_SEL_8M_V  0x1
+#define DPORT_LPCLK_SEL_8M_S  25
+/* DPORT_LPCLK_SEL_RTC_SLOW : R/W ;bitpos:[24] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_LPCLK_SEL_RTC_SLOW  (BIT(24))
+#define DPORT_LPCLK_SEL_RTC_SLOW_M  (BIT(24))
+#define DPORT_LPCLK_SEL_RTC_SLOW_V  0x1
+#define DPORT_LPCLK_SEL_RTC_SLOW_S  24
+/* DPORT_BT_LPCK_DIV_A : R/W ;bitpos:[23:12] ;default: 12'd1 ; */
+/*description: */
+#define DPORT_BT_LPCK_DIV_A  0x00000FFF
+#define DPORT_BT_LPCK_DIV_A_M  ((DPORT_BT_LPCK_DIV_A_V)<<(DPORT_BT_LPCK_DIV_A_S))
+#define DPORT_BT_LPCK_DIV_A_V  0xFFF
+#define DPORT_BT_LPCK_DIV_A_S  12
+/* DPORT_BT_LPCK_DIV_B : R/W ;bitpos:[11:0] ;default: 12'd1 ; */
+/*description: */
+#define DPORT_BT_LPCK_DIV_B  0x00000FFF
+#define DPORT_BT_LPCK_DIV_B_M  ((DPORT_BT_LPCK_DIV_B_V)<<(DPORT_BT_LPCK_DIV_B_S))
+#define DPORT_BT_LPCK_DIV_B_V  0xFFF
+#define DPORT_BT_LPCK_DIV_B_S  0
+
+#define DPORT_CPU_INTR_FROM_CPU_0_REG          (DR_REG_DPORT_BASE + 0x0DC)
+/* DPORT_CPU_INTR_FROM_CPU_0 : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_CPU_INTR_FROM_CPU_0  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_0_M  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_0_V  0x1
+#define DPORT_CPU_INTR_FROM_CPU_0_S  0
+
+#define DPORT_CPU_INTR_FROM_CPU_1_REG          (DR_REG_DPORT_BASE + 0x0E0)
+/* DPORT_CPU_INTR_FROM_CPU_1 : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_CPU_INTR_FROM_CPU_1  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_1_M  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_1_V  0x1
+#define DPORT_CPU_INTR_FROM_CPU_1_S  0
+
+#define DPORT_CPU_INTR_FROM_CPU_2_REG          (DR_REG_DPORT_BASE + 0x0E4)
+/* DPORT_CPU_INTR_FROM_CPU_2 : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_CPU_INTR_FROM_CPU_2  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_2_M  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_2_V  0x1
+#define DPORT_CPU_INTR_FROM_CPU_2_S  0
+
+#define DPORT_CPU_INTR_FROM_CPU_3_REG          (DR_REG_DPORT_BASE + 0x0E8)
+/* DPORT_CPU_INTR_FROM_CPU_3 : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_CPU_INTR_FROM_CPU_3  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_3_M  (BIT(0))
+#define DPORT_CPU_INTR_FROM_CPU_3_V  0x1
+#define DPORT_CPU_INTR_FROM_CPU_3_S  0
+
+#define DPORT_PRO_INTR_STATUS_0_REG          (DR_REG_DPORT_BASE + 0x0EC)
+/* DPORT_PRO_INTR_STATUS_0 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PRO_INTR_STATUS_0  0xFFFFFFFF
+#define DPORT_PRO_INTR_STATUS_0_M  ((DPORT_PRO_INTR_STATUS_0_V)<<(DPORT_PRO_INTR_STATUS_0_S))
+#define DPORT_PRO_INTR_STATUS_0_V  0xFFFFFFFF
+#define DPORT_PRO_INTR_STATUS_0_S  0
+
+#define DPORT_PRO_INTR_STATUS_1_REG          (DR_REG_DPORT_BASE + 0x0F0)
+/* DPORT_PRO_INTR_STATUS_1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PRO_INTR_STATUS_1  0xFFFFFFFF
+#define DPORT_PRO_INTR_STATUS_1_M  ((DPORT_PRO_INTR_STATUS_1_V)<<(DPORT_PRO_INTR_STATUS_1_S))
+#define DPORT_PRO_INTR_STATUS_1_V  0xFFFFFFFF
+#define DPORT_PRO_INTR_STATUS_1_S  0
+
+#define DPORT_PRO_INTR_STATUS_2_REG          (DR_REG_DPORT_BASE + 0x0F4)
+/* DPORT_PRO_INTR_STATUS_2 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_PRO_INTR_STATUS_2  0xFFFFFFFF
+#define DPORT_PRO_INTR_STATUS_2_M  ((DPORT_PRO_INTR_STATUS_2_V)<<(DPORT_PRO_INTR_STATUS_2_S))
+#define DPORT_PRO_INTR_STATUS_2_V  0xFFFFFFFF
+#define DPORT_PRO_INTR_STATUS_2_S  0
+
+#define DPORT_APP_INTR_STATUS_0_REG          (DR_REG_DPORT_BASE + 0x0F8)
+/* DPORT_APP_INTR_STATUS_0 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_APP_INTR_STATUS_0  0xFFFFFFFF
+#define DPORT_APP_INTR_STATUS_0_M  ((DPORT_APP_INTR_STATUS_0_V)<<(DPORT_APP_INTR_STATUS_0_S))
+#define DPORT_APP_INTR_STATUS_0_V  0xFFFFFFFF
+#define DPORT_APP_INTR_STATUS_0_S  0
+
+#define DPORT_APP_INTR_STATUS_1_REG          (DR_REG_DPORT_BASE + 0x0FC)
+/* DPORT_APP_INTR_STATUS_1 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_APP_INTR_STATUS_1  0xFFFFFFFF
+#define DPORT_APP_INTR_STATUS_1_M  ((DPORT_APP_INTR_STATUS_1_V)<<(DPORT_APP_INTR_STATUS_1_S))
+#define DPORT_APP_INTR_STATUS_1_V  0xFFFFFFFF
+#define DPORT_APP_INTR_STATUS_1_S  0
+
+#define DPORT_APP_INTR_STATUS_2_REG          (DR_REG_DPORT_BASE + 0x100)
+/* DPORT_APP_INTR_STATUS_2 : RO ;bitpos:[31:0] ;default: 32'h0 ; */
+/*description: */
+#define DPORT_APP_INTR_STATUS_2  0xFFFFFFFF
+#define DPORT_APP_INTR_STATUS_2_M  ((DPORT_APP_INTR_STATUS_2_V)<<(DPORT_APP_INTR_STATUS_2_S))
+#define DPORT_APP_INTR_STATUS_2_V  0xFFFFFFFF
+#define DPORT_APP_INTR_STATUS_2_S  0
+
+#define DPORT_PRO_MAC_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x104)
+/* DPORT_PRO_MAC_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_MAC_INTR_MAP  0x0000001F
+#define DPORT_PRO_MAC_INTR_MAP_M  ((DPORT_PRO_MAC_INTR_MAP_V)<<(DPORT_PRO_MAC_INTR_MAP_S))
+#define DPORT_PRO_MAC_INTR_MAP_V  0x1F
+#define DPORT_PRO_MAC_INTR_MAP_S  0
+
+#define DPORT_PRO_MAC_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x108)
+/* DPORT_PRO_MAC_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_MAC_NMI_MAP  0x0000001F
+#define DPORT_PRO_MAC_NMI_MAP_M  ((DPORT_PRO_MAC_NMI_MAP_V)<<(DPORT_PRO_MAC_NMI_MAP_S))
+#define DPORT_PRO_MAC_NMI_MAP_V  0x1F
+#define DPORT_PRO_MAC_NMI_MAP_S  0
+
+#define DPORT_PRO_BB_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x10C)
+/* DPORT_PRO_BB_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_BB_INT_MAP  0x0000001F
+#define DPORT_PRO_BB_INT_MAP_M  ((DPORT_PRO_BB_INT_MAP_V)<<(DPORT_PRO_BB_INT_MAP_S))
+#define DPORT_PRO_BB_INT_MAP_V  0x1F
+#define DPORT_PRO_BB_INT_MAP_S  0
+
+#define DPORT_PRO_BT_MAC_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x110)
+/* DPORT_PRO_BT_MAC_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_BT_MAC_INT_MAP  0x0000001F
+#define DPORT_PRO_BT_MAC_INT_MAP_M  ((DPORT_PRO_BT_MAC_INT_MAP_V)<<(DPORT_PRO_BT_MAC_INT_MAP_S))
+#define DPORT_PRO_BT_MAC_INT_MAP_V  0x1F
+#define DPORT_PRO_BT_MAC_INT_MAP_S  0
+
+#define DPORT_PRO_BT_BB_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x114)
+/* DPORT_PRO_BT_BB_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_BT_BB_INT_MAP  0x0000001F
+#define DPORT_PRO_BT_BB_INT_MAP_M  ((DPORT_PRO_BT_BB_INT_MAP_V)<<(DPORT_PRO_BT_BB_INT_MAP_S))
+#define DPORT_PRO_BT_BB_INT_MAP_V  0x1F
+#define DPORT_PRO_BT_BB_INT_MAP_S  0
+
+#define DPORT_PRO_BT_BB_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x118)
+/* DPORT_PRO_BT_BB_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_BT_BB_NMI_MAP  0x0000001F
+#define DPORT_PRO_BT_BB_NMI_MAP_M  ((DPORT_PRO_BT_BB_NMI_MAP_V)<<(DPORT_PRO_BT_BB_NMI_MAP_S))
+#define DPORT_PRO_BT_BB_NMI_MAP_V  0x1F
+#define DPORT_PRO_BT_BB_NMI_MAP_S  0
+
+#define DPORT_PRO_RWBT_IRQ_MAP_REG          (DR_REG_DPORT_BASE + 0x11C)
+/* DPORT_PRO_RWBT_IRQ_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RWBT_IRQ_MAP  0x0000001F
+#define DPORT_PRO_RWBT_IRQ_MAP_M  ((DPORT_PRO_RWBT_IRQ_MAP_V)<<(DPORT_PRO_RWBT_IRQ_MAP_S))
+#define DPORT_PRO_RWBT_IRQ_MAP_V  0x1F
+#define DPORT_PRO_RWBT_IRQ_MAP_S  0
+
+#define DPORT_PRO_RWBLE_IRQ_MAP_REG          (DR_REG_DPORT_BASE + 0x120)
+/* DPORT_PRO_RWBLE_IRQ_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RWBLE_IRQ_MAP  0x0000001F
+#define DPORT_PRO_RWBLE_IRQ_MAP_M  ((DPORT_PRO_RWBLE_IRQ_MAP_V)<<(DPORT_PRO_RWBLE_IRQ_MAP_S))
+#define DPORT_PRO_RWBLE_IRQ_MAP_V  0x1F
+#define DPORT_PRO_RWBLE_IRQ_MAP_S  0
+
+#define DPORT_PRO_RWBT_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x124)
+/* DPORT_PRO_RWBT_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RWBT_NMI_MAP  0x0000001F
+#define DPORT_PRO_RWBT_NMI_MAP_M  ((DPORT_PRO_RWBT_NMI_MAP_V)<<(DPORT_PRO_RWBT_NMI_MAP_S))
+#define DPORT_PRO_RWBT_NMI_MAP_V  0x1F
+#define DPORT_PRO_RWBT_NMI_MAP_S  0
+
+#define DPORT_PRO_RWBLE_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x128)
+/* DPORT_PRO_RWBLE_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RWBLE_NMI_MAP  0x0000001F
+#define DPORT_PRO_RWBLE_NMI_MAP_M  ((DPORT_PRO_RWBLE_NMI_MAP_V)<<(DPORT_PRO_RWBLE_NMI_MAP_S))
+#define DPORT_PRO_RWBLE_NMI_MAP_V  0x1F
+#define DPORT_PRO_RWBLE_NMI_MAP_S  0
+
+#define DPORT_PRO_SLC0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x12C)
+/* DPORT_PRO_SLC0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SLC0_INTR_MAP  0x0000001F
+#define DPORT_PRO_SLC0_INTR_MAP_M  ((DPORT_PRO_SLC0_INTR_MAP_V)<<(DPORT_PRO_SLC0_INTR_MAP_S))
+#define DPORT_PRO_SLC0_INTR_MAP_V  0x1F
+#define DPORT_PRO_SLC0_INTR_MAP_S  0
+
+#define DPORT_PRO_SLC1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x130)
+/* DPORT_PRO_SLC1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SLC1_INTR_MAP  0x0000001F
+#define DPORT_PRO_SLC1_INTR_MAP_M  ((DPORT_PRO_SLC1_INTR_MAP_V)<<(DPORT_PRO_SLC1_INTR_MAP_S))
+#define DPORT_PRO_SLC1_INTR_MAP_V  0x1F
+#define DPORT_PRO_SLC1_INTR_MAP_S  0
+
+#define DPORT_PRO_UHCI0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x134)
+/* DPORT_PRO_UHCI0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_UHCI0_INTR_MAP  0x0000001F
+#define DPORT_PRO_UHCI0_INTR_MAP_M  ((DPORT_PRO_UHCI0_INTR_MAP_V)<<(DPORT_PRO_UHCI0_INTR_MAP_S))
+#define DPORT_PRO_UHCI0_INTR_MAP_V  0x1F
+#define DPORT_PRO_UHCI0_INTR_MAP_S  0
+
+#define DPORT_PRO_UHCI1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x138)
+/* DPORT_PRO_UHCI1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_UHCI1_INTR_MAP  0x0000001F
+#define DPORT_PRO_UHCI1_INTR_MAP_M  ((DPORT_PRO_UHCI1_INTR_MAP_V)<<(DPORT_PRO_UHCI1_INTR_MAP_S))
+#define DPORT_PRO_UHCI1_INTR_MAP_V  0x1F
+#define DPORT_PRO_UHCI1_INTR_MAP_S  0
+
+#define DPORT_PRO_TG_T0_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x13C)
+/* DPORT_PRO_TG_T0_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_T0_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_T0_LEVEL_INT_MAP_M  ((DPORT_PRO_TG_T0_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG_T0_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG_T0_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_T0_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG_T1_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x140)
+/* DPORT_PRO_TG_T1_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_T1_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_T1_LEVEL_INT_MAP_M  ((DPORT_PRO_TG_T1_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG_T1_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG_T1_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_T1_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x144)
+/* DPORT_PRO_TG_WDT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP_M  ((DPORT_PRO_TG_WDT_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG_WDT_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_WDT_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x148)
+/* DPORT_PRO_TG_LACT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP_M  ((DPORT_PRO_TG_LACT_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG_LACT_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_LACT_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x14C)
+/* DPORT_PRO_TG1_T0_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP_M  ((DPORT_PRO_TG1_T0_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG1_T0_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_T0_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x150)
+/* DPORT_PRO_TG1_T1_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP_M  ((DPORT_PRO_TG1_T1_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG1_T1_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_T1_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x154)
+/* DPORT_PRO_TG1_WDT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_M  ((DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_WDT_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x158)
+/* DPORT_PRO_TG1_LACT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_M  ((DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_V)<<(DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_S))
+#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_LACT_LEVEL_INT_MAP_S  0
+
+#define DPORT_PRO_GPIO_INTERRUPT_MAP_REG          (DR_REG_DPORT_BASE + 0x15C)
+/* DPORT_PRO_GPIO_INTERRUPT_PRO_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_MAP  0x0000001F
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_MAP_M  ((DPORT_PRO_GPIO_INTERRUPT_PRO_MAP_V)<<(DPORT_PRO_GPIO_INTERRUPT_PRO_MAP_S))
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_MAP_V  0x1F
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_MAP_S  0
+
+#define DPORT_PRO_GPIO_INTERRUPT_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x160)
+/* DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP  0x0000001F
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP_M  ((DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP_V)<<(DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP_S))
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP_V  0x1F
+#define DPORT_PRO_GPIO_INTERRUPT_PRO_NMI_MAP_S  0
+
+#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_REG          (DR_REG_DPORT_BASE + 0x164)
+/* DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP  0x0000001F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_M  ((DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_V)<<(DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_S))
+#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_V  0x1F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_0_MAP_S  0
+
+#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_REG          (DR_REG_DPORT_BASE + 0x168)
+/* DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP  0x0000001F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_M  ((DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_V)<<(DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_S))
+#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_V  0x1F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_1_MAP_S  0
+
+#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_REG          (DR_REG_DPORT_BASE + 0x16C)
+/* DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP  0x0000001F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_M  ((DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_V)<<(DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_S))
+#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_V  0x1F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_2_MAP_S  0
+
+#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_REG          (DR_REG_DPORT_BASE + 0x170)
+/* DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP  0x0000001F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_M  ((DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_V)<<(DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_S))
+#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_V  0x1F
+#define DPORT_PRO_CPU_INTR_FROM_CPU_3_MAP_S  0
+
+#define DPORT_PRO_SPI_INTR_0_MAP_REG          (DR_REG_DPORT_BASE + 0x174)
+/* DPORT_PRO_SPI_INTR_0_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI_INTR_0_MAP  0x0000001F
+#define DPORT_PRO_SPI_INTR_0_MAP_M  ((DPORT_PRO_SPI_INTR_0_MAP_V)<<(DPORT_PRO_SPI_INTR_0_MAP_S))
+#define DPORT_PRO_SPI_INTR_0_MAP_V  0x1F
+#define DPORT_PRO_SPI_INTR_0_MAP_S  0
+
+#define DPORT_PRO_SPI_INTR_1_MAP_REG          (DR_REG_DPORT_BASE + 0x178)
+/* DPORT_PRO_SPI_INTR_1_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI_INTR_1_MAP  0x0000001F
+#define DPORT_PRO_SPI_INTR_1_MAP_M  ((DPORT_PRO_SPI_INTR_1_MAP_V)<<(DPORT_PRO_SPI_INTR_1_MAP_S))
+#define DPORT_PRO_SPI_INTR_1_MAP_V  0x1F
+#define DPORT_PRO_SPI_INTR_1_MAP_S  0
+
+#define DPORT_PRO_SPI_INTR_2_MAP_REG          (DR_REG_DPORT_BASE + 0x17C)
+/* DPORT_PRO_SPI_INTR_2_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI_INTR_2_MAP  0x0000001F
+#define DPORT_PRO_SPI_INTR_2_MAP_M  ((DPORT_PRO_SPI_INTR_2_MAP_V)<<(DPORT_PRO_SPI_INTR_2_MAP_S))
+#define DPORT_PRO_SPI_INTR_2_MAP_V  0x1F
+#define DPORT_PRO_SPI_INTR_2_MAP_S  0
+
+#define DPORT_PRO_SPI_INTR_3_MAP_REG          (DR_REG_DPORT_BASE + 0x180)
+/* DPORT_PRO_SPI_INTR_3_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI_INTR_3_MAP  0x0000001F
+#define DPORT_PRO_SPI_INTR_3_MAP_M  ((DPORT_PRO_SPI_INTR_3_MAP_V)<<(DPORT_PRO_SPI_INTR_3_MAP_S))
+#define DPORT_PRO_SPI_INTR_3_MAP_V  0x1F
+#define DPORT_PRO_SPI_INTR_3_MAP_S  0
+
+#define DPORT_PRO_I2S0_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x184)
+/* DPORT_PRO_I2S0_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_I2S0_INT_MAP  0x0000001F
+#define DPORT_PRO_I2S0_INT_MAP_M  ((DPORT_PRO_I2S0_INT_MAP_V)<<(DPORT_PRO_I2S0_INT_MAP_S))
+#define DPORT_PRO_I2S0_INT_MAP_V  0x1F
+#define DPORT_PRO_I2S0_INT_MAP_S  0
+
+#define DPORT_PRO_I2S1_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x188)
+/* DPORT_PRO_I2S1_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_I2S1_INT_MAP  0x0000001F
+#define DPORT_PRO_I2S1_INT_MAP_M  ((DPORT_PRO_I2S1_INT_MAP_V)<<(DPORT_PRO_I2S1_INT_MAP_S))
+#define DPORT_PRO_I2S1_INT_MAP_V  0x1F
+#define DPORT_PRO_I2S1_INT_MAP_S  0
+
+#define DPORT_PRO_UART_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x18C)
+/* DPORT_PRO_UART_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_UART_INTR_MAP  0x0000001F
+#define DPORT_PRO_UART_INTR_MAP_M  ((DPORT_PRO_UART_INTR_MAP_V)<<(DPORT_PRO_UART_INTR_MAP_S))
+#define DPORT_PRO_UART_INTR_MAP_V  0x1F
+#define DPORT_PRO_UART_INTR_MAP_S  0
+
+#define DPORT_PRO_UART1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x190)
+/* DPORT_PRO_UART1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_UART1_INTR_MAP  0x0000001F
+#define DPORT_PRO_UART1_INTR_MAP_M  ((DPORT_PRO_UART1_INTR_MAP_V)<<(DPORT_PRO_UART1_INTR_MAP_S))
+#define DPORT_PRO_UART1_INTR_MAP_V  0x1F
+#define DPORT_PRO_UART1_INTR_MAP_S  0
+
+#define DPORT_PRO_UART2_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x194)
+/* DPORT_PRO_UART2_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_UART2_INTR_MAP  0x0000001F
+#define DPORT_PRO_UART2_INTR_MAP_M  ((DPORT_PRO_UART2_INTR_MAP_V)<<(DPORT_PRO_UART2_INTR_MAP_S))
+#define DPORT_PRO_UART2_INTR_MAP_V  0x1F
+#define DPORT_PRO_UART2_INTR_MAP_S  0
+
+#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_REG          (DR_REG_DPORT_BASE + 0x198)
+/* DPORT_PRO_SDIO_HOST_INTERRUPT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP  0x0000001F
+#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_M  ((DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_V)<<(DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_S))
+#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_V  0x1F
+#define DPORT_PRO_SDIO_HOST_INTERRUPT_MAP_S  0
+
+#define DPORT_PRO_EMAC_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x19C)
+/* DPORT_PRO_EMAC_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_EMAC_INT_MAP  0x0000001F
+#define DPORT_PRO_EMAC_INT_MAP_M  ((DPORT_PRO_EMAC_INT_MAP_V)<<(DPORT_PRO_EMAC_INT_MAP_S))
+#define DPORT_PRO_EMAC_INT_MAP_V  0x1F
+#define DPORT_PRO_EMAC_INT_MAP_S  0
+
+#define DPORT_PRO_PWM0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1A0)
+/* DPORT_PRO_PWM0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_PWM0_INTR_MAP  0x0000001F
+#define DPORT_PRO_PWM0_INTR_MAP_M  ((DPORT_PRO_PWM0_INTR_MAP_V)<<(DPORT_PRO_PWM0_INTR_MAP_S))
+#define DPORT_PRO_PWM0_INTR_MAP_V  0x1F
+#define DPORT_PRO_PWM0_INTR_MAP_S  0
+
+#define DPORT_PRO_PWM1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1A4)
+/* DPORT_PRO_PWM1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_PWM1_INTR_MAP  0x0000001F
+#define DPORT_PRO_PWM1_INTR_MAP_M  ((DPORT_PRO_PWM1_INTR_MAP_V)<<(DPORT_PRO_PWM1_INTR_MAP_S))
+#define DPORT_PRO_PWM1_INTR_MAP_V  0x1F
+#define DPORT_PRO_PWM1_INTR_MAP_S  0
+
+#define DPORT_PRO_PWM2_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1A8)
+/* DPORT_PRO_PWM2_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_PWM2_INTR_MAP  0x0000001F
+#define DPORT_PRO_PWM2_INTR_MAP_M  ((DPORT_PRO_PWM2_INTR_MAP_V)<<(DPORT_PRO_PWM2_INTR_MAP_S))
+#define DPORT_PRO_PWM2_INTR_MAP_V  0x1F
+#define DPORT_PRO_PWM2_INTR_MAP_S  0
+
+#define DPORT_PRO_PWM3_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1AC)
+/* DPORT_PRO_PWM3_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_PWM3_INTR_MAP  0x0000001F
+#define DPORT_PRO_PWM3_INTR_MAP_M  ((DPORT_PRO_PWM3_INTR_MAP_V)<<(DPORT_PRO_PWM3_INTR_MAP_S))
+#define DPORT_PRO_PWM3_INTR_MAP_V  0x1F
+#define DPORT_PRO_PWM3_INTR_MAP_S  0
+
+#define DPORT_PRO_LEDC_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1B0)
+/* DPORT_PRO_LEDC_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_LEDC_INT_MAP  0x0000001F
+#define DPORT_PRO_LEDC_INT_MAP_M  ((DPORT_PRO_LEDC_INT_MAP_V)<<(DPORT_PRO_LEDC_INT_MAP_S))
+#define DPORT_PRO_LEDC_INT_MAP_V  0x1F
+#define DPORT_PRO_LEDC_INT_MAP_S  0
+
+#define DPORT_PRO_EFUSE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1B4)
+/* DPORT_PRO_EFUSE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_EFUSE_INT_MAP  0x0000001F
+#define DPORT_PRO_EFUSE_INT_MAP_M  ((DPORT_PRO_EFUSE_INT_MAP_V)<<(DPORT_PRO_EFUSE_INT_MAP_S))
+#define DPORT_PRO_EFUSE_INT_MAP_V  0x1F
+#define DPORT_PRO_EFUSE_INT_MAP_S  0
+
+#define DPORT_PRO_CAN_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1B8)
+/* DPORT_PRO_CAN_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_CAN_INT_MAP  0x0000001F
+#define DPORT_PRO_CAN_INT_MAP_M  ((DPORT_PRO_CAN_INT_MAP_V)<<(DPORT_PRO_CAN_INT_MAP_S))
+#define DPORT_PRO_CAN_INT_MAP_V  0x1F
+#define DPORT_PRO_CAN_INT_MAP_S  0
+
+#define DPORT_PRO_RTC_CORE_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1BC)
+/* DPORT_PRO_RTC_CORE_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RTC_CORE_INTR_MAP  0x0000001F
+#define DPORT_PRO_RTC_CORE_INTR_MAP_M  ((DPORT_PRO_RTC_CORE_INTR_MAP_V)<<(DPORT_PRO_RTC_CORE_INTR_MAP_S))
+#define DPORT_PRO_RTC_CORE_INTR_MAP_V  0x1F
+#define DPORT_PRO_RTC_CORE_INTR_MAP_S  0
+
+#define DPORT_PRO_RMT_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1C0)
+/* DPORT_PRO_RMT_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RMT_INTR_MAP  0x0000001F
+#define DPORT_PRO_RMT_INTR_MAP_M  ((DPORT_PRO_RMT_INTR_MAP_V)<<(DPORT_PRO_RMT_INTR_MAP_S))
+#define DPORT_PRO_RMT_INTR_MAP_V  0x1F
+#define DPORT_PRO_RMT_INTR_MAP_S  0
+
+#define DPORT_PRO_PCNT_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1C4)
+/* DPORT_PRO_PCNT_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_PCNT_INTR_MAP  0x0000001F
+#define DPORT_PRO_PCNT_INTR_MAP_M  ((DPORT_PRO_PCNT_INTR_MAP_V)<<(DPORT_PRO_PCNT_INTR_MAP_S))
+#define DPORT_PRO_PCNT_INTR_MAP_V  0x1F
+#define DPORT_PRO_PCNT_INTR_MAP_S  0
+
+#define DPORT_PRO_I2C_EXT0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1C8)
+/* DPORT_PRO_I2C_EXT0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_I2C_EXT0_INTR_MAP  0x0000001F
+#define DPORT_PRO_I2C_EXT0_INTR_MAP_M  ((DPORT_PRO_I2C_EXT0_INTR_MAP_V)<<(DPORT_PRO_I2C_EXT0_INTR_MAP_S))
+#define DPORT_PRO_I2C_EXT0_INTR_MAP_V  0x1F
+#define DPORT_PRO_I2C_EXT0_INTR_MAP_S  0
+
+#define DPORT_PRO_I2C_EXT1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1CC)
+/* DPORT_PRO_I2C_EXT1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_I2C_EXT1_INTR_MAP  0x0000001F
+#define DPORT_PRO_I2C_EXT1_INTR_MAP_M  ((DPORT_PRO_I2C_EXT1_INTR_MAP_V)<<(DPORT_PRO_I2C_EXT1_INTR_MAP_S))
+#define DPORT_PRO_I2C_EXT1_INTR_MAP_V  0x1F
+#define DPORT_PRO_I2C_EXT1_INTR_MAP_S  0
+
+#define DPORT_PRO_RSA_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x1D0)
+/* DPORT_PRO_RSA_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_RSA_INTR_MAP  0x0000001F
+#define DPORT_PRO_RSA_INTR_MAP_M  ((DPORT_PRO_RSA_INTR_MAP_V)<<(DPORT_PRO_RSA_INTR_MAP_S))
+#define DPORT_PRO_RSA_INTR_MAP_V  0x1F
+#define DPORT_PRO_RSA_INTR_MAP_S  0
+
+#define DPORT_PRO_SPI1_DMA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1D4)
+/* DPORT_PRO_SPI1_DMA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI1_DMA_INT_MAP  0x0000001F
+#define DPORT_PRO_SPI1_DMA_INT_MAP_M  ((DPORT_PRO_SPI1_DMA_INT_MAP_V)<<(DPORT_PRO_SPI1_DMA_INT_MAP_S))
+#define DPORT_PRO_SPI1_DMA_INT_MAP_V  0x1F
+#define DPORT_PRO_SPI1_DMA_INT_MAP_S  0
+
+#define DPORT_PRO_SPI2_DMA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1D8)
+/* DPORT_PRO_SPI2_DMA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI2_DMA_INT_MAP  0x0000001F
+#define DPORT_PRO_SPI2_DMA_INT_MAP_M  ((DPORT_PRO_SPI2_DMA_INT_MAP_V)<<(DPORT_PRO_SPI2_DMA_INT_MAP_S))
+#define DPORT_PRO_SPI2_DMA_INT_MAP_V  0x1F
+#define DPORT_PRO_SPI2_DMA_INT_MAP_S  0
+
+#define DPORT_PRO_SPI3_DMA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1DC)
+/* DPORT_PRO_SPI3_DMA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_SPI3_DMA_INT_MAP  0x0000001F
+#define DPORT_PRO_SPI3_DMA_INT_MAP_M  ((DPORT_PRO_SPI3_DMA_INT_MAP_V)<<(DPORT_PRO_SPI3_DMA_INT_MAP_S))
+#define DPORT_PRO_SPI3_DMA_INT_MAP_V  0x1F
+#define DPORT_PRO_SPI3_DMA_INT_MAP_S  0
+
+#define DPORT_PRO_WDG_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1E0)
+/* DPORT_PRO_WDG_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_WDG_INT_MAP  0x0000001F
+#define DPORT_PRO_WDG_INT_MAP_M  ((DPORT_PRO_WDG_INT_MAP_V)<<(DPORT_PRO_WDG_INT_MAP_S))
+#define DPORT_PRO_WDG_INT_MAP_V  0x1F
+#define DPORT_PRO_WDG_INT_MAP_S  0
+
+#define DPORT_PRO_TIMER_INT1_MAP_REG          (DR_REG_DPORT_BASE + 0x1E4)
+/* DPORT_PRO_TIMER_INT1_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TIMER_INT1_MAP  0x0000001F
+#define DPORT_PRO_TIMER_INT1_MAP_M  ((DPORT_PRO_TIMER_INT1_MAP_V)<<(DPORT_PRO_TIMER_INT1_MAP_S))
+#define DPORT_PRO_TIMER_INT1_MAP_V  0x1F
+#define DPORT_PRO_TIMER_INT1_MAP_S  0
+
+#define DPORT_PRO_TIMER_INT2_MAP_REG          (DR_REG_DPORT_BASE + 0x1E8)
+/* DPORT_PRO_TIMER_INT2_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TIMER_INT2_MAP  0x0000001F
+#define DPORT_PRO_TIMER_INT2_MAP_M  ((DPORT_PRO_TIMER_INT2_MAP_V)<<(DPORT_PRO_TIMER_INT2_MAP_S))
+#define DPORT_PRO_TIMER_INT2_MAP_V  0x1F
+#define DPORT_PRO_TIMER_INT2_MAP_S  0
+
+#define DPORT_PRO_TG_T0_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1EC)
+/* DPORT_PRO_TG_T0_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_T0_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_T0_EDGE_INT_MAP_M  ((DPORT_PRO_TG_T0_EDGE_INT_MAP_V)<<(DPORT_PRO_TG_T0_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG_T0_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_T0_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG_T1_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1F0)
+/* DPORT_PRO_TG_T1_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_T1_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_T1_EDGE_INT_MAP_M  ((DPORT_PRO_TG_T1_EDGE_INT_MAP_V)<<(DPORT_PRO_TG_T1_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG_T1_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_T1_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG_WDT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1F4)
+/* DPORT_PRO_TG_WDT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_WDT_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_WDT_EDGE_INT_MAP_M  ((DPORT_PRO_TG_WDT_EDGE_INT_MAP_V)<<(DPORT_PRO_TG_WDT_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG_WDT_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_WDT_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG_LACT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1F8)
+/* DPORT_PRO_TG_LACT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG_LACT_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG_LACT_EDGE_INT_MAP_M  ((DPORT_PRO_TG_LACT_EDGE_INT_MAP_V)<<(DPORT_PRO_TG_LACT_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG_LACT_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG_LACT_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_T0_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x1FC)
+/* DPORT_PRO_TG1_T0_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_T0_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_T0_EDGE_INT_MAP_M  ((DPORT_PRO_TG1_T0_EDGE_INT_MAP_V)<<(DPORT_PRO_TG1_T0_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG1_T0_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_T0_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_T1_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x200)
+/* DPORT_PRO_TG1_T1_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_T1_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_T1_EDGE_INT_MAP_M  ((DPORT_PRO_TG1_T1_EDGE_INT_MAP_V)<<(DPORT_PRO_TG1_T1_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG1_T1_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_T1_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x204)
+/* DPORT_PRO_TG1_WDT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP_M  ((DPORT_PRO_TG1_WDT_EDGE_INT_MAP_V)<<(DPORT_PRO_TG1_WDT_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_WDT_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x208)
+/* DPORT_PRO_TG1_LACT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP  0x0000001F
+#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP_M  ((DPORT_PRO_TG1_LACT_EDGE_INT_MAP_V)<<(DPORT_PRO_TG1_LACT_EDGE_INT_MAP_S))
+#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP_V  0x1F
+#define DPORT_PRO_TG1_LACT_EDGE_INT_MAP_S  0
+
+#define DPORT_PRO_MMU_IA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x20C)
+/* DPORT_PRO_MMU_IA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_MMU_IA_INT_MAP  0x0000001F
+#define DPORT_PRO_MMU_IA_INT_MAP_M  ((DPORT_PRO_MMU_IA_INT_MAP_V)<<(DPORT_PRO_MMU_IA_INT_MAP_S))
+#define DPORT_PRO_MMU_IA_INT_MAP_V  0x1F
+#define DPORT_PRO_MMU_IA_INT_MAP_S  0
+
+#define DPORT_PRO_MPU_IA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x210)
+/* DPORT_PRO_MPU_IA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_MPU_IA_INT_MAP  0x0000001F
+#define DPORT_PRO_MPU_IA_INT_MAP_M  ((DPORT_PRO_MPU_IA_INT_MAP_V)<<(DPORT_PRO_MPU_IA_INT_MAP_S))
+#define DPORT_PRO_MPU_IA_INT_MAP_V  0x1F
+#define DPORT_PRO_MPU_IA_INT_MAP_S  0
+
+#define DPORT_PRO_CACHE_IA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x214)
+/* DPORT_PRO_CACHE_IA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_PRO_CACHE_IA_INT_MAP  0x0000001F
+#define DPORT_PRO_CACHE_IA_INT_MAP_M  ((DPORT_PRO_CACHE_IA_INT_MAP_V)<<(DPORT_PRO_CACHE_IA_INT_MAP_S))
+#define DPORT_PRO_CACHE_IA_INT_MAP_V  0x1F
+#define DPORT_PRO_CACHE_IA_INT_MAP_S  0
+
+#define DPORT_APP_MAC_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x218)
+/* DPORT_APP_MAC_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_MAC_INTR_MAP  0x0000001F
+#define DPORT_APP_MAC_INTR_MAP_M  ((DPORT_APP_MAC_INTR_MAP_V)<<(DPORT_APP_MAC_INTR_MAP_S))
+#define DPORT_APP_MAC_INTR_MAP_V  0x1F
+#define DPORT_APP_MAC_INTR_MAP_S  0
+
+#define DPORT_APP_MAC_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x21C)
+/* DPORT_APP_MAC_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_MAC_NMI_MAP  0x0000001F
+#define DPORT_APP_MAC_NMI_MAP_M  ((DPORT_APP_MAC_NMI_MAP_V)<<(DPORT_APP_MAC_NMI_MAP_S))
+#define DPORT_APP_MAC_NMI_MAP_V  0x1F
+#define DPORT_APP_MAC_NMI_MAP_S  0
+
+#define DPORT_APP_BB_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x220)
+/* DPORT_APP_BB_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_BB_INT_MAP  0x0000001F
+#define DPORT_APP_BB_INT_MAP_M  ((DPORT_APP_BB_INT_MAP_V)<<(DPORT_APP_BB_INT_MAP_S))
+#define DPORT_APP_BB_INT_MAP_V  0x1F
+#define DPORT_APP_BB_INT_MAP_S  0
+
+#define DPORT_APP_BT_MAC_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x224)
+/* DPORT_APP_BT_MAC_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_BT_MAC_INT_MAP  0x0000001F
+#define DPORT_APP_BT_MAC_INT_MAP_M  ((DPORT_APP_BT_MAC_INT_MAP_V)<<(DPORT_APP_BT_MAC_INT_MAP_S))
+#define DPORT_APP_BT_MAC_INT_MAP_V  0x1F
+#define DPORT_APP_BT_MAC_INT_MAP_S  0
+
+#define DPORT_APP_BT_BB_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x228)
+/* DPORT_APP_BT_BB_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_BT_BB_INT_MAP  0x0000001F
+#define DPORT_APP_BT_BB_INT_MAP_M  ((DPORT_APP_BT_BB_INT_MAP_V)<<(DPORT_APP_BT_BB_INT_MAP_S))
+#define DPORT_APP_BT_BB_INT_MAP_V  0x1F
+#define DPORT_APP_BT_BB_INT_MAP_S  0
+
+#define DPORT_APP_BT_BB_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x22C)
+/* DPORT_APP_BT_BB_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_BT_BB_NMI_MAP  0x0000001F
+#define DPORT_APP_BT_BB_NMI_MAP_M  ((DPORT_APP_BT_BB_NMI_MAP_V)<<(DPORT_APP_BT_BB_NMI_MAP_S))
+#define DPORT_APP_BT_BB_NMI_MAP_V  0x1F
+#define DPORT_APP_BT_BB_NMI_MAP_S  0
+
+#define DPORT_APP_RWBT_IRQ_MAP_REG          (DR_REG_DPORT_BASE + 0x230)
+/* DPORT_APP_RWBT_IRQ_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RWBT_IRQ_MAP  0x0000001F
+#define DPORT_APP_RWBT_IRQ_MAP_M  ((DPORT_APP_RWBT_IRQ_MAP_V)<<(DPORT_APP_RWBT_IRQ_MAP_S))
+#define DPORT_APP_RWBT_IRQ_MAP_V  0x1F
+#define DPORT_APP_RWBT_IRQ_MAP_S  0
+
+#define DPORT_APP_RWBLE_IRQ_MAP_REG          (DR_REG_DPORT_BASE + 0x234)
+/* DPORT_APP_RWBLE_IRQ_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RWBLE_IRQ_MAP  0x0000001F
+#define DPORT_APP_RWBLE_IRQ_MAP_M  ((DPORT_APP_RWBLE_IRQ_MAP_V)<<(DPORT_APP_RWBLE_IRQ_MAP_S))
+#define DPORT_APP_RWBLE_IRQ_MAP_V  0x1F
+#define DPORT_APP_RWBLE_IRQ_MAP_S  0
+
+#define DPORT_APP_RWBT_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x238)
+/* DPORT_APP_RWBT_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RWBT_NMI_MAP  0x0000001F
+#define DPORT_APP_RWBT_NMI_MAP_M  ((DPORT_APP_RWBT_NMI_MAP_V)<<(DPORT_APP_RWBT_NMI_MAP_S))
+#define DPORT_APP_RWBT_NMI_MAP_V  0x1F
+#define DPORT_APP_RWBT_NMI_MAP_S  0
+
+#define DPORT_APP_RWBLE_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x23C)
+/* DPORT_APP_RWBLE_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RWBLE_NMI_MAP  0x0000001F
+#define DPORT_APP_RWBLE_NMI_MAP_M  ((DPORT_APP_RWBLE_NMI_MAP_V)<<(DPORT_APP_RWBLE_NMI_MAP_S))
+#define DPORT_APP_RWBLE_NMI_MAP_V  0x1F
+#define DPORT_APP_RWBLE_NMI_MAP_S  0
+
+#define DPORT_APP_SLC0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x240)
+/* DPORT_APP_SLC0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SLC0_INTR_MAP  0x0000001F
+#define DPORT_APP_SLC0_INTR_MAP_M  ((DPORT_APP_SLC0_INTR_MAP_V)<<(DPORT_APP_SLC0_INTR_MAP_S))
+#define DPORT_APP_SLC0_INTR_MAP_V  0x1F
+#define DPORT_APP_SLC0_INTR_MAP_S  0
+
+#define DPORT_APP_SLC1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x244)
+/* DPORT_APP_SLC1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SLC1_INTR_MAP  0x0000001F
+#define DPORT_APP_SLC1_INTR_MAP_M  ((DPORT_APP_SLC1_INTR_MAP_V)<<(DPORT_APP_SLC1_INTR_MAP_S))
+#define DPORT_APP_SLC1_INTR_MAP_V  0x1F
+#define DPORT_APP_SLC1_INTR_MAP_S  0
+
+#define DPORT_APP_UHCI0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x248)
+/* DPORT_APP_UHCI0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_UHCI0_INTR_MAP  0x0000001F
+#define DPORT_APP_UHCI0_INTR_MAP_M  ((DPORT_APP_UHCI0_INTR_MAP_V)<<(DPORT_APP_UHCI0_INTR_MAP_S))
+#define DPORT_APP_UHCI0_INTR_MAP_V  0x1F
+#define DPORT_APP_UHCI0_INTR_MAP_S  0
+
+#define DPORT_APP_UHCI1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x24C)
+/* DPORT_APP_UHCI1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_UHCI1_INTR_MAP  0x0000001F
+#define DPORT_APP_UHCI1_INTR_MAP_M  ((DPORT_APP_UHCI1_INTR_MAP_V)<<(DPORT_APP_UHCI1_INTR_MAP_S))
+#define DPORT_APP_UHCI1_INTR_MAP_V  0x1F
+#define DPORT_APP_UHCI1_INTR_MAP_S  0
+
+#define DPORT_APP_TG_T0_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x250)
+/* DPORT_APP_TG_T0_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_T0_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG_T0_LEVEL_INT_MAP_M  ((DPORT_APP_TG_T0_LEVEL_INT_MAP_V)<<(DPORT_APP_TG_T0_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG_T0_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG_T0_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG_T1_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x254)
+/* DPORT_APP_TG_T1_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_T1_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG_T1_LEVEL_INT_MAP_M  ((DPORT_APP_TG_T1_LEVEL_INT_MAP_V)<<(DPORT_APP_TG_T1_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG_T1_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG_T1_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG_WDT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x258)
+/* DPORT_APP_TG_WDT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_WDT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG_WDT_LEVEL_INT_MAP_M  ((DPORT_APP_TG_WDT_LEVEL_INT_MAP_V)<<(DPORT_APP_TG_WDT_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG_WDT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG_WDT_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG_LACT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x25C)
+/* DPORT_APP_TG_LACT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_LACT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG_LACT_LEVEL_INT_MAP_M  ((DPORT_APP_TG_LACT_LEVEL_INT_MAP_V)<<(DPORT_APP_TG_LACT_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG_LACT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG_LACT_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG1_T0_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x260)
+/* DPORT_APP_TG1_T0_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_T0_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_T0_LEVEL_INT_MAP_M  ((DPORT_APP_TG1_T0_LEVEL_INT_MAP_V)<<(DPORT_APP_TG1_T0_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG1_T0_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_T0_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG1_T1_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x264)
+/* DPORT_APP_TG1_T1_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_T1_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_T1_LEVEL_INT_MAP_M  ((DPORT_APP_TG1_T1_LEVEL_INT_MAP_V)<<(DPORT_APP_TG1_T1_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG1_T1_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_T1_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x268)
+/* DPORT_APP_TG1_WDT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP_M  ((DPORT_APP_TG1_WDT_LEVEL_INT_MAP_V)<<(DPORT_APP_TG1_WDT_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_WDT_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x26C)
+/* DPORT_APP_TG1_LACT_LEVEL_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP_M  ((DPORT_APP_TG1_LACT_LEVEL_INT_MAP_V)<<(DPORT_APP_TG1_LACT_LEVEL_INT_MAP_S))
+#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_LACT_LEVEL_INT_MAP_S  0
+
+#define DPORT_APP_GPIO_INTERRUPT_MAP_REG          (DR_REG_DPORT_BASE + 0x270)
+/* DPORT_APP_GPIO_INTERRUPT_APP_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_GPIO_INTERRUPT_APP_MAP  0x0000001F
+#define DPORT_APP_GPIO_INTERRUPT_APP_MAP_M  ((DPORT_APP_GPIO_INTERRUPT_APP_MAP_V)<<(DPORT_APP_GPIO_INTERRUPT_APP_MAP_S))
+#define DPORT_APP_GPIO_INTERRUPT_APP_MAP_V  0x1F
+#define DPORT_APP_GPIO_INTERRUPT_APP_MAP_S  0
+
+#define DPORT_APP_GPIO_INTERRUPT_NMI_MAP_REG          (DR_REG_DPORT_BASE + 0x274)
+/* DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP  0x0000001F
+#define DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP_M  ((DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP_V)<<(DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP_S))
+#define DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP_V  0x1F
+#define DPORT_APP_GPIO_INTERRUPT_APP_NMI_MAP_S  0
+
+#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_REG          (DR_REG_DPORT_BASE + 0x278)
+/* DPORT_APP_CPU_INTR_FROM_CPU_0_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP  0x0000001F
+#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_M  ((DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_V)<<(DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_S))
+#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_V  0x1F
+#define DPORT_APP_CPU_INTR_FROM_CPU_0_MAP_S  0
+
+#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_REG          (DR_REG_DPORT_BASE + 0x27C)
+/* DPORT_APP_CPU_INTR_FROM_CPU_1_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP  0x0000001F
+#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_M  ((DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_V)<<(DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_S))
+#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_V  0x1F
+#define DPORT_APP_CPU_INTR_FROM_CPU_1_MAP_S  0
+
+#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_REG          (DR_REG_DPORT_BASE + 0x280)
+/* DPORT_APP_CPU_INTR_FROM_CPU_2_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP  0x0000001F
+#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_M  ((DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_V)<<(DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_S))
+#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_V  0x1F
+#define DPORT_APP_CPU_INTR_FROM_CPU_2_MAP_S  0
+
+#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_REG          (DR_REG_DPORT_BASE + 0x284)
+/* DPORT_APP_CPU_INTR_FROM_CPU_3_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP  0x0000001F
+#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_M  ((DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_V)<<(DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_S))
+#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_V  0x1F
+#define DPORT_APP_CPU_INTR_FROM_CPU_3_MAP_S  0
+
+#define DPORT_APP_SPI_INTR_0_MAP_REG          (DR_REG_DPORT_BASE + 0x288)
+/* DPORT_APP_SPI_INTR_0_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI_INTR_0_MAP  0x0000001F
+#define DPORT_APP_SPI_INTR_0_MAP_M  ((DPORT_APP_SPI_INTR_0_MAP_V)<<(DPORT_APP_SPI_INTR_0_MAP_S))
+#define DPORT_APP_SPI_INTR_0_MAP_V  0x1F
+#define DPORT_APP_SPI_INTR_0_MAP_S  0
+
+#define DPORT_APP_SPI_INTR_1_MAP_REG          (DR_REG_DPORT_BASE + 0x28C)
+/* DPORT_APP_SPI_INTR_1_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI_INTR_1_MAP  0x0000001F
+#define DPORT_APP_SPI_INTR_1_MAP_M  ((DPORT_APP_SPI_INTR_1_MAP_V)<<(DPORT_APP_SPI_INTR_1_MAP_S))
+#define DPORT_APP_SPI_INTR_1_MAP_V  0x1F
+#define DPORT_APP_SPI_INTR_1_MAP_S  0
+
+#define DPORT_APP_SPI_INTR_2_MAP_REG          (DR_REG_DPORT_BASE + 0x290)
+/* DPORT_APP_SPI_INTR_2_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI_INTR_2_MAP  0x0000001F
+#define DPORT_APP_SPI_INTR_2_MAP_M  ((DPORT_APP_SPI_INTR_2_MAP_V)<<(DPORT_APP_SPI_INTR_2_MAP_S))
+#define DPORT_APP_SPI_INTR_2_MAP_V  0x1F
+#define DPORT_APP_SPI_INTR_2_MAP_S  0
+
+#define DPORT_APP_SPI_INTR_3_MAP_REG          (DR_REG_DPORT_BASE + 0x294)
+/* DPORT_APP_SPI_INTR_3_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI_INTR_3_MAP  0x0000001F
+#define DPORT_APP_SPI_INTR_3_MAP_M  ((DPORT_APP_SPI_INTR_3_MAP_V)<<(DPORT_APP_SPI_INTR_3_MAP_S))
+#define DPORT_APP_SPI_INTR_3_MAP_V  0x1F
+#define DPORT_APP_SPI_INTR_3_MAP_S  0
+
+#define DPORT_APP_I2S0_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x298)
+/* DPORT_APP_I2S0_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_I2S0_INT_MAP  0x0000001F
+#define DPORT_APP_I2S0_INT_MAP_M  ((DPORT_APP_I2S0_INT_MAP_V)<<(DPORT_APP_I2S0_INT_MAP_S))
+#define DPORT_APP_I2S0_INT_MAP_V  0x1F
+#define DPORT_APP_I2S0_INT_MAP_S  0
+
+#define DPORT_APP_I2S1_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x29C)
+/* DPORT_APP_I2S1_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_I2S1_INT_MAP  0x0000001F
+#define DPORT_APP_I2S1_INT_MAP_M  ((DPORT_APP_I2S1_INT_MAP_V)<<(DPORT_APP_I2S1_INT_MAP_S))
+#define DPORT_APP_I2S1_INT_MAP_V  0x1F
+#define DPORT_APP_I2S1_INT_MAP_S  0
+
+#define DPORT_APP_UART_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2A0)
+/* DPORT_APP_UART_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_UART_INTR_MAP  0x0000001F
+#define DPORT_APP_UART_INTR_MAP_M  ((DPORT_APP_UART_INTR_MAP_V)<<(DPORT_APP_UART_INTR_MAP_S))
+#define DPORT_APP_UART_INTR_MAP_V  0x1F
+#define DPORT_APP_UART_INTR_MAP_S  0
+
+#define DPORT_APP_UART1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2A4)
+/* DPORT_APP_UART1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_UART1_INTR_MAP  0x0000001F
+#define DPORT_APP_UART1_INTR_MAP_M  ((DPORT_APP_UART1_INTR_MAP_V)<<(DPORT_APP_UART1_INTR_MAP_S))
+#define DPORT_APP_UART1_INTR_MAP_V  0x1F
+#define DPORT_APP_UART1_INTR_MAP_S  0
+
+#define DPORT_APP_UART2_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2A8)
+/* DPORT_APP_UART2_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_UART2_INTR_MAP  0x0000001F
+#define DPORT_APP_UART2_INTR_MAP_M  ((DPORT_APP_UART2_INTR_MAP_V)<<(DPORT_APP_UART2_INTR_MAP_S))
+#define DPORT_APP_UART2_INTR_MAP_V  0x1F
+#define DPORT_APP_UART2_INTR_MAP_S  0
+
+#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP_REG          (DR_REG_DPORT_BASE + 0x2AC)
+/* DPORT_APP_SDIO_HOST_INTERRUPT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP  0x0000001F
+#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP_M  ((DPORT_APP_SDIO_HOST_INTERRUPT_MAP_V)<<(DPORT_APP_SDIO_HOST_INTERRUPT_MAP_S))
+#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP_V  0x1F
+#define DPORT_APP_SDIO_HOST_INTERRUPT_MAP_S  0
+
+#define DPORT_APP_EMAC_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2B0)
+/* DPORT_APP_EMAC_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_EMAC_INT_MAP  0x0000001F
+#define DPORT_APP_EMAC_INT_MAP_M  ((DPORT_APP_EMAC_INT_MAP_V)<<(DPORT_APP_EMAC_INT_MAP_S))
+#define DPORT_APP_EMAC_INT_MAP_V  0x1F
+#define DPORT_APP_EMAC_INT_MAP_S  0
+
+#define DPORT_APP_PWM0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2B4)
+/* DPORT_APP_PWM0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_PWM0_INTR_MAP  0x0000001F
+#define DPORT_APP_PWM0_INTR_MAP_M  ((DPORT_APP_PWM0_INTR_MAP_V)<<(DPORT_APP_PWM0_INTR_MAP_S))
+#define DPORT_APP_PWM0_INTR_MAP_V  0x1F
+#define DPORT_APP_PWM0_INTR_MAP_S  0
+
+#define DPORT_APP_PWM1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2B8)
+/* DPORT_APP_PWM1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_PWM1_INTR_MAP  0x0000001F
+#define DPORT_APP_PWM1_INTR_MAP_M  ((DPORT_APP_PWM1_INTR_MAP_V)<<(DPORT_APP_PWM1_INTR_MAP_S))
+#define DPORT_APP_PWM1_INTR_MAP_V  0x1F
+#define DPORT_APP_PWM1_INTR_MAP_S  0
+
+#define DPORT_APP_PWM2_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2BC)
+/* DPORT_APP_PWM2_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_PWM2_INTR_MAP  0x0000001F
+#define DPORT_APP_PWM2_INTR_MAP_M  ((DPORT_APP_PWM2_INTR_MAP_V)<<(DPORT_APP_PWM2_INTR_MAP_S))
+#define DPORT_APP_PWM2_INTR_MAP_V  0x1F
+#define DPORT_APP_PWM2_INTR_MAP_S  0
+
+#define DPORT_APP_PWM3_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2C0)
+/* DPORT_APP_PWM3_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_PWM3_INTR_MAP  0x0000001F
+#define DPORT_APP_PWM3_INTR_MAP_M  ((DPORT_APP_PWM3_INTR_MAP_V)<<(DPORT_APP_PWM3_INTR_MAP_S))
+#define DPORT_APP_PWM3_INTR_MAP_V  0x1F
+#define DPORT_APP_PWM3_INTR_MAP_S  0
+
+#define DPORT_APP_LEDC_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2C4)
+/* DPORT_APP_LEDC_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_LEDC_INT_MAP  0x0000001F
+#define DPORT_APP_LEDC_INT_MAP_M  ((DPORT_APP_LEDC_INT_MAP_V)<<(DPORT_APP_LEDC_INT_MAP_S))
+#define DPORT_APP_LEDC_INT_MAP_V  0x1F
+#define DPORT_APP_LEDC_INT_MAP_S  0
+
+#define DPORT_APP_EFUSE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2C8)
+/* DPORT_APP_EFUSE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_EFUSE_INT_MAP  0x0000001F
+#define DPORT_APP_EFUSE_INT_MAP_M  ((DPORT_APP_EFUSE_INT_MAP_V)<<(DPORT_APP_EFUSE_INT_MAP_S))
+#define DPORT_APP_EFUSE_INT_MAP_V  0x1F
+#define DPORT_APP_EFUSE_INT_MAP_S  0
+
+#define DPORT_APP_CAN_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2CC)
+/* DPORT_APP_CAN_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_CAN_INT_MAP  0x0000001F
+#define DPORT_APP_CAN_INT_MAP_M  ((DPORT_APP_CAN_INT_MAP_V)<<(DPORT_APP_CAN_INT_MAP_S))
+#define DPORT_APP_CAN_INT_MAP_V  0x1F
+#define DPORT_APP_CAN_INT_MAP_S  0
+
+#define DPORT_APP_RTC_CORE_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2D0)
+/* DPORT_APP_RTC_CORE_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RTC_CORE_INTR_MAP  0x0000001F
+#define DPORT_APP_RTC_CORE_INTR_MAP_M  ((DPORT_APP_RTC_CORE_INTR_MAP_V)<<(DPORT_APP_RTC_CORE_INTR_MAP_S))
+#define DPORT_APP_RTC_CORE_INTR_MAP_V  0x1F
+#define DPORT_APP_RTC_CORE_INTR_MAP_S  0
+
+#define DPORT_APP_RMT_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2D4)
+/* DPORT_APP_RMT_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RMT_INTR_MAP  0x0000001F
+#define DPORT_APP_RMT_INTR_MAP_M  ((DPORT_APP_RMT_INTR_MAP_V)<<(DPORT_APP_RMT_INTR_MAP_S))
+#define DPORT_APP_RMT_INTR_MAP_V  0x1F
+#define DPORT_APP_RMT_INTR_MAP_S  0
+
+#define DPORT_APP_PCNT_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2D8)
+/* DPORT_APP_PCNT_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_PCNT_INTR_MAP  0x0000001F
+#define DPORT_APP_PCNT_INTR_MAP_M  ((DPORT_APP_PCNT_INTR_MAP_V)<<(DPORT_APP_PCNT_INTR_MAP_S))
+#define DPORT_APP_PCNT_INTR_MAP_V  0x1F
+#define DPORT_APP_PCNT_INTR_MAP_S  0
+
+#define DPORT_APP_I2C_EXT0_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2DC)
+/* DPORT_APP_I2C_EXT0_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_I2C_EXT0_INTR_MAP  0x0000001F
+#define DPORT_APP_I2C_EXT0_INTR_MAP_M  ((DPORT_APP_I2C_EXT0_INTR_MAP_V)<<(DPORT_APP_I2C_EXT0_INTR_MAP_S))
+#define DPORT_APP_I2C_EXT0_INTR_MAP_V  0x1F
+#define DPORT_APP_I2C_EXT0_INTR_MAP_S  0
+
+#define DPORT_APP_I2C_EXT1_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2E0)
+/* DPORT_APP_I2C_EXT1_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_I2C_EXT1_INTR_MAP  0x0000001F
+#define DPORT_APP_I2C_EXT1_INTR_MAP_M  ((DPORT_APP_I2C_EXT1_INTR_MAP_V)<<(DPORT_APP_I2C_EXT1_INTR_MAP_S))
+#define DPORT_APP_I2C_EXT1_INTR_MAP_V  0x1F
+#define DPORT_APP_I2C_EXT1_INTR_MAP_S  0
+
+#define DPORT_APP_RSA_INTR_MAP_REG          (DR_REG_DPORT_BASE + 0x2E4)
+/* DPORT_APP_RSA_INTR_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_RSA_INTR_MAP  0x0000001F
+#define DPORT_APP_RSA_INTR_MAP_M  ((DPORT_APP_RSA_INTR_MAP_V)<<(DPORT_APP_RSA_INTR_MAP_S))
+#define DPORT_APP_RSA_INTR_MAP_V  0x1F
+#define DPORT_APP_RSA_INTR_MAP_S  0
+
+#define DPORT_APP_SPI1_DMA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2E8)
+/* DPORT_APP_SPI1_DMA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI1_DMA_INT_MAP  0x0000001F
+#define DPORT_APP_SPI1_DMA_INT_MAP_M  ((DPORT_APP_SPI1_DMA_INT_MAP_V)<<(DPORT_APP_SPI1_DMA_INT_MAP_S))
+#define DPORT_APP_SPI1_DMA_INT_MAP_V  0x1F
+#define DPORT_APP_SPI1_DMA_INT_MAP_S  0
+
+#define DPORT_APP_SPI2_DMA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2EC)
+/* DPORT_APP_SPI2_DMA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI2_DMA_INT_MAP  0x0000001F
+#define DPORT_APP_SPI2_DMA_INT_MAP_M  ((DPORT_APP_SPI2_DMA_INT_MAP_V)<<(DPORT_APP_SPI2_DMA_INT_MAP_S))
+#define DPORT_APP_SPI2_DMA_INT_MAP_V  0x1F
+#define DPORT_APP_SPI2_DMA_INT_MAP_S  0
+
+#define DPORT_APP_SPI3_DMA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2F0)
+/* DPORT_APP_SPI3_DMA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_SPI3_DMA_INT_MAP  0x0000001F
+#define DPORT_APP_SPI3_DMA_INT_MAP_M  ((DPORT_APP_SPI3_DMA_INT_MAP_V)<<(DPORT_APP_SPI3_DMA_INT_MAP_S))
+#define DPORT_APP_SPI3_DMA_INT_MAP_V  0x1F
+#define DPORT_APP_SPI3_DMA_INT_MAP_S  0
+
+#define DPORT_APP_WDG_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x2F4)
+/* DPORT_APP_WDG_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_WDG_INT_MAP  0x0000001F
+#define DPORT_APP_WDG_INT_MAP_M  ((DPORT_APP_WDG_INT_MAP_V)<<(DPORT_APP_WDG_INT_MAP_S))
+#define DPORT_APP_WDG_INT_MAP_V  0x1F
+#define DPORT_APP_WDG_INT_MAP_S  0
+
+#define DPORT_APP_TIMER_INT1_MAP_REG          (DR_REG_DPORT_BASE + 0x2F8)
+/* DPORT_APP_TIMER_INT1_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TIMER_INT1_MAP  0x0000001F
+#define DPORT_APP_TIMER_INT1_MAP_M  ((DPORT_APP_TIMER_INT1_MAP_V)<<(DPORT_APP_TIMER_INT1_MAP_S))
+#define DPORT_APP_TIMER_INT1_MAP_V  0x1F
+#define DPORT_APP_TIMER_INT1_MAP_S  0
+
+#define DPORT_APP_TIMER_INT2_MAP_REG          (DR_REG_DPORT_BASE + 0x2FC)
+/* DPORT_APP_TIMER_INT2_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TIMER_INT2_MAP  0x0000001F
+#define DPORT_APP_TIMER_INT2_MAP_M  ((DPORT_APP_TIMER_INT2_MAP_V)<<(DPORT_APP_TIMER_INT2_MAP_S))
+#define DPORT_APP_TIMER_INT2_MAP_V  0x1F
+#define DPORT_APP_TIMER_INT2_MAP_S  0
+
+#define DPORT_APP_TG_T0_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x300)
+/* DPORT_APP_TG_T0_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_T0_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG_T0_EDGE_INT_MAP_M  ((DPORT_APP_TG_T0_EDGE_INT_MAP_V)<<(DPORT_APP_TG_T0_EDGE_INT_MAP_S))
+#define DPORT_APP_TG_T0_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG_T0_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG_T1_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x304)
+/* DPORT_APP_TG_T1_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_T1_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG_T1_EDGE_INT_MAP_M  ((DPORT_APP_TG_T1_EDGE_INT_MAP_V)<<(DPORT_APP_TG_T1_EDGE_INT_MAP_S))
+#define DPORT_APP_TG_T1_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG_T1_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG_WDT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x308)
+/* DPORT_APP_TG_WDT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_WDT_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG_WDT_EDGE_INT_MAP_M  ((DPORT_APP_TG_WDT_EDGE_INT_MAP_V)<<(DPORT_APP_TG_WDT_EDGE_INT_MAP_S))
+#define DPORT_APP_TG_WDT_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG_WDT_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG_LACT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x30C)
+/* DPORT_APP_TG_LACT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG_LACT_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG_LACT_EDGE_INT_MAP_M  ((DPORT_APP_TG_LACT_EDGE_INT_MAP_V)<<(DPORT_APP_TG_LACT_EDGE_INT_MAP_S))
+#define DPORT_APP_TG_LACT_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG_LACT_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG1_T0_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x310)
+/* DPORT_APP_TG1_T0_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_T0_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_T0_EDGE_INT_MAP_M  ((DPORT_APP_TG1_T0_EDGE_INT_MAP_V)<<(DPORT_APP_TG1_T0_EDGE_INT_MAP_S))
+#define DPORT_APP_TG1_T0_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_T0_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG1_T1_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x314)
+/* DPORT_APP_TG1_T1_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_T1_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_T1_EDGE_INT_MAP_M  ((DPORT_APP_TG1_T1_EDGE_INT_MAP_V)<<(DPORT_APP_TG1_T1_EDGE_INT_MAP_S))
+#define DPORT_APP_TG1_T1_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_T1_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG1_WDT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x318)
+/* DPORT_APP_TG1_WDT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_WDT_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_WDT_EDGE_INT_MAP_M  ((DPORT_APP_TG1_WDT_EDGE_INT_MAP_V)<<(DPORT_APP_TG1_WDT_EDGE_INT_MAP_S))
+#define DPORT_APP_TG1_WDT_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_WDT_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_TG1_LACT_EDGE_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x31C)
+/* DPORT_APP_TG1_LACT_EDGE_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_TG1_LACT_EDGE_INT_MAP  0x0000001F
+#define DPORT_APP_TG1_LACT_EDGE_INT_MAP_M  ((DPORT_APP_TG1_LACT_EDGE_INT_MAP_V)<<(DPORT_APP_TG1_LACT_EDGE_INT_MAP_S))
+#define DPORT_APP_TG1_LACT_EDGE_INT_MAP_V  0x1F
+#define DPORT_APP_TG1_LACT_EDGE_INT_MAP_S  0
+
+#define DPORT_APP_MMU_IA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x320)
+/* DPORT_APP_MMU_IA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_MMU_IA_INT_MAP  0x0000001F
+#define DPORT_APP_MMU_IA_INT_MAP_M  ((DPORT_APP_MMU_IA_INT_MAP_V)<<(DPORT_APP_MMU_IA_INT_MAP_S))
+#define DPORT_APP_MMU_IA_INT_MAP_V  0x1F
+#define DPORT_APP_MMU_IA_INT_MAP_S  0
+
+#define DPORT_APP_MPU_IA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x324)
+/* DPORT_APP_MPU_IA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_MPU_IA_INT_MAP  0x0000001F
+#define DPORT_APP_MPU_IA_INT_MAP_M  ((DPORT_APP_MPU_IA_INT_MAP_V)<<(DPORT_APP_MPU_IA_INT_MAP_S))
+#define DPORT_APP_MPU_IA_INT_MAP_V  0x1F
+#define DPORT_APP_MPU_IA_INT_MAP_S  0
+
+#define DPORT_APP_CACHE_IA_INT_MAP_REG          (DR_REG_DPORT_BASE + 0x328)
+/* DPORT_APP_CACHE_IA_INT_MAP : R/W ;bitpos:[4:0] ;default: 5'd16 ; */
+/*description: */
+#define DPORT_APP_CACHE_IA_INT_MAP  0x0000001F
+#define DPORT_APP_CACHE_IA_INT_MAP_M  ((DPORT_APP_CACHE_IA_INT_MAP_V)<<(DPORT_APP_CACHE_IA_INT_MAP_S))
+#define DPORT_APP_CACHE_IA_INT_MAP_V  0x1F
+#define DPORT_APP_CACHE_IA_INT_MAP_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_UART_REG          (DR_REG_DPORT_BASE + 0x32C)
+/* DPORT_UART_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_UART_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_UART_ACCESS_GRANT_CONFIG_M  ((DPORT_UART_ACCESS_GRANT_CONFIG_V)<<(DPORT_UART_ACCESS_GRANT_CONFIG_S))
+#define DPORT_UART_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_UART_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SPI1_REG          (DR_REG_DPORT_BASE + 0x330)
+/* DPORT_SPI1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SPI1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SPI1_ACCESS_GRANT_CONFIG_M  ((DPORT_SPI1_ACCESS_GRANT_CONFIG_V)<<(DPORT_SPI1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SPI1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SPI1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SPI0_REG          (DR_REG_DPORT_BASE + 0x334)
+/* DPORT_SPI0_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SPI0_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SPI0_ACCESS_GRANT_CONFIG_M  ((DPORT_SPI0_ACCESS_GRANT_CONFIG_V)<<(DPORT_SPI0_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SPI0_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SPI0_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_GPIO_REG          (DR_REG_DPORT_BASE + 0x338)
+/* DPORT_GPIO_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_GPIO_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_GPIO_ACCESS_GRANT_CONFIG_M  ((DPORT_GPIO_ACCESS_GRANT_CONFIG_V)<<(DPORT_GPIO_ACCESS_GRANT_CONFIG_S))
+#define DPORT_GPIO_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_GPIO_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_FE2_REG          (DR_REG_DPORT_BASE + 0x33C)
+/* DPORT_FE2_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_FE2_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_FE2_ACCESS_GRANT_CONFIG_M  ((DPORT_FE2_ACCESS_GRANT_CONFIG_V)<<(DPORT_FE2_ACCESS_GRANT_CONFIG_S))
+#define DPORT_FE2_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_FE2_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_FE_REG          (DR_REG_DPORT_BASE + 0x340)
+/* DPORT_FE_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_FE_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_FE_ACCESS_GRANT_CONFIG_M  ((DPORT_FE_ACCESS_GRANT_CONFIG_V)<<(DPORT_FE_ACCESS_GRANT_CONFIG_S))
+#define DPORT_FE_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_FE_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_TIMER_REG          (DR_REG_DPORT_BASE + 0x344)
+/* DPORT_TIMER_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_TIMER_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_TIMER_ACCESS_GRANT_CONFIG_M  ((DPORT_TIMER_ACCESS_GRANT_CONFIG_V)<<(DPORT_TIMER_ACCESS_GRANT_CONFIG_S))
+#define DPORT_TIMER_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_TIMER_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_RTC_REG          (DR_REG_DPORT_BASE + 0x348)
+/* DPORT_RTC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_RTC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_RTC_ACCESS_GRANT_CONFIG_M  ((DPORT_RTC_ACCESS_GRANT_CONFIG_V)<<(DPORT_RTC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_RTC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_RTC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_IO_MUX_REG          (DR_REG_DPORT_BASE + 0x34C)
+/* DPORT_IOMUX_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_IOMUX_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_IOMUX_ACCESS_GRANT_CONFIG_M  ((DPORT_IOMUX_ACCESS_GRANT_CONFIG_V)<<(DPORT_IOMUX_ACCESS_GRANT_CONFIG_S))
+#define DPORT_IOMUX_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_IOMUX_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_WDG_REG          (DR_REG_DPORT_BASE + 0x350)
+/* DPORT_WDG_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_WDG_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_WDG_ACCESS_GRANT_CONFIG_M  ((DPORT_WDG_ACCESS_GRANT_CONFIG_V)<<(DPORT_WDG_ACCESS_GRANT_CONFIG_S))
+#define DPORT_WDG_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_WDG_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_HINF_REG          (DR_REG_DPORT_BASE + 0x354)
+/* DPORT_HINF_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_HINF_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_HINF_ACCESS_GRANT_CONFIG_M  ((DPORT_HINF_ACCESS_GRANT_CONFIG_V)<<(DPORT_HINF_ACCESS_GRANT_CONFIG_S))
+#define DPORT_HINF_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_HINF_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_UHCI1_REG          (DR_REG_DPORT_BASE + 0x358)
+/* DPORT_UHCI1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_UHCI1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_UHCI1_ACCESS_GRANT_CONFIG_M  ((DPORT_UHCI1_ACCESS_GRANT_CONFIG_V)<<(DPORT_UHCI1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_UHCI1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_UHCI1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_MISC_REG          (DR_REG_DPORT_BASE + 0x35C)
+/* DPORT_MISC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_MISC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_MISC_ACCESS_GRANT_CONFIG_M  ((DPORT_MISC_ACCESS_GRANT_CONFIG_V)<<(DPORT_MISC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_MISC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_MISC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_I2C_REG          (DR_REG_DPORT_BASE + 0x360)
+/* DPORT_I2C_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_I2C_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_I2C_ACCESS_GRANT_CONFIG_M  ((DPORT_I2C_ACCESS_GRANT_CONFIG_V)<<(DPORT_I2C_ACCESS_GRANT_CONFIG_S))
+#define DPORT_I2C_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_I2C_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_I2S0_REG          (DR_REG_DPORT_BASE + 0x364)
+/* DPORT_I2S0_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_I2S0_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_I2S0_ACCESS_GRANT_CONFIG_M  ((DPORT_I2S0_ACCESS_GRANT_CONFIG_V)<<(DPORT_I2S0_ACCESS_GRANT_CONFIG_S))
+#define DPORT_I2S0_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_I2S0_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_UART1_REG          (DR_REG_DPORT_BASE + 0x368)
+/* DPORT_UART1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_UART1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_UART1_ACCESS_GRANT_CONFIG_M  ((DPORT_UART1_ACCESS_GRANT_CONFIG_V)<<(DPORT_UART1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_UART1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_UART1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_BT_REG          (DR_REG_DPORT_BASE + 0x36C)
+/* DPORT_BT_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_BT_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_BT_ACCESS_GRANT_CONFIG_M  ((DPORT_BT_ACCESS_GRANT_CONFIG_V)<<(DPORT_BT_ACCESS_GRANT_CONFIG_S))
+#define DPORT_BT_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_BT_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_BT_BUFFER_REG          (DR_REG_DPORT_BASE + 0x370)
+/* DPORT_BTBUFFER_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_BTBUFFER_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_BTBUFFER_ACCESS_GRANT_CONFIG_M  ((DPORT_BTBUFFER_ACCESS_GRANT_CONFIG_V)<<(DPORT_BTBUFFER_ACCESS_GRANT_CONFIG_S))
+#define DPORT_BTBUFFER_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_BTBUFFER_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_I2C_EXT0_REG          (DR_REG_DPORT_BASE + 0x374)
+/* DPORT_I2CEXT0_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_I2CEXT0_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_I2CEXT0_ACCESS_GRANT_CONFIG_M  ((DPORT_I2CEXT0_ACCESS_GRANT_CONFIG_V)<<(DPORT_I2CEXT0_ACCESS_GRANT_CONFIG_S))
+#define DPORT_I2CEXT0_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_I2CEXT0_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_UHCI0_REG          (DR_REG_DPORT_BASE + 0x378)
+/* DPORT_UHCI0_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_UHCI0_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_UHCI0_ACCESS_GRANT_CONFIG_M  ((DPORT_UHCI0_ACCESS_GRANT_CONFIG_V)<<(DPORT_UHCI0_ACCESS_GRANT_CONFIG_S))
+#define DPORT_UHCI0_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_UHCI0_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SLCHOST_REG          (DR_REG_DPORT_BASE + 0x37C)
+/* DPORT_SLCHOST_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SLCHOST_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SLCHOST_ACCESS_GRANT_CONFIG_M  ((DPORT_SLCHOST_ACCESS_GRANT_CONFIG_V)<<(DPORT_SLCHOST_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SLCHOST_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SLCHOST_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_RMT_REG          (DR_REG_DPORT_BASE + 0x380)
+/* DPORT_RMT_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_RMT_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_RMT_ACCESS_GRANT_CONFIG_M  ((DPORT_RMT_ACCESS_GRANT_CONFIG_V)<<(DPORT_RMT_ACCESS_GRANT_CONFIG_S))
+#define DPORT_RMT_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_RMT_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_PCNT_REG          (DR_REG_DPORT_BASE + 0x384)
+/* DPORT_PCNT_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PCNT_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_PCNT_ACCESS_GRANT_CONFIG_M  ((DPORT_PCNT_ACCESS_GRANT_CONFIG_V)<<(DPORT_PCNT_ACCESS_GRANT_CONFIG_S))
+#define DPORT_PCNT_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_PCNT_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SLC_REG          (DR_REG_DPORT_BASE + 0x388)
+/* DPORT_SLC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SLC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SLC_ACCESS_GRANT_CONFIG_M  ((DPORT_SLC_ACCESS_GRANT_CONFIG_V)<<(DPORT_SLC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SLC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SLC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_LEDC_REG          (DR_REG_DPORT_BASE + 0x38C)
+/* DPORT_LEDC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_LEDC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_LEDC_ACCESS_GRANT_CONFIG_M  ((DPORT_LEDC_ACCESS_GRANT_CONFIG_V)<<(DPORT_LEDC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_LEDC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_LEDC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_EFUSE_REG          (DR_REG_DPORT_BASE + 0x390)
+/* DPORT_EFUSE_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_EFUSE_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_EFUSE_ACCESS_GRANT_CONFIG_M  ((DPORT_EFUSE_ACCESS_GRANT_CONFIG_V)<<(DPORT_EFUSE_ACCESS_GRANT_CONFIG_S))
+#define DPORT_EFUSE_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_EFUSE_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SPI_ENCRYPT_REG          (DR_REG_DPORT_BASE + 0x394)
+/* DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG_M  ((DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG_V)<<(DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SPI_ENCRYPY_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_BB_REG          (DR_REG_DPORT_BASE + 0x398)
+/* DPORT_BB_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_BB_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_BB_ACCESS_GRANT_CONFIG_M  ((DPORT_BB_ACCESS_GRANT_CONFIG_V)<<(DPORT_BB_ACCESS_GRANT_CONFIG_S))
+#define DPORT_BB_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_BB_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_PWM0_REG          (DR_REG_DPORT_BASE + 0x39C)
+/* DPORT_PWM0_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PWM0_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_PWM0_ACCESS_GRANT_CONFIG_M  ((DPORT_PWM0_ACCESS_GRANT_CONFIG_V)<<(DPORT_PWM0_ACCESS_GRANT_CONFIG_S))
+#define DPORT_PWM0_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_PWM0_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_TIMERGROUP_REG          (DR_REG_DPORT_BASE + 0x3A0)
+/* DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG_M  ((DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG_V)<<(DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG_S))
+#define DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_TIMERGROUP_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_TIMERGROUP1_REG          (DR_REG_DPORT_BASE + 0x3A4)
+/* DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG_M  ((DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG_V)<<(DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_TIMERGROUP1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SPI2_REG          (DR_REG_DPORT_BASE + 0x3A8)
+/* DPORT_SPI2_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SPI2_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SPI2_ACCESS_GRANT_CONFIG_M  ((DPORT_SPI2_ACCESS_GRANT_CONFIG_V)<<(DPORT_SPI2_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SPI2_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SPI2_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SPI3_REG          (DR_REG_DPORT_BASE + 0x3AC)
+/* DPORT_SPI3_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SPI3_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SPI3_ACCESS_GRANT_CONFIG_M  ((DPORT_SPI3_ACCESS_GRANT_CONFIG_V)<<(DPORT_SPI3_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SPI3_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SPI3_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_APB_CTRL_REG          (DR_REG_DPORT_BASE + 0x3B0)
+/* DPORT_APBCTRL_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_APBCTRL_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_APBCTRL_ACCESS_GRANT_CONFIG_M  ((DPORT_APBCTRL_ACCESS_GRANT_CONFIG_V)<<(DPORT_APBCTRL_ACCESS_GRANT_CONFIG_S))
+#define DPORT_APBCTRL_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_APBCTRL_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_I2C_EXT1_REG          (DR_REG_DPORT_BASE + 0x3B4)
+/* DPORT_I2CEXT1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_I2CEXT1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_I2CEXT1_ACCESS_GRANT_CONFIG_M  ((DPORT_I2CEXT1_ACCESS_GRANT_CONFIG_V)<<(DPORT_I2CEXT1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_I2CEXT1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_I2CEXT1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_SDIO_HOST_REG          (DR_REG_DPORT_BASE + 0x3B8)
+/* DPORT_SDIOHOST_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_SDIOHOST_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_SDIOHOST_ACCESS_GRANT_CONFIG_M  ((DPORT_SDIOHOST_ACCESS_GRANT_CONFIG_V)<<(DPORT_SDIOHOST_ACCESS_GRANT_CONFIG_S))
+#define DPORT_SDIOHOST_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_SDIOHOST_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_EMAC_REG          (DR_REG_DPORT_BASE + 0x3BC)
+/* DPORT_EMAC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_EMAC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_EMAC_ACCESS_GRANT_CONFIG_M  ((DPORT_EMAC_ACCESS_GRANT_CONFIG_V)<<(DPORT_EMAC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_EMAC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_EMAC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_CAN_REG          (DR_REG_DPORT_BASE + 0x3C0)
+/* DPORT_CAN_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_CAN_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_CAN_ACCESS_GRANT_CONFIG_M  ((DPORT_CAN_ACCESS_GRANT_CONFIG_V)<<(DPORT_CAN_ACCESS_GRANT_CONFIG_S))
+#define DPORT_CAN_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_CAN_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_PWM1_REG          (DR_REG_DPORT_BASE + 0x3C4)
+/* DPORT_PWM1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PWM1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_PWM1_ACCESS_GRANT_CONFIG_M  ((DPORT_PWM1_ACCESS_GRANT_CONFIG_V)<<(DPORT_PWM1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_PWM1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_PWM1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_I2S1_REG          (DR_REG_DPORT_BASE + 0x3C8)
+/* DPORT_I2S1_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_I2S1_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_I2S1_ACCESS_GRANT_CONFIG_M  ((DPORT_I2S1_ACCESS_GRANT_CONFIG_V)<<(DPORT_I2S1_ACCESS_GRANT_CONFIG_S))
+#define DPORT_I2S1_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_I2S1_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_UART2_REG          (DR_REG_DPORT_BASE + 0x3CC)
+/* DPORT_UART2_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_UART2_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_UART2_ACCESS_GRANT_CONFIG_M  ((DPORT_UART2_ACCESS_GRANT_CONFIG_V)<<(DPORT_UART2_ACCESS_GRANT_CONFIG_S))
+#define DPORT_UART2_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_UART2_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_PWM2_REG          (DR_REG_DPORT_BASE + 0x3D0)
+/* DPORT_PWM2_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PWM2_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_PWM2_ACCESS_GRANT_CONFIG_M  ((DPORT_PWM2_ACCESS_GRANT_CONFIG_V)<<(DPORT_PWM2_ACCESS_GRANT_CONFIG_S))
+#define DPORT_PWM2_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_PWM2_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_PWM3_REG          (DR_REG_DPORT_BASE + 0x3D4)
+/* DPORT_PWM3_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PWM3_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_PWM3_ACCESS_GRANT_CONFIG_M  ((DPORT_PWM3_ACCESS_GRANT_CONFIG_V)<<(DPORT_PWM3_ACCESS_GRANT_CONFIG_S))
+#define DPORT_PWM3_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_PWM3_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_RWBT_REG          (DR_REG_DPORT_BASE + 0x3D8)
+/* DPORT_RWBT_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_RWBT_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_RWBT_ACCESS_GRANT_CONFIG_M  ((DPORT_RWBT_ACCESS_GRANT_CONFIG_V)<<(DPORT_RWBT_ACCESS_GRANT_CONFIG_S))
+#define DPORT_RWBT_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_RWBT_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_BTMAC_REG          (DR_REG_DPORT_BASE + 0x3DC)
+/* DPORT_BTMAC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_BTMAC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_BTMAC_ACCESS_GRANT_CONFIG_M  ((DPORT_BTMAC_ACCESS_GRANT_CONFIG_V)<<(DPORT_BTMAC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_BTMAC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_BTMAC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_WIFIMAC_REG          (DR_REG_DPORT_BASE + 0x3E0)
+/* DPORT_WIFIMAC_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_WIFIMAC_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_WIFIMAC_ACCESS_GRANT_CONFIG_M  ((DPORT_WIFIMAC_ACCESS_GRANT_CONFIG_V)<<(DPORT_WIFIMAC_ACCESS_GRANT_CONFIG_S))
+#define DPORT_WIFIMAC_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_WIFIMAC_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_AHBLITE_MPU_TABLE_PWR_REG          (DR_REG_DPORT_BASE + 0x3E4)
+/* DPORT_PWR_ACCESS_GRANT_CONFIG : R/W ;bitpos:[5:0] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PWR_ACCESS_GRANT_CONFIG  0x0000003F
+#define DPORT_PWR_ACCESS_GRANT_CONFIG_M  ((DPORT_PWR_ACCESS_GRANT_CONFIG_V)<<(DPORT_PWR_ACCESS_GRANT_CONFIG_S))
+#define DPORT_PWR_ACCESS_GRANT_CONFIG_V  0x3F
+#define DPORT_PWR_ACCESS_GRANT_CONFIG_S  0
+
+#define DPORT_MEM_ACCESS_DBUG0_REG          (DR_REG_DPORT_BASE + 0x3E8)
+/* DPORT_INTERNAL_SRAM_MMU_MULTI_HIT : RO ;bitpos:[29:26] ;default: 4'b0 ; */
+/*description: */
+#define DPORT_INTERNAL_SRAM_MMU_MULTI_HIT  0x0000000F
+#define DPORT_INTERNAL_SRAM_MMU_MULTI_HIT_M  ((DPORT_INTERNAL_SRAM_MMU_MULTI_HIT_V)<<(DPORT_INTERNAL_SRAM_MMU_MULTI_HIT_S))
+#define DPORT_INTERNAL_SRAM_MMU_MULTI_HIT_V  0xF
+#define DPORT_INTERNAL_SRAM_MMU_MULTI_HIT_S  26
+/* DPORT_INTERNAL_SRAM_IA : RO ;bitpos:[25:14] ;default: 12'b0 ; */
+/*description: */
+#define DPORT_INTERNAL_SRAM_IA  0x00000FFF
+#define DPORT_INTERNAL_SRAM_IA_M  ((DPORT_INTERNAL_SRAM_IA_V)<<(DPORT_INTERNAL_SRAM_IA_S))
+#define DPORT_INTERNAL_SRAM_IA_V  0xFFF
+#define DPORT_INTERNAL_SRAM_IA_S  14
+/* DPORT_INTERNAL_SRAM_MMU_AD : RO ;bitpos:[13:10] ;default: 4'b0 ; */
+/*description: */
+#define DPORT_INTERNAL_SRAM_MMU_AD  0x0000000F
+#define DPORT_INTERNAL_SRAM_MMU_AD_M  ((DPORT_INTERNAL_SRAM_MMU_AD_V)<<(DPORT_INTERNAL_SRAM_MMU_AD_S))
+#define DPORT_INTERNAL_SRAM_MMU_AD_V  0xF
+#define DPORT_INTERNAL_SRAM_MMU_AD_S  10
+/* DPORT_SHARE_ROM_IA : RO ;bitpos:[9:6] ;default: 4'b0 ; */
+/*description: */
+#define DPORT_SHARE_ROM_IA  0x0000000F
+#define DPORT_SHARE_ROM_IA_M  ((DPORT_SHARE_ROM_IA_V)<<(DPORT_SHARE_ROM_IA_S))
+#define DPORT_SHARE_ROM_IA_V  0xF
+#define DPORT_SHARE_ROM_IA_S  6
+/* DPORT_SHARE_ROM_MPU_AD : RO ;bitpos:[5:4] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_SHARE_ROM_MPU_AD  0x00000003
+#define DPORT_SHARE_ROM_MPU_AD_M  ((DPORT_SHARE_ROM_MPU_AD_V)<<(DPORT_SHARE_ROM_MPU_AD_S))
+#define DPORT_SHARE_ROM_MPU_AD_V  0x3
+#define DPORT_SHARE_ROM_MPU_AD_S  4
+/* DPORT_APP_ROM_IA : RO ;bitpos:[3] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_ROM_IA  (BIT(3))
+#define DPORT_APP_ROM_IA_M  (BIT(3))
+#define DPORT_APP_ROM_IA_V  0x1
+#define DPORT_APP_ROM_IA_S  3
+/* DPORT_APP_ROM_MPU_AD : RO ;bitpos:[2] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_ROM_MPU_AD  (BIT(2))
+#define DPORT_APP_ROM_MPU_AD_M  (BIT(2))
+#define DPORT_APP_ROM_MPU_AD_V  0x1
+#define DPORT_APP_ROM_MPU_AD_S  2
+/* DPORT_PRO_ROM_IA : RO ;bitpos:[1] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_ROM_IA  (BIT(1))
+#define DPORT_PRO_ROM_IA_M  (BIT(1))
+#define DPORT_PRO_ROM_IA_V  0x1
+#define DPORT_PRO_ROM_IA_S  1
+/* DPORT_PRO_ROM_MPU_AD : RO ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_ROM_MPU_AD  (BIT(0))
+#define DPORT_PRO_ROM_MPU_AD_M  (BIT(0))
+#define DPORT_PRO_ROM_MPU_AD_V  0x1
+#define DPORT_PRO_ROM_MPU_AD_S  0
+
+#define DPORT_MEM_ACCESS_DBUG1_REG          (DR_REG_DPORT_BASE + 0x3EC)
+/* DPORT_AHBLITE_IA : RO ;bitpos:[10] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHBLITE_IA  (BIT(10))
+#define DPORT_AHBLITE_IA_M  (BIT(10))
+#define DPORT_AHBLITE_IA_V  0x1
+#define DPORT_AHBLITE_IA_S  10
+/* DPORT_AHBLITE_ACCESS_DENY : RO ;bitpos:[9] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHBLITE_ACCESS_DENY  (BIT(9))
+#define DPORT_AHBLITE_ACCESS_DENY_M  (BIT(9))
+#define DPORT_AHBLITE_ACCESS_DENY_V  0x1
+#define DPORT_AHBLITE_ACCESS_DENY_S  9
+/* DPORT_AHB_ACCESS_DENY : RO ;bitpos:[8] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AHB_ACCESS_DENY  (BIT(8))
+#define DPORT_AHB_ACCESS_DENY_M  (BIT(8))
+#define DPORT_AHB_ACCESS_DENY_V  0x1
+#define DPORT_AHB_ACCESS_DENY_S  8
+/* DPORT_PIDGEN_IA : RO ;bitpos:[7:6] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_PIDGEN_IA  0x00000003
+#define DPORT_PIDGEN_IA_M  ((DPORT_PIDGEN_IA_V)<<(DPORT_PIDGEN_IA_S))
+#define DPORT_PIDGEN_IA_V  0x3
+#define DPORT_PIDGEN_IA_S  6
+/* DPORT_ARB_IA : RO ;bitpos:[5:4] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_ARB_IA  0x00000003
+#define DPORT_ARB_IA_M  ((DPORT_ARB_IA_V)<<(DPORT_ARB_IA_S))
+#define DPORT_ARB_IA_V  0x3
+#define DPORT_ARB_IA_S  4
+/* DPORT_INTERNAL_SRAM_MMU_MISS : RO ;bitpos:[3:0] ;default: 4'b0 ; */
+/*description: */
+#define DPORT_INTERNAL_SRAM_MMU_MISS  0x0000000F
+#define DPORT_INTERNAL_SRAM_MMU_MISS_M  ((DPORT_INTERNAL_SRAM_MMU_MISS_V)<<(DPORT_INTERNAL_SRAM_MMU_MISS_S))
+#define DPORT_INTERNAL_SRAM_MMU_MISS_V  0xF
+#define DPORT_INTERNAL_SRAM_MMU_MISS_S  0
+
+#define DPORT_PRO_DCACHE_DBUG0_REG          (DR_REG_DPORT_BASE + 0x3F0)
+/* DPORT_PRO_RX_END : RO ;bitpos:[23] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_RX_END  (BIT(23))
+#define DPORT_PRO_RX_END_M  (BIT(23))
+#define DPORT_PRO_RX_END_V  0x1
+#define DPORT_PRO_RX_END_S  23
+/* DPORT_PRO_SLAVE_WDATA_V : RO ;bitpos:[22] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_SLAVE_WDATA_V  (BIT(22))
+#define DPORT_PRO_SLAVE_WDATA_V_M  (BIT(22))
+#define DPORT_PRO_SLAVE_WDATA_V_V  0x1
+#define DPORT_PRO_SLAVE_WDATA_V_S  22
+/* DPORT_PRO_SLAVE_WR : RO ;bitpos:[21] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_SLAVE_WR  (BIT(21))
+#define DPORT_PRO_SLAVE_WR_M  (BIT(21))
+#define DPORT_PRO_SLAVE_WR_V  0x1
+#define DPORT_PRO_SLAVE_WR_S  21
+/* DPORT_PRO_TX_END : RO ;bitpos:[20] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_TX_END  (BIT(20))
+#define DPORT_PRO_TX_END_M  (BIT(20))
+#define DPORT_PRO_TX_END_V  0x1
+#define DPORT_PRO_TX_END_S  20
+/* DPORT_PRO_WR_BAK_TO_READ : RO ;bitpos:[19] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_WR_BAK_TO_READ  (BIT(19))
+#define DPORT_PRO_WR_BAK_TO_READ_M  (BIT(19))
+#define DPORT_PRO_WR_BAK_TO_READ_V  0x1
+#define DPORT_PRO_WR_BAK_TO_READ_S  19
+/* DPORT_PRO_CACHE_STATE : RO ;bitpos:[18:7] ;default: 12'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_STATE  0x00000FFF
+#define DPORT_PRO_CACHE_STATE_M  ((DPORT_PRO_CACHE_STATE_V)<<(DPORT_PRO_CACHE_STATE_S))
+#define DPORT_PRO_CACHE_STATE_V  0xFFF
+#define DPORT_PRO_CACHE_STATE_S  7
+/* DPORT_PRO_CACHE_IA : RO ;bitpos:[6:1] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_IA  0x0000003F
+#define DPORT_PRO_CACHE_IA_M  ((DPORT_PRO_CACHE_IA_V)<<(DPORT_PRO_CACHE_IA_S))
+#define DPORT_PRO_CACHE_IA_V  0x3F
+#define DPORT_PRO_CACHE_IA_S  1
+/* DPORT_PRO_CACHE_MMU_IA : RO ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_MMU_IA  (BIT(0))
+#define DPORT_PRO_CACHE_MMU_IA_M  (BIT(0))
+#define DPORT_PRO_CACHE_MMU_IA_V  0x1
+#define DPORT_PRO_CACHE_MMU_IA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG1_REG          (DR_REG_DPORT_BASE + 0x3F4)
+/* DPORT_PRO_CTAG_RAM_RDATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_PRO_CTAG_RAM_RDATA  0xFFFFFFFF
+#define DPORT_PRO_CTAG_RAM_RDATA_M  ((DPORT_PRO_CTAG_RAM_RDATA_V)<<(DPORT_PRO_CTAG_RAM_RDATA_S))
+#define DPORT_PRO_CTAG_RAM_RDATA_V  0xFFFFFFFF
+#define DPORT_PRO_CTAG_RAM_RDATA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG2_REG          (DR_REG_DPORT_BASE + 0x3F8)
+/* DPORT_PRO_CACHE_VADDR : RO ;bitpos:[26:0] ;default: 27'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_VADDR  0x07FFFFFF
+#define DPORT_PRO_CACHE_VADDR_M  ((DPORT_PRO_CACHE_VADDR_V)<<(DPORT_PRO_CACHE_VADDR_S))
+#define DPORT_PRO_CACHE_VADDR_V  0x7FFFFFF
+#define DPORT_PRO_CACHE_VADDR_S  0
+
+#define DPORT_PRO_DCACHE_DBUG3_REG          (DR_REG_DPORT_BASE + 0x3FC)
+/* DPORT_PRO_CACHE_IRAM0_PID_ERROR : RO ;bitpos:[15] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CACHE_IRAM0_PID_ERROR  (BIT(15))
+#define DPORT_PRO_CACHE_IRAM0_PID_ERROR_M  (BIT(15))
+#define DPORT_PRO_CACHE_IRAM0_PID_ERROR_V  0x1
+#define DPORT_PRO_CACHE_IRAM0_PID_ERROR_S  15
+/* DPORT_PRO_CPU_DISABLED_CACHE_IA : RO ;bitpos:[14:9] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA  0x0000003F
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_M  ((DPORT_PRO_CPU_DISABLED_CACHE_IA_V)<<(DPORT_PRO_CPU_DISABLED_CACHE_IA_S))
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_V  0x3F
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_S  9
+/* This is the contents of DPORT_PRO_CPU_DISABLED_CACHE_IA field expanded */
+/* The following bits will be set upon invalid access for different memory
+ * regions: */
+/* Port of the APP CPU cache when cache is used in high/low or odd/even mode */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_OPPOSITE   BIT(9)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_OPPOSITE_M BIT(9)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_OPPOSITE_V 1
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_OPPOSITE_S 9
+/* DRAM1: 0x3F80_0000 ~ 0x3FBF_FFFF(R/W) */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DRAM1    BIT(10)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DRAM1_M  BIT(10)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DRAM1_V  1
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DRAM1_S  10
+/* IROM0: 0x4080_0000 ~ 0x40BF_FFFF(RO) */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IROM0    BIT(11)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IROM0_M  BIT(11)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IROM0_V  1
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IROM0_S  11
+/* IRAM1:  0x4040_0000 ~ 0x407F_FFFF(RO) */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM1    BIT(12)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM1_M  BIT(12)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM1_V  1
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM1_S  12
+/* IRAM0: 0x4080_0000 ~ 0x40BF_FFFF(RO) */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM0    BIT(13)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM0_M  BIT(13)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM0_V  1
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_IRAM0_S  13
+/* DROM0: 0x3F40_0000 ~ 0x3F7F_FFFF (RO) */
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DROM0    BIT(14)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DROM0_M  BIT(14)
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DROM0_V  1
+#define DPORT_PRO_CPU_DISABLED_CACHE_IA_DROM0_S  14
+
+/* DPORT_PRO_MMU_RDATA : RO ;bitpos:[8:0] ;default: 9'h0 ; */
+/*description: */
+#define DPORT_PRO_MMU_RDATA  0x000001FF
+#define DPORT_PRO_MMU_RDATA_M  ((DPORT_PRO_MMU_RDATA_V)<<(DPORT_PRO_MMU_RDATA_S))
+#define DPORT_PRO_MMU_RDATA_V  0x1FF
+#define DPORT_PRO_MMU_RDATA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG4_REG          (DR_REG_DPORT_BASE + 0x400)
+/* DPORT_PRO_DRAM1ADDR0_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_PRO_DRAM1ADDR0_IA  0x000FFFFF
+#define DPORT_PRO_DRAM1ADDR0_IA_M  ((DPORT_PRO_DRAM1ADDR0_IA_V)<<(DPORT_PRO_DRAM1ADDR0_IA_S))
+#define DPORT_PRO_DRAM1ADDR0_IA_V  0xFFFFF
+#define DPORT_PRO_DRAM1ADDR0_IA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG5_REG          (DR_REG_DPORT_BASE + 0x404)
+/* DPORT_PRO_DROM0ADDR0_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_PRO_DROM0ADDR0_IA  0x000FFFFF
+#define DPORT_PRO_DROM0ADDR0_IA_M  ((DPORT_PRO_DROM0ADDR0_IA_V)<<(DPORT_PRO_DROM0ADDR0_IA_S))
+#define DPORT_PRO_DROM0ADDR0_IA_V  0xFFFFF
+#define DPORT_PRO_DROM0ADDR0_IA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG6_REG          (DR_REG_DPORT_BASE + 0x408)
+/* DPORT_PRO_IRAM0ADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_PRO_IRAM0ADDR_IA  0x000FFFFF
+#define DPORT_PRO_IRAM0ADDR_IA_M  ((DPORT_PRO_IRAM0ADDR_IA_V)<<(DPORT_PRO_IRAM0ADDR_IA_S))
+#define DPORT_PRO_IRAM0ADDR_IA_V  0xFFFFF
+#define DPORT_PRO_IRAM0ADDR_IA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG7_REG          (DR_REG_DPORT_BASE + 0x40C)
+/* DPORT_PRO_IRAM1ADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_PRO_IRAM1ADDR_IA  0x000FFFFF
+#define DPORT_PRO_IRAM1ADDR_IA_M  ((DPORT_PRO_IRAM1ADDR_IA_V)<<(DPORT_PRO_IRAM1ADDR_IA_S))
+#define DPORT_PRO_IRAM1ADDR_IA_V  0xFFFFF
+#define DPORT_PRO_IRAM1ADDR_IA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG8_REG          (DR_REG_DPORT_BASE + 0x410)
+/* DPORT_PRO_IROM0ADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_PRO_IROM0ADDR_IA  0x000FFFFF
+#define DPORT_PRO_IROM0ADDR_IA_M  ((DPORT_PRO_IROM0ADDR_IA_V)<<(DPORT_PRO_IROM0ADDR_IA_S))
+#define DPORT_PRO_IROM0ADDR_IA_V  0xFFFFF
+#define DPORT_PRO_IROM0ADDR_IA_S  0
+
+#define DPORT_PRO_DCACHE_DBUG9_REG          (DR_REG_DPORT_BASE + 0x414)
+/* DPORT_PRO_OPSDRAMADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_PRO_OPSDRAMADDR_IA  0x000FFFFF
+#define DPORT_PRO_OPSDRAMADDR_IA_M  ((DPORT_PRO_OPSDRAMADDR_IA_V)<<(DPORT_PRO_OPSDRAMADDR_IA_S))
+#define DPORT_PRO_OPSDRAMADDR_IA_V  0xFFFFF
+#define DPORT_PRO_OPSDRAMADDR_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG0_REG          (DR_REG_DPORT_BASE + 0x418)
+/* DPORT_APP_RX_END : RO ;bitpos:[23] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_RX_END  (BIT(23))
+#define DPORT_APP_RX_END_M  (BIT(23))
+#define DPORT_APP_RX_END_V  0x1
+#define DPORT_APP_RX_END_S  23
+/* DPORT_APP_SLAVE_WDATA_V : RO ;bitpos:[22] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_SLAVE_WDATA_V  (BIT(22))
+#define DPORT_APP_SLAVE_WDATA_V_M  (BIT(22))
+#define DPORT_APP_SLAVE_WDATA_V_V  0x1
+#define DPORT_APP_SLAVE_WDATA_V_S  22
+/* DPORT_APP_SLAVE_WR : RO ;bitpos:[21] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_SLAVE_WR  (BIT(21))
+#define DPORT_APP_SLAVE_WR_M  (BIT(21))
+#define DPORT_APP_SLAVE_WR_V  0x1
+#define DPORT_APP_SLAVE_WR_S  21
+/* DPORT_APP_TX_END : RO ;bitpos:[20] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_TX_END  (BIT(20))
+#define DPORT_APP_TX_END_M  (BIT(20))
+#define DPORT_APP_TX_END_V  0x1
+#define DPORT_APP_TX_END_S  20
+/* DPORT_APP_WR_BAK_TO_READ : RO ;bitpos:[19] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_WR_BAK_TO_READ  (BIT(19))
+#define DPORT_APP_WR_BAK_TO_READ_M  (BIT(19))
+#define DPORT_APP_WR_BAK_TO_READ_V  0x1
+#define DPORT_APP_WR_BAK_TO_READ_S  19
+/* DPORT_APP_CACHE_STATE : RO ;bitpos:[18:7] ;default: 12'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_STATE  0x00000FFF
+#define DPORT_APP_CACHE_STATE_M  ((DPORT_APP_CACHE_STATE_V)<<(DPORT_APP_CACHE_STATE_S))
+#define DPORT_APP_CACHE_STATE_V  0xFFF
+#define DPORT_APP_CACHE_STATE_S  7
+/* DPORT_APP_CACHE_IA : RO ;bitpos:[6:1] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_IA  0x0000003F
+#define DPORT_APP_CACHE_IA_M  ((DPORT_APP_CACHE_IA_V)<<(DPORT_APP_CACHE_IA_S))
+#define DPORT_APP_CACHE_IA_V  0x3F
+#define DPORT_APP_CACHE_IA_S  1
+/* DPORT_APP_CACHE_MMU_IA : RO ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_MMU_IA  (BIT(0))
+#define DPORT_APP_CACHE_MMU_IA_M  (BIT(0))
+#define DPORT_APP_CACHE_MMU_IA_V  0x1
+#define DPORT_APP_CACHE_MMU_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG1_REG          (DR_REG_DPORT_BASE + 0x41C)
+/* DPORT_APP_CTAG_RAM_RDATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_APP_CTAG_RAM_RDATA  0xFFFFFFFF
+#define DPORT_APP_CTAG_RAM_RDATA_M  ((DPORT_APP_CTAG_RAM_RDATA_V)<<(DPORT_APP_CTAG_RAM_RDATA_S))
+#define DPORT_APP_CTAG_RAM_RDATA_V  0xFFFFFFFF
+#define DPORT_APP_CTAG_RAM_RDATA_S  0
+
+#define DPORT_APP_DCACHE_DBUG2_REG          (DR_REG_DPORT_BASE + 0x420)
+/* DPORT_APP_CACHE_VADDR : RO ;bitpos:[26:0] ;default: 27'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_VADDR  0x07FFFFFF
+#define DPORT_APP_CACHE_VADDR_M  ((DPORT_APP_CACHE_VADDR_V)<<(DPORT_APP_CACHE_VADDR_S))
+#define DPORT_APP_CACHE_VADDR_V  0x7FFFFFF
+#define DPORT_APP_CACHE_VADDR_S  0
+
+#define DPORT_APP_DCACHE_DBUG3_REG          (DR_REG_DPORT_BASE + 0x424)
+/* DPORT_APP_CACHE_IRAM0_PID_ERROR : RO ;bitpos:[15] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CACHE_IRAM0_PID_ERROR  (BIT(15))
+#define DPORT_APP_CACHE_IRAM0_PID_ERROR_M  (BIT(15))
+#define DPORT_APP_CACHE_IRAM0_PID_ERROR_V  0x1
+#define DPORT_APP_CACHE_IRAM0_PID_ERROR_S  15
+/* DPORT_APP_CPU_DISABLED_CACHE_IA : RO ;bitpos:[14:9] ;default: 6'b0 ; */
+/*description: */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA  0x0000003F
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_M  ((DPORT_APP_CPU_DISABLED_CACHE_IA_V)<<(DPORT_APP_CPU_DISABLED_CACHE_IA_S))
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_V  0x3F
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_S  9
+/* This is the contents of DPORT_APP_CPU_DISABLED_CACHE_IA field expanded */
+/* The following bits will be set upon invalid access for different memory
+ * regions: */
+/* Port of the PRO CPU cache when cache is used in high/low or odd/even mode */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_OPPOSITE   BIT(9)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_OPPOSITE_M BIT(9)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_OPPOSITE_V 1
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_OPPOSITE_S 9
+/* DRAM1: 0x3F80_0000 ~ 0x3FBF_FFFF(R/W) */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DRAM1    BIT(10)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DRAM1_M  BIT(10)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DRAM1_V  1
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DRAM1_S  10
+/* IROM0: 0x4080_0000 ~ 0x40BF_FFFF(RO) */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IROM0    BIT(11)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IROM0_M  BIT(11)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IROM0_V  1
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IROM0_S  11
+/* IRAM1:  0x4040_0000 ~ 0x407F_FFFF(RO) */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM1    BIT(12)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM1_M  BIT(12)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM1_V  1
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM1_S  12
+/* IRAM0: 0x4080_0000 ~ 0x40BF_FFFF(RO) */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM0    BIT(13)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM0_M  BIT(13)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM0_V  1
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_IRAM0_S  13
+/* DROM0: 0x3F40_0000 ~ 0x3F7F_FFFF (RO) */
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DROM0    BIT(14)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DROM0_M  BIT(14)
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DROM0_V  1
+#define DPORT_APP_CPU_DISABLED_CACHE_IA_DROM0_S  14
+
+/* DPORT_APP_MMU_RDATA : RO ;bitpos:[8:0] ;default: 9'h0 ; */
+/*description: */
+#define DPORT_APP_MMU_RDATA  0x000001FF
+#define DPORT_APP_MMU_RDATA_M  ((DPORT_APP_MMU_RDATA_V)<<(DPORT_APP_MMU_RDATA_S))
+#define DPORT_APP_MMU_RDATA_V  0x1FF
+#define DPORT_APP_MMU_RDATA_S  0
+
+#define DPORT_APP_DCACHE_DBUG4_REG          (DR_REG_DPORT_BASE + 0x428)
+/* DPORT_APP_DRAM1ADDR0_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_APP_DRAM1ADDR0_IA  0x000FFFFF
+#define DPORT_APP_DRAM1ADDR0_IA_M  ((DPORT_APP_DRAM1ADDR0_IA_V)<<(DPORT_APP_DRAM1ADDR0_IA_S))
+#define DPORT_APP_DRAM1ADDR0_IA_V  0xFFFFF
+#define DPORT_APP_DRAM1ADDR0_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG5_REG          (DR_REG_DPORT_BASE + 0x42C)
+/* DPORT_APP_DROM0ADDR0_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_APP_DROM0ADDR0_IA  0x000FFFFF
+#define DPORT_APP_DROM0ADDR0_IA_M  ((DPORT_APP_DROM0ADDR0_IA_V)<<(DPORT_APP_DROM0ADDR0_IA_S))
+#define DPORT_APP_DROM0ADDR0_IA_V  0xFFFFF
+#define DPORT_APP_DROM0ADDR0_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG6_REG          (DR_REG_DPORT_BASE + 0x430)
+/* DPORT_APP_IRAM0ADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_APP_IRAM0ADDR_IA  0x000FFFFF
+#define DPORT_APP_IRAM0ADDR_IA_M  ((DPORT_APP_IRAM0ADDR_IA_V)<<(DPORT_APP_IRAM0ADDR_IA_S))
+#define DPORT_APP_IRAM0ADDR_IA_V  0xFFFFF
+#define DPORT_APP_IRAM0ADDR_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG7_REG          (DR_REG_DPORT_BASE + 0x434)
+/* DPORT_APP_IRAM1ADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_APP_IRAM1ADDR_IA  0x000FFFFF
+#define DPORT_APP_IRAM1ADDR_IA_M  ((DPORT_APP_IRAM1ADDR_IA_V)<<(DPORT_APP_IRAM1ADDR_IA_S))
+#define DPORT_APP_IRAM1ADDR_IA_V  0xFFFFF
+#define DPORT_APP_IRAM1ADDR_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG8_REG          (DR_REG_DPORT_BASE + 0x438)
+/* DPORT_APP_IROM0ADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_APP_IROM0ADDR_IA  0x000FFFFF
+#define DPORT_APP_IROM0ADDR_IA_M  ((DPORT_APP_IROM0ADDR_IA_V)<<(DPORT_APP_IROM0ADDR_IA_S))
+#define DPORT_APP_IROM0ADDR_IA_V  0xFFFFF
+#define DPORT_APP_IROM0ADDR_IA_S  0
+
+#define DPORT_APP_DCACHE_DBUG9_REG          (DR_REG_DPORT_BASE + 0x43C)
+/* DPORT_APP_OPSDRAMADDR_IA : RO ;bitpos:[19:0] ;default: 20'b0 ; */
+/*description: */
+#define DPORT_APP_OPSDRAMADDR_IA  0x000FFFFF
+#define DPORT_APP_OPSDRAMADDR_IA_M  ((DPORT_APP_OPSDRAMADDR_IA_V)<<(DPORT_APP_OPSDRAMADDR_IA_S))
+#define DPORT_APP_OPSDRAMADDR_IA_V  0xFFFFF
+#define DPORT_APP_OPSDRAMADDR_IA_S  0
+
+#define DPORT_PRO_CPU_RECORD_CTRL_REG          (DR_REG_DPORT_BASE + 0x440)
+/* DPORT_PRO_CPU_PDEBUG_ENABLE : R/W ;bitpos:[8] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_CPU_PDEBUG_ENABLE  (BIT(8))
+#define DPORT_PRO_CPU_PDEBUG_ENABLE_M  (BIT(8))
+#define DPORT_PRO_CPU_PDEBUG_ENABLE_V  0x1
+#define DPORT_PRO_CPU_PDEBUG_ENABLE_S  8
+/* DPORT_PRO_CPU_RECORD_DISABLE : R/W ;bitpos:[4] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CPU_RECORD_DISABLE  (BIT(4))
+#define DPORT_PRO_CPU_RECORD_DISABLE_M  (BIT(4))
+#define DPORT_PRO_CPU_RECORD_DISABLE_V  0x1
+#define DPORT_PRO_CPU_RECORD_DISABLE_S  4
+/* DPORT_PRO_CPU_RECORD_ENABLE : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CPU_RECORD_ENABLE  (BIT(0))
+#define DPORT_PRO_CPU_RECORD_ENABLE_M  (BIT(0))
+#define DPORT_PRO_CPU_RECORD_ENABLE_V  0x1
+#define DPORT_PRO_CPU_RECORD_ENABLE_S  0
+
+#define DPORT_PRO_CPU_RECORD_STATUS_REG          (DR_REG_DPORT_BASE + 0x444)
+/* DPORT_PRO_CPU_RECORDING : RO ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PRO_CPU_RECORDING  (BIT(0))
+#define DPORT_PRO_CPU_RECORDING_M  (BIT(0))
+#define DPORT_PRO_CPU_RECORDING_V  0x1
+#define DPORT_PRO_CPU_RECORDING_S  0
+
+#define DPORT_PRO_CPU_RECORD_PID_REG          (DR_REG_DPORT_BASE + 0x448)
+/* DPORT_RECORD_PRO_PID : RO ;bitpos:[2:0] ;default: 3'd0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PID  0x00000007
+#define DPORT_RECORD_PRO_PID_M  ((DPORT_RECORD_PRO_PID_V)<<(DPORT_RECORD_PRO_PID_S))
+#define DPORT_RECORD_PRO_PID_V  0x7
+#define DPORT_RECORD_PRO_PID_S  0
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGINST_REG          (DR_REG_DPORT_BASE + 0x44C)
+/* DPORT_RECORD_PRO_PDEBUGINST : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGINST  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGINST_M  ((DPORT_RECORD_PRO_PDEBUGINST_V)<<(DPORT_RECORD_PRO_PDEBUGINST_S))
+#define DPORT_RECORD_PRO_PDEBUGINST_V  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGINST_S  0
+/* register layout:
+ * SIZE [7..0]          : Instructions normally complete in the W stage. The size of the instruction in the W is given
+ *                       by this field in number of bytes. If it is 8’b0 in a given cycle the W stage has no completing
+ *                       instruction. This is also known as a bubble cycle. Also see DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG.
+ * ISRC [14..12]     : Instruction source.
+** LOOP [23..20]     : Loopback status.
+** CINTLEVEL [27..24]: CINTLEVEL.
+*/
+#define DPORT_RECORD_PDEBUGINST_SZ_M          ((DPORT_RECORD_PDEBUGINST_SZ_V)<<(DPORT_RECORD_PDEBUGINST_SZ_S))
+#define DPORT_RECORD_PDEBUGINST_SZ_V          0xFF
+#define DPORT_RECORD_PDEBUGINST_SZ_S          0
+#define DPORT_RECORD_PDEBUGINST_SZ(_r_)        (((_r_)>>DPORT_RECORD_PDEBUGINST_SZ_S) & DPORT_RECORD_PDEBUGINST_SZ_V)
+#define DPORT_RECORD_PDEBUGINST_ISRC_M      ((DPORT_RECORD_PDEBUGINST_ISRC_V)<<(DPORT_RECORD_PDEBUGINST_ISRC_S))
+#define DPORT_RECORD_PDEBUGINST_ISRC_V      0x07
+#define DPORT_RECORD_PDEBUGINST_ISRC_S      12
+#define DPORT_RECORD_PDEBUGINST_ISRC(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGINST_ISRC_S) & DPORT_RECORD_PDEBUGINST_ISRC_V)
+// #define DPORT_RECORD_PDEBUGINST_LOOP_M      ((DPORT_RECORD_PDEBUGINST_LOOP_V)<<(DPORT_RECORD_PDEBUGINST_LOOP_S))
+// #define DPORT_RECORD_PDEBUGINST_LOOP_V      0x0F
+// #define DPORT_RECORD_PDEBUGINST_LOOP_S      20
+// #define DPORT_RECORD_PDEBUGINST_LOOP(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGINST_LOOP_S) & DPORT_RECORD_PDEBUGINST_LOOP_V)
+#define DPORT_RECORD_PDEBUGINST_LOOP_REP     (BIT(20)) /* loopback will occur */
+#define DPORT_RECORD_PDEBUGINST_LOOP        (BIT(21)) /* last inst of loop */
+#define DPORT_RECORD_PDEBUGINST_CINTL_M      ((DPORT_RECORD_PDEBUGINST_CINTL_V)<<(DPORT_RECORD_PDEBUGINST_CINTL_S))
+#define DPORT_RECORD_PDEBUGINST_CINTL_V      0x0F
+#define DPORT_RECORD_PDEBUGINST_CINTL_S      24
+#define DPORT_RECORD_PDEBUGINST_CINTL(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGINST_CINTL_S) & DPORT_RECORD_PDEBUGINST_CINTL_V)
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGSTATUS_REG          (DR_REG_DPORT_BASE + 0x450)
+/* DPORT_RECORD_PRO_PDEBUGSTATUS : RO ;bitpos:[7:0] ;default: 8'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGSTATUS  0x000000FF
+#define DPORT_RECORD_PRO_PDEBUGSTATUS_M  ((DPORT_RECORD_PRO_PDEBUGSTATUS_V)<<(DPORT_RECORD_PRO_PDEBUGSTATUS_S))
+#define DPORT_RECORD_PRO_PDEBUGSTATUS_V  0xFF
+#define DPORT_RECORD_PRO_PDEBUGSTATUS_S  0
+/* register layout:
+ * BBCAUSE [5..0]: Indicates cause for bubble cycle. See below for posible values. When DPORT_RECORD_PDEBUGINST_SZ == 0
+ * INSNTYPE[5..0]: Indicates type of instruction retiring in the W stage. See below for posible values. When DPORT_RECORD_PDEBUGINST_SZ > 0
+*/
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_M          ((DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_V)<<(DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_S))
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_V          0x3F
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_S          0
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE(_r_)        (((_r_)>>DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_S) & DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_V)
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_PSO        0x00 /* Power shut off */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DEP        0x02 /* Register dependency or resource conflict. See DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG for extra info. */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_CTL        0x04 /* Control transfer bubble */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_ICM        0x08 /* I-cache miss (incl uncached miss) */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DCM        0x0C /* D-cache miss (excl uncached miss) */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_EXC0        0x10 /* Exception or interrupt (W stage). See DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG for extra info.
+                                                            The virtual address of the instruction that was killed appears on DPORT_PRO_CPU_RECORD_PDEBUGPC_REG[31:0] */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_EXC1        0x11 /* Exception or interrupt (W+1 stage). See DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG for extra info. */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_RPL        0x14 /* Instruction replay (other). DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG has the PC of the replaying instruction. */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_ITLB        0x18 /* HW ITLB refill. The refill address and data are available on
+                                                            DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG and DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG. */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_ITLBM        0x1A /* ITLB miss */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DTLB        0x1C /* HW DTLB refill. The refill address and data are available on
+                                                            DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG and DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG. */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DTLBM        0x1E /* DTLB miss */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_STALL        0x20 /* Stall . The cause of the global stall is further classified in the DPORT_XXX_CPU_RECORD_PDEBUGDATA_REG. */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_HWMEC        0x24 /* HW-corrected memory error */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_WAITI        0x28 /* WAITI mode */
+#define DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_OTHER        0x3C /* all other bubbles */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_M          ((DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_V)<<(DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S))
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_V          0x3F
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S          0
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE(_r_)        (((_r_)>>DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S) & DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_V)
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_JX        0x00 /* JX */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_CALLX    0x04 /* CALLX */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_CRET        0x08 /* All call returns */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_ERET        0x0C /* All exception returns */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_B        0x10 /* Branch taken or loop not taken */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_J        0x14 /* J */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_CALL        0x18 /* CALL */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_BN        0x1C /* Branch not taken */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_LOOP        0x20 /* Loop instruction (taken) */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_S32C1I    0x24 /* S32C1I. The address and load data (before the conditional store) are available on the LS signals*/
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_WXSR2LB    0x28 /* WSR/XSR to LBEGIN */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_WSR2MMID    0x2C /* WSR to MMID */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWXSR    0x30 /* RSR or WSR (except MMID and LBEGIN) or XSR (except LBEGIN) */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWER        0x34 /* RER or WER */
+#define DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_DEF        0x3C /* Default */
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGDATA_REG          (DR_REG_DPORT_BASE + 0x454)
+/* DPORT_RECORD_PRO_PDEBUGDATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGDATA  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGDATA_M  ((DPORT_RECORD_PRO_PDEBUGDATA_V)<<(DPORT_RECORD_PRO_PDEBUGDATA_S))
+#define DPORT_RECORD_PRO_PDEBUGDATA_V  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGDATA_S  0
+/* register layout when bubble cycke cause is DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_DEP:
+ *
+ * HALT [17]: HALT instruction (TX only)
+ * MEMW [16]: MEMW, EXTW or EXCW instruction dependency
+ * REG  [12]: register dependencies or resource (e.g.TIE ports) conflicts
+ * STR  [11]: store release (instruction) dependency
+ * LSU  [8] : various LSU dependencies (MHT access, prefetch, cache access insts, s32c1i, etc)
+ * OTHER[0] : all other hold dependencies resulting from data or resource dependencies
+*/
+#define DPORT_RECORD_PDEBUGDATA_DEP_HALT      (BIT(17))
+#define DPORT_RECORD_PDEBUGDATA_DEP_MEMW      (BIT(16))
+#define DPORT_RECORD_PDEBUGDATA_DEP_REG      (BIT(12))
+#define DPORT_RECORD_PDEBUGDATA_DEP_STR      (BIT(11))
+#define DPORT_RECORD_PDEBUGDATA_DEP_LSU      (BIT(8))
+#define DPORT_RECORD_PDEBUGDATA_DEP_OTHER    (BIT(0))
+/* register layout when bubble cycke cause is DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_EXCn:
+ *
+ * EXCCAUSE[21..16]: Processor exception cause
+ * EXCVEC  [4..0]  : Encoded Exception Vector
+*/
+#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE_M      ((DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V)<<(DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S))
+#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V      0x3F
+#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S      16
+#define DPORT_RECORD_PDEBUGDATA_EXCCAUSE(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S) & DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V)
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_M          ((DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V)<<(DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S))
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_V          0x1F
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_S          0
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC(_r_)        (((_r_)>>DPORT_RECORD_PDEBUGDATA_EXCCAUSE_S) & DPORT_RECORD_PDEBUGDATA_EXCCAUSE_V)
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_NONE        0x00 /* no vector */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_RST        0x01 /* Reset */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_DBG        0x02 /* Debug (repl corresp level “n”) */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_NMI        0x03 /* NMI (repl corresp level “n”) */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_USR        0x04 /* User */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_KRNL        0x05 /* Kernel */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_DBL        0x06 /* Double */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_EMEM        0x07 /* Memory Error */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_OVF4        0x0A /* Window Overflow 4 */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_UNF4        0x0B /* Window Underflow 4 */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_OVF8        0x0C /* Window Overflow 8 */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_UNF8        0x0D /* Window Underflow 8 */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_OVF12    0x0E /* Window Overflow 12 */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_UNF12    0x0F /* Window Underflow 12 */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT2        0x10 /* Int Level 2 (n/a if debug/NMI) */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT3        0x11 /* Int Level 3 (n/a if debug/NMI) */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT4        0x12 /* Int Level 4 (n/a if debug/NMI) */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT5        0x13 /* Int Level 5 (n/a if debug/NMI) */
+#define DPORT_RECORD_PDEBUGDATA_EXCVEC_INT6        0x14 /* Int Level 6 (n/a if debug/NMI) */
+/* register layout when bubble cycke cause is DPORT_RECORD_PDEBUGSTATUS_BBCAUSE_STALL:
+ *
+ * ITERDIV[19]  : Iterative divide stall.
+ * ITERMUL[18]  : Iterative multiply stall.
+ * BANKCONFL[16]: Bank-conflict stall.
+ * BPLOAD[15]      : Bypass load stall.
+ * LSPROC[14]      : Load/store miss-processing stall.
+ * L32R[13]           : FastL32R stall.
+ * BPIFETCH[12]    : Bypass I fetch stall.
+ * RUNSTALL[10]    : RunStall.
+ * TIE[9]            : TIE port stall.
+ * IPIF[8]           : Instruction RAM inbound-PIF stall.
+ * IRAMBUSY[7]     : Instruction RAM/ROM busy stall.
+ * ICM[6]            : I-cache-miss stall.
+ * LSU[4]          : The LSU will stall the pipeline under various local memory access conflict situations.
+ * DCM[3]            : D-cache-miss stall.
+ * BUFFCONFL[2]    : Store buffer conflict stall.
+ * BUFF[1]            : Store buffer full stall.
+*/
+#define DPORT_RECORD_PDEBUGDATA_STALL_ITERDIV    (BIT(19))
+#define DPORT_RECORD_PDEBUGDATA_STALL_ITERMUL    (BIT(18))
+#define DPORT_RECORD_PDEBUGDATA_STALL_BANKCONFL    (BIT(16))
+#define DPORT_RECORD_PDEBUGDATA_STALL_BPLOAD    (BIT(15))
+#define DPORT_RECORD_PDEBUGDATA_STALL_LSPROC    (BIT(14))
+#define DPORT_RECORD_PDEBUGDATA_STALL_L32R        (BIT(13))
+#define DPORT_RECORD_PDEBUGDATA_STALL_BPIFETCH    (BIT(12))
+#define DPORT_RECORD_PDEBUGDATA_STALL_RUN        (BIT(10))
+#define DPORT_RECORD_PDEBUGDATA_STALL_TIE        (BIT(9))
+#define DPORT_RECORD_PDEBUGDATA_STALL_IPIF        (BIT(8))
+#define DPORT_RECORD_PDEBUGDATA_STALL_IRAMBUSY    (BIT(7))
+#define DPORT_RECORD_PDEBUGDATA_STALL_ICM        (BIT(6))
+#define DPORT_RECORD_PDEBUGDATA_STALL_LSU        (BIT(4))
+#define DPORT_RECORD_PDEBUGDATA_STALL_DCM        (BIT(3))
+#define DPORT_RECORD_PDEBUGDATA_STALL_BUFFCONFL    (BIT(2))
+#define DPORT_RECORD_PDEBUGDATA_STALL_BUFF        (BIT(1))
+/* register layout for DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWXSR:
+ *
+ * XSR[10]        : XSR Instruction
+ * WSR[9]        : WSR Instruction
+ * RSR[8]        : RSR Instruction
+ * SR[7..0] : Special Register Number
+*/
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_XSR        (BIT(10))
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_WSR        (BIT(9))
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_RSR        (BIT(8))
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_M          ((DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_V)<<(DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_S))
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_V          0xFF
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_S          0
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_S) & DPORT_RECORD_PDEBUGDATA_INSNTYPE_SR_V)
+/* register layout for DPORT_RECORD_PDEBUGSTATUS_INSNTYPE_RWER:
+ *
+ * ER[13..2]: ER Address
+ * WER[1]    : WER Instruction
+ * RER[0]    : RER Instruction
+*/
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_M          ((DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_V)<<(DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_S))
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_V          0xFFF
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_S          2
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_S) & DPORT_RECORD_PDEBUGDATA_INSNTYPE_ER_V)
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_WER        (BIT(1))
+#define DPORT_RECORD_PDEBUGDATA_INSNTYPE_RER        (BIT(0))
+
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGPC_REG          (DR_REG_DPORT_BASE + 0x458)
+/* DPORT_RECORD_PRO_PDEBUGPC : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGPC  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGPC_M  ((DPORT_RECORD_PRO_PDEBUGPC_V)<<(DPORT_RECORD_PRO_PDEBUGPC_S))
+#define DPORT_RECORD_PRO_PDEBUGPC_V  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGPC_S  0
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGLS0STAT_REG          (DR_REG_DPORT_BASE + 0x45C)
+/* DPORT_RECORD_PRO_PDEBUGLS0STAT : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGLS0STAT  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGLS0STAT_M  ((DPORT_RECORD_PRO_PDEBUGLS0STAT_V)<<(DPORT_RECORD_PRO_PDEBUGLS0STAT_S))
+#define DPORT_RECORD_PRO_PDEBUGLS0STAT_V  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGLS0STAT_S  0
+/* register layout:
+ * TYPE [3..0]      : Type of instruction in LS.
+ * SZ [7..4]     : Operand size.
+ * DTLBM [8]     : Data TLB miss.
+ * DCM [9]         : D-cache miss.
+ * DCH [10]         : D-cache hit.
+ * UC [12]         : Uncached.
+ * WB [13]         : Writeback.
+ * COH [16]         : Coherency.
+ * STCOH [18..17]: Coherent state.
+ * TGT [23..20]  : Local target.
+*/
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_M          ((DPORT_RECORD_PDEBUGLS0STAT_TYPE_V)<<(DPORT_RECORD_PDEBUGLS0STAT_TYPE_S))
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_V          0x0F
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_S          0
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_TYPE_S) & DPORT_RECORD_PDEBUGLS0STAT_TYPE_V)
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_NONE    0x00 /* neither */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_ITLBR    0x01 /* hw itlb refill */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_DTLBR    0x02 /* hw dtlb refill */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_LD        0x05 /* load */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_STR        0x06 /* store */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_L32R    0x08 /* l32r */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_S32CLI1    0x0A /* s32ci1 */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_CTI        0x0C /* cache test inst */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_RWXSR    0x0E /* rsr/wsr/xsr */
+#define DPORT_RECORD_PDEBUGLS0STAT_TYPE_RWER    0x0F /* rer/wer */
+#define DPORT_RECORD_PDEBUGLS0STAT_SZ_M          ((DPORT_RECORD_PDEBUGLS0STAT_SZ_V)<<(DPORT_RECORD_PDEBUGLS0STAT_SZ_S))
+#define DPORT_RECORD_PDEBUGLS0STAT_SZ_V          0x0F
+#define DPORT_RECORD_PDEBUGLS0STAT_SZ_S          4
+#define DPORT_RECORD_PDEBUGLS0STAT_SZ(_r_)        (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_SZ_S) & DPORT_RECORD_PDEBUGLS0STAT_SZ_V)
+#define DPORT_RECORD_PDEBUGLS0STAT_SZB(_r_)        ((8<<DPORT_RECORD_PDEBUGLS0STAT_SZ(_r_))/8) // in bytes
+#define DPORT_RECORD_PDEBUGLS0STAT_DTLBM        (BIT(8))
+#define DPORT_RECORD_PDEBUGLS0STAT_DCM            (BIT(9))
+#define DPORT_RECORD_PDEBUGLS0STAT_DCH            (BIT(10))
+#define DPORT_RECORD_PDEBUGLS0STAT_UC            (BIT(12))
+#define DPORT_RECORD_PDEBUGLS0STAT_WB            (BIT(13))
+#define DPORT_RECORD_PDEBUGLS0STAT_COH            (BIT(16))
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_M      ((DPORT_RECORD_PDEBUGLS0STAT_STCOH_V)<<(DPORT_RECORD_PDEBUGLS0STAT_STCOH_S))
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_V      0x03
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_S      17
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH(_r_)    (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_STCOH_S) & DPORT_RECORD_PDEBUGLS0STAT_STCOH_V)
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_NONE      0x0 /* neither shared nor exclusive nor modified */
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_SHARED    0x1 /* shared */
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_EXCL      0x2 /* exclusive */
+#define DPORT_RECORD_PDEBUGLS0STAT_STCOH_MOD      0x3 /* modified */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_M          ((DPORT_RECORD_PDEBUGLS0STAT_TGT_V)<<(DPORT_RECORD_PDEBUGLS0STAT_TGT_S))
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_V          0x0F
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_S          20
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT(_r_)        (((_r_)>>DPORT_RECORD_PDEBUGLS0STAT_TGT_S) & DPORT_RECORD_PDEBUGLS0STAT_TGT_V)
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_EXT      0x0 /* not to local memory */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IRAM0    0x2 /* 001x: InstRAM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IRAM1    0x3 /* 001x: InstRAM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IROM0      0x4 /* 010x: InstROM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_IROM1      0x5 /* 010x: InstROM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DRAM0      0x0A /* 101x: DataRAM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DRAM1      0x0B /* 101x: DataRAM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DROM0      0xE /* 111x: DataROM (0/1) */
+#define DPORT_RECORD_PDEBUGLS0STAT_TGT_DROM1      0xF /* 111x: DataROM (0/1) */
+// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_IRAM(_t_)    (((_t_)&0xE)=0x2) /* 001x: InstRAM (0/1) */
+// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_IROM(_t_)      (((_t_)&0xE)=0x4) /* 010x: InstROM (0/1) */
+// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_DRAM(_t_)      (((_t_)&0xE)=0x2) /* 101x: DataRAM (0/1) */
+// #define DPORT_RECORD_PDEBUGLS0STAT_TGT_DROM(_t_)      (((_t_)&0xE)=0x2) /* 111x: DataROM (0/1) */
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGLS0ADDR_REG          (DR_REG_DPORT_BASE + 0x460)
+/* DPORT_RECORD_PRO_PDEBUGLS0ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGLS0ADDR  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGLS0ADDR_M  ((DPORT_RECORD_PRO_PDEBUGLS0ADDR_V)<<(DPORT_RECORD_PRO_PDEBUGLS0ADDR_S))
+#define DPORT_RECORD_PRO_PDEBUGLS0ADDR_V  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGLS0ADDR_S  0
+
+#define DPORT_PRO_CPU_RECORD_PDEBUGLS0DATA_REG          (DR_REG_DPORT_BASE + 0x464)
+/* DPORT_RECORD_PRO_PDEBUGLS0DATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_PRO_PDEBUGLS0DATA  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGLS0DATA_M  ((DPORT_RECORD_PRO_PDEBUGLS0DATA_V)<<(DPORT_RECORD_PRO_PDEBUGLS0DATA_S))
+#define DPORT_RECORD_PRO_PDEBUGLS0DATA_V  0xFFFFFFFF
+#define DPORT_RECORD_PRO_PDEBUGLS0DATA_S  0
+
+#define DPORT_APP_CPU_RECORD_CTRL_REG          (DR_REG_DPORT_BASE + 0x468)
+/* DPORT_APP_CPU_PDEBUG_ENABLE : R/W ;bitpos:[8] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_CPU_PDEBUG_ENABLE  (BIT(8))
+#define DPORT_APP_CPU_PDEBUG_ENABLE_M  (BIT(8))
+#define DPORT_APP_CPU_PDEBUG_ENABLE_V  0x1
+#define DPORT_APP_CPU_PDEBUG_ENABLE_S  8
+/* DPORT_APP_CPU_RECORD_DISABLE : R/W ;bitpos:[4] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CPU_RECORD_DISABLE  (BIT(4))
+#define DPORT_APP_CPU_RECORD_DISABLE_M  (BIT(4))
+#define DPORT_APP_CPU_RECORD_DISABLE_V  0x1
+#define DPORT_APP_CPU_RECORD_DISABLE_S  4
+/* DPORT_APP_CPU_RECORD_ENABLE : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CPU_RECORD_ENABLE  (BIT(0))
+#define DPORT_APP_CPU_RECORD_ENABLE_M  (BIT(0))
+#define DPORT_APP_CPU_RECORD_ENABLE_V  0x1
+#define DPORT_APP_CPU_RECORD_ENABLE_S  0
+
+#define DPORT_APP_CPU_RECORD_STATUS_REG          (DR_REG_DPORT_BASE + 0x46C)
+/* DPORT_APP_CPU_RECORDING : RO ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_APP_CPU_RECORDING  (BIT(0))
+#define DPORT_APP_CPU_RECORDING_M  (BIT(0))
+#define DPORT_APP_CPU_RECORDING_V  0x1
+#define DPORT_APP_CPU_RECORDING_S  0
+
+#define DPORT_APP_CPU_RECORD_PID_REG          (DR_REG_DPORT_BASE + 0x470)
+/* DPORT_RECORD_APP_PID : RO ;bitpos:[2:0] ;default: 3'd0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PID  0x00000007
+#define DPORT_RECORD_APP_PID_M  ((DPORT_RECORD_APP_PID_V)<<(DPORT_RECORD_APP_PID_S))
+#define DPORT_RECORD_APP_PID_V  0x7
+#define DPORT_RECORD_APP_PID_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGINST_REG          (DR_REG_DPORT_BASE + 0x474)
+/* DPORT_RECORD_APP_PDEBUGINST : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGINST  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGINST_M  ((DPORT_RECORD_APP_PDEBUGINST_V)<<(DPORT_RECORD_APP_PDEBUGINST_S))
+#define DPORT_RECORD_APP_PDEBUGINST_V  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGINST_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGSTATUS_REG          (DR_REG_DPORT_BASE + 0x478)
+/* DPORT_RECORD_APP_PDEBUGSTATUS : RO ;bitpos:[7:0] ;default: 8'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGSTATUS  0x000000FF
+#define DPORT_RECORD_APP_PDEBUGSTATUS_M  ((DPORT_RECORD_APP_PDEBUGSTATUS_V)<<(DPORT_RECORD_APP_PDEBUGSTATUS_S))
+#define DPORT_RECORD_APP_PDEBUGSTATUS_V  0xFF
+#define DPORT_RECORD_APP_PDEBUGSTATUS_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGDATA_REG          (DR_REG_DPORT_BASE + 0x47C)
+/* DPORT_RECORD_APP_PDEBUGDATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGDATA  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGDATA_M  ((DPORT_RECORD_APP_PDEBUGDATA_V)<<(DPORT_RECORD_APP_PDEBUGDATA_S))
+#define DPORT_RECORD_APP_PDEBUGDATA_V  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGDATA_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGPC_REG          (DR_REG_DPORT_BASE + 0x480)
+/* DPORT_RECORD_APP_PDEBUGPC : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGPC  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGPC_M  ((DPORT_RECORD_APP_PDEBUGPC_V)<<(DPORT_RECORD_APP_PDEBUGPC_S))
+#define DPORT_RECORD_APP_PDEBUGPC_V  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGPC_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGLS0STAT_REG          (DR_REG_DPORT_BASE + 0x484)
+/* DPORT_RECORD_APP_PDEBUGLS0STAT : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGLS0STAT  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGLS0STAT_M  ((DPORT_RECORD_APP_PDEBUGLS0STAT_V)<<(DPORT_RECORD_APP_PDEBUGLS0STAT_S))
+#define DPORT_RECORD_APP_PDEBUGLS0STAT_V  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGLS0STAT_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGLS0ADDR_REG          (DR_REG_DPORT_BASE + 0x488)
+/* DPORT_RECORD_APP_PDEBUGLS0ADDR : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGLS0ADDR  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGLS0ADDR_M  ((DPORT_RECORD_APP_PDEBUGLS0ADDR_V)<<(DPORT_RECORD_APP_PDEBUGLS0ADDR_S))
+#define DPORT_RECORD_APP_PDEBUGLS0ADDR_V  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGLS0ADDR_S  0
+
+#define DPORT_APP_CPU_RECORD_PDEBUGLS0DATA_REG          (DR_REG_DPORT_BASE + 0x48C)
+/* DPORT_RECORD_APP_PDEBUGLS0DATA : RO ;bitpos:[31:0] ;default: 32'b0 ; */
+/*description: */
+#define DPORT_RECORD_APP_PDEBUGLS0DATA  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGLS0DATA_M  ((DPORT_RECORD_APP_PDEBUGLS0DATA_V)<<(DPORT_RECORD_APP_PDEBUGLS0DATA_S))
+#define DPORT_RECORD_APP_PDEBUGLS0DATA_V  0xFFFFFFFF
+#define DPORT_RECORD_APP_PDEBUGLS0DATA_S  0
+
+#define DPORT_RSA_PD_CTRL_REG          (DR_REG_DPORT_BASE + 0x490)
+/* DPORT_RSA_PD : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_RSA_PD  (BIT(0))
+#define DPORT_RSA_PD_M  (BIT(0))
+#define DPORT_RSA_PD_V  0x1
+#define DPORT_RSA_PD_S  0
+
+#define DPORT_ROM_MPU_TABLE0_REG          (DR_REG_DPORT_BASE + 0x494)
+/* DPORT_ROM_MPU_TABLE0 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_ROM_MPU_TABLE0  0x00000003
+#define DPORT_ROM_MPU_TABLE0_M  ((DPORT_ROM_MPU_TABLE0_V)<<(DPORT_ROM_MPU_TABLE0_S))
+#define DPORT_ROM_MPU_TABLE0_V  0x3
+#define DPORT_ROM_MPU_TABLE0_S  0
+
+#define DPORT_ROM_MPU_TABLE1_REG          (DR_REG_DPORT_BASE + 0x498)
+/* DPORT_ROM_MPU_TABLE1 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_ROM_MPU_TABLE1  0x00000003
+#define DPORT_ROM_MPU_TABLE1_M  ((DPORT_ROM_MPU_TABLE1_V)<<(DPORT_ROM_MPU_TABLE1_S))
+#define DPORT_ROM_MPU_TABLE1_V  0x3
+#define DPORT_ROM_MPU_TABLE1_S  0
+
+#define DPORT_ROM_MPU_TABLE2_REG          (DR_REG_DPORT_BASE + 0x49C)
+/* DPORT_ROM_MPU_TABLE2 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_ROM_MPU_TABLE2  0x00000003
+#define DPORT_ROM_MPU_TABLE2_M  ((DPORT_ROM_MPU_TABLE2_V)<<(DPORT_ROM_MPU_TABLE2_S))
+#define DPORT_ROM_MPU_TABLE2_V  0x3
+#define DPORT_ROM_MPU_TABLE2_S  0
+
+#define DPORT_ROM_MPU_TABLE3_REG          (DR_REG_DPORT_BASE + 0x4A0)
+/* DPORT_ROM_MPU_TABLE3 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_ROM_MPU_TABLE3  0x00000003
+#define DPORT_ROM_MPU_TABLE3_M  ((DPORT_ROM_MPU_TABLE3_V)<<(DPORT_ROM_MPU_TABLE3_S))
+#define DPORT_ROM_MPU_TABLE3_V  0x3
+#define DPORT_ROM_MPU_TABLE3_S  0
+
+#define DPORT_SHROM_MPU_TABLE0_REG          (DR_REG_DPORT_BASE + 0x4A4)
+/* DPORT_SHROM_MPU_TABLE0 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE0  0x00000003
+#define DPORT_SHROM_MPU_TABLE0_M  ((DPORT_SHROM_MPU_TABLE0_V)<<(DPORT_SHROM_MPU_TABLE0_S))
+#define DPORT_SHROM_MPU_TABLE0_V  0x3
+#define DPORT_SHROM_MPU_TABLE0_S  0
+
+#define DPORT_SHROM_MPU_TABLE1_REG          (DR_REG_DPORT_BASE + 0x4A8)
+/* DPORT_SHROM_MPU_TABLE1 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE1  0x00000003
+#define DPORT_SHROM_MPU_TABLE1_M  ((DPORT_SHROM_MPU_TABLE1_V)<<(DPORT_SHROM_MPU_TABLE1_S))
+#define DPORT_SHROM_MPU_TABLE1_V  0x3
+#define DPORT_SHROM_MPU_TABLE1_S  0
+
+#define DPORT_SHROM_MPU_TABLE2_REG          (DR_REG_DPORT_BASE + 0x4AC)
+/* DPORT_SHROM_MPU_TABLE2 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE2  0x00000003
+#define DPORT_SHROM_MPU_TABLE2_M  ((DPORT_SHROM_MPU_TABLE2_V)<<(DPORT_SHROM_MPU_TABLE2_S))
+#define DPORT_SHROM_MPU_TABLE2_V  0x3
+#define DPORT_SHROM_MPU_TABLE2_S  0
+
+#define DPORT_SHROM_MPU_TABLE3_REG          (DR_REG_DPORT_BASE + 0x4B0)
+/* DPORT_SHROM_MPU_TABLE3 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE3  0x00000003
+#define DPORT_SHROM_MPU_TABLE3_M  ((DPORT_SHROM_MPU_TABLE3_V)<<(DPORT_SHROM_MPU_TABLE3_S))
+#define DPORT_SHROM_MPU_TABLE3_V  0x3
+#define DPORT_SHROM_MPU_TABLE3_S  0
+
+#define DPORT_SHROM_MPU_TABLE4_REG          (DR_REG_DPORT_BASE + 0x4B4)
+/* DPORT_SHROM_MPU_TABLE4 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE4  0x00000003
+#define DPORT_SHROM_MPU_TABLE4_M  ((DPORT_SHROM_MPU_TABLE4_V)<<(DPORT_SHROM_MPU_TABLE4_S))
+#define DPORT_SHROM_MPU_TABLE4_V  0x3
+#define DPORT_SHROM_MPU_TABLE4_S  0
+
+#define DPORT_SHROM_MPU_TABLE5_REG          (DR_REG_DPORT_BASE + 0x4B8)
+/* DPORT_SHROM_MPU_TABLE5 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE5  0x00000003
+#define DPORT_SHROM_MPU_TABLE5_M  ((DPORT_SHROM_MPU_TABLE5_V)<<(DPORT_SHROM_MPU_TABLE5_S))
+#define DPORT_SHROM_MPU_TABLE5_V  0x3
+#define DPORT_SHROM_MPU_TABLE5_S  0
+
+#define DPORT_SHROM_MPU_TABLE6_REG          (DR_REG_DPORT_BASE + 0x4BC)
+/* DPORT_SHROM_MPU_TABLE6 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE6  0x00000003
+#define DPORT_SHROM_MPU_TABLE6_M  ((DPORT_SHROM_MPU_TABLE6_V)<<(DPORT_SHROM_MPU_TABLE6_S))
+#define DPORT_SHROM_MPU_TABLE6_V  0x3
+#define DPORT_SHROM_MPU_TABLE6_S  0
+
+#define DPORT_SHROM_MPU_TABLE7_REG          (DR_REG_DPORT_BASE + 0x4C0)
+/* DPORT_SHROM_MPU_TABLE7 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE7  0x00000003
+#define DPORT_SHROM_MPU_TABLE7_M  ((DPORT_SHROM_MPU_TABLE7_V)<<(DPORT_SHROM_MPU_TABLE7_S))
+#define DPORT_SHROM_MPU_TABLE7_V  0x3
+#define DPORT_SHROM_MPU_TABLE7_S  0
+
+#define DPORT_SHROM_MPU_TABLE8_REG          (DR_REG_DPORT_BASE + 0x4C4)
+/* DPORT_SHROM_MPU_TABLE8 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE8  0x00000003
+#define DPORT_SHROM_MPU_TABLE8_M  ((DPORT_SHROM_MPU_TABLE8_V)<<(DPORT_SHROM_MPU_TABLE8_S))
+#define DPORT_SHROM_MPU_TABLE8_V  0x3
+#define DPORT_SHROM_MPU_TABLE8_S  0
+
+#define DPORT_SHROM_MPU_TABLE9_REG          (DR_REG_DPORT_BASE + 0x4C8)
+/* DPORT_SHROM_MPU_TABLE9 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE9  0x00000003
+#define DPORT_SHROM_MPU_TABLE9_M  ((DPORT_SHROM_MPU_TABLE9_V)<<(DPORT_SHROM_MPU_TABLE9_S))
+#define DPORT_SHROM_MPU_TABLE9_V  0x3
+#define DPORT_SHROM_MPU_TABLE9_S  0
+
+#define DPORT_SHROM_MPU_TABLE10_REG          (DR_REG_DPORT_BASE + 0x4CC)
+/* DPORT_SHROM_MPU_TABLE10 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE10  0x00000003
+#define DPORT_SHROM_MPU_TABLE10_M  ((DPORT_SHROM_MPU_TABLE10_V)<<(DPORT_SHROM_MPU_TABLE10_S))
+#define DPORT_SHROM_MPU_TABLE10_V  0x3
+#define DPORT_SHROM_MPU_TABLE10_S  0
+
+#define DPORT_SHROM_MPU_TABLE11_REG          (DR_REG_DPORT_BASE + 0x4D0)
+/* DPORT_SHROM_MPU_TABLE11 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE11  0x00000003
+#define DPORT_SHROM_MPU_TABLE11_M  ((DPORT_SHROM_MPU_TABLE11_V)<<(DPORT_SHROM_MPU_TABLE11_S))
+#define DPORT_SHROM_MPU_TABLE11_V  0x3
+#define DPORT_SHROM_MPU_TABLE11_S  0
+
+#define DPORT_SHROM_MPU_TABLE12_REG          (DR_REG_DPORT_BASE + 0x4D4)
+/* DPORT_SHROM_MPU_TABLE12 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE12  0x00000003
+#define DPORT_SHROM_MPU_TABLE12_M  ((DPORT_SHROM_MPU_TABLE12_V)<<(DPORT_SHROM_MPU_TABLE12_S))
+#define DPORT_SHROM_MPU_TABLE12_V  0x3
+#define DPORT_SHROM_MPU_TABLE12_S  0
+
+#define DPORT_SHROM_MPU_TABLE13_REG          (DR_REG_DPORT_BASE + 0x4D8)
+/* DPORT_SHROM_MPU_TABLE13 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE13  0x00000003
+#define DPORT_SHROM_MPU_TABLE13_M  ((DPORT_SHROM_MPU_TABLE13_V)<<(DPORT_SHROM_MPU_TABLE13_S))
+#define DPORT_SHROM_MPU_TABLE13_V  0x3
+#define DPORT_SHROM_MPU_TABLE13_S  0
+
+#define DPORT_SHROM_MPU_TABLE14_REG          (DR_REG_DPORT_BASE + 0x4DC)
+/* DPORT_SHROM_MPU_TABLE14 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE14  0x00000003
+#define DPORT_SHROM_MPU_TABLE14_M  ((DPORT_SHROM_MPU_TABLE14_V)<<(DPORT_SHROM_MPU_TABLE14_S))
+#define DPORT_SHROM_MPU_TABLE14_V  0x3
+#define DPORT_SHROM_MPU_TABLE14_S  0
+
+#define DPORT_SHROM_MPU_TABLE15_REG          (DR_REG_DPORT_BASE + 0x4E0)
+/* DPORT_SHROM_MPU_TABLE15 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE15  0x00000003
+#define DPORT_SHROM_MPU_TABLE15_M  ((DPORT_SHROM_MPU_TABLE15_V)<<(DPORT_SHROM_MPU_TABLE15_S))
+#define DPORT_SHROM_MPU_TABLE15_V  0x3
+#define DPORT_SHROM_MPU_TABLE15_S  0
+
+#define DPORT_SHROM_MPU_TABLE16_REG          (DR_REG_DPORT_BASE + 0x4E4)
+/* DPORT_SHROM_MPU_TABLE16 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE16  0x00000003
+#define DPORT_SHROM_MPU_TABLE16_M  ((DPORT_SHROM_MPU_TABLE16_V)<<(DPORT_SHROM_MPU_TABLE16_S))
+#define DPORT_SHROM_MPU_TABLE16_V  0x3
+#define DPORT_SHROM_MPU_TABLE16_S  0
+
+#define DPORT_SHROM_MPU_TABLE17_REG          (DR_REG_DPORT_BASE + 0x4E8)
+/* DPORT_SHROM_MPU_TABLE17 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE17  0x00000003
+#define DPORT_SHROM_MPU_TABLE17_M  ((DPORT_SHROM_MPU_TABLE17_V)<<(DPORT_SHROM_MPU_TABLE17_S))
+#define DPORT_SHROM_MPU_TABLE17_V  0x3
+#define DPORT_SHROM_MPU_TABLE17_S  0
+
+#define DPORT_SHROM_MPU_TABLE18_REG          (DR_REG_DPORT_BASE + 0x4EC)
+/* DPORT_SHROM_MPU_TABLE18 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE18  0x00000003
+#define DPORT_SHROM_MPU_TABLE18_M  ((DPORT_SHROM_MPU_TABLE18_V)<<(DPORT_SHROM_MPU_TABLE18_S))
+#define DPORT_SHROM_MPU_TABLE18_V  0x3
+#define DPORT_SHROM_MPU_TABLE18_S  0
+
+#define DPORT_SHROM_MPU_TABLE19_REG          (DR_REG_DPORT_BASE + 0x4F0)
+/* DPORT_SHROM_MPU_TABLE19 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE19  0x00000003
+#define DPORT_SHROM_MPU_TABLE19_M  ((DPORT_SHROM_MPU_TABLE19_V)<<(DPORT_SHROM_MPU_TABLE19_S))
+#define DPORT_SHROM_MPU_TABLE19_V  0x3
+#define DPORT_SHROM_MPU_TABLE19_S  0
+
+#define DPORT_SHROM_MPU_TABLE20_REG          (DR_REG_DPORT_BASE + 0x4F4)
+/* DPORT_SHROM_MPU_TABLE20 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE20  0x00000003
+#define DPORT_SHROM_MPU_TABLE20_M  ((DPORT_SHROM_MPU_TABLE20_V)<<(DPORT_SHROM_MPU_TABLE20_S))
+#define DPORT_SHROM_MPU_TABLE20_V  0x3
+#define DPORT_SHROM_MPU_TABLE20_S  0
+
+#define DPORT_SHROM_MPU_TABLE21_REG          (DR_REG_DPORT_BASE + 0x4F8)
+/* DPORT_SHROM_MPU_TABLE21 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE21  0x00000003
+#define DPORT_SHROM_MPU_TABLE21_M  ((DPORT_SHROM_MPU_TABLE21_V)<<(DPORT_SHROM_MPU_TABLE21_S))
+#define DPORT_SHROM_MPU_TABLE21_V  0x3
+#define DPORT_SHROM_MPU_TABLE21_S  0
+
+#define DPORT_SHROM_MPU_TABLE22_REG          (DR_REG_DPORT_BASE + 0x4FC)
+/* DPORT_SHROM_MPU_TABLE22 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE22  0x00000003
+#define DPORT_SHROM_MPU_TABLE22_M  ((DPORT_SHROM_MPU_TABLE22_V)<<(DPORT_SHROM_MPU_TABLE22_S))
+#define DPORT_SHROM_MPU_TABLE22_V  0x3
+#define DPORT_SHROM_MPU_TABLE22_S  0
+
+#define DPORT_SHROM_MPU_TABLE23_REG          (DR_REG_DPORT_BASE + 0x500)
+/* DPORT_SHROM_MPU_TABLE23 : R/W ;bitpos:[1:0] ;default: 2'b1 ; */
+/*description: */
+#define DPORT_SHROM_MPU_TABLE23  0x00000003
+#define DPORT_SHROM_MPU_TABLE23_M  ((DPORT_SHROM_MPU_TABLE23_V)<<(DPORT_SHROM_MPU_TABLE23_S))
+#define DPORT_SHROM_MPU_TABLE23_V  0x3
+#define DPORT_SHROM_MPU_TABLE23_S  0
+
+#define DPORT_IMMU_TABLE0_REG          (DR_REG_DPORT_BASE + 0x504)
+/* DPORT_IMMU_TABLE0 : R/W ;bitpos:[6:0] ;default: 7'd0 ; */
+/*description: */
+#define DPORT_IMMU_TABLE0  0x0000007F
+#define DPORT_IMMU_TABLE0_M  ((DPORT_IMMU_TABLE0_V)<<(DPORT_IMMU_TABLE0_S))
+#define DPORT_IMMU_TABLE0_V  0x7F
+#define DPORT_IMMU_TABLE0_S  0
+
+#define DPORT_IMMU_TABLE1_REG          (DR_REG_DPORT_BASE + 0x508)
+/* DPORT_IMMU_TABLE1 : R/W ;bitpos:[6:0] ;default: 7'd1 ; */
+/*description: */
+#define DPORT_IMMU_TABLE1  0x0000007F
+#define DPORT_IMMU_TABLE1_M  ((DPORT_IMMU_TABLE1_V)<<(DPORT_IMMU_TABLE1_S))
+#define DPORT_IMMU_TABLE1_V  0x7F
+#define DPORT_IMMU_TABLE1_S  0
+
+#define DPORT_IMMU_TABLE2_REG          (DR_REG_DPORT_BASE + 0x50C)
+/* DPORT_IMMU_TABLE2 : R/W ;bitpos:[6:0] ;default: 7'd2 ; */
+/*description: */
+#define DPORT_IMMU_TABLE2  0x0000007F
+#define DPORT_IMMU_TABLE2_M  ((DPORT_IMMU_TABLE2_V)<<(DPORT_IMMU_TABLE2_S))
+#define DPORT_IMMU_TABLE2_V  0x7F
+#define DPORT_IMMU_TABLE2_S  0
+
+#define DPORT_IMMU_TABLE3_REG          (DR_REG_DPORT_BASE + 0x510)
+/* DPORT_IMMU_TABLE3 : R/W ;bitpos:[6:0] ;default: 7'd3 ; */
+/*description: */
+#define DPORT_IMMU_TABLE3  0x0000007F
+#define DPORT_IMMU_TABLE3_M  ((DPORT_IMMU_TABLE3_V)<<(DPORT_IMMU_TABLE3_S))
+#define DPORT_IMMU_TABLE3_V  0x7F
+#define DPORT_IMMU_TABLE3_S  0
+
+#define DPORT_IMMU_TABLE4_REG          (DR_REG_DPORT_BASE + 0x514)
+/* DPORT_IMMU_TABLE4 : R/W ;bitpos:[6:0] ;default: 7'd4 ; */
+/*description: */
+#define DPORT_IMMU_TABLE4  0x0000007F
+#define DPORT_IMMU_TABLE4_M  ((DPORT_IMMU_TABLE4_V)<<(DPORT_IMMU_TABLE4_S))
+#define DPORT_IMMU_TABLE4_V  0x7F
+#define DPORT_IMMU_TABLE4_S  0
+
+#define DPORT_IMMU_TABLE5_REG          (DR_REG_DPORT_BASE + 0x518)
+/* DPORT_IMMU_TABLE5 : R/W ;bitpos:[6:0] ;default: 7'd5 ; */
+/*description: */
+#define DPORT_IMMU_TABLE5  0x0000007F
+#define DPORT_IMMU_TABLE5_M  ((DPORT_IMMU_TABLE5_V)<<(DPORT_IMMU_TABLE5_S))
+#define DPORT_IMMU_TABLE5_V  0x7F
+#define DPORT_IMMU_TABLE5_S  0
+
+#define DPORT_IMMU_TABLE6_REG          (DR_REG_DPORT_BASE + 0x51C)
+/* DPORT_IMMU_TABLE6 : R/W ;bitpos:[6:0] ;default: 7'd6 ; */
+/*description: */
+#define DPORT_IMMU_TABLE6  0x0000007F
+#define DPORT_IMMU_TABLE6_M  ((DPORT_IMMU_TABLE6_V)<<(DPORT_IMMU_TABLE6_S))
+#define DPORT_IMMU_TABLE6_V  0x7F
+#define DPORT_IMMU_TABLE6_S  0
+
+#define DPORT_IMMU_TABLE7_REG          (DR_REG_DPORT_BASE + 0x520)
+/* DPORT_IMMU_TABLE7 : R/W ;bitpos:[6:0] ;default: 7'd7 ; */
+/*description: */
+#define DPORT_IMMU_TABLE7  0x0000007F
+#define DPORT_IMMU_TABLE7_M  ((DPORT_IMMU_TABLE7_V)<<(DPORT_IMMU_TABLE7_S))
+#define DPORT_IMMU_TABLE7_V  0x7F
+#define DPORT_IMMU_TABLE7_S  0
+
+#define DPORT_IMMU_TABLE8_REG          (DR_REG_DPORT_BASE + 0x524)
+/* DPORT_IMMU_TABLE8 : R/W ;bitpos:[6:0] ;default: 7'd8 ; */
+/*description: */
+#define DPORT_IMMU_TABLE8  0x0000007F
+#define DPORT_IMMU_TABLE8_M  ((DPORT_IMMU_TABLE8_V)<<(DPORT_IMMU_TABLE8_S))
+#define DPORT_IMMU_TABLE8_V  0x7F
+#define DPORT_IMMU_TABLE8_S  0
+
+#define DPORT_IMMU_TABLE9_REG          (DR_REG_DPORT_BASE + 0x528)
+/* DPORT_IMMU_TABLE9 : R/W ;bitpos:[6:0] ;default: 7'd9 ; */
+/*description: */
+#define DPORT_IMMU_TABLE9  0x0000007F
+#define DPORT_IMMU_TABLE9_M  ((DPORT_IMMU_TABLE9_V)<<(DPORT_IMMU_TABLE9_S))
+#define DPORT_IMMU_TABLE9_V  0x7F
+#define DPORT_IMMU_TABLE9_S  0
+
+#define DPORT_IMMU_TABLE10_REG          (DR_REG_DPORT_BASE + 0x52C)
+/* DPORT_IMMU_TABLE10 : R/W ;bitpos:[6:0] ;default: 7'd10 ; */
+/*description: */
+#define DPORT_IMMU_TABLE10  0x0000007F
+#define DPORT_IMMU_TABLE10_M  ((DPORT_IMMU_TABLE10_V)<<(DPORT_IMMU_TABLE10_S))
+#define DPORT_IMMU_TABLE10_V  0x7F
+#define DPORT_IMMU_TABLE10_S  0
+
+#define DPORT_IMMU_TABLE11_REG          (DR_REG_DPORT_BASE + 0x530)
+/* DPORT_IMMU_TABLE11 : R/W ;bitpos:[6:0] ;default: 7'd11 ; */
+/*description: */
+#define DPORT_IMMU_TABLE11  0x0000007F
+#define DPORT_IMMU_TABLE11_M  ((DPORT_IMMU_TABLE11_V)<<(DPORT_IMMU_TABLE11_S))
+#define DPORT_IMMU_TABLE11_V  0x7F
+#define DPORT_IMMU_TABLE11_S  0
+
+#define DPORT_IMMU_TABLE12_REG          (DR_REG_DPORT_BASE + 0x534)
+/* DPORT_IMMU_TABLE12 : R/W ;bitpos:[6:0] ;default: 7'd12 ; */
+/*description: */
+#define DPORT_IMMU_TABLE12  0x0000007F
+#define DPORT_IMMU_TABLE12_M  ((DPORT_IMMU_TABLE12_V)<<(DPORT_IMMU_TABLE12_S))
+#define DPORT_IMMU_TABLE12_V  0x7F
+#define DPORT_IMMU_TABLE12_S  0
+
+#define DPORT_IMMU_TABLE13_REG          (DR_REG_DPORT_BASE + 0x538)
+/* DPORT_IMMU_TABLE13 : R/W ;bitpos:[6:0] ;default: 7'd13 ; */
+/*description: */
+#define DPORT_IMMU_TABLE13  0x0000007F
+#define DPORT_IMMU_TABLE13_M  ((DPORT_IMMU_TABLE13_V)<<(DPORT_IMMU_TABLE13_S))
+#define DPORT_IMMU_TABLE13_V  0x7F
+#define DPORT_IMMU_TABLE13_S  0
+
+#define DPORT_IMMU_TABLE14_REG          (DR_REG_DPORT_BASE + 0x53C)
+/* DPORT_IMMU_TABLE14 : R/W ;bitpos:[6:0] ;default: 7'd14 ; */
+/*description: */
+#define DPORT_IMMU_TABLE14  0x0000007F
+#define DPORT_IMMU_TABLE14_M  ((DPORT_IMMU_TABLE14_V)<<(DPORT_IMMU_TABLE14_S))
+#define DPORT_IMMU_TABLE14_V  0x7F
+#define DPORT_IMMU_TABLE14_S  0
+
+#define DPORT_IMMU_TABLE15_REG          (DR_REG_DPORT_BASE + 0x540)
+/* DPORT_IMMU_TABLE15 : R/W ;bitpos:[6:0] ;default: 7'd15 ; */
+/*description: */
+#define DPORT_IMMU_TABLE15  0x0000007F
+#define DPORT_IMMU_TABLE15_M  ((DPORT_IMMU_TABLE15_V)<<(DPORT_IMMU_TABLE15_S))
+#define DPORT_IMMU_TABLE15_V  0x7F
+#define DPORT_IMMU_TABLE15_S  0
+
+#define DPORT_DMMU_TABLE0_REG          (DR_REG_DPORT_BASE + 0x544)
+/* DPORT_DMMU_TABLE0 : R/W ;bitpos:[6:0] ;default: 7'd0 ; */
+/*description: */
+#define DPORT_DMMU_TABLE0  0x0000007F
+#define DPORT_DMMU_TABLE0_M  ((DPORT_DMMU_TABLE0_V)<<(DPORT_DMMU_TABLE0_S))
+#define DPORT_DMMU_TABLE0_V  0x7F
+#define DPORT_DMMU_TABLE0_S  0
+
+#define DPORT_DMMU_TABLE1_REG          (DR_REG_DPORT_BASE + 0x548)
+/* DPORT_DMMU_TABLE1 : R/W ;bitpos:[6:0] ;default: 7'd1 ; */
+/*description: */
+#define DPORT_DMMU_TABLE1  0x0000007F
+#define DPORT_DMMU_TABLE1_M  ((DPORT_DMMU_TABLE1_V)<<(DPORT_DMMU_TABLE1_S))
+#define DPORT_DMMU_TABLE1_V  0x7F
+#define DPORT_DMMU_TABLE1_S  0
+
+#define DPORT_DMMU_TABLE2_REG          (DR_REG_DPORT_BASE + 0x54C)
+/* DPORT_DMMU_TABLE2 : R/W ;bitpos:[6:0] ;default: 7'd2 ; */
+/*description: */
+#define DPORT_DMMU_TABLE2  0x0000007F
+#define DPORT_DMMU_TABLE2_M  ((DPORT_DMMU_TABLE2_V)<<(DPORT_DMMU_TABLE2_S))
+#define DPORT_DMMU_TABLE2_V  0x7F
+#define DPORT_DMMU_TABLE2_S  0
+
+#define DPORT_DMMU_TABLE3_REG          (DR_REG_DPORT_BASE + 0x550)
+/* DPORT_DMMU_TABLE3 : R/W ;bitpos:[6:0] ;default: 7'd3 ; */
+/*description: */
+#define DPORT_DMMU_TABLE3  0x0000007F
+#define DPORT_DMMU_TABLE3_M  ((DPORT_DMMU_TABLE3_V)<<(DPORT_DMMU_TABLE3_S))
+#define DPORT_DMMU_TABLE3_V  0x7F
+#define DPORT_DMMU_TABLE3_S  0
+
+#define DPORT_DMMU_TABLE4_REG          (DR_REG_DPORT_BASE + 0x554)
+/* DPORT_DMMU_TABLE4 : R/W ;bitpos:[6:0] ;default: 7'd4 ; */
+/*description: */
+#define DPORT_DMMU_TABLE4  0x0000007F
+#define DPORT_DMMU_TABLE4_M  ((DPORT_DMMU_TABLE4_V)<<(DPORT_DMMU_TABLE4_S))
+#define DPORT_DMMU_TABLE4_V  0x7F
+#define DPORT_DMMU_TABLE4_S  0
+
+#define DPORT_DMMU_TABLE5_REG          (DR_REG_DPORT_BASE + 0x558)
+/* DPORT_DMMU_TABLE5 : R/W ;bitpos:[6:0] ;default: 7'd5 ; */
+/*description: */
+#define DPORT_DMMU_TABLE5  0x0000007F
+#define DPORT_DMMU_TABLE5_M  ((DPORT_DMMU_TABLE5_V)<<(DPORT_DMMU_TABLE5_S))
+#define DPORT_DMMU_TABLE5_V  0x7F
+#define DPORT_DMMU_TABLE5_S  0
+
+#define DPORT_DMMU_TABLE6_REG          (DR_REG_DPORT_BASE + 0x55C)
+/* DPORT_DMMU_TABLE6 : R/W ;bitpos:[6:0] ;default: 7'd6 ; */
+/*description: */
+#define DPORT_DMMU_TABLE6  0x0000007F
+#define DPORT_DMMU_TABLE6_M  ((DPORT_DMMU_TABLE6_V)<<(DPORT_DMMU_TABLE6_S))
+#define DPORT_DMMU_TABLE6_V  0x7F
+#define DPORT_DMMU_TABLE6_S  0
+
+#define DPORT_DMMU_TABLE7_REG          (DR_REG_DPORT_BASE + 0x560)
+/* DPORT_DMMU_TABLE7 : R/W ;bitpos:[6:0] ;default: 7'd7 ; */
+/*description: */
+#define DPORT_DMMU_TABLE7  0x0000007F
+#define DPORT_DMMU_TABLE7_M  ((DPORT_DMMU_TABLE7_V)<<(DPORT_DMMU_TABLE7_S))
+#define DPORT_DMMU_TABLE7_V  0x7F
+#define DPORT_DMMU_TABLE7_S  0
+
+#define DPORT_DMMU_TABLE8_REG          (DR_REG_DPORT_BASE + 0x564)
+/* DPORT_DMMU_TABLE8 : R/W ;bitpos:[6:0] ;default: 7'd8 ; */
+/*description: */
+#define DPORT_DMMU_TABLE8  0x0000007F
+#define DPORT_DMMU_TABLE8_M  ((DPORT_DMMU_TABLE8_V)<<(DPORT_DMMU_TABLE8_S))
+#define DPORT_DMMU_TABLE8_V  0x7F
+#define DPORT_DMMU_TABLE8_S  0
+
+#define DPORT_DMMU_TABLE9_REG          (DR_REG_DPORT_BASE + 0x568)
+/* DPORT_DMMU_TABLE9 : R/W ;bitpos:[6:0] ;default: 7'd9 ; */
+/*description: */
+#define DPORT_DMMU_TABLE9  0x0000007F
+#define DPORT_DMMU_TABLE9_M  ((DPORT_DMMU_TABLE9_V)<<(DPORT_DMMU_TABLE9_S))
+#define DPORT_DMMU_TABLE9_V  0x7F
+#define DPORT_DMMU_TABLE9_S  0
+
+#define DPORT_DMMU_TABLE10_REG          (DR_REG_DPORT_BASE + 0x56C)
+/* DPORT_DMMU_TABLE10 : R/W ;bitpos:[6:0] ;default: 7'd10 ; */
+/*description: */
+#define DPORT_DMMU_TABLE10  0x0000007F
+#define DPORT_DMMU_TABLE10_M  ((DPORT_DMMU_TABLE10_V)<<(DPORT_DMMU_TABLE10_S))
+#define DPORT_DMMU_TABLE10_V  0x7F
+#define DPORT_DMMU_TABLE10_S  0
+
+#define DPORT_DMMU_TABLE11_REG          (DR_REG_DPORT_BASE + 0x570)
+/* DPORT_DMMU_TABLE11 : R/W ;bitpos:[6:0] ;default: 7'd11 ; */
+/*description: */
+#define DPORT_DMMU_TABLE11  0x0000007F
+#define DPORT_DMMU_TABLE11_M  ((DPORT_DMMU_TABLE11_V)<<(DPORT_DMMU_TABLE11_S))
+#define DPORT_DMMU_TABLE11_V  0x7F
+#define DPORT_DMMU_TABLE11_S  0
+
+#define DPORT_DMMU_TABLE12_REG          (DR_REG_DPORT_BASE + 0x574)
+/* DPORT_DMMU_TABLE12 : R/W ;bitpos:[6:0] ;default: 7'd12 ; */
+/*description: */
+#define DPORT_DMMU_TABLE12  0x0000007F
+#define DPORT_DMMU_TABLE12_M  ((DPORT_DMMU_TABLE12_V)<<(DPORT_DMMU_TABLE12_S))
+#define DPORT_DMMU_TABLE12_V  0x7F
+#define DPORT_DMMU_TABLE12_S  0
+
+#define DPORT_DMMU_TABLE13_REG          (DR_REG_DPORT_BASE + 0x578)
+/* DPORT_DMMU_TABLE13 : R/W ;bitpos:[6:0] ;default: 7'd13 ; */
+/*description: */
+#define DPORT_DMMU_TABLE13  0x0000007F
+#define DPORT_DMMU_TABLE13_M  ((DPORT_DMMU_TABLE13_V)<<(DPORT_DMMU_TABLE13_S))
+#define DPORT_DMMU_TABLE13_V  0x7F
+#define DPORT_DMMU_TABLE13_S  0
+
+#define DPORT_DMMU_TABLE14_REG          (DR_REG_DPORT_BASE + 0x57C)
+/* DPORT_DMMU_TABLE14 : R/W ;bitpos:[6:0] ;default: 7'd14 ; */
+/*description: */
+#define DPORT_DMMU_TABLE14  0x0000007F
+#define DPORT_DMMU_TABLE14_M  ((DPORT_DMMU_TABLE14_V)<<(DPORT_DMMU_TABLE14_S))
+#define DPORT_DMMU_TABLE14_V  0x7F
+#define DPORT_DMMU_TABLE14_S  0
+
+#define DPORT_DMMU_TABLE15_REG          (DR_REG_DPORT_BASE + 0x580)
+/* DPORT_DMMU_TABLE15 : R/W ;bitpos:[6:0] ;default: 7'd15 ; */
+/*description: */
+#define DPORT_DMMU_TABLE15  0x0000007F
+#define DPORT_DMMU_TABLE15_M  ((DPORT_DMMU_TABLE15_V)<<(DPORT_DMMU_TABLE15_S))
+#define DPORT_DMMU_TABLE15_V  0x7F
+#define DPORT_DMMU_TABLE15_S  0
+
+#define DPORT_PRO_INTRUSION_CTRL_REG          (DR_REG_DPORT_BASE + 0x584)
+/* DPORT_PRO_INTRUSION_RECORD_RESET_N : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PRO_INTRUSION_RECORD_RESET_N  (BIT(0))
+#define DPORT_PRO_INTRUSION_RECORD_RESET_N_M  (BIT(0))
+#define DPORT_PRO_INTRUSION_RECORD_RESET_N_V  0x1
+#define DPORT_PRO_INTRUSION_RECORD_RESET_N_S  0
+
+#define DPORT_PRO_INTRUSION_STATUS_REG          (DR_REG_DPORT_BASE + 0x588)
+/* DPORT_PRO_INTRUSION_RECORD : RO ;bitpos:[3:0] ;default: 4'b0 ; */
+/*description: */
+#define DPORT_PRO_INTRUSION_RECORD  0x0000000F
+#define DPORT_PRO_INTRUSION_RECORD_M  ((DPORT_PRO_INTRUSION_RECORD_V)<<(DPORT_PRO_INTRUSION_RECORD_S))
+#define DPORT_PRO_INTRUSION_RECORD_V  0xF
+#define DPORT_PRO_INTRUSION_RECORD_S  0
+
+#define DPORT_APP_INTRUSION_CTRL_REG          (DR_REG_DPORT_BASE + 0x58C)
+/* DPORT_APP_INTRUSION_RECORD_RESET_N : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_APP_INTRUSION_RECORD_RESET_N  (BIT(0))
+#define DPORT_APP_INTRUSION_RECORD_RESET_N_M  (BIT(0))
+#define DPORT_APP_INTRUSION_RECORD_RESET_N_V  0x1
+#define DPORT_APP_INTRUSION_RECORD_RESET_N_S  0
+
+#define DPORT_APP_INTRUSION_STATUS_REG          (DR_REG_DPORT_BASE + 0x590)
+/* DPORT_APP_INTRUSION_RECORD : RO ;bitpos:[3:0] ;default: 4'b0 ; */
+/*description: */
+#define DPORT_APP_INTRUSION_RECORD  0x0000000F
+#define DPORT_APP_INTRUSION_RECORD_M  ((DPORT_APP_INTRUSION_RECORD_V)<<(DPORT_APP_INTRUSION_RECORD_S))
+#define DPORT_APP_INTRUSION_RECORD_V  0xF
+#define DPORT_APP_INTRUSION_RECORD_S  0
+
+#define DPORT_FRONT_END_MEM_PD_REG          (DR_REG_DPORT_BASE + 0x594)
+/* DPORT_PBUS_MEM_FORCE_PD : R/W ;bitpos:[3] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_PBUS_MEM_FORCE_PD  (BIT(3))
+#define DPORT_PBUS_MEM_FORCE_PD_M  (BIT(3))
+#define DPORT_PBUS_MEM_FORCE_PD_V  0x1
+#define DPORT_PBUS_MEM_FORCE_PD_S  3
+/* DPORT_PBUS_MEM_FORCE_PU : R/W ;bitpos:[2] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_PBUS_MEM_FORCE_PU  (BIT(2))
+#define DPORT_PBUS_MEM_FORCE_PU_M  (BIT(2))
+#define DPORT_PBUS_MEM_FORCE_PU_V  0x1
+#define DPORT_PBUS_MEM_FORCE_PU_S  2
+/* DPORT_AGC_MEM_FORCE_PD : R/W ;bitpos:[1] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_AGC_MEM_FORCE_PD  (BIT(1))
+#define DPORT_AGC_MEM_FORCE_PD_M  (BIT(1))
+#define DPORT_AGC_MEM_FORCE_PD_V  0x1
+#define DPORT_AGC_MEM_FORCE_PD_S  1
+/* DPORT_AGC_MEM_FORCE_PU : R/W ;bitpos:[0] ;default: 1'b1 ; */
+/*description: */
+#define DPORT_AGC_MEM_FORCE_PU  (BIT(0))
+#define DPORT_AGC_MEM_FORCE_PU_M  (BIT(0))
+#define DPORT_AGC_MEM_FORCE_PU_V  0x1
+#define DPORT_AGC_MEM_FORCE_PU_S  0
+
+#define DPORT_MMU_IA_INT_EN_REG          (DR_REG_DPORT_BASE + 0x598)
+/* DPORT_MMU_IA_INT_EN : R/W ;bitpos:[23:0] ;default: 24'b0 ; */
+/*description: */
+#define DPORT_MMU_IA_INT_EN  0x00FFFFFF
+#define DPORT_MMU_IA_INT_EN_M  ((DPORT_MMU_IA_INT_EN_V)<<(DPORT_MMU_IA_INT_EN_S))
+#define DPORT_MMU_IA_INT_EN_V  0xFFFFFF
+#define DPORT_MMU_IA_INT_EN_S  0
+
+#define DPORT_MPU_IA_INT_EN_REG          (DR_REG_DPORT_BASE + 0x59C)
+/* DPORT_MPU_IA_INT_EN : R/W ;bitpos:[16:0] ;default: 17'b0 ; */
+/*description: */
+#define DPORT_MPU_IA_INT_EN  0x0001FFFF
+#define DPORT_MPU_IA_INT_EN_M  ((DPORT_MPU_IA_INT_EN_V)<<(DPORT_MPU_IA_INT_EN_S))
+#define DPORT_MPU_IA_INT_EN_V  0x1FFFF
+#define DPORT_MPU_IA_INT_EN_S  0
+
+#define DPORT_CACHE_IA_INT_EN_REG          (DR_REG_DPORT_BASE + 0x5A0)
+/* DPORT_CACHE_IA_INT_EN : R/W ;bitpos:[27:0] ;default: 28'b0 ; */
+/*description: Interrupt enable bits for various invalid cache access reasons*/
+#define DPORT_CACHE_IA_INT_EN  0x0FFFFFFF
+#define DPORT_CACHE_IA_INT_EN_M  ((DPORT_CACHE_IA_INT_EN_V)<<(DPORT_CACHE_IA_INT_EN_S))
+#define DPORT_CACHE_IA_INT_EN_V  0xFFFFFFF
+#define DPORT_CACHE_IA_INT_EN_S  0
+/* Contents of DPORT_CACHE_IA_INT_EN field: */
+/* DPORT_CACHE_IA_INT_PRO_OPPOSITE : R/W ;bitpos:[19] ;default: 1'b0 ; */
+/*description: PRO CPU invalid access to APP CPU cache when cache disabled */
+#define DPORT_CACHE_IA_INT_PRO_OPPOSITE    BIT(19)
+#define DPORT_CACHE_IA_INT_PRO_OPPOSITE_M  BIT(19)
+#define DPORT_CACHE_IA_INT_PRO_OPPOSITE_V  (1)
+#define DPORT_CACHE_IA_INT_PRO_OPPOSITE_S  (19)
+/* DPORT_CACHE_IA_INT_PRO_DRAM1 : R/W ;bitpos:[18] ;default: 1'b0 ; */
+/*description: PRO CPU invalid access to DRAM1 when cache is disabled */
+#define DPORT_CACHE_IA_INT_PRO_DRAM1    BIT(18)
+#define DPORT_CACHE_IA_INT_PRO_DRAM1_M  BIT(18)
+#define DPORT_CACHE_IA_INT_PRO_DRAM1_V  (1)
+#define DPORT_CACHE_IA_INT_PRO_DRAM1_S  (18)
+/* DPORT_CACHE_IA_INT_PRO_IROM0 : R/W ;bitpos:[17] ;default: 1'b0 ; */
+/*description: PRO CPU invalid access to IROM0 when cache is disabled */
+#define DPORT_CACHE_IA_INT_PRO_IROM0    BIT(17)
+#define DPORT_CACHE_IA_INT_PRO_IROM0_M  BIT(17)
+#define DPORT_CACHE_IA_INT_PRO_IROM0_V  (1)
+#define DPORT_CACHE_IA_INT_PRO_IROM0_S  (17)
+/* DPORT_CACHE_IA_INT_PRO_IRAM1 : R/W ;bitpos:[16] ;default: 1'b0 ; */
+/*description: PRO CPU invalid access to IRAM1 when cache is disabled */
+#define DPORT_CACHE_IA_INT_PRO_IRAM1    BIT(16)
+#define DPORT_CACHE_IA_INT_PRO_IRAM1_M  BIT(16)
+#define DPORT_CACHE_IA_INT_PRO_IRAM1_V  (1)
+#define DPORT_CACHE_IA_INT_PRO_IRAM1_S  (16)
+/* DPORT_CACHE_IA_INT_PRO_IRAM0 : R/W ;bitpos:[15] ;default: 1'b0 ; */
+/*description: PRO CPU invalid access to IRAM0 when cache is disabled */
+#define DPORT_CACHE_IA_INT_PRO_IRAM0    BIT(15)
+#define DPORT_CACHE_IA_INT_PRO_IRAM0_M  BIT(15)
+#define DPORT_CACHE_IA_INT_PRO_IRAM0_V  (1)
+#define DPORT_CACHE_IA_INT_PRO_IRAM0_S  (15)
+/* DPORT_CACHE_IA_INT_PRO_DROM0 : R/W ;bitpos:[14] ;default: 1'b0 ; */
+/*description: PRO CPU invalid access to DROM0 when cache is disabled */
+#define DPORT_CACHE_IA_INT_PRO_DROM0    BIT(14)
+#define DPORT_CACHE_IA_INT_PRO_DROM0_M  BIT(14)
+#define DPORT_CACHE_IA_INT_PRO_DROM0_V  (1)
+#define DPORT_CACHE_IA_INT_PRO_DROM0_S  (14)
+/* DPORT_CACHE_IA_INT_APP_OPPOSITE : R/W ;bitpos:[5] ;default: 1'b0 ; */
+/*description: APP CPU invalid access to APP CPU cache when cache disabled */
+#define DPORT_CACHE_IA_INT_APP_OPPOSITE    BIT(5)
+#define DPORT_CACHE_IA_INT_APP_OPPOSITE_M  BIT(5)
+#define DPORT_CACHE_IA_INT_APP_OPPOSITE_V  (1)
+#define DPORT_CACHE_IA_INT_APP_OPPOSITE_S  (5)
+/* DPORT_CACHE_IA_INT_APP_DRAM1 : R/W ;bitpos:43] ;default: 1'b0 ; */
+/*description: APP CPU invalid access to DRAM1 when cache is disabled */
+#define DPORT_CACHE_IA_INT_APP_DRAM1    BIT(4)
+#define DPORT_CACHE_IA_INT_APP_DRAM1_M  BIT(4)
+#define DPORT_CACHE_IA_INT_APP_DRAM1_V  (1)
+#define DPORT_CACHE_IA_INT_APP_DRAM1_S  (4)
+/* DPORT_CACHE_IA_INT_APP_IROM0 : R/W ;bitpos:[3] ;default: 1'b0 ; */
+/*description: APP CPU invalid access to IROM0 when cache is disabled */
+#define DPORT_CACHE_IA_INT_APP_IROM0    BIT(3)
+#define DPORT_CACHE_IA_INT_APP_IROM0_M  BIT(3)
+#define DPORT_CACHE_IA_INT_APP_IROM0_V  (1)
+#define DPORT_CACHE_IA_INT_APP_IROM0_S  (3)
+/* DPORT_CACHE_IA_INT_APP_IRAM1 : R/W ;bitpos:[2] ;default: 1'b0 ; */
+/*description: APP CPU invalid access to IRAM1 when cache is disabled */
+#define DPORT_CACHE_IA_INT_APP_IRAM1    BIT(2)
+#define DPORT_CACHE_IA_INT_APP_IRAM1_M  BIT(2)
+#define DPORT_CACHE_IA_INT_APP_IRAM1_V  (1)
+#define DPORT_CACHE_IA_INT_APP_IRAM1_S  (2)
+/* DPORT_CACHE_IA_INT_APP_IRAM0 : R/W ;bitpos:[1] ;default: 1'b0 ; */
+/*description: APP CPU invalid access to IRAM0 when cache is disabled */
+#define DPORT_CACHE_IA_INT_APP_IRAM0    BIT(1)
+#define DPORT_CACHE_IA_INT_APP_IRAM0_M  BIT(1)
+#define DPORT_CACHE_IA_INT_APP_IRAM0_V  (1)
+#define DPORT_CACHE_IA_INT_APP_IRAM0_S  (1)
+/* DPORT_CACHE_IA_INT_APP_DROM0 : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: APP CPU invalid access to DROM0 when cache is disabled */
+#define DPORT_CACHE_IA_INT_APP_DROM0    BIT(0)
+#define DPORT_CACHE_IA_INT_APP_DROM0_M  BIT(0)
+#define DPORT_CACHE_IA_INT_APP_DROM0_V  (1)
+#define DPORT_CACHE_IA_INT_APP_DROM0_S  (0)
+
+#define DPORT_SECURE_BOOT_CTRL_REG          (DR_REG_DPORT_BASE + 0x5A4)
+/* DPORT_SW_BOOTLOADER_SEL : R/W ;bitpos:[0] ;default: 1'b0 ; */
+/*description: */
+#define DPORT_SW_BOOTLOADER_SEL  (BIT(0))
+#define DPORT_SW_BOOTLOADER_SEL_M  (BIT(0))
+#define DPORT_SW_BOOTLOADER_SEL_V  0x1
+#define DPORT_SW_BOOTLOADER_SEL_S  0
+
+#define DPORT_SPI_DMA_CHAN_SEL_REG          (DR_REG_DPORT_BASE + 0x5A8)
+/* DPORT_SPI3_DMA_CHAN_SEL : R/W ;bitpos:[5:4] ;default: 2'b00 ; */
+/*description: */
+#define DPORT_SPI3_DMA_CHAN_SEL  0x00000003
+#define DPORT_SPI3_DMA_CHAN_SEL_M  ((DPORT_SPI3_DMA_CHAN_SEL_V)<<(DPORT_SPI3_DMA_CHAN_SEL_S))
+#define DPORT_SPI3_DMA_CHAN_SEL_V  0x3
+#define DPORT_SPI3_DMA_CHAN_SEL_S  4
+/* DPORT_SPI2_DMA_CHAN_SEL : R/W ;bitpos:[3:2] ;default: 2'b00 ; */
+/*description: */
+#define DPORT_SPI2_DMA_CHAN_SEL  0x00000003
+#define DPORT_SPI2_DMA_CHAN_SEL_M  ((DPORT_SPI2_DMA_CHAN_SEL_V)<<(DPORT_SPI2_DMA_CHAN_SEL_S))
+#define DPORT_SPI2_DMA_CHAN_SEL_V  0x3
+#define DPORT_SPI2_DMA_CHAN_SEL_S  2
+/* DPORT_SPI1_DMA_CHAN_SEL : R/W ;bitpos:[1:0] ;default: 2'b00 ; */
+/*description: */
+#define DPORT_SPI1_DMA_CHAN_SEL  0x00000003
+#define DPORT_SPI1_DMA_CHAN_SEL_M  ((DPORT_SPI1_DMA_CHAN_SEL_V)<<(DPORT_SPI1_DMA_CHAN_SEL_S))
+#define DPORT_SPI1_DMA_CHAN_SEL_V  0x3
+#define DPORT_SPI1_DMA_CHAN_SEL_S  0
+
+#define DPORT_PRO_VECBASE_CTRL_REG          (DR_REG_DPORT_BASE + 0x5AC)
+/* DPORT_PRO_OUT_VECBASE_SEL : R/W ;bitpos:[1:0] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_PRO_OUT_VECBASE_SEL  0x00000003
+#define DPORT_PRO_OUT_VECBASE_SEL_M  ((DPORT_PRO_OUT_VECBASE_SEL_V)<<(DPORT_PRO_OUT_VECBASE_SEL_S))
+#define DPORT_PRO_OUT_VECBASE_SEL_V  0x3
+#define DPORT_PRO_OUT_VECBASE_SEL_S  0
+
+#define DPORT_PRO_VECBASE_SET_REG          (DR_REG_DPORT_BASE + 0x5B0)
+/* DPORT_PRO_OUT_VECBASE_REG : R/W ;bitpos:[21:0] ;default: 22'b0 ; */
+/*description: */
+#define DPORT_PRO_OUT_VECBASE_REG  0x003FFFFF
+#define DPORT_PRO_OUT_VECBASE_REG_M  ((DPORT_PRO_OUT_VECBASE_REG_V)<<(DPORT_PRO_OUT_VECBASE_REG_S))
+#define DPORT_PRO_OUT_VECBASE_REG_V  0x3FFFFF
+#define DPORT_PRO_OUT_VECBASE_REG_S  0
+
+#define DPORT_APP_VECBASE_CTRL_REG          (DR_REG_DPORT_BASE + 0x5B4)
+/* DPORT_APP_OUT_VECBASE_SEL : R/W ;bitpos:[1:0] ;default: 2'b0 ; */
+/*description: */
+#define DPORT_APP_OUT_VECBASE_SEL  0x00000003
+#define DPORT_APP_OUT_VECBASE_SEL_M  ((DPORT_APP_OUT_VECBASE_SEL_V)<<(DPORT_APP_OUT_VECBASE_SEL_S))
+#define DPORT_APP_OUT_VECBASE_SEL_V  0x3
+#define DPORT_APP_OUT_VECBASE_SEL_S  0
+
+#define DPORT_APP_VECBASE_SET_REG          (DR_REG_DPORT_BASE + 0x5B8)
+/* DPORT_APP_OUT_VECBASE_REG : R/W ;bitpos:[21:0] ;default: 22'b0 ; */
+/*description: */
+#define DPORT_APP_OUT_VECBASE_REG  0x003FFFFF
+#define DPORT_APP_OUT_VECBASE_REG_M  ((DPORT_APP_OUT_VECBASE_REG_V)<<(DPORT_APP_OUT_VECBASE_REG_S))
+#define DPORT_APP_OUT_VECBASE_REG_V  0x3FFFFF
+#define DPORT_APP_OUT_VECBASE_REG_S  0
+
+#define DPORT_DATE_REG          (DR_REG_DPORT_BASE + 0xFFC)
+/* DPORT_DATE : R/W ;bitpos:[27:0] ;default: 28'h1605190 ; */
+/*description: */
+#define DPORT_DATE  0x0FFFFFFF
+#define DPORT_DATE_M  ((DPORT_DATE_V)<<(DPORT_DATE_S))
+#define DPORT_DATE_V  0xFFFFFFF
+#define DPORT_DATE_S  0
+#define DPORT_DPORT_DATE_VERSION 0x1605190
+
+/* Flash MMU table for PRO CPU */
+#define DPORT_PRO_FLASH_MMU_TABLE ((volatile uint32_t*) 0x3FF10000)
+
+/* Flash MMU table for APP CPU */
+#define DPORT_APP_FLASH_MMU_TABLE ((volatile uint32_t*) 0x3FF12000)
+
+#define DPORT_FLASH_MMU_TABLE_SIZE 0x100
+
+#define DPORT_FLASH_MMU_TABLE_INVALID_VAL 0x100
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOC_DPORT_REG_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/soc/rtc.h b/cpu/esp32/vendor/esp-idf/include/soc/rtc.h
new file mode 100644
index 0000000000000000000000000000000000000000..d43973a833d9683071ec0e4aa4694c2775de0126
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/soc/rtc.h
@@ -0,0 +1,623 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOC_RTC_H
+#define SOC_RTC_H
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include "soc/soc.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file rtc.h
+ * @brief Low-level RTC power, clock, and sleep functions.
+ *
+ * Functions in this file facilitate configuration of ESP32's RTC_CNTL peripheral.
+ * RTC_CNTL peripheral handles many functions:
+ * - enables/disables clocks and power to various parts of the chip; this is
+ *   done using direct register access (forcing power up or power down) or by
+ *   allowing state machines to control power and clocks automatically
+ * - handles sleep and wakeup functions
+ * - maintains a 48-bit counter which can be used for timekeeping
+ *
+ * These functions are not thread safe, and should not be viewed as high level
+ * APIs. For example, while this file provides a function which can switch
+ * CPU frequency, this function is on its own is not sufficient to implement
+ * frequency switching in ESP-IDF context: some coordination with RTOS,
+ * peripheral drivers, and WiFi/BT stacks is also required.
+ *
+ * These functions will normally not be used in applications directly.
+ * ESP-IDF provides, or will provide, drivers and other facilities to use
+ * RTC subsystem functionality.
+ *
+ * The functions are loosely split into the following groups:
+ * - rtc_clk: clock switching, calibration
+ * - rtc_time: reading RTC counter, conversion between counter values and time
+ * - rtc_sleep: entry into sleep modes
+ * - rtc_init: initialization
+ */
+
+
+/**
+ * @brief Possible main XTAL frequency values.
+ *
+ * Enum values should be equal to frequency in MHz.
+ */
+typedef enum {
+    RTC_XTAL_FREQ_AUTO = 0,     //!< Automatic XTAL frequency detection
+    RTC_XTAL_FREQ_40M = 40,     //!< 40 MHz XTAL
+    RTC_XTAL_FREQ_26M = 26,     //!< 26 MHz XTAL
+    RTC_XTAL_FREQ_24M = 24,     //!< 24 MHz XTAL
+} rtc_xtal_freq_t;
+
+/**
+ * @brief CPU frequency values
+ */
+typedef enum {
+    RTC_CPU_FREQ_XTAL = 0,      //!< Main XTAL frequency
+    RTC_CPU_FREQ_80M = 1,       //!< 80 MHz
+    RTC_CPU_FREQ_160M = 2,      //!< 160 MHz
+    RTC_CPU_FREQ_240M = 3,      //!< 240 MHz
+    RTC_CPU_FREQ_2M = 4,        //!< 2 MHz
+} rtc_cpu_freq_t;
+
+/**
+ * @brief RTC SLOW_CLK frequency values
+ */
+typedef enum {
+    RTC_SLOW_FREQ_RTC = 0,      //!< Internal 150 kHz RC oscillator
+    RTC_SLOW_FREQ_32K_XTAL = 1, //!< External 32 kHz XTAL
+    RTC_SLOW_FREQ_8MD256 = 2,   //!< Internal 8 MHz RC oscillator, divided by 256
+} rtc_slow_freq_t;
+
+/**
+ * @brief RTC FAST_CLK frequency values
+ */
+typedef enum {
+    RTC_FAST_FREQ_XTALD4 = 0,   //!< Main XTAL, divided by 4
+    RTC_FAST_FREQ_8M = 1,       //!< Internal 8 MHz RC oscillator
+} rtc_fast_freq_t;
+
+/* With the default value of CK8M_DFREQ, 8M clock frequency is 8.5 MHz +/- 7% */
+#define RTC_FAST_CLK_FREQ_APPROX 8500000
+
+/**
+ * @brief Clock source to be calibrated using rtc_clk_cal function
+ */
+typedef enum {
+    RTC_CAL_RTC_MUX = 0,       //!< Currently selected RTC SLOW_CLK
+    RTC_CAL_8MD256 = 1,        //!< Internal 8 MHz RC oscillator, divided by 256
+    RTC_CAL_32K_XTAL = 2       //!< External 32 kHz XTAL
+} rtc_cal_sel_t;
+
+/**
+ * Initialization parameters for rtc_clk_init
+ */
+typedef struct {
+    rtc_xtal_freq_t xtal_freq : 8;  //!< Main XTAL frequency
+    rtc_cpu_freq_t cpu_freq : 3;    //!< CPU frequency to set
+    rtc_fast_freq_t fast_freq : 1;  //!< RTC_FAST_CLK frequency to set
+    rtc_slow_freq_t slow_freq : 2;  //!< RTC_SLOW_CLK frequency to set
+    uint32_t clk_8m_div : 3;        //!< RTC 8M clock divider (division is by clk_8m_div+1, i.e. 0 means 8MHz frequency)
+    uint32_t slow_clk_dcap : 8;     //!< RTC 150k clock adjustment parameter (higher value leads to lower frequency)
+    uint32_t clk_8m_dfreq : 8;      //!< RTC 8m clock adjustment parameter (higher value leads to higher frequency)
+} rtc_clk_config_t;
+
+/**
+ * Default initializer for rtc_clk_config_t
+ */
+#define RTC_CLK_CONFIG_DEFAULT() { \
+    .xtal_freq = RTC_XTAL_FREQ_AUTO, \
+    .cpu_freq = RTC_CPU_FREQ_80M, \
+    .fast_freq = RTC_FAST_FREQ_8M, \
+    .slow_freq = RTC_SLOW_FREQ_RTC, \
+    .clk_8m_div = 0, \
+    .slow_clk_dcap = RTC_CNTL_SCK_DCAP_DEFAULT, \
+    .clk_8m_dfreq = RTC_CNTL_CK8M_DFREQ_DEFAULT, \
+}
+
+/**
+ * Initialize clocks and set CPU frequency
+ *
+ * If cfg.xtal_freq is set to RTC_XTAL_FREQ_AUTO, this function will attempt
+ * to auto detect XTAL frequency. Auto detection is performed by comparing
+ * XTAL frequency with the frequency of internal 8MHz oscillator. Note that at
+ * high temperatures the frequency of the internal 8MHz oscillator may drift
+ * enough for auto detection to be unreliable.
+ * Auto detection code will attempt to distinguish between 26MHz and 40MHz
+ * crystals. 24 MHz crystals are not supported by auto detection code.
+ * If XTAL frequency can not be auto detected, this 26MHz frequency will be used.
+ *
+ * @param cfg clock configuration as rtc_clk_config_t
+ */
+void rtc_clk_init(rtc_clk_config_t cfg);
+
+/**
+ * @brief Get main XTAL frequency
+ *
+ * This is the value stored in RTC register RTC_XTAL_FREQ_REG by the bootloader. As passed to
+ * rtc_clk_init function, or if the value was RTC_XTAL_FREQ_AUTO, the detected
+ * XTAL frequency.
+ *
+ * @return XTAL frequency, one of rtc_xtal_freq_t
+ */
+rtc_xtal_freq_t rtc_clk_xtal_freq_get(void);
+
+/**
+ * @brief Update XTAL frequency
+ *
+ * Updates the XTAL value stored in RTC_XTAL_FREQ_REG. Usually this value is ignored
+ * after startup.
+ *
+ * @param xtal_freq New frequency value
+ */
+void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq);
+
+/**
+ * @brief Enable or disable 32 kHz XTAL oscillator
+ * @param en  true to enable, false to disable
+ */
+void rtc_clk_32k_enable(bool en);
+
+/**
+ * @brief Get the state of 32k XTAL oscillator
+ * @return true if 32k XTAL oscillator has been enabled
+ */
+bool rtc_clk_32k_enabled(void);
+
+/**
+ * @brief Enable 32k oscillator, configuring it for fast startup time.
+ * Note: to achieve higher frequency stability, rtc_clk_32k_enable function
+ * must be called one the 32k XTAL oscillator has started up. This function
+ * will initially disable the 32k XTAL oscillator, so it should not be called
+ * when the system is using 32k XTAL as RTC_SLOW_CLK.
+ *
+ * @param cycle Number of 32kHz cycles to bootstrap external crystal.
+ *              If 0, no square wave will be used to bootstrap crystal oscillation.
+ */
+void rtc_clk_32k_bootstrap(uint32_t cycle);
+
+/**
+ * @brief Enable or disable 8 MHz internal oscillator
+ *
+ * Output from 8 MHz internal oscillator is passed into a configurable
+ * divider, which by default divides the input clock frequency by 256.
+ * Output of the divider may be used as RTC_SLOW_CLK source.
+ * Output of the divider is referred to in register descriptions and code as
+ * 8md256 or simply d256. Divider values other than 256 may be configured, but
+ * this facility is not currently needed, so is not exposed in the code.
+ *
+ * When 8MHz/256 divided output is not needed, the divider should be disabled
+ * to reduce power consumption.
+ *
+ * @param clk_8m_en true to enable 8MHz generator
+ * @param d256_en true to enable /256 divider
+ */
+void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en);
+
+/**
+ * @brief Get the state of 8 MHz internal oscillator
+ * @return true if the oscillator is enabled
+ */
+bool rtc_clk_8m_enabled(void);
+
+/**
+ * @brief Get the state of /256 divider which is applied to 8MHz clock
+ * @return true if the divided output is enabled
+ */
+bool rtc_clk_8md256_enabled(void);
+
+/**
+ * @brief Enable or disable APLL
+ *
+ * Output frequency is given by the formula:
+ * apll_freq = xtal_freq * (4 + sdm2 + sdm1/256 + sdm0/65536)/((o_div + 2) * 2)
+ *
+ * The dividend in this expression should be in the range of 240 - 600 MHz.
+ *
+ * In rev. 0 of ESP32, sdm0 and sdm1 are unused and always set to 0.
+ *
+ * @param enable  true to enable, false to disable
+ * @param sdm0  frequency adjustment parameter, 0..255
+ * @param sdm1  frequency adjustment parameter, 0..255
+ * @param sdm2  frequency adjustment parameter, 0..63
+ * @param o_div  frequency divider, 0..31
+ */
+void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1,
+        uint32_t sdm2, uint32_t o_div);
+
+/**
+ * @brief Select source for RTC_SLOW_CLK
+ * @param slow_freq clock source (one of rtc_slow_freq_t values)
+ */
+void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq);
+
+/**
+ * @brief Get the RTC_SLOW_CLK source
+ * @return currently selected clock source (one of rtc_slow_freq_t values)
+ */
+rtc_slow_freq_t rtc_clk_slow_freq_get(void);
+
+/**
+ * @brief Get the approximate frequency of RTC_SLOW_CLK, in Hz
+ *
+ * - if RTC_SLOW_FREQ_RTC is selected, returns ~150000
+ * - if RTC_SLOW_FREQ_32K_XTAL is selected, returns 32768
+ * - if RTC_SLOW_FREQ_8MD256 is selected, returns ~33000
+ *
+ * rtc_clk_cal function can be used to get more precise value by comparing
+ * RTC_SLOW_CLK frequency to the frequency of main XTAL.
+ *
+ * @return RTC_SLOW_CLK frequency, in Hz
+ */
+uint32_t rtc_clk_slow_freq_get_hz(void);
+
+/**
+ * @brief Select source for RTC_FAST_CLK
+ * @param fast_freq clock source (one of rtc_fast_freq_t values)
+ */
+void rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq);
+
+/**
+ * @brief Get the RTC_FAST_CLK source
+ * @return currently selected clock source (one of rtc_fast_freq_t values)
+ */
+rtc_fast_freq_t rtc_clk_fast_freq_get(void);
+
+/**
+ * @brief Switch CPU frequency
+ *
+ * If a PLL-derived frequency is requested (80, 160, 240 MHz), this function
+ * will enable the PLL. Otherwise, PLL will be disabled.
+ * Note: this function is not optimized for switching speed. It may take several
+ * hundred microseconds to perform frequency switch.
+ *
+ * @param cpu_freq  new CPU frequency
+ */
+void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq);
+
+/**
+ * @brief Switch CPU frequency
+ *
+ * This is a faster version of rtc_clk_cpu_freq_set, which can handle some of
+ * the frequency switch paths (XTAL -> PLL, PLL -> XTAL).
+ * When switching from PLL to XTAL, PLL is not disabled (unlike rtc_clk_cpu_freq_set).
+ * When switching back from XTAL to PLL, only the same PLL can be used.
+ * Therefore it is not possible to switch 240 -> XTAL -> (80 or 160) using this
+ * function.
+ *
+ * For unsupported cases, this function falls back to rtc_clk_cpu_freq_set.
+ *
+ * Unlike rtc_clk_cpu_freq_set, this function relies on static data, so it is
+ * less safe to use it e.g. from a panic handler (when memory might be corrupted).
+ *
+ * @param cpu_freq  new CPU frequency
+ */
+void rtc_clk_cpu_freq_set_fast(rtc_cpu_freq_t cpu_freq);
+
+/**
+ * @brief Get the currently selected CPU frequency
+ *
+ * Although CPU can be clocked by APLL and RTC 8M sources, such support is not
+ * exposed through this library. As such, this function will not return
+ * meaningful values when these clock sources are configured (e.g. using direct
+ * access to clock selection registers). In debug builds, it will assert; in
+ * release builds, it will return RTC_CPU_FREQ_XTAL.
+ *
+ * @return CPU frequency (one of rtc_cpu_freq_t values)
+ */
+rtc_cpu_freq_t rtc_clk_cpu_freq_get(void);
+
+/**
+ * @brief Get corresponding frequency value for rtc_cpu_freq_t enum value
+ * @param cpu_freq  CPU frequency, on of rtc_cpu_freq_t values
+ * @return CPU frequency, in HZ
+ */
+uint32_t rtc_clk_cpu_freq_value(rtc_cpu_freq_t cpu_freq);
+
+/**
+ * @brief Get rtc_cpu_freq_t enum value for given CPU frequency
+ * @param cpu_freq_mhz  CPU frequency, one of 80, 160, 240, 2, and XTAL frequency
+ * @param[out] out_val output, rtc_cpu_freq_t value corresponding to the frequency
+ * @return true if the given frequency value matches one of enum values
+ */
+ bool rtc_clk_cpu_freq_from_mhz(int cpu_freq_mhz, rtc_cpu_freq_t* out_val);
+
+/**
+ * @brief Store new APB frequency value into RTC_APB_FREQ_REG
+ *
+ * This function doesn't change any hardware clocks.
+ *
+ * Functions which perform frequency switching and change APB frequency call
+ * this function to update the value of APB frequency stored in RTC_APB_FREQ_REG
+ * (one of RTC general purpose retention registers). This should not normally
+ * be called from application code.
+ *
+ * @param apb_freq  new APB frequency, in Hz
+ */
+void rtc_clk_apb_freq_update(uint32_t apb_freq);
+
+/**
+ * @brief Get the current stored APB frequency.
+ * @return The APB frequency value as last set via rtc_clk_apb_freq_update(), in Hz.
+ */
+uint32_t rtc_clk_apb_freq_get(void);
+
+#define RTC_CLK_CAL_FRACT  19  //!< Number of fractional bits in values returned by rtc_clk_cal
+
+/**
+ * @brief Measure RTC slow clock's period, based on main XTAL frequency
+ *
+ * This function will time out and return 0 if the time for the given number
+ * of cycles to be counted exceeds the expected time twice. This may happen if
+ * 32k XTAL is being calibrated, but the oscillator has not started up (due to
+ * incorrect loading capacitance, board design issue, or lack of 32 XTAL on board).
+ *
+ * @param cal_clk  clock to be measured
+ * @param slow_clk_cycles  number of slow clock cycles to average
+ * @return average slow clock period in microseconds, Q13.19 fixed point format,
+ *         or 0 if calibration has timed out
+ */
+uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
+
+/**
+ * @brief Measure ratio between XTAL frequency and RTC slow clock frequency
+ * @param cal_clk slow clock to be measured
+ * @param slow_clk_cycles number of slow clock cycles to average
+ * @return average ratio between XTAL frequency and slow clock frequency,
+ *         Q13.19 fixed point format, or 0 if calibration has timed out.
+ */
+uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slow_clk_cycles);
+
+/**
+ * @brief Convert time interval from microseconds to RTC_SLOW_CLK cycles
+ * @param time_in_us Time interval in microseconds
+ * @param slow_clk_period  Period of slow clock in microseconds, Q13.19
+ *                         fixed point format (as returned by rtc_slowck_cali).
+ * @return number of slow clock cycles
+ */
+uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period);
+
+/**
+ * @brief Convert time interval from RTC_SLOW_CLK to microseconds
+ * @param time_in_us Time interval in RTC_SLOW_CLK cycles
+ * @param slow_clk_period  Period of slow clock in microseconds, Q13.19
+ *                         fixed point format (as returned by rtc_slowck_cali).
+ * @return time interval in microseconds
+ */
+uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period);
+
+/**
+ * @brief Get current value of RTC counter
+ *
+ * RTC has a 48-bit counter which is incremented by 2 every 2 RTC_SLOW_CLK
+ * cycles. Counter value is not writable by software. The value is not adjusted
+ * when switching to a different RTC_SLOW_CLK source.
+ *
+ * Note: this function may take up to 1 RTC_SLOW_CLK cycle to execute
+ *
+ * @return current value of RTC counter
+ */
+uint64_t rtc_time_get(void);
+
+/**
+ * @brief Busy loop until next RTC_SLOW_CLK cycle
+ *
+ * This function returns not earlier than the next RTC_SLOW_CLK clock cycle.
+ * In some cases (e.g. when RTC_SLOW_CLK cycle is very close), it may return
+ * one RTC_SLOW_CLK cycle later.
+ */
+void rtc_clk_wait_for_slow_cycle(void);
+
+/**
+ * @brief sleep configuration for rtc_sleep_init function
+ */
+typedef struct {
+    uint32_t lslp_mem_inf_fpu : 1;      //!< force normal voltage in sleep mode (digital domain memory)
+    uint32_t rtc_mem_inf_fpu : 1;       //!< force normal voltage in sleep mode (RTC memory)
+    uint32_t rtc_mem_inf_follow_cpu : 1;//!< keep low voltage in sleep mode (even if ULP/touch is used)
+    uint32_t rtc_fastmem_pd_en : 1;     //!< power down RTC fast memory
+    uint32_t rtc_slowmem_pd_en : 1;     //!< power down RTC slow memory
+    uint32_t rtc_peri_pd_en : 1;        //!< power down RTC peripherals
+    uint32_t wifi_pd_en : 1;            //!< power down WiFi
+    uint32_t rom_mem_pd_en : 1;         //!< power down main RAM and ROM
+    uint32_t deep_slp : 1;              //!< power down digital domain
+    uint32_t wdt_flashboot_mod_en : 1;  //!< enable WDT flashboot mode
+    uint32_t dig_dbias_wak : 3;         //!< set bias for digital domain, in active mode
+    uint32_t dig_dbias_slp : 3;         //!< set bias for digital domain, in sleep mode
+    uint32_t rtc_dbias_wak : 3;         //!< set bias for RTC domain, in active mode
+    uint32_t rtc_dbias_slp : 3;         //!< set bias for RTC domain, in sleep mode
+    uint32_t lslp_meminf_pd : 1;        //!< remove all peripheral force power up flags
+    uint32_t vddsdio_pd_en : 1;         //!< power down VDDSDIO regulator
+    uint32_t xtal_fpu : 1;              //!< keep main XTAL powered up in sleep
+} rtc_sleep_config_t;
+
+/**
+ * Default initializer for rtc_sleep_config_t
+ *
+ * This initializer sets all fields to "reasonable" values (e.g. suggested for
+ * production use) based on a combination of RTC_SLEEP_PD_x flags.
+ *
+ * @param RTC_SLEEP_PD_x flags combined using bitwise OR
+ */
+#define RTC_SLEEP_CONFIG_DEFAULT(sleep_flags) { \
+    .lslp_mem_inf_fpu = 0, \
+    .rtc_mem_inf_fpu = 0, \
+    .rtc_mem_inf_follow_cpu = ((sleep_flags) & RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU) ? 1 : 0, \
+    .rtc_fastmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_FAST_MEM) ? 1 : 0, \
+    .rtc_slowmem_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_SLOW_MEM) ? 1 : 0, \
+    .rtc_peri_pd_en = ((sleep_flags) & RTC_SLEEP_PD_RTC_PERIPH) ? 1 : 0, \
+    .wifi_pd_en = 0, \
+    .rom_mem_pd_en = 0, \
+    .deep_slp = ((sleep_flags) & RTC_SLEEP_PD_DIG) ? 1 : 0, \
+    .wdt_flashboot_mod_en = 0, \
+    .dig_dbias_wak = RTC_CNTL_DBIAS_1V10, \
+    .dig_dbias_slp = RTC_CNTL_DBIAS_0V90, \
+    .rtc_dbias_wak = RTC_CNTL_DBIAS_1V10, \
+    .rtc_dbias_slp = RTC_CNTL_DBIAS_0V90, \
+    .lslp_meminf_pd = 1, \
+    .vddsdio_pd_en = ((sleep_flags) & RTC_SLEEP_PD_VDDSDIO) ? 1 : 0, \
+    .xtal_fpu = ((sleep_flags) & RTC_SLEEP_PD_XTAL) ? 0 : 1 \
+};
+
+#define RTC_SLEEP_PD_DIG                BIT(0)  //!< Deep sleep (power down digital domain)
+#define RTC_SLEEP_PD_RTC_PERIPH         BIT(1)  //!< Power down RTC peripherals
+#define RTC_SLEEP_PD_RTC_SLOW_MEM       BIT(2)  //!< Power down RTC SLOW memory
+#define RTC_SLEEP_PD_RTC_FAST_MEM       BIT(3)  //!< Power down RTC FAST memory
+#define RTC_SLEEP_PD_RTC_MEM_FOLLOW_CPU BIT(4)  //!< RTC FAST and SLOW memories are automatically powered up and down along with the CPU
+#define RTC_SLEEP_PD_VDDSDIO            BIT(5)  //!< Power down VDDSDIO regulator
+#define RTC_SLEEP_PD_XTAL               BIT(6)  //!< Power down main XTAL
+
+/**
+ * @brief Prepare the chip to enter sleep mode
+ *
+ * This function configures various power control state machines to handle
+ * entry into light sleep or deep sleep mode, switches APB and CPU clock source
+ * (usually to XTAL), and sets bias voltages for digital and RTC power domains.
+ *
+ * This function does not actually enter sleep mode; this is done using
+ * rtc_sleep_start function. Software may do some other actions between
+ * rtc_sleep_init and rtc_sleep_start, such as set wakeup timer and configure
+ * wakeup sources.
+ * @param cfg sleep mode configuration
+ */
+void rtc_sleep_init(rtc_sleep_config_t cfg);
+
+
+/**
+ * @brief Set target value of RTC counter for RTC_TIMER_TRIG_EN wakeup source
+ * @param t value of RTC counter at which wakeup from sleep will happen;
+ *          only the lower 48 bits are used
+ */
+void rtc_sleep_set_wakeup_time(uint64_t t);
+
+
+#define RTC_EXT0_TRIG_EN    BIT(0)  //!< EXT0 GPIO wakeup
+#define RTC_EXT1_TRIG_EN    BIT(1)  //!< EXT1 GPIO wakeup
+#define RTC_GPIO_TRIG_EN    BIT(2)  //!< GPIO wakeup (light sleep only)
+#define RTC_TIMER_TRIG_EN   BIT(3)  //!< Timer wakeup
+#define RTC_SDIO_TRIG_EN    BIT(4)  //!< SDIO wakeup (light sleep only)
+#define RTC_MAC_TRIG_EN     BIT(5)  //!< MAC wakeup (light sleep only)
+#define RTC_UART0_TRIG_EN   BIT(6)  //!< UART0 wakeup (light sleep only)
+#define RTC_UART1_TRIG_EN   BIT(7)  //!< UART1 wakeup (light sleep only)
+#define RTC_TOUCH_TRIG_EN   BIT(8)  //!< Touch wakeup
+#define RTC_ULP_TRIG_EN     BIT(9)  //!< ULP wakeup
+#define RTC_BT_TRIG_EN      BIT(10) //!< BT wakeup (light sleep only)
+
+/**
+ * @brief Enter deep or light sleep mode
+ *
+ * This function enters the sleep mode previously configured using rtc_sleep_init
+ * function. Before entering sleep, software should configure wake up sources
+ * appropriately (set up GPIO wakeup registers, timer wakeup registers,
+ * and so on).
+ *
+ * If deep sleep mode was configured using rtc_sleep_init, and sleep is not
+ * rejected by hardware (based on reject_opt flags), this function never returns.
+ * When the chip wakes up from deep sleep, CPU is reset and execution starts
+ * from ROM bootloader.
+ *
+ * If light sleep mode was configured using rtc_sleep_init, this function
+ * returns on wakeup, or if sleep is rejected by hardware.
+ *
+ * @param wakeup_opt  bit mask wake up reasons to enable (RTC_xxx_TRIG_EN flags
+ *                    combined with OR)
+ * @param reject_opt  bit mask of sleep reject reasons:
+ *                      - RTC_CNTL_GPIO_REJECT_EN
+ *                      - RTC_CNTL_SDIO_REJECT_EN
+ *                    These flags are used to prevent entering sleep when e.g.
+ *                    an external host is communicating via SDIO slave
+ * @return non-zero if sleep was rejected by hardware
+ */
+uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt);
+
+/**
+ * RTC power and clock control initialization settings
+ */
+typedef struct {
+    uint32_t ck8m_wait : 8;         //!< Number of rtc_fast_clk cycles to wait for 8M clock to be ready
+    uint32_t xtal_wait : 8;         //!< Number of rtc_fast_clk cycles to wait for XTAL clock to be ready
+    uint32_t pll_wait : 8;          //!< Number of rtc_fast_clk cycles to wait for PLL to be ready
+    uint32_t clkctl_init : 1;       //!< Perform clock control related initialization
+    uint32_t pwrctl_init : 1;       //!< Perform power control related initialization
+    uint32_t rtc_dboost_fpd : 1;    //!< Force power down RTC_DBOOST
+} rtc_config_t;
+
+/**
+ * Default initializer of rtc_config_t.
+ *
+ * This initializer sets all fields to "reasonable" values (e.g. suggested for
+ * production use).
+ */
+#define RTC_CONFIG_DEFAULT() {\
+    .ck8m_wait = RTC_CNTL_CK8M_WAIT_DEFAULT, \
+    .xtal_wait = RTC_CNTL_XTL_BUF_WAIT_DEFAULT, \
+    .pll_wait  = RTC_CNTL_PLL_BUF_WAIT_DEFAULT, \
+    .clkctl_init = 1, \
+    .pwrctl_init = 1, \
+    .rtc_dboost_fpd = 1 \
+}
+
+/**
+ * Initialize RTC clock and power control related functions
+ * @param cfg configuration options as rtc_config_t
+ *
+ * We had to rename this function from rtc_init to rtc_init_module because of
+ * conflicts with RIOT's rtc_init function
+ */
+void rtc_init_module(rtc_config_t cfg);
+
+#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
+#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
+
+/**
+ * Structure describing vddsdio configuration
+ */
+typedef struct {
+    uint32_t force : 1;     //!< If 1, use configuration from RTC registers; if 0, use EFUSE/bootstrapping pins.
+    uint32_t enable : 1;    //!< Enable VDDSDIO regulator
+    uint32_t tieh  : 1;     //!< Select VDDSDIO voltage: 1 — 1.8V, 0 — 3.3V
+    uint32_t drefh : 2;     //!< Tuning parameter for VDDSDIO regulator
+    uint32_t drefm : 2;     //!< Tuning parameter for VDDSDIO regulator
+    uint32_t drefl : 2;     //!< Tuning parameter for VDDSDIO regulator
+} rtc_vddsdio_config_t;
+
+/**
+ * Get current VDDSDIO configuration
+ * If VDDSDIO configuration is overridden by RTC, get values from RTC
+ * Otherwise, if VDDSDIO is configured by EFUSE, get values from EFUSE
+ * Otherwise, use default values and the level of MTDI bootstrapping pin.
+ * @return currently used VDDSDIO configuration
+ */
+rtc_vddsdio_config_t rtc_vddsdio_get_config(void);
+
+/**
+ * Set new VDDSDIO configuration using RTC registers.
+ * If config.force == 1, this overrides configuration done using bootstrapping
+ * pins and EFUSE.
+ *
+ * @param config new VDDSDIO configuration
+ */
+void rtc_vddsdio_set_config(rtc_vddsdio_config_t config);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOC_RTC_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/spi_flash/esp_partition.h b/cpu/esp32/vendor/esp-idf/include/spi_flash/esp_partition.h
new file mode 100644
index 0000000000000000000000000000000000000000..0f876fd4da9950b977c4754e1ac089345b807cb8
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/spi_flash/esp_partition.h
@@ -0,0 +1,295 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SPI_FLASH_ESP_PARTITION_H
+#define SPI_FLASH_ESP_PARTITION_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "esp_err.h"
+#include "esp_spi_flash.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @file esp_partition.h
+ * @brief Partition APIs
+ */
+
+
+/**
+ * @brief Partition type
+ * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py
+ */
+typedef enum {
+    ESP_PARTITION_TYPE_APP = 0x00,       //!< Application partition type
+    ESP_PARTITION_TYPE_DATA = 0x01,      //!< Data partition type
+} esp_partition_type_t;
+
+/**
+ * @brief Partition subtype
+ * @note Keep this enum in sync with PartitionDefinition class gen_esp32part.py
+ */
+typedef enum {
+    ESP_PARTITION_SUBTYPE_APP_FACTORY = 0x00,                                 //!< Factory application partition
+    ESP_PARTITION_SUBTYPE_APP_OTA_MIN = 0x10,                                 //!< Base for OTA partition subtypes
+    ESP_PARTITION_SUBTYPE_APP_OTA_0 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 0,  //!< OTA partition 0
+    ESP_PARTITION_SUBTYPE_APP_OTA_1 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 1,  //!< OTA partition 1
+    ESP_PARTITION_SUBTYPE_APP_OTA_2 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 2,  //!< OTA partition 2
+    ESP_PARTITION_SUBTYPE_APP_OTA_3 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 3,  //!< OTA partition 3
+    ESP_PARTITION_SUBTYPE_APP_OTA_4 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 4,  //!< OTA partition 4
+    ESP_PARTITION_SUBTYPE_APP_OTA_5 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 5,  //!< OTA partition 5
+    ESP_PARTITION_SUBTYPE_APP_OTA_6 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 6,  //!< OTA partition 6
+    ESP_PARTITION_SUBTYPE_APP_OTA_7 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 7,  //!< OTA partition 7
+    ESP_PARTITION_SUBTYPE_APP_OTA_8 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 8,  //!< OTA partition 8
+    ESP_PARTITION_SUBTYPE_APP_OTA_9 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 9,  //!< OTA partition 9
+    ESP_PARTITION_SUBTYPE_APP_OTA_10 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 10,//!< OTA partition 10
+    ESP_PARTITION_SUBTYPE_APP_OTA_11 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 11,//!< OTA partition 11
+    ESP_PARTITION_SUBTYPE_APP_OTA_12 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 12,//!< OTA partition 12
+    ESP_PARTITION_SUBTYPE_APP_OTA_13 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 13,//!< OTA partition 13
+    ESP_PARTITION_SUBTYPE_APP_OTA_14 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 14,//!< OTA partition 14
+    ESP_PARTITION_SUBTYPE_APP_OTA_15 = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 15,//!< OTA partition 15
+    ESP_PARTITION_SUBTYPE_APP_OTA_MAX = ESP_PARTITION_SUBTYPE_APP_OTA_MIN + 16,//!< Max subtype of OTA partition
+    ESP_PARTITION_SUBTYPE_APP_TEST = 0x20,                                    //!< Test application partition
+
+    ESP_PARTITION_SUBTYPE_DATA_OTA = 0x00,                                    //!< OTA selection partition
+    ESP_PARTITION_SUBTYPE_DATA_PHY = 0x01,                                    //!< PHY init data partition
+    ESP_PARTITION_SUBTYPE_DATA_NVS = 0x02,                                    //!< NVS partition
+    ESP_PARTITION_SUBTYPE_DATA_COREDUMP = 0x03,                               //!< COREDUMP partition
+
+    ESP_PARTITION_SUBTYPE_DATA_ESPHTTPD = 0x80,                               //!< ESPHTTPD partition
+    ESP_PARTITION_SUBTYPE_DATA_FAT = 0x81,                                    //!< FAT partition
+    ESP_PARTITION_SUBTYPE_DATA_SPIFFS = 0x82,                                 //!< SPIFFS partition
+
+    ESP_PARTITION_SUBTYPE_ANY = 0xff,                                         //!< Used to search for partitions with any subtype
+} esp_partition_subtype_t;
+
+/**
+ * @brief Convenience macro to get esp_partition_subtype_t value for the i-th OTA partition
+ */
+#define ESP_PARTITION_SUBTYPE_OTA(i) ((esp_partition_subtype_t)(ESP_PARTITION_SUBTYPE_APP_OTA_MIN + ((i) & 0xf)))
+
+/**
+ * @brief Opaque partition iterator type
+ */
+typedef struct esp_partition_iterator_opaque_* esp_partition_iterator_t;
+
+/**
+ * @brief partition information structure
+ *
+ * This is not the format in flash, that format is esp_partition_info_t.
+ *
+ * However, this is the format used by this API.
+ */
+typedef struct {
+    esp_partition_type_t type;          /*!< partition type (app/data) */
+    esp_partition_subtype_t subtype;    /*!< partition subtype */
+    uint32_t address;                   /*!< starting address of the partition in flash */
+    uint32_t size;                      /*!< size of the partition, in bytes */
+    char label[17];                     /*!< partition label, zero-terminated ASCII string */
+    bool encrypted;                     /*!< flag is set to true if partition is encrypted */
+} esp_partition_t;
+
+/**
+ * @brief Find partition based on one or more parameters
+ *
+ * @param type Partition type, one of esp_partition_type_t values
+ * @param subtype Partition subtype, one of esp_partition_subtype_t values.
+ *                To find all partitions of given type, use
+ *                ESP_PARTITION_SUBTYPE_ANY.
+ * @param label (optional) Partition label. Set this value if looking
+ *             for partition with a specific name. Pass NULL otherwise.
+ *
+ * @return iterator which can be used to enumerate all the partitions found,
+ *         or NULL if no partitions were found.
+ *         Iterator obtained through this function has to be released
+ *         using esp_partition_iterator_release when not used any more.
+ */
+esp_partition_iterator_t esp_partition_find(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
+
+/**
+ * @brief Find first partition based on one or more parameters
+ *
+ * @param type Partition type, one of esp_partition_type_t values
+ * @param subtype Partition subtype, one of esp_partition_subtype_t values.
+ *                To find all partitions of given type, use
+ *                ESP_PARTITION_SUBTYPE_ANY.
+ * @param label (optional) Partition label. Set this value if looking
+ *             for partition with a specific name. Pass NULL otherwise.
+ *
+ * @return pointer to esp_partition_t structure, or NULL if no partition is found.
+ *         This pointer is valid for the lifetime of the application.
+ */
+const esp_partition_t* esp_partition_find_first(esp_partition_type_t type, esp_partition_subtype_t subtype, const char* label);
+
+/**
+ * @brief Get esp_partition_t structure for given partition
+ *
+ * @param iterator  Iterator obtained using esp_partition_find. Must be non-NULL.
+ *
+ * @return pointer to esp_partition_t structure. This pointer is valid for the lifetime
+ *         of the application.
+ */
+const esp_partition_t* esp_partition_get(esp_partition_iterator_t iterator);
+
+/**
+ * @brief Move partition iterator to the next partition found
+ *
+ * Any copies of the iterator will be invalid after this call.
+ *
+ * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
+ *
+ * @return NULL if no partition was found, valid esp_partition_iterator_t otherwise.
+ */
+esp_partition_iterator_t esp_partition_next(esp_partition_iterator_t iterator);
+
+/**
+ * @brief Release partition iterator
+ *
+ * @param iterator Iterator obtained using esp_partition_find. Must be non-NULL.
+ *
+ */
+void esp_partition_iterator_release(esp_partition_iterator_t iterator);
+
+/**
+ * @brief Verify partition data
+ *
+ * Given a pointer to partition data, verify this partition exists in the partition table (all fields match.)
+ *
+ * This function is also useful to take partition data which may be in a RAM buffer and convert it to a pointer to the
+ * permanent partition data stored in flash.
+ *
+ * Pointers returned from this function can be compared directly to the address of any pointer returned from
+ * esp_partition_get(), as a test for equality.
+ *
+ * @param partition Pointer to partition data to verify. Must be non-NULL. All fields of this structure must match the
+ * partition table entry in flash for this function to return a successful match.
+ *
+ * @return
+ * - If partition not found, returns NULL.
+ * - If found, returns a pointer to the esp_partition_t structure in flash. This pointer is always valid for the lifetime of the application.
+ */
+const esp_partition_t *esp_partition_verify(const esp_partition_t *partition);
+
+/**
+ * @brief Read data from the partition
+ *
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
+ * @param dst Pointer to the buffer where data should be stored.
+ *            Pointer must be non-NULL and buffer must be at least 'size' bytes long.
+ * @param src_offset Address of the data to be read, relative to the
+ *                   beginning of the partition.
+ * @param size Size of data to be read, in bytes.
+ *
+ * @return ESP_OK, if data was read successfully;
+ *         ESP_ERR_INVALID_ARG, if src_offset exceeds partition size;
+ *         ESP_ERR_INVALID_SIZE, if read would go out of bounds of the partition;
+ *         or one of error codes from lower-level flash driver.
+ */
+esp_err_t esp_partition_read(const esp_partition_t* partition,
+                             size_t src_offset, void* dst, size_t size);
+
+/**
+ * @brief Write data to the partition
+ *
+ * Before writing data to flash, corresponding region of flash needs to be erased.
+ * This can be done using esp_partition_erase_range function.
+ *
+ * Partitions marked with an encryption flag will automatically be
+ * written via the spi_flash_write_encrypted() function. If writing to
+ * an encrypted partition, all write offsets and lengths must be
+ * multiples of 16 bytes. See the spi_flash_write_encrypted() function
+ * for more details. Unencrypted partitions do not have this
+ * restriction.
+ *
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
+ * @param dst_offset Address where the data should be written, relative to the
+ *                   beginning of the partition.
+ * @param src Pointer to the source buffer.  Pointer must be non-NULL and
+ *            buffer must be at least 'size' bytes long.
+ * @param size Size of data to be written, in bytes.
+ *
+ * @note Prior to writing to flash memory, make sure it has been erased with
+ *       esp_partition_erase_range call.
+ *
+ * @return ESP_OK, if data was written successfully;
+ *         ESP_ERR_INVALID_ARG, if dst_offset exceeds partition size;
+ *         ESP_ERR_INVALID_SIZE, if write would go out of bounds of the partition;
+ *         or one of error codes from lower-level flash driver.
+ */
+esp_err_t esp_partition_write(const esp_partition_t* partition,
+                             size_t dst_offset, const void* src, size_t size);
+
+/**
+ * @brief Erase part of the partition
+ *
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
+ * @param start_addr Address where erase operation should start. Must be aligned
+ *                   to 4 kilobytes.
+ * @param size Size of the range which should be erased, in bytes.
+ *                   Must be divisible by 4 kilobytes.
+ *
+ * @return ESP_OK, if the range was erased successfully;
+ *         ESP_ERR_INVALID_ARG, if iterator or dst are NULL;
+ *         ESP_ERR_INVALID_SIZE, if erase would go out of bounds of the partition;
+ *         or one of error codes from lower-level flash driver.
+ */
+esp_err_t esp_partition_erase_range(const esp_partition_t* partition,
+                                    uint32_t start_addr, uint32_t size);
+
+/**
+ * @brief Configure MMU to map partition into data memory
+ *
+ * Unlike spi_flash_mmap function, which requires a 64kB aligned base address,
+ * this function doesn't impose such a requirement.
+ * If offset results in a flash address which is not aligned to 64kB boundary,
+ * address will be rounded to the lower 64kB boundary, so that mapped region
+ * includes requested range.
+ * Pointer returned via out_ptr argument will be adjusted to point to the
+ * requested offset (not necessarily to the beginning of mmap-ed region).
+ *
+ * To release mapped memory, pass handle returned via out_handle argument to
+ * spi_flash_munmap function.
+ *
+ * @param partition Pointer to partition structure obtained using
+ *                  esp_partition_find_first or esp_partition_get.
+ *                  Must be non-NULL.
+ * @param offset Offset from the beginning of partition where mapping should start.
+ * @param size Size of the area to be mapped.
+ * @param memory  Memory space where the region should be mapped
+ * @param out_ptr  Output, pointer to the mapped memory region
+ * @param out_handle  Output, handle which should be used for spi_flash_munmap call
+ *
+ * @return ESP_OK, if successful
+ */
+esp_err_t esp_partition_mmap(const esp_partition_t* partition, uint32_t offset, uint32_t size,
+                             spi_flash_mmap_memory_t memory,
+                             const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* SPI_FLASH_ESP_PARTITION_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/spi_flash/esp_spi_flash.h b/cpu/esp32/vendor/esp-idf/include/spi_flash/esp_spi_flash.h
new file mode 100644
index 0000000000000000000000000000000000000000..09d401f36b6ec847e7a9ade2cc5bb68dc37e4bf4
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/spi_flash/esp_spi_flash.h
@@ -0,0 +1,423 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SPI_FLASH_ESP_SPI_FLASH_H
+#define SPI_FLASH_ESP_SPI_FLASH_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "esp_err.h"
+#include "sdk_conf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define ESP_ERR_FLASH_BASE       0x10010
+#define ESP_ERR_FLASH_OP_FAIL    (ESP_ERR_FLASH_BASE + 1)
+#define ESP_ERR_FLASH_OP_TIMEOUT (ESP_ERR_FLASH_BASE + 2)
+
+#define SPI_FLASH_SEC_SIZE  4096    /**< SPI Flash sector size */
+
+#define SPI_FLASH_MMU_PAGE_SIZE 0x10000 /**< Flash cache MMU mapping page size */
+
+/**
+ * @brief  Initialize SPI flash access driver
+ *
+ *  This function must be called exactly once, before any other
+ *  spi_flash_* functions are called.
+ *  Currently this function is called from startup code. There is
+ *  no need to call it from application code.
+ *
+ */
+void spi_flash_init(void);
+
+/**
+ * @brief  Get flash chip size, as set in binary image header
+ *
+ * @note This value does not necessarily match real flash size.
+ *
+ * @return size of flash chip, in bytes
+ */
+size_t spi_flash_get_chip_size(void);
+
+/**
+ * @brief  Erase the Flash sector.
+ *
+ * @param  sector  Sector number, the count starts at sector 0, 4KB per sector.
+ *
+ * @return esp_err_t
+ */
+esp_err_t spi_flash_erase_sector(size_t sector);
+
+/**
+ * @brief  Erase a range of flash sectors
+ *
+ * @param  start_address  Address where erase operation has to start.
+ *                                  Must be 4kB-aligned
+ * @param  size  Size of erased range, in bytes. Must be divisible by 4kB.
+ *
+ * @return esp_err_t
+ */
+esp_err_t spi_flash_erase_range(size_t start_address, size_t size);
+
+
+/**
+ * @brief  Write data to Flash.
+ *
+ * @note For fastest write performance, write a 4 byte aligned size at a
+ * 4 byte aligned offset in flash from a source buffer in DRAM. Varying any of
+ * these parameters will still work, but will be slower due to buffering.
+ *
+ * @note Writing more than 8KB at a time will be split into multiple
+ * write operations to avoid disrupting other tasks in the system.
+ *
+ * @param  dest_addr Destination address in Flash.
+ * @param  src       Pointer to the source buffer.
+ * @param  size      Length of data, in bytes.
+ *
+ * @return esp_err_t
+ */
+esp_err_t spi_flash_write(size_t dest_addr, const void *src, size_t size);
+
+
+/**
+ * @brief  Write data encrypted to Flash.
+ *
+ * @note Flash encryption must be enabled for this function to work.
+ *
+ * @note Flash encryption must be enabled when calling this function.
+ * If flash encryption is disabled, the function returns
+ * ESP_ERR_INVALID_STATE.  Use esp_flash_encryption_enabled()
+ * function to determine if flash encryption is enabled.
+ *
+ * @note Both dest_addr and size must be multiples of 16 bytes. For
+ * absolute best performance, both dest_addr and size arguments should
+ * be multiples of 32 bytes.
+ *
+ * @param  dest_addr Destination address in Flash. Must be a multiple of 16 bytes.
+ * @param  src       Pointer to the source buffer.
+ * @param  size      Length of data, in bytes. Must be a multiple of 16 bytes.
+ *
+ * @return esp_err_t
+ */
+esp_err_t spi_flash_write_encrypted(size_t dest_addr, const void *src, size_t size);
+
+/**
+ * @brief  Read data from Flash.
+ *
+ * @note For fastest read performance, all parameters should be
+ * 4 byte aligned. If source address and read size are not 4 byte
+ * aligned, read may be split into multiple flash operations. If
+ * destination buffer is not 4 byte aligned, a temporary buffer will
+ * be allocated on the stack.
+ *
+ * @note Reading more than 16KB of data at a time will be split
+ * into multiple reads to avoid disruption to other tasks in the
+ * system. Consider using spi_flash_mmap() to read large amounts
+ * of data.
+ *
+ * @param  src_addr source address of the data in Flash.
+ * @param  dest     pointer to the destination buffer
+ * @param  size     length of data
+ *
+ *
+ * @return esp_err_t
+ */
+esp_err_t spi_flash_read(size_t src_addr, void *dest, size_t size);
+
+
+/**
+ * @brief  Read data from Encrypted Flash.
+ *
+ * If flash encryption is enabled, this function will transparently decrypt data as it is read.
+ * If flash encryption is not enabled, this function behaves the same as spi_flash_read().
+ *
+ * See esp_flash_encryption_enabled() for a function to check if flash encryption is enabled.
+ *
+ * @param  src   source address of the data in Flash.
+ * @param  dest  pointer to the destination buffer
+ * @param  size  length of data
+ *
+ * @return esp_err_t
+ */
+esp_err_t spi_flash_read_encrypted(size_t src, void *dest, size_t size);
+
+/**
+ * @brief Enumeration which specifies memory space requested in an mmap call
+ */
+typedef enum {
+    SPI_FLASH_MMAP_DATA,    /**< map to data memory (Vaddr0), allows byte-aligned access, 4 MB total */
+    SPI_FLASH_MMAP_INST,    /**< map to instruction memory (Vaddr1-3), allows only 4-byte-aligned access, 11 MB total */
+} spi_flash_mmap_memory_t;
+
+/**
+ * @brief Opaque handle for memory region obtained from spi_flash_mmap.
+ */
+typedef uint32_t spi_flash_mmap_handle_t;
+
+/**
+ * @brief Map region of flash memory into data or instruction address space
+ *
+ * This function allocates sufficient number of 64kB MMU pages and configures
+ * them to map the requested region of flash memory into the address space.
+ * It may reuse MMU pages which already provide the required mapping.
+ *
+ * As with any allocator, if mmap/munmap are heavily used then the address space
+ * may become fragmented. To troubleshoot issues with page allocation, use
+ * spi_flash_mmap_dump() function.
+ *
+ * @param src_addr  Physical address in flash where requested region starts.
+ *                  This address *must* be aligned to 64kB boundary
+ *                  (SPI_FLASH_MMU_PAGE_SIZE)
+ * @param size  Size of region to be mapped. This size will be rounded
+ *              up to a 64kB boundary
+ * @param memory  Address space where the region should be mapped (data or instruction)
+ * @param out_ptr  Output, pointer to the mapped memory region
+ * @param out_handle  Output, handle which should be used for spi_flash_munmap call
+ *
+ * @return  ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
+ */
+esp_err_t spi_flash_mmap(size_t src_addr, size_t size, spi_flash_mmap_memory_t memory,
+                         const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
+
+/**
+ * @brief Map sequences of pages of flash memory into data or instruction address space
+ *
+ * This function allocates sufficient number of 64kB MMU pages and configures
+ * them to map the indicated pages of flash memory contiguously into address space.
+ * In this respect, it works in a similar way as spi_flash_mmap() but it allows mapping
+ * a (maybe non-contiguous) set of pages into a contiguous region of memory.
+ *
+ * @param pages An array of numbers indicating the 64kB pages in flash to be mapped
+ *              contiguously into memory. These indicate the indexes of the 64kB pages,
+ *              not the byte-size addresses as used in other functions.
+ * @param pagecount  Number of entries in the pages array
+ * @param memory  Address space where the region should be mapped (instruction or data)
+ * @param out_ptr  Output, pointer to the mapped memory region
+ * @param out_handle  Output, handle which should be used for spi_flash_munmap call
+ *
+ * @return  ESP_OK on success, ESP_ERR_NO_MEM if pages can not be allocated
+ */
+esp_err_t spi_flash_mmap_pages(int *pages, size_t pagecount, spi_flash_mmap_memory_t memory,
+                         const void** out_ptr, spi_flash_mmap_handle_t* out_handle);
+
+
+/**
+ * @brief Release region previously obtained using spi_flash_mmap
+ *
+ * @note Calling this function will not necessarily unmap memory region.
+ *       Region will only be unmapped when there are no other handles which
+ *       reference this region. In case of partially overlapping regions
+ *       it is possible that memory will be unmapped partially.
+ *
+ * @param handle  Handle obtained from spi_flash_mmap
+ */
+void spi_flash_munmap(spi_flash_mmap_handle_t handle);
+
+/**
+ * @brief Display information about mapped regions
+ *
+ * This function lists handles obtained using spi_flash_mmap, along with range
+ * of pages allocated to each handle. It also lists all non-zero entries of
+ * MMU table and corresponding reference counts.
+ */
+void spi_flash_mmap_dump(void);
+
+/**
+ * @brief get free pages number which can be mmap
+ *
+ * This function will return free page number of the mmu table which can mmap,
+ * when you want to call spi_flash_mmap to mmap an ranger of flash data to Dcache or Icache
+ * memmory region, maybe the size of  MMU table will exceed,so if you are not sure the
+ * size need mmap is ok, can call the interface and watch how many MMU table page can be
+ * mmaped.
+ *
+ * @param memory  memmory type of MMU table free page
+ *
+ * @return  number of free pages which can be mmaped
+ */
+uint32_t spi_flash_mmap_get_free_pages(spi_flash_mmap_memory_t memory);
+
+
+#define SPI_FLASH_CACHE2PHYS_FAIL UINT32_MAX /*<! Result from spi_flash_cache2phys() if flash cache address is invalid */
+
+/**
+ * @brief Given a memory address where flash is mapped, return the corresponding physical flash offset.
+ *
+ * Cache address does not have have been assigned via spi_flash_mmap(), any address in memory mapped flash space can be looked up.
+ *
+ * @param cached Pointer to flashed cached memory.
+ *
+ * @return
+ * - SPI_FLASH_CACHE2PHYS_FAIL If cache address is outside flash cache region, or the address is not mapped.
+ * - Otherwise, returns physical offset in flash
+ */
+size_t spi_flash_cache2phys(const void *cached);
+
+/** @brief Given a physical offset in flash, return the address where it is mapped in the memory space.
+ *
+ * Physical address does not have to have been assigned via spi_flash_mmap(), any address in flash can be looked up.
+ *
+ * @note Only the first matching cache address is returned. If MMU flash cache table is configured so multiple entries
+ * point to the same physical address, there may be more than one cache address corresponding to that physical
+ * address. It is also possible for a single physical address to be mapped to both the IROM and DROM regions.
+ *
+ * @note This function doesn't impose any alignment constraints, but if memory argument is SPI_FLASH_MMAP_INST and
+ * phys_offs is not 4-byte aligned, then reading from the returned pointer will result in a crash.
+ *
+ * @param phys_offs Physical offset in flash memory to look up.
+ * @param memory Address space type to look up a flash cache address mapping for (instruction or data)
+ *
+ * @return
+ * - NULL if the physical address is invalid or not mapped to flash cache of the specified memory type.
+ * - Cached memory address (in IROM or DROM space) corresponding to phys_offs.
+ */
+const void *spi_flash_phys2cache(size_t phys_offs, spi_flash_mmap_memory_t memory);
+
+/** @brief Check at runtime if flash cache is enabled on both CPUs
+ *
+ * @return true if both CPUs have flash cache enabled, false otherwise.
+ */
+bool spi_flash_cache_enabled(void);
+
+/**
+ * @brief SPI flash critical section enter function.
+ *
+ */
+typedef void (*spi_flash_guard_start_func_t)(void);
+/**
+ * @brief SPI flash critical section exit function.
+ */
+typedef void (*spi_flash_guard_end_func_t)(void);
+/**
+ * @brief SPI flash operation lock function.
+ */
+typedef void (*spi_flash_op_lock_func_t)(void);
+/**
+ * @brief SPI flash operation unlock function.
+ */
+typedef void (*spi_flash_op_unlock_func_t)(void);
+
+/**
+ * Structure holding SPI flash access critical sections management functions.
+ *
+ * Flash API uses two types of flash access management functions:
+ * 1) Functions which prepare/restore flash cache and interrupts before calling
+ *    appropriate ROM functions (SPIWrite, SPIRead and SPIEraseBlock):
+ *   - 'start' function should disables flash cache and non-IRAM interrupts and
+ *      is invoked before the call to one of ROM function above.
+ *   - 'end' function should restore state of flash cache and non-IRAM interrupts and
+ *      is invoked after the call to one of ROM function above.
+ *    These two functions are not recursive.
+ * 2) Functions which synchronizes access to internal data used by flash API.
+ *    This functions are mostly intended to synchronize access to flash API internal data
+ *    in multithreaded environment and use OS primitives:
+ *   - 'op_lock' locks access to flash API internal data.
+ *   - 'op_unlock' unlocks access to flash API internal data.
+ *   These two functions are recursive and can be used around the outside of multiple calls to
+ *   'start' & 'end', in order to create atomic multi-part flash operations.
+ *
+ * Different versions of the guarding functions should be used depending on the context of
+ * execution (with or without functional OS). In normal conditions when flash API is called
+ * from task the functions use OS primitives. When there is no OS at all or when
+ * it is not guaranteed that OS is functional (accessing flash from exception handler) these
+ * functions cannot use OS primitives or even does not need them (multithreaded access is not possible).
+ *
+ * @note Structure and corresponding guard functions should not reside in flash.
+ *       For example structure can be placed in DRAM and functions in IRAM sections.
+ */
+typedef struct {
+    spi_flash_guard_start_func_t    start;      /**< critical section start function. */
+    spi_flash_guard_end_func_t      end;        /**< critical section end function. */
+    spi_flash_op_lock_func_t        op_lock;    /**< flash access API lock function.*/
+    spi_flash_op_unlock_func_t      op_unlock;  /**< flash access API unlock function.*/
+} spi_flash_guard_funcs_t;
+
+/**
+ * @brief  Sets guard functions to access flash.
+ *
+ * @note Pointed structure and corresponding guard functions should not reside in flash.
+ *       For example structure can be placed in DRAM and functions in IRAM sections.
+ *
+ * @param funcs pointer to structure holding flash access guard functions.
+ */
+void spi_flash_guard_set(const spi_flash_guard_funcs_t* funcs);
+
+
+/**
+ * @brief Get the guard functions used for flash access
+ *
+ * @return The guard functions that were set via spi_flash_guard_set(). These functions
+ * can be called if implementing custom low-level SPI flash operations.
+ */
+const spi_flash_guard_funcs_t *spi_flash_guard_get(void);
+
+/**
+ * @brief Default OS-aware flash access guard functions
+ */
+extern const spi_flash_guard_funcs_t g_flash_guard_default_ops;
+
+/**
+ * @brief Non-OS flash access guard functions
+ *
+ * @note This version of flash guard functions is to be used when no OS is present or from panic handler.
+ *       It does not use any OS primitives and IPC and implies that only calling CPU is active.
+ */
+extern const spi_flash_guard_funcs_t g_flash_guard_no_os_ops;
+
+#if CONFIG_SPI_FLASH_ENABLE_COUNTERS
+
+/**
+ * Structure holding statistics for one type of operation
+ */
+typedef struct {
+    uint32_t count;     // number of times operation was executed
+    uint32_t time;      // total time taken, in microseconds
+    uint32_t bytes;     // total number of bytes
+} spi_flash_counter_t;
+
+typedef struct {
+    spi_flash_counter_t read;
+    spi_flash_counter_t write;
+    spi_flash_counter_t erase;
+} spi_flash_counters_t;
+
+/**
+ * @brief  Reset SPI flash operation counters
+ */
+void spi_flash_reset_counters(void);
+
+/**
+ * @brief  Print SPI flash operation counters
+ */
+void spi_flash_dump_counters(void);
+
+/**
+ * @brief  Return current SPI flash operation counters
+ *
+ * @return  pointer to the spi_flash_counters_t structure holding values
+ *          of the operation counters
+ */
+const spi_flash_counters_t* spi_flash_get_counters(void);
+
+#endif //CONFIG_SPI_FLASH_ENABLE_COUNTERS
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* SPI_FLASH_ESP_SPI_FLASH_H */
diff --git a/cpu/esp32/vendor/esp-idf/include/tcpip_adapter/tcpip_adapter.h b/cpu/esp32/vendor/esp-idf/include/tcpip_adapter/tcpip_adapter.h
new file mode 100644
index 0000000000000000000000000000000000000000..6666b12d7f7b410f3db7c93e3d450f0ec8e27644
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/include/tcpip_adapter/tcpip_adapter.h
@@ -0,0 +1,656 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef TCPIP_ADAPTER_TCPIP_ADAPTER_H
+#define TCPIP_ADAPTER_TCPIP_ADAPTER_H
+
+/**
+ * @brief TCPIP adapter library
+ *
+ * The aim of this adapter is to provide an abstract layer upon TCPIP stack.
+ * With this layer, switch to other TCPIP stack is possible and easy in esp-idf.
+ *
+ * If users want to use other TCPIP stack, all those functions should be implemented
+ * by using the specific APIs of that stack. The macros in CONFIG_TCPIP_LWIP should be
+ * re-defined.
+ *
+ * tcpip_adapter_init should be called in the start of app_main for only once.
+ *
+ * Currently most adapter APIs are called in event_default_handlers.c.
+ *
+ * We recommend users only use set/get IP APIs, DHCP server/client APIs,
+ * get free station list APIs in application side. Other APIs are used in esp-idf internal,
+ * otherwise the state maybe wrong.
+ *
+ * TODO: ipv6 support will be added, use menuconfig to disable CONFIG_TCPIP_LWIP
+ */
+
+#include <stdint.h>
+#include "rom/queue.h"
+#include "esp_wifi_types.h"
+
+#define CONFIG_TCPIP_LWIP 1
+#define CONFIG_DHCP_STA_LIST 1
+
+#if CONFIG_TCPIP_LWIP
+#ifdef RIOT_VERSION
+#include <stdint.h>
+#include <stdbool.h>
+/* source /path/to/esp-idf/components/lwip/include/lwip/lwip/ip4_addr.h */
+struct ip4_addr {
+  uint32_t addr;
+};
+typedef struct ip4_addr ip4_addr_t;
+
+/* source /path/to/esp-idf/components/lwip/include/lwip/lwip/ip6_addr.h */
+struct ip6_addr {
+  uint32_t addr[4];
+};
+typedef struct ip6_addr ip6_addr_t;
+
+/* source /path/to/esp-idf/components/lwip/include/lwip/lwip/ip_addr.h */
+typedef struct _ip_addr {
+  union {
+    ip6_addr_t ip6;
+    ip4_addr_t ip4;
+  } u_addr;
+  uint8_t type;
+} ip_addr_t;
+
+/* source /path/to/esp-idf/components/lwip/include/lwip/apps/dhcpserver.h */
+typedef struct {
+    bool enable;
+    ip4_addr_t start_ip;
+    ip4_addr_t end_ip;
+} dhcps_lease_t;
+
+
+#else /* RIOT_VERSION */
+#include "lwip/ip_addr.h"
+#include "apps/dhcpserver.h"
+#endif /* RIOT_VERSION */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define IP2STR(ipaddr) ip4_addr1_16(ipaddr), \
+    ip4_addr2_16(ipaddr), \
+    ip4_addr3_16(ipaddr), \
+    ip4_addr4_16(ipaddr)
+
+#define IPSTR "%d.%d.%d.%d"
+
+#define IPV62STR(ipaddr) IP6_ADDR_BLOCK1(&(ipaddr)),     \
+    IP6_ADDR_BLOCK2(&(ipaddr)),     \
+    IP6_ADDR_BLOCK3(&(ipaddr)),     \
+    IP6_ADDR_BLOCK4(&(ipaddr)),     \
+    IP6_ADDR_BLOCK5(&(ipaddr)),     \
+    IP6_ADDR_BLOCK6(&(ipaddr)),     \
+    IP6_ADDR_BLOCK7(&(ipaddr)),     \
+    IP6_ADDR_BLOCK8(&(ipaddr))
+
+#define IPV6STR "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x"
+
+typedef struct {
+    ip4_addr_t ip;
+    ip4_addr_t netmask;
+    ip4_addr_t gw;
+} tcpip_adapter_ip_info_t;
+
+typedef struct {
+    ip6_addr_t ip;
+} tcpip_adapter_ip6_info_t;
+
+typedef dhcps_lease_t tcpip_adapter_dhcps_lease_t;
+
+#if CONFIG_DHCP_STA_LIST
+typedef struct {
+    uint8_t mac[6];
+    ip4_addr_t ip;
+} tcpip_adapter_sta_info_t;
+
+typedef struct {
+    tcpip_adapter_sta_info_t sta[ESP_WIFI_MAX_CONN_NUM];
+    int num;
+} tcpip_adapter_sta_list_t;
+#endif
+
+#endif
+
+#define ESP_ERR_TCPIP_ADAPTER_BASE      0x5000      // TODO: move base address to esp_err.h
+
+#define ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS        ESP_ERR_TCPIP_ADAPTER_BASE + 0x01
+#define ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY          ESP_ERR_TCPIP_ADAPTER_BASE + 0x02
+#define ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED    ESP_ERR_TCPIP_ADAPTER_BASE + 0x03
+#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED  ESP_ERR_TCPIP_ADAPTER_BASE + 0x04
+#define ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED  ESP_ERR_TCPIP_ADAPTER_BASE + 0x05
+#define ESP_ERR_TCPIP_ADAPTER_NO_MEM                ESP_ERR_TCPIP_ADAPTER_BASE + 0x06
+#define ESP_ERR_TCPIP_ADAPTER_DHCP_NOT_STOPPED      ESP_ERR_TCPIP_ADAPTER_BASE + 0x07
+
+/* TODO: add Ethernet interface */
+typedef enum {
+    TCPIP_ADAPTER_IF_STA = 0,     /**< ESP32 station interface */
+    TCPIP_ADAPTER_IF_AP,          /**< ESP32 soft-AP interface */
+    TCPIP_ADAPTER_IF_ETH,         /**< ESP32 ethernet interface */
+    TCPIP_ADAPTER_IF_MAX
+} tcpip_adapter_if_t;
+
+/*type of DNS server*/
+typedef enum {
+    TCPIP_ADAPTER_DNS_MAIN= 0,       /**DNS main server address*/
+    TCPIP_ADAPTER_DNS_BACKUP,        /**DNS backup server address,for STA only,support soft-AP in future*/
+    TCPIP_ADAPTER_DNS_FALLBACK,      /**DNS fallback server address,for STA only*/
+    TCPIP_ADAPTER_DNS_MAX            /**Max DNS */
+} tcpip_adapter_dns_type_t;
+
+/*info of DNS server*/
+typedef struct {
+    ip_addr_t ip;
+} tcpip_adapter_dns_info_t;
+
+/* status of DHCP client or DHCP server */
+typedef enum {
+    TCPIP_ADAPTER_DHCP_INIT = 0,    /**< DHCP client/server in initial state */
+    TCPIP_ADAPTER_DHCP_STARTED,     /**< DHCP client/server already been started */
+    TCPIP_ADAPTER_DHCP_STOPPED,     /**< DHCP client/server already been stopped */
+    TCPIP_ADAPTER_DHCP_STATUS_MAX
+} tcpip_adapter_dhcp_status_t;
+
+/* set the option mode for DHCP client or DHCP server */
+typedef enum{
+    TCPIP_ADAPTER_OP_START = 0,
+    TCPIP_ADAPTER_OP_SET,           /**< set option mode */
+    TCPIP_ADAPTER_OP_GET,           /**< get option mode */
+    TCPIP_ADAPTER_OP_MAX
+} tcpip_adapter_option_mode_t;
+
+typedef enum{
+    TCPIP_ADAPTER_DOMAIN_NAME_SERVER            = 6,    /**< domain name server */
+    TCPIP_ADAPTER_ROUTER_SOLICITATION_ADDRESS   = 32,   /**< solicitation router address */
+    TCPIP_ADAPTER_REQUESTED_IP_ADDRESS          = 50,   /**< request IP address pool */
+    TCPIP_ADAPTER_IP_ADDRESS_LEASE_TIME         = 51,   /**< request IP address lease time */
+    TCPIP_ADAPTER_IP_REQUEST_RETRY_TIME         = 52,   /**< request IP address retry counter */
+} tcpip_adapter_option_id_t;
+
+struct tcpip_adapter_api_msg_s;
+typedef int (*tcpip_adapter_api_fn)(struct tcpip_adapter_api_msg_s *msg);
+typedef struct tcpip_adapter_api_msg_s {
+    int type;  /**< The first field MUST be int */
+    int ret;
+    tcpip_adapter_api_fn api_fn;
+    tcpip_adapter_if_t tcpip_if;
+    tcpip_adapter_ip_info_t *ip_info;
+    uint8_t *mac;
+    void    *data;
+} tcpip_adapter_api_msg_t;
+
+typedef struct tcpip_adapter_dns_param_s {
+    tcpip_adapter_dns_type_t dns_type;
+    tcpip_adapter_dns_info_t *dns_info;
+} tcpip_adapter_dns_param_t;
+
+#define TCPIP_ADAPTER_TRHEAD_SAFE 1
+#define TCPIP_ADAPTER_IPC_LOCAL   0
+#define TCPIP_ADAPTER_IPC_REMOTE  1
+
+#define TCPIP_ADAPTER_IPC_CALL(_if, _mac, _ip, _data, _fn) do {\
+    tcpip_adapter_api_msg_t msg;\
+    if (tcpip_inited == false) {\
+        ESP_LOGE(TAG, "tcpip_adapter is not initialized!");\
+        abort();\
+    }\
+    memset(&msg, 0, sizeof(msg));\
+    msg.tcpip_if = (_if);\
+    msg.mac      = (uint8_t*)(_mac);\
+    msg.ip_info  = (tcpip_adapter_ip_info_t*)(_ip);\
+    msg.data     = (void*)(_data);\
+    msg.api_fn   = (_fn);\
+    if (TCPIP_ADAPTER_IPC_REMOTE == tcpip_adapter_ipc_check(&msg)) {\
+        ESP_LOGV(TAG, "check: remote, if=%d fn=%p\n", (_if), (_fn));\
+        return msg.ret;\
+    } else {\
+        ESP_LOGV(TAG, "check: local, if=%d fn=%p\n", (_if), (_fn));\
+    }\
+}while(0)
+
+typedef struct tcpip_adatper_ip_lost_timer_s {
+    bool timer_running;
+} tcpip_adapter_ip_lost_timer_t;
+
+/**
+ * @brief  Initialize tcpip adapter
+ *
+ * This will initialize TCPIP stack inside.
+ */
+void tcpip_adapter_init(void);
+
+/**
+ * @brief  Start the ethernet interface with specific MAC and IP
+ *
+ * @param[in]  mac: set MAC address of this interface
+ * @param[in]  ip_info: set IP address of this interface
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_NO_MEM
+ */
+esp_err_t tcpip_adapter_eth_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info);
+
+/**
+ * @brief  Start the Wi-Fi station interface with specific MAC and IP
+ *
+ * Station interface will be initialized, connect WiFi stack with TCPIP stack.
+ *
+ * @param[in]  mac: set MAC address of this interface
+ * @param[in]  ip_info: set IP address of this interface
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_NO_MEM
+ */
+esp_err_t tcpip_adapter_sta_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info);
+
+/**
+ * @brief  Start the Wi-Fi AP interface with specific MAC and IP
+ *
+ * softAP interface will be initialized, connect WiFi stack with TCPIP stack.
+ *
+ * DHCP server will be started automatically.
+ *
+ * @param[in]  mac: set MAC address of this interface
+ * @param[in]  ip_info: set IP address of this interface
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_NO_MEM
+ */
+esp_err_t tcpip_adapter_ap_start(uint8_t *mac, tcpip_adapter_ip_info_t *ip_info);
+
+/**
+ * @brief  Stop an interface
+ *
+ * The interface will be cleanup in this API, if DHCP server/client are started, will be stopped.
+ *
+ * @param[in]  tcpip_if: the interface which will be started
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
+ */
+esp_err_t tcpip_adapter_stop(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  Bring up an interface
+ *
+ * Only station interface need to be brought up, since station interface will be shut down when disconnect.
+ *
+ * @param[in]  tcpip_if: the interface which will be up
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
+ */
+esp_err_t tcpip_adapter_up(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  Shut down an interface
+ *
+ * Only station interface need to be shut down, since station interface will be brought up when connect.
+ *
+ * @param[in]  tcpip_if: the interface which will be down
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
+ */
+esp_err_t tcpip_adapter_down(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  Get interface's IP information
+ *
+ * There has an IP information copy in adapter library, if interface is up, get IP information from
+ * interface, otherwise get from copy.
+ *
+ * @param[in]   tcpip_if: the interface which we want to get IP information
+ * @param[out]  ip_info: If successful, IP information will be returned in this argument.
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_get_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info);
+
+/**
+ * @brief  Set interface's IP information
+ *
+ * There has an IP information copy in adapter library, if interface is up, also set interface's IP.
+ * DHCP client/server should be stopped before set new IP information.
+ *
+ * This function is mainly used for setting static IP.
+ *
+ * @param[in]  tcpip_if: the interface which we want to set IP information
+ * @param[in]  ip_info: store the IP information which needs to be set to specified interface
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_set_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info);
+
+/**
+ * @brief  Set DNS Server's information
+ *
+ * There has an DNS Server information copy in adapter library, set DNS Server for appointed interface and type.
+ *
+ * 1.In station mode, if dhcp client is enabled, then only the fallback DNS server can be set(TCPIP_ADAPTER_DNS_FALLBACK).
+ *   Fallback DNS server is only used if no DNS servers are set via DHCP.
+ *   If dhcp client is disabled, then need to set main/backup dns server(TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP).
+ *
+ * 2.In soft-AP mode, the DNS Server's main dns server offered to the station is the IP address of soft-AP,
+ *   if the application don't want to use the IP address of soft-AP, they can set the main dns server.
+ *
+ * This function is mainly used for setting static or Fallback DNS Server.
+ *
+ * @param[in]  tcpip_if: the interface which we want to set DNS Server information
+ * @param[in]  type: the type of DNS Server,including TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK
+ * @param[in]  dns:  the DNS Server address to be set
+ *
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params
+ */
+esp_err_t tcpip_adapter_set_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns);
+
+/**
+ * @brief  Get DNS Server's information
+ *
+ * When set the DNS Server information successfully, can get the DNS Server's information via the appointed tcpip_if and type
+ *
+ * This function is mainly used for getting DNS Server information.
+ *
+ * @param[in]  tcpip_if: the interface which we want to get DNS Server information
+ * @param[in]  type: the type of DNS Server,including TCPIP_ADAPTER_DNS_MAIN, TCPIP_ADAPTER_DNS_BACKUP, TCPIP_ADAPTER_DNS_FALLBACK
+ * @param[in]  dns:  the DNS Server address to be get
+ *
+ * @return
+ *      - ESP_OK on success
+ *      - ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS invalid params
+ */
+esp_err_t tcpip_adapter_get_dns_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dns_type_t type, tcpip_adapter_dns_info_t *dns);
+
+/**
+ * @brief  Get interface's old IP information
+ *
+ * When the interface successfully gets a valid IP from DHCP server or static configured, a copy of
+ * the IP information is set to the old IP information. When IP lost timer expires, the old IP
+ * information is reset to 0.
+ *
+ * @param[in]   tcpip_if: the interface which we want to get old IP information
+ * @param[out]  ip_info: If successful, IP information will be returned in this argument.
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_get_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info);
+
+/**
+ * @brief  Set interface's old IP information
+ *
+ * When the interface successfully gets a valid IP from DHCP server or static configured, a copy of
+ * the IP information is set to the old IP information. When IP lost timer expires, the old IP
+ * information is reset to 0.
+ *
+ * @param[in]  tcpip_if: the interface which we want to set old IP information
+ * @param[in]  ip_info: store the IP information which needs to be set to specified interface
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_set_old_ip_info(tcpip_adapter_if_t tcpip_if, tcpip_adapter_ip_info_t *ip_info);
+
+
+/**
+ * @brief  create interface's linklocal IPv6 information
+ *
+ * @note this function will create a linklocal IPv6 address about input interface,
+ *       if this address status changed to preferred, will call event call back ,
+ *       notify user linklocal IPv6 address has been verified
+ *
+ * @param[in]  tcpip_if: the interface which we want to set IP information
+ *
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_create_ip6_linklocal(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  get interface's linkloacl IPv6 information
+ *
+ * There has an IPv6 information copy in adapter library, if interface is up,and IPv6 info
+ * is preferred,it will get IPv6 linklocal IP successfully
+ *
+ * @param[in]  tcpip_if: the interface which we want to set IP information
+ * @param[in]  if_ip6: If successful, IPv6 information will be returned in this argument.
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_get_ip6_linklocal(tcpip_adapter_if_t tcpip_if, ip6_addr_t *if_ip6);
+
+#if 0
+esp_err_t tcpip_adapter_get_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac);
+
+esp_err_t tcpip_adapter_set_mac(tcpip_adapter_if_t tcpip_if, uint8_t *mac);
+#endif
+
+/**
+ * @brief  Get DHCP server's status
+ *
+ * @param[in]   tcpip_if: the interface which we will get status of DHCP server
+ * @param[out]  status: If successful, the status of DHCP server will be return in this argument.
+ *
+ * @return ESP_OK
+ */
+esp_err_t tcpip_adapter_dhcps_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status);
+
+/**
+ * @brief  Set or Get DHCP server's option
+ *
+ * @param[in]  opt_op: option operate type, 1 for SET, 2 for GET.
+ * @param[in]  opt_id: option index, 32 for ROUTER, 50 for IP POLL, 51 for LEASE TIME, 52 for REQUEST TIME
+ * @param[in]  opt_val: option parameter
+ * @param[in]  opt_len: option length
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPPED
+ *         ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED
+ */
+esp_err_t tcpip_adapter_dhcps_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len);
+
+/**
+ * @brief  Start DHCP server
+ *
+ * @note   Currently DHCP server is bind to softAP interface.
+ *
+ * @param[in]  tcpip_if: the interface which we will start DHCP server
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED
+ */
+esp_err_t tcpip_adapter_dhcps_start(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  Stop DHCP server
+ *
+ * @note   Currently DHCP server is bind to softAP interface.
+ *
+ * @param[in]  tcpip_if: the interface which we will stop DHCP server
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
+ */
+esp_err_t tcpip_adapter_dhcps_stop(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  Get DHCP client status
+ *
+ * @param[in]  tcpip_if: the interface which we will get status of DHCP client
+ * @param[out]  status: If successful, the status of DHCP client will be return in this argument.
+ *
+ * @return ESP_OK
+ */
+esp_err_t tcpip_adapter_dhcpc_get_status(tcpip_adapter_if_t tcpip_if, tcpip_adapter_dhcp_status_t *status);
+
+/**
+ * @brief  Set or Get DHCP client's option
+ *
+ * @note   This function is not implement now.
+ *
+ * @param[in]  opt_op: option operate type, 1 for SET, 2 for GET.
+ * @param[in]  opt_id: option index, 32 for ROUTER, 50 for IP POLL, 51 for LEASE TIME, 52 for REQUEST TIME
+ * @param[in]  opt_val: option parameter
+ * @param[in]  opt_len: option length
+ *
+ * @return ESP_OK
+ */
+esp_err_t tcpip_adapter_dhcpc_option(tcpip_adapter_option_mode_t opt_op, tcpip_adapter_option_id_t opt_id, void *opt_val, uint32_t opt_len);
+
+/**
+ * @brief  Start DHCP client
+ *
+ * @note   Currently DHCP client is bind to station interface.
+ *
+ * @param[in]  tcpip_if: the interface which we will start DHCP client
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STARTED
+ *         ESP_ERR_TCPIP_ADAPTER_DHCPC_START_FAILED
+ */
+esp_err_t tcpip_adapter_dhcpc_start(tcpip_adapter_if_t tcpip_if);
+
+/**
+ * @brief  Stop DHCP client
+ *
+ * @note   Currently DHCP client is bind to station interface.
+ *
+ * @param[in]  tcpip_if: the interface which we will stop DHCP client
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ *         ESP_ERR_TCPIP_ADAPTER_DHCP_ALREADY_STOPED
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY
+ */
+esp_err_t tcpip_adapter_dhcpc_stop(tcpip_adapter_if_t tcpip_if);
+
+
+
+esp_err_t tcpip_adapter_eth_input(void *buffer, uint16_t len, void *eb);
+
+/**
+ * @brief  Get data from station interface
+ *
+ * This function should be installed by esp_wifi_reg_rxcb, so WiFi packets will be forward to TCPIP stack.
+ *
+ * @param[in]  void *buffer: the received data point
+ * @param[in]  uint16_t len: the received data length
+ * @param[in]  void *eb: parameter
+ *
+ * @return ESP_OK
+ */
+esp_err_t tcpip_adapter_sta_input(void *buffer, uint16_t len, void *eb);
+
+/**
+ * @brief  Get data from softAP interface
+ *
+ * This function should be installed by esp_wifi_reg_rxcb, so WiFi packets will be forward to TCPIP stack.
+ *
+ * @param[in]  void *buffer: the received data point
+ * @param[in]  uint16_t len: the received data length
+ * @param[in]  void *eb: parameter
+ *
+ * @return ESP_OK
+ */
+esp_err_t tcpip_adapter_ap_input(void *buffer, uint16_t len, void *eb);
+
+/**
+ * @brief  Get WiFi interface index
+ *
+ * Get WiFi interface from TCPIP interface struct pointer.
+ *
+ * @param[in]  void *dev: adapter interface
+ *
+ * @return ESP_IF_WIFI_STA
+ *         ESP_IF_WIFI_AP
+           ESP_IF_ETH
+ *         ESP_IF_MAX
+ */
+esp_interface_t tcpip_adapter_get_esp_if(void *dev);
+
+/**
+ * @brief  Get the station information list
+ *
+ * @param[in]   wifi_sta_list_t *wifi_sta_list: station list info
+ * @param[out]  tcpip_adapter_sta_list_t *tcpip_sta_list: station list info
+ *
+ * @return ESP_OK
+ *         ESP_ERR_TCPIP_ADAPTER_NO_MEM
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS
+ */
+esp_err_t tcpip_adapter_get_sta_list(wifi_sta_list_t *wifi_sta_list, tcpip_adapter_sta_list_t *tcpip_sta_list);
+
+#define TCPIP_HOSTNAME_MAX_SIZE    32
+/**
+ * @brief  Set the hostname to the interface
+ *
+ * @param[in]   tcpip_if: the interface which we will set the hostname
+ * @param[in]   hostname: the host name for set the interface, the max length of hostname is 32 bytes
+ *
+ * @return ESP_OK:success
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error
+ */
+esp_err_t tcpip_adapter_set_hostname(tcpip_adapter_if_t tcpip_if, const char *hostname);
+
+/**
+ * @brief  Get the hostname from the interface
+ *
+ * @param[in]   tcpip_if: the interface which we will get the hostname
+ * @param[in]   hostname: the host name from the interface
+ *
+ * @return ESP_OK:success
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error
+ */
+esp_err_t tcpip_adapter_get_hostname(tcpip_adapter_if_t tcpip_if, const char **hostname);
+
+/**
+ * @brief  Get the LwIP netif* that is assigned to the interface
+ *
+ * @param[in]   tcpip_if: the interface which we will get the hostname
+ * @param[out]  void ** netif: pointer to fill the resulting interface
+ *
+ * @return ESP_OK:success
+ *         ESP_ERR_TCPIP_ADAPTER_IF_NOT_READY:interface status error
+ *         ESP_ERR_TCPIP_ADAPTER_INVALID_PARAMS:parameter error
+ */
+esp_err_t tcpip_adapter_get_netif(tcpip_adapter_if_t tcpip_if, void ** netif);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* TCPIP_ADAPTER_TCPIP_ADAPTER_H */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/.gitignore b/cpu/esp32/vendor/esp-idf/nvs_flash/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..3318e40684b2b381d1881e8386957d4ee0696283
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/.gitignore
@@ -0,0 +1,7 @@
+test_nvs_host/test_nvs
+test_nvs_host/coverage_report
+test_nvs_host/coverage.info
+**/*.gcno
+**/*.gcda
+**/*.gcov
+**/*.o
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/Makefile b/cpu/esp32/vendor/esp-idf/nvs_flash/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..f92caf4df7f11ac7aa875938c516e8920746cc1e
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/Makefile
@@ -0,0 +1,9 @@
+MODULE=esp_idf_nvs_flash
+
+include $(RIOTBASE)/Makefile.base
+
+CFLAGS   += -DESP_PLATFORM
+CXXFLAGS += -std=c++11
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(ESP32_SDK_DIR)/components/nvs_flash/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/spi_flash/include
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/README.rst b/cpu/esp32/vendor/esp-idf/nvs_flash/README.rst
new file mode 100644
index 0000000000000000000000000000000000000000..5ce1eff373691d756d2dc386363aeadf49ff959e
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/README.rst
@@ -0,0 +1,233 @@
+Non-volatile storage library
+============================
+
+Introduction
+------------
+
+Non-volatile storage (NVS) library is designed to store key-value pairs in flash. This sections introduces some concepts used by NVS.
+
+Underlying storage
+^^^^^^^^^^^^^^^^^^
+
+Currently NVS uses a portion of main flash memory through ``spi_flash_{read|write|erase}`` APIs. The library uses the all the partitions with ``data`` type and ``nvs`` subtype. The application can choose to use the partition with label ``nvs`` through ``nvs_open`` API or any of the other partition by specifying its name through ``nvs_open_from_part`` API.
+
+Future versions of this library may add other storage backends to keep data in another flash chip (SPI or I2C), RTC, FRAM, etc.
+
+.. note:: if an NVS partition is truncated (for example, when the partition table layout is changed), its contents should be erased. ESP-IDF build system provides a ``make erase_flash`` target to erase all contents of the flash chip.
+
+.. note:: NVS works best for storing many small values, rather than a few large values of type 'string' and 'blob'. If storing large blobs or strings is required, consider using the facilities provided by the FAT filesystem on top of the wear levelling library.
+
+Keys and values
+^^^^^^^^^^^^^^^
+
+NVS operates on key-value pairs. Keys are ASCII strings, maximum key length is currently 15 characters. Values can have one of the following types:
+
+-  integer types: ``uint8_t``, ``int8_t``, ``uint16_t``, ``int16_t``, ``uint32_t``, ``int32_t``, ``uint64_t``, ``int64_t``
+-  zero-terminated string
+-  variable length binary data (blob)
+
+.. note::
+   String and blob values are currently limited to 1984 bytes. For strings, this includes the null terminator.
+
+Additional types, such as ``float`` and ``double`` may be added later.
+
+Keys are required to be unique. Writing a value for a key which already exists behaves as follows:
+
+-  if the new value is of the same type as old one, value is updated
+-  if the new value has different data type, an error is returned
+
+Data type check is also performed when reading a value. An error is returned if data type of read operation doesn’t match the data type of the value.
+
+Namespaces
+^^^^^^^^^^
+
+To mitigate potential conflicts in key names between different components, NVS assigns each key-value pair to one of namespaces. Namespace names follow the same rules as key names, i.e. 15 character maximum length. Namespace name is specified in the ``nvs_open`` or ``nvs_open_from_part`` call. This call returns an opaque handle, which is used in subsequent calls to ``nvs_read_*``, ``nvs_write_*``, and ``nvs_commit`` functions. This way, handle is associated with a namespace, and key names will not collide with same names in other namespaces.
+Please note that the namespaces with same name in different NVS partitions are considered as separate namespaces.
+
+Security, tampering, and robustness
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+NVS library doesn't implement tamper prevention measures. It is possible for anyone with physical access to the flash chip to alter, erase, or add key-value pairs.
+
+NVS is compatible with the ESP32 flash encryption system, and it can store  key-value pairs in an encrypted form. Some metadata, like page state and write/erase flags of individual entries can not be encrypted as they are represented as bits of flash memory for efficient access and manipulation. Flash encryption can prevent some forms of modification:
+
+- replacing keys or values with arbitrary data
+- changing data types of values
+
+The following forms of modification are still possible when flash encryption is used:
+
+- erasing a page completely, removing all key-value pairs which were stored in that page
+- corrupting data in a page, which will cause the page to be erased automatically when such condition is detected
+- rolling back the contents of flash memory to an earlier snapshot
+- merging two snapshots of flash memory, rolling back some key-value pairs to an earlier state (although this is possible to mitigate with the current design — TODO)
+
+The library does try to recover from conditions when flash memory is in an inconsistent state. In particular, one should be able to power off the device at any point and time and then power it back on. This should not result in loss of data, expect for the new key-value pair if it was being written at the moment of power off. The library should also be able to initialize properly with any random data present in flash memory.
+
+Internals
+---------
+
+Log of key-value pairs
+^^^^^^^^^^^^^^^^^^^^^^
+
+NVS stores key-value pairs sequentially, with new key-value pairs being added at the end. When a value of any given key has to be updated, new key-value pair is added at the end of the log and old key-value pair is marked as erased.
+
+Pages and entries
+^^^^^^^^^^^^^^^^^
+
+NVS library uses two main entities in its operation: pages and entries. Page is a logical structure which stores a portion of the overall log. Logical page corresponds to one physical sector of flash memory. Pages which are in use have a *sequence number* associated with them. Sequence numbers impose an ordering on pages. Higher sequence numbers correspond to pages which were created later. Each page can be in one of the following states:
+
+Empty/uninitialized
+    Flash storage for the page is empty (all bytes are ``0xff``). Page isn't used to store any data at this point and doesn’t have a sequence number.
+
+Active
+    Flash storage is initialized, page header has been written to flash, page has a valid sequence number. Page has some empty entries and data can be written there. At most one page can be in this state at any given moment.
+
+Full
+    Flash storage is in a consistent state and is filled with key-value pairs.
+    Writing new key-value pairs into this page is not possible. It is still possible to mark some key-value pairs as erased.
+
+Erasing
+    Non-erased key-value pairs are being moved into another page so that the current page can be erased. This is a transient state, i.e. page should never stay in this state when any API call returns. In case of a sudden power off, move-and-erase process will be completed upon next power on.
+
+Corrupted
+    Page header contains invalid data, and further parsing of page data was canceled. Any items previously written into this page will not be accessible. Corresponding flash sector will not be erased immediately, and will be kept along with sectors in *uninitialized* state for later use. This may be useful for debugging.
+
+Mapping from flash sectors to logical pages doesn't have any particular order. Library will inspect sequence numbers of pages found in each flash sector and organize pages in a list based on these numbers.
+
+::
+
+    +--------+     +--------+     +--------+     +--------+
+    | Page 1 |     | Page 2 |     | Page 3 |     | Page 4 |
+    | Full   +---> | Full   +---> | Active |     | Empty  |   <- states
+    | #11    |     | #12    |     | #14    |     |        |   <- sequence numbers
+    +---+----+     +----+---+     +----+---+     +---+----+
+        |               |              |             |
+        |               |              |             |
+        |               |              |             |
+    +---v------+  +-----v----+  +------v---+  +------v---+
+    | Sector 3 |  | Sector 0 |  | Sector 2 |  | Sector 1 |    <- physical sectors
+    +----------+  +----------+  +----------+  +----------+
+
+Structure of a page
+^^^^^^^^^^^^^^^^^^^
+
+For now we assume that flash sector size is 4096 bytes and that ESP32 flash encryption hardware operates on 32-byte blocks. It is possible to introduce some settings configurable at compile-time (e.g. via menuconfig) to accommodate flash chips with different sector sizes (although it is not clear if other components in the system, e.g. SPI flash driver and SPI flash cache can support these other sizes).
+
+Page consists of three parts: header, entry state bitmap, and entries themselves. To be compatible with ESP32 flash encryption, entry size is 32 bytes. For integer types, entry holds one key-value pair. For strings and blobs, an entry holds part of key-value pair (more on that in the entry structure description).
+
+The following diagram illustrates page structure. Numbers in parentheses indicate size of each part in bytes. ::
+
+    +-----------+--------------+-------------+-----------+
+    | State (4) | Seq. no. (4) | Unused (20) | CRC32 (4) | Header (32)
+    +-----------+--------------+-------------+-----------+
+    |                Entry state bitmap (32)             |
+    +----------------------------------------------------+
+    |                       Entry 0 (32)                 |
+    +----------------------------------------------------+
+    |                       Entry 1 (32)                 |
+    +----------------------------------------------------+
+    /                                                    /
+    /                                                    /
+    +----------------------------------------------------+
+    |                       Entry 125 (32)               |
+    +----------------------------------------------------+
+
+Page header and entry state bitmap are always written to flash unencrypted. Entries are encrypted if flash encryption feature of the ESP32 is used.
+
+Page state values are defined in such a way that changing state is possible by writing 0 into some of the bits. Therefore it not necessary to erase the page to change page state, unless that is a change to *erased* state.
+
+CRC32 value in header is calculated over the part which doesn't include state value (bytes 4 to 28). Unused part is currently filled with ``0xff`` bytes. Future versions of the library may store format version there.
+
+The following sections describe structure of entry state bitmap and entry itself.
+
+Entry and entry state bitmap
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Each entry can be in one of the following three states. Each state is represented with two bits in the entry state bitmap. Final four bits in the bitmap (256 - 2 * 126) are unused.
+
+Empty (2'b11)
+    Nothing is written into the specific entry yet. It is in an uninitialized state (all bytes ``0xff``).
+
+Written (2'b10)
+    A key-value pair (or part of key-value pair which spans multiple entries) has been written into the entry.
+
+Erased (2'b00)
+    A key-value pair in this entry has been discarded. Contents of this entry will not be parsed anymore.
+
+
+Structure of entry
+^^^^^^^^^^^^^^^^^^
+
+For values of primitive types (currently integers from 1 to 8 bytes long), entry holds one key-value pair. For string and blob types, entry holds part of the whole key-value pair. In case when a key-value pair spans multiple entries, all entries are stored in the same page.
+
+::
+
+    +--------+----------+----------+---------+-----------+---------------+----------+
+    | NS (1) | Type (1) | Span (1) | Rsv (1) | CRC32 (4) |    Key (16)   | Data (8) |
+    +--------+----------+----------+---------+-----------+---------------+----------+
+
+                                                   +--------------------------------+
+                             +->    Fixed length:  | Data (8)                       |
+                             |                     +--------------------------------+
+              Data format ---+
+                             |                     +----------+---------+-----------+
+                             +-> Variable length:  | Size (2) | Rsv (2) | CRC32 (4) |
+                                                   +----------+---------+-----------+
+
+
+Individual fields in entry structure have the following meanings:
+
+NS
+    Namespace index for this entry. See section on namespaces implementation for explanation of this value.
+
+Type
+    One byte indicating data type of value. See ``ItemType`` enumeration in ``nvs_types.h`` for possible values.
+
+Span
+    Number of entries used by this key-value pair. For integer types, this is equal to 1. For strings and blobs this depends on value length.
+
+Rsv
+    Unused field, should be ``0xff``.
+
+CRC32
+    Checksum calculated over all the bytes in this entry, except for the CRC32 field itself.
+
+Key
+    Zero-terminated ASCII string containing key name. Maximum string length is 15 bytes, excluding zero terminator.
+
+Data
+    For integer types, this field contains the value itself. If the value itself is shorter than 8 bytes it is padded to the right, with unused bytes filled with ``0xff``. For string and blob values, these 8 bytes hold additional data about the value, described next:
+
+Size
+    (Only for strings and blobs.) Size, in bytes, of actual data. For strings, this includes zero terminator.
+
+CRC32
+    (Only for strings and blobs.) Checksum calculated over all bytes of data.
+
+Variable length values (strings and blobs) are written into subsequent entries, 32 bytes per entry. `Span` field of the first entry indicates how many entries are used.
+
+
+Namespaces
+^^^^^^^^^^
+
+As mentioned above, each key-value pair belongs to one of the namespaces. Namespaces identifiers (strings) are stored as keys of key-value pairs in namespace with index 0. Values corresponding to these keys are indexes of these namespaces.
+
+::
+
+    +-------------------------------------------+
+    | NS=0 Type=uint8_t Key="wifi" Value=1      |   Entry describing namespace "wifi"
+    +-------------------------------------------+
+    | NS=1 Type=uint32_t Key="channel" Value=6  |   Key "channel" in namespace "wifi"
+    +-------------------------------------------+
+    | NS=0 Type=uint8_t Key="pwm" Value=2       |   Entry describing namespace "pwm"
+    +-------------------------------------------+
+    | NS=2 Type=uint16_t Key="channel" Value=20 |   Key "channel" in namespace "pwm"
+    +-------------------------------------------+
+
+
+Item hash list
+^^^^^^^^^^^^^^
+
+To reduce the number of reads performed from flash memory, each member of Page class maintains a list of pairs: (item index; item hash). This list makes searches much quicker. Instead of iterating over all entries, reading them from flash one at a time, ``Page::findItem`` first performs search for item hash in the hash list. This gives the item index within the page, if such an item exists. Due to a hash collision it is possible that a different item will be found. This is handled by falling back to iteration over items in flash.
+
+Each node in hash list contains a 24-bit hash and 8-bit item index. Hash is calculated based on item namespace and key name. CRC32 is used for calculation, result is truncated to 24 bits. To reduce overhead of storing 32-bit entries in a linked list, list is implemented as a doubly-linked list of arrays. Each array holds 29 entries, for the total size of 128 bytes, together with linked list pointers and 32-bit count field. Minimal amount of extra RAM useage per page is therefore 128 bytes, maximum is 640 bytes.
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/compressed_enum_table.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/compressed_enum_table.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..319d86a45ce5ede22db56f504b2c17858bf7a2a6
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/compressed_enum_table.hpp
@@ -0,0 +1,79 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef compressed_enum_table_h
+#define compressed_enum_table_h
+
+#include <cstdint>
+#include <cassert>
+#include <type_traits>
+
+template<typename Tenum, size_t Nbits, size_t Nitems>
+class CompressedEnumTable
+{
+public:
+    uint32_t* data()
+    {
+        return mData;
+    }
+
+    const uint32_t* data() const
+    {
+        return mData;
+    }
+
+    Tenum get(size_t index) const
+    {
+        assert(index >= 0 && index < Nitems);
+        size_t wordIndex = index / ITEMS_PER_WORD;
+        size_t offset = (index % ITEMS_PER_WORD) * Nbits;
+
+        return static_cast<Tenum>((mData[wordIndex] >> offset) & VALUE_MASK);
+    }
+
+    void set(size_t index, Tenum val)
+    {
+        assert(index >= 0 && index < Nitems);
+        size_t wordIndex = index / ITEMS_PER_WORD;
+        size_t offset = (index % ITEMS_PER_WORD) * Nbits;
+
+        uint32_t v = static_cast<uint32_t>(val) << offset;
+        mData[wordIndex] = (mData[wordIndex] & ~(VALUE_MASK << offset)) | v;
+    }
+
+    static constexpr size_t getWordIndex(size_t index)
+    {
+        return index / ITEMS_PER_WORD;
+    }
+
+    static constexpr size_t byteSize()
+    {
+        return WORD_COUNT * 4;
+    }
+
+    static constexpr size_t count()
+    {
+        return Nitems;
+    }
+
+
+protected:
+    static_assert(32 % Nbits == 0, "Nbits must divide 32");
+    static const size_t ITEMS_PER_WORD = 32 / Nbits;
+    static const size_t WORD_COUNT = ( Nbits * Nitems + 31 ) / 32;
+    static const uint32_t VALUE_MASK = (1 << Nbits) - 1;
+    uint32_t mData[WORD_COUNT];
+};
+
+#endif /* compressed_enum_table_h */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/intrusive_list.h b/cpu/esp32/vendor/esp-idf/nvs_flash/intrusive_list.h
new file mode 100644
index 0000000000000000000000000000000000000000..fb553551b13b91b6041c2503af40888fa64e80e7
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/intrusive_list.h
@@ -0,0 +1,256 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef INTRUSIVE_LIST_H
+#define INTRUSIVE_LIST_H
+
+#include <cassert>
+
+template <typename T>
+class intrusive_list;
+
+template <typename T>
+class intrusive_list_node
+{
+protected:
+    friend class intrusive_list<T>;
+    T* mPrev = nullptr;
+    T* mNext = nullptr;
+};
+
+template <typename T>
+class intrusive_list
+{
+    typedef intrusive_list_node<T> TNode;
+    static_assert(std::is_base_of<TNode, T>::value, "");
+
+public:
+
+    class iterator : public std::iterator<std::forward_iterator_tag, T>
+    {
+    public:
+
+        iterator() : mPos(nullptr) {}
+
+        iterator(T* pos) : mPos(pos) {}
+
+        iterator operator++(int)
+        {
+            auto result = *this;
+            mPos = mPos->mNext;
+            return result;
+        }
+
+        iterator operator--(int)
+        {
+            auto result = *this;
+            mPos = mPos->mPrev;
+            return result;
+        }
+
+        iterator& operator++()
+        {
+            mPos = mPos->mNext;
+            return *this;
+        }
+
+        iterator& operator--()
+        {
+            mPos = mPos->mPrev;
+            return *this;
+        }
+
+
+        bool operator==(const iterator& other) const
+        {
+            return mPos == other.mPos;
+        }
+
+        bool operator!=(const iterator& other) const
+        {
+            return !(*this == other);
+        }
+
+        T& operator*()
+        {
+            return *mPos;
+        }
+
+        const T& operator*() const
+        {
+            return *mPos;
+        }
+
+        T* operator->()
+        {
+            return mPos;
+        }
+
+        const T* operator->() const
+        {
+            return mPos;
+        }
+
+        operator T*()
+        {
+            return mPos;
+        }
+
+        operator const T*() const
+        {
+            return mPos;
+        }
+
+
+    protected:
+        T* mPos;
+    };
+
+    void push_back(T* node)
+    {
+        if (mLast) {
+            mLast->mNext = node;
+        }
+        node->mPrev = mLast;
+        node->mNext = nullptr;
+        mLast = node;
+        if (mFirst == nullptr) {
+            mFirst = node;
+        }
+        ++mSize;
+    }
+
+    void push_front(T* node)
+    {
+        node->mPrev = nullptr;
+        node->mNext = mFirst;
+        if (mFirst) {
+            mFirst->mPrev = node;
+        }
+        mFirst = node;
+        if (mLast == nullptr) {
+            mLast = node;
+        }
+        ++mSize;
+    }
+
+    T& back()
+    {
+        return *mLast;
+    }
+
+    const T& back() const
+    {
+        return *mLast;
+    }
+
+    T& front()
+    {
+        return *mFirst;
+    }
+
+    const T& front() const
+    {
+        return *mFirst;
+    }
+
+    void pop_front()
+    {
+        erase(mFirst);
+    }
+
+    void pop_back()
+    {
+        erase(mLast);
+    }
+
+    void insert(iterator next, T* node)
+    {
+        if (static_cast<T*>(next) == nullptr) {
+            push_back(node);
+        } else {
+            auto prev = next->mPrev;
+            if (!prev) {
+                push_front(node);
+            } else {
+                prev->mNext = node;
+                next->mPrev = node;
+                node->mNext = next;
+                node->mPrev = &(*prev);
+                ++mSize;
+            }
+        }
+    }
+
+    void erase(iterator it)
+    {
+        auto prev = it->mPrev;
+        auto next = it->mNext;
+
+        if (prev) {
+            prev->mNext = next;
+        } else {
+            mFirst = next;
+        }
+        if (next) {
+            next->mPrev = prev;
+        } else {
+            mLast = prev;
+        }
+        --mSize;
+    }
+
+    iterator begin()
+    {
+        return iterator(mFirst);
+    }
+
+    iterator end()
+    {
+        return iterator(nullptr);
+    }
+
+    size_t size() const
+    {
+        return mSize;
+    }
+
+    bool empty() const
+    {
+        return mSize == 0;
+    }
+
+
+    void clear()
+    {
+        while (mFirst) {
+            erase(mFirst);
+        }
+    }
+
+protected:
+    T* mFirst = nullptr;
+    T* mLast = nullptr;
+    size_t mSize = 0;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* INTRUSIVE_LIST_H */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..d2f9d3d014cdc1a7110e6846cf29757cc61a9f7c
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs.hpp
@@ -0,0 +1,25 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef nvs_hpp
+#define nvs_hpp
+
+
+#include <memory>
+#include "nvs.h"
+#include "nvs_types.hpp"
+#include "nvs_page.hpp"
+#include "nvs_pagemanager.hpp"
+#include "nvs_storage.hpp"
+
+#endif /* nvs_hpp */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_api.cpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_api.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8d0e6c038935fcc686ccde7a65e5d2061361d465
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_api.cpp
@@ -0,0 +1,509 @@
+// 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 "nvs.hpp"
+#include "nvs_flash.h"
+#include "nvs_storage.hpp"
+#include "intrusive_list.h"
+#include "nvs_platform.hpp"
+#include "esp_partition.h"
+#include "sdkconfig.h"
+
+#ifdef ESP_PLATFORM
+// Uncomment this line to force output from this module
+// #define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
+#include "esp_log.h"
+static const char* TAG = "nvs";
+#else
+#define ESP_LOGD(...)
+#endif
+
+extern "C" void nvs_dump(const char *partName);
+extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount);
+
+class HandleEntry : public intrusive_list_node<HandleEntry>
+{
+    static uint32_t s_nvs_next_handle;
+public:
+    HandleEntry() {}
+
+    HandleEntry(bool readOnly, uint8_t nsIndex, nvs::Storage* StoragePtr) :
+        mHandle(++s_nvs_next_handle),  // Begin the handle value with 1
+        mReadOnly(readOnly),
+        mNsIndex(nsIndex),
+        mStoragePtr(StoragePtr)
+    {
+    }
+
+    nvs_handle mHandle;
+    uint8_t mReadOnly;
+    uint8_t mNsIndex;
+    nvs::Storage* mStoragePtr;
+};
+
+#ifdef ESP_PLATFORM
+SemaphoreHandle_t nvs::Lock::mSemaphore = NULL;
+#endif
+
+using namespace std;
+using namespace nvs;
+
+static intrusive_list<HandleEntry> s_nvs_handles;
+uint32_t HandleEntry::s_nvs_next_handle;
+static intrusive_list<nvs::Storage> s_nvs_storage_list;
+
+static nvs::Storage* lookup_storage_from_name(const char *name)
+{
+    auto it = find_if(begin(s_nvs_storage_list), end(s_nvs_storage_list), [=](Storage& e) -> bool {
+        return (strcmp(e.getPartName(), name) == 0);
+    });
+
+    if (it == end(s_nvs_storage_list)) {
+        return NULL;
+    }
+    return it;
+}
+
+extern "C" void nvs_dump(const char *partName)
+{
+    Lock lock;
+    nvs::Storage* pStorage;
+
+    pStorage = lookup_storage_from_name(partName);
+    if (pStorage == NULL) {
+        return;
+    }
+
+    pStorage->debugDump();
+    return;
+}
+
+extern "C" esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount)
+{
+    ESP_LOGD(TAG, "nvs_flash_init_custom partition=%s start=%d count=%d", partName, baseSector, sectorCount);
+    nvs::Storage* new_storage = NULL;
+    nvs::Storage* storage = lookup_storage_from_name(partName);
+    if (storage == NULL) {
+        new_storage = new nvs::Storage((const char *)partName);
+        storage = new_storage;
+    }
+
+    esp_err_t err = storage->init(baseSector, sectorCount);
+    if (new_storage != NULL) {
+        if (err == ESP_OK) {
+            s_nvs_storage_list.push_back(new_storage);
+        } else {
+            delete new_storage;
+        }
+    }
+    return err;
+}
+
+#ifdef ESP_PLATFORM
+extern "C" esp_err_t nvs_flash_init_partition(const char *part_name)
+{
+    Lock::init();
+    Lock lock;
+    nvs::Storage* mStorage;
+
+    mStorage = lookup_storage_from_name(part_name);
+    if (mStorage) {
+        return ESP_OK;
+    }
+
+    const esp_partition_t* partition = esp_partition_find_first(
+            ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
+    if (partition == NULL) {
+        return ESP_ERR_NOT_FOUND;
+    }
+
+    return nvs_flash_init_custom(part_name, partition->address / SPI_FLASH_SEC_SIZE,
+            partition->size / SPI_FLASH_SEC_SIZE);
+}
+
+extern "C" esp_err_t nvs_flash_init(void)
+{
+    return nvs_flash_init_partition(NVS_DEFAULT_PART_NAME);
+}
+
+extern "C" esp_err_t nvs_flash_erase_partition(const char *part_name)
+{
+    const esp_partition_t* partition = esp_partition_find_first(
+            ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_NVS, part_name);
+    if (partition == NULL) {
+        return ESP_ERR_NOT_FOUND;
+    }
+
+    return esp_partition_erase_range(partition, 0, partition->size);
+}
+
+extern "C" esp_err_t nvs_flash_erase()
+{
+    return nvs_flash_erase_partition(NVS_DEFAULT_PART_NAME);
+}
+#endif // ESP_PLATFORM
+
+extern "C" esp_err_t nvs_flash_deinit_partition(const char* partition_name)
+{
+    Lock::init();
+    Lock lock;
+
+    nvs::Storage* storage = lookup_storage_from_name(partition_name);
+    if (!storage) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    /* Clean up handles related to the storage being deinitialized */
+    auto it = s_nvs_handles.begin();
+    auto next = it;
+    while(it != s_nvs_handles.end()) {
+        next++;
+        if (it->mStoragePtr == storage) {
+            ESP_LOGD(TAG, "Deleting handle %d (ns=%d) related to partition \"%s\" (missing call to nvs_close?)",
+                     it->mHandle, it->mNsIndex, partition_name);
+            s_nvs_handles.erase(it);
+            delete static_cast<HandleEntry*>(it);
+        }
+        it = next;
+    }
+
+    /* Finally delete the storage itself */
+    s_nvs_storage_list.erase(storage);
+    delete storage;
+
+    return ESP_OK;
+}
+
+extern "C" esp_err_t nvs_flash_deinit(void)
+{
+    return nvs_flash_deinit_partition(NVS_DEFAULT_PART_NAME);
+}
+
+static esp_err_t nvs_find_ns_handle(nvs_handle handle, HandleEntry& entry)
+{
+    auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool {
+        return e.mHandle == handle;
+    });
+    if (it == end(s_nvs_handles)) {
+        return ESP_ERR_NVS_INVALID_HANDLE;
+    }
+    entry = *it;
+    return ESP_OK;
+}
+
+extern "C" esp_err_t nvs_open_from_partition(const char *part_name, const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s %d", __func__, name, open_mode);
+    uint8_t nsIndex;
+    nvs::Storage* sHandle;
+
+    sHandle = lookup_storage_from_name(part_name);
+    if (sHandle == NULL) {
+        return ESP_ERR_NVS_PART_NOT_FOUND;
+    }
+
+    esp_err_t err = sHandle->createOrOpenNamespace(name, open_mode == NVS_READWRITE, nsIndex);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    HandleEntry *handle_entry = new HandleEntry(open_mode==NVS_READONLY, nsIndex, sHandle);
+    s_nvs_handles.push_back(handle_entry);
+
+    *out_handle = handle_entry->mHandle;
+
+    return ESP_OK;
+}
+
+extern "C" esp_err_t nvs_open(const char* name, nvs_open_mode open_mode, nvs_handle *out_handle)
+{
+    if (s_nvs_storage_list.size() == 0) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    return nvs_open_from_partition(NVS_DEFAULT_PART_NAME, name, open_mode, out_handle);
+}
+
+extern "C" void nvs_close(nvs_handle handle)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %d", __func__, handle);
+    auto it = find_if(begin(s_nvs_handles), end(s_nvs_handles), [=](HandleEntry& e) -> bool {
+        return e.mHandle == handle;
+    });
+    if (it == end(s_nvs_handles)) {
+        return;
+    }
+    s_nvs_handles.erase(it);
+    delete static_cast<HandleEntry*>(it);
+}
+
+extern "C" esp_err_t nvs_erase_key(nvs_handle handle, const char* key)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s\r\n", __func__, key);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    if (entry.mReadOnly) {
+        return ESP_ERR_NVS_READ_ONLY;
+    }
+    return entry.mStoragePtr->eraseItem(entry.mNsIndex, key);
+}
+
+extern "C" esp_err_t nvs_erase_all(nvs_handle handle)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s\r\n", __func__);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    if (entry.mReadOnly) {
+        return ESP_ERR_NVS_READ_ONLY;
+    }
+    return entry.mStoragePtr->eraseNamespace(entry.mNsIndex);
+}
+
+template<typename T>
+static esp_err_t nvs_set(nvs_handle handle, const char* key, T value)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s %d %d", __func__, key, sizeof(T), (uint32_t) value);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    if (entry.mReadOnly) {
+        return ESP_ERR_NVS_READ_ONLY;
+    }
+    return entry.mStoragePtr->writeItem(entry.mNsIndex, key, value);
+}
+
+extern "C" esp_err_t nvs_set_i8  (nvs_handle handle, const char* key, int8_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_u8  (nvs_handle handle, const char* key, uint8_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_i16 (nvs_handle handle, const char* key, int16_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_u16 (nvs_handle handle, const char* key, uint16_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_i32 (nvs_handle handle, const char* key, int32_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_u32 (nvs_handle handle, const char* key, uint32_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_i64 (nvs_handle handle, const char* key, int64_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_set_u64 (nvs_handle handle, const char* key, uint64_t value)
+{
+    return nvs_set(handle, key, value);
+}
+
+extern "C" esp_err_t nvs_commit(nvs_handle handle)
+{
+    Lock lock;
+    // no-op for now, to be used when intermediate cache is added
+    HandleEntry entry;
+    return nvs_find_ns_handle(handle, entry);
+}
+
+extern "C" esp_err_t nvs_set_str(nvs_handle handle, const char* key, const char* value)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s %s", __func__, key, value);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::SZ, key, value, strlen(value) + 1);
+}
+
+extern "C" esp_err_t nvs_set_blob(nvs_handle handle, const char* key, const void* value, size_t length)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s %d", __func__, key, length);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    return entry.mStoragePtr->writeItem(entry.mNsIndex, nvs::ItemType::BLOB, key, value, length);
+}
+
+
+template<typename T>
+static esp_err_t nvs_get(nvs_handle handle, const char* key, T* out_value)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s %d", __func__, key, sizeof(T));
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+    return entry.mStoragePtr->readItem(entry.mNsIndex, key, *out_value);
+}
+
+extern "C" esp_err_t nvs_get_i8  (nvs_handle handle, const char* key, int8_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_u8  (nvs_handle handle, const char* key, uint8_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_i16 (nvs_handle handle, const char* key, int16_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_u16 (nvs_handle handle, const char* key, uint16_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_i32 (nvs_handle handle, const char* key, int32_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_u32 (nvs_handle handle, const char* key, uint32_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_i64 (nvs_handle handle, const char* key, int64_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+extern "C" esp_err_t nvs_get_u64 (nvs_handle handle, const char* key, uint64_t* out_value)
+{
+    return nvs_get(handle, key, out_value);
+}
+
+static esp_err_t nvs_get_str_or_blob(nvs_handle handle, nvs::ItemType type, const char* key, void* out_value, size_t* length)
+{
+    Lock lock;
+    ESP_LOGD(TAG, "%s %s", __func__, key);
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    size_t dataSize;
+    err = entry.mStoragePtr->getItemDataSize(entry.mNsIndex, type, key, dataSize);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    if (length == nullptr) {
+        return ESP_ERR_NVS_INVALID_LENGTH;
+    } else if (out_value == nullptr) {
+        *length = dataSize;
+        return ESP_OK;
+    } else if (*length < dataSize) {
+        *length = dataSize;
+        return ESP_ERR_NVS_INVALID_LENGTH;
+    }
+
+    *length = dataSize;
+    return entry.mStoragePtr->readItem(entry.mNsIndex, type, key, out_value, dataSize);
+}
+
+extern "C" esp_err_t nvs_get_str(nvs_handle handle, const char* key, char* out_value, size_t* length)
+{
+    return nvs_get_str_or_blob(handle, nvs::ItemType::SZ, key, out_value, length);
+}
+
+extern "C" esp_err_t nvs_get_blob(nvs_handle handle, const char* key, void* out_value, size_t* length)
+{
+    return nvs_get_str_or_blob(handle, nvs::ItemType::BLOB, key, out_value, length);
+}
+
+extern "C" esp_err_t nvs_get_stats(const char* part_name, nvs_stats_t* nvs_stats)
+{
+    Lock lock;
+    nvs::Storage* pStorage;
+
+    if (nvs_stats == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+    nvs_stats->used_entries     = 0;
+    nvs_stats->free_entries     = 0;
+    nvs_stats->total_entries    = 0;
+    nvs_stats->namespace_count  = 0;
+
+    pStorage = lookup_storage_from_name((part_name == NULL) ? NVS_DEFAULT_PART_NAME : part_name);
+    if (pStorage == NULL) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    if(!pStorage->isValid()){
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+
+    return pStorage->fillStats(*nvs_stats);
+}
+
+extern "C" esp_err_t nvs_get_used_entry_count(nvs_handle handle, size_t* used_entries)
+{
+    Lock lock;
+    if(used_entries == NULL){
+        return ESP_ERR_INVALID_ARG;
+    }
+    *used_entries = 0;
+
+    HandleEntry entry;
+    auto err = nvs_find_ns_handle(handle, entry);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    size_t used_entry_count;
+    err = entry.mStoragePtr->calcEntriesInNamespace(entry.mNsIndex, used_entry_count);
+    if(err == ESP_OK){
+        *used_entries = used_entry_count;
+    }
+    return err;
+}
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_item_hash_list.cpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_item_hash_list.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..0a6bc00047f324e48426227a933d6e227db654b4
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_item_hash_list.cpp
@@ -0,0 +1,107 @@
+// 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 "nvs_item_hash_list.hpp"
+
+namespace nvs
+{
+
+HashList::HashList()
+{
+}
+
+void HashList::clear()
+{
+    for (auto it = mBlockList.begin(); it != mBlockList.end();) {
+        auto tmp = it;
+        ++it;
+        mBlockList.erase(tmp);
+        delete static_cast<HashListBlock*>(tmp);
+    }
+}
+
+HashList::~HashList()
+{
+    clear();
+}
+
+HashList::HashListBlock::HashListBlock()
+{
+    static_assert(sizeof(HashListBlock) == HashListBlock::BYTE_SIZE,
+                  "cache block size calculation incorrect");
+}
+
+void HashList::insert(const Item& item, size_t index)
+{
+    const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff;
+    // add entry to the end of last block if possible
+    if (mBlockList.size()) {
+        auto& block = mBlockList.back();
+        if (block.mCount < HashListBlock::ENTRY_COUNT) {
+            block.mNodes[block.mCount++] = HashListNode(hash_24, index);
+            return;
+        }
+    }
+    // if the above failed, create a new block and add entry to it
+    HashListBlock* newBlock = new HashListBlock;
+    mBlockList.push_back(newBlock);
+    newBlock->mNodes[0] = HashListNode(hash_24, index);
+    newBlock->mCount++;
+}
+
+void HashList::erase(size_t index, bool itemShouldExist)
+{
+    for (auto it = mBlockList.begin(); it != mBlockList.end();) {
+        bool haveEntries = false;
+        for (size_t i = 0; i < it->mCount; ++i) {
+            if (it->mNodes[i].mIndex == index) {
+                it->mNodes[i].mIndex = 0xff;
+                return;
+            }
+            if (it->mNodes[i].mIndex != 0xff) {
+                haveEntries = true;
+            }
+        }
+        if (!haveEntries) {
+            auto tmp = it;
+            ++it;
+            mBlockList.erase(tmp);
+            delete static_cast<HashListBlock*>(tmp);
+        } else {
+            ++it;
+        }
+    }
+    if (itemShouldExist) {
+        assert(false && "item should have been present in cache");
+    }
+}
+
+size_t HashList::find(size_t start, const Item& item)
+{
+    const uint32_t hash_24 = item.calculateCrc32WithoutValue() & 0xffffff;
+    for (auto it = mBlockList.begin(); it != mBlockList.end(); ++it) {
+        for (size_t index = 0; index < it->mCount; ++index) {
+            HashListNode& e = it->mNodes[index];
+            if (e.mIndex >= start &&
+                    e.mHash == hash_24 &&
+                    e.mIndex != 0xff) {
+                return e.mIndex;
+            }
+        }
+    }
+    return SIZE_MAX;
+}
+
+
+} // namespace nvs
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_item_hash_list.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_item_hash_list.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..bea5d8e52b84ef5afbc26fecd683a174cda322eb
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_item_hash_list.hpp
@@ -0,0 +1,74 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef nvs_item_hash_list_h
+#define nvs_item_hash_list_h
+
+#include "nvs.h"
+#include "nvs_types.hpp"
+#include "intrusive_list.h"
+
+namespace nvs
+{
+
+class HashList
+{
+public:
+    HashList();
+    ~HashList();
+
+    void insert(const Item& item, size_t index);
+    void erase(const size_t index, bool itemShouldExist=true);
+    size_t find(size_t start, const Item& item);
+    void clear();
+
+private:
+    HashList(const HashList& other);
+    const HashList& operator= (const HashList& rhs);
+
+protected:
+
+    struct HashListNode {
+        HashListNode() :
+            mIndex(0xff), mHash(0)
+        {
+        }
+
+        HashListNode(uint32_t hash, size_t index) :
+            mIndex((uint32_t) index), mHash(hash)
+        {
+        }
+
+        uint32_t mIndex : 8;
+        uint32_t mHash  : 24;
+    };
+
+    struct HashListBlock : public intrusive_list_node<HashList::HashListBlock> {
+        HashListBlock();
+
+        static const size_t BYTE_SIZE = 128;
+        static const size_t ENTRY_COUNT = (BYTE_SIZE - sizeof(intrusive_list_node<HashListBlock>) - sizeof(size_t)) / 4;
+
+        size_t mCount = 0;
+        HashListNode mNodes[ENTRY_COUNT];
+    };
+
+    typedef intrusive_list<HashListBlock> TBlockList;
+    TBlockList mBlockList;
+}; // class HashList
+
+} // namespace nvs
+
+
+#endif /* nvs_item_hash_list_h */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_page.cpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_page.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1b227653734e68902f973a9e8f5cc61f0404b8ae
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_page.cpp
@@ -0,0 +1,920 @@
+// 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 "nvs_page.hpp"
+#if defined(ESP_PLATFORM)
+#include <rom/crc.h>
+#else
+#include "crc.h"
+#endif
+#include <cstdio>
+#include <cstring>
+
+namespace nvs
+{
+
+uint32_t Page::Header::calculateCrc32()
+{
+    return crc32_le(0xffffffff,
+                    reinterpret_cast<uint8_t*>(this) + offsetof(Header, mSeqNumber),
+                    offsetof(Header, mCrc32) - offsetof(Header, mSeqNumber));
+}
+
+esp_err_t Page::load(uint32_t sectorNumber)
+{
+    mBaseAddress = sectorNumber * SEC_SIZE;
+    mUsedEntryCount = 0;
+    mErasedEntryCount = 0;
+
+    Header header;
+    auto rc = spi_flash_read(mBaseAddress, &header, sizeof(header));
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+    if (header.mState == PageState::UNINITIALIZED) {
+        mState = header.mState;
+        // check if the whole page is really empty
+        // reading the whole page takes ~40 times less than erasing it
+        uint32_t line[8];
+        for (uint32_t i = 0; i < SPI_FLASH_SEC_SIZE; i += sizeof(line)) {
+            rc = spi_flash_read(mBaseAddress + i, line, sizeof(line));
+            if (rc != ESP_OK) {
+                mState = PageState::INVALID;
+                return rc;
+            }
+            if (std::any_of(line, line + 4, [](uint32_t val) -> bool { return val != 0xffffffff; })) {
+                // page isn't as empty after all, mark it as corrupted
+                mState = PageState::CORRUPT;
+                break;
+            }
+        }
+    } else if (header.mCrc32 != header.calculateCrc32()) {
+        header.mState = PageState::CORRUPT;
+    } else {
+        mState = header.mState;
+        mSeqNumber = header.mSeqNumber;
+    }
+
+    switch (mState) {
+    case PageState::UNINITIALIZED:
+        break;
+
+    case PageState::FULL:
+    case PageState::ACTIVE:
+    case PageState::FREEING:
+        mLoadEntryTable();
+        break;
+
+    default:
+        mState = PageState::CORRUPT;
+        break;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t Page::writeEntry(const Item& item)
+{
+    auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), &item, sizeof(item));
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+
+    auto err = alterEntryState(mNextFreeEntry, EntryState::WRITTEN);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    if (mFirstUsedEntry == INVALID_ENTRY) {
+        mFirstUsedEntry = mNextFreeEntry;
+    }
+
+    ++mUsedEntryCount;
+    ++mNextFreeEntry;
+
+    return ESP_OK;
+}
+
+esp_err_t Page::writeEntryData(const uint8_t* data, size_t size)
+{
+    assert(size % ENTRY_SIZE == 0);
+    assert(mNextFreeEntry != INVALID_ENTRY);
+    assert(mFirstUsedEntry != INVALID_ENTRY);
+    const uint16_t count = size / ENTRY_SIZE;
+
+    const uint8_t* buf = data;
+
+#ifdef ESP_PLATFORM
+    /* On the ESP32, data can come from DROM, which is not accessible by spi_flash_write
+     * function. To work around this, we copy the data to heap if it came from DROM.
+     * Hopefully this won't happen very often in practice. For data from DRAM, we should
+     * still be able to write it to flash directly.
+     * TODO: figure out how to make this platform-specific check nicer (probably by introducing
+     * a platform-specific flash layer).
+     */
+    if ((uint32_t) data < 0x3ff00000) {
+        buf = (uint8_t*) malloc(size);
+        if (!buf) {
+            return ESP_ERR_NO_MEM;
+        }
+        memcpy((void*)buf, data, size);
+    }
+#endif //ESP_PLATFORM
+    auto rc = spi_flash_write(getEntryAddress(mNextFreeEntry), buf, size);
+#ifdef ESP_PLATFORM
+    if (buf != data) {
+        free((void*)buf);
+    }
+#endif //ESP_PLATFORM
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+    auto err = alterEntryRangeState(mNextFreeEntry, mNextFreeEntry + count, EntryState::WRITTEN);
+    if (err != ESP_OK) {
+        return err;
+    }
+    mUsedEntryCount += count;
+    mNextFreeEntry += count;
+    return ESP_OK;
+}
+
+esp_err_t Page::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize)
+{
+    Item item;
+    esp_err_t err;
+
+    if (mState == PageState::INVALID) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+
+    if (mState == PageState::UNINITIALIZED) {
+        err = initialize();
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    if (mState == PageState::FULL) {
+        return ESP_ERR_NVS_PAGE_FULL;
+    }
+
+    const size_t keySize = strlen(key);
+    if (keySize > Item::MAX_KEY_LENGTH) {
+        return ESP_ERR_NVS_KEY_TOO_LONG;
+    }
+
+    if (dataSize > Page::BLOB_MAX_SIZE) {
+        return ESP_ERR_NVS_VALUE_TOO_LONG;
+    }
+
+    size_t totalSize = ENTRY_SIZE;
+    size_t entriesCount = 1;
+    if (datatype == ItemType::SZ || datatype == ItemType::BLOB) {
+        size_t roundedSize = (dataSize + ENTRY_SIZE - 1) & ~(ENTRY_SIZE - 1);
+        totalSize += roundedSize;
+        entriesCount += roundedSize / ENTRY_SIZE;
+    }
+
+    // primitive types should fit into one entry
+    assert(totalSize == ENTRY_SIZE || datatype == ItemType::BLOB || datatype == ItemType::SZ);
+
+    if (mNextFreeEntry == INVALID_ENTRY || mNextFreeEntry + entriesCount > ENTRY_COUNT) {
+        // page will not fit this amount of data
+        return ESP_ERR_NVS_PAGE_FULL;
+    }
+
+    // write first item
+    size_t span = (totalSize + ENTRY_SIZE - 1) / ENTRY_SIZE;
+    item = Item(nsIndex, datatype, span, key);
+    mHashList.insert(item, mNextFreeEntry);
+
+    if (datatype != ItemType::SZ && datatype != ItemType::BLOB) {
+        memcpy(item.data, data, dataSize);
+        item.crc32 = item.calculateCrc32();
+        err = writeEntry(item);
+        if (err != ESP_OK) {
+            return err;
+        }
+    } else {
+        const uint8_t* src = reinterpret_cast<const uint8_t*>(data);
+        item.varLength.dataCrc32 = Item::calculateCrc32(src, dataSize);
+        item.varLength.dataSize = dataSize;
+        item.varLength.reserved2 = 0xffff;
+        item.crc32 = item.calculateCrc32();
+        err = writeEntry(item);
+        if (err != ESP_OK) {
+            return err;
+        }
+
+        size_t left = dataSize / ENTRY_SIZE * ENTRY_SIZE;
+        if (left > 0) {
+            err = writeEntryData(static_cast<const uint8_t*>(data), left);
+            if (err != ESP_OK) {
+                return err;
+            }
+        }
+
+        size_t tail = dataSize - left;
+        if (tail > 0) {
+            std::fill_n(item.rawData, ENTRY_SIZE / 4, 0xffffffff);
+            memcpy(item.rawData, static_cast<const uint8_t*>(data) + left, tail);
+            err = writeEntry(item);
+            if (err != ESP_OK) {
+                return err;
+            }
+        }
+
+    }
+    return ESP_OK;
+}
+
+esp_err_t Page::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize)
+{
+    size_t index = 0;
+    Item item;
+
+    if (mState == PageState::INVALID) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+
+    esp_err_t rc = findItem(nsIndex, datatype, key, index, item);
+    if (rc != ESP_OK) {
+        return rc;
+    }
+
+    if (datatype != ItemType::SZ && datatype != ItemType::BLOB) {
+        if (dataSize != getAlignmentForType(datatype)) {
+            return ESP_ERR_NVS_TYPE_MISMATCH;
+        }
+
+        memcpy(data, item.data, dataSize);
+        return ESP_OK;
+    }
+
+    if (dataSize < static_cast<size_t>(item.varLength.dataSize)) {
+        return ESP_ERR_NVS_INVALID_LENGTH;
+    }
+
+    uint8_t* dst = reinterpret_cast<uint8_t*>(data);
+    size_t left = item.varLength.dataSize;
+    for (size_t i = index + 1; i < index + item.span; ++i) {
+        Item ditem;
+        rc = readEntry(i, ditem);
+        if (rc != ESP_OK) {
+            return rc;
+        }
+        size_t willCopy = ENTRY_SIZE;
+        willCopy = (left < willCopy)?left:willCopy;
+        memcpy(dst, ditem.rawData, willCopy);
+        left -= willCopy;
+        dst += willCopy;
+    }
+    if (Item::calculateCrc32(reinterpret_cast<uint8_t*>(data), item.varLength.dataSize) != item.varLength.dataCrc32) {
+        rc = eraseEntryAndSpan(index);
+        if (rc != ESP_OK) {
+            return rc;
+        }
+        return ESP_ERR_NVS_NOT_FOUND;
+    }
+    return ESP_OK;
+}
+
+esp_err_t Page::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key)
+{
+    size_t index = 0;
+    Item item;
+    esp_err_t rc = findItem(nsIndex, datatype, key, index, item);
+    if (rc != ESP_OK) {
+        return rc;
+    }
+    return eraseEntryAndSpan(index);
+}
+
+esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key)
+{
+    size_t index = 0;
+    Item item;
+    return findItem(nsIndex, datatype, key, index, item);
+}
+
+esp_err_t Page::eraseEntryAndSpan(size_t index)
+{
+    auto state = mEntryTable.get(index);
+    assert(state == EntryState::WRITTEN || state == EntryState::EMPTY);
+
+    size_t span = 1;
+    if (state == EntryState::WRITTEN) {
+        Item item;
+        auto rc = readEntry(index, item);
+        if (rc != ESP_OK) {
+            return rc;
+        }
+        if (item.calculateCrc32() != item.crc32) {
+            mHashList.erase(index, false);
+            rc = alterEntryState(index, EntryState::ERASED);
+            --mUsedEntryCount;
+            ++mErasedEntryCount;
+            if (rc != ESP_OK) {
+                return rc;
+            }
+        } else {
+            mHashList.erase(index);
+            span = item.span;
+            for (ptrdiff_t i = index + span - 1; i >= static_cast<ptrdiff_t>(index); --i) {
+                if (mEntryTable.get(i) == EntryState::WRITTEN) {
+                    --mUsedEntryCount;
+                }
+                ++mErasedEntryCount;
+            }
+            if (span == 1) {
+                rc = alterEntryState(index, EntryState::ERASED);
+            } else {
+                rc = alterEntryRangeState(index, index + span, EntryState::ERASED);
+            }
+            if (rc != ESP_OK) {
+                return rc;
+            }
+        }
+    } else {
+        auto rc = alterEntryState(index, EntryState::ERASED);
+        if (rc != ESP_OK) {
+            return rc;
+        }
+    }
+
+    if (index == mFirstUsedEntry) {
+        updateFirstUsedEntry(index, span);
+    }
+
+    if (index + span > mNextFreeEntry) {
+        mNextFreeEntry = index + span;
+    }
+
+    return ESP_OK;
+}
+
+void Page::updateFirstUsedEntry(size_t index, size_t span)
+{
+    assert(index == mFirstUsedEntry);
+    mFirstUsedEntry = INVALID_ENTRY;
+    size_t end = mNextFreeEntry;
+    if (end > ENTRY_COUNT) {
+        end = ENTRY_COUNT;
+    }
+    for (size_t i = index + span; i < end; ++i) {
+        if (mEntryTable.get(i) == EntryState::WRITTEN) {
+            mFirstUsedEntry = i;
+            break;
+        }
+    }
+}
+
+esp_err_t Page::copyItems(Page& other)
+{
+    if (mFirstUsedEntry == INVALID_ENTRY) {
+        return ESP_ERR_NVS_NOT_FOUND;
+    }
+
+    if (other.mState == PageState::UNINITIALIZED) {
+        auto err = other.initialize();
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    Item entry;
+    size_t readEntryIndex = mFirstUsedEntry;
+
+    while (readEntryIndex < ENTRY_COUNT) {
+
+        if (mEntryTable.get(readEntryIndex) != EntryState::WRITTEN) {
+            assert(readEntryIndex != mFirstUsedEntry);
+            readEntryIndex++;
+            continue;
+        }
+        auto err = readEntry(readEntryIndex, entry);
+        if (err != ESP_OK) {
+            return err;
+        }
+
+        other.mHashList.insert(entry, other.mNextFreeEntry);
+        err = other.writeEntry(entry);
+        if (err != ESP_OK) {
+            return err;
+        }
+        size_t span = entry.span;
+        size_t end = readEntryIndex + span;
+
+        assert(end <= ENTRY_COUNT);
+
+        for (size_t i = readEntryIndex + 1; i < end; ++i) {
+            readEntry(i, entry);
+            err = other.writeEntry(entry);
+            if (err != ESP_OK) {
+                return err;
+            }
+        }
+        readEntryIndex = end;
+
+    }
+    return ESP_OK;
+}
+
+esp_err_t Page::mLoadEntryTable()
+{
+    // for states where we actually care about data in the page, read entry state table
+    if (mState == PageState::ACTIVE ||
+            mState == PageState::FULL ||
+            mState == PageState::FREEING) {
+        auto rc = spi_flash_read(mBaseAddress + ENTRY_TABLE_OFFSET, mEntryTable.data(),
+                                 mEntryTable.byteSize());
+        if (rc != ESP_OK) {
+            mState = PageState::INVALID;
+            return rc;
+        }
+    }
+
+    mErasedEntryCount = 0;
+    mUsedEntryCount = 0;
+    for (size_t i = 0; i < ENTRY_COUNT; ++i) {
+        auto s = mEntryTable.get(i);
+        if (s == EntryState::WRITTEN) {
+            if (mFirstUsedEntry == INVALID_ENTRY) {
+                mFirstUsedEntry = i;
+            }
+            ++mUsedEntryCount;
+        } else if (s == EntryState::ERASED) {
+            ++mErasedEntryCount;
+        }
+    }
+
+    // for PageState::ACTIVE, we may have more data written to this page
+    // as such, we need to figure out where the first unused entry is
+    if (mState == PageState::ACTIVE) {
+        for (size_t i = 0; i < ENTRY_COUNT; ++i) {
+            if (mEntryTable.get(i) == EntryState::EMPTY) {
+                mNextFreeEntry = i;
+                break;
+            }
+        }
+
+        // however, if power failed after some data was written into the entry.
+        // but before the entry state table was altered, the entry locacted via
+        // entry state table may actually be half-written.
+        // this is easy to check by reading EntryHeader (i.e. first word)
+        while (mNextFreeEntry < ENTRY_COUNT) {
+            uint32_t entryAddress = getEntryAddress(mNextFreeEntry);
+            uint32_t header;
+            auto rc = spi_flash_read(entryAddress, &header, sizeof(header));
+            if (rc != ESP_OK) {
+                mState = PageState::INVALID;
+                return rc;
+            }
+            if (header != 0xffffffff) {
+                auto oldState = mEntryTable.get(mNextFreeEntry);
+                auto err = alterEntryState(mNextFreeEntry, EntryState::ERASED);
+                if (err != ESP_OK) {
+                    mState = PageState::INVALID;
+                    return err;
+                }
+                ++mNextFreeEntry;
+                if (oldState == EntryState::WRITTEN) {
+                    --mUsedEntryCount;
+                }
+                ++mErasedEntryCount;
+            }
+            else {
+                break;
+            }
+        }
+
+        // check that all variable-length items are written or erased fully
+        Item item;
+        size_t lastItemIndex = INVALID_ENTRY;
+        size_t end = mNextFreeEntry;
+        if (end > ENTRY_COUNT) {
+            end = ENTRY_COUNT;
+        }
+        size_t span;
+        for (size_t i = 0; i < end; i += span) {
+            span = 1;
+            if (mEntryTable.get(i) == EntryState::ERASED) {
+                lastItemIndex = INVALID_ENTRY;
+                continue;
+            }
+
+            lastItemIndex = i;
+
+            auto err = readEntry(i, item);
+            if (err != ESP_OK) {
+                mState = PageState::INVALID;
+                return err;
+            }
+
+            if (item.crc32 != item.calculateCrc32()) {
+                err = eraseEntryAndSpan(i);
+                if (err != ESP_OK) {
+                    mState = PageState::INVALID;
+                    return err;
+                }
+                continue;
+            }
+
+            mHashList.insert(item, i);
+
+            // search for potential duplicate item
+            size_t duplicateIndex = mHashList.find(0, item);
+
+            if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) {
+                span = item.span;
+                bool needErase = false;
+                for (size_t j = i; j < i + span; ++j) {
+                    if (mEntryTable.get(j) != EntryState::WRITTEN) {
+                        needErase = true;
+                        lastItemIndex = INVALID_ENTRY;
+                        break;
+                    }
+                }
+                if (needErase) {
+                    eraseEntryAndSpan(i);
+                    continue;
+                }
+            }
+
+            if (duplicateIndex < i) {
+                eraseEntryAndSpan(duplicateIndex);
+            }
+        }
+
+        // check that last item is not duplicate
+        if (lastItemIndex != INVALID_ENTRY) {
+            size_t findItemIndex = 0;
+            Item dupItem;
+            if (findItem(item.nsIndex, item.datatype, item.key, findItemIndex, dupItem) == ESP_OK) {
+                if (findItemIndex < lastItemIndex) {
+                    auto err = eraseEntryAndSpan(findItemIndex);
+                    if (err != ESP_OK) {
+                        mState = PageState::INVALID;
+                        return err;
+                    }
+                }
+            }
+        }
+    } else if (mState == PageState::FULL || mState == PageState::FREEING) {
+        // We have already filled mHashList for page in active state.
+        // Do the same for the case when page is in full or freeing state.
+        Item item;
+        for (size_t i = mFirstUsedEntry; i < ENTRY_COUNT; ++i) {
+            if (mEntryTable.get(i) != EntryState::WRITTEN) {
+                continue;
+            }
+
+            auto err = readEntry(i, item);
+            if (err != ESP_OK) {
+                mState = PageState::INVALID;
+                return err;
+            }
+
+            if (item.crc32 != item.calculateCrc32()) {
+                err = eraseEntryAndSpan(i);
+                if (err != ESP_OK) {
+                    mState = PageState::INVALID;
+                    return err;
+                }
+                continue;
+            }
+
+            assert(item.span > 0);
+
+            mHashList.insert(item, i);
+
+            size_t span = item.span;
+
+            if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) {
+                for (size_t j = i + 1; j < i + span; ++j) {
+                    if (mEntryTable.get(j) != EntryState::WRITTEN) {
+                        eraseEntryAndSpan(i);
+                        break;
+                    }
+                }
+            }
+
+            i += span - 1;
+        }
+
+    }
+
+    return ESP_OK;
+}
+
+
+esp_err_t Page::initialize()
+{
+    assert(mState == PageState::UNINITIALIZED);
+    mState = PageState::ACTIVE;
+    Header header;
+    header.mState = mState;
+    header.mSeqNumber = mSeqNumber;
+    header.mCrc32 = header.calculateCrc32();
+
+    auto rc = spi_flash_write(mBaseAddress, &header, sizeof(header));
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+
+    mNextFreeEntry = 0;
+    std::fill_n(mEntryTable.data(), mEntryTable.byteSize() / sizeof(uint32_t), 0xffffffff);
+    return ESP_OK;
+}
+
+esp_err_t Page::alterEntryState(size_t index, EntryState state)
+{
+    assert(index < ENTRY_COUNT);
+    mEntryTable.set(index, state);
+    size_t wordToWrite = mEntryTable.getWordIndex(index);
+    uint32_t word = mEntryTable.data()[wordToWrite];
+    auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast<uint32_t>(wordToWrite) * 4,
+            &word, sizeof(word));
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+    return ESP_OK;
+}
+
+esp_err_t Page::alterEntryRangeState(size_t begin, size_t end, EntryState state)
+{
+    assert(end <= ENTRY_COUNT);
+    assert(end > begin);
+    size_t wordIndex = mEntryTable.getWordIndex(end - 1);
+    for (ptrdiff_t i = end - 1; i >= static_cast<ptrdiff_t>(begin); --i) {
+        mEntryTable.set(i, state);
+        size_t nextWordIndex;
+        if (i == static_cast<ptrdiff_t>(begin)) {
+            nextWordIndex = (size_t) -1;
+        } else {
+            nextWordIndex = mEntryTable.getWordIndex(i - 1);
+        }
+        if (nextWordIndex != wordIndex) {
+            uint32_t word = mEntryTable.data()[wordIndex];
+            auto rc = spi_flash_write(mBaseAddress + ENTRY_TABLE_OFFSET + static_cast<uint32_t>(wordIndex) * 4,
+                    &word, 4);
+            if (rc != ESP_OK) {
+                return rc;
+            }
+        }
+        wordIndex = nextWordIndex;
+    }
+    return ESP_OK;
+}
+
+esp_err_t Page::alterPageState(PageState state)
+{
+    uint32_t state_val = static_cast<uint32_t>(state);
+    auto rc = spi_flash_write(mBaseAddress, &state_val, sizeof(state));
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+    mState = (PageState) state;
+    return ESP_OK;
+}
+
+esp_err_t Page::readEntry(size_t index, Item& dst) const
+{
+    auto rc = spi_flash_read(getEntryAddress(index), &dst, sizeof(dst));
+    if (rc != ESP_OK) {
+        return rc;
+    }
+    return ESP_OK;
+}
+
+esp_err_t Page::findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item)
+{
+    if (mState == PageState::CORRUPT || mState == PageState::INVALID || mState == PageState::UNINITIALIZED) {
+        return ESP_ERR_NVS_NOT_FOUND;
+    }
+
+    size_t findBeginIndex = itemIndex;
+    if (findBeginIndex >= ENTRY_COUNT) {
+        return ESP_ERR_NVS_NOT_FOUND;
+    }
+
+    size_t start = mFirstUsedEntry;
+    if (findBeginIndex > mFirstUsedEntry && findBeginIndex < ENTRY_COUNT) {
+        start = findBeginIndex;
+    }
+
+    size_t end = mNextFreeEntry;
+    if (end > ENTRY_COUNT) {
+        end = ENTRY_COUNT;
+    }
+
+    if (nsIndex != NS_ANY && datatype != ItemType::ANY && key != NULL) {
+        size_t cachedIndex = mHashList.find(start, Item(nsIndex, datatype, 0, key));
+        if (cachedIndex < ENTRY_COUNT) {
+            start = cachedIndex;
+        } else {
+            return ESP_ERR_NVS_NOT_FOUND;
+        }
+    }
+
+    size_t next;
+    for (size_t i = start; i < end; i = next) {
+        next = i + 1;
+        if (mEntryTable.get(i) != EntryState::WRITTEN) {
+            continue;
+        }
+
+        auto rc = readEntry(i, item);
+        if (rc != ESP_OK) {
+            mState = PageState::INVALID;
+            return rc;
+        }
+
+        auto crc32 = item.calculateCrc32();
+        if (item.crc32 != crc32) {
+            rc = eraseEntryAndSpan(i);
+            if (rc != ESP_OK) {
+                mState = PageState::INVALID;
+                return rc;
+            }
+            continue;
+        }
+
+        if (item.datatype == ItemType::BLOB || item.datatype == ItemType::SZ) {
+            next = i + item.span;
+        }
+
+        if (nsIndex != NS_ANY && item.nsIndex != nsIndex) {
+            continue;
+        }
+
+        if (key != nullptr && strncmp(key, item.key, Item::MAX_KEY_LENGTH) != 0) {
+            continue;
+        }
+
+        if (datatype != ItemType::ANY && item.datatype != datatype) {
+            return ESP_ERR_NVS_TYPE_MISMATCH;
+        }
+
+        itemIndex = i;
+
+        return ESP_OK;
+    }
+
+    return ESP_ERR_NVS_NOT_FOUND;
+}
+
+esp_err_t Page::getSeqNumber(uint32_t& seqNumber) const
+{
+    if (mState != PageState::UNINITIALIZED && mState != PageState::INVALID && mState != PageState::CORRUPT) {
+        seqNumber = mSeqNumber;
+        return ESP_OK;
+    }
+    return ESP_ERR_NVS_NOT_INITIALIZED;
+}
+
+
+esp_err_t Page::setSeqNumber(uint32_t seqNumber)
+{
+    if (mState != PageState::UNINITIALIZED) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+    mSeqNumber = seqNumber;
+    return ESP_OK;
+}
+
+esp_err_t Page::erase()
+{
+    auto sector = mBaseAddress / SPI_FLASH_SEC_SIZE;
+    auto rc = spi_flash_erase_sector(sector);
+    if (rc != ESP_OK) {
+        mState = PageState::INVALID;
+        return rc;
+    }
+    mUsedEntryCount = 0;
+    mErasedEntryCount = 0;
+    mFirstUsedEntry = INVALID_ENTRY;
+    mNextFreeEntry = INVALID_ENTRY;
+    mState = PageState::UNINITIALIZED;
+    mHashList.clear();
+    return ESP_OK;
+}
+
+esp_err_t Page::markFreeing()
+{
+    if (mState != PageState::FULL && mState != PageState::ACTIVE) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+    return alterPageState(PageState::FREEING);
+}
+
+esp_err_t Page::markFull()
+{
+    if (mState != PageState::ACTIVE) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+    return alterPageState(PageState::FULL);
+}
+
+const char* Page::pageStateToName(PageState ps)
+{
+    switch (ps) {
+        case PageState::CORRUPT:
+            return "CORRUPT";
+
+        case PageState::ACTIVE:
+            return "ACTIVE";
+
+        case PageState::FREEING:
+            return "FREEING";
+
+        case PageState::FULL:
+            return "FULL";
+
+        case PageState::INVALID:
+            return "INVALID";
+
+        case PageState::UNINITIALIZED:
+            return "UNINITIALIZED";
+
+        default:
+            assert(0 && "invalid state value");
+            return "";
+    }
+}
+
+void Page::debugDump() const
+{
+    printf("state=%x (%s) addr=%x seq=%d\nfirstUsed=%d nextFree=%d used=%d erased=%d\n", (uint32_t) mState, pageStateToName(mState), mBaseAddress, mSeqNumber, static_cast<int>(mFirstUsedEntry), static_cast<int>(mNextFreeEntry), mUsedEntryCount, mErasedEntryCount);
+    size_t skip = 0;
+    for (size_t i = 0; i < ENTRY_COUNT; ++i) {
+        printf("%3d: ", static_cast<int>(i));
+        EntryState state = mEntryTable.get(i);
+        if (state == EntryState::EMPTY) {
+            printf("E\n");
+        } else if (state == EntryState::ERASED) {
+            printf("X\n");
+        } else if (state == EntryState::WRITTEN) {
+            Item item;
+            readEntry(i, item);
+            if (skip == 0) {
+                printf("W ns=%2u type=%2u span=%3u key=\"%s\" len=%d\n", item.nsIndex, static_cast<unsigned>(item.datatype), item.span, item.key, (item.span != 1)?((int)item.varLength.dataSize):-1);
+                if (item.span > 0 && item.span <= ENTRY_COUNT - i) {
+                    skip = item.span - 1;
+                } else {
+                    skip = 0;
+                }
+            } else {
+                printf("D\n");
+                skip--;
+            }
+        }
+    }
+}
+
+esp_err_t Page::calcEntries(nvs_stats_t &nvsStats)
+{
+    assert(mState != PageState::FREEING);
+
+    nvsStats.total_entries += ENTRY_COUNT;
+
+    switch (mState) {
+        case PageState::UNINITIALIZED:
+        case PageState::CORRUPT:
+            nvsStats.free_entries += ENTRY_COUNT;
+            break;
+
+        case PageState::FULL:
+        case PageState::ACTIVE:
+            nvsStats.used_entries += mUsedEntryCount;
+            nvsStats.free_entries += ENTRY_COUNT - mUsedEntryCount; // it's equivalent free + erase entries.
+            break;
+
+        case PageState::INVALID:
+            return ESP_ERR_INVALID_STATE;
+            break;
+
+        default:
+            assert(false && "Unhandled state");
+            break;
+    }
+    return ESP_OK;
+}
+
+} // namespace nvs
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_page.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_page.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..594d9682a4b90bf600bf650bc2d3aad0455af158
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_page.hpp
@@ -0,0 +1,223 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef nvs_page_hpp
+#define nvs_page_hpp
+
+#include "nvs.h"
+#include "nvs_types.hpp"
+#include <cstdint>
+#include <type_traits>
+#include <cstring>
+#include <algorithm>
+#include "esp_spi_flash.h"
+#include "compressed_enum_table.hpp"
+#include "intrusive_list.h"
+#include "nvs_item_hash_list.hpp"
+
+namespace nvs
+{
+
+
+class Page : public intrusive_list_node<Page>
+{
+public:
+    static const uint32_t PSB_INIT = 0x1;
+    static const uint32_t PSB_FULL = 0x2;
+    static const uint32_t PSB_FREEING = 0x4;
+    static const uint32_t PSB_CORRUPT = 0x8;
+
+    static const uint32_t ESB_WRITTEN = 0x1;
+    static const uint32_t ESB_ERASED = 0x2;
+
+    static const uint32_t SEC_SIZE = SPI_FLASH_SEC_SIZE;
+
+    static const size_t ENTRY_SIZE  = 32;
+    static const size_t ENTRY_COUNT = 126;
+    static const uint32_t INVALID_ENTRY = 0xffffffff;
+
+    static const size_t BLOB_MAX_SIZE = ENTRY_SIZE * (ENTRY_COUNT / 2 - 1);
+
+    static const uint8_t NS_INDEX = 0;
+    static const uint8_t NS_ANY = 255;
+
+    enum class PageState : uint32_t {
+        // All bits set, default state after flash erase. Page has not been initialized yet.
+        UNINITIALIZED = 0xffffffff,
+
+        // Page is initialized, and will accept writes.
+        ACTIVE        = UNINITIALIZED & ~PSB_INIT,
+
+        // Page is marked as full and will not accept new writes.
+        FULL          = ACTIVE & ~PSB_FULL,
+
+        // Data is being moved from this page to a new one.
+        FREEING       = FULL & ~PSB_FREEING,
+
+        // Page was found to be in a corrupt and unrecoverable state.
+        // Instead of being erased immediately, it will be kept for diagnostics and data recovery.
+        // It will be erased once we run out out free pages.
+        CORRUPT       = FREEING & ~PSB_CORRUPT,
+
+        // Page object wasn't loaded from flash memory
+        INVALID       = 0
+    };
+
+    PageState state() const
+    {
+        return mState;
+    }
+
+    esp_err_t load(uint32_t sectorNumber);
+
+    esp_err_t getSeqNumber(uint32_t& seqNumber) const;
+
+    esp_err_t setSeqNumber(uint32_t seqNumber);
+
+    esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize);
+
+    esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize);
+
+    esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key);
+
+    esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key);
+
+    esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, size_t &itemIndex, Item& item);
+
+    template<typename T>
+    esp_err_t writeItem(uint8_t nsIndex, const char* key, const T& value)
+    {
+        return writeItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value));
+    }
+
+    template<typename T>
+    esp_err_t readItem(uint8_t nsIndex, const char* key, T& value)
+    {
+        return readItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value));
+    }
+
+    template<typename T>
+    esp_err_t eraseItem(uint8_t nsIndex, const char* key)
+    {
+        return eraseItem(nsIndex, itemTypeOf<T>(), key);
+    }
+
+    size_t getUsedEntryCount() const
+    {
+        return mUsedEntryCount;
+    }
+
+    size_t getErasedEntryCount() const
+    {
+        return mErasedEntryCount;
+    }
+
+
+    esp_err_t markFull();
+
+    esp_err_t markFreeing();
+
+    esp_err_t copyItems(Page& other);
+
+    esp_err_t erase();
+
+    void debugDump() const;
+
+    esp_err_t calcEntries(nvs_stats_t &nvsStats);
+
+protected:
+
+    class Header
+    {
+    public:
+        Header()
+        {
+            std::fill_n(mReserved, sizeof(mReserved)/sizeof(mReserved[0]), UINT32_MAX);
+        }
+
+        PageState mState;       // page state
+        uint32_t mSeqNumber;    // sequence number of this page
+        uint32_t mReserved[5];  // unused, must be 0xffffffff
+        uint32_t mCrc32;        // crc of everything except mState
+
+        uint32_t calculateCrc32();
+    };
+
+    enum class EntryState {
+        EMPTY   = 0x3, // 0b11, default state after flash erase
+        WRITTEN = EMPTY & ~ESB_WRITTEN, // entry was written
+        ERASED  = WRITTEN & ~ESB_ERASED, // entry was written and then erased
+        INVALID = 0x4 // entry is in inconsistent state (write started but ESB_WRITTEN has not been set yet)
+    };
+
+    esp_err_t mLoadEntryTable();
+
+    esp_err_t initialize();
+
+    esp_err_t alterEntryState(size_t index, EntryState state);
+
+    esp_err_t alterEntryRangeState(size_t begin, size_t end, EntryState state);
+
+    esp_err_t alterPageState(PageState state);
+
+    esp_err_t readEntry(size_t index, Item& dst) const;
+
+    esp_err_t writeEntry(const Item& item);
+
+    esp_err_t writeEntryData(const uint8_t* data, size_t size);
+
+    esp_err_t eraseEntryAndSpan(size_t index);
+
+    void updateFirstUsedEntry(size_t index, size_t span);
+
+    static constexpr size_t getAlignmentForType(ItemType type)
+    {
+        return static_cast<uint8_t>(type) & 0x0f;
+    }
+
+    uint32_t getEntryAddress(size_t entry) const
+    {
+        assert(entry < ENTRY_COUNT);
+        return mBaseAddress + ENTRY_DATA_OFFSET + static_cast<uint32_t>(entry) * ENTRY_SIZE;
+    }
+
+    static const char* pageStateToName(PageState ps);
+
+
+protected:
+    uint32_t mBaseAddress = 0;
+    PageState mState = PageState::INVALID;
+    uint32_t mSeqNumber = UINT32_MAX;
+    typedef CompressedEnumTable<EntryState, 2, ENTRY_COUNT> TEntryTable;
+    TEntryTable mEntryTable;
+    size_t mNextFreeEntry = INVALID_ENTRY;
+    size_t mFirstUsedEntry = INVALID_ENTRY;
+    uint16_t mUsedEntryCount = 0;
+    uint16_t mErasedEntryCount = 0;
+
+    HashList mHashList;
+
+    static const uint32_t HEADER_OFFSET = 0;
+    static const uint32_t ENTRY_TABLE_OFFSET = HEADER_OFFSET + 32;
+    static const uint32_t ENTRY_DATA_OFFSET = ENTRY_TABLE_OFFSET + 32;
+
+    static_assert(sizeof(Header) == 32, "header size must be 32 bytes");
+    static_assert(ENTRY_TABLE_OFFSET % 32 == 0, "entry table offset should be aligned");
+    static_assert(ENTRY_DATA_OFFSET % 32 == 0, "entry data offset should be aligned");
+
+}; // class Page
+
+} // namespace nvs
+
+
+#endif /* nvs_page_hpp */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_pagemanager.cpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_pagemanager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3f3c5f01cd1d9e07f9fe37bd557b76067d5c6b7e
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_pagemanager.cpp
@@ -0,0 +1,225 @@
+// 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 "nvs_pagemanager.hpp"
+
+namespace nvs
+{
+esp_err_t PageManager::load(uint32_t baseSector, uint32_t sectorCount)
+{
+    mBaseSector = baseSector;
+    mPageCount = sectorCount;
+    mPageList.clear();
+    mFreePageList.clear();
+    mPages.reset(new Page[sectorCount]);
+
+    for (uint32_t i = 0; i < sectorCount; ++i) {
+        auto err = mPages[i].load(baseSector + i);
+        if (err != ESP_OK) {
+            return err;
+        }
+        uint32_t seqNumber;
+        if (mPages[i].getSeqNumber(seqNumber) != ESP_OK) {
+            mFreePageList.push_back(&mPages[i]);
+        } else {
+            auto pos = std::find_if(std::begin(mPageList), std::end(mPageList), [=](const Page& page) -> bool {
+                uint32_t otherSeqNumber;
+                return page.getSeqNumber(otherSeqNumber) == ESP_OK && otherSeqNumber > seqNumber;
+            });
+            if (pos == mPageList.end()) {
+                mPageList.push_back(&mPages[i]);
+            } else {
+                mPageList.insert(pos, &mPages[i]);
+            }
+        }
+    }
+
+    if (mPageList.empty()) {
+        mSeqNumber = 0;
+        return activatePage();
+    } else {
+        uint32_t lastSeqNo;
+        ESP_ERROR_CHECK( mPageList.back().getSeqNumber(lastSeqNo) );
+        mSeqNumber = lastSeqNo + 1;
+    }
+
+    // if power went out after a new item for the given key was written,
+    // but before the old one was erased, we end up with a duplicate item
+    Page& lastPage = back();
+    size_t lastItemIndex = SIZE_MAX;
+    Item item;
+    size_t itemIndex = 0;
+    while (lastPage.findItem(Page::NS_ANY, ItemType::ANY, nullptr, itemIndex, item) == ESP_OK) {
+        itemIndex += item.span;
+        lastItemIndex = itemIndex;
+    }
+
+    if (lastItemIndex != SIZE_MAX) {
+        auto last = PageManager::TPageListIterator(&lastPage);
+        for (auto it = begin(); it != last; ++it) {
+
+            if ((it->state() != Page::PageState::FREEING) &&
+                    (it->eraseItem(item.nsIndex, item.datatype, item.key) == ESP_OK)) {
+                break;
+            }
+        }
+    }
+
+    // check if power went out while page was being freed
+    for (auto it = begin(); it!= end(); ++it) {
+        if (it->state() == Page::PageState::FREEING) {
+            Page* newPage = &mPageList.back();
+            if (newPage->state() == Page::PageState::ACTIVE) {
+                auto err = newPage->erase();
+                if (err != ESP_OK) {
+                    return err;
+                }
+                mPageList.erase(newPage);
+                mFreePageList.push_back(newPage);
+            }
+            auto err = activatePage();
+            if (err != ESP_OK) {
+                return err;
+            }
+            newPage = &mPageList.back();
+
+            err = it->copyItems(*newPage);
+            if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
+                return err;
+            }
+
+            err = it->erase();
+            if (err != ESP_OK) {
+                return err;
+            }
+
+            Page* p = static_cast<Page*>(it);
+            mPageList.erase(it);
+            mFreePageList.push_back(p);
+            break;
+        }
+    }
+
+    // partition should have at least one free page
+    if (mFreePageList.size() == 0) {
+        return ESP_ERR_NVS_NO_FREE_PAGES;
+    }
+
+    return ESP_OK;
+}
+
+esp_err_t PageManager::requestNewPage()
+{
+    if (mFreePageList.empty()) {
+        return ESP_ERR_NVS_INVALID_STATE;
+    }
+
+    // do we have at least two free pages? in that case no erasing is required
+    if (mFreePageList.size() >= 2) {
+        return activatePage();
+    }
+
+    // find the page with the higest number of erased items
+    TPageListIterator maxUnusedItemsPageIt;
+    size_t maxUnusedItems = 0;
+    for (auto it = begin(); it != end(); ++it) {
+
+        auto unused =  Page::ENTRY_COUNT - it->getUsedEntryCount();
+        if (unused > maxUnusedItems) {
+            maxUnusedItemsPageIt = it;
+            maxUnusedItems = unused;
+        }
+    }
+
+    if (maxUnusedItems == 0) {
+        return ESP_ERR_NVS_NOT_ENOUGH_SPACE;
+    }
+
+    esp_err_t err = activatePage();
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    Page* newPage = &mPageList.back();
+
+    Page* erasedPage = maxUnusedItemsPageIt;
+
+#ifndef NDEBUG
+    size_t usedEntries = erasedPage->getUsedEntryCount();
+#endif
+    err = erasedPage->markFreeing();
+    if (err != ESP_OK) {
+        return err;
+    }
+    err = erasedPage->copyItems(*newPage);
+    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
+        return err;
+    }
+
+    err = erasedPage->erase();
+    if (err != ESP_OK) {
+        return err;
+    }
+
+#ifndef NDEBUG
+    assert(usedEntries == newPage->getUsedEntryCount());
+#endif
+
+    mPageList.erase(maxUnusedItemsPageIt);
+    mFreePageList.push_back(erasedPage);
+
+    return ESP_OK;
+}
+
+esp_err_t PageManager::activatePage()
+{
+    if (mFreePageList.empty()) {
+        return ESP_ERR_NVS_NOT_ENOUGH_SPACE;
+    }
+    Page* p = &mFreePageList.front();
+    if (p->state() == Page::PageState::CORRUPT) {
+        auto err = p->erase();
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+    mFreePageList.pop_front();
+    mPageList.push_back(p);
+    p->setSeqNumber(mSeqNumber);
+    ++mSeqNumber;
+    return ESP_OK;
+}
+
+esp_err_t PageManager::fillStats(nvs_stats_t& nvsStats)
+{
+    nvsStats.used_entries      = 0;
+    nvsStats.free_entries      = 0;
+    nvsStats.total_entries     = 0;
+    esp_err_t err = ESP_OK;
+
+    // list of used pages
+    for (auto p = mPageList.begin(); p != mPageList.end(); ++p) {
+        err = p->calcEntries(nvsStats);
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+
+    // free pages
+    nvsStats.total_entries += mFreePageList.size() * Page::ENTRY_COUNT;
+    nvsStats.free_entries  += mFreePageList.size() * Page::ENTRY_COUNT;
+
+    return err;
+}
+
+} // namespace nvs
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_pagemanager.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_pagemanager.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..74305e95200c1a91987db963f73fe8ddf6688ac7
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_pagemanager.hpp
@@ -0,0 +1,72 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef nvs_pagemanager_hpp
+#define nvs_pagemanager_hpp
+
+#include <memory>
+#include <list>
+#include "nvs_types.hpp"
+#include "nvs_page.hpp"
+#include "nvs_pagemanager.hpp"
+#include "intrusive_list.h"
+
+namespace nvs
+{
+class PageManager
+{
+    using TPageList = intrusive_list<Page>;
+    using TPageListIterator = TPageList::iterator;
+public:
+
+    PageManager() {}
+
+    esp_err_t load(uint32_t baseSector, uint32_t sectorCount);
+
+    TPageListIterator begin()
+    {
+        return mPageList.begin();
+    }
+
+    TPageListIterator end()
+    {
+        return mPageList.end();
+    }
+
+    Page& back()
+    {
+        return mPageList.back();
+    }
+
+    esp_err_t requestNewPage();
+
+    esp_err_t fillStats(nvs_stats_t& nvsStats);
+
+protected:
+    friend class Iterator;
+
+    esp_err_t activatePage();
+
+    TPageList mPageList;
+    TPageList mFreePageList;
+    std::unique_ptr<Page[]> mPages;
+    uint32_t mBaseSector;
+    uint32_t mPageCount;
+    uint32_t mSeqNumber;
+}; // class PageManager
+
+
+} // namespace nvs
+
+
+#endif /* nvs_pagemanager_hpp */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_platform.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_platform.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..0973c4875c38f5eaca4d6ae48ae88ce9d6db4e68
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_platform.hpp
@@ -0,0 +1,81 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef nvs_platform_h
+#define nvs_platform_h
+
+
+#ifdef ESP_PLATFORM
+#include "freertos/FreeRTOS.h"
+#include "freertos/semphr.h"
+
+namespace nvs
+{
+
+class Lock
+{
+public:
+    Lock()
+    {
+        if (mSemaphore) {
+            xSemaphoreTake(mSemaphore, portMAX_DELAY);
+        }
+    }
+
+    ~Lock()
+    {
+        if (mSemaphore) {
+            xSemaphoreGive(mSemaphore);
+        }
+    }
+
+    static esp_err_t init()
+    {
+        if (mSemaphore) {
+            return ESP_OK;
+        }
+        mSemaphore = xSemaphoreCreateMutex();
+        if (!mSemaphore) {
+            return ESP_ERR_NO_MEM;
+        }
+        return ESP_OK;
+    }
+
+    static void uninit()
+    {
+        if (mSemaphore) {
+            vSemaphoreDelete(mSemaphore);
+        }
+        mSemaphore = nullptr;
+    }
+
+    static SemaphoreHandle_t mSemaphore;
+};
+} // namespace nvs
+
+#else // ESP_PLATFORM
+namespace nvs
+{
+class Lock
+{
+public:
+    Lock() { }
+    ~Lock() { }
+    static void init() {}
+    static void uninit() {}
+};
+} // namespace nvs
+#endif // ESP_PLATFORM
+
+
+#endif /* nvs_platform_h */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_storage.cpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_storage.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e3e52cff1e81321d14981ee344244f57d049a994
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_storage.cpp
@@ -0,0 +1,327 @@
+// 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 "nvs_storage.hpp"
+
+#ifndef ESP_PLATFORM
+#include <map>
+#include <sstream>
+#endif
+
+namespace nvs
+{
+
+Storage::~Storage()
+{
+    clearNamespaces();
+}
+
+void Storage::clearNamespaces()
+{
+    for (auto it = std::begin(mNamespaces); it != std::end(mNamespaces); ) {
+        auto tmp = it;
+        ++it;
+        mNamespaces.erase(tmp);
+        delete static_cast<NamespaceEntry*>(tmp);
+    }
+}
+
+esp_err_t Storage::init(uint32_t baseSector, uint32_t sectorCount)
+{
+    auto err = mPageManager.load(baseSector, sectorCount);
+    if (err != ESP_OK) {
+        mState = StorageState::INVALID;
+        return err;
+    }
+
+    // load namespaces list
+    clearNamespaces();
+    std::fill_n(mNamespaceUsage.data(), mNamespaceUsage.byteSize() / 4, 0);
+    for (auto it = mPageManager.begin(); it != mPageManager.end(); ++it) {
+        Page& p = *it;
+        size_t itemIndex = 0;
+        Item item;
+        while (p.findItem(Page::NS_INDEX, ItemType::U8, nullptr, itemIndex, item) == ESP_OK) {
+            NamespaceEntry* entry = new NamespaceEntry;
+            item.getKey(entry->mName, sizeof(entry->mName) - 1);
+            item.getValue(entry->mIndex);
+            mNamespaces.push_back(entry);
+            mNamespaceUsage.set(entry->mIndex, true);
+            itemIndex += item.span;
+        }
+    }
+    mNamespaceUsage.set(0, true);
+    mNamespaceUsage.set(255, true);
+    mState = StorageState::ACTIVE;
+#ifndef ESP_PLATFORM
+    debugCheck();
+#endif
+    return ESP_OK;
+}
+
+bool Storage::isValid() const
+{
+    return mState == StorageState::ACTIVE;
+}
+
+esp_err_t Storage::findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item)
+{
+    for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
+        size_t itemIndex = 0;
+        auto err = it->findItem(nsIndex, datatype, key, itemIndex, item);
+        if (err == ESP_OK) {
+            page = it;
+            return ESP_OK;
+        }
+    }
+    return ESP_ERR_NVS_NOT_FOUND;
+}
+
+esp_err_t Storage::writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    Page* findPage = nullptr;
+    Item item;
+    auto err = findItem(nsIndex, datatype, key, findPage, item);
+    if (err != ESP_OK && err != ESP_ERR_NVS_NOT_FOUND) {
+        return err;
+    }
+
+    Page& page = getCurrentPage();
+    err = page.writeItem(nsIndex, datatype, key, data, dataSize);
+    if (err == ESP_ERR_NVS_PAGE_FULL) {
+        if (page.state() != Page::PageState::FULL) {
+            err = page.markFull();
+            if (err != ESP_OK) {
+                return err;
+            }
+        }
+        err = mPageManager.requestNewPage();
+        if (err != ESP_OK) {
+            return err;
+        }
+
+        err = getCurrentPage().writeItem(nsIndex, datatype, key, data, dataSize);
+        if (err == ESP_ERR_NVS_PAGE_FULL) {
+            return ESP_ERR_NVS_NOT_ENOUGH_SPACE;
+        }
+        if (err != ESP_OK) {
+            return err;
+        }
+    } else if (err != ESP_OK) {
+        return err;
+    }
+
+    if (findPage) {
+        if (findPage->state() == Page::PageState::UNINITIALIZED ||
+                findPage->state() == Page::PageState::INVALID) {
+            ESP_ERROR_CHECK( findItem(nsIndex, datatype, key, findPage, item) );
+        }
+        err = findPage->eraseItem(nsIndex, datatype, key);
+        if (err == ESP_ERR_FLASH_OP_FAIL) {
+            return ESP_ERR_NVS_REMOVE_FAILED;
+        }
+        if (err != ESP_OK) {
+            return err;
+        }
+    }
+#ifndef ESP_PLATFORM
+    debugCheck();
+#endif
+    return ESP_OK;
+}
+
+esp_err_t Storage::createOrOpenNamespace(const char* nsName, bool canCreate, uint8_t& nsIndex)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+    auto it = std::find_if(mNamespaces.begin(), mNamespaces.end(), [=] (const NamespaceEntry& e) -> bool {
+        return strncmp(nsName, e.mName, sizeof(e.mName) - 1) == 0;
+    });
+    if (it == std::end(mNamespaces)) {
+        if (!canCreate) {
+            return ESP_ERR_NVS_NOT_FOUND;
+        }
+
+        uint8_t ns;
+        for (ns = 1; ns < 255; ++ns) {
+            if (mNamespaceUsage.get(ns) == false) {
+                break;
+            }
+        }
+
+        if (ns == 255) {
+            return ESP_ERR_NVS_NOT_ENOUGH_SPACE;
+        }
+
+        auto err = writeItem(Page::NS_INDEX, ItemType::U8, nsName, &ns, sizeof(ns));
+        if (err != ESP_OK) {
+            return err;
+        }
+        mNamespaceUsage.set(ns, true);
+        nsIndex = ns;
+
+        NamespaceEntry* entry = new NamespaceEntry;
+        entry->mIndex = ns;
+        strncpy(entry->mName, nsName, sizeof(entry->mName) - 1);
+        entry->mName[sizeof(entry->mName) - 1] = 0;
+        mNamespaces.push_back(entry);
+
+    } else {
+        nsIndex = it->mIndex;
+    }
+    return ESP_OK;
+}
+
+esp_err_t Storage::readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    Item item;
+    Page* findPage = nullptr;
+    auto err = findItem(nsIndex, datatype, key, findPage, item);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    return findPage->readItem(nsIndex, datatype, key, data, dataSize);
+}
+
+esp_err_t Storage::eraseItem(uint8_t nsIndex, ItemType datatype, const char* key)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    Item item;
+    Page* findPage = nullptr;
+    auto err = findItem(nsIndex, datatype, key, findPage, item);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    return findPage->eraseItem(nsIndex, datatype, key);
+}
+
+esp_err_t Storage::eraseNamespace(uint8_t nsIndex)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
+        while (true) {
+            auto err = it->eraseItem(nsIndex, ItemType::ANY, nullptr);
+            if (err == ESP_ERR_NVS_NOT_FOUND) {
+                break;
+            }
+            else if (err != ESP_OK) {
+                return err;
+            }
+        }
+    }
+    return ESP_OK;
+
+}
+
+esp_err_t Storage::getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize)
+{
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    Item item;
+    Page* findPage = nullptr;
+    auto err = findItem(nsIndex, datatype, key, findPage, item);
+    if (err != ESP_OK) {
+        return err;
+    }
+
+    dataSize = item.varLength.dataSize;
+    return ESP_OK;
+}
+
+void Storage::debugDump()
+{
+    for (auto p = mPageManager.begin(); p != mPageManager.end(); ++p) {
+        p->debugDump();
+    }
+}
+
+#ifndef ESP_PLATFORM
+void Storage::debugCheck()
+{
+    std::map<std::string, Page*> keys;
+
+    for (auto p = mPageManager.begin(); p != mPageManager.end(); ++p) {
+        size_t itemIndex = 0;
+        size_t usedCount = 0;
+        Item item;
+        while (p->findItem(Page::NS_ANY, ItemType::ANY, nullptr, itemIndex, item) == ESP_OK) {
+            std::stringstream keyrepr;
+            keyrepr << static_cast<unsigned>(item.nsIndex) << "_" << static_cast<unsigned>(item.datatype) << "_" << item.key;
+            std::string keystr = keyrepr.str();
+            if (keys.find(keystr) != std::end(keys)) {
+                printf("Duplicate key: %s\n", keystr.c_str());
+                debugDump();
+                assert(0);
+            }
+            keys.insert(std::make_pair(keystr, static_cast<Page*>(p)));
+            itemIndex += item.span;
+            usedCount += item.span;
+        }
+        assert(usedCount == p->getUsedEntryCount());
+    }
+}
+#endif //ESP_PLATFORM
+
+esp_err_t Storage::fillStats(nvs_stats_t& nvsStats)
+{
+    nvsStats.namespace_count = mNamespaces.size();
+    return mPageManager.fillStats(nvsStats);
+}
+
+esp_err_t Storage::calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries)
+{
+    usedEntries = 0;
+
+    if (mState != StorageState::ACTIVE) {
+        return ESP_ERR_NVS_NOT_INITIALIZED;
+    }
+
+    for (auto it = std::begin(mPageManager); it != std::end(mPageManager); ++it) {
+        size_t itemIndex = 0;
+        Item item;
+        while (true) {
+            auto err = it->findItem(nsIndex, ItemType::ANY, nullptr, itemIndex, item);
+            if (err == ESP_ERR_NVS_NOT_FOUND) {
+                break;
+            }
+            else if (err != ESP_OK) {
+                return err;
+            }
+            usedEntries += item.span;
+            itemIndex   += item.span;
+            if(itemIndex >= it->ENTRY_COUNT) break;
+        }
+    }
+    return ESP_OK;
+}
+
+}
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_storage.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_storage.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..f6b8925d8b107ee18e5f283dbec463cfaef575cd
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_storage.hpp
@@ -0,0 +1,120 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef nvs_storage_hpp
+#define nvs_storage_hpp
+
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include "nvs.hpp"
+#include "nvs_types.hpp"
+#include "nvs_page.hpp"
+#include "nvs_pagemanager.hpp"
+
+//extern void dumpBytes(const uint8_t* data, size_t count);
+
+namespace nvs
+{
+
+class Storage : public intrusive_list_node<Storage>
+{
+    enum class StorageState : uint32_t {
+        INVALID,
+        ACTIVE,
+    };
+
+    struct NamespaceEntry : public intrusive_list_node<NamespaceEntry> {
+    public:
+        char mName[Item::MAX_KEY_LENGTH + 1];
+        uint8_t mIndex;
+    };
+
+    typedef intrusive_list<NamespaceEntry> TNamespaces;
+
+public:
+    ~Storage();
+
+    Storage(const char *pName = NVS_DEFAULT_PART_NAME) : mPartitionName(pName) { };
+
+    esp_err_t init(uint32_t baseSector, uint32_t sectorCount);
+
+    bool isValid() const;
+
+    esp_err_t createOrOpenNamespace(const char* nsName, bool canCreate, uint8_t& nsIndex);
+
+    esp_err_t writeItem(uint8_t nsIndex, ItemType datatype, const char* key, const void* data, size_t dataSize);
+
+    esp_err_t readItem(uint8_t nsIndex, ItemType datatype, const char* key, void* data, size_t dataSize);
+
+    esp_err_t getItemDataSize(uint8_t nsIndex, ItemType datatype, const char* key, size_t& dataSize);
+
+    esp_err_t eraseItem(uint8_t nsIndex, ItemType datatype, const char* key);
+
+    template<typename T>
+    esp_err_t writeItem(uint8_t nsIndex, const char* key, const T& value)
+    {
+        return writeItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value));
+    }
+
+    template<typename T>
+    esp_err_t readItem(uint8_t nsIndex, const char* key, T& value)
+    {
+        return readItem(nsIndex, itemTypeOf(value), key, &value, sizeof(value));
+    }
+
+    esp_err_t eraseItem(uint8_t nsIndex, const char* key)
+    {
+        return eraseItem(nsIndex, ItemType::ANY, key);
+    }
+
+    esp_err_t eraseNamespace(uint8_t nsIndex);
+
+    const char *getPartName() const
+    {
+        return mPartitionName;
+    }
+
+    void debugDump();
+
+    void debugCheck();
+
+    esp_err_t fillStats(nvs_stats_t& nvsStats);
+
+    esp_err_t calcEntriesInNamespace(uint8_t nsIndex, size_t& usedEntries);
+
+protected:
+
+    Page& getCurrentPage()
+    {
+        return mPageManager.back();
+    }
+
+    void clearNamespaces();
+
+    esp_err_t findItem(uint8_t nsIndex, ItemType datatype, const char* key, Page* &page, Item& item);
+
+protected:
+    const char *mPartitionName;
+    size_t mPageCount;
+    PageManager mPageManager;
+    TNamespaces mNamespaces;
+    CompressedEnumTable<bool, 1, 256> mNamespaceUsage;
+    StorageState mState = StorageState::INVALID;
+};
+
+} // namespace nvs
+
+
+
+#endif /* nvs_storage_hpp */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_test_api.h b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_test_api.h
new file mode 100644
index 0000000000000000000000000000000000000000..f1a3a2ebb42db6445a236cfe0e2a7961b5615dff
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_test_api.h
@@ -0,0 +1,53 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef NVS_TEST_API_H
+#define NVS_TEST_API_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "nvs_flash.h"
+
+/**
+ * @brief Initialize NVS flash storage with custom flash sector layout
+ *
+ * @note  This API is intended to be used in unit tests.
+ *
+ * @param partName Partition name of the NVS partition as per partition table
+ * @param baseSector Flash sector (units of 4096 bytes) offset to start NVS
+ * @param sectorCount Length (in flash sectors) of NVS region.
+                       NVS partition must be at least 3 sectors long.
+ * @return ESP_OK if flash was successfully initialized
+ */
+esp_err_t nvs_flash_init_custom(const char *partName, uint32_t baseSector, uint32_t sectorCount);
+
+
+/**
+ * @brief Dump contents of NVS storage to stdout
+ *
+ * This function may be used for debugging purposes to inspect the state
+ * of NVS pages. For each page, list of entries is also dumped.
+ *
+ * @param partName Partition name of the NVS partition as per partition table
+ */
+void nvs_dump(const char *partName);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* NVS_TEST_API_H */
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_types.cpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_types.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..d44d8b29f93f064e3284ed290d6c55a5217bc1a3
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_types.cpp
@@ -0,0 +1,52 @@
+// 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 "nvs_types.hpp"
+
+#if defined(ESP_PLATFORM)
+#include <rom/crc.h>
+#else
+#include "crc.h"
+#endif
+
+namespace nvs
+{
+uint32_t Item::calculateCrc32() const
+{
+    uint32_t result = 0xffffffff;
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(this);
+    result = crc32_le(result, p + offsetof(Item, nsIndex),
+                      offsetof(Item, crc32) - offsetof(Item, nsIndex));
+    result = crc32_le(result, p + offsetof(Item, key), sizeof(key));
+    result = crc32_le(result, p + offsetof(Item, data), sizeof(data));
+    return result;
+}
+
+uint32_t Item::calculateCrc32WithoutValue() const
+{
+    uint32_t result = 0xffffffff;
+    const uint8_t* p = reinterpret_cast<const uint8_t*>(this);
+    result = crc32_le(result, p + offsetof(Item, nsIndex),
+                      offsetof(Item, datatype) - offsetof(Item, nsIndex));
+    result = crc32_le(result, p + offsetof(Item, key), sizeof(key));
+    return result;
+}
+
+uint32_t Item::calculateCrc32(const uint8_t* data, size_t size)
+{
+    uint32_t result = 0xffffffff;
+    result = crc32_le(result, data, size);
+    return result;
+}
+
+} // namespace nvs
diff --git a/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_types.hpp b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_types.hpp
new file mode 100644
index 0000000000000000000000000000000000000000..5306744b5f22bec7d7e241e86f6e70810de22033
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/nvs_flash/nvs_types.hpp
@@ -0,0 +1,118 @@
+// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef nvs_types_h
+#define nvs_types_h
+
+#include <cstdint>
+#include <type_traits>
+#include <cstring>
+#include <cassert>
+#include <algorithm>
+#include "nvs.h"
+#include "compressed_enum_table.hpp"
+
+
+namespace nvs
+{
+
+enum class ItemType : uint8_t {
+    U8   = 0x01,
+    I8   = 0x11,
+    U16  = 0x02,
+    I16  = 0x12,
+    U32  = 0x04,
+    I32  = 0x14,
+    U64  = 0x08,
+    I64  = 0x18,
+    SZ   = 0x21,
+    BLOB = 0x41,
+    ANY  = 0xff
+};
+
+template<typename T, typename std::enable_if<std::is_integral<T>::value, void*>::type = nullptr>
+constexpr ItemType itemTypeOf()
+{
+    return static_cast<ItemType>(((std::is_signed<T>::value)?0x10:0x00) | sizeof(T));
+}
+
+template<typename T>
+constexpr ItemType itemTypeOf(const T&)
+{
+    return itemTypeOf<T>();
+}
+
+class Item
+{
+public:
+    union {
+        struct {
+            uint8_t  nsIndex;
+            ItemType datatype;
+            uint8_t  span;
+            uint8_t  reserved;
+            uint32_t crc32;
+            char     key[16];
+            union {
+                struct {
+                    uint16_t dataSize;
+                    uint16_t reserved2;
+                    uint32_t dataCrc32;
+                } varLength;
+                uint8_t data[8];
+            };
+        };
+        uint8_t rawData[32];
+    };
+
+    static const size_t MAX_KEY_LENGTH = sizeof(key) - 1;
+
+    Item(uint8_t nsIndex, ItemType datatype, uint8_t span, const char* key_)
+        : nsIndex(nsIndex), datatype(datatype), span(span), reserved(0xff)
+    {
+        std::fill_n(reinterpret_cast<uint32_t*>(key),  sizeof(key)  / 4, 0xffffffff);
+        std::fill_n(reinterpret_cast<uint32_t*>(data), sizeof(data) / 4, 0xffffffff);
+        if (key_) {
+            strncpy(key, key_, sizeof(key) - 1);
+            key[sizeof(key) - 1] = 0;
+        } else {
+            key[0] = 0;
+        }
+    }
+
+    Item()
+    {
+    }
+
+    uint32_t calculateCrc32() const;
+    uint32_t calculateCrc32WithoutValue() const;
+    static uint32_t calculateCrc32(const uint8_t* data, size_t size);
+
+    void getKey(char* dst, size_t dstSize)
+    {
+        strncpy(dst, key, (dstSize<MAX_KEY_LENGTH)?dstSize:MAX_KEY_LENGTH);
+    }
+
+    template<typename T>
+    void getValue(T& dst)
+    {
+        assert(itemTypeOf(dst) == datatype);
+        dst = *reinterpret_cast<T*>(data);
+    }
+};
+
+} // namespace nvs
+
+
+
+#endif /* nvs_types_h */
diff --git a/cpu/esp32/vendor/esp-idf/soc/Makefile b/cpu/esp32/vendor/esp-idf/soc/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..b3e7c845e072e85e6d284a774100116e8196f96a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/Makefile
@@ -0,0 +1,6 @@
+MODULE=esp_idf_soc
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(ESP32_SDK_DIR)/components/soc/esp32
diff --git a/cpu/esp32/vendor/esp-idf/soc/cpu_util.c b/cpu/esp32/vendor/esp-idf/soc/cpu_util.c
new file mode 100644
index 0000000000000000000000000000000000000000..452b4131e28dfc2721ef8a1868923b599cffa4c0
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/cpu_util.c
@@ -0,0 +1,64 @@
+// Copyright 2013-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 "esp_common.h"
+#include "esp_attr.h"
+#include "soc/cpu.h"
+#include "soc/soc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "sdk_conf.h"
+
+void IRAM_ATTR esp_cpu_stall(int cpu_id)
+{
+    if (cpu_id == 1) {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
+        SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_APPCPU_C1_S);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_APPCPU_C0_S);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
+        SET_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, 0x21<<RTC_CNTL_SW_STALL_PROCPU_C1_S);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, 2<<RTC_CNTL_SW_STALL_PROCPU_C0_S);
+    }
+}
+
+void IRAM_ATTR esp_cpu_unstall(int cpu_id)
+{
+    if (cpu_id == 1) {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_APPCPU_C1_M);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_APPCPU_C0_M);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_SW_CPU_STALL_REG, RTC_CNTL_SW_STALL_PROCPU_C1_M);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_STALL_PROCPU_C0_M);
+    }
+}
+
+void IRAM_ATTR esp_cpu_reset(int cpu_id)
+{
+    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
+            cpu_id == 0 ? RTC_CNTL_SW_PROCPU_RST_M : RTC_CNTL_SW_APPCPU_RST_M);
+}
+
+bool IRAM_ATTR esp_cpu_in_ocd_debug_mode(void)
+{
+#if CONFIG_ESP32_DEBUG_OCDAWARE
+    int dcr;
+    int reg=0x10200C; //DSRSET register
+    asm("rer %0,%1":"=r"(dcr):"r"(reg));
+    return (dcr&0x1);
+#else
+    return false; // Always return false if "OCD aware" is disabled
+#endif
+}
diff --git a/cpu/esp32/vendor/esp-idf/soc/rtc_clk.c b/cpu/esp32/vendor/esp-idf/soc/rtc_clk.c
new file mode 100644
index 0000000000000000000000000000000000000000..febdc65aa91da867abe3b13a40931d48280cd2fc
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/rtc_clk.c
@@ -0,0 +1,764 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <stddef.h>
+#include <assert.h>
+#include "rom/ets_sys.h"
+#include "rom/rtc.h"
+#include "rom/uart.h"
+#ifndef RIOT_VERSION
+#include "rom/gpio.h"
+#endif
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/rtc_io_reg.h"
+#include "soc/sens_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/efuse_reg.h"
+#include "soc/apb_ctrl_reg.h"
+#include "i2c_rtc_clk.h"
+#include "soc_log.h"
+#include "sdk_conf.h"
+#include "xtensa/core-macros.h"
+
+#ifdef RIOT_VERSION
+/* These functions are declared in rom/gpio.h. However, due to conflichts with
+   RIOT's periph/gpio.h, we cannot include rom/gpio.h */
+extern void gpio_pad_select_gpio(uint8_t gpio_num);
+extern void gpio_output_set_high(uint32_t set_mask, uint32_t clear_mask, uint32_t enable_mask, uint32_t disable_mask);
+#endif
+
+#define MHZ (1000000)
+
+/* Frequency of the 8M oscillator is 8.5MHz +/- 5%, at the default DCAP setting */
+#define RTC_FAST_CLK_FREQ_8M        8500000
+#define RTC_SLOW_CLK_FREQ_150K      150000
+#define RTC_SLOW_CLK_FREQ_8MD256    (RTC_FAST_CLK_FREQ_8M / 256)
+#define RTC_SLOW_CLK_FREQ_32K       32768
+
+static const char* TAG = "rtc_clk";
+
+/* Various constants related to the analog internals of the chip.
+ * Defined here because they don't have any use outside of this file.
+ */
+
+#define BBPLL_ENDIV5_VAL_320M       0x43
+#define BBPLL_BBADC_DSMP_VAL_320M   0x84
+#define BBPLL_ENDIV5_VAL_480M       0xc3
+#define BBPLL_BBADC_DSMP_VAL_480M   0x74
+
+#define APLL_SDM_STOP_VAL_1         0x09
+#define APLL_SDM_STOP_VAL_2_REV0    0x69
+#define APLL_SDM_STOP_VAL_2_REV1    0x49
+
+#define APLL_CAL_DELAY_1            0x0f
+#define APLL_CAL_DELAY_2            0x3f
+#define APLL_CAL_DELAY_3            0x1f
+
+#define XTAL_32K_DAC_VAL    1
+#define XTAL_32K_DRES_VAL   3
+#define XTAL_32K_DBIAS_VAL  0
+
+#define XTAL_32K_BOOTSTRAP_DAC_VAL      3
+#define XTAL_32K_BOOTSTRAP_DRES_VAL     3
+#define XTAL_32K_BOOTSTRAP_DBIAS_VAL    0
+#define XTAL_32K_BOOTSTRAP_TIME_US      7
+
+/* Delays for various clock sources to be enabled/switched.
+ * All values are in microseconds.
+ * TODO: some of these are excessive, and should be reduced.
+ */
+#define DELAY_PLL_DBIAS_RAISE           3
+#define DELAY_PLL_ENABLE_WITH_150K      80
+#define DELAY_PLL_ENABLE_WITH_32K       160
+#define DELAY_FAST_CLK_SWITCH           3
+#define DELAY_SLOW_CLK_SWITCH           300
+#define DELAY_8M_ENABLE                 50
+
+/* Number of 8M/256 clock cycles to use for XTAL frequency estimation.
+ * 10 cycles will take approximately 300 microseconds.
+ */
+#define XTAL_FREQ_EST_CYCLES            10
+
+/* Core voltage needs to be increased in two cases:
+ * 1. running at 240 MHz
+ * 2. running with 80MHz Flash frequency
+ */
+#ifdef CONFIG_ESPTOOLPY_FLASHFREQ_80M
+#define DIG_DBIAS_80M_160M  RTC_CNTL_DBIAS_1V25
+#else
+#define DIG_DBIAS_80M_160M  RTC_CNTL_DBIAS_1V10
+#endif
+#define DIG_DBIAS_240M      RTC_CNTL_DBIAS_1V25
+#define DIG_DBIAS_XTAL      RTC_CNTL_DBIAS_1V10
+#define DIG_DBIAS_2M        RTC_CNTL_DBIAS_1V00
+
+/* PLL currently enabled, if any */
+typedef enum {
+    RTC_PLL_NONE,
+    RTC_PLL_320M,
+    RTC_PLL_480M
+} rtc_pll_t;
+static rtc_pll_t s_cur_pll = RTC_PLL_NONE;
+
+/* Current CPU frequency; saved in a variable for faster freq. switching */
+static rtc_cpu_freq_t s_cur_freq = RTC_CPU_FREQ_XTAL;
+
+
+static void rtc_clk_32k_enable_internal(int dac, int dres, int dbias)
+{
+    SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
+    CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG,
+            RTC_IO_X32P_RDE | RTC_IO_X32P_RUE | RTC_IO_X32N_RUE |
+            RTC_IO_X32N_RDE | RTC_IO_X32N_MUX_SEL | RTC_IO_X32P_MUX_SEL);
+    REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DAC_XTAL_32K, dac);
+    REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DRES_XTAL_32K, dres);
+    REG_SET_FIELD(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_DBIAS_XTAL_32K, dbias);
+    SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K);
+}
+
+void rtc_clk_32k_enable(bool enable)
+{
+    if (enable) {
+        rtc_clk_32k_enable_internal(XTAL_32K_DAC_VAL, XTAL_32K_DRES_VAL, XTAL_32K_DBIAS_VAL);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K);
+    }
+}
+
+/* Helping external 32kHz crystal to start up.
+ * External crystal connected to outputs GPIO32 GPIO33.
+ * Forms N pulses with a frequency of about 32KHz on the outputs of the crystal.
+ */
+void rtc_clk_32k_bootstrap(uint32_t cycle)
+{
+    if (cycle){
+        const uint32_t pin_32 = 32;
+        const uint32_t pin_33 = 33;
+        const uint32_t mask_32 = (1 << (pin_32 - 32));
+        const uint32_t mask_33 = (1 << (pin_33 - 32));
+
+        gpio_pad_select_gpio(pin_32);
+        gpio_pad_select_gpio(pin_33);
+        gpio_output_set_high(mask_32, mask_33, mask_32 | mask_33, 0);
+
+        const uint32_t delay_us = (1000000 / RTC_SLOW_CLK_FREQ_32K / 2);
+        while(cycle){
+            gpio_output_set_high(mask_32, mask_33, mask_32 | mask_33, 0);
+            ets_delay_us(delay_us);
+            gpio_output_set_high(mask_33, mask_32, mask_32 | mask_33, 0);
+            ets_delay_us(delay_us);
+            cycle--;
+        }
+        gpio_output_set_high(0, 0, 0, mask_32 | mask_33); // disable pins
+    }
+
+    CLEAR_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K);
+    SET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_X32P_RUE | RTC_IO_X32N_RDE);
+    ets_delay_us(XTAL_32K_BOOTSTRAP_TIME_US);
+
+    rtc_clk_32k_enable_internal(XTAL_32K_BOOTSTRAP_DAC_VAL,
+            XTAL_32K_BOOTSTRAP_DRES_VAL, XTAL_32K_BOOTSTRAP_DBIAS_VAL);
+}
+
+bool rtc_clk_32k_enabled(void)
+{
+    return GET_PERI_REG_MASK(RTC_IO_XTAL_32K_PAD_REG, RTC_IO_XPD_XTAL_32K) != 0;
+}
+
+void rtc_clk_8m_enable(bool clk_8m_en, bool d256_en)
+{
+    if (clk_8m_en) {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
+        /* no need to wait once enabled by software */
+        REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, 1);
+        if (d256_en) {
+            CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
+        } else {
+            SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV);
+        }
+        ets_delay_us(DELAY_8M_ENABLE);
+    } else {
+        SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M);
+        REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_DEFAULT);
+    }
+}
+
+bool rtc_clk_8m_enabled(void)
+{
+    return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M) == 0;
+}
+
+bool rtc_clk_8md256_enabled(void)
+{
+    return GET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ENB_CK8M_DIV) == 0;
+}
+
+void rtc_clk_apll_enable(bool enable, uint32_t sdm0, uint32_t sdm1, uint32_t sdm2, uint32_t o_div)
+{
+    REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD, enable ? 0 : 1);
+    REG_SET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU, enable ? 1 : 0);
+
+    if (!enable &&
+        REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL) != RTC_CNTL_SOC_CLK_SEL_PLL) {
+        REG_SET_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
+    } else {
+        REG_CLR_BIT(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
+    }
+
+    if (enable) {
+        uint8_t sdm_stop_val_2 = APLL_SDM_STOP_VAL_2_REV1;
+        uint32_t is_rev0 = (GET_PERI_REG_BITS2(EFUSE_BLK0_RDATA3_REG, 1, 15) == 0);
+        if (is_rev0) {
+            sdm0 = 0;
+            sdm1 = 0;
+            sdm_stop_val_2 = APLL_SDM_STOP_VAL_2_REV0;
+        }
+        I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_DSDM2, sdm2);
+        I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_DSDM0, sdm0);
+        I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_DSDM1, sdm1);
+        I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_SDM_STOP, APLL_SDM_STOP_VAL_1);
+        I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_SDM_STOP, sdm_stop_val_2);
+        I2C_WRITEREG_MASK_RTC(I2C_APLL, I2C_APLL_OR_OUTPUT_DIV, o_div);
+
+        /* calibration */
+        I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_1);
+        I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_2);
+        I2C_WRITEREG_RTC(I2C_APLL, I2C_APLL_IR_CAL_DELAY, APLL_CAL_DELAY_3);
+
+        /* wait for calibration end */
+        while (!(I2C_READREG_MASK_RTC(I2C_APLL, I2C_APLL_OR_CAL_END))) {
+            /* use ets_delay_us so the RTC bus doesn't get flooded */
+            ets_delay_us(1);
+        }
+    }
+}
+
+void rtc_clk_slow_freq_set(rtc_slow_freq_t slow_freq)
+{
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL, slow_freq);
+
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN,
+            (slow_freq == RTC_SLOW_FREQ_32K_XTAL) ? 1 : 0);
+
+    ets_delay_us(DELAY_SLOW_CLK_SWITCH);
+}
+
+rtc_slow_freq_t rtc_clk_slow_freq_get(void)
+{
+    return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
+}
+
+uint32_t rtc_clk_slow_freq_get_hz(void)
+{
+    switch(rtc_clk_slow_freq_get()) {
+        case RTC_SLOW_FREQ_RTC: return RTC_SLOW_CLK_FREQ_150K;
+        case RTC_SLOW_FREQ_32K_XTAL: return RTC_SLOW_CLK_FREQ_32K;
+        case RTC_SLOW_FREQ_8MD256: return RTC_SLOW_CLK_FREQ_8MD256;
+    }
+    return 0;
+}
+
+void rtc_clk_fast_freq_set(rtc_fast_freq_t fast_freq)
+{
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL, fast_freq);
+    ets_delay_us(DELAY_FAST_CLK_SWITCH);
+}
+
+rtc_fast_freq_t rtc_clk_fast_freq_get(void)
+{
+    return REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_FAST_CLK_RTC_SEL);
+}
+
+void rtc_clk_bbpll_set(rtc_xtal_freq_t xtal_freq, rtc_cpu_freq_t cpu_freq)
+{
+    uint8_t div_ref;
+    uint8_t div7_0;
+    uint8_t div10_8;
+    uint8_t lref;
+    uint8_t dcur;
+    uint8_t bw;
+
+    if (cpu_freq != RTC_CPU_FREQ_240M) {
+        /* Raise the voltage, if needed */
+        REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_80M_160M);
+        /* Configure 320M PLL */
+        switch (xtal_freq) {
+            case RTC_XTAL_FREQ_40M:
+                div_ref = 0;
+                div7_0 = 32;
+                div10_8 = 0;
+                lref = 0;
+                dcur = 6;
+                bw = 3;
+                break;
+            case RTC_XTAL_FREQ_26M:
+                div_ref = 12;
+                div7_0 = 224;
+                div10_8 = 4;
+                lref = 1;
+                dcur = 0;
+                bw = 1;
+                break;
+            case RTC_XTAL_FREQ_24M:
+                div_ref = 11;
+                div7_0 = 224;
+                div10_8 = 4;
+                lref = 1;
+                dcur = 0;
+                bw = 1;
+                break;
+            default:
+                div_ref = 12;
+                div7_0 = 224;
+                div10_8 = 4;
+                lref = 0;
+                dcur = 0;
+                bw = 0;
+                break;
+        }
+        I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_320M);
+        I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_320M);
+    } else {
+        /* Raise the voltage */
+        REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M);
+        ets_delay_us(DELAY_PLL_DBIAS_RAISE);
+        /* Configure 480M PLL */
+        switch (xtal_freq) {
+            case RTC_XTAL_FREQ_40M:
+                div_ref = 0;
+                div7_0 = 28;
+                div10_8 = 0;
+                lref = 0;
+                dcur = 6;
+                bw = 3;
+                break;
+            case RTC_XTAL_FREQ_26M:
+                div_ref = 12;
+                div7_0 = 144;
+                div10_8 = 4;
+                lref = 1;
+                dcur = 0;
+                bw = 1;
+                break;
+            case RTC_XTAL_FREQ_24M:
+                div_ref = 11;
+                div7_0 = 144;
+                div10_8 = 4;
+                lref = 1;
+                dcur = 0;
+                bw = 1;
+                break;
+            default:
+                div_ref = 12;
+                div7_0 = 224;
+                div10_8 = 4;
+                lref = 0;
+                dcur = 0;
+                bw = 0;
+                break;
+        }
+        I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_ENDIV5, BBPLL_ENDIV5_VAL_480M);
+        I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_BBADC_DSMP, BBPLL_BBADC_DSMP_VAL_480M);
+    }
+
+    uint8_t i2c_bbpll_lref  = (lref << 7) | (div10_8 << 4) | (div_ref);
+    uint8_t i2c_bbpll_div_7_0 = div7_0;
+    uint8_t i2c_bbpll_dcur = (bw << 6) | dcur;
+    I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_LREF, i2c_bbpll_lref);
+    I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DIV_7_0, i2c_bbpll_div_7_0);
+    I2C_WRITEREG_RTC(I2C_BBPLL, I2C_BBPLL_OC_DCUR, i2c_bbpll_dcur);
+    uint32_t delay_pll_en = (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) ?
+            DELAY_PLL_ENABLE_WITH_150K : DELAY_PLL_ENABLE_WITH_32K;
+    ets_delay_us(delay_pll_en);
+}
+
+/**
+ * Switch to XTAL frequency. Does not disable the PLL.
+ */
+static void rtc_clk_cpu_freq_to_xtal(void)
+{
+    rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
+    ets_update_cpu_frequency(xtal_freq);
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
+    REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, 0);
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_XTL);
+    DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 0); // clear DPORT_CPUPERIOD_SEL
+
+    rtc_clk_apb_freq_update(xtal_freq * MHZ);
+    s_cur_freq = RTC_CPU_FREQ_XTAL;
+}
+
+/**
+ * Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
+ * PLL must already be enabled.
+ * If switching between frequencies derived from different PLLs (320M and 480M),
+ * fall back to rtc_clk_cpu_freq_set.
+ * @param cpu_freq new CPU frequency
+ */
+static void rtc_clk_cpu_freq_to_pll(rtc_cpu_freq_t cpu_freq)
+{
+    int freq = 0;
+    if (s_cur_pll == RTC_PLL_NONE ||
+        (cpu_freq == RTC_CPU_FREQ_240M && s_cur_pll == RTC_PLL_320M) ||
+        (cpu_freq != RTC_CPU_FREQ_240M && s_cur_pll == RTC_PLL_480M)) {
+        /* need to switch PLLs, fall back to full implementation */
+        rtc_clk_cpu_freq_set(cpu_freq);
+        return;
+    }
+
+    if (cpu_freq == RTC_CPU_FREQ_80M) {
+        REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_80M_160M);
+        DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 0);
+        freq = 80;
+    } else if (cpu_freq == RTC_CPU_FREQ_160M) {
+        REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_80M_160M);
+        DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 1);
+        freq = 160;
+    } else if (cpu_freq == RTC_CPU_FREQ_240M) {
+        REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_240M);
+        DPORT_REG_WRITE(DPORT_CPU_PER_CONF_REG, 2);
+        freq = 240;
+    }
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL);
+    rtc_clk_apb_freq_update(80 * MHZ);
+    ets_update_cpu_frequency(freq);
+    s_cur_freq = cpu_freq;
+}
+
+void rtc_clk_cpu_freq_set_fast(rtc_cpu_freq_t cpu_freq)
+{
+    if (cpu_freq == s_cur_freq) {
+        return;
+    } else if (cpu_freq == RTC_CPU_FREQ_2M || s_cur_freq == RTC_CPU_FREQ_2M) {
+        /* fall back to full implementation if switch to/from 2M is needed */
+        rtc_clk_cpu_freq_set(cpu_freq);
+    } else if (cpu_freq == RTC_CPU_FREQ_XTAL) {
+        rtc_clk_cpu_freq_to_xtal();
+    } else if (cpu_freq > RTC_CPU_FREQ_XTAL) {
+        rtc_clk_cpu_freq_to_pll(cpu_freq);
+        rtc_clk_wait_for_slow_cycle();
+    }
+}
+
+void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq)
+{
+    rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
+    /* Switch CPU to XTAL frequency first */
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_XTAL);
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_XTL);
+    REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, 0);
+    ets_update_cpu_frequency(xtal_freq);
+
+    /* Frequency switch is synchronized to SLOW_CLK cycle. Wait until the switch
+     * is complete before disabling the PLL.
+     */
+    rtc_clk_wait_for_slow_cycle();
+
+    DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
+    SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
+            RTC_CNTL_BB_I2C_FORCE_PD | RTC_CNTL_BBPLL_FORCE_PD |
+            RTC_CNTL_BBPLL_I2C_FORCE_PD);
+    s_cur_pll = RTC_PLL_NONE;
+    rtc_clk_apb_freq_update(xtal_freq * MHZ);
+
+    /* is APLL under force power down? */
+    uint32_t apll_fpd = REG_GET_FIELD(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD);
+    if (apll_fpd) {
+        /* then also power down the internal I2C bus */
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PD);
+    }
+    /* now switch to the desired frequency */
+    if (cpu_freq == RTC_CPU_FREQ_XTAL) {
+        /* already at XTAL, nothing to do */
+    } else if (cpu_freq == RTC_CPU_FREQ_2M) {
+        /* set up divider to produce 2MHz from XTAL */
+        REG_SET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT, (xtal_freq / 2) - 1);
+        ets_update_cpu_frequency(2);
+        rtc_clk_apb_freq_update(2 * MHZ);
+        /* lower the voltage */
+        REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, DIG_DBIAS_2M);
+    } else {
+        /* use PLL as clock source */
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG,
+                RTC_CNTL_BIAS_I2C_FORCE_PD | RTC_CNTL_BB_I2C_FORCE_PD |
+                RTC_CNTL_BBPLL_FORCE_PD | RTC_CNTL_BBPLL_I2C_FORCE_PD);
+        rtc_clk_bbpll_set(xtal_freq, cpu_freq);
+        if (cpu_freq == RTC_CPU_FREQ_80M) {
+            DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 0);
+            ets_update_cpu_frequency(80);
+            s_cur_pll = RTC_PLL_320M;
+        } else if (cpu_freq == RTC_CPU_FREQ_160M) {
+            DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 1);
+            ets_update_cpu_frequency(160);
+            s_cur_pll = RTC_PLL_320M;
+        } else if (cpu_freq == RTC_CPU_FREQ_240M) {
+            DPORT_REG_SET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL, 2);
+            ets_update_cpu_frequency(240);
+            s_cur_pll = RTC_PLL_480M;
+        }
+        REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL);
+        rtc_clk_wait_for_slow_cycle();
+        rtc_clk_apb_freq_update(80 * MHZ);
+    }
+    s_cur_freq = cpu_freq;
+}
+
+rtc_cpu_freq_t rtc_clk_cpu_freq_get(void)
+{
+    uint32_t soc_clk_sel = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL);
+    switch (soc_clk_sel) {
+        case RTC_CNTL_SOC_CLK_SEL_XTL: {
+            uint32_t pre_div = REG_GET_FIELD(APB_CTRL_SYSCLK_CONF_REG, APB_CTRL_PRE_DIV_CNT);
+            if (pre_div == 0) {
+                return RTC_CPU_FREQ_XTAL;
+            } else if (pre_div == rtc_clk_xtal_freq_get() / 2 - 1) {
+                return RTC_CPU_FREQ_2M;
+            } else {
+                assert(false && "unsupported frequency");
+            }
+            break;
+        }
+        case RTC_CNTL_SOC_CLK_SEL_PLL: {
+            uint32_t cpuperiod_sel = DPORT_REG_GET_FIELD(DPORT_CPU_PER_CONF_REG, DPORT_CPUPERIOD_SEL);
+            if (cpuperiod_sel == 0) {
+                return RTC_CPU_FREQ_80M;
+            } else if (cpuperiod_sel == 1) {
+                return RTC_CPU_FREQ_160M;
+            } else if (cpuperiod_sel == 2) {
+                return RTC_CPU_FREQ_240M;
+            } else {
+                assert(false && "unsupported frequency");
+            }
+            break;
+        }
+        case RTC_CNTL_SOC_CLK_SEL_APLL:
+        case RTC_CNTL_SOC_CLK_SEL_8M:
+        default:
+            assert(false && "unsupported frequency");
+    }
+    return RTC_CNTL_SOC_CLK_SEL_XTL;
+}
+
+uint32_t rtc_clk_cpu_freq_value(rtc_cpu_freq_t cpu_freq)
+{
+    switch (cpu_freq) {
+        case RTC_CPU_FREQ_XTAL:
+            return ((uint32_t) rtc_clk_xtal_freq_get()) * MHZ;
+        case RTC_CPU_FREQ_2M:
+            return 2 * MHZ;
+        case RTC_CPU_FREQ_80M:
+            return 80 * MHZ;
+        case RTC_CPU_FREQ_160M:
+            return 160 * MHZ;
+        case RTC_CPU_FREQ_240M:
+            return 240 * MHZ;
+        default:
+            assert(false && "invalid rtc_cpu_freq_t value");
+            return 0;
+    }
+}
+
+bool rtc_clk_cpu_freq_from_mhz(int mhz, rtc_cpu_freq_t* out_val)
+{
+    if (mhz == 240) {
+        *out_val = RTC_CPU_FREQ_240M;
+    } else if (mhz == 160) {
+        *out_val = RTC_CPU_FREQ_160M;
+    } else if (mhz == 80) {
+        *out_val = RTC_CPU_FREQ_80M;
+    } else if (mhz == (int) rtc_clk_xtal_freq_get()) {
+        *out_val = RTC_CPU_FREQ_XTAL;
+    } else if (mhz == 2) {
+        *out_val = RTC_CPU_FREQ_2M;
+    } else {
+        return false;
+    }
+    return true;
+}
+
+/* Values of RTC_XTAL_FREQ_REG and RTC_APB_FREQ_REG are stored as two copies in
+ * lower and upper 16-bit halves. These are the routines to work with such a
+ * representation.
+ */
+static bool clk_val_is_valid(uint32_t val) {
+    return (val & 0xffff) == ((val >> 16) & 0xffff) &&
+            val != 0 &&
+            val != UINT32_MAX;
+}
+
+static uint32_t reg_val_to_clk_val(uint32_t val) {
+    return val & UINT16_MAX;
+}
+
+static uint32_t clk_val_to_reg_val(uint32_t val) {
+    return (val & UINT16_MAX) | ((val & UINT16_MAX) << 16);
+}
+
+rtc_xtal_freq_t rtc_clk_xtal_freq_get(void)
+{
+    /* We may have already written XTAL value into RTC_XTAL_FREQ_REG */
+    uint32_t xtal_freq_reg = READ_PERI_REG(RTC_XTAL_FREQ_REG);
+    if (!clk_val_is_valid(xtal_freq_reg)) {
+        SOC_LOGW(TAG, "invalid RTC_XTAL_FREQ_REG value: 0x%08x", xtal_freq_reg);
+        return RTC_XTAL_FREQ_AUTO;
+    }
+    return reg_val_to_clk_val(xtal_freq_reg);
+}
+
+void rtc_clk_xtal_freq_update(rtc_xtal_freq_t xtal_freq)
+{
+    WRITE_PERI_REG(RTC_XTAL_FREQ_REG, clk_val_to_reg_val(xtal_freq));
+}
+
+static rtc_xtal_freq_t rtc_clk_xtal_freq_estimate(void)
+{
+    /* Enable 8M/256 clock if needed */
+    const bool clk_8m_enabled = rtc_clk_8m_enabled();
+    const bool clk_8md256_enabled = rtc_clk_8md256_enabled();
+    if (!clk_8md256_enabled) {
+        rtc_clk_8m_enable(true, true);
+    }
+
+    uint64_t cal_val = rtc_clk_cal_ratio(RTC_CAL_8MD256, XTAL_FREQ_EST_CYCLES);
+    /* cal_val contains period of 8M/256 clock in XTAL clock cycles
+     * (shifted by RTC_CLK_CAL_FRACT bits).
+     * Xtal frequency will be (cal_val * 8M / 256) / 2^19
+     */
+    uint32_t freq_mhz = (cal_val * RTC_FAST_CLK_FREQ_APPROX / MHZ / 256 ) >> RTC_CLK_CAL_FRACT;
+    /* Guess the XTAL type. For now, only 40 and 26MHz are supported.
+     */
+    switch (freq_mhz) {
+        case 21 ... 31:
+            return RTC_XTAL_FREQ_26M;
+        case 32 ... 33:
+            SOC_LOGW(TAG, "Potentially bogus XTAL frequency: %d MHz, guessing 26 MHz", freq_mhz);
+            return RTC_XTAL_FREQ_26M;
+        case 34 ... 35:
+            SOC_LOGW(TAG, "Potentially bogus XTAL frequency: %d MHz, guessing 40 MHz", freq_mhz);
+            return RTC_XTAL_FREQ_40M;
+        case 36 ... 45:
+            return RTC_XTAL_FREQ_40M;
+        default:
+            SOC_LOGW(TAG, "Bogus XTAL frequency: %d MHz", freq_mhz);
+            return RTC_XTAL_FREQ_AUTO;
+    }
+    /* Restore 8M and 8md256 clocks to original state */
+    rtc_clk_8m_enable(clk_8m_enabled, clk_8md256_enabled);
+}
+
+void rtc_clk_apb_freq_update(uint32_t apb_freq)
+{
+    WRITE_PERI_REG(RTC_APB_FREQ_REG, clk_val_to_reg_val(apb_freq >> 12));
+}
+
+uint32_t rtc_clk_apb_freq_get(void)
+{
+    uint32_t freq_hz = reg_val_to_clk_val(READ_PERI_REG(RTC_APB_FREQ_REG)) << 12;
+    // round to the nearest MHz
+    freq_hz += MHZ / 2;
+    uint32_t remainder = freq_hz % MHZ;
+    return freq_hz - remainder;
+}
+
+
+void rtc_clk_init(rtc_clk_config_t cfg)
+{
+    rtc_cpu_freq_t cpu_source_before = rtc_clk_cpu_freq_get();
+
+    /* If we get a TG WDT system reset while running at 240MHz,
+     * DPORT_CPUPERIOD_SEL register will be reset to 0 resulting in 120MHz
+     * APB and CPU frequencies after reset. This will cause issues with XTAL
+     * frequency estimation, so we switch to XTAL frequency first.
+     *
+     * Ideally we would only do this if RTC_CNTL_SOC_CLK_SEL == PLL and
+     * PLL is configured for 480M, but it takes less time to switch to 40M and
+     * run the following code than querying the PLL does.
+     */
+    if (REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL) == RTC_CNTL_SOC_CLK_SEL_PLL) {
+        rtc_clk_cpu_freq_set(RTC_CPU_FREQ_XTAL);
+    }
+
+    /* Set tuning parameters for 8M and 150k clocks.
+     * Note: this doesn't attempt to set the clocks to precise frequencies.
+     * Instead, we calibrate these clocks against XTAL frequency later, when necessary.
+     * - SCK_DCAP value controls tuning of 150k clock.
+     *   The higher the value of DCAP is, the lower is the frequency.
+     * - CK8M_DFREQ value controls tuning of 8M clock.
+     *   CLK_8M_DFREQ constant gives the best temperature characteristics.
+     */
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_SCK_DCAP, cfg.slow_clk_dcap);
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DFREQ, cfg.clk_8m_dfreq);
+
+    /* Configure 8M clock division */
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_DIV_SEL, cfg.clk_8m_div);
+
+    /* Enable the internal bus used to configure PLLs */
+    SET_PERI_REG_BITS(ANA_CONFIG_REG, ANA_CONFIG_M, ANA_CONFIG_M, ANA_CONFIG_S);
+    CLEAR_PERI_REG_MASK(ANA_CONFIG_REG, I2C_APLL_M | I2C_BBPLL_M);
+
+    /* Estimate XTAL frequency */
+    rtc_xtal_freq_t xtal_freq = cfg.xtal_freq;
+    if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
+        if (clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) {
+            /* XTAL frequency has already been set, use existing value */
+            xtal_freq = rtc_clk_xtal_freq_get();
+        } else {
+            /* Not set yet, estimate XTAL frequency based on RTC_FAST_CLK */
+            xtal_freq = rtc_clk_xtal_freq_estimate();
+            if (xtal_freq == RTC_XTAL_FREQ_AUTO) {
+                SOC_LOGW(TAG, "Can't estimate XTAL frequency, assuming 26MHz");
+                xtal_freq = RTC_XTAL_FREQ_26M;
+            }
+        }
+    } else if (!clk_val_is_valid(READ_PERI_REG(RTC_XTAL_FREQ_REG))) {
+        /* Exact frequency was set in sdkconfig, but still warn if autodetected
+         * frequency is different. If autodetection failed, worst case we get a
+         * bit of garbage output.
+         */
+        rtc_xtal_freq_t est_xtal_freq = rtc_clk_xtal_freq_estimate();
+        if (est_xtal_freq != xtal_freq) {
+            SOC_LOGW(TAG, "Possibly invalid CONFIG_ESP32_XTAL_FREQ setting (%dMHz). Detected %d MHz.",
+                    xtal_freq, est_xtal_freq);
+        }
+    }
+    uart_tx_wait_idle(0);
+    rtc_clk_xtal_freq_update(xtal_freq);
+    rtc_clk_apb_freq_update(xtal_freq * MHZ);
+    /* Set CPU frequency */
+    rtc_clk_cpu_freq_set(cfg.cpu_freq);
+
+    /* Re-calculate the ccount to make time calculation correct. */
+    uint32_t freq_before = rtc_clk_cpu_freq_value(cpu_source_before) / MHZ;
+    uint32_t freq_after = rtc_clk_cpu_freq_value(cfg.cpu_freq) / MHZ;
+    XTHAL_SET_CCOUNT( XTHAL_GET_CCOUNT() * freq_after / freq_before );
+
+    /* Slow & fast clocks setup */
+    if (cfg.slow_freq == RTC_SLOW_FREQ_32K_XTAL) {
+        rtc_clk_32k_enable(true);
+    }
+    if (cfg.fast_freq == RTC_FAST_FREQ_8M) {
+        bool need_8md256 = cfg.slow_freq == RTC_SLOW_FREQ_8MD256;
+        rtc_clk_8m_enable(true, need_8md256);
+    }
+    rtc_clk_fast_freq_set(cfg.fast_freq);
+    rtc_clk_slow_freq_set(cfg.slow_freq);
+}
+
+/* Name used in libphy.a:phy_chip_v7.o
+ * TODO: update the library to use rtc_clk_xtal_freq_get
+ */
+rtc_xtal_freq_t rtc_get_xtal(void) __attribute__((alias("rtc_clk_xtal_freq_get")));
diff --git a/cpu/esp32/vendor/esp-idf/soc/rtc_init.c b/cpu/esp32/vendor/esp-idf/soc/rtc_init.c
new file mode 100644
index 0000000000000000000000000000000000000000..399d1b7303dc83abc48f08f728ef99f9e1750030
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/rtc_init.c
@@ -0,0 +1,154 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+
+#include "soc/soc.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/efuse_reg.h"
+#include "soc/gpio_reg.h"
+
+/*
+ * We had to rename this function from rtc_init to rtc_init_module because of
+ * conflicts with RIOT's rtc_init function
+ */
+void rtc_init_module(rtc_config_t cfg)
+{
+    CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PVTMON_PU);
+
+    REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, cfg.pll_wait);
+    REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, cfg.xtal_wait);
+    REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, cfg.ck8m_wait);
+
+    REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, RTC_CNTL_DBG_ATTEN_DEFAULT);
+    SET_PERI_REG_MASK(RTC_CNTL_BIAS_CONF_REG,
+            RTC_CNTL_DEC_HEARTBEAT_WIDTH | RTC_CNTL_INC_HEARTBEAT_PERIOD);
+
+    /* Reset RTC bias to default value (needed if waking up from deep sleep) */
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, RTC_CNTL_DBIAS_1V10);
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, RTC_CNTL_DBIAS_1V10);
+
+    if (cfg.clkctl_init) {
+        //clear CMMU clock force on
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_PRO_CACHE_CTRL1_REG, DPORT_PRO_CMMU_FORCE_ON);
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_APP_CACHE_CTRL1_REG, DPORT_APP_CMMU_FORCE_ON);
+        //clear rom clock force on
+        DPORT_SET_PERI_REG_BITS(DPORT_ROM_FO_CTRL_REG, DPORT_SHARE_ROM_FO, 0, DPORT_SHARE_ROM_FO_S);
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_ROM_FO_CTRL_REG, DPORT_APP_ROM_FO);
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_ROM_FO_CTRL_REG, DPORT_PRO_ROM_FO);
+        //clear sram clock force on
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_SRAM_FO_CTRL_0_REG, DPORT_SRAM_FO_0);
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_SRAM_FO_CTRL_1_REG, DPORT_SRAM_FO_1);
+        //clear tag clock force on
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_TAG_FO_CTRL_REG, DPORT_APP_CACHE_TAG_FORCE_ON);
+        DPORT_CLEAR_PERI_REG_MASK(DPORT_TAG_FO_CTRL_REG, DPORT_PRO_CACHE_TAG_FORCE_ON);
+    }
+
+    if (cfg.pwrctl_init) {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_CK8M_FORCE_PU);
+        //cancel xtal force pu
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU);
+        //cancel BIAS force pu
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_CORE_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_FORCE_NOSLEEP);
+        // bias follow 8M
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_CORE_FOLW_8M);
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_I2C_FOLW_8M);
+        SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_SLEEP_FOLW_8M);
+        // CLEAR APLL close
+        CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PU);
+        SET_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, RTC_CNTL_PLLA_FORCE_PD);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BBPLL_I2C_FORCE_PU);
+        //cancel RTC REG force PU
+        CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PU);
+        if (cfg.rtc_dboost_fpd) {
+            SET_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD);
+        } else {
+            CLEAR_PERI_REG_MASK(RTC_CNTL_REG, RTC_CNTL_DBOOST_FORCE_PD);
+        }
+        //cancel digital pu force
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PWC_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_WRAP_FORCE_NOISO);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_WIFI_FORCE_NOISO);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_CPU_ROM_RAM_FORCE_NOISO);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_NOISO);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FORCE_NOISO);
+        //cancel digital PADS force no iso
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_UNHOLD);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO);
+    }
+}
+
+rtc_vddsdio_config_t rtc_vddsdio_get_config(void)
+{
+    rtc_vddsdio_config_t result;
+    uint32_t sdio_conf_reg = REG_READ(RTC_CNTL_SDIO_CONF_REG);
+    result.drefh = (sdio_conf_reg & RTC_CNTL_DREFH_SDIO_M) >> RTC_CNTL_DREFH_SDIO_S;
+    result.drefm = (sdio_conf_reg & RTC_CNTL_DREFM_SDIO_M) >> RTC_CNTL_DREFM_SDIO_S;
+    result.drefl = (sdio_conf_reg & RTC_CNTL_DREFL_SDIO_M) >> RTC_CNTL_DREFL_SDIO_S;
+    if (sdio_conf_reg & RTC_CNTL_SDIO_FORCE) {
+        // Get configuration from RTC
+        result.force = 1;
+        result.enable = (sdio_conf_reg & RTC_CNTL_XPD_SDIO_REG_M) >> RTC_CNTL_XPD_SDIO_REG_S;
+        result.tieh = (sdio_conf_reg & RTC_CNTL_SDIO_TIEH_M) >> RTC_CNTL_SDIO_TIEH_S;
+        return result;
+    }
+    uint32_t efuse_reg = REG_READ(EFUSE_BLK0_RDATA4_REG);
+    if (efuse_reg & EFUSE_RD_SDIO_FORCE) {
+        // Get configuration from EFUSE
+        result.force = 0;
+        result.enable = (efuse_reg & EFUSE_RD_XPD_SDIO_REG_M) >> EFUSE_RD_XPD_SDIO_REG_S;
+        result.tieh = (efuse_reg & EFUSE_RD_SDIO_TIEH_M) >> EFUSE_RD_SDIO_TIEH_S;
+        //DREFH/M/L eFuse are used for EFUSE_ADC_VREF instead. Therefore tuning
+        //will only be available on older chips that don't have EFUSE_ADC_VREF
+        if(REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG ,EFUSE_RD_BLK3_PART_RESERVE) == 0){
+            //BLK3_PART_RESERVE indicates the presence of EFUSE_ADC_VREF
+            // in this case, DREFH/M/L are also set from EFUSE
+            result.drefh = (efuse_reg & EFUSE_RD_SDIO_DREFH_M) >> EFUSE_RD_SDIO_DREFH_S;
+            result.drefm = (efuse_reg & EFUSE_RD_SDIO_DREFM_M) >> EFUSE_RD_SDIO_DREFM_S;
+            result.drefl = (efuse_reg & EFUSE_RD_SDIO_DREFL_M) >> EFUSE_RD_SDIO_DREFL_S;
+        }
+        return result;
+    }
+
+    // Otherwise, VDD_SDIO is controlled by bootstrapping pin
+    uint32_t strap_reg = REG_READ(GPIO_STRAP_REG);
+    result.force = 0;
+    result.tieh = (strap_reg & BIT(5)) ? RTC_VDDSDIO_TIEH_1_8V : RTC_VDDSDIO_TIEH_3_3V;
+    result.enable = 1;
+    return result;
+}
+
+void rtc_vddsdio_set_config(rtc_vddsdio_config_t config)
+{
+    uint32_t val = 0;
+    val |= (config.force << RTC_CNTL_SDIO_FORCE_S);
+    val |= (config.enable << RTC_CNTL_XPD_SDIO_REG_S);
+    val |= (config.drefh << RTC_CNTL_DREFH_SDIO_S);
+    val |= (config.drefm << RTC_CNTL_DREFM_SDIO_S);
+    val |= (config.drefl << RTC_CNTL_DREFL_SDIO_S);
+    val |= (config.tieh << RTC_CNTL_SDIO_TIEH_S);
+    val |= RTC_CNTL_SDIO_PD_EN;
+    REG_WRITE(RTC_CNTL_SDIO_CONF_REG, val);
+}
diff --git a/cpu/esp32/vendor/esp-idf/soc/rtc_sleep.c b/cpu/esp32/vendor/esp-idf/soc/rtc_sleep.c
new file mode 100644
index 0000000000000000000000000000000000000000..041c2d1b6b9e82377cb3b45ee43c86ecc9bfa2fb
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/rtc_sleep.c
@@ -0,0 +1,236 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+#include "soc/soc.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/dport_reg.h"
+#include "soc/rtc.h"
+#include "soc/i2s_reg.h"
+#include "soc/timer_group_reg.h"
+#include "soc/bb_reg.h"
+#include "soc/nrx_reg.h"
+#include "soc/fe_reg.h"
+#include "soc/rtc.h"
+#include "rom/ets_sys.h"
+
+#define MHZ (1000000)
+
+/* Various delays to be programmed into power control state machines */
+#define RTC_CNTL_XTL_BUF_WAIT_SLP   2
+#define RTC_CNTL_PLL_BUF_WAIT_SLP   2
+#define RTC_CNTL_CK8M_WAIT_SLP      4
+#define OTHER_BLOCKS_POWERUP        1
+#define OTHER_BLOCKS_WAIT           1
+
+#define ROM_RAM_POWERUP_CYCLES   OTHER_BLOCKS_POWERUP
+#define ROM_RAM_WAIT_CYCLES      OTHER_BLOCKS_WAIT
+
+#define WIFI_POWERUP_CYCLES      OTHER_BLOCKS_POWERUP
+#define WIFI_WAIT_CYCLES         OTHER_BLOCKS_WAIT
+
+#define RTC_POWERUP_CYCLES       OTHER_BLOCKS_POWERUP
+#define RTC_WAIT_CYCLES          OTHER_BLOCKS_WAIT
+
+#define DG_WRAP_POWERUP_CYCLES   OTHER_BLOCKS_POWERUP
+#define DG_WRAP_WAIT_CYCLES      OTHER_BLOCKS_WAIT
+
+#define RTC_MEM_POWERUP_CYCLES   OTHER_BLOCKS_POWERUP
+#define RTC_MEM_WAIT_CYCLES      OTHER_BLOCKS_WAIT
+
+/**
+ * @brief Power down flags for rtc_sleep_pd function
+ */
+typedef struct {
+    uint32_t dig_pd : 1;    //!< Set to 1 to power down digital part in sleep
+    uint32_t rtc_pd : 1;    //!< Set to 1 to power down RTC memories in sleep
+    uint32_t cpu_pd : 1;    //!< Set to 1 to power down digital memories and CPU in sleep
+    uint32_t i2s_pd : 1;    //!< Set to 1 to power down I2S in sleep
+    uint32_t bb_pd : 1;     //!< Set to 1 to power down WiFi in sleep
+    uint32_t nrx_pd : 1;    //!< Set to 1 to power down WiFi in sleep
+    uint32_t fe_pd : 1;     //!< Set to 1 to power down WiFi in sleep
+} rtc_sleep_pd_config_t;
+
+/**
+ * Initializer for rtc_sleep_pd_config_t which sets all flags to the same value
+ */
+#define RTC_SLEEP_PD_CONFIG_ALL(val) {\
+    .dig_pd = (val), \
+    .rtc_pd = (val), \
+    .cpu_pd = (val), \
+    .i2s_pd = (val), \
+    .bb_pd = (val), \
+    .nrx_pd = (val), \
+    .fe_pd = (val), \
+}
+
+/**
+ * Configure whether certain peripherals are powered down in deep sleep
+ * @param cfg power down flags as rtc_sleep_pd_config_t structure
+ */
+static void rtc_sleep_pd(rtc_sleep_pd_config_t cfg)
+{
+    REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, ~cfg.dig_pd);
+    REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_LPU, ~cfg.rtc_pd);
+    REG_SET_FIELD(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_LPU, ~cfg.rtc_pd);
+    DPORT_REG_SET_FIELD(DPORT_MEM_PD_MASK_REG, DPORT_LSLP_MEM_PD_MASK, ~cfg.cpu_pd);
+    REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_PLC_MEM_FORCE_PU, ~cfg.i2s_pd);
+    REG_SET_FIELD(I2S_PD_CONF_REG(0), I2S_FIFO_FORCE_PU, ~cfg.i2s_pd);
+    REG_SET_FIELD(BBPD_CTRL, BB_FFT_FORCE_PU, ~cfg.bb_pd);
+    REG_SET_FIELD(BBPD_CTRL, BB_DC_EST_FORCE_PU, ~cfg.bb_pd);
+    REG_SET_FIELD(NRXPD_CTRL, NRX_RX_ROT_FORCE_PU, ~cfg.nrx_pd);
+    REG_SET_FIELD(NRXPD_CTRL, NRX_VIT_FORCE_PU, ~cfg.nrx_pd);
+    REG_SET_FIELD(NRXPD_CTRL, NRX_DEMAP_FORCE_PU, ~cfg.nrx_pd);
+    REG_SET_FIELD(FE_GEN_CTRL, FE_IQ_EST_FORCE_PU, ~cfg.fe_pd);
+    REG_SET_FIELD(FE2_TX_INTERP_CTRL, FE2_TX_INF_FORCE_PU, ~cfg.fe_pd);
+}
+
+void rtc_sleep_init(rtc_sleep_config_t cfg)
+{
+    // set 5 PWC state machine times to fit in main state machine time
+    REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_PLL_BUF_WAIT, RTC_CNTL_PLL_BUF_WAIT_SLP);
+    REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_XTL_BUF_WAIT, RTC_CNTL_XTL_BUF_WAIT_SLP);
+    REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP);
+
+    // set shortest possible sleep time limit
+    REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_MIN_SLP_VAL, RTC_CNTL_MIN_SLP_VAL_MIN);
+
+    // set rom&ram timer
+    REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_POWERUP_TIMER, ROM_RAM_POWERUP_CYCLES);
+    REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_ROM_RAM_WAIT_TIMER, ROM_RAM_WAIT_CYCLES);
+    // set wifi timer
+    REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_POWERUP_TIMER, WIFI_POWERUP_CYCLES);
+    REG_SET_FIELD(RTC_CNTL_TIMER3_REG, RTC_CNTL_WIFI_WAIT_TIMER, WIFI_WAIT_CYCLES);
+    // set rtc peri timer
+    REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_POWERUP_TIMER, RTC_POWERUP_CYCLES);
+    REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_WAIT_TIMER, RTC_WAIT_CYCLES);
+    // set digital wrap timer
+    REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_POWERUP_TIMER, DG_WRAP_POWERUP_CYCLES);
+    REG_SET_FIELD(RTC_CNTL_TIMER4_REG, RTC_CNTL_DG_WRAP_WAIT_TIMER, DG_WRAP_WAIT_CYCLES);
+    // set rtc memory timer
+    REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_POWERUP_TIMER, RTC_MEM_POWERUP_CYCLES);
+    REG_SET_FIELD(RTC_CNTL_TIMER5_REG, RTC_CNTL_RTCMEM_WAIT_TIMER, RTC_MEM_WAIT_CYCLES);
+
+    REG_SET_FIELD(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_LSLP_MEM_FORCE_PU, cfg.lslp_mem_inf_fpu);
+
+    rtc_sleep_pd_config_t pd_cfg = RTC_SLEEP_PD_CONFIG_ALL(cfg.lslp_meminf_pd);
+    rtc_sleep_pd(pd_cfg);
+
+    if (cfg.rtc_mem_inf_fpu) {
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FORCE_PU);
+    }
+
+    if (cfg.rtc_mem_inf_follow_cpu) {
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_MEM_FOLW_CPU);
+    }
+
+    if (cfg.rtc_fastmem_pd_en) {
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_PD_EN);
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_PU);
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_FASTMEM_FORCE_NOISO);
+    }
+
+    if (cfg.rtc_slowmem_pd_en) {
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_NOISO);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_PD_EN);
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_PU);
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_SLOWMEM_FORCE_NOISO);
+    }
+
+    if (cfg.rtc_peri_pd_en) {
+        SET_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_PWC_REG, RTC_CNTL_PD_EN);
+    }
+
+    if (cfg.wifi_pd_en) {
+        SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_WIFI_PD_EN);
+    }
+
+    if (cfg.rom_mem_pd_en) {
+        SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_PD_EN);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_CPU_ROM_RAM_PD_EN);
+    }
+
+    if (cfg.deep_slp) {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG,
+                RTC_CNTL_DG_PAD_FORCE_ISO | RTC_CNTL_DG_PAD_FORCE_NOISO);
+        SET_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG,
+                RTC_CNTL_DG_WRAP_FORCE_PU | RTC_CNTL_DG_WRAP_FORCE_PD);
+        CLEAR_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_FORCE_NOSLEEP);
+
+        // Shut down parts of RTC which may have been left enabled by the wireless drivers
+        CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG,
+                RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU |
+                RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU);
+    } else {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_PWC_REG, RTC_CNTL_DG_WRAP_PD_EN);
+        REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, 0);
+    }
+
+    REG_SET_FIELD(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_XTL_FORCE_PU, cfg.xtal_fpu);
+
+    /* enable VDDSDIO control by state machine */
+    REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE);
+    REG_SET_FIELD(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_PD_EN, cfg.vddsdio_pd_en);
+
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_SLP, cfg.rtc_dbias_slp);
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DBIAS_WAK, cfg.rtc_dbias_wak);
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_WAK, cfg.dig_dbias_wak);
+    REG_SET_FIELD(RTC_CNTL_REG, RTC_CNTL_DIG_DBIAS_SLP, cfg.dig_dbias_slp);
+}
+
+void rtc_sleep_set_wakeup_time(uint64_t t)
+{
+    WRITE_PERI_REG(RTC_CNTL_SLP_TIMER0_REG, t & UINT32_MAX);
+    WRITE_PERI_REG(RTC_CNTL_SLP_TIMER1_REG, t >> 32);
+}
+
+uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt)
+{
+    REG_SET_FIELD(RTC_CNTL_WAKEUP_STATE_REG, RTC_CNTL_WAKEUP_ENA, wakeup_opt);
+    WRITE_PERI_REG(RTC_CNTL_SLP_REJECT_CONF_REG, reject_opt);
+
+    /* Start entry into sleep mode */
+    SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SLEEP_EN);
+
+    while (GET_PERI_REG_MASK(RTC_CNTL_INT_RAW_REG,
+            RTC_CNTL_SLP_REJECT_INT_RAW | RTC_CNTL_SLP_WAKEUP_INT_RAW) == 0) {
+        ;
+    }
+    /* In deep sleep mode, we never get here */
+    uint32_t reject = REG_GET_FIELD(RTC_CNTL_INT_RAW_REG, RTC_CNTL_SLP_REJECT_INT_RAW);
+    SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG,
+            RTC_CNTL_SLP_REJECT_INT_CLR | RTC_CNTL_SLP_WAKEUP_INT_CLR);
+
+    /* restore DBG_ATTEN to the default value */
+    REG_SET_FIELD(RTC_CNTL_BIAS_CONF_REG, RTC_CNTL_DBG_ATTEN, RTC_CNTL_DBG_ATTEN_DEFAULT);
+    return reject;
+}
diff --git a/cpu/esp32/vendor/esp-idf/soc/rtc_time.c b/cpu/esp32/vendor/esp-idf/soc/rtc_time.c
new file mode 100644
index 0000000000000000000000000000000000000000..1e13ac45b3ee5b5d8a7d08568b1e480113fa1f9f
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/rtc_time.c
@@ -0,0 +1,155 @@
+// Copyright 2015-2017 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#include <stdint.h>
+#include "rom/ets_sys.h"
+#include "soc/rtc.h"
+#include "soc/rtc_cntl_reg.h"
+#include "soc/timer_group_reg.h"
+
+#define MHZ (1000000)
+
+/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
+ * This feature counts the number of XTAL clock cycles within a given number of
+ * RTC_SLOW_CLK cycles.
+ *
+ * Slow clock calibration feature has two modes of operation: one-off and cycling.
+ * In cycling mode (which is enabled by default on SoC reset), counting of XTAL
+ * cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
+ * using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
+ * once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
+ * enabled using TIMG_RTC_CALI_START bit.
+ */
+
+/**
+ * @brief Clock calibration function used by rtc_clk_cal and rtc_clk_cal_ratio
+ * @param cal_clk which clock to calibrate
+ * @param slowclk_cycles number of slow clock cycles to count
+ * @return number of XTAL clock cycles within the given number of slow clock cycles
+ */
+static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
+{
+    /* Enable requested clock (150k clock is always on) */
+    int dig_32k_xtal_state = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN);
+    if (cal_clk == RTC_CAL_32K_XTAL && !dig_32k_xtal_state) {
+        REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, 1);
+    }
+
+    if (cal_clk == RTC_CAL_8MD256) {
+        SET_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
+    }
+    /* Prepare calibration */
+    REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cal_clk);
+    CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
+    REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
+    /* Figure out how long to wait for calibration to finish */
+    uint32_t expected_freq;
+    rtc_slow_freq_t slow_freq = REG_GET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_ANA_CLK_RTC_SEL);
+    if (cal_clk == RTC_CAL_32K_XTAL ||
+        (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_32K_XTAL)) {
+        expected_freq = 32768; /* standard 32k XTAL */
+    } else if (cal_clk == RTC_CAL_8MD256 ||
+            (cal_clk == RTC_CAL_RTC_MUX && slow_freq == RTC_SLOW_FREQ_8MD256)) {
+        expected_freq = RTC_FAST_CLK_FREQ_APPROX / 256;
+    } else {
+        expected_freq = 150000; /* 150k internal oscillator */
+    }
+    uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
+    /* Start calibration */
+    CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
+    SET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
+    /* Wait the expected time calibration should take.
+     * TODO: if running under RTOS, and us_time_estimate > RTOS tick, use the
+     * RTOS delay function.
+     */
+    ets_delay_us(us_time_estimate);
+    /* Wait for calibration to finish up to another us_time_estimate */
+    int timeout_us = us_time_estimate;
+    while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY) &&
+            timeout_us > 0) {
+        timeout_us--;
+        ets_delay_us(1);
+    }
+
+    REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_XTAL32K_EN, dig_32k_xtal_state);
+
+    if (cal_clk == RTC_CAL_8MD256) {
+        CLEAR_PERI_REG_MASK(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_DIG_CLK8M_D256_EN);
+    }
+    if (timeout_us == 0) {
+        /* timed out waiting for calibration */
+        return 0;
+    }
+
+    return REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
+}
+
+uint32_t rtc_clk_cal_ratio(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
+{
+    uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
+    uint64_t ratio_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT)) / slowclk_cycles;
+    uint32_t ratio = (uint32_t)(ratio_64 & UINT32_MAX);
+    return ratio;
+}
+
+uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
+{
+    rtc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
+    uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
+    uint64_t divider = ((uint64_t)xtal_freq) * slowclk_cycles;
+    uint64_t period_64 = ((xtal_cycles << RTC_CLK_CAL_FRACT) + divider / 2 - 1) / divider;
+    uint32_t period = (uint32_t)(period_64 & UINT32_MAX);
+    return period;
+}
+
+uint64_t rtc_time_us_to_slowclk(uint64_t time_in_us, uint32_t period)
+{
+    /* Overflow will happen in this function if time_in_us >= 2^45, which is about 400 days.
+     * TODO: fix overflow.
+     */
+    return (time_in_us << RTC_CLK_CAL_FRACT) / period;
+}
+
+uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
+{
+    return (rtc_cycles * period) >> RTC_CLK_CAL_FRACT;
+}
+
+uint64_t rtc_time_get(void)
+{
+    SET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_UPDATE);
+    while (GET_PERI_REG_MASK(RTC_CNTL_TIME_UPDATE_REG, RTC_CNTL_TIME_VALID) == 0) {
+        ets_delay_us(1); // might take 1 RTC slowclk period, don't flood RTC bus
+    }
+    SET_PERI_REG_MASK(RTC_CNTL_INT_CLR_REG, RTC_CNTL_TIME_VALID_INT_CLR);
+    uint64_t t = READ_PERI_REG(RTC_CNTL_TIME0_REG);
+    t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32;
+    return t;
+}
+
+void rtc_clk_wait_for_slow_cycle(void)
+{
+    REG_CLR_BIT(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING | TIMG_RTC_CALI_START);
+    REG_CLR_BIT(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY);
+    REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, RTC_CAL_RTC_MUX);
+    /* Request to run calibration for 0 slow clock cycles.
+     * RDY bit will be set on the nearest slow clock cycle.
+     */
+    REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, 0);
+    REG_SET_BIT(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START);
+    ets_delay_us(1); /* RDY needs some time to go low */
+    while (!GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) {
+        ets_delay_us(1);
+    }
+}
diff --git a/cpu/esp32/vendor/esp-idf/soc/soc_cpu.h b/cpu/esp32/vendor/esp-idf/soc/soc_cpu.h
new file mode 100644
index 0000000000000000000000000000000000000000..59ba85dde8870e3d9359f4d7ef15d332133cebf7
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/soc_cpu.h
@@ -0,0 +1,112 @@
+// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+#ifndef SOC_CPU_H
+#define SOC_CPU_H
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include "xtensa/corebits.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* C macros for xtensa special register read/write/exchange */
+
+#define RSR(reg, curval)  asm volatile ("rsr %0, " #reg : "=r" (curval));
+#define WSR(reg, newval)  asm volatile ("wsr %0, " #reg : : "r" (newval));
+#define XSR(reg, swapval) asm volatile ("xsr %0, " #reg : "+r" (swapval));
+
+/** @brief Read current stack pointer address
+ *
+ */
+static inline void *get_sp(void)
+{
+    void *sp;
+    asm volatile ("mov %0, sp;" : "=r" (sp));
+    return sp;
+}
+
+/* Functions to set page attributes for Region Protection option in the CPU.
+ * See Xtensa ISA Reference manual for explanation of arguments (section 4.6.3.2).
+ */
+
+static inline void cpu_write_dtlb(uint32_t vpn, unsigned attr)
+{
+    asm volatile ("wdtlb  %1, %0; dsync\n" :: "r" (vpn), "r" (attr));
+}
+
+
+static inline void cpu_write_itlb(unsigned vpn, unsigned attr)
+{
+    asm volatile ("witlb  %1, %0; isync\n" :: "r" (vpn), "r" (attr));
+}
+
+/**
+ * @brief Configure memory region protection
+ *
+ * Make page 0 access raise an exception.
+ * Also protect some other unused pages so we can catch weirdness.
+ * Useful attribute values:
+ * 0 — cached, RW
+ * 2 — bypass cache, RWX (default value after CPU reset)
+ * 15 — no access, raise exception
+ */
+
+static inline void cpu_configure_region_protection(void)
+{
+    const uint32_t pages_to_protect[] = {0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000};
+    for (unsigned i = 0; i < sizeof(pages_to_protect)/sizeof(pages_to_protect[0]); ++i) {
+        cpu_write_dtlb(pages_to_protect[i], 0xf);
+        cpu_write_itlb(pages_to_protect[i], 0xf);
+    }
+    cpu_write_dtlb(0x20000000, 0);
+    cpu_write_itlb(0x20000000, 0);
+}
+
+/**
+ * @brief Stall CPU using RTC controller
+ * @param cpu_id ID of the CPU to stall (0 = PRO, 1 = APP)
+ */
+void esp_cpu_stall(int cpu_id);
+
+/**
+ * @brief Un-stall CPU using RTC controller
+ * @param cpu_id ID of the CPU to un-stall (0 = PRO, 1 = APP)
+ */
+void esp_cpu_unstall(int cpu_id);
+
+/**
+ * @brief Reset CPU using RTC controller
+ * @param cpu_id ID of the CPU to reset (0 = PRO, 1 = APP)
+ */
+void esp_cpu_reset(int cpu_id);
+
+
+/**
+ * @brief Returns true if a JTAG debugger is attached to CPU
+ * OCD (on chip debug) port.
+ *
+ * @note If "Make exception and panic handlers JTAG/OCD aware"
+ * is disabled, this function always returns false.
+ */
+bool esp_cpu_in_ocd_debug_mode(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SOC_CPU_H */
diff --git a/cpu/esp32/vendor/esp-idf/soc/soc_memory_layout.c b/cpu/esp32/vendor/esp-idf/soc/soc_memory_layout.c
new file mode 100644
index 0000000000000000000000000000000000000000..6a288c9b6de741d20b7aa6242fa305255c97a0af
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/soc/soc_memory_layout.c
@@ -0,0 +1,172 @@
+// Copyright 2010-2016 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+#ifndef BOOTLOADER_BUILD
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "soc/soc.h"
+#include "soc/soc_memory_layout.h"
+#include "esp_heap_caps.h"
+#include "sdk_conf.h"
+
+/* Memory layout for ESP32 SoC */
+
+/*
+Memory type descriptors. These describe the capabilities of a type of memory in the SoC. Each type of memory
+map consist of one or more regions in the address space.
+
+Each type contains an array of prioritised capabilities; types with later entries are only taken if earlier
+ones can't fulfill the memory request.
+
+The prioritised capabilities work roughly like this:
+- For a normal malloc (MALLOC_CAP_DEFAULT), give away the DRAM-only memory first, then pass off any dual-use IRAM regions,
+  finally eat into the application memory.
+- For a malloc where 32-bit-aligned-only access is okay, first allocate IRAM, then DRAM, finally application IRAM.
+- Application mallocs (PIDx) will allocate IRAM first, if possible, then DRAM.
+- Most other malloc caps only fit in one region anyway.
+
+*/
+const soc_memory_type_desc_t soc_memory_types[] = {
+    //Type 0: Plain ole D-port RAM
+    { "DRAM", { MALLOC_CAP_8BIT|MALLOC_CAP_DEFAULT, MALLOC_CAP_INTERNAL|MALLOC_CAP_DMA|MALLOC_CAP_32BIT, 0 }, false, false},
+    //Type 1: Plain ole D-port RAM which has an alias on the I-port
+    //(This DRAM is also the region used by ROM during startup)
+    { "D/IRAM", { 0, MALLOC_CAP_DMA|MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL|MALLOC_CAP_DEFAULT, MALLOC_CAP_32BIT|MALLOC_CAP_EXEC }, true, true},
+    //Type 2: IRAM
+    { "IRAM", { MALLOC_CAP_EXEC|MALLOC_CAP_32BIT|MALLOC_CAP_INTERNAL, 0, 0 }, false, false},
+    //Type 3-8: PID 2-7 IRAM
+    { "PID2IRAM", { MALLOC_CAP_PID2|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
+    { "PID3IRAM", { MALLOC_CAP_PID3|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
+    { "PID4IRAM", { MALLOC_CAP_PID4|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
+    { "PID5IRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
+    { "PID6IRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
+    { "PID7IRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, 0, MALLOC_CAP_EXEC|MALLOC_CAP_32BIT }, false, false},
+    //Type 9-14: PID 2-7 DRAM
+    { "PID2DRAM", { MALLOC_CAP_PID2|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
+    { "PID3DRAM", { MALLOC_CAP_PID3|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
+    { "PID4DRAM", { MALLOC_CAP_PID4|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
+    { "PID5DRAM", { MALLOC_CAP_PID5|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
+    { "PID6DRAM", { MALLOC_CAP_PID6|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
+    { "PID7DRAM", { MALLOC_CAP_PID7|MALLOC_CAP_INTERNAL, MALLOC_CAP_8BIT, MALLOC_CAP_32BIT|MALLOC_CAP_DEFAULT }, false, false},
+    //Type 15: SPI SRAM data
+    { "SPIRAM", { MALLOC_CAP_SPIRAM|MALLOC_CAP_DEFAULT, 0, MALLOC_CAP_8BIT|MALLOC_CAP_32BIT}, false, false},
+};
+
+const size_t soc_memory_type_count = sizeof(soc_memory_types)/sizeof(soc_memory_type_desc_t);
+
+/*
+Region descriptors. These describe all regions of memory available, and map them to a type in the above type.
+
+Because of requirements in the coalescing code which merges adjacent regions, this list should always be sorted
+from low to high start address.
+*/
+const soc_memory_region_t soc_memory_regions[] = {
+    { 0x3F800000, 0x400000, 15, 0}, //SPI SRAM, if available
+    { 0x3FFAE000, 0x2000, 0, 0}, //pool 16 <- used for rom code
+    { 0x3FFB0000, 0x8000, 0, 0}, //pool 15 <- if BT is enabled, used as BT HW shared memory
+    { 0x3FFB8000, 0x8000, 0, 0}, //pool 14 <- if BT is enabled, used data memory for BT ROM functions.
+    { 0x3FFC0000, 0x2000, 0, 0}, //pool 10-13, mmu page 0
+    { 0x3FFC2000, 0x2000, 0, 0}, //pool 10-13, mmu page 1
+    { 0x3FFC4000, 0x2000, 0, 0}, //pool 10-13, mmu page 2
+    { 0x3FFC6000, 0x2000, 0, 0}, //pool 10-13, mmu page 3
+    { 0x3FFC8000, 0x2000, 0, 0}, //pool 10-13, mmu page 4
+    { 0x3FFCA000, 0x2000, 0, 0}, //pool 10-13, mmu page 5
+    { 0x3FFCC000, 0x2000, 0, 0}, //pool 10-13, mmu page 6
+    { 0x3FFCE000, 0x2000, 0, 0}, //pool 10-13, mmu page 7
+    { 0x3FFD0000, 0x2000, 0, 0}, //pool 10-13, mmu page 8
+    { 0x3FFD2000, 0x2000, 0, 0}, //pool 10-13, mmu page 9
+    { 0x3FFD4000, 0x2000, 0, 0}, //pool 10-13, mmu page 10
+    { 0x3FFD6000, 0x2000, 0, 0}, //pool 10-13, mmu page 11
+    { 0x3FFD8000, 0x2000, 0, 0}, //pool 10-13, mmu page 12
+    { 0x3FFDA000, 0x2000, 0, 0}, //pool 10-13, mmu page 13
+    { 0x3FFDC000, 0x2000, 0, 0}, //pool 10-13, mmu page 14
+    { 0x3FFDE000, 0x2000, 0, 0}, //pool 10-13, mmu page 15
+    { 0x3FFE0000, 0x4000, 1, 0x400BC000}, //pool 9 blk 1
+    { 0x3FFE4000, 0x4000, 1, 0x400B8000}, //pool 9 blk 0
+    { 0x3FFE8000, 0x8000, 1, 0x400B0000}, //pool 8 <- can be remapped to ROM, used for MAC dump
+    { 0x3FFF0000, 0x8000, 1, 0x400A8000}, //pool 7 <- can be used for MAC dump
+    { 0x3FFF8000, 0x4000, 1, 0x400A4000}, //pool 6 blk 1 <- can be used as trace memory
+    { 0x3FFFC000, 0x4000, 1, 0x400A0000}, //pool 6 blk 0 <- can be used as trace memory
+    { 0x40070000, 0x8000, 2, 0}, //pool 0
+    { 0x40078000, 0x8000, 2, 0}, //pool 1
+    { 0x40080000, 0x2000, 2, 0}, //pool 2-5, mmu page 0
+    { 0x40082000, 0x2000, 2, 0}, //pool 2-5, mmu page 1
+    { 0x40084000, 0x2000, 2, 0}, //pool 2-5, mmu page 2
+    { 0x40086000, 0x2000, 2, 0}, //pool 2-5, mmu page 3
+    { 0x40088000, 0x2000, 2, 0}, //pool 2-5, mmu page 4
+    { 0x4008A000, 0x2000, 2, 0}, //pool 2-5, mmu page 5
+    { 0x4008C000, 0x2000, 2, 0}, //pool 2-5, mmu page 6
+    { 0x4008E000, 0x2000, 2, 0}, //pool 2-5, mmu page 7
+    { 0x40090000, 0x2000, 2, 0}, //pool 2-5, mmu page 8
+    { 0x40092000, 0x2000, 2, 0}, //pool 2-5, mmu page 9
+    { 0x40094000, 0x2000, 2, 0}, //pool 2-5, mmu page 10
+    { 0x40096000, 0x2000, 2, 0}, //pool 2-5, mmu page 11
+    { 0x40098000, 0x2000, 2, 0}, //pool 2-5, mmu page 12
+    { 0x4009A000, 0x2000, 2, 0}, //pool 2-5, mmu page 13
+    { 0x4009C000, 0x2000, 2, 0}, //pool 2-5, mmu page 14
+    { 0x4009E000, 0x2000, 2, 0}, //pool 2-5, mmu page 15
+};
+
+const size_t soc_memory_region_count = sizeof(soc_memory_regions)/sizeof(soc_memory_region_t);
+
+
+/* Reserved memory regions
+
+   These are removed from the soc_memory_regions array when heaps are created.
+ */
+const soc_reserved_region_t soc_reserved_regions[] = {
+    { 0x40070000, 0x40078000 }, //CPU0 cache region
+    { 0x40078000, 0x40080000 }, //CPU1 cache region
+
+    /* Warning: The ROM stack is located in the 0x3ffe0000 area. We do not specifically disable that area here because
+       after the scheduler has started, the ROM stack is not used anymore by anything. We handle it instead by not allowing
+       any mallocs memory regions with the startup_stack flag set (these are the IRAM/DRAM region) until the
+       scheduler has started.
+
+       The 0x3ffe0000 region also contains static RAM for various ROM functions. The following lines
+       reserve the regions for UART and ETSC, so these functions are usable. Libraries like xtos, which are
+       not usable in FreeRTOS anyway, are commented out in the linker script so they cannot be used; we
+       do not disable their memory regions here and they will be used as general purpose heap memory.
+
+       Enabling the heap allocator for this region but disabling allocation here until FreeRTOS is started up
+       is a somewhat risky action in theory, because on initializing the allocator, the multi_heap implementation
+       will go and write metadata at the start and end of all regions. For the ESP32, these linked
+       list entries happen to end up in a region that is not touched by the stack; they can be placed safely there.
+    */
+
+    { 0x3ffe0000, 0x3ffe0440 }, //Reserve ROM PRO data region
+    { 0x3ffe4000, 0x3ffe4350 }, //Reserve ROM APP data region
+
+#if CONFIG_BT_ENABLED
+    { 0x3ffb0000, 0x3ffc0000 }, //Reserve BT hardware shared memory & BT data region
+    { 0x3ffae000, 0x3ffaff10 }, //Reserve ROM data region, inc region needed for BT ROM routines
+#else
+    { 0x3ffae000, 0x3ffae6e0 }, //Reserve ROM data region
+#endif
+
+#if CONFIG_MEMMAP_TRACEMEM
+#if CONFIG_MEMMAP_TRACEMEM_TWOBANKS
+    { 0x3fff8000, 0x40000000 }, //Reserve trace mem region
+#else
+    { 0x3fff8000, 0x3fffc000 }, //Reserve trace mem region
+#endif
+#endif
+
+    { 0x3f800000, 0x3fC00000 }, //SPI RAM gets added later if needed, in spiram.c; reserve it for now
+};
+
+const size_t soc_reserved_region_count = sizeof(soc_reserved_regions)/sizeof(soc_reserved_region_t);
+
+#endif
diff --git a/cpu/esp32/vendor/esp-idf/spi_flash/Makefile b/cpu/esp32/vendor/esp-idf/spi_flash/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..d5ad01791e0bf1d5d31e514bc0971da606c1d094
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/spi_flash/Makefile
@@ -0,0 +1,5 @@
+MODULE=esp_idf_spi_flash
+
+include $(RIOTBASE)/Makefile.base
+
+INCLUDES += -I$(ESP32_SDK_DIR)/components/bootloader_support/include
diff --git a/cpu/esp32/vendor/esp-idf/spi_flash/spi_flash_rom_patch.c b/cpu/esp32/vendor/esp-idf/spi_flash/spi_flash_rom_patch.c
new file mode 100644
index 0000000000000000000000000000000000000000..c66d10dc1c64e1c2f00ee4f28332d7c82b89146f
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/spi_flash/spi_flash_rom_patch.c
@@ -0,0 +1,664 @@
+// 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 "rom/ets_sys.h"
+#ifndef RIOT_VERSION
+#include "rom/gpio.h"
+#endif
+#include "rom/spi_flash.h"
+#include "sdk_conf.h"
+
+#define SPI_IDX   1
+#define OTH_IDX   0
+
+extern esp_rom_spiflash_chip_t g_rom_spiflash_chip;
+
+esp_rom_spiflash_result_t esp_rom_spiflash_wait_idle(esp_rom_spiflash_chip_t *spi)
+{
+    uint32_t status;
+
+    //wait for spi control ready
+    while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
+    }
+    while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
+    }
+    //wait for flash status ready
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_status(spi, &status)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+    return  ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+
+/* Modified version of esp_rom_spiflash_unlock() that replaces version in ROM.
+
+   This works around a bug where esp_rom_spiflash_unlock sometimes reads the wrong
+   high status byte (RDSR2 result) and then copies it back to the
+   flash status, which can cause the CMP bit or Status Register
+   Protect bit to become set.
+
+   Like other ROM SPI functions, this function is not designed to be
+   called directly from an RTOS environment without taking precautions
+   about interrupts, CPU coordination, flash mapping. However some of
+   the functions in esp_spi_flash.c call it.
+ */
+esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void)
+{
+    uint32_t status;
+
+    esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
+
+    if (esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status) != ESP_ROM_SPIFLASH_RESULT_OK) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    /* Clear all bits except QIE, if it is set.
+     (This is different from ROM esp_rom_spiflash_unlock, which keeps all bits as-is.)
+    */
+    status &= ESP_ROM_SPIFLASH_QE;
+
+    esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
+    REG_WRITE(SPI_CMD_REG(SPI_IDX), SPI_FLASH_WREN);
+    while (REG_READ(SPI_CMD_REG(SPI_IDX)) != 0) {
+    }
+    esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
+
+    SET_PERI_REG_MASK(SPI_CTRL_REG(SPI_IDX), SPI_WRSR_2B);
+    if (esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status) != ESP_ROM_SPIFLASH_RESULT_OK) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+
+#if CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
+
+extern uint8_t g_rom_spiflash_dummy_len_plus[];
+
+
+static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi);
+
+//only support spi1
+static esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip_internal(esp_rom_spiflash_chip_t *spi)
+{
+    esp_rom_spiflash_wait_idle(spi);
+
+    // Chip erase.
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_CE);
+    while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
+
+    // check erase is finished.
+    esp_rom_spiflash_wait_idle(spi);
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+//only support spi1
+static esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector_internal(esp_rom_spiflash_chip_t *spi, uint32_t addr)
+{
+    //check if addr is 4k alignment
+    if (0 != (addr & 0xfff)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    esp_rom_spiflash_wait_idle(spi);
+
+    // sector erase  4Kbytes erase is sector erase.
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr & 0xffffff);
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_SE);
+    while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
+
+    esp_rom_spiflash_wait_idle(spi);
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+//only support spi1
+static esp_rom_spiflash_result_t esp_rom_spiflash_erase_block_internal(esp_rom_spiflash_chip_t *spi, uint32_t addr)
+{
+    esp_rom_spiflash_wait_idle(spi);
+
+    // sector erase  4Kbytes erase is sector erase.
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, addr & 0xffffff);
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_BE);
+    while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
+
+    esp_rom_spiflash_wait_idle(spi);
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+//only support spi1
+static esp_rom_spiflash_result_t esp_rom_spiflash_program_page_internal(esp_rom_spiflash_chip_t *spi, uint32_t spi_addr,
+        uint32_t *addr_source, int32_t byte_length)
+{
+    uint32_t  temp_addr;
+    int32_t  temp_bl;
+    uint8_t   i;
+    uint8_t   remain_word_num;
+
+    //check 4byte alignment
+    if (0 != (byte_length & 0x3)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    //check if write in one page
+    if ((spi->page_size) < ((spi_addr % (spi->page_size)) + byte_length)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    esp_rom_spiflash_wait_idle(spi);
+
+    temp_addr = spi_addr;
+    temp_bl = byte_length;
+
+    while (temp_bl > 0 ) {
+        if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(spi)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+        if ( temp_bl >= ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM ) {
+            WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, (temp_addr & 0xffffff) | ( ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM << ESP_ROM_SPIFLASH_BYTES_LEN )); // 32 byte a block
+
+            for (i = 0; i < (ESP_ROM_SPIFLASH_BUFF_BYTE_WRITE_NUM >> 2); i++) {
+                WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4, *addr_source++);
+            }
+            temp_bl = temp_bl - 32;
+            temp_addr = temp_addr + 32;
+        } else {
+            WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, (temp_addr & 0xffffff) | (temp_bl << ESP_ROM_SPIFLASH_BYTES_LEN ));
+
+            remain_word_num = (0 == (temp_bl & 0x3)) ? (temp_bl >> 2) : (temp_bl >> 2) + 1;
+            for (i = 0; i < remain_word_num; i++) {
+                WRITE_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4, *addr_source++);
+                temp_bl = temp_bl - 4;
+            }
+            temp_bl = 0;
+        }
+
+        WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_PP);
+        while ( READ_PERI_REG(PERIPHS_SPI_FLASH_CMD ) != 0 );
+
+        esp_rom_spiflash_wait_idle(spi);
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+//only support spi1
+static esp_rom_spiflash_result_t esp_rom_spiflash_read_data(esp_rom_spiflash_chip_t *spi, uint32_t flash_addr,
+        uint32_t *addr_dest, int32_t byte_length)
+{
+    uint32_t  temp_addr;
+    int32_t  temp_length;
+    uint8_t   i;
+    uint8_t   remain_word_num;
+
+    //address range check
+    if ((flash_addr + byte_length) > (spi->chip_size)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    temp_addr = flash_addr;
+    temp_length = byte_length;
+
+    esp_rom_spiflash_wait_idle(spi);
+
+    while (temp_length > 0) {
+        if (temp_length >= ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM) {
+            //WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr |(ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << ESP_ROM_SPIFLASH_BYTES_LEN));
+            REG_WRITE(SPI_MISO_DLEN_REG(1),  ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_USR_MISO_DBITLEN_S);
+            WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
+            REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_USR);
+            while (REG_READ(PERIPHS_SPI_FLASH_CMD) != 0);
+
+            for (i = 0; i < (ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM >> 2); i++) {
+                *addr_dest++ = READ_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4);
+            }
+            temp_length = temp_length - ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM;
+            temp_addr = temp_addr + ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM;
+        } else {
+            //WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr |(temp_length << ESP_ROM_SPIFLASH_BYTES_LEN ));
+            WRITE_PERI_REG(PERIPHS_SPI_FLASH_ADDR, temp_addr << 8);
+            REG_WRITE(SPI_MISO_DLEN_REG(1),  ((ESP_ROM_SPIFLASH_BUFF_BYTE_READ_NUM << 3) - 1) << SPI_USR_MISO_DBITLEN_S);
+            REG_WRITE(PERIPHS_SPI_FLASH_CMD, SPI_USR);
+            while (REG_READ(PERIPHS_SPI_FLASH_CMD) != 0);
+
+            remain_word_num = (0 == (temp_length & 0x3)) ? (temp_length >> 2) : (temp_length >> 2) + 1;
+            for (i = 0; i < remain_word_num; i++) {
+                *addr_dest++ = READ_PERI_REG(PERIPHS_SPI_FLASH_C0 + i * 4);
+            }
+            temp_length = 0;
+        }
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_read_status(esp_rom_spiflash_chip_t *spi, uint32_t *status)
+{
+    uint32_t status_value = ESP_ROM_SPIFLASH_BUSY_FLAG;
+
+    if (g_rom_spiflash_dummy_len_plus[1] == 0) {
+        while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) {
+            WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, 0);       // clear regisrter
+            WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_RDSR);
+            while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
+
+            status_value = READ_PERI_REG(PERIPHS_SPI_FLASH_STATUS) & (spi->status_mask);
+        }
+    } else {
+        while (ESP_ROM_SPIFLASH_BUSY_FLAG == (status_value & ESP_ROM_SPIFLASH_BUSY_FLAG)) {
+            esp_rom_spiflash_read_user_cmd(&status_value, 0x05);
+        }
+    }
+    *status = status_value;
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_read_statushigh(esp_rom_spiflash_chip_t *spi, uint32_t *status)
+{
+    esp_rom_spiflash_result_t ret;
+    esp_rom_spiflash_wait_idle(&g_rom_spiflash_chip);
+    ret = esp_rom_spiflash_read_user_cmd(status, 0x35);
+    *status = *status << 8;
+    return ret;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_write_status(esp_rom_spiflash_chip_t *spi, uint32_t status_value)
+{
+    esp_rom_spiflash_wait_idle(spi);
+
+    // update status value by status_value
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_STATUS, status_value);    // write status regisrter
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WRSR);
+    while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
+    esp_rom_spiflash_wait_idle(spi);
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi)
+{
+    uint32_t flash_status = 0;
+
+    esp_rom_spiflash_wait_idle(spi);
+
+    //enable write
+    WRITE_PERI_REG(PERIPHS_SPI_FLASH_CMD, SPI_FLASH_WREN);     // enable write operation
+    while (READ_PERI_REG(PERIPHS_SPI_FLASH_CMD) != 0);
+
+    // make sure the flash is ready for writing
+    while (ESP_ROM_SPIFLASH_WRENABLE_FLAG != (flash_status & ESP_ROM_SPIFLASH_WRENABLE_FLAG)) {
+        esp_rom_spiflash_read_status(spi, &flash_status);
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+static void spi_cache_mode_switch(uint32_t  modebit)
+{
+    if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) {
+        REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
+        REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
+        REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_QIO_ADDR_BITSLEN);
+        REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_QIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
+        REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0xEB);
+    } else if (modebit & SPI_FASTRD_MODE) {
+        REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
+        REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
+        REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_FAST_ADDR_BITSLEN);
+        if ((modebit & SPI_FREAD_QUAD)) {
+            REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x6B);
+            REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
+        } else if ((modebit & SPI_FREAD_DIO)) {
+            REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_DIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
+            REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0xBB);
+        } else if ((modebit & SPI_FREAD_DUAL)) {
+            REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
+            REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x3B);
+        } else {
+            REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, SPI0_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[0]);
+            REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x0B);
+        }
+    } else {
+        REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_MOSI);
+        if (g_rom_spiflash_dummy_len_plus[0] == 0) {
+            REG_CLR_BIT(SPI_USER_REG(0), SPI_USR_DUMMY);
+        } else {
+            REG_SET_BIT(SPI_USER_REG(0), SPI_USR_DUMMY);
+            REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[0] - 1);
+        }
+        REG_SET_BIT(SPI_USER_REG(0), SPI_USR_MISO | SPI_USR_ADDR);
+        REG_SET_FIELD(SPI_USER1_REG(0), SPI_USR_ADDR_BITLEN, SPI0_R_SIO_ADDR_BITSLEN);
+        REG_SET_FIELD(SPI_USER2_REG(0), SPI_USR_COMMAND_VALUE, 0x03);
+    }
+
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_lock(void)
+{
+    uint32_t status;
+
+    //read QE bit, not write if not QE
+    if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_statushigh(&g_rom_spiflash_chip, &status)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+    //enable 2 byte status writing
+    SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, ESP_ROM_SPIFLASH_TWO_BYTE_STATUS_EN);
+
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_write_status(&g_rom_spiflash_chip, status | ESP_ROM_SPIFLASH_WR_PROTECT)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+
+esp_rom_spiflash_result_t esp_rom_spiflash_config_readmode(esp_rom_spiflash_read_mode_t mode)
+{
+    uint32_t  modebit;
+
+    while ((REG_READ(SPI_EXT2_REG(1)) & SPI_ST)) {
+    }
+    while ((REG_READ(SPI_EXT2_REG(0)) & SPI_ST)) {
+    }
+    //clear old mode bit
+    CLEAR_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, SPI_FREAD_QIO | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_DUAL | SPI_FASTRD_MODE);
+    CLEAR_PERI_REG_MASK(SPI_CTRL_REG(0), SPI_FREAD_QIO | SPI_FREAD_QUAD | SPI_FREAD_DIO | SPI_FREAD_DUAL | SPI_FASTRD_MODE);
+    //configure read mode
+    switch (mode) {
+    case ESP_ROM_SPIFLASH_QIO_MODE   :  modebit = SPI_FREAD_QIO  | SPI_FASTRD_MODE; break;
+    case ESP_ROM_SPIFLASH_QOUT_MODE  :  modebit = SPI_FREAD_QUAD | SPI_FASTRD_MODE; break;
+    case ESP_ROM_SPIFLASH_DIO_MODE   :  modebit = SPI_FREAD_DIO  | SPI_FASTRD_MODE; break;
+    case ESP_ROM_SPIFLASH_DOUT_MODE  :  modebit = SPI_FREAD_DUAL | SPI_FASTRD_MODE; break;
+    case ESP_ROM_SPIFLASH_FASTRD_MODE:  modebit = SPI_FASTRD_MODE; break;
+    case ESP_ROM_SPIFLASH_SLOWRD_MODE:  modebit = 0; break;
+    default : modebit = 0;
+    }
+
+    SET_PERI_REG_MASK(PERIPHS_SPI_FLASH_CTRL, modebit);
+    SET_PERI_REG_MASK(SPI_CTRL_REG(0), modebit);
+    spi_cache_mode_switch(modebit);
+
+    return  ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_chip(void)
+{
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_chip_internal(&g_rom_spiflash_chip)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_block(uint32_t block_num)
+{
+    // flash write is always 1 line currently
+    REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+    REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
+
+    //check program size
+    if (block_num >= ((g_rom_spiflash_chip.chip_size) / (g_rom_spiflash_chip.block_size))) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_block_internal(&g_rom_spiflash_chip, block_num * (g_rom_spiflash_chip.block_size))) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_sector(uint32_t sector_num)
+{
+    // flash write is always 1 line currently
+    REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+    REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
+
+    //check program size
+    if (sector_num >= ((g_rom_spiflash_chip.chip_size) / (g_rom_spiflash_chip.sector_size))) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_enable_write(&g_rom_spiflash_chip)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector_internal(&g_rom_spiflash_chip, sector_num * (g_rom_spiflash_chip.sector_size))) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_write(uint32_t target, const uint32_t *src_addr, int32_t len)
+{
+    uint32_t  page_size;
+    uint32_t  pgm_len;
+
+    // flash write is always 1 line currently
+    REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+    REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, ESP_ROM_SPIFLASH_W_SIO_ADDR_BITSLEN);
+
+    //check program size
+    if ( (target + len) > (g_rom_spiflash_chip.chip_size)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    page_size = g_rom_spiflash_chip.page_size;
+    pgm_len = page_size - (target % page_size);
+    if ((uint32_t)len < pgm_len) {
+        if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
+                target, (uint32_t *)src_addr, len)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+    } else {
+        if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
+                target, (uint32_t *)src_addr, pgm_len)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+
+        //whole page program
+        uint32_t pgm_num = (len - pgm_len) / page_size;
+        uint8_t  i;
+        for (i = 0; i < pgm_num; i++) {
+            if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
+                    target + pgm_len, (uint32_t *)src_addr + (pgm_len >> 2), page_size)) {
+                return ESP_ROM_SPIFLASH_RESULT_ERR;
+            }
+            pgm_len += page_size;
+        }
+
+        //remain parts to program
+        if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_program_page_internal(&g_rom_spiflash_chip,
+                target + pgm_len, (uint32_t *)src_addr + (pgm_len >> 2), len - pgm_len)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+    }
+    return  ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_write_encrypted(uint32_t flash_addr, uint32_t *data, uint32_t len)
+{
+    esp_rom_spiflash_result_t ret = ESP_ROM_SPIFLASH_RESULT_OK;
+    uint32_t i;
+
+    if ((flash_addr & 0x1f) || (len & 0x1f)) {  //check 32 byte alignment
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    esp_rom_spiflash_write_encrypted_enable();
+
+    for (i = 0; i < (len >> 5); i++) {
+        if ((ret = esp_rom_spiflash_prepare_encrypted_data(flash_addr + (i << 5), data + (i << 3))) != ESP_ROM_SPIFLASH_RESULT_OK) {
+            break;
+        }
+
+        if ((ret = esp_rom_spiflash_write(flash_addr + (i << 5), data, 32)) != ESP_ROM_SPIFLASH_RESULT_OK) {
+            break;
+        }
+    }
+
+    esp_rom_spiflash_write_encrypted_disable();
+
+    return ret;
+}
+
+
+esp_rom_spiflash_result_t esp_rom_spiflash_read(uint32_t target, uint32_t *dest_addr, int32_t len)
+{
+    // QIO or SIO, non-QIO regard as SIO
+    uint32_t modebit;
+    modebit = READ_PERI_REG(PERIPHS_SPI_FLASH_CTRL);
+    if ((modebit & SPI_FREAD_QIO) && (modebit & SPI_FASTRD_MODE)) {
+        REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
+        REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_DUMMY | SPI_USR_ADDR);
+        REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_QIO_ADDR_BITSLEN);
+        REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, SPI1_R_QIO_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
+        //REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0xEB);
+        REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xEB);
+    } else if (modebit & SPI_FASTRD_MODE) {
+        REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
+        REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_ADDR);
+        if (modebit & SPI_FREAD_DIO) {
+            if (g_rom_spiflash_dummy_len_plus[1] == 0) {
+                REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+                REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
+                REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0xBB);
+            } else {
+                REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+                REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_DIO_ADDR_BITSLEN);
+                REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, g_rom_spiflash_dummy_len_plus[1] - 1);
+                REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0xBB);
+            }
+        } else {
+            if ((modebit & SPI_FREAD_QUAD)) {
+                //REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x6B);
+                REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x6B);
+            } else if ((modebit & SPI_FREAD_DUAL)) {
+                //REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x3B);
+                REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x3B);
+            } else {
+                //REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x0B);
+                REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x0B);
+            }
+            REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+            REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_FAST_ADDR_BITSLEN);
+            REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN, SPI1_R_FAST_DUMMY_CYCLELEN + g_rom_spiflash_dummy_len_plus[1]);
+        }
+    } else {
+        REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MOSI);
+        if (g_rom_spiflash_dummy_len_plus[1] == 0) {
+            REG_CLR_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+        } else {
+            REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_DUMMY);
+            REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_DUMMY_CYCLELEN,  g_rom_spiflash_dummy_len_plus[1] - 1);
+        }
+        REG_SET_BIT(PERIPHS_SPI_FLASH_USRREG, SPI_USR_MISO | SPI_USR_ADDR);
+        REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG1, SPI_USR_ADDR_BITLEN, SPI1_R_SIO_ADDR_BITSLEN);
+        //REG_SET_FIELD(PERIPHS_SPI_FLASH_USRREG2, SPI_USR_COMMAND_VALUE, 0x03);
+        REG_WRITE(PERIPHS_SPI_FLASH_USRREG2, (0x7 << SPI_USR_COMMAND_BITLEN_S) | 0x03);
+    }
+
+    if ( ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_read_data(&g_rom_spiflash_chip, target, dest_addr, len)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+esp_rom_spiflash_result_t esp_rom_spiflash_erase_area(uint32_t start_addr, uint32_t area_len)
+{
+    int32_t total_sector_num;
+    int32_t head_sector_num;
+    uint32_t sector_no;
+    uint32_t sector_num_per_block;
+
+    //set read mode to Fastmode ,not QDIO mode for erase
+    //
+    // TODO: this is probably a bug as it doesn't re-enable QIO mode, not serious as this
+    // function is not used in IDF.
+    esp_rom_spiflash_config_readmode(ESP_ROM_SPIFLASH_SLOWRD_MODE);
+
+    //check if area is oversize of flash
+    if ((start_addr + area_len) > g_rom_spiflash_chip.chip_size) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    //start_addr is aligned as sector boundary
+    if (0 != (start_addr % g_rom_spiflash_chip.sector_size)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    //Unlock flash to enable erase
+    if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_unlock(/*&g_rom_spiflash_chip*/)) {
+        return ESP_ROM_SPIFLASH_RESULT_ERR;
+    }
+
+    sector_no = start_addr / g_rom_spiflash_chip.sector_size;
+    sector_num_per_block = g_rom_spiflash_chip.block_size / g_rom_spiflash_chip.sector_size;
+    total_sector_num = (0 == (area_len % g_rom_spiflash_chip.sector_size)) ? area_len / g_rom_spiflash_chip.sector_size :
+                       1 + (area_len / g_rom_spiflash_chip.sector_size);
+
+    //check if erase area reach over block boundary
+    head_sector_num = sector_num_per_block - (sector_no % sector_num_per_block);
+
+    head_sector_num = (head_sector_num >= total_sector_num) ? total_sector_num : head_sector_num;
+
+    //JJJ, BUG of 6.0 erase
+    //middle part of area is aligned by blocks
+    total_sector_num -= head_sector_num;
+
+    //head part of area is erased
+    while (0 != head_sector_num) {
+        if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector(sector_no)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+        sector_no++;
+        head_sector_num--;
+    }
+    while (total_sector_num > (int32_t)sector_num_per_block) {
+        if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_block(sector_no / sector_num_per_block)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+        sector_no += sector_num_per_block;
+        total_sector_num -= sector_num_per_block;
+    }
+
+    //tail part of area burn
+    while (0 < total_sector_num) {
+        if (ESP_ROM_SPIFLASH_RESULT_OK != esp_rom_spiflash_erase_sector(sector_no)) {
+            return ESP_ROM_SPIFLASH_RESULT_ERR;
+        }
+        sector_no++;
+        total_sector_num--;
+    }
+
+    return ESP_ROM_SPIFLASH_RESULT_OK;
+}
+
+#endif
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/COPYING b/cpu/esp32/vendor/esp-idf/wpa_supplicant/COPYING
new file mode 100644
index 0000000000000000000000000000000000000000..7efce0dee1a727319eb172ff67236e0e6eaf2447
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/COPYING
@@ -0,0 +1,22 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2016, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+
+See the README file for the current license terms.
+
+This software was previously distributed under BSD/GPL v2 dual license
+terms that allowed either of those license alternatives to be
+selected. As of February 11, 2012, the project has chosen to use only
+the BSD license option for future distribution. As such, the GPL v2
+license option is no longer used. It should be noted that the BSD
+license option (the one with advertisement clause removed) is compatible
+with GPL and as such, does not prevent use of this software in projects
+that use GPL.
+
+Some of the files may still include pointers to GPL version 2 license
+terms. However, such copyright and license notifications are maintained
+only for attribution purposes and any distribution of this software
+after February 11, 2012 is no longer under the GPL v2 option.
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/Makefile b/cpu/esp32/vendor/esp-idf/wpa_supplicant/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..7278372c790e3426d517d24946e6f61cfa1f6d80
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/Makefile
@@ -0,0 +1,9 @@
+ifneq (,$(filter esp_idf_wpa_supplicant_port ,$(USEMODULE)))
+    DIRS += port
+endif
+
+ifneq (,$(filter esp_idf_wpa_supplicant_crypto ,$(USEMODULE)))
+    DIRS += src/crypto
+endif
+
+include $(RIOTBASE)/Makefile.base
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/Makefile b/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..5628a427bc7b426f931911b40cd1f36885b01578
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/Makefile
@@ -0,0 +1,17 @@
+MODULE=esp_idf_wpa_supplicant_port
+
+include $(RIOTBASE)/Makefile.base
+
+# we have to do it in that way to avoid that $(RIOTBASE)/sys/include/crypto
+# is found first
+INCLUDES  = -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/wpa_supplicant/port/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/port/include
+CFLAGS += -D__ets__
+
+include $(RIOTCPU)/$(CPU)/Makefile.include
+
+INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include
+INCLUDES += -I$(RIOTBASE)/core/include
+INCLUDES += -I$(RIOTBASE)/drivers/include
+INCLUDES += -I$(RIOTCPU)/$(CPU)/include
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/include/os.h b/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/include/os.h
new file mode 100644
index 0000000000000000000000000000000000000000..3db4416edc2679eb41cc20ba35ea118f12840b27
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/include/os.h
@@ -0,0 +1,299 @@
+/*
+ * OS specific functions
+ * Copyright (c) 2005-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef OS_H
+#define OS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "esp_types.h"
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "esp_err.h"
+#include "rom/ets_sys.h"
+
+typedef long os_time_t;
+
+/**
+ * os_sleep - Sleep (sec, usec)
+ * @sec: Number of seconds to sleep
+ * @usec: Number of microseconds to sleep
+ */
+void os_sleep(os_time_t sec, os_time_t usec);
+
+struct os_time {
+    os_time_t sec;
+    os_time_t usec;
+};
+
+/**
+ * os_get_time - Get current time (sec, usec)
+ * @t: Pointer to buffer for the time
+ * Returns: 0 on success, -1 on failure
+ */
+int os_get_time(struct os_time *t);
+
+
+/* Helper macros for handling struct os_time */
+
+#define os_time_before(a, b) \
+    ((a)->sec < (b)->sec || \
+     ((a)->sec == (b)->sec && (a)->usec < (b)->usec))
+
+#define os_time_sub(a, b, res) do { \
+    (res)->sec = (a)->sec - (b)->sec; \
+    (res)->usec = (a)->usec - (b)->usec; \
+    if ((res)->usec < 0) { \
+        (res)->sec--; \
+        (res)->usec += 1000000; \
+    } \
+} while (0)
+
+/**
+ * os_mktime - Convert broken-down time into seconds since 1970-01-01
+ * @year: Four digit year
+ * @month: Month (1 .. 12)
+ * @day: Day of month (1 .. 31)
+ * @hour: Hour (0 .. 23)
+ * @min: Minute (0 .. 59)
+ * @sec: Second (0 .. 60)
+ * @t: Buffer for returning calendar time representation (seconds since
+ * 1970-01-01 00:00:00)
+ * Returns: 0 on success, -1 on failure
+ *
+ * Note: The result is in seconds from Epoch, i.e., in UTC, not in local time
+ * which is used by POSIX mktime().
+ */
+int os_mktime(int year, int month, int day, int hour, int min, int sec,
+          os_time_t *t);
+
+
+/**
+ * os_daemonize - Run in the background (detach from the controlling terminal)
+ * @pid_file: File name to write the process ID to or %NULL to skip this
+ * Returns: 0 on success, -1 on failure
+ */
+int os_daemonize(const char *pid_file);
+
+/**
+ * os_daemonize_terminate - Stop running in the background (remove pid file)
+ * @pid_file: File name to write the process ID to or %NULL to skip this
+ */
+void os_daemonize_terminate(const char *pid_file);
+
+/**
+ * os_get_random - Get cryptographically strong pseudo random data
+ * @buf: Buffer for pseudo random data
+ * @len: Length of the buffer
+ * Returns: 0 on success, -1 on failure
+ */
+int os_get_random(unsigned char *buf, size_t len);
+
+/**
+ * os_random - Get pseudo random value (not necessarily very strong)
+ * Returns: Pseudo random value
+ */
+unsigned long os_random(void);
+
+/**
+ * os_rel2abs_path - Get an absolute path for a file
+ * @rel_path: Relative path to a file
+ * Returns: Absolute path for the file or %NULL on failure
+ *
+ * This function tries to convert a relative path of a file to an absolute path
+ * in order for the file to be found even if current working directory has
+ * changed. The returned value is allocated and caller is responsible for
+ * freeing it. It is acceptable to just return the same path in an allocated
+ * buffer, e.g., return strdup(rel_path). This function is only used to find
+ * configuration files when os_daemonize() may have changed the current working
+ * directory and relative path would be pointing to a different location.
+ */
+char * os_rel2abs_path(const char *rel_path);
+
+/**
+ * os_program_init - Program initialization (called at start)
+ * Returns: 0 on success, -1 on failure
+ *
+ * This function is called when a programs starts. If there are any OS specific
+ * processing that is needed, it can be placed here. It is also acceptable to
+ * just return 0 if not special processing is needed.
+ */
+int os_program_init(void);
+
+/**
+ * os_program_deinit - Program deinitialization (called just before exit)
+ *
+ * This function is called just before a program exists. If there are any OS
+ * specific processing, e.g., freeing resourced allocated in os_program_init(),
+ * it should be done here. It is also acceptable for this function to do
+ * nothing.
+ */
+void os_program_deinit(void);
+
+/**
+ * os_setenv - Set environment variable
+ * @name: Name of the variable
+ * @value: Value to set to the variable
+ * @overwrite: Whether existing variable should be overwritten
+ * Returns: 0 on success, -1 on error
+ *
+ * This function is only used for wpa_cli action scripts. OS wrapper does not
+ * need to implement this if such functionality is not needed.
+ */
+int os_setenv(const char *name, const char *value, int overwrite);
+
+/**
+ * os_unsetenv - Delete environent variable
+ * @name: Name of the variable
+ * Returns: 0 on success, -1 on error
+ *
+ * This function is only used for wpa_cli action scripts. OS wrapper does not
+ * need to implement this if such functionality is not needed.
+ */
+int os_unsetenv(const char *name);
+
+/**
+ * os_readfile - Read a file to an allocated memory buffer
+ * @name: Name of the file to read
+ * @len: For returning the length of the allocated buffer
+ * Returns: Pointer to the allocated buffer or %NULL on failure
+ *
+ * This function allocates memory and reads the given file to this buffer. Both
+ * binary and text files can be read with this function. The caller is
+ * responsible for freeing the returned buffer with os_free().
+ */
+char * os_readfile(const char *name, size_t *len);
+
+/*
+ * The following functions are wrapper for standard ANSI C or POSIX functions.
+ * By default, they are just defined to use the standard function name and no
+ * os_*.c implementation is needed for them. This avoids extra function calls
+ * by allowing the C pre-processor take care of the function name mapping.
+ *
+ * If the target system uses a C library that does not provide these functions,
+ * build_config.h can be used to define the wrappers to use a different
+ * function name. This can be done on function-by-function basis since the
+ * defines here are only used if build_config.h does not define the os_* name.
+ * If needed, os_*.c file can be used to implement the functions that are not
+ * included in the C library on the target system. Alternatively,
+ * OS_NO_C_LIB_DEFINES can be defined to skip all defines here in which case
+ * these functions need to be implemented in os_*.c file for the target system.
+ */
+
+#ifndef os_malloc
+#define os_malloc(s) malloc((s))
+#endif
+#ifndef os_realloc
+#define os_realloc(p, s) realloc((p), (s))
+#endif
+#ifndef os_zalloc
+#define os_zalloc(s) calloc(1, (s))
+#endif
+#ifndef os_free
+#define os_free(p) free((p))
+#endif
+
+#ifndef os_bzero
+#define os_bzero(s, n) bzero(s, n)
+#endif
+
+
+#ifndef os_strdup
+#ifdef _MSC_VER
+#define os_strdup(s) _strdup(s)
+#else
+#define os_strdup(s) strdup(s)
+#endif
+#endif
+char * ets_strdup(const char *s);
+
+#ifndef os_memcpy
+#define os_memcpy(d, s, n) memcpy((d), (s), (n))
+#endif
+#ifndef os_memmove
+#define os_memmove(d, s, n) memmove((d), (s), (n))
+#endif
+#ifndef os_memset
+#define os_memset(s, c, n) memset(s, c, n)
+#endif
+#ifndef os_memcmp
+#define os_memcmp(s1, s2, n) memcmp((s1), (s2), (n))
+#endif
+
+#ifndef os_strlen
+#define os_strlen(s) strlen(s)
+#endif
+#ifndef os_strcasecmp
+#ifdef _MSC_VER
+#define os_strcasecmp(s1, s2) _stricmp((s1), (s2))
+#else
+#define os_strcasecmp(s1, s2) strcasecmp((s1), (s2))
+#endif
+#endif
+#ifndef os_strncasecmp
+#ifdef _MSC_VER
+#define os_strncasecmp(s1, s2, n) _strnicmp((s1), (s2), (n))
+#else
+#define os_strncasecmp(s1, s2, n) strncasecmp((s1), (s2), (n))
+#endif
+#endif
+#ifndef os_strchr
+#define os_strchr(s, c) strchr((s), (c))
+#endif
+#ifndef os_strcmp
+#define os_strcmp(s1, s2) strcmp((s1), (s2))
+#endif
+#ifndef os_strncmp
+#define os_strncmp(s1, s2, n) strncmp((s1), (s2), (n))
+#endif
+#ifndef os_strncpy
+#define os_strncpy(d, s, n) strncpy((d), (s), (n))
+#endif
+#ifndef os_strrchr
+//hard cold
+#define os_strrchr(s, c)  NULL
+#endif
+#ifndef os_strstr
+#define os_strstr(h, n) strstr((h), (n))
+#endif
+
+#ifndef os_snprintf
+#ifdef _MSC_VER
+#define os_snprintf _snprintf
+#else
+#define os_snprintf vsnprintf
+#endif
+#endif
+
+/**
+ * os_strlcpy - Copy a string with size bound and NUL-termination
+ * @dest: Destination
+ * @src: Source
+ * @siz: Size of the target buffer
+ * Returns: Total length of the target string (length of src) (not including
+ * NUL-termination)
+ *
+ * This function matches in behavior with the strlcpy(3) function in OpenBSD.
+ */
+size_t os_strlcpy(char *dest, const char *src, size_t siz);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* OS_H */
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/os_xtensa.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/os_xtensa.c
new file mode 100644
index 0000000000000000000000000000000000000000..7d1665d81868fde93459e575fe5a7b35aefa6ca3
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/port/os_xtensa.c
@@ -0,0 +1,67 @@
+/*
+ * wpa_supplicant/hostapd / Internal implementation of OS specific functions
+ * Copyright (c) 2005-2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ *
+ * This file is an example of operating system specific  wrapper functions.
+ * This version implements many of the functions internally, so it can be used
+ * to fill in missing functions from the target system C libraries.
+ *
+ * Some of the functions are using standard C library calls in order to keep
+ * this file in working condition to allow the functions to be tested on a
+ * Linux target. Please note that OS_NO_C_LIB_DEFINES needs to be defined for
+ * this file to work correctly. Note that these implementations are only
+ * examples and are not optimized for speed.
+ */
+
+#include "crypto/common.h"
+#include "os.h"
+#include <stdlib.h>
+#include <time.h>
+#include <sys/time.h>
+#include "esp_system.h"
+
+#ifndef RIOT_VERSION
+
+int os_get_time(struct os_time *t)
+{
+    return gettimeofday((struct timeval*) t, NULL);
+}
+
+unsigned long os_random(void)
+{
+    return esp_random();
+}
+
+unsigned long r_rand(void) __attribute__((alias("os_random")));
+
+
+int os_get_random(unsigned char *buf, size_t len)
+{
+    unsigned int i, j;
+    unsigned long tmp;
+
+    for (i = 0; i < ((len + 3) & ~3) / 4; i++) {
+        tmp = r_rand();
+
+        for (j = 0; j < 4; j++) {
+            if ((i * 4 + j) < len) {
+                buf[i * 4 + j] = (uint8_t)(tmp >> (j * 8));
+            } else {
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
+
+#endif
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/Makefile b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..90e894d7913dd3ff0323b9278b2cb1fcb44ce6b4
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/Makefile
@@ -0,0 +1,20 @@
+MODULE=esp_idf_wpa_supplicant_crypto
+
+include $(RIOTBASE)/Makefile.base
+
+# we have to do it in that way to avoid that $(RIOTBASE)/sys/include/crypto
+# is found first
+INCLUDES  = -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/wpa_supplicant/port/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/include
+INCLUDES += -I$(ESP32_SDK_DIR)/components/wpa_supplicant/port/include
+CFLAGS += -D__ets__ -DESPRESSIF_USE
+
+include $(RIOTCPU)/$(CPU)/Makefile.include
+
+INCLUDES += -I$(RIOTBASE)/core/include
+INCLUDES += -I$(RIOTBASE)/drivers/include
+INCLUDES += -I$(RIOTBASE)/sys/include
+INCLUDES += -I$(RIOTBASE)/sys/posix/include
+INCLUDES += -I$(RIOTCPU)/$(CPU)/vendor/esp-idf/include/log
+INCLUDES += -I$(RIOTCPU)/$(CPU)/include
+INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-cbc.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-cbc.c
new file mode 100644
index 0000000000000000000000000000000000000000..a99daef1a79c9642f97d0171a19edfa95d87593a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-cbc.c
@@ -0,0 +1,88 @@
+/*
+ * AES-128 CBC
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+
+/**
+ * aes_128_cbc_encrypt - AES-128 CBC encryption
+ * @key: Encryption key
+ * @iv: Encryption IV for CBC mode (16 bytes)
+ * @data: Data to encrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+aes_128_cbc_encrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+    void *ctx;
+    u8 cbc[AES_BLOCK_SIZE];
+    u8 *pos = data;
+    int i, j, blocks;
+
+    ctx = aes_encrypt_init(key, 16);
+    if (ctx == NULL)
+        return -1;
+    os_memcpy(cbc, iv, AES_BLOCK_SIZE);
+
+    blocks = data_len / AES_BLOCK_SIZE;
+    for (i = 0; i < blocks; i++) {
+        for (j = 0; j < AES_BLOCK_SIZE; j++)
+            cbc[j] ^= pos[j];
+        aes_encrypt(ctx, cbc, cbc);
+        os_memcpy(pos, cbc, AES_BLOCK_SIZE);
+        pos += AES_BLOCK_SIZE;
+    }
+    aes_encrypt_deinit(ctx);
+    return 0;
+}
+
+
+/**
+ * aes_128_cbc_decrypt - AES-128 CBC decryption
+ * @key: Decryption key
+ * @iv: Decryption IV for CBC mode (16 bytes)
+ * @data: Data to decrypt in-place
+ * @data_len: Length of data in bytes (must be divisible by 16)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+aes_128_cbc_decrypt(const u8 *key, const u8 *iv, u8 *data, size_t data_len)
+{
+    void *ctx;
+    u8 cbc[AES_BLOCK_SIZE], tmp[AES_BLOCK_SIZE];
+    u8 *pos = data;
+    int i, j, blocks;
+
+    ctx = aes_decrypt_init(key, 16);
+    if (ctx == NULL)
+        return -1;
+    os_memcpy(cbc, iv, AES_BLOCK_SIZE);
+
+    blocks = data_len / AES_BLOCK_SIZE;
+    for (i = 0; i < blocks; i++) {
+        os_memcpy(tmp, pos, AES_BLOCK_SIZE);
+        aes_decrypt(ctx, pos, pos);
+        for (j = 0; j < AES_BLOCK_SIZE; j++)
+            pos[j] ^= cbc[j];
+        os_memcpy(cbc, tmp, AES_BLOCK_SIZE);
+        pos += AES_BLOCK_SIZE;
+    }
+    aes_decrypt_deinit(ctx);
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal-dec.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal-dec.c
new file mode 100644
index 0000000000000000000000000000000000000000..36696e8a21738f4c9dca310c81be64392d381a40
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal-dec.c
@@ -0,0 +1,172 @@
+/*
+ * AES (Rijndael) cipher - decrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes_i.h"
+
+
+
+//static unsigned char aes_priv_buf[AES_PRIV_SIZE];
+
+/**
+ * Expand the cipher key into the decryption key schedule.
+ *
+ * @return    the number of rounds for the given cipher key size.
+ */
+static int  rijndaelKeySetupDec(u32 rk[], const u8 cipherKey[], int keyBits)
+{
+    int Nr, i, j;
+    u32 temp;
+
+    /* expand the cipher key: */
+    Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
+    if (Nr < 0)
+        return Nr;
+    /* invert the order of the round keys: */
+    for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
+        temp = rk[i    ]; rk[i    ] = rk[j    ]; rk[j    ] = temp;
+        temp = rk[i + 1]; rk[i + 1] = rk[j + 1]; rk[j + 1] = temp;
+        temp = rk[i + 2]; rk[i + 2] = rk[j + 2]; rk[j + 2] = temp;
+        temp = rk[i + 3]; rk[i + 3] = rk[j + 3]; rk[j + 3] = temp;
+    }
+    /* apply the inverse MixColumn transform to all round keys but the
+     * first and the last: */
+    for (i = 1; i < Nr; i++) {
+        rk += 4;
+        for (j = 0; j < 4; j++) {
+            rk[j] = TD0_(TE4((rk[j] >> 24)       )) ^
+                TD1_(TE4((rk[j] >> 16) & 0xff)) ^
+                TD2_(TE4((rk[j] >>  8) & 0xff)) ^
+                TD3_(TE4((rk[j]      ) & 0xff));
+        }
+    }
+
+    return Nr;
+}
+
+void *  aes_decrypt_init(const u8 *key, size_t len)
+{
+    u32 *rk;
+    int res;
+    rk = os_malloc(AES_PRIV_SIZE);
+    if (rk == NULL)
+        return NULL;
+    res = rijndaelKeySetupDec(rk, key, len * 8);
+    if (res < 0) {
+        os_free(rk);
+        return NULL;
+    }
+    rk[AES_PRIV_NR_POS] = res;
+    return rk;
+}
+
+static void  rijndaelDecrypt(const u32 rk[/*44*/], int Nr, const u8 ct[16],
+                u8 pt[16])
+{
+    u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    s0 = GETU32(ct     ) ^ rk[0];
+    s1 = GETU32(ct +  4) ^ rk[1];
+    s2 = GETU32(ct +  8) ^ rk[2];
+    s3 = GETU32(ct + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TD0(s##0) ^ TD1(s##3) ^ TD2(s##2) ^ TD3(s##1) ^ rk[4 * i]; \
+d##1 = TD0(s##1) ^ TD1(s##0) ^ TD2(s##3) ^ TD3(s##2) ^ rk[4 * i + 1]; \
+d##2 = TD0(s##2) ^ TD1(s##1) ^ TD2(s##0) ^ TD3(s##3) ^ rk[4 * i + 2]; \
+d##3 = TD0(s##3) ^ TD1(s##2) ^ TD2(s##1) ^ TD3(s##0) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+    ROUND(1,t,s);
+    ROUND(2,s,t);
+    ROUND(3,t,s);
+    ROUND(4,s,t);
+    ROUND(5,t,s);
+    ROUND(6,s,t);
+    ROUND(7,t,s);
+    ROUND(8,s,t);
+    ROUND(9,t,s);
+    if (Nr > 10) {
+        ROUND(10,s,t);
+        ROUND(11,t,s);
+        if (Nr > 12) {
+            ROUND(12,s,t);
+            ROUND(13,t,s);
+        }
+    }
+
+    rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+    /* Nr - 1 full rounds: */
+    r = Nr >> 1;
+    for (;;) {
+        ROUND(1,t,s);
+        rk += 8;
+        if (--r == 0)
+            break;
+        ROUND(0,s,t);
+    }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+    s0 = TD41(t0) ^ TD42(t3) ^ TD43(t2) ^ TD44(t1) ^ rk[0];
+    PUTU32(pt     , s0);
+    s1 = TD41(t1) ^ TD42(t0) ^ TD43(t3) ^ TD44(t2) ^ rk[1];
+    PUTU32(pt +  4, s1);
+    s2 = TD41(t2) ^ TD42(t1) ^ TD43(t0) ^ TD44(t3) ^ rk[2];
+    PUTU32(pt +  8, s2);
+    s3 = TD41(t3) ^ TD42(t2) ^ TD43(t1) ^ TD44(t0) ^ rk[3];
+    PUTU32(pt + 12, s3);
+}
+
+void  aes_decrypt(void *ctx, const u8 *crypt, u8 *plain)
+{
+    u32 *rk = ctx;
+    rijndaelDecrypt(ctx, rk[AES_PRIV_NR_POS], crypt, plain);
+}
+
+
+void  aes_decrypt_deinit(void *ctx)
+{
+    os_memset(ctx, 0, AES_PRIV_SIZE);
+    os_free(ctx);
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal-enc.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal-enc.c
new file mode 100644
index 0000000000000000000000000000000000000000..68beb4228e3acd6bc143ec9e33492e78dc8c1ae0
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal-enc.c
@@ -0,0 +1,134 @@
+/*
+ * AES (Rijndael) cipher - encrypt
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes_i.h"
+
+#include "os.h"
+
+void  rijndaelEncrypt(const u32 rk[], int Nr, const u8 pt[16], u8 ct[16])
+{
+    u32 s0, s1, s2, s3, t0, t1, t2, t3;
+#ifndef FULL_UNROLL
+    int r;
+#endif /* ?FULL_UNROLL */
+
+    /*
+     * map byte array block to cipher state
+     * and add initial round key:
+     */
+    s0 = GETU32(pt     ) ^ rk[0];
+    s1 = GETU32(pt +  4) ^ rk[1];
+    s2 = GETU32(pt +  8) ^ rk[2];
+    s3 = GETU32(pt + 12) ^ rk[3];
+
+#define ROUND(i,d,s) \
+d##0 = TE0(s##0) ^ TE1(s##1) ^ TE2(s##2) ^ TE3(s##3) ^ rk[4 * i]; \
+d##1 = TE0(s##1) ^ TE1(s##2) ^ TE2(s##3) ^ TE3(s##0) ^ rk[4 * i + 1]; \
+d##2 = TE0(s##2) ^ TE1(s##3) ^ TE2(s##0) ^ TE3(s##1) ^ rk[4 * i + 2]; \
+d##3 = TE0(s##3) ^ TE1(s##0) ^ TE2(s##1) ^ TE3(s##2) ^ rk[4 * i + 3]
+
+#ifdef FULL_UNROLL
+
+    ROUND(1,t,s);
+    ROUND(2,s,t);
+    ROUND(3,t,s);
+    ROUND(4,s,t);
+    ROUND(5,t,s);
+    ROUND(6,s,t);
+    ROUND(7,t,s);
+    ROUND(8,s,t);
+    ROUND(9,t,s);
+    if (Nr > 10) {
+        ROUND(10,s,t);
+        ROUND(11,t,s);
+        if (Nr > 12) {
+            ROUND(12,s,t);
+            ROUND(13,t,s);
+        }
+    }
+
+    rk += Nr << 2;
+
+#else  /* !FULL_UNROLL */
+
+    /* Nr - 1 full rounds: */
+    r = Nr >> 1;
+    for (;;) {
+        ROUND(1,t,s);
+        rk += 8;
+        if (--r == 0)
+            break;
+        ROUND(0,s,t);
+    }
+
+#endif /* ?FULL_UNROLL */
+
+#undef ROUND
+
+    /*
+     * apply last round and
+     * map cipher state to byte array block:
+     */
+    s0 = TE41(t0) ^ TE42(t1) ^ TE43(t2) ^ TE44(t3) ^ rk[0];
+    PUTU32(ct     , s0);
+    s1 = TE41(t1) ^ TE42(t2) ^ TE43(t3) ^ TE44(t0) ^ rk[1];
+    PUTU32(ct +  4, s1);
+    s2 = TE41(t2) ^ TE42(t3) ^ TE43(t0) ^ TE44(t1) ^ rk[2];
+    PUTU32(ct +  8, s2);
+    s3 = TE41(t3) ^ TE42(t0) ^ TE43(t1) ^ TE44(t2) ^ rk[3];
+    PUTU32(ct + 12, s3);
+}
+
+
+void *  aes_encrypt_init(const u8 *key, size_t len)
+{
+    u32 *rk;
+    int res;
+    rk = os_malloc(AES_PRIV_SIZE);
+    if (rk == NULL)
+        return NULL;
+    res = rijndaelKeySetupEnc(rk, key, len * 8);
+    if (res < 0) {
+        os_free(rk);
+        return NULL;
+    }
+    rk[AES_PRIV_NR_POS] = res;
+    return rk;
+}
+
+
+void  aes_encrypt(void *ctx, const u8 *plain, u8 *crypt)
+{
+    u32 *rk = ctx;
+    rijndaelEncrypt(ctx, rk[AES_PRIV_NR_POS], plain, crypt);
+}
+
+
+void  aes_encrypt_deinit(void *ctx)
+{
+    os_memset(ctx, 0, AES_PRIV_SIZE);
+    os_free(ctx);
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..35ff8329d7e346e8091464760742b2d0f1389b09
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-internal.c
@@ -0,0 +1,854 @@
+/*
+ * AES (Rijndael) cipher
+ *
+ * Modifications to public domain implementation:
+ * - support only 128-bit keys
+ * - cleanup
+ * - use C pre-processor to make it easier to change S table access
+ * - added option (AES_SMALL_TABLES) for reducing code size by about 8 kB at
+ *   cost of reduced throughput (quite small difference on Pentium 4,
+ *   10-25% when using -O1 or -O2 optimization)
+ *
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+//#include "wpa/common.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes_i.h"
+
+/*
+ * rijndael-alg-fst.c
+ *
+ * @version 3.0 (December 2000)
+ *
+ * Optimised ANSI C code for the Rijndael cipher (now AES)
+ *
+ * @author Vincent Rijmen <vincent.rijmen@esat.kuleuven.ac.be>
+ * @author Antoon Bosselaers <antoon.bosselaers@esat.kuleuven.ac.be>
+ * @author Paulo Barreto <paulo.barreto@terra.com.br>
+ *
+ * This code is hereby placed in the public domain.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#define AES_SMALL_TABLES
+
+/*
+Te0[x] = S [x].[02, 01, 01, 03];
+Te1[x] = S [x].[03, 02, 01, 01];
+Te2[x] = S [x].[01, 03, 02, 01];
+Te3[x] = S [x].[01, 01, 03, 02];
+Te4[x] = S [x].[01, 01, 01, 01];
+
+Td0[x] = Si[x].[0e, 09, 0d, 0b];
+Td1[x] = Si[x].[0b, 0e, 09, 0d];
+Td2[x] = Si[x].[0d, 0b, 0e, 09];
+Td3[x] = Si[x].[09, 0d, 0b, 0e];
+Td4[x] = Si[x].[01, 01, 01, 01];
+*/
+
+const u32 Te0[256] /* ICACHE_RODATA_ATTR */ = {
+    0xc66363a5U, 0xf87c7c84U, 0xee777799U, 0xf67b7b8dU,
+    0xfff2f20dU, 0xd66b6bbdU, 0xde6f6fb1U, 0x91c5c554U,
+    0x60303050U, 0x02010103U, 0xce6767a9U, 0x562b2b7dU,
+    0xe7fefe19U, 0xb5d7d762U, 0x4dababe6U, 0xec76769aU,
+    0x8fcaca45U, 0x1f82829dU, 0x89c9c940U, 0xfa7d7d87U,
+    0xeffafa15U, 0xb25959ebU, 0x8e4747c9U, 0xfbf0f00bU,
+    0x41adadecU, 0xb3d4d467U, 0x5fa2a2fdU, 0x45afafeaU,
+    0x239c9cbfU, 0x53a4a4f7U, 0xe4727296U, 0x9bc0c05bU,
+    0x75b7b7c2U, 0xe1fdfd1cU, 0x3d9393aeU, 0x4c26266aU,
+    0x6c36365aU, 0x7e3f3f41U, 0xf5f7f702U, 0x83cccc4fU,
+    0x6834345cU, 0x51a5a5f4U, 0xd1e5e534U, 0xf9f1f108U,
+    0xe2717193U, 0xabd8d873U, 0x62313153U, 0x2a15153fU,
+    0x0804040cU, 0x95c7c752U, 0x46232365U, 0x9dc3c35eU,
+    0x30181828U, 0x379696a1U, 0x0a05050fU, 0x2f9a9ab5U,
+    0x0e070709U, 0x24121236U, 0x1b80809bU, 0xdfe2e23dU,
+    0xcdebeb26U, 0x4e272769U, 0x7fb2b2cdU, 0xea75759fU,
+    0x1209091bU, 0x1d83839eU, 0x582c2c74U, 0x341a1a2eU,
+    0x361b1b2dU, 0xdc6e6eb2U, 0xb45a5aeeU, 0x5ba0a0fbU,
+    0xa45252f6U, 0x763b3b4dU, 0xb7d6d661U, 0x7db3b3ceU,
+    0x5229297bU, 0xdde3e33eU, 0x5e2f2f71U, 0x13848497U,
+    0xa65353f5U, 0xb9d1d168U, 0x00000000U, 0xc1eded2cU,
+    0x40202060U, 0xe3fcfc1fU, 0x79b1b1c8U, 0xb65b5bedU,
+    0xd46a6abeU, 0x8dcbcb46U, 0x67bebed9U, 0x7239394bU,
+    0x944a4adeU, 0x984c4cd4U, 0xb05858e8U, 0x85cfcf4aU,
+    0xbbd0d06bU, 0xc5efef2aU, 0x4faaaae5U, 0xedfbfb16U,
+    0x864343c5U, 0x9a4d4dd7U, 0x66333355U, 0x11858594U,
+    0x8a4545cfU, 0xe9f9f910U, 0x04020206U, 0xfe7f7f81U,
+    0xa05050f0U, 0x783c3c44U, 0x259f9fbaU, 0x4ba8a8e3U,
+    0xa25151f3U, 0x5da3a3feU, 0x804040c0U, 0x058f8f8aU,
+    0x3f9292adU, 0x219d9dbcU, 0x70383848U, 0xf1f5f504U,
+    0x63bcbcdfU, 0x77b6b6c1U, 0xafdada75U, 0x42212163U,
+    0x20101030U, 0xe5ffff1aU, 0xfdf3f30eU, 0xbfd2d26dU,
+    0x81cdcd4cU, 0x180c0c14U, 0x26131335U, 0xc3ecec2fU,
+    0xbe5f5fe1U, 0x359797a2U, 0x884444ccU, 0x2e171739U,
+    0x93c4c457U, 0x55a7a7f2U, 0xfc7e7e82U, 0x7a3d3d47U,
+    0xc86464acU, 0xba5d5de7U, 0x3219192bU, 0xe6737395U,
+    0xc06060a0U, 0x19818198U, 0x9e4f4fd1U, 0xa3dcdc7fU,
+    0x44222266U, 0x542a2a7eU, 0x3b9090abU, 0x0b888883U,
+    0x8c4646caU, 0xc7eeee29U, 0x6bb8b8d3U, 0x2814143cU,
+    0xa7dede79U, 0xbc5e5ee2U, 0x160b0b1dU, 0xaddbdb76U,
+    0xdbe0e03bU, 0x64323256U, 0x743a3a4eU, 0x140a0a1eU,
+    0x924949dbU, 0x0c06060aU, 0x4824246cU, 0xb85c5ce4U,
+    0x9fc2c25dU, 0xbdd3d36eU, 0x43acacefU, 0xc46262a6U,
+    0x399191a8U, 0x319595a4U, 0xd3e4e437U, 0xf279798bU,
+    0xd5e7e732U, 0x8bc8c843U, 0x6e373759U, 0xda6d6db7U,
+    0x018d8d8cU, 0xb1d5d564U, 0x9c4e4ed2U, 0x49a9a9e0U,
+    0xd86c6cb4U, 0xac5656faU, 0xf3f4f407U, 0xcfeaea25U,
+    0xca6565afU, 0xf47a7a8eU, 0x47aeaee9U, 0x10080818U,
+    0x6fbabad5U, 0xf0787888U, 0x4a25256fU, 0x5c2e2e72U,
+    0x381c1c24U, 0x57a6a6f1U, 0x73b4b4c7U, 0x97c6c651U,
+    0xcbe8e823U, 0xa1dddd7cU, 0xe874749cU, 0x3e1f1f21U,
+    0x964b4bddU, 0x61bdbddcU, 0x0d8b8b86U, 0x0f8a8a85U,
+    0xe0707090U, 0x7c3e3e42U, 0x71b5b5c4U, 0xcc6666aaU,
+    0x904848d8U, 0x06030305U, 0xf7f6f601U, 0x1c0e0e12U,
+    0xc26161a3U, 0x6a35355fU, 0xae5757f9U, 0x69b9b9d0U,
+    0x17868691U, 0x99c1c158U, 0x3a1d1d27U, 0x279e9eb9U,
+    0xd9e1e138U, 0xebf8f813U, 0x2b9898b3U, 0x22111133U,
+    0xd26969bbU, 0xa9d9d970U, 0x078e8e89U, 0x339494a7U,
+    0x2d9b9bb6U, 0x3c1e1e22U, 0x15878792U, 0xc9e9e920U,
+    0x87cece49U, 0xaa5555ffU, 0x50282878U, 0xa5dfdf7aU,
+    0x038c8c8fU, 0x59a1a1f8U, 0x09898980U, 0x1a0d0d17U,
+    0x65bfbfdaU, 0xd7e6e631U, 0x844242c6U, 0xd06868b8U,
+    0x824141c3U, 0x299999b0U, 0x5a2d2d77U, 0x1e0f0f11U,
+    0x7bb0b0cbU, 0xa85454fcU, 0x6dbbbbd6U, 0x2c16163aU,
+};
+#ifndef AES_SMALL_TABLES
+const u32 Te1[256] /* ICACHE_RODATA_ATTR */ = {
+    0xa5c66363U, 0x84f87c7cU, 0x99ee7777U, 0x8df67b7bU,
+    0x0dfff2f2U, 0xbdd66b6bU, 0xb1de6f6fU, 0x5491c5c5U,
+    0x50603030U, 0x03020101U, 0xa9ce6767U, 0x7d562b2bU,
+    0x19e7fefeU, 0x62b5d7d7U, 0xe64dababU, 0x9aec7676U,
+    0x458fcacaU, 0x9d1f8282U, 0x4089c9c9U, 0x87fa7d7dU,
+    0x15effafaU, 0xebb25959U, 0xc98e4747U, 0x0bfbf0f0U,
+    0xec41adadU, 0x67b3d4d4U, 0xfd5fa2a2U, 0xea45afafU,
+    0xbf239c9cU, 0xf753a4a4U, 0x96e47272U, 0x5b9bc0c0U,
+    0xc275b7b7U, 0x1ce1fdfdU, 0xae3d9393U, 0x6a4c2626U,
+    0x5a6c3636U, 0x417e3f3fU, 0x02f5f7f7U, 0x4f83ccccU,
+    0x5c683434U, 0xf451a5a5U, 0x34d1e5e5U, 0x08f9f1f1U,
+    0x93e27171U, 0x73abd8d8U, 0x53623131U, 0x3f2a1515U,
+    0x0c080404U, 0x5295c7c7U, 0x65462323U, 0x5e9dc3c3U,
+    0x28301818U, 0xa1379696U, 0x0f0a0505U, 0xb52f9a9aU,
+    0x090e0707U, 0x36241212U, 0x9b1b8080U, 0x3ddfe2e2U,
+    0x26cdebebU, 0x694e2727U, 0xcd7fb2b2U, 0x9fea7575U,
+    0x1b120909U, 0x9e1d8383U, 0x74582c2cU, 0x2e341a1aU,
+    0x2d361b1bU, 0xb2dc6e6eU, 0xeeb45a5aU, 0xfb5ba0a0U,
+    0xf6a45252U, 0x4d763b3bU, 0x61b7d6d6U, 0xce7db3b3U,
+    0x7b522929U, 0x3edde3e3U, 0x715e2f2fU, 0x97138484U,
+    0xf5a65353U, 0x68b9d1d1U, 0x00000000U, 0x2cc1ededU,
+    0x60402020U, 0x1fe3fcfcU, 0xc879b1b1U, 0xedb65b5bU,
+    0xbed46a6aU, 0x468dcbcbU, 0xd967bebeU, 0x4b723939U,
+    0xde944a4aU, 0xd4984c4cU, 0xe8b05858U, 0x4a85cfcfU,
+    0x6bbbd0d0U, 0x2ac5efefU, 0xe54faaaaU, 0x16edfbfbU,
+    0xc5864343U, 0xd79a4d4dU, 0x55663333U, 0x94118585U,
+    0xcf8a4545U, 0x10e9f9f9U, 0x06040202U, 0x81fe7f7fU,
+    0xf0a05050U, 0x44783c3cU, 0xba259f9fU, 0xe34ba8a8U,
+    0xf3a25151U, 0xfe5da3a3U, 0xc0804040U, 0x8a058f8fU,
+    0xad3f9292U, 0xbc219d9dU, 0x48703838U, 0x04f1f5f5U,
+    0xdf63bcbcU, 0xc177b6b6U, 0x75afdadaU, 0x63422121U,
+    0x30201010U, 0x1ae5ffffU, 0x0efdf3f3U, 0x6dbfd2d2U,
+    0x4c81cdcdU, 0x14180c0cU, 0x35261313U, 0x2fc3ececU,
+    0xe1be5f5fU, 0xa2359797U, 0xcc884444U, 0x392e1717U,
+    0x5793c4c4U, 0xf255a7a7U, 0x82fc7e7eU, 0x477a3d3dU,
+    0xacc86464U, 0xe7ba5d5dU, 0x2b321919U, 0x95e67373U,
+    0xa0c06060U, 0x98198181U, 0xd19e4f4fU, 0x7fa3dcdcU,
+    0x66442222U, 0x7e542a2aU, 0xab3b9090U, 0x830b8888U,
+    0xca8c4646U, 0x29c7eeeeU, 0xd36bb8b8U, 0x3c281414U,
+    0x79a7dedeU, 0xe2bc5e5eU, 0x1d160b0bU, 0x76addbdbU,
+    0x3bdbe0e0U, 0x56643232U, 0x4e743a3aU, 0x1e140a0aU,
+    0xdb924949U, 0x0a0c0606U, 0x6c482424U, 0xe4b85c5cU,
+    0x5d9fc2c2U, 0x6ebdd3d3U, 0xef43acacU, 0xa6c46262U,
+    0xa8399191U, 0xa4319595U, 0x37d3e4e4U, 0x8bf27979U,
+    0x32d5e7e7U, 0x438bc8c8U, 0x596e3737U, 0xb7da6d6dU,
+    0x8c018d8dU, 0x64b1d5d5U, 0xd29c4e4eU, 0xe049a9a9U,
+    0xb4d86c6cU, 0xfaac5656U, 0x07f3f4f4U, 0x25cfeaeaU,
+    0xafca6565U, 0x8ef47a7aU, 0xe947aeaeU, 0x18100808U,
+    0xd56fbabaU, 0x88f07878U, 0x6f4a2525U, 0x725c2e2eU,
+    0x24381c1cU, 0xf157a6a6U, 0xc773b4b4U, 0x5197c6c6U,
+    0x23cbe8e8U, 0x7ca1ddddU, 0x9ce87474U, 0x213e1f1fU,
+    0xdd964b4bU, 0xdc61bdbdU, 0x860d8b8bU, 0x850f8a8aU,
+    0x90e07070U, 0x427c3e3eU, 0xc471b5b5U, 0xaacc6666U,
+    0xd8904848U, 0x05060303U, 0x01f7f6f6U, 0x121c0e0eU,
+    0xa3c26161U, 0x5f6a3535U, 0xf9ae5757U, 0xd069b9b9U,
+    0x91178686U, 0x5899c1c1U, 0x273a1d1dU, 0xb9279e9eU,
+    0x38d9e1e1U, 0x13ebf8f8U, 0xb32b9898U, 0x33221111U,
+    0xbbd26969U, 0x70a9d9d9U, 0x89078e8eU, 0xa7339494U,
+    0xb62d9b9bU, 0x223c1e1eU, 0x92158787U, 0x20c9e9e9U,
+    0x4987ceceU, 0xffaa5555U, 0x78502828U, 0x7aa5dfdfU,
+    0x8f038c8cU, 0xf859a1a1U, 0x80098989U, 0x171a0d0dU,
+    0xda65bfbfU, 0x31d7e6e6U, 0xc6844242U, 0xb8d06868U,
+    0xc3824141U, 0xb0299999U, 0x775a2d2dU, 0x111e0f0fU,
+    0xcb7bb0b0U, 0xfca85454U, 0xd66dbbbbU, 0x3a2c1616U,
+};
+const u32 Te2[256] /* ICACHE_RODATA_ATTR */ = {
+    0x63a5c663U, 0x7c84f87cU, 0x7799ee77U, 0x7b8df67bU,
+    0xf20dfff2U, 0x6bbdd66bU, 0x6fb1de6fU, 0xc55491c5U,
+    0x30506030U, 0x01030201U, 0x67a9ce67U, 0x2b7d562bU,
+    0xfe19e7feU, 0xd762b5d7U, 0xabe64dabU, 0x769aec76U,
+    0xca458fcaU, 0x829d1f82U, 0xc94089c9U, 0x7d87fa7dU,
+    0xfa15effaU, 0x59ebb259U, 0x47c98e47U, 0xf00bfbf0U,
+    0xadec41adU, 0xd467b3d4U, 0xa2fd5fa2U, 0xafea45afU,
+    0x9cbf239cU, 0xa4f753a4U, 0x7296e472U, 0xc05b9bc0U,
+    0xb7c275b7U, 0xfd1ce1fdU, 0x93ae3d93U, 0x266a4c26U,
+    0x365a6c36U, 0x3f417e3fU, 0xf702f5f7U, 0xcc4f83ccU,
+    0x345c6834U, 0xa5f451a5U, 0xe534d1e5U, 0xf108f9f1U,
+    0x7193e271U, 0xd873abd8U, 0x31536231U, 0x153f2a15U,
+    0x040c0804U, 0xc75295c7U, 0x23654623U, 0xc35e9dc3U,
+    0x18283018U, 0x96a13796U, 0x050f0a05U, 0x9ab52f9aU,
+    0x07090e07U, 0x12362412U, 0x809b1b80U, 0xe23ddfe2U,
+    0xeb26cdebU, 0x27694e27U, 0xb2cd7fb2U, 0x759fea75U,
+    0x091b1209U, 0x839e1d83U, 0x2c74582cU, 0x1a2e341aU,
+    0x1b2d361bU, 0x6eb2dc6eU, 0x5aeeb45aU, 0xa0fb5ba0U,
+    0x52f6a452U, 0x3b4d763bU, 0xd661b7d6U, 0xb3ce7db3U,
+    0x297b5229U, 0xe33edde3U, 0x2f715e2fU, 0x84971384U,
+    0x53f5a653U, 0xd168b9d1U, 0x00000000U, 0xed2cc1edU,
+    0x20604020U, 0xfc1fe3fcU, 0xb1c879b1U, 0x5bedb65bU,
+    0x6abed46aU, 0xcb468dcbU, 0xbed967beU, 0x394b7239U,
+    0x4ade944aU, 0x4cd4984cU, 0x58e8b058U, 0xcf4a85cfU,
+    0xd06bbbd0U, 0xef2ac5efU, 0xaae54faaU, 0xfb16edfbU,
+    0x43c58643U, 0x4dd79a4dU, 0x33556633U, 0x85941185U,
+    0x45cf8a45U, 0xf910e9f9U, 0x02060402U, 0x7f81fe7fU,
+    0x50f0a050U, 0x3c44783cU, 0x9fba259fU, 0xa8e34ba8U,
+    0x51f3a251U, 0xa3fe5da3U, 0x40c08040U, 0x8f8a058fU,
+    0x92ad3f92U, 0x9dbc219dU, 0x38487038U, 0xf504f1f5U,
+    0xbcdf63bcU, 0xb6c177b6U, 0xda75afdaU, 0x21634221U,
+    0x10302010U, 0xff1ae5ffU, 0xf30efdf3U, 0xd26dbfd2U,
+    0xcd4c81cdU, 0x0c14180cU, 0x13352613U, 0xec2fc3ecU,
+    0x5fe1be5fU, 0x97a23597U, 0x44cc8844U, 0x17392e17U,
+    0xc45793c4U, 0xa7f255a7U, 0x7e82fc7eU, 0x3d477a3dU,
+    0x64acc864U, 0x5de7ba5dU, 0x192b3219U, 0x7395e673U,
+    0x60a0c060U, 0x81981981U, 0x4fd19e4fU, 0xdc7fa3dcU,
+    0x22664422U, 0x2a7e542aU, 0x90ab3b90U, 0x88830b88U,
+    0x46ca8c46U, 0xee29c7eeU, 0xb8d36bb8U, 0x143c2814U,
+    0xde79a7deU, 0x5ee2bc5eU, 0x0b1d160bU, 0xdb76addbU,
+    0xe03bdbe0U, 0x32566432U, 0x3a4e743aU, 0x0a1e140aU,
+    0x49db9249U, 0x060a0c06U, 0x246c4824U, 0x5ce4b85cU,
+    0xc25d9fc2U, 0xd36ebdd3U, 0xacef43acU, 0x62a6c462U,
+    0x91a83991U, 0x95a43195U, 0xe437d3e4U, 0x798bf279U,
+    0xe732d5e7U, 0xc8438bc8U, 0x37596e37U, 0x6db7da6dU,
+    0x8d8c018dU, 0xd564b1d5U, 0x4ed29c4eU, 0xa9e049a9U,
+    0x6cb4d86cU, 0x56faac56U, 0xf407f3f4U, 0xea25cfeaU,
+    0x65afca65U, 0x7a8ef47aU, 0xaee947aeU, 0x08181008U,
+    0xbad56fbaU, 0x7888f078U, 0x256f4a25U, 0x2e725c2eU,
+    0x1c24381cU, 0xa6f157a6U, 0xb4c773b4U, 0xc65197c6U,
+    0xe823cbe8U, 0xdd7ca1ddU, 0x749ce874U, 0x1f213e1fU,
+    0x4bdd964bU, 0xbddc61bdU, 0x8b860d8bU, 0x8a850f8aU,
+    0x7090e070U, 0x3e427c3eU, 0xb5c471b5U, 0x66aacc66U,
+    0x48d89048U, 0x03050603U, 0xf601f7f6U, 0x0e121c0eU,
+    0x61a3c261U, 0x355f6a35U, 0x57f9ae57U, 0xb9d069b9U,
+    0x86911786U, 0xc15899c1U, 0x1d273a1dU, 0x9eb9279eU,
+    0xe138d9e1U, 0xf813ebf8U, 0x98b32b98U, 0x11332211U,
+    0x69bbd269U, 0xd970a9d9U, 0x8e89078eU, 0x94a73394U,
+    0x9bb62d9bU, 0x1e223c1eU, 0x87921587U, 0xe920c9e9U,
+    0xce4987ceU, 0x55ffaa55U, 0x28785028U, 0xdf7aa5dfU,
+    0x8c8f038cU, 0xa1f859a1U, 0x89800989U, 0x0d171a0dU,
+    0xbfda65bfU, 0xe631d7e6U, 0x42c68442U, 0x68b8d068U,
+    0x41c38241U, 0x99b02999U, 0x2d775a2dU, 0x0f111e0fU,
+    0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
+};
+const u32 Te3[256] /* ICACHE_RODATA_ATTR */ = {
+
+    0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
+    0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
+    0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
+    0xfefe19e7U, 0xd7d762b5U, 0xababe64dU, 0x76769aecU,
+    0xcaca458fU, 0x82829d1fU, 0xc9c94089U, 0x7d7d87faU,
+    0xfafa15efU, 0x5959ebb2U, 0x4747c98eU, 0xf0f00bfbU,
+    0xadadec41U, 0xd4d467b3U, 0xa2a2fd5fU, 0xafafea45U,
+    0x9c9cbf23U, 0xa4a4f753U, 0x727296e4U, 0xc0c05b9bU,
+    0xb7b7c275U, 0xfdfd1ce1U, 0x9393ae3dU, 0x26266a4cU,
+    0x36365a6cU, 0x3f3f417eU, 0xf7f702f5U, 0xcccc4f83U,
+    0x34345c68U, 0xa5a5f451U, 0xe5e534d1U, 0xf1f108f9U,
+    0x717193e2U, 0xd8d873abU, 0x31315362U, 0x15153f2aU,
+    0x04040c08U, 0xc7c75295U, 0x23236546U, 0xc3c35e9dU,
+    0x18182830U, 0x9696a137U, 0x05050f0aU, 0x9a9ab52fU,
+    0x0707090eU, 0x12123624U, 0x80809b1bU, 0xe2e23ddfU,
+    0xebeb26cdU, 0x2727694eU, 0xb2b2cd7fU, 0x75759feaU,
+    0x09091b12U, 0x83839e1dU, 0x2c2c7458U, 0x1a1a2e34U,
+    0x1b1b2d36U, 0x6e6eb2dcU, 0x5a5aeeb4U, 0xa0a0fb5bU,
+    0x5252f6a4U, 0x3b3b4d76U, 0xd6d661b7U, 0xb3b3ce7dU,
+    0x29297b52U, 0xe3e33eddU, 0x2f2f715eU, 0x84849713U,
+    0x5353f5a6U, 0xd1d168b9U, 0x00000000U, 0xeded2cc1U,
+    0x20206040U, 0xfcfc1fe3U, 0xb1b1c879U, 0x5b5bedb6U,
+    0x6a6abed4U, 0xcbcb468dU, 0xbebed967U, 0x39394b72U,
+    0x4a4ade94U, 0x4c4cd498U, 0x5858e8b0U, 0xcfcf4a85U,
+    0xd0d06bbbU, 0xefef2ac5U, 0xaaaae54fU, 0xfbfb16edU,
+    0x4343c586U, 0x4d4dd79aU, 0x33335566U, 0x85859411U,
+    0x4545cf8aU, 0xf9f910e9U, 0x02020604U, 0x7f7f81feU,
+    0x5050f0a0U, 0x3c3c4478U, 0x9f9fba25U, 0xa8a8e34bU,
+    0x5151f3a2U, 0xa3a3fe5dU, 0x4040c080U, 0x8f8f8a05U,
+    0x9292ad3fU, 0x9d9dbc21U, 0x38384870U, 0xf5f504f1U,
+    0xbcbcdf63U, 0xb6b6c177U, 0xdada75afU, 0x21216342U,
+    0x10103020U, 0xffff1ae5U, 0xf3f30efdU, 0xd2d26dbfU,
+    0xcdcd4c81U, 0x0c0c1418U, 0x13133526U, 0xecec2fc3U,
+    0x5f5fe1beU, 0x9797a235U, 0x4444cc88U, 0x1717392eU,
+    0xc4c45793U, 0xa7a7f255U, 0x7e7e82fcU, 0x3d3d477aU,
+    0x6464acc8U, 0x5d5de7baU, 0x19192b32U, 0x737395e6U,
+    0x6060a0c0U, 0x81819819U, 0x4f4fd19eU, 0xdcdc7fa3U,
+    0x22226644U, 0x2a2a7e54U, 0x9090ab3bU, 0x8888830bU,
+    0x4646ca8cU, 0xeeee29c7U, 0xb8b8d36bU, 0x14143c28U,
+    0xdede79a7U, 0x5e5ee2bcU, 0x0b0b1d16U, 0xdbdb76adU,
+    0xe0e03bdbU, 0x32325664U, 0x3a3a4e74U, 0x0a0a1e14U,
+    0x4949db92U, 0x06060a0cU, 0x24246c48U, 0x5c5ce4b8U,
+    0xc2c25d9fU, 0xd3d36ebdU, 0xacacef43U, 0x6262a6c4U,
+    0x9191a839U, 0x9595a431U, 0xe4e437d3U, 0x79798bf2U,
+    0xe7e732d5U, 0xc8c8438bU, 0x3737596eU, 0x6d6db7daU,
+    0x8d8d8c01U, 0xd5d564b1U, 0x4e4ed29cU, 0xa9a9e049U,
+    0x6c6cb4d8U, 0x5656faacU, 0xf4f407f3U, 0xeaea25cfU,
+    0x6565afcaU, 0x7a7a8ef4U, 0xaeaee947U, 0x08081810U,
+    0xbabad56fU, 0x787888f0U, 0x25256f4aU, 0x2e2e725cU,
+    0x1c1c2438U, 0xa6a6f157U, 0xb4b4c773U, 0xc6c65197U,
+    0xe8e823cbU, 0xdddd7ca1U, 0x74749ce8U, 0x1f1f213eU,
+    0x4b4bdd96U, 0xbdbddc61U, 0x8b8b860dU, 0x8a8a850fU,
+    0x707090e0U, 0x3e3e427cU, 0xb5b5c471U, 0x6666aaccU,
+    0x4848d890U, 0x03030506U, 0xf6f601f7U, 0x0e0e121cU,
+    0x6161a3c2U, 0x35355f6aU, 0x5757f9aeU, 0xb9b9d069U,
+    0x86869117U, 0xc1c15899U, 0x1d1d273aU, 0x9e9eb927U,
+    0xe1e138d9U, 0xf8f813ebU, 0x9898b32bU, 0x11113322U,
+    0x6969bbd2U, 0xd9d970a9U, 0x8e8e8907U, 0x9494a733U,
+    0x9b9bb62dU, 0x1e1e223cU, 0x87879215U, 0xe9e920c9U,
+    0xcece4987U, 0x5555ffaaU, 0x28287850U, 0xdfdf7aa5U,
+    0x8c8c8f03U, 0xa1a1f859U, 0x89898009U, 0x0d0d171aU,
+    0xbfbfda65U, 0xe6e631d7U, 0x4242c684U, 0x6868b8d0U,
+    0x4141c382U, 0x9999b029U, 0x2d2d775aU, 0x0f0f111eU,
+    0xb0b0cb7bU, 0x5454fca8U, 0xbbbbd66dU, 0x16163a2cU,
+};
+const u32 Te4[256] /* ICACHE_RODATA_ATTR */ = {
+    0x63636363U, 0x7c7c7c7cU, 0x77777777U, 0x7b7b7b7bU,
+    0xf2f2f2f2U, 0x6b6b6b6bU, 0x6f6f6f6fU, 0xc5c5c5c5U,
+    0x30303030U, 0x01010101U, 0x67676767U, 0x2b2b2b2bU,
+    0xfefefefeU, 0xd7d7d7d7U, 0xababababU, 0x76767676U,
+    0xcacacacaU, 0x82828282U, 0xc9c9c9c9U, 0x7d7d7d7dU,
+    0xfafafafaU, 0x59595959U, 0x47474747U, 0xf0f0f0f0U,
+    0xadadadadU, 0xd4d4d4d4U, 0xa2a2a2a2U, 0xafafafafU,
+    0x9c9c9c9cU, 0xa4a4a4a4U, 0x72727272U, 0xc0c0c0c0U,
+    0xb7b7b7b7U, 0xfdfdfdfdU, 0x93939393U, 0x26262626U,
+    0x36363636U, 0x3f3f3f3fU, 0xf7f7f7f7U, 0xccccccccU,
+    0x34343434U, 0xa5a5a5a5U, 0xe5e5e5e5U, 0xf1f1f1f1U,
+    0x71717171U, 0xd8d8d8d8U, 0x31313131U, 0x15151515U,
+    0x04040404U, 0xc7c7c7c7U, 0x23232323U, 0xc3c3c3c3U,
+    0x18181818U, 0x96969696U, 0x05050505U, 0x9a9a9a9aU,
+    0x07070707U, 0x12121212U, 0x80808080U, 0xe2e2e2e2U,
+    0xebebebebU, 0x27272727U, 0xb2b2b2b2U, 0x75757575U,
+    0x09090909U, 0x83838383U, 0x2c2c2c2cU, 0x1a1a1a1aU,
+    0x1b1b1b1bU, 0x6e6e6e6eU, 0x5a5a5a5aU, 0xa0a0a0a0U,
+    0x52525252U, 0x3b3b3b3bU, 0xd6d6d6d6U, 0xb3b3b3b3U,
+    0x29292929U, 0xe3e3e3e3U, 0x2f2f2f2fU, 0x84848484U,
+    0x53535353U, 0xd1d1d1d1U, 0x00000000U, 0xededededU,
+    0x20202020U, 0xfcfcfcfcU, 0xb1b1b1b1U, 0x5b5b5b5bU,
+    0x6a6a6a6aU, 0xcbcbcbcbU, 0xbebebebeU, 0x39393939U,
+    0x4a4a4a4aU, 0x4c4c4c4cU, 0x58585858U, 0xcfcfcfcfU,
+    0xd0d0d0d0U, 0xefefefefU, 0xaaaaaaaaU, 0xfbfbfbfbU,
+    0x43434343U, 0x4d4d4d4dU, 0x33333333U, 0x85858585U,
+    0x45454545U, 0xf9f9f9f9U, 0x02020202U, 0x7f7f7f7fU,
+    0x50505050U, 0x3c3c3c3cU, 0x9f9f9f9fU, 0xa8a8a8a8U,
+    0x51515151U, 0xa3a3a3a3U, 0x40404040U, 0x8f8f8f8fU,
+    0x92929292U, 0x9d9d9d9dU, 0x38383838U, 0xf5f5f5f5U,
+    0xbcbcbcbcU, 0xb6b6b6b6U, 0xdadadadaU, 0x21212121U,
+    0x10101010U, 0xffffffffU, 0xf3f3f3f3U, 0xd2d2d2d2U,
+    0xcdcdcdcdU, 0x0c0c0c0cU, 0x13131313U, 0xececececU,
+    0x5f5f5f5fU, 0x97979797U, 0x44444444U, 0x17171717U,
+    0xc4c4c4c4U, 0xa7a7a7a7U, 0x7e7e7e7eU, 0x3d3d3d3dU,
+    0x64646464U, 0x5d5d5d5dU, 0x19191919U, 0x73737373U,
+    0x60606060U, 0x81818181U, 0x4f4f4f4fU, 0xdcdcdcdcU,
+    0x22222222U, 0x2a2a2a2aU, 0x90909090U, 0x88888888U,
+    0x46464646U, 0xeeeeeeeeU, 0xb8b8b8b8U, 0x14141414U,
+    0xdedededeU, 0x5e5e5e5eU, 0x0b0b0b0bU, 0xdbdbdbdbU,
+    0xe0e0e0e0U, 0x32323232U, 0x3a3a3a3aU, 0x0a0a0a0aU,
+    0x49494949U, 0x06060606U, 0x24242424U, 0x5c5c5c5cU,
+    0xc2c2c2c2U, 0xd3d3d3d3U, 0xacacacacU, 0x62626262U,
+    0x91919191U, 0x95959595U, 0xe4e4e4e4U, 0x79797979U,
+    0xe7e7e7e7U, 0xc8c8c8c8U, 0x37373737U, 0x6d6d6d6dU,
+    0x8d8d8d8dU, 0xd5d5d5d5U, 0x4e4e4e4eU, 0xa9a9a9a9U,
+    0x6c6c6c6cU, 0x56565656U, 0xf4f4f4f4U, 0xeaeaeaeaU,
+    0x65656565U, 0x7a7a7a7aU, 0xaeaeaeaeU, 0x08080808U,
+    0xbabababaU, 0x78787878U, 0x25252525U, 0x2e2e2e2eU,
+    0x1c1c1c1cU, 0xa6a6a6a6U, 0xb4b4b4b4U, 0xc6c6c6c6U,
+    0xe8e8e8e8U, 0xddddddddU, 0x74747474U, 0x1f1f1f1fU,
+    0x4b4b4b4bU, 0xbdbdbdbdU, 0x8b8b8b8bU, 0x8a8a8a8aU,
+    0x70707070U, 0x3e3e3e3eU, 0xb5b5b5b5U, 0x66666666U,
+    0x48484848U, 0x03030303U, 0xf6f6f6f6U, 0x0e0e0e0eU,
+    0x61616161U, 0x35353535U, 0x57575757U, 0xb9b9b9b9U,
+    0x86868686U, 0xc1c1c1c1U, 0x1d1d1d1dU, 0x9e9e9e9eU,
+    0xe1e1e1e1U, 0xf8f8f8f8U, 0x98989898U, 0x11111111U,
+    0x69696969U, 0xd9d9d9d9U, 0x8e8e8e8eU, 0x94949494U,
+    0x9b9b9b9bU, 0x1e1e1e1eU, 0x87878787U, 0xe9e9e9e9U,
+    0xcecececeU, 0x55555555U, 0x28282828U, 0xdfdfdfdfU,
+    0x8c8c8c8cU, 0xa1a1a1a1U, 0x89898989U, 0x0d0d0d0dU,
+    0xbfbfbfbfU, 0xe6e6e6e6U, 0x42424242U, 0x68686868U,
+    0x41414141U, 0x99999999U, 0x2d2d2d2dU, 0x0f0f0f0fU,
+    0xb0b0b0b0U, 0x54545454U, 0xbbbbbbbbU, 0x16161616U,
+};
+#endif /* AES_SMALL_TABLES */
+const u32 Td0[256] /* ICACHE_RODATA_ATTR */ = {
+    0x51f4a750U, 0x7e416553U, 0x1a17a4c3U, 0x3a275e96U,
+    0x3bab6bcbU, 0x1f9d45f1U, 0xacfa58abU, 0x4be30393U,
+    0x2030fa55U, 0xad766df6U, 0x88cc7691U, 0xf5024c25U,
+    0x4fe5d7fcU, 0xc52acbd7U, 0x26354480U, 0xb562a38fU,
+    0xdeb15a49U, 0x25ba1b67U, 0x45ea0e98U, 0x5dfec0e1U,
+    0xc32f7502U, 0x814cf012U, 0x8d4697a3U, 0x6bd3f9c6U,
+    0x038f5fe7U, 0x15929c95U, 0xbf6d7aebU, 0x955259daU,
+    0xd4be832dU, 0x587421d3U, 0x49e06929U, 0x8ec9c844U,
+    0x75c2896aU, 0xf48e7978U, 0x99583e6bU, 0x27b971ddU,
+    0xbee14fb6U, 0xf088ad17U, 0xc920ac66U, 0x7dce3ab4U,
+    0x63df4a18U, 0xe51a3182U, 0x97513360U, 0x62537f45U,
+    0xb16477e0U, 0xbb6bae84U, 0xfe81a01cU, 0xf9082b94U,
+    0x70486858U, 0x8f45fd19U, 0x94de6c87U, 0x527bf8b7U,
+    0xab73d323U, 0x724b02e2U, 0xe31f8f57U, 0x6655ab2aU,
+    0xb2eb2807U, 0x2fb5c203U, 0x86c57b9aU, 0xd33708a5U,
+    0x302887f2U, 0x23bfa5b2U, 0x02036abaU, 0xed16825cU,
+    0x8acf1c2bU, 0xa779b492U, 0xf307f2f0U, 0x4e69e2a1U,
+    0x65daf4cdU, 0x0605bed5U, 0xd134621fU, 0xc4a6fe8aU,
+    0x342e539dU, 0xa2f355a0U, 0x058ae132U, 0xa4f6eb75U,
+    0x0b83ec39U, 0x4060efaaU, 0x5e719f06U, 0xbd6e1051U,
+    0x3e218af9U, 0x96dd063dU, 0xdd3e05aeU, 0x4de6bd46U,
+    0x91548db5U, 0x71c45d05U, 0x0406d46fU, 0x605015ffU,
+    0x1998fb24U, 0xd6bde997U, 0x894043ccU, 0x67d99e77U,
+    0xb0e842bdU, 0x07898b88U, 0xe7195b38U, 0x79c8eedbU,
+    0xa17c0a47U, 0x7c420fe9U, 0xf8841ec9U, 0x00000000U,
+    0x09808683U, 0x322bed48U, 0x1e1170acU, 0x6c5a724eU,
+    0xfd0efffbU, 0x0f853856U, 0x3daed51eU, 0x362d3927U,
+    0x0a0fd964U, 0x685ca621U, 0x9b5b54d1U, 0x24362e3aU,
+    0x0c0a67b1U, 0x9357e70fU, 0xb4ee96d2U, 0x1b9b919eU,
+    0x80c0c54fU, 0x61dc20a2U, 0x5a774b69U, 0x1c121a16U,
+    0xe293ba0aU, 0xc0a02ae5U, 0x3c22e043U, 0x121b171dU,
+    0x0e090d0bU, 0xf28bc7adU, 0x2db6a8b9U, 0x141ea9c8U,
+    0x57f11985U, 0xaf75074cU, 0xee99ddbbU, 0xa37f60fdU,
+    0xf701269fU, 0x5c72f5bcU, 0x44663bc5U, 0x5bfb7e34U,
+    0x8b432976U, 0xcb23c6dcU, 0xb6edfc68U, 0xb8e4f163U,
+    0xd731dccaU, 0x42638510U, 0x13972240U, 0x84c61120U,
+    0x854a247dU, 0xd2bb3df8U, 0xaef93211U, 0xc729a16dU,
+    0x1d9e2f4bU, 0xdcb230f3U, 0x0d8652ecU, 0x77c1e3d0U,
+    0x2bb3166cU, 0xa970b999U, 0x119448faU, 0x47e96422U,
+    0xa8fc8cc4U, 0xa0f03f1aU, 0x567d2cd8U, 0x223390efU,
+    0x87494ec7U, 0xd938d1c1U, 0x8ccaa2feU, 0x98d40b36U,
+    0xa6f581cfU, 0xa57ade28U, 0xdab78e26U, 0x3fadbfa4U,
+    0x2c3a9de4U, 0x5078920dU, 0x6a5fcc9bU, 0x547e4662U,
+    0xf68d13c2U, 0x90d8b8e8U, 0x2e39f75eU, 0x82c3aff5U,
+    0x9f5d80beU, 0x69d0937cU, 0x6fd52da9U, 0xcf2512b3U,
+    0xc8ac993bU, 0x10187da7U, 0xe89c636eU, 0xdb3bbb7bU,
+    0xcd267809U, 0x6e5918f4U, 0xec9ab701U, 0x834f9aa8U,
+    0xe6956e65U, 0xaaffe67eU, 0x21bccf08U, 0xef15e8e6U,
+    0xbae79bd9U, 0x4a6f36ceU, 0xea9f09d4U, 0x29b07cd6U,
+    0x31a4b2afU, 0x2a3f2331U, 0xc6a59430U, 0x35a266c0U,
+    0x744ebc37U, 0xfc82caa6U, 0xe090d0b0U, 0x33a7d815U,
+    0xf104984aU, 0x41ecdaf7U, 0x7fcd500eU, 0x1791f62fU,
+    0x764dd68dU, 0x43efb04dU, 0xccaa4d54U, 0xe49604dfU,
+    0x9ed1b5e3U, 0x4c6a881bU, 0xc12c1fb8U, 0x4665517fU,
+    0x9d5eea04U, 0x018c355dU, 0xfa877473U, 0xfb0b412eU,
+    0xb3671d5aU, 0x92dbd252U, 0xe9105633U, 0x6dd64713U,
+    0x9ad7618cU, 0x37a10c7aU, 0x59f8148eU, 0xeb133c89U,
+    0xcea927eeU, 0xb761c935U, 0xe11ce5edU, 0x7a47b13cU,
+    0x9cd2df59U, 0x55f2733fU, 0x1814ce79U, 0x73c737bfU,
+    0x53f7cdeaU, 0x5ffdaa5bU, 0xdf3d6f14U, 0x7844db86U,
+    0xcaaff381U, 0xb968c43eU, 0x3824342cU, 0xc2a3405fU,
+    0x161dc372U, 0xbce2250cU, 0x283c498bU, 0xff0d9541U,
+    0x39a80171U, 0x080cb3deU, 0xd8b4e49cU, 0x6456c190U,
+    0x7bcb8461U, 0xd532b670U, 0x486c5c74U, 0xd0b85742U,
+};
+#ifndef AES_SMALL_TABLES
+const u32 Td1[256] /* ICACHE_RODATA_ATTR */ = {
+    0x5051f4a7U, 0x537e4165U, 0xc31a17a4U, 0x963a275eU,
+    0xcb3bab6bU, 0xf11f9d45U, 0xabacfa58U, 0x934be303U,
+    0x552030faU, 0xf6ad766dU, 0x9188cc76U, 0x25f5024cU,
+    0xfc4fe5d7U, 0xd7c52acbU, 0x80263544U, 0x8fb562a3U,
+    0x49deb15aU, 0x6725ba1bU, 0x9845ea0eU, 0xe15dfec0U,
+    0x02c32f75U, 0x12814cf0U, 0xa38d4697U, 0xc66bd3f9U,
+    0xe7038f5fU, 0x9515929cU, 0xebbf6d7aU, 0xda955259U,
+    0x2dd4be83U, 0xd3587421U, 0x2949e069U, 0x448ec9c8U,
+    0x6a75c289U, 0x78f48e79U, 0x6b99583eU, 0xdd27b971U,
+    0xb6bee14fU, 0x17f088adU, 0x66c920acU, 0xb47dce3aU,
+    0x1863df4aU, 0x82e51a31U, 0x60975133U, 0x4562537fU,
+    0xe0b16477U, 0x84bb6baeU, 0x1cfe81a0U, 0x94f9082bU,
+    0x58704868U, 0x198f45fdU, 0x8794de6cU, 0xb7527bf8U,
+    0x23ab73d3U, 0xe2724b02U, 0x57e31f8fU, 0x2a6655abU,
+    0x07b2eb28U, 0x032fb5c2U, 0x9a86c57bU, 0xa5d33708U,
+    0xf2302887U, 0xb223bfa5U, 0xba02036aU, 0x5ced1682U,
+    0x2b8acf1cU, 0x92a779b4U, 0xf0f307f2U, 0xa14e69e2U,
+    0xcd65daf4U, 0xd50605beU, 0x1fd13462U, 0x8ac4a6feU,
+    0x9d342e53U, 0xa0a2f355U, 0x32058ae1U, 0x75a4f6ebU,
+    0x390b83ecU, 0xaa4060efU, 0x065e719fU, 0x51bd6e10U,
+    0xf93e218aU, 0x3d96dd06U, 0xaedd3e05U, 0x464de6bdU,
+    0xb591548dU, 0x0571c45dU, 0x6f0406d4U, 0xff605015U,
+    0x241998fbU, 0x97d6bde9U, 0xcc894043U, 0x7767d99eU,
+    0xbdb0e842U, 0x8807898bU, 0x38e7195bU, 0xdb79c8eeU,
+    0x47a17c0aU, 0xe97c420fU, 0xc9f8841eU, 0x00000000U,
+    0x83098086U, 0x48322bedU, 0xac1e1170U, 0x4e6c5a72U,
+    0xfbfd0effU, 0x560f8538U, 0x1e3daed5U, 0x27362d39U,
+    0x640a0fd9U, 0x21685ca6U, 0xd19b5b54U, 0x3a24362eU,
+    0xb10c0a67U, 0x0f9357e7U, 0xd2b4ee96U, 0x9e1b9b91U,
+    0x4f80c0c5U, 0xa261dc20U, 0x695a774bU, 0x161c121aU,
+    0x0ae293baU, 0xe5c0a02aU, 0x433c22e0U, 0x1d121b17U,
+    0x0b0e090dU, 0xadf28bc7U, 0xb92db6a8U, 0xc8141ea9U,
+    0x8557f119U, 0x4caf7507U, 0xbbee99ddU, 0xfda37f60U,
+    0x9ff70126U, 0xbc5c72f5U, 0xc544663bU, 0x345bfb7eU,
+    0x768b4329U, 0xdccb23c6U, 0x68b6edfcU, 0x63b8e4f1U,
+    0xcad731dcU, 0x10426385U, 0x40139722U, 0x2084c611U,
+    0x7d854a24U, 0xf8d2bb3dU, 0x11aef932U, 0x6dc729a1U,
+    0x4b1d9e2fU, 0xf3dcb230U, 0xec0d8652U, 0xd077c1e3U,
+    0x6c2bb316U, 0x99a970b9U, 0xfa119448U, 0x2247e964U,
+    0xc4a8fc8cU, 0x1aa0f03fU, 0xd8567d2cU, 0xef223390U,
+    0xc787494eU, 0xc1d938d1U, 0xfe8ccaa2U, 0x3698d40bU,
+    0xcfa6f581U, 0x28a57adeU, 0x26dab78eU, 0xa43fadbfU,
+    0xe42c3a9dU, 0x0d507892U, 0x9b6a5fccU, 0x62547e46U,
+    0xc2f68d13U, 0xe890d8b8U, 0x5e2e39f7U, 0xf582c3afU,
+    0xbe9f5d80U, 0x7c69d093U, 0xa96fd52dU, 0xb3cf2512U,
+    0x3bc8ac99U, 0xa710187dU, 0x6ee89c63U, 0x7bdb3bbbU,
+    0x09cd2678U, 0xf46e5918U, 0x01ec9ab7U, 0xa8834f9aU,
+    0x65e6956eU, 0x7eaaffe6U, 0x0821bccfU, 0xe6ef15e8U,
+    0xd9bae79bU, 0xce4a6f36U, 0xd4ea9f09U, 0xd629b07cU,
+    0xaf31a4b2U, 0x312a3f23U, 0x30c6a594U, 0xc035a266U,
+    0x37744ebcU, 0xa6fc82caU, 0xb0e090d0U, 0x1533a7d8U,
+    0x4af10498U, 0xf741ecdaU, 0x0e7fcd50U, 0x2f1791f6U,
+    0x8d764dd6U, 0x4d43efb0U, 0x54ccaa4dU, 0xdfe49604U,
+    0xe39ed1b5U, 0x1b4c6a88U, 0xb8c12c1fU, 0x7f466551U,
+    0x049d5eeaU, 0x5d018c35U, 0x73fa8774U, 0x2efb0b41U,
+    0x5ab3671dU, 0x5292dbd2U, 0x33e91056U, 0x136dd647U,
+    0x8c9ad761U, 0x7a37a10cU, 0x8e59f814U, 0x89eb133cU,
+    0xeecea927U, 0x35b761c9U, 0xede11ce5U, 0x3c7a47b1U,
+    0x599cd2dfU, 0x3f55f273U, 0x791814ceU, 0xbf73c737U,
+    0xea53f7cdU, 0x5b5ffdaaU, 0x14df3d6fU, 0x867844dbU,
+    0x81caaff3U, 0x3eb968c4U, 0x2c382434U, 0x5fc2a340U,
+    0x72161dc3U, 0x0cbce225U, 0x8b283c49U, 0x41ff0d95U,
+    0x7139a801U, 0xde080cb3U, 0x9cd8b4e4U, 0x906456c1U,
+    0x617bcb84U, 0x70d532b6U, 0x74486c5cU, 0x42d0b857U,
+};
+const u32 Td2[256] /* ICACHE_RODATA_ATTR */ = {
+    0xa75051f4U, 0x65537e41U, 0xa4c31a17U, 0x5e963a27U,
+    0x6bcb3babU, 0x45f11f9dU, 0x58abacfaU, 0x03934be3U,
+    0xfa552030U, 0x6df6ad76U, 0x769188ccU, 0x4c25f502U,
+    0xd7fc4fe5U, 0xcbd7c52aU, 0x44802635U, 0xa38fb562U,
+    0x5a49deb1U, 0x1b6725baU, 0x0e9845eaU, 0xc0e15dfeU,
+    0x7502c32fU, 0xf012814cU, 0x97a38d46U, 0xf9c66bd3U,
+    0x5fe7038fU, 0x9c951592U, 0x7aebbf6dU, 0x59da9552U,
+    0x832dd4beU, 0x21d35874U, 0x692949e0U, 0xc8448ec9U,
+    0x896a75c2U, 0x7978f48eU, 0x3e6b9958U, 0x71dd27b9U,
+    0x4fb6bee1U, 0xad17f088U, 0xac66c920U, 0x3ab47dceU,
+    0x4a1863dfU, 0x3182e51aU, 0x33609751U, 0x7f456253U,
+    0x77e0b164U, 0xae84bb6bU, 0xa01cfe81U, 0x2b94f908U,
+    0x68587048U, 0xfd198f45U, 0x6c8794deU, 0xf8b7527bU,
+    0xd323ab73U, 0x02e2724bU, 0x8f57e31fU, 0xab2a6655U,
+    0x2807b2ebU, 0xc2032fb5U, 0x7b9a86c5U, 0x08a5d337U,
+    0x87f23028U, 0xa5b223bfU, 0x6aba0203U, 0x825ced16U,
+    0x1c2b8acfU, 0xb492a779U, 0xf2f0f307U, 0xe2a14e69U,
+    0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
+    0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
+    0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
+
+    0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
+    0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
+    0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
+    0x42bdb0e8U, 0x8b880789U, 0x5b38e719U, 0xeedb79c8U,
+    0x0a47a17cU, 0x0fe97c42U, 0x1ec9f884U, 0x00000000U,
+    0x86830980U, 0xed48322bU, 0x70ac1e11U, 0x724e6c5aU,
+    0xfffbfd0eU, 0x38560f85U, 0xd51e3daeU, 0x3927362dU,
+    0xd9640a0fU, 0xa621685cU, 0x54d19b5bU, 0x2e3a2436U,
+    0x67b10c0aU, 0xe70f9357U, 0x96d2b4eeU, 0x919e1b9bU,
+    0xc54f80c0U, 0x20a261dcU, 0x4b695a77U, 0x1a161c12U,
+    0xba0ae293U, 0x2ae5c0a0U, 0xe0433c22U, 0x171d121bU,
+    0x0d0b0e09U, 0xc7adf28bU, 0xa8b92db6U, 0xa9c8141eU,
+    0x198557f1U, 0x074caf75U, 0xddbbee99U, 0x60fda37fU,
+    0x269ff701U, 0xf5bc5c72U, 0x3bc54466U, 0x7e345bfbU,
+    0x29768b43U, 0xc6dccb23U, 0xfc68b6edU, 0xf163b8e4U,
+    0xdccad731U, 0x85104263U, 0x22401397U, 0x112084c6U,
+    0x247d854aU, 0x3df8d2bbU, 0x3211aef9U, 0xa16dc729U,
+    0x2f4b1d9eU, 0x30f3dcb2U, 0x52ec0d86U, 0xe3d077c1U,
+    0x166c2bb3U, 0xb999a970U, 0x48fa1194U, 0x642247e9U,
+    0x8cc4a8fcU, 0x3f1aa0f0U, 0x2cd8567dU, 0x90ef2233U,
+    0x4ec78749U, 0xd1c1d938U, 0xa2fe8ccaU, 0x0b3698d4U,
+    0x81cfa6f5U, 0xde28a57aU, 0x8e26dab7U, 0xbfa43fadU,
+    0x9de42c3aU, 0x920d5078U, 0xcc9b6a5fU, 0x4662547eU,
+    0x13c2f68dU, 0xb8e890d8U, 0xf75e2e39U, 0xaff582c3U,
+    0x80be9f5dU, 0x937c69d0U, 0x2da96fd5U, 0x12b3cf25U,
+    0x993bc8acU, 0x7da71018U, 0x636ee89cU, 0xbb7bdb3bU,
+    0x7809cd26U, 0x18f46e59U, 0xb701ec9aU, 0x9aa8834fU,
+    0x6e65e695U, 0xe67eaaffU, 0xcf0821bcU, 0xe8e6ef15U,
+    0x9bd9bae7U, 0x36ce4a6fU, 0x09d4ea9fU, 0x7cd629b0U,
+    0xb2af31a4U, 0x23312a3fU, 0x9430c6a5U, 0x66c035a2U,
+    0xbc37744eU, 0xcaa6fc82U, 0xd0b0e090U, 0xd81533a7U,
+    0x984af104U, 0xdaf741ecU, 0x500e7fcdU, 0xf62f1791U,
+    0xd68d764dU, 0xb04d43efU, 0x4d54ccaaU, 0x04dfe496U,
+    0xb5e39ed1U, 0x881b4c6aU, 0x1fb8c12cU, 0x517f4665U,
+    0xea049d5eU, 0x355d018cU, 0x7473fa87U, 0x412efb0bU,
+    0x1d5ab367U, 0xd25292dbU, 0x5633e910U, 0x47136dd6U,
+    0x618c9ad7U, 0x0c7a37a1U, 0x148e59f8U, 0x3c89eb13U,
+    0x27eecea9U, 0xc935b761U, 0xe5ede11cU, 0xb13c7a47U,
+    0xdf599cd2U, 0x733f55f2U, 0xce791814U, 0x37bf73c7U,
+    0xcdea53f7U, 0xaa5b5ffdU, 0x6f14df3dU, 0xdb867844U,
+    0xf381caafU, 0xc43eb968U, 0x342c3824U, 0x405fc2a3U,
+    0xc372161dU, 0x250cbce2U, 0x498b283cU, 0x9541ff0dU,
+    0x017139a8U, 0xb3de080cU, 0xe49cd8b4U, 0xc1906456U,
+    0x84617bcbU, 0xb670d532U, 0x5c74486cU, 0x5742d0b8U,
+};
+const u32 Td3[256] /* ICACHE_RODATA_ATTR */ = {
+    0xf4a75051U, 0x4165537eU, 0x17a4c31aU, 0x275e963aU,
+    0xab6bcb3bU, 0x9d45f11fU, 0xfa58abacU, 0xe303934bU,
+    0x30fa5520U, 0x766df6adU, 0xcc769188U, 0x024c25f5U,
+    0xe5d7fc4fU, 0x2acbd7c5U, 0x35448026U, 0x62a38fb5U,
+    0xb15a49deU, 0xba1b6725U, 0xea0e9845U, 0xfec0e15dU,
+    0x2f7502c3U, 0x4cf01281U, 0x4697a38dU, 0xd3f9c66bU,
+    0x8f5fe703U, 0x929c9515U, 0x6d7aebbfU, 0x5259da95U,
+    0xbe832dd4U, 0x7421d358U, 0xe0692949U, 0xc9c8448eU,
+    0xc2896a75U, 0x8e7978f4U, 0x583e6b99U, 0xb971dd27U,
+    0xe14fb6beU, 0x88ad17f0U, 0x20ac66c9U, 0xce3ab47dU,
+    0xdf4a1863U, 0x1a3182e5U, 0x51336097U, 0x537f4562U,
+    0x6477e0b1U, 0x6bae84bbU, 0x81a01cfeU, 0x082b94f9U,
+    0x48685870U, 0x45fd198fU, 0xde6c8794U, 0x7bf8b752U,
+    0x73d323abU, 0x4b02e272U, 0x1f8f57e3U, 0x55ab2a66U,
+    0xeb2807b2U, 0xb5c2032fU, 0xc57b9a86U, 0x3708a5d3U,
+    0x2887f230U, 0xbfa5b223U, 0x036aba02U, 0x16825cedU,
+    0xcf1c2b8aU, 0x79b492a7U, 0x07f2f0f3U, 0x69e2a14eU,
+    0xdaf4cd65U, 0x05bed506U, 0x34621fd1U, 0xa6fe8ac4U,
+    0x2e539d34U, 0xf355a0a2U, 0x8ae13205U, 0xf6eb75a4U,
+    0x83ec390bU, 0x60efaa40U, 0x719f065eU, 0x6e1051bdU,
+    0x218af93eU, 0xdd063d96U, 0x3e05aeddU, 0xe6bd464dU,
+    0x548db591U, 0xc45d0571U, 0x06d46f04U, 0x5015ff60U,
+    0x98fb2419U, 0xbde997d6U, 0x4043cc89U, 0xd99e7767U,
+    0xe842bdb0U, 0x898b8807U, 0x195b38e7U, 0xc8eedb79U,
+    0x7c0a47a1U, 0x420fe97cU, 0x841ec9f8U, 0x00000000U,
+    0x80868309U, 0x2bed4832U, 0x1170ac1eU, 0x5a724e6cU,
+    0x0efffbfdU, 0x8538560fU, 0xaed51e3dU, 0x2d392736U,
+    0x0fd9640aU, 0x5ca62168U, 0x5b54d19bU, 0x362e3a24U,
+    0x0a67b10cU, 0x57e70f93U, 0xee96d2b4U, 0x9b919e1bU,
+    0xc0c54f80U, 0xdc20a261U, 0x774b695aU, 0x121a161cU,
+    0x93ba0ae2U, 0xa02ae5c0U, 0x22e0433cU, 0x1b171d12U,
+    0x090d0b0eU, 0x8bc7adf2U, 0xb6a8b92dU, 0x1ea9c814U,
+    0xf1198557U, 0x75074cafU, 0x99ddbbeeU, 0x7f60fda3U,
+    0x01269ff7U, 0x72f5bc5cU, 0x663bc544U, 0xfb7e345bU,
+    0x4329768bU, 0x23c6dccbU, 0xedfc68b6U, 0xe4f163b8U,
+    0x31dccad7U, 0x63851042U, 0x97224013U, 0xc6112084U,
+    0x4a247d85U, 0xbb3df8d2U, 0xf93211aeU, 0x29a16dc7U,
+    0x9e2f4b1dU, 0xb230f3dcU, 0x8652ec0dU, 0xc1e3d077U,
+    0xb3166c2bU, 0x70b999a9U, 0x9448fa11U, 0xe9642247U,
+    0xfc8cc4a8U, 0xf03f1aa0U, 0x7d2cd856U, 0x3390ef22U,
+    0x494ec787U, 0x38d1c1d9U, 0xcaa2fe8cU, 0xd40b3698U,
+    0xf581cfa6U, 0x7ade28a5U, 0xb78e26daU, 0xadbfa43fU,
+    0x3a9de42cU, 0x78920d50U, 0x5fcc9b6aU, 0x7e466254U,
+    0x8d13c2f6U, 0xd8b8e890U, 0x39f75e2eU, 0xc3aff582U,
+    0x5d80be9fU, 0xd0937c69U, 0xd52da96fU, 0x2512b3cfU,
+    0xac993bc8U, 0x187da710U, 0x9c636ee8U, 0x3bbb7bdbU,
+    0x267809cdU, 0x5918f46eU, 0x9ab701ecU, 0x4f9aa883U,
+    0x956e65e6U, 0xffe67eaaU, 0xbccf0821U, 0x15e8e6efU,
+    0xe79bd9baU, 0x6f36ce4aU, 0x9f09d4eaU, 0xb07cd629U,
+    0xa4b2af31U, 0x3f23312aU, 0xa59430c6U, 0xa266c035U,
+    0x4ebc3774U, 0x82caa6fcU, 0x90d0b0e0U, 0xa7d81533U,
+    0x04984af1U, 0xecdaf741U, 0xcd500e7fU, 0x91f62f17U,
+    0x4dd68d76U, 0xefb04d43U, 0xaa4d54ccU, 0x9604dfe4U,
+    0xd1b5e39eU, 0x6a881b4cU, 0x2c1fb8c1U, 0x65517f46U,
+    0x5eea049dU, 0x8c355d01U, 0x877473faU, 0x0b412efbU,
+    0x671d5ab3U, 0xdbd25292U, 0x105633e9U, 0xd647136dU,
+    0xd7618c9aU, 0xa10c7a37U, 0xf8148e59U, 0x133c89ebU,
+    0xa927eeceU, 0x61c935b7U, 0x1ce5ede1U, 0x47b13c7aU,
+    0xd2df599cU, 0xf2733f55U, 0x14ce7918U, 0xc737bf73U,
+    0xf7cdea53U, 0xfdaa5b5fU, 0x3d6f14dfU, 0x44db8678U,
+    0xaff381caU, 0x68c43eb9U, 0x24342c38U, 0xa3405fc2U,
+    0x1dc37216U, 0xe2250cbcU, 0x3c498b28U, 0x0d9541ffU,
+    0xa8017139U, 0x0cb3de08U, 0xb4e49cd8U, 0x56c19064U,
+    0xcb84617bU, 0x32b670d5U, 0x6c5c7448U, 0xb85742d0U,
+};
+const u32 Td4[256] /* ICACHE_RODATA_ATTR */ = {
+    0x52525252U, 0x09090909U, 0x6a6a6a6aU, 0xd5d5d5d5U,
+    0x30303030U, 0x36363636U, 0xa5a5a5a5U, 0x38383838U,
+    0xbfbfbfbfU, 0x40404040U, 0xa3a3a3a3U, 0x9e9e9e9eU,
+    0x81818181U, 0xf3f3f3f3U, 0xd7d7d7d7U, 0xfbfbfbfbU,
+    0x7c7c7c7cU, 0xe3e3e3e3U, 0x39393939U, 0x82828282U,
+    0x9b9b9b9bU, 0x2f2f2f2fU, 0xffffffffU, 0x87878787U,
+    0x34343434U, 0x8e8e8e8eU, 0x43434343U, 0x44444444U,
+    0xc4c4c4c4U, 0xdedededeU, 0xe9e9e9e9U, 0xcbcbcbcbU,
+    0x54545454U, 0x7b7b7b7bU, 0x94949494U, 0x32323232U,
+    0xa6a6a6a6U, 0xc2c2c2c2U, 0x23232323U, 0x3d3d3d3dU,
+    0xeeeeeeeeU, 0x4c4c4c4cU, 0x95959595U, 0x0b0b0b0bU,
+    0x42424242U, 0xfafafafaU, 0xc3c3c3c3U, 0x4e4e4e4eU,
+    0x08080808U, 0x2e2e2e2eU, 0xa1a1a1a1U, 0x66666666U,
+    0x28282828U, 0xd9d9d9d9U, 0x24242424U, 0xb2b2b2b2U,
+    0x76767676U, 0x5b5b5b5bU, 0xa2a2a2a2U, 0x49494949U,
+    0x6d6d6d6dU, 0x8b8b8b8bU, 0xd1d1d1d1U, 0x25252525U,
+    0x72727272U, 0xf8f8f8f8U, 0xf6f6f6f6U, 0x64646464U,
+    0x86868686U, 0x68686868U, 0x98989898U, 0x16161616U,
+    0xd4d4d4d4U, 0xa4a4a4a4U, 0x5c5c5c5cU, 0xccccccccU,
+    0x5d5d5d5dU, 0x65656565U, 0xb6b6b6b6U, 0x92929292U,
+    0x6c6c6c6cU, 0x70707070U, 0x48484848U, 0x50505050U,
+    0xfdfdfdfdU, 0xededededU, 0xb9b9b9b9U, 0xdadadadaU,
+    0x5e5e5e5eU, 0x15151515U, 0x46464646U, 0x57575757U,
+    0xa7a7a7a7U, 0x8d8d8d8dU, 0x9d9d9d9dU, 0x84848484U,
+    0x90909090U, 0xd8d8d8d8U, 0xababababU, 0x00000000U,
+    0x8c8c8c8cU, 0xbcbcbcbcU, 0xd3d3d3d3U, 0x0a0a0a0aU,
+    0xf7f7f7f7U, 0xe4e4e4e4U, 0x58585858U, 0x05050505U,
+    0xb8b8b8b8U, 0xb3b3b3b3U, 0x45454545U, 0x06060606U,
+    0xd0d0d0d0U, 0x2c2c2c2cU, 0x1e1e1e1eU, 0x8f8f8f8fU,
+    0xcacacacaU, 0x3f3f3f3fU, 0x0f0f0f0fU, 0x02020202U,
+    0xc1c1c1c1U, 0xafafafafU, 0xbdbdbdbdU, 0x03030303U,
+    0x01010101U, 0x13131313U, 0x8a8a8a8aU, 0x6b6b6b6bU,
+    0x3a3a3a3aU, 0x91919191U, 0x11111111U, 0x41414141U,
+    0x4f4f4f4fU, 0x67676767U, 0xdcdcdcdcU, 0xeaeaeaeaU,
+    0x97979797U, 0xf2f2f2f2U, 0xcfcfcfcfU, 0xcecececeU,
+    0xf0f0f0f0U, 0xb4b4b4b4U, 0xe6e6e6e6U, 0x73737373U,
+    0x96969696U, 0xacacacacU, 0x74747474U, 0x22222222U,
+    0xe7e7e7e7U, 0xadadadadU, 0x35353535U, 0x85858585U,
+    0xe2e2e2e2U, 0xf9f9f9f9U, 0x37373737U, 0xe8e8e8e8U,
+    0x1c1c1c1cU, 0x75757575U, 0xdfdfdfdfU, 0x6e6e6e6eU,
+    0x47474747U, 0xf1f1f1f1U, 0x1a1a1a1aU, 0x71717171U,
+    0x1d1d1d1dU, 0x29292929U, 0xc5c5c5c5U, 0x89898989U,
+    0x6f6f6f6fU, 0xb7b7b7b7U, 0x62626262U, 0x0e0e0e0eU,
+    0xaaaaaaaaU, 0x18181818U, 0xbebebebeU, 0x1b1b1b1bU,
+    0xfcfcfcfcU, 0x56565656U, 0x3e3e3e3eU, 0x4b4b4b4bU,
+    0xc6c6c6c6U, 0xd2d2d2d2U, 0x79797979U, 0x20202020U,
+    0x9a9a9a9aU, 0xdbdbdbdbU, 0xc0c0c0c0U, 0xfefefefeU,
+    0x78787878U, 0xcdcdcdcdU, 0x5a5a5a5aU, 0xf4f4f4f4U,
+    0x1f1f1f1fU, 0xddddddddU, 0xa8a8a8a8U, 0x33333333U,
+    0x88888888U, 0x07070707U, 0xc7c7c7c7U, 0x31313131U,
+    0xb1b1b1b1U, 0x12121212U, 0x10101010U, 0x59595959U,
+    0x27272727U, 0x80808080U, 0xececececU, 0x5f5f5f5fU,
+    0x60606060U, 0x51515151U, 0x7f7f7f7fU, 0xa9a9a9a9U,
+    0x19191919U, 0xb5b5b5b5U, 0x4a4a4a4aU, 0x0d0d0d0dU,
+    0x2d2d2d2dU, 0xe5e5e5e5U, 0x7a7a7a7aU, 0x9f9f9f9fU,
+    0x93939393U, 0xc9c9c9c9U, 0x9c9c9c9cU, 0xefefefefU,
+    0xa0a0a0a0U, 0xe0e0e0e0U, 0x3b3b3b3bU, 0x4d4d4d4dU,
+    0xaeaeaeaeU, 0x2a2a2a2aU, 0xf5f5f5f5U, 0xb0b0b0b0U,
+    0xc8c8c8c8U, 0xebebebebU, 0xbbbbbbbbU, 0x3c3c3c3cU,
+    0x83838383U, 0x53535353U, 0x99999999U, 0x61616161U,
+    0x17171717U, 0x2b2b2b2bU, 0x04040404U, 0x7e7e7e7eU,
+    0xbabababaU, 0x77777777U, 0xd6d6d6d6U, 0x26262626U,
+    0xe1e1e1e1U, 0x69696969U, 0x14141414U, 0x63636363U,
+    0x55555555U, 0x21212121U, 0x0c0c0c0cU, 0x7d7d7d7dU,
+};
+const u32 rcon[] /* ICACHE_RODATA_ATTR */ = {
+    0x01000000, 0x02000000, 0x04000000, 0x08000000,
+    0x10000000, 0x20000000, 0x40000000, 0x80000000,
+    0x1B000000, 0x36000000, /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#else /* AES_SMALL_TABLES */
+const u8 Td4s[256] /* ICACHE_RODATA_ATTR */ = {
+    0x52U, 0x09U, 0x6aU, 0xd5U, 0x30U, 0x36U, 0xa5U, 0x38U,
+    0xbfU, 0x40U, 0xa3U, 0x9eU, 0x81U, 0xf3U, 0xd7U, 0xfbU,
+    0x7cU, 0xe3U, 0x39U, 0x82U, 0x9bU, 0x2fU, 0xffU, 0x87U,
+    0x34U, 0x8eU, 0x43U, 0x44U, 0xc4U, 0xdeU, 0xe9U, 0xcbU,
+    0x54U, 0x7bU, 0x94U, 0x32U, 0xa6U, 0xc2U, 0x23U, 0x3dU,
+    0xeeU, 0x4cU, 0x95U, 0x0bU, 0x42U, 0xfaU, 0xc3U, 0x4eU,
+    0x08U, 0x2eU, 0xa1U, 0x66U, 0x28U, 0xd9U, 0x24U, 0xb2U,
+    0x76U, 0x5bU, 0xa2U, 0x49U, 0x6dU, 0x8bU, 0xd1U, 0x25U,
+    0x72U, 0xf8U, 0xf6U, 0x64U, 0x86U, 0x68U, 0x98U, 0x16U,
+    0xd4U, 0xa4U, 0x5cU, 0xccU, 0x5dU, 0x65U, 0xb6U, 0x92U,
+    0x6cU, 0x70U, 0x48U, 0x50U, 0xfdU, 0xedU, 0xb9U, 0xdaU,
+    0x5eU, 0x15U, 0x46U, 0x57U, 0xa7U, 0x8dU, 0x9dU, 0x84U,
+    0x90U, 0xd8U, 0xabU, 0x00U, 0x8cU, 0xbcU, 0xd3U, 0x0aU,
+    0xf7U, 0xe4U, 0x58U, 0x05U, 0xb8U, 0xb3U, 0x45U, 0x06U,
+    0xd0U, 0x2cU, 0x1eU, 0x8fU, 0xcaU, 0x3fU, 0x0fU, 0x02U,
+    0xc1U, 0xafU, 0xbdU, 0x03U, 0x01U, 0x13U, 0x8aU, 0x6bU,
+    0x3aU, 0x91U, 0x11U, 0x41U, 0x4fU, 0x67U, 0xdcU, 0xeaU,
+    0x97U, 0xf2U, 0xcfU, 0xceU, 0xf0U, 0xb4U, 0xe6U, 0x73U,
+    0x96U, 0xacU, 0x74U, 0x22U, 0xe7U, 0xadU, 0x35U, 0x85U,
+    0xe2U, 0xf9U, 0x37U, 0xe8U, 0x1cU, 0x75U, 0xdfU, 0x6eU,
+    0x47U, 0xf1U, 0x1aU, 0x71U, 0x1dU, 0x29U, 0xc5U, 0x89U,
+    0x6fU, 0xb7U, 0x62U, 0x0eU, 0xaaU, 0x18U, 0xbeU, 0x1bU,
+    0xfcU, 0x56U, 0x3eU, 0x4bU, 0xc6U, 0xd2U, 0x79U, 0x20U,
+    0x9aU, 0xdbU, 0xc0U, 0xfeU, 0x78U, 0xcdU, 0x5aU, 0xf4U,
+    0x1fU, 0xddU, 0xa8U, 0x33U, 0x88U, 0x07U, 0xc7U, 0x31U,
+    0xb1U, 0x12U, 0x10U, 0x59U, 0x27U, 0x80U, 0xecU, 0x5fU,
+    0x60U, 0x51U, 0x7fU, 0xa9U, 0x19U, 0xb5U, 0x4aU, 0x0dU,
+    0x2dU, 0xe5U, 0x7aU, 0x9fU, 0x93U, 0xc9U, 0x9cU, 0xefU,
+    0xa0U, 0xe0U, 0x3bU, 0x4dU, 0xaeU, 0x2aU, 0xf5U, 0xb0U,
+    0xc8U, 0xebU, 0xbbU, 0x3cU, 0x83U, 0x53U, 0x99U, 0x61U,
+    0x17U, 0x2bU, 0x04U, 0x7eU, 0xbaU, 0x77U, 0xd6U, 0x26U,
+    0xe1U, 0x69U, 0x14U, 0x63U, 0x55U, 0x21U, 0x0cU, 0x7dU,
+};
+const u8 rcons[] /* ICACHE_RODATA_ATTR */ = {
+    0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1B, 0x36
+    /* for 128-bit blocks, Rijndael never uses more than 10 rcon values */
+};
+#endif /* AES_SMALL_TABLES */
+/**
+ * Expand the cipher key into the encryption key schedule.
+ *
+ * @return    the number of rounds for the given cipher key size.
+ */
+int rijndaelKeySetupEnc(u32 rk[], const u8 cipherKey[], int keyBits)
+{
+    int i;
+    u32 temp;
+
+    rk[0] = GETU32(cipherKey     );
+    rk[1] = GETU32(cipherKey +  4);
+    rk[2] = GETU32(cipherKey +  8);
+    rk[3] = GETU32(cipherKey + 12);
+
+    if (keyBits == 128) {
+        for (i = 0; i < 10; i++) {
+            temp  = rk[3];
+            rk[4] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
+                TE443(temp) ^ TE414(temp) ^ RCON(i);
+            rk[5] = rk[1] ^ rk[4];
+            rk[6] = rk[2] ^ rk[5];
+            rk[7] = rk[3] ^ rk[6];
+            rk += 4;
+        }
+        return 10;
+    }
+
+    rk[4] = GETU32(cipherKey + 16);
+    rk[5] = GETU32(cipherKey + 20);
+
+    if (keyBits == 192) {
+        for (i = 0; i < 8; i++) {
+            temp  = rk[5];
+            rk[6] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
+                TE443(temp) ^ TE414(temp) ^ RCON(i);
+            rk[7] = rk[1] ^ rk[6];
+            rk[8] = rk[2] ^ rk[7];
+            rk[9] = rk[3] ^ rk[8];
+            if (i == 7)
+                return 12;
+            rk[10] = rk[4] ^ rk[9];
+            rk[11] = rk[5] ^ rk[10];
+            rk += 6;
+        }
+    }
+
+    rk[6] = GETU32(cipherKey + 24);
+    rk[7] = GETU32(cipherKey + 28);
+
+    if (keyBits == 256) {
+        for (i = 0; i < 7; i++) {
+            temp  = rk[7];
+            rk[8] = rk[0] ^ TE421(temp) ^ TE432(temp) ^
+                TE443(temp) ^ TE414(temp) ^ RCON(i);
+            rk[9] = rk[1] ^ rk[8];
+            rk[10] = rk[2] ^ rk[9];
+            rk[11] = rk[3] ^ rk[10];
+            if (i == 6)
+                return 14;
+            temp  = rk[11];
+            rk[12] = rk[4] ^ TE411(temp) ^ TE422(temp) ^
+                TE433(temp) ^ TE444(temp);
+            rk[13] = rk[5] ^ rk[12];
+            rk[14] = rk[6] ^ rk[13];
+            rk[15] = rk[7] ^ rk[14];
+            rk += 8;
+        }
+    }
+
+    return -1;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-unwrap.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-unwrap.c
new file mode 100644
index 0000000000000000000000000000000000000000..3cd91a119155d614e22b72fad612fe71f9176db3
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-unwrap.c
@@ -0,0 +1,80 @@
+/*
+ * AES key unwrap (128-bit KEK, RFC3394)
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+
+/**
+ * aes_unwrap - Unwrap key with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @cipher: Wrapped key to be unwrapped, (n + 1) * 64 bits
+ * @plain: Plaintext key, n * 64 bits
+ * Returns: 0 on success, -1 on failure (e.g., integrity verification failed)
+ */
+int
+aes_unwrap(const u8 *kek, int n, const u8 *cipher, u8 *plain)
+{
+    u8 a[8], *r, b[16];
+    int i, j;
+    void *ctx;
+
+    /* 1) Initialize variables. */
+    os_memcpy(a, cipher, 8);
+    r = plain;
+    os_memcpy(r, cipher + 8, 8 * n);
+
+    ctx = aes_decrypt_init(kek, 16);
+    if (ctx == NULL)
+        return -1;
+
+    /* 2) Compute intermediate values.
+     * For j = 5 to 0
+     *     For i = n to 1
+     *         B = AES-1(K, (A ^ t) | R[i]) where t = n*j+i
+     *         A = MSB(64, B)
+     *         R[i] = LSB(64, B)
+     */
+    for (j = 5; j >= 0; j--) {
+        r = plain + (n - 1) * 8;
+        for (i = n; i >= 1; i--) {
+            os_memcpy(b, a, 8);
+            b[7] ^= n * j + i;
+
+            os_memcpy(b + 8, r, 8);
+            aes_decrypt(ctx, b, b);
+            os_memcpy(a, b, 8);
+            os_memcpy(r, b + 8, 8);
+            r -= 8;
+        }
+    }
+    aes_decrypt_deinit(ctx);
+
+    /* 3) Output results.
+     *
+     * These are already in @plain due to the location of temporary
+     * variables. Just verify that the IV matches with the expected value.
+     */
+    for (i = 0; i < 8; i++) {
+        if (a[i] != 0xa6)
+            return -1;
+    }
+
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-wrap.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-wrap.c
new file mode 100644
index 0000000000000000000000000000000000000000..2c2c8d33508b9def69cde33560c8eac9f35b46c5
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/aes-wrap.c
@@ -0,0 +1,70 @@
+/*
+ * AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ *
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/aes.h"
+#include "crypto/aes_wrap.h"
+
+/**
+ * aes_wrap - Wrap keys with AES Key Wrap Algorithm (128-bit KEK) (RFC3394)
+ * @kek: 16-octet Key encryption key (KEK)
+ * @n: Length of the plaintext key in 64-bit units; e.g., 2 = 128-bit = 16
+ * bytes
+ * @plain: Plaintext key to be wrapped, n * 64 bits
+ * @cipher: Wrapped key, (n + 1) * 64 bits
+ * Returns: 0 on success, -1 on failure
+ */
+int  aes_wrap(const u8 *kek, int n, const u8 *plain, u8 *cipher)
+{
+    u8 *a, *r, b[16];
+    int i, j;
+    void *ctx;
+
+    a = cipher;
+    r = cipher + 8;
+
+    /* 1) Initialize variables. */
+    os_memset(a, 0xa6, 8);
+    os_memcpy(r, plain, 8 * n);
+
+    ctx = aes_encrypt_init(kek, 16);
+    if (ctx == NULL)
+        return -1;
+
+    /* 2) Calculate intermediate values.
+     * For j = 0 to 5
+     *     For i=1 to n
+     *         B = AES(K, A | R[i])
+     *         A = MSB(64, B) ^ t where t = (n*j)+i
+     *         R[i] = LSB(64, B)
+     */
+    for (j = 0; j <= 5; j++) {
+        r = cipher + 8;
+        for (i = 1; i <= n; i++) {
+            os_memcpy(b, a, 8);
+            os_memcpy(b + 8, r, 8);
+            aes_encrypt(ctx, b, b);
+            os_memcpy(a, b, 8);
+            a[7] ^= n * j + i;
+            os_memcpy(r, b + 8, 8);
+            r += 8;
+        }
+    }
+    aes_encrypt_deinit(ctx);
+
+    /* 3) Output the results.
+     *
+     * These are already in @cipher due to the location of temporary
+     * variables.
+     */
+
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/bignum.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/bignum.c
new file mode 100644
index 0000000000000000000000000000000000000000..2aa64e34a9fa62099630dfc95e8e3b9ee904cd98
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/bignum.c
@@ -0,0 +1,244 @@
+/*
+ * Big number math
+ * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+#include "crypto/common.h"
+#include "wpa/wpabuf.h"
+#include "wpa/wpa_debug.h"
+#include "bignum.h"
+
+#define CONFIG_INTERNAL_LIBTOMMATH
+#ifdef CONFIG_INTERNAL_LIBTOMMATH
+#include "libtommath.h"
+#else /* CONFIG_INTERNAL_LIBTOMMATH */
+#include <tommath.h>
+#endif /* CONFIG_INTERNAL_LIBTOMMATH */
+
+
+/*
+ * The current version is just a wrapper for LibTomMath library, so
+ * struct bignum is just typecast to mp_int.
+ */
+
+/**
+ * bignum_init - Allocate memory for bignum
+ * Returns: Pointer to allocated bignum or %NULL on failure
+ */
+struct bignum *
+bignum_init(void)
+{
+    struct bignum *n = (struct bignum *)os_zalloc(sizeof(mp_int));
+    if (n == NULL)
+        return NULL;
+    if (mp_init((mp_int *) n) != MP_OKAY) {
+        os_free(n);
+        n = NULL;
+    }
+    return n;
+}
+
+
+/**
+ * bignum_deinit - Free bignum
+ * @n: Bignum from bignum_init()
+ */
+void
+bignum_deinit(struct bignum *n)
+{
+    if (n) {
+        mp_clear((mp_int *) n);
+        os_free(n);
+    }
+}
+
+
+/**
+ * bignum_get_unsigned_bin - Get length of bignum as an unsigned binary buffer
+ * @n: Bignum from bignum_init()
+ * Returns: Length of n if written to a binary buffer
+ */
+size_t
+bignum_get_unsigned_bin_len(struct bignum *n)
+{
+    return mp_unsigned_bin_size((mp_int *) n);
+}
+
+
+/**
+ * bignum_get_unsigned_bin - Set binary buffer to unsigned bignum
+ * @n: Bignum from bignum_init()
+ * @buf: Buffer for the binary number
+ * @len: Length of the buffer, can be %NULL if buffer is known to be long
+ * enough. Set to used buffer length on success if not %NULL.
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len)
+{
+    size_t need = mp_unsigned_bin_size((mp_int *) n);
+    if (len && need > *len) {
+        *len = need;
+        return -1;
+    }
+    if (mp_to_unsigned_bin((mp_int *) n, buf) != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    if (len)
+        *len = need;
+    return 0;
+}
+
+
+/**
+ * bignum_set_unsigned_bin - Set bignum based on unsigned binary buffer
+ * @n: Bignum from bignum_init(); to be set to the given value
+ * @buf: Buffer with unsigned binary value
+ * @len: Length of buf in octets
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len)
+{
+    if (mp_read_unsigned_bin((mp_int *) n, (u8 *) buf, len) != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+
+/**
+ * bignum_cmp - Signed comparison
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_cmp(const struct bignum *a, const struct bignum *b)
+{
+    return mp_cmp((mp_int *) a, (mp_int *) b);
+}
+
+
+/**
+ * bignum_cmd_d - Compare bignum to standard integer
+ * @a: Bignum from bignum_init()
+ * @b: Small integer
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_cmp_d(const struct bignum *a, unsigned long b)
+{
+    return mp_cmp_d((mp_int *) a, b);
+}
+
+
+/**
+ * bignum_add - c = a + b
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); used to store the result of a + b
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_add(const struct bignum *a, const struct bignum *b,
+           struct bignum *c)
+{
+    if (mp_add((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+
+/**
+ * bignum_sub - c = a - b
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); used to store the result of a - b
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_sub(const struct bignum *a, const struct bignum *b,
+           struct bignum *c)
+{
+    if (mp_sub((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+
+/**
+ * bignum_mul - c = a * b
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); used to store the result of a * b
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_mul(const struct bignum *a, const struct bignum *b,
+           struct bignum *c)
+{
+    if (mp_mul((mp_int *) a, (mp_int *) b, (mp_int *) c) != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+
+/**
+ * bignum_mulmod - d = a * b (mod c)
+ * @a: Bignum from bignum_init()
+ * @b: Bignum from bignum_init()
+ * @c: Bignum from bignum_init(); modulus
+ * @d: Bignum from bignum_init(); used to store the result of a * b (mod c)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_mulmod(const struct bignum *a, const struct bignum *b,
+          const struct bignum *c, struct bignum *d)
+{
+    if (mp_mulmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
+        != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    return 0;
+}
+
+
+/**
+ * bignum_exptmod - Modular exponentiation: d = a^b (mod c)
+ * @a: Bignum from bignum_init(); base
+ * @b: Bignum from bignum_init(); exponent
+ * @c: Bignum from bignum_init(); modulus
+ * @d: Bignum from bignum_init(); used to store the result of a^b (mod c)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+bignum_exptmod(const struct bignum *a, const struct bignum *b,
+           const struct bignum *c, struct bignum *d)
+{
+    if (mp_exptmod((mp_int *) a, (mp_int *) b, (mp_int *) c, (mp_int *) d)
+        != MP_OKAY) {
+        wpa_printf(MSG_DEBUG, "BIGNUM: %s failed", __func__);
+        return -1;
+    }
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/bignum.h b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/bignum.h
new file mode 100644
index 0000000000000000000000000000000000000000..9281b4369312f82478a69212f09c6b811d178078
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/bignum.h
@@ -0,0 +1,46 @@
+/*
+ * Big number math
+ * Copyright (c) 2006, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#ifndef BIGNUM_H
+#define BIGNUM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct bignum;
+
+struct bignum * bignum_init(void);
+void bignum_deinit(struct bignum *n);
+size_t bignum_get_unsigned_bin_len(struct bignum *n);
+int bignum_get_unsigned_bin(const struct bignum *n, u8 *buf, size_t *len);
+int bignum_set_unsigned_bin(struct bignum *n, const u8 *buf, size_t len);
+int bignum_cmp(const struct bignum *a, const struct bignum *b);
+int bignum_cmp_d(const struct bignum *a, unsigned long b);
+int bignum_add(const struct bignum *a, const struct bignum *b,
+           struct bignum *c);
+int bignum_sub(const struct bignum *a, const struct bignum *b,
+           struct bignum *c);
+int bignum_mul(const struct bignum *a, const struct bignum *b,
+           struct bignum *c);
+int bignum_mulmod(const struct bignum *a, const struct bignum *b,
+          const struct bignum *c, struct bignum *d);
+int bignum_exptmod(const struct bignum *a, const struct bignum *b,
+           const struct bignum *c, struct bignum *d);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BIGNUM_H */
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-cipher.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-cipher.c
new file mode 100644
index 0000000000000000000000000000000000000000..53dea2cd18167c0ae2347ce1cd7597d19741492a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-cipher.c
@@ -0,0 +1,268 @@
+/*
+ * Crypto wrapper for internal crypto implementation - Cipher wrappers
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+//#include "wpa/includes.h"
+
+//#include "wpa/common.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/aes.h"
+#if defined(CONFIG_DES) || defined(CONFIG_DES3)
+#include "crypto/des_i.h"
+#endif
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
+
+struct crypto_cipher {
+    enum crypto_cipher_alg alg;
+    union {
+        struct {
+            size_t used_bytes;
+            u8 key[16];
+            size_t keylen;
+        } rc4;
+        struct {
+            u8 cbc[32];
+            void *ctx_enc;
+            void *ctx_dec;
+        } aes;
+#ifdef CONFIG_DES3
+        struct {
+            struct des3_key_s key;
+            u8 cbc[8];
+        } des3;
+#endif
+#ifdef CONFIG_DES
+        struct {
+            u32 ek[32];
+            u32 dk[32];
+            u8 cbc[8];
+        } des;
+#endif
+    } u;
+};
+
+
+struct crypto_cipher *  crypto_cipher_init(enum crypto_cipher_alg alg,
+                      const u8 *iv, const u8 *key,
+                      size_t key_len)
+{
+    struct crypto_cipher *ctx;
+
+    ctx = (struct crypto_cipher *)os_zalloc(sizeof(*ctx));
+    if (ctx == NULL)
+        return NULL;
+
+    ctx->alg = alg;
+
+    switch (alg) {
+    case CRYPTO_CIPHER_ALG_RC4:
+        if (key_len > sizeof(ctx->u.rc4.key)) {
+            os_free(ctx);
+            return NULL;
+        }
+        ctx->u.rc4.keylen = key_len;
+        os_memcpy(ctx->u.rc4.key, key, key_len);
+        break;
+    case CRYPTO_CIPHER_ALG_AES:
+        ctx->u.aes.ctx_enc = aes_encrypt_init(key, key_len);
+        if (ctx->u.aes.ctx_enc == NULL) {
+            os_free(ctx);
+            return NULL;
+        }
+        ctx->u.aes.ctx_dec = aes_decrypt_init(key, key_len);
+        if (ctx->u.aes.ctx_dec == NULL) {
+            aes_encrypt_deinit(ctx->u.aes.ctx_enc);
+            os_free(ctx);
+            return NULL;
+        }
+        os_memcpy(ctx->u.aes.cbc, iv, AES_BLOCK_SIZE);
+        break;
+#ifdef CONFIG_DES3
+    case CRYPTO_CIPHER_ALG_3DES:
+        if (key_len != 24) {
+            os_free(ctx);
+            return NULL;
+        }
+        des3_key_setup(key, &ctx->u.des3.key);
+        os_memcpy(ctx->u.des3.cbc, iv, 8);
+        break;
+#endif
+#ifdef CONFIG_DES
+    case CRYPTO_CIPHER_ALG_DES:
+        if (key_len != 8) {
+            os_free(ctx);
+            return NULL;
+        }
+        des_key_setup(key, ctx->u.des.ek, ctx->u.des.dk);
+        os_memcpy(ctx->u.des.cbc, iv, 8);
+        break;
+#endif
+    default:
+        os_free(ctx);
+        return NULL;
+    }
+
+    return ctx;
+}
+
+
+int  crypto_cipher_encrypt(struct crypto_cipher *ctx, const u8 *plain,
+              u8 *crypt, size_t len)
+{
+    size_t i, j, blocks;
+
+    switch (ctx->alg) {
+    case CRYPTO_CIPHER_ALG_RC4:
+        if (plain != crypt)
+            os_memcpy(crypt, plain, len);
+        rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
+             ctx->u.rc4.used_bytes, crypt, len);
+        ctx->u.rc4.used_bytes += len;
+        break;
+    case CRYPTO_CIPHER_ALG_AES:
+        if (len % AES_BLOCK_SIZE)
+            return -1;
+        blocks = len / AES_BLOCK_SIZE;
+        for (i = 0; i < blocks; i++) {
+            for (j = 0; j < AES_BLOCK_SIZE; j++)
+                ctx->u.aes.cbc[j] ^= plain[j];
+            aes_encrypt(ctx->u.aes.ctx_enc, ctx->u.aes.cbc,
+                    ctx->u.aes.cbc);
+            os_memcpy(crypt, ctx->u.aes.cbc, AES_BLOCK_SIZE);
+            plain += AES_BLOCK_SIZE;
+            crypt += AES_BLOCK_SIZE;
+        }
+        break;
+#ifdef CONFIG_DES3
+    case CRYPTO_CIPHER_ALG_3DES:
+        if (len % 8)
+            return -1;
+        blocks = len / 8;
+        for (i = 0; i < blocks; i++) {
+            for (j = 0; j < 8; j++)
+                ctx->u.des3.cbc[j] ^= plain[j];
+            des3_encrypt(ctx->u.des3.cbc, &ctx->u.des3.key,
+                     ctx->u.des3.cbc);
+            os_memcpy(crypt, ctx->u.des3.cbc, 8);
+            plain += 8;
+            crypt += 8;
+        }
+        break;
+#endif
+#ifdef CONFIG_DES
+    case CRYPTO_CIPHER_ALG_DES:
+        if (len % 8)
+            return -1;
+        blocks = len / 8;
+        for (i = 0; i < blocks; i++) {
+            for (j = 0; j < 8; j++)
+                ctx->u.des3.cbc[j] ^= plain[j];
+            des_block_encrypt(ctx->u.des.cbc, ctx->u.des.ek,
+                      ctx->u.des.cbc);
+            os_memcpy(crypt, ctx->u.des.cbc, 8);
+            plain += 8;
+            crypt += 8;
+        }
+        break;
+#endif
+    default:
+        return -1;
+    }
+
+    return 0;
+}
+
+
+int  crypto_cipher_decrypt(struct crypto_cipher *ctx, const u8 *crypt,
+              u8 *plain, size_t len)
+{
+    size_t i, j, blocks;
+    u8 tmp[32];
+
+    switch (ctx->alg) {
+    case CRYPTO_CIPHER_ALG_RC4:
+        if (plain != crypt)
+            os_memcpy(plain, crypt, len);
+        rc4_skip(ctx->u.rc4.key, ctx->u.rc4.keylen,
+             ctx->u.rc4.used_bytes, plain, len);
+        ctx->u.rc4.used_bytes += len;
+        break;
+    case CRYPTO_CIPHER_ALG_AES:
+        if (len % AES_BLOCK_SIZE)
+            return -1;
+        blocks = len / AES_BLOCK_SIZE;
+        for (i = 0; i < blocks; i++) {
+            os_memcpy(tmp, crypt, AES_BLOCK_SIZE);
+            aes_decrypt(ctx->u.aes.ctx_dec, crypt, plain);
+            for (j = 0; j < AES_BLOCK_SIZE; j++)
+                plain[j] ^= ctx->u.aes.cbc[j];
+            os_memcpy(ctx->u.aes.cbc, tmp, AES_BLOCK_SIZE);
+            plain += AES_BLOCK_SIZE;
+            crypt += AES_BLOCK_SIZE;
+        }
+        break;
+#ifdef CONFIG_DES3
+    case CRYPTO_CIPHER_ALG_3DES:
+        if (len % 8)
+            return -1;
+        blocks = len / 8;
+        for (i = 0; i < blocks; i++) {
+            os_memcpy(tmp, crypt, 8);
+            des3_decrypt(crypt, &ctx->u.des3.key, plain);
+            for (j = 0; j < 8; j++)
+                plain[j] ^= ctx->u.des3.cbc[j];
+            os_memcpy(ctx->u.des3.cbc, tmp, 8);
+            plain += 8;
+            crypt += 8;
+        }
+        break;
+#endif
+#ifdef CONFIG_DES
+    case CRYPTO_CIPHER_ALG_DES:
+        if (len % 8)
+            return -1;
+        blocks = len / 8;
+        for (i = 0; i < blocks; i++) {
+            os_memcpy(tmp, crypt, 8);
+            des_block_decrypt(crypt, ctx->u.des.dk, plain);
+            for (j = 0; j < 8; j++)
+                plain[j] ^= ctx->u.des.cbc[j];
+            os_memcpy(ctx->u.des.cbc, tmp, 8);
+            plain += 8;
+            crypt += 8;
+        }
+        break;
+#endif
+    default:
+        return -1;
+    }
+
+    return 0;
+}
+
+
+void  crypto_cipher_deinit(struct crypto_cipher *ctx)
+{
+    switch (ctx->alg) {
+    case CRYPTO_CIPHER_ALG_AES:
+        aes_encrypt_deinit(ctx->u.aes.ctx_enc);
+        aes_decrypt_deinit(ctx->u.aes.ctx_dec);
+        break;
+#ifdef CONFIG_DES3
+    case CRYPTO_CIPHER_ALG_3DES:
+        break;
+#endif
+    default:
+        break;
+    }
+    os_free(ctx);
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-modexp.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-modexp.c
new file mode 100644
index 0000000000000000000000000000000000000000..46165c93cec7200f561b6e86ec73ce5639fd7618
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-modexp.c
@@ -0,0 +1,56 @@
+/*
+ * Crypto wrapper for internal crypto implementation - modexp
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "bignum.h"
+#include "crypto/crypto.h"
+
+
+int
+crypto_mod_exp(const u8 *base, size_t base_len,
+           const u8 *power, size_t power_len,
+           const u8 *modulus, size_t modulus_len,
+           u8 *result, size_t *result_len)
+{
+    struct bignum *bn_base, *bn_exp, *bn_modulus, *bn_result;
+    int ret = -1;
+
+    bn_base = bignum_init();
+    bn_exp = bignum_init();
+    bn_modulus = bignum_init();
+    bn_result = bignum_init();
+
+    if (bn_base == NULL || bn_exp == NULL || bn_modulus == NULL ||
+        bn_result == NULL)
+        goto error;
+
+    if (bignum_set_unsigned_bin(bn_base, base, base_len) < 0 ||
+        bignum_set_unsigned_bin(bn_exp, power, power_len) < 0 ||
+        bignum_set_unsigned_bin(bn_modulus, modulus, modulus_len) < 0)
+        goto error;
+
+    if (bignum_exptmod(bn_base, bn_exp, bn_modulus, bn_result) < 0)
+        goto error;
+
+    ret = bignum_get_unsigned_bin(bn_result, result, result_len);
+
+error:
+    bignum_deinit(bn_base);
+    bignum_deinit(bn_exp);
+    bignum_deinit(bn_modulus);
+    bignum_deinit(bn_result);
+    return ret;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-rsa.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-rsa.c
new file mode 100644
index 0000000000000000000000000000000000000000..0423714d5184d7877158d12b6703a0536e709791
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal-rsa.c
@@ -0,0 +1,111 @@
+/*
+ * Crypto wrapper for internal crypto implementation - RSA parts
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+
+#include "wpa/includes.h"
+#include "wpa/common.h"
+#include "wpa/wpa_debug.h"
+
+#include "wpa2/tls/rsa.h"
+#include "wpa2/tls/pkcs1.h"
+#include "wpa2/tls/pkcs8.h"
+
+/* Dummy structures; these are just typecast to struct crypto_rsa_key */
+struct crypto_public_key;
+struct crypto_private_key;
+
+
+struct crypto_public_key *  crypto_public_key_import(const u8 *key, size_t len)
+{
+    return (struct crypto_public_key *)
+        crypto_rsa_import_public_key(key, len);
+}
+
+
+struct crypto_private_key *  crypto_private_key_import(const u8 *key,
+                              size_t len,
+                              const char *passwd)
+{
+    struct crypto_private_key *res;
+
+    /* First, check for possible PKCS #8 encoding */
+    res = pkcs8_key_import(key, len);
+    if (res)
+        return res;
+
+    if (passwd) {
+        /* Try to parse as encrypted PKCS #8 */
+        res = pkcs8_enc_key_import(key, len, passwd);
+        if (res)
+            return res;
+    }
+
+    /* Not PKCS#8, so try to import PKCS #1 encoded RSA private key */
+    wpa_printf(MSG_DEBUG, "Trying to parse PKCS #1 encoded RSA private "
+           "key");
+    return (struct crypto_private_key *)
+        crypto_rsa_import_private_key(key, len);
+}
+
+
+struct crypto_public_key *  crypto_public_key_from_cert(const u8 *buf,
+                               size_t len)
+{
+    /* No X.509 support in crypto_internal.c */
+    return NULL;
+}
+
+
+int  crypto_public_key_encrypt_pkcs1_v15(struct crypto_public_key *key,
+                    const u8 *in, size_t inlen,
+                    u8 *out, size_t *outlen)
+{
+    return pkcs1_encrypt(2, (struct crypto_rsa_key *) key,
+                 0, in, inlen, out, outlen);
+}
+
+
+int  crypto_private_key_decrypt_pkcs1_v15(struct crypto_private_key *key,
+                     const u8 *in, size_t inlen,
+                     u8 *out, size_t *outlen)
+{
+    return pkcs1_v15_private_key_decrypt((struct crypto_rsa_key *) key,
+                         in, inlen, out, outlen);
+}
+
+
+int  crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
+                  const u8 *in, size_t inlen,
+                  u8 *out, size_t *outlen)
+{
+    return pkcs1_encrypt(1, (struct crypto_rsa_key *) key,
+                 1, in, inlen, out, outlen);
+}
+
+
+void  crypto_public_key_free(struct crypto_public_key *key)
+{
+    crypto_rsa_free((struct crypto_rsa_key *) key);
+}
+
+
+void  crypto_private_key_free(struct crypto_private_key *key)
+{
+    crypto_rsa_free((struct crypto_rsa_key *) key);
+}
+
+
+int  crypto_public_key_decrypt_pkcs1(struct crypto_public_key *key,
+                    const u8 *crypt, size_t crypt_len,
+                    u8 *plain, size_t *plain_len)
+{
+    return pkcs1_decrypt_public_key((struct crypto_rsa_key *) key,
+                    crypt, crypt_len, plain, plain_len);
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..2738008ef05f4fd48716f68bee510c3e5777f907
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/crypto_internal.c
@@ -0,0 +1,280 @@
+/*
+ * Crypto wrapper for internal crypto implementation
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+#include "crypto/includes.h"
+#include "crypto/common.h"
+//#include "wpa/common.h"
+#include "crypto/crypto.h"
+//#include "crypto/sha256_i.h"
+#include "crypto/sha1_i.h"
+#include "crypto/md5_i.h"
+
+#ifdef MEMLEAK_DEBUG
+static const char mem_debug_file[] ICACHE_RODATA_ATTR = __FILE__;
+#endif
+
+
+struct crypto_hash {
+    enum crypto_hash_alg alg;
+    union {
+        struct MD5Context md5;
+        struct SHA1Context sha1;
+#ifdef CONFIG_SHA256
+        struct sha256_state sha256;
+#endif /* CONFIG_SHA256 */
+    } u;
+    u8 key[64];
+    size_t key_len;
+};
+
+
+struct crypto_hash *  crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
+                      size_t key_len)
+{
+    struct crypto_hash *ctx;
+    u8 k_pad[64];
+    u8 tk[32];
+    size_t i;
+
+    ctx = (struct crypto_hash *)os_zalloc(sizeof(*ctx));
+    if (ctx == NULL)
+        return NULL;
+
+    ctx->alg = alg;
+
+    switch (alg) {
+    case CRYPTO_HASH_ALG_MD5:
+        MD5Init(&ctx->u.md5);
+        break;
+    case CRYPTO_HASH_ALG_SHA1:
+        SHA1Init(&ctx->u.sha1);
+        break;
+#ifdef CONFIG_SHA256
+    case CRYPTO_HASH_ALG_SHA256:
+        sha256_init(&ctx->u.sha256);
+        break;
+#endif /* CONFIG_SHA256 */
+    case CRYPTO_HASH_ALG_HMAC_MD5:
+        if (key_len > sizeof(k_pad)) {
+            MD5Init(&ctx->u.md5);
+            MD5Update(&ctx->u.md5, key, key_len);
+            MD5Final(tk, &ctx->u.md5);
+            key = tk;
+            key_len = 16;
+        }
+        os_memcpy(ctx->key, key, key_len);
+        ctx->key_len = key_len;
+
+        os_memcpy(k_pad, key, key_len);
+        if (key_len < sizeof(k_pad))
+            os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+        for (i = 0; i < sizeof(k_pad); i++)
+            k_pad[i] ^= 0x36;
+        MD5Init(&ctx->u.md5);
+        MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
+        break;
+    case CRYPTO_HASH_ALG_HMAC_SHA1:
+        if (key_len > sizeof(k_pad)) {
+            SHA1Init(&ctx->u.sha1);
+            SHA1Update(&ctx->u.sha1, key, key_len);
+            SHA1Final(tk, &ctx->u.sha1);
+            key = tk;
+            key_len = 20;
+        }
+        os_memcpy(ctx->key, key, key_len);
+        ctx->key_len = key_len;
+
+        os_memcpy(k_pad, key, key_len);
+        if (key_len < sizeof(k_pad))
+            os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+        for (i = 0; i < sizeof(k_pad); i++)
+            k_pad[i] ^= 0x36;
+        SHA1Init(&ctx->u.sha1);
+        SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
+        break;
+#ifdef CONFIG_SHA256
+    case CRYPTO_HASH_ALG_HMAC_SHA256:
+        if (key_len > sizeof(k_pad)) {
+            sha256_init(&ctx->u.sha256);
+            sha256_process(&ctx->u.sha256, key, key_len);
+            sha256_done(&ctx->u.sha256, tk);
+            key = tk;
+            key_len = 32;
+        }
+        os_memcpy(ctx->key, key, key_len);
+        ctx->key_len = key_len;
+
+        os_memcpy(k_pad, key, key_len);
+        if (key_len < sizeof(k_pad))
+            os_memset(k_pad + key_len, 0, sizeof(k_pad) - key_len);
+        for (i = 0; i < sizeof(k_pad); i++)
+            k_pad[i] ^= 0x36;
+        sha256_init(&ctx->u.sha256);
+        sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
+        break;
+#endif /* CONFIG_SHA256 */
+    default:
+        os_free(ctx);
+        return NULL;
+    }
+
+    return ctx;
+}
+
+
+void  crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len)
+{
+    if (ctx == NULL)
+        return;
+
+    switch (ctx->alg) {
+    case CRYPTO_HASH_ALG_MD5:
+    case CRYPTO_HASH_ALG_HMAC_MD5:
+        MD5Update(&ctx->u.md5, data, len);
+        break;
+    case CRYPTO_HASH_ALG_SHA1:
+    case CRYPTO_HASH_ALG_HMAC_SHA1:
+        SHA1Update(&ctx->u.sha1, data, len);
+        break;
+#ifdef CONFIG_SHA256
+    case CRYPTO_HASH_ALG_SHA256:
+    case CRYPTO_HASH_ALG_HMAC_SHA256:
+        sha256_process(&ctx->u.sha256, data, len);
+        break;
+#endif /* CONFIG_SHA256 */
+    default:
+        break;
+    }
+}
+
+
+int  crypto_hash_finish(struct crypto_hash *ctx, u8 *mac, size_t *len)
+{
+    u8 k_pad[64];
+    size_t i;
+
+    if (ctx == NULL)
+        return -2;
+
+    if (mac == NULL || len == NULL) {
+        os_free(ctx);
+        return 0;
+    }
+
+    switch (ctx->alg) {
+    case CRYPTO_HASH_ALG_MD5:
+        if (*len < 16) {
+            *len = 16;
+            os_free(ctx);
+            return -1;
+        }
+        *len = 16;
+        MD5Final(mac, &ctx->u.md5);
+        break;
+    case CRYPTO_HASH_ALG_SHA1:
+        if (*len < 20) {
+            *len = 20;
+            os_free(ctx);
+            return -1;
+        }
+        *len = 20;
+        SHA1Final(mac, &ctx->u.sha1);
+        break;
+#ifdef CONFIG_SHA256
+    case CRYPTO_HASH_ALG_SHA256:
+        if (*len < 32) {
+            *len = 32;
+            os_free(ctx);
+            return -1;
+        }
+        *len = 32;
+        sha256_done(&ctx->u.sha256, mac);
+        break;
+#endif /* CONFIG_SHA256 */
+    case CRYPTO_HASH_ALG_HMAC_MD5:
+        if (*len < 16) {
+            *len = 16;
+            os_free(ctx);
+            return -1;
+        }
+        *len = 16;
+
+        MD5Final(mac, &ctx->u.md5);
+
+        os_memcpy(k_pad, ctx->key, ctx->key_len);
+        os_memset(k_pad + ctx->key_len, 0,
+              sizeof(k_pad) - ctx->key_len);
+        for (i = 0; i < sizeof(k_pad); i++)
+            k_pad[i] ^= 0x5c;
+        MD5Init(&ctx->u.md5);
+        MD5Update(&ctx->u.md5, k_pad, sizeof(k_pad));
+        MD5Update(&ctx->u.md5, mac, 16);
+        MD5Final(mac, &ctx->u.md5);
+        break;
+    case CRYPTO_HASH_ALG_HMAC_SHA1:
+        if (*len < 20) {
+            *len = 20;
+            os_free(ctx);
+            return -1;
+        }
+        *len = 20;
+
+        SHA1Final(mac, &ctx->u.sha1);
+
+        os_memcpy(k_pad, ctx->key, ctx->key_len);
+        os_memset(k_pad + ctx->key_len, 0,
+              sizeof(k_pad) - ctx->key_len);
+        for (i = 0; i < sizeof(k_pad); i++)
+            k_pad[i] ^= 0x5c;
+        SHA1Init(&ctx->u.sha1);
+        SHA1Update(&ctx->u.sha1, k_pad, sizeof(k_pad));
+        SHA1Update(&ctx->u.sha1, mac, 20);
+        SHA1Final(mac, &ctx->u.sha1);
+        break;
+#ifdef CONFIG_SHA256
+    case CRYPTO_HASH_ALG_HMAC_SHA256:
+        if (*len < 32) {
+            *len = 32;
+            os_free(ctx);
+            return -1;
+        }
+        *len = 32;
+
+        sha256_done(&ctx->u.sha256, mac);
+
+        os_memcpy(k_pad, ctx->key, ctx->key_len);
+        os_memset(k_pad + ctx->key_len, 0,
+              sizeof(k_pad) - ctx->key_len);
+        for (i = 0; i < sizeof(k_pad); i++)
+            k_pad[i] ^= 0x5c;
+        sha256_init(&ctx->u.sha256);
+        sha256_process(&ctx->u.sha256, k_pad, sizeof(k_pad));
+        sha256_process(&ctx->u.sha256, mac, 32);
+        sha256_done(&ctx->u.sha256, mac);
+        break;
+#endif /* CONFIG_SHA256 */
+    default:
+        os_free(ctx);
+        return -1;
+    }
+
+    os_free(ctx);
+
+    return 0;
+}
+
+
+int  crypto_global_init(void)
+{
+    return 0;
+}
+
+
+void  crypto_global_deinit(void)
+{
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/des-internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/des-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..f03ae4efb7934df5d1b51b23530394fd0463d68d
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/des-internal.c
@@ -0,0 +1,493 @@
+/*
+ * DES and 3DES-EDE ciphers
+ *
+ * Modifications to LibTomCrypt implementation:
+ * Copyright (c) 2006-2009, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+
+#include "wpa/includes.h"
+
+#include "wpa/common.h"
+#include "crypto/crypto.h"
+//#include "des_i.h"
+
+/*
+ * This implementation is based on a DES implementation included in
+ * LibTomCrypt. The version here is modified to fit in wpa_supplicant/hostapd
+ * coding style.
+ */
+
+/* LibTomCrypt, modular cryptographic library -- Tom St Denis
+ *
+ * LibTomCrypt is a library that provides various cryptographic
+ * algorithms in a highly modular and flexible manner.
+ *
+ * The library is free for all purposes without any express
+ * guarantee it works.
+ *
+ * Tom St Denis, tomstdenis@gmail.com, http://libtomcrypt.com
+ */
+
+/**
+  DES code submitted by Dobes Vandermeer
+*/
+
+#define ROLc(x, y) \
+    ((((unsigned long) (x) << (unsigned long) ((y) & 31)) | \
+      (((unsigned long) (x) & 0xFFFFFFFFUL) >> \
+       (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
+#define RORc(x, y) \
+    (((((unsigned long) (x) & 0xFFFFFFFFUL) >> \
+       (unsigned long) ((y) & 31)) | \
+      ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & \
+     0xFFFFFFFFUL)
+
+
+static const u32 bytebit[8] =
+{
+    0200, 0100, 040, 020, 010, 04, 02, 01
+};
+
+static const u32 bigbyte[24] =
+{
+    0x800000UL,  0x400000UL,  0x200000UL,  0x100000UL,
+    0x80000UL,   0x40000UL,   0x20000UL,   0x10000UL,
+    0x8000UL,    0x4000UL,    0x2000UL,    0x1000UL,
+    0x800UL,     0x400UL,     0x200UL,     0x100UL,
+    0x80UL,      0x40UL,      0x20UL,      0x10UL,
+    0x8UL,       0x4UL,       0x2UL,       0x1L
+};
+
+/* Use the key schedule specific in the standard (ANSI X3.92-1981) */
+
+static const u8 pc1[56] = {
+    56, 48, 40, 32, 24, 16,  8,  0, 57, 49, 41, 33, 25, 17,
+     9,  1, 58, 50, 42, 34, 26, 18, 10,  2, 59, 51, 43, 35,
+    62, 54, 46, 38, 30, 22, 14,  6, 61, 53, 45, 37, 29, 21,
+    13,  5, 60, 52, 44, 36, 28, 20, 12,  4, 27, 19, 11,  3
+};
+
+static const u8 totrot[16] = {
+    1,   2,  4,  6,
+    8,  10, 12, 14,
+    15, 17, 19, 21,
+    23, 25, 27, 28
+};
+
+static const u8 pc2[48] = {
+    13, 16, 10, 23,  0,  4,      2, 27, 14,  5, 20,  9,
+    22, 18, 11,  3, 25,  7,     15,  6, 26, 19, 12,  1,
+    40, 51, 30, 36, 46, 54,     29, 39, 50, 44, 32, 47,
+    43, 48, 38, 55, 33, 52,     45, 41, 49, 35, 28, 31
+};
+
+
+static const u32 SP1[64] =
+{
+    0x01010400UL, 0x00000000UL, 0x00010000UL, 0x01010404UL,
+    0x01010004UL, 0x00010404UL, 0x00000004UL, 0x00010000UL,
+    0x00000400UL, 0x01010400UL, 0x01010404UL, 0x00000400UL,
+    0x01000404UL, 0x01010004UL, 0x01000000UL, 0x00000004UL,
+    0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00010400UL,
+    0x00010400UL, 0x01010000UL, 0x01010000UL, 0x01000404UL,
+    0x00010004UL, 0x01000004UL, 0x01000004UL, 0x00010004UL,
+    0x00000000UL, 0x00000404UL, 0x00010404UL, 0x01000000UL,
+    0x00010000UL, 0x01010404UL, 0x00000004UL, 0x01010000UL,
+    0x01010400UL, 0x01000000UL, 0x01000000UL, 0x00000400UL,
+    0x01010004UL, 0x00010000UL, 0x00010400UL, 0x01000004UL,
+    0x00000400UL, 0x00000004UL, 0x01000404UL, 0x00010404UL,
+    0x01010404UL, 0x00010004UL, 0x01010000UL, 0x01000404UL,
+    0x01000004UL, 0x00000404UL, 0x00010404UL, 0x01010400UL,
+    0x00000404UL, 0x01000400UL, 0x01000400UL, 0x00000000UL,
+    0x00010004UL, 0x00010400UL, 0x00000000UL, 0x01010004UL
+};
+
+static const u32 SP2[64] =
+{
+    0x80108020UL, 0x80008000UL, 0x00008000UL, 0x00108020UL,
+    0x00100000UL, 0x00000020UL, 0x80100020UL, 0x80008020UL,
+    0x80000020UL, 0x80108020UL, 0x80108000UL, 0x80000000UL,
+    0x80008000UL, 0x00100000UL, 0x00000020UL, 0x80100020UL,
+    0x00108000UL, 0x00100020UL, 0x80008020UL, 0x00000000UL,
+    0x80000000UL, 0x00008000UL, 0x00108020UL, 0x80100000UL,
+    0x00100020UL, 0x80000020UL, 0x00000000UL, 0x00108000UL,
+    0x00008020UL, 0x80108000UL, 0x80100000UL, 0x00008020UL,
+    0x00000000UL, 0x00108020UL, 0x80100020UL, 0x00100000UL,
+    0x80008020UL, 0x80100000UL, 0x80108000UL, 0x00008000UL,
+    0x80100000UL, 0x80008000UL, 0x00000020UL, 0x80108020UL,
+    0x00108020UL, 0x00000020UL, 0x00008000UL, 0x80000000UL,
+    0x00008020UL, 0x80108000UL, 0x00100000UL, 0x80000020UL,
+    0x00100020UL, 0x80008020UL, 0x80000020UL, 0x00100020UL,
+    0x00108000UL, 0x00000000UL, 0x80008000UL, 0x00008020UL,
+    0x80000000UL, 0x80100020UL, 0x80108020UL, 0x00108000UL
+};
+
+static const u32 SP3[64] =
+{
+    0x00000208UL, 0x08020200UL, 0x00000000UL, 0x08020008UL,
+    0x08000200UL, 0x00000000UL, 0x00020208UL, 0x08000200UL,
+    0x00020008UL, 0x08000008UL, 0x08000008UL, 0x00020000UL,
+    0x08020208UL, 0x00020008UL, 0x08020000UL, 0x00000208UL,
+    0x08000000UL, 0x00000008UL, 0x08020200UL, 0x00000200UL,
+    0x00020200UL, 0x08020000UL, 0x08020008UL, 0x00020208UL,
+    0x08000208UL, 0x00020200UL, 0x00020000UL, 0x08000208UL,
+    0x00000008UL, 0x08020208UL, 0x00000200UL, 0x08000000UL,
+    0x08020200UL, 0x08000000UL, 0x00020008UL, 0x00000208UL,
+    0x00020000UL, 0x08020200UL, 0x08000200UL, 0x00000000UL,
+    0x00000200UL, 0x00020008UL, 0x08020208UL, 0x08000200UL,
+    0x08000008UL, 0x00000200UL, 0x00000000UL, 0x08020008UL,
+    0x08000208UL, 0x00020000UL, 0x08000000UL, 0x08020208UL,
+    0x00000008UL, 0x00020208UL, 0x00020200UL, 0x08000008UL,
+    0x08020000UL, 0x08000208UL, 0x00000208UL, 0x08020000UL,
+    0x00020208UL, 0x00000008UL, 0x08020008UL, 0x00020200UL
+};
+
+static const u32 SP4[64] =
+{
+    0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
+    0x00802080UL, 0x00800081UL, 0x00800001UL, 0x00002001UL,
+    0x00000000UL, 0x00802000UL, 0x00802000UL, 0x00802081UL,
+    0x00000081UL, 0x00000000UL, 0x00800080UL, 0x00800001UL,
+    0x00000001UL, 0x00002000UL, 0x00800000UL, 0x00802001UL,
+    0x00000080UL, 0x00800000UL, 0x00002001UL, 0x00002080UL,
+    0x00800081UL, 0x00000001UL, 0x00002080UL, 0x00800080UL,
+    0x00002000UL, 0x00802080UL, 0x00802081UL, 0x00000081UL,
+    0x00800080UL, 0x00800001UL, 0x00802000UL, 0x00802081UL,
+    0x00000081UL, 0x00000000UL, 0x00000000UL, 0x00802000UL,
+    0x00002080UL, 0x00800080UL, 0x00800081UL, 0x00000001UL,
+    0x00802001UL, 0x00002081UL, 0x00002081UL, 0x00000080UL,
+    0x00802081UL, 0x00000081UL, 0x00000001UL, 0x00002000UL,
+    0x00800001UL, 0x00002001UL, 0x00802080UL, 0x00800081UL,
+    0x00002001UL, 0x00002080UL, 0x00800000UL, 0x00802001UL,
+    0x00000080UL, 0x00800000UL, 0x00002000UL, 0x00802080UL
+};
+
+static const u32 SP5[64] =
+{
+    0x00000100UL, 0x02080100UL, 0x02080000UL, 0x42000100UL,
+    0x00080000UL, 0x00000100UL, 0x40000000UL, 0x02080000UL,
+    0x40080100UL, 0x00080000UL, 0x02000100UL, 0x40080100UL,
+    0x42000100UL, 0x42080000UL, 0x00080100UL, 0x40000000UL,
+    0x02000000UL, 0x40080000UL, 0x40080000UL, 0x00000000UL,
+    0x40000100UL, 0x42080100UL, 0x42080100UL, 0x02000100UL,
+    0x42080000UL, 0x40000100UL, 0x00000000UL, 0x42000000UL,
+    0x02080100UL, 0x02000000UL, 0x42000000UL, 0x00080100UL,
+    0x00080000UL, 0x42000100UL, 0x00000100UL, 0x02000000UL,
+    0x40000000UL, 0x02080000UL, 0x42000100UL, 0x40080100UL,
+    0x02000100UL, 0x40000000UL, 0x42080000UL, 0x02080100UL,
+    0x40080100UL, 0x00000100UL, 0x02000000UL, 0x42080000UL,
+    0x42080100UL, 0x00080100UL, 0x42000000UL, 0x42080100UL,
+    0x02080000UL, 0x00000000UL, 0x40080000UL, 0x42000000UL,
+    0x00080100UL, 0x02000100UL, 0x40000100UL, 0x00080000UL,
+    0x00000000UL, 0x40080000UL, 0x02080100UL, 0x40000100UL
+};
+
+static const u32 SP6[64] =
+{
+    0x20000010UL, 0x20400000UL, 0x00004000UL, 0x20404010UL,
+    0x20400000UL, 0x00000010UL, 0x20404010UL, 0x00400000UL,
+    0x20004000UL, 0x00404010UL, 0x00400000UL, 0x20000010UL,
+    0x00400010UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
+    0x00000000UL, 0x00400010UL, 0x20004010UL, 0x00004000UL,
+    0x00404000UL, 0x20004010UL, 0x00000010UL, 0x20400010UL,
+    0x20400010UL, 0x00000000UL, 0x00404010UL, 0x20404000UL,
+    0x00004010UL, 0x00404000UL, 0x20404000UL, 0x20000000UL,
+    0x20004000UL, 0x00000010UL, 0x20400010UL, 0x00404000UL,
+    0x20404010UL, 0x00400000UL, 0x00004010UL, 0x20000010UL,
+    0x00400000UL, 0x20004000UL, 0x20000000UL, 0x00004010UL,
+    0x20000010UL, 0x20404010UL, 0x00404000UL, 0x20400000UL,
+    0x00404010UL, 0x20404000UL, 0x00000000UL, 0x20400010UL,
+    0x00000010UL, 0x00004000UL, 0x20400000UL, 0x00404010UL,
+    0x00004000UL, 0x00400010UL, 0x20004010UL, 0x00000000UL,
+    0x20404000UL, 0x20000000UL, 0x00400010UL, 0x20004010UL
+};
+
+static const u32 SP7[64] =
+{
+    0x00200000UL, 0x04200002UL, 0x04000802UL, 0x00000000UL,
+    0x00000800UL, 0x04000802UL, 0x00200802UL, 0x04200800UL,
+    0x04200802UL, 0x00200000UL, 0x00000000UL, 0x04000002UL,
+    0x00000002UL, 0x04000000UL, 0x04200002UL, 0x00000802UL,
+    0x04000800UL, 0x00200802UL, 0x00200002UL, 0x04000800UL,
+    0x04000002UL, 0x04200000UL, 0x04200800UL, 0x00200002UL,
+    0x04200000UL, 0x00000800UL, 0x00000802UL, 0x04200802UL,
+    0x00200800UL, 0x00000002UL, 0x04000000UL, 0x00200800UL,
+    0x04000000UL, 0x00200800UL, 0x00200000UL, 0x04000802UL,
+    0x04000802UL, 0x04200002UL, 0x04200002UL, 0x00000002UL,
+    0x00200002UL, 0x04000000UL, 0x04000800UL, 0x00200000UL,
+    0x04200800UL, 0x00000802UL, 0x00200802UL, 0x04200800UL,
+    0x00000802UL, 0x04000002UL, 0x04200802UL, 0x04200000UL,
+    0x00200800UL, 0x00000000UL, 0x00000002UL, 0x04200802UL,
+    0x00000000UL, 0x00200802UL, 0x04200000UL, 0x00000800UL,
+    0x04000002UL, 0x04000800UL, 0x00000800UL, 0x00200002UL
+};
+
+static const u32 SP8[64] =
+{
+    0x10001040UL, 0x00001000UL, 0x00040000UL, 0x10041040UL,
+    0x10000000UL, 0x10001040UL, 0x00000040UL, 0x10000000UL,
+    0x00040040UL, 0x10040000UL, 0x10041040UL, 0x00041000UL,
+    0x10041000UL, 0x00041040UL, 0x00001000UL, 0x00000040UL,
+    0x10040000UL, 0x10000040UL, 0x10001000UL, 0x00001040UL,
+    0x00041000UL, 0x00040040UL, 0x10040040UL, 0x10041000UL,
+    0x00001040UL, 0x00000000UL, 0x00000000UL, 0x10040040UL,
+    0x10000040UL, 0x10001000UL, 0x00041040UL, 0x00040000UL,
+    0x00041040UL, 0x00040000UL, 0x10041000UL, 0x00001000UL,
+    0x00000040UL, 0x10040040UL, 0x00001000UL, 0x00041040UL,
+    0x10001000UL, 0x00000040UL, 0x10000040UL, 0x10040000UL,
+    0x10040040UL, 0x10000000UL, 0x00040000UL, 0x10001040UL,
+    0x00000000UL, 0x10041040UL, 0x00040040UL, 0x10000040UL,
+    0x10040000UL, 0x10001000UL, 0x10001040UL, 0x00000000UL,
+    0x10041040UL, 0x00041000UL, 0x00041000UL, 0x00001040UL,
+    0x00001040UL, 0x00040040UL, 0x10000000UL, 0x10041000UL
+};
+
+static void cookey(const u32 *raw1, u32 *keyout)
+{
+    u32 *cook;
+    const u32 *raw0;
+    u32 dough[32];
+    int i;
+
+    cook = dough;
+    for (i = 0; i < 16; i++, raw1++) {
+        raw0 = raw1++;
+        *cook    = (*raw0 & 0x00fc0000L) << 6;
+        *cook   |= (*raw0 & 0x00000fc0L) << 10;
+        *cook   |= (*raw1 & 0x00fc0000L) >> 10;
+        *cook++ |= (*raw1 & 0x00000fc0L) >> 6;
+        *cook    = (*raw0 & 0x0003f000L) << 12;
+        *cook   |= (*raw0 & 0x0000003fL) << 16;
+        *cook   |= (*raw1 & 0x0003f000L) >> 4;
+        *cook++ |= (*raw1 & 0x0000003fL);
+    }
+
+    os_memcpy(keyout, dough, sizeof(dough));
+}
+
+
+static void deskey(const u8 *key, int decrypt, u32 *keyout)
+{
+    u32 i, j, l, m, n, kn[32];
+    u8 pc1m[56], pcr[56];
+
+    for (j = 0; j < 56; j++) {
+        l = (u32) pc1[j];
+        m = l & 7;
+        pc1m[j] = (u8)
+            ((key[l >> 3U] & bytebit[m]) == bytebit[m] ? 1 : 0);
+    }
+
+    for (i = 0; i < 16; i++) {
+        if (decrypt)
+            m = (15 - i) << 1;
+        else
+            m = i << 1;
+        n = m + 1;
+        kn[m] = kn[n] = 0L;
+        for (j = 0; j < 28; j++) {
+            l = j + (u32) totrot[i];
+            if (l < 28)
+                pcr[j] = pc1m[l];
+            else
+                pcr[j] = pc1m[l - 28];
+        }
+        for (/* j = 28 */; j < 56; j++) {
+            l = j + (u32) totrot[i];
+            if (l < 56)
+                pcr[j] = pc1m[l];
+            else
+                pcr[j] = pc1m[l - 28];
+        }
+        for (j = 0; j < 24; j++) {
+            if ((int) pcr[(int) pc2[j]] != 0)
+                kn[m] |= bigbyte[j];
+            if ((int) pcr[(int) pc2[j + 24]] != 0)
+                kn[n] |= bigbyte[j];
+        }
+    }
+
+    cookey(kn, keyout);
+}
+
+
+static void desfunc(u32 *block, const u32 *keys)
+{
+    u32 work, right, leftt;
+    int cur_round;
+
+    leftt = block[0];
+    right = block[1];
+
+    work = ((leftt >> 4)  ^ right) & 0x0f0f0f0fL;
+    right ^= work;
+    leftt ^= (work << 4);
+
+    work = ((leftt >> 16) ^ right) & 0x0000ffffL;
+    right ^= work;
+    leftt ^= (work << 16);
+
+    work = ((right >> 2)  ^ leftt) & 0x33333333L;
+    leftt ^= work;
+    right ^= (work << 2);
+
+    work = ((right >> 8)  ^ leftt) & 0x00ff00ffL;
+    leftt ^= work;
+    right ^= (work << 8);
+
+    right = ROLc(right, 1);
+    work = (leftt ^ right) & 0xaaaaaaaaL;
+
+    leftt ^= work;
+    right ^= work;
+    leftt = ROLc(leftt, 1);
+
+    for (cur_round = 0; cur_round < 8; cur_round++) {
+        work  = RORc(right, 4) ^ *keys++;
+        leftt ^= SP7[work        & 0x3fL]
+            ^ SP5[(work >>  8) & 0x3fL]
+            ^ SP3[(work >> 16) & 0x3fL]
+            ^ SP1[(work >> 24) & 0x3fL];
+        work  = right ^ *keys++;
+        leftt ^= SP8[ work        & 0x3fL]
+            ^  SP6[(work >>  8) & 0x3fL]
+            ^  SP4[(work >> 16) & 0x3fL]
+            ^  SP2[(work >> 24) & 0x3fL];
+
+        work = RORc(leftt, 4) ^ *keys++;
+        right ^= SP7[ work        & 0x3fL]
+            ^  SP5[(work >>  8) & 0x3fL]
+            ^  SP3[(work >> 16) & 0x3fL]
+            ^  SP1[(work >> 24) & 0x3fL];
+        work  = leftt ^ *keys++;
+        right ^= SP8[ work        & 0x3fL]
+            ^  SP6[(work >>  8) & 0x3fL]
+            ^  SP4[(work >> 16) & 0x3fL]
+            ^  SP2[(work >> 24) & 0x3fL];
+    }
+
+    right = RORc(right, 1);
+    work = (leftt ^ right) & 0xaaaaaaaaL;
+    leftt ^= work;
+    right ^= work;
+    leftt = RORc(leftt, 1);
+    work = ((leftt >> 8) ^ right) & 0x00ff00ffL;
+    right ^= work;
+    leftt ^= (work << 8);
+    /* -- */
+    work = ((leftt >> 2) ^ right) & 0x33333333L;
+    right ^= work;
+    leftt ^= (work << 2);
+    work = ((right >> 16) ^ leftt) & 0x0000ffffL;
+    leftt ^= work;
+    right ^= (work << 16);
+    work = ((right >> 4) ^ leftt) & 0x0f0f0f0fL;
+    leftt ^= work;
+    right ^= (work << 4);
+
+    block[0] = right;
+    block[1] = leftt;
+}
+
+
+/* wpa_supplicant/hostapd specific wrapper */
+
+void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher)
+{
+    u8 pkey[8], next, tmp;
+    int i;
+    u32 ek[32], work[2];
+
+    /* Add parity bits to the key */
+    next = 0;
+    for (i = 0; i < 7; i++) {
+        tmp = key[i];
+        pkey[i] = (tmp >> i) | next | 1;
+        next = tmp << (7 - i);
+    }
+    pkey[i] = next | 1;
+
+    deskey(pkey, 0, ek);
+
+    work[0] = WPA_GET_BE32(clear);
+    work[1] = WPA_GET_BE32(clear + 4);
+    desfunc(work, ek);
+    WPA_PUT_BE32(cypher, work[0]);
+    WPA_PUT_BE32(cypher + 4, work[1]);
+
+    os_memset(pkey, 0, sizeof(pkey));
+    os_memset(ek, 0, sizeof(ek));
+}
+
+/*
+void des_key_setup(const u8 *key, u32 *ek, u32 *dk)
+{
+    deskey(key, 0, ek);
+    deskey(key, 1, dk);
+}
+
+
+void des_block_encrypt(const u8 *plain, const u32 *ek, u8 *crypt)
+{
+    u32 work[2];
+    work[0] = WPA_GET_BE32(plain);
+    work[1] = WPA_GET_BE32(plain + 4);
+    desfunc(work, ek);
+    WPA_PUT_BE32(crypt, work[0]);
+    WPA_PUT_BE32(crypt + 4, work[1]);
+}
+
+
+void des_block_decrypt(const u8 *crypt, const u32 *dk, u8 *plain)
+{
+    u32 work[2];
+    work[0] = WPA_GET_BE32(crypt);
+    work[1] = WPA_GET_BE32(crypt + 4);
+    desfunc(work, dk);
+    WPA_PUT_BE32(plain, work[0]);
+    WPA_PUT_BE32(plain + 4, work[1]);
+}
+
+
+void des3_key_setup(const u8 *key, struct des3_key_s *dkey)
+{
+    deskey(key, 0, dkey->ek[0]);
+    deskey(key + 8, 1, dkey->ek[1]);
+    deskey(key + 16, 0, dkey->ek[2]);
+
+    deskey(key, 1, dkey->dk[2]);
+    deskey(key + 8, 0, dkey->dk[1]);
+    deskey(key + 16, 1, dkey->dk[0]);
+}
+
+
+void des3_encrypt(const u8 *plain, const struct des3_key_s *key, u8 *crypt)
+{
+    u32 work[2];
+
+    work[0] = WPA_GET_BE32(plain);
+    work[1] = WPA_GET_BE32(plain + 4);
+    desfunc(work, key->ek[0]);
+    desfunc(work, key->ek[1]);
+    desfunc(work, key->ek[2]);
+    WPA_PUT_BE32(crypt, work[0]);
+    WPA_PUT_BE32(crypt + 4, work[1]);
+}
+
+
+void des3_decrypt(const u8 *crypt, const struct des3_key_s *key, u8 *plain)
+{
+    u32 work[2];
+
+    work[0] = WPA_GET_BE32(crypt);
+    work[1] = WPA_GET_BE32(crypt + 4);
+    desfunc(work, key->dk[0]);
+    desfunc(work, key->dk[1]);
+    desfunc(work, key->dk[2]);
+    WPA_PUT_BE32(plain, work[0]);
+    WPA_PUT_BE32(plain + 4, work[1]);
+}*/
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/dh_group5.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/dh_group5.c
new file mode 100644
index 0000000000000000000000000000000000000000..5f4550c901f2c2aa587553b03ace30abb354246f
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/dh_group5.c
@@ -0,0 +1,43 @@
+/*
+ * Diffie-Hellman group 5 operations
+ * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/dh_groups.h"
+#include "crypto/dh_group5.h"
+
+
+void *
+dh5_init(struct wpabuf **priv, struct wpabuf **publ)
+{
+    *publ = dh_init(dh_groups_get(5), priv);
+    if (*publ == 0)
+        return NULL;
+    return (void *) 1;
+}
+
+
+struct wpabuf *
+dh5_derive_shared(void *ctx, const struct wpabuf *peer_public,
+                  const struct wpabuf *own_private)
+{
+    return dh_derive_shared(peer_public, own_private, dh_groups_get(5));
+}
+
+
+void
+dh5_free(void *ctx)
+{
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/dh_groups.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/dh_groups.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ce22435229c01f025eb9e83e666eeb9ae4ef9f8
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/dh_groups.c
@@ -0,0 +1,654 @@
+/*
+ * Diffie-Hellman groups
+ * Copyright (c) 2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+#include "crypto/random.h"
+#include "crypto/dh_groups.h"
+#include "wpa/wpabuf.h"
+#include "wpa/wpa_debug.h"
+#include "esp_wifi_crypto_types.h"
+
+extern wps_crypto_funcs_t wps_crypto_funcs;
+
+#ifdef ALL_DH_GROUPS
+
+/* RFC 4306, B.1. Group 1 - 768 Bit MODP
+ * Generator: 2
+ * Prime: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
+ */
+static const u8 dh_group1_generator[1] = { 0x02 };
+static const u8 dh_group1_prime[96] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 4306, B.2. Group 2 - 1024 Bit MODP
+ * Generator: 2
+ * Prime: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }
+ */
+static const u8 dh_group2_generator[1] = { 0x02 };
+static const u8 dh_group2_prime[128] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#endif /* ALL_DH_GROUPS */
+
+/* RFC 3526, 2. Group 5 - 1536 Bit MODP
+ * Generator: 2
+ * Prime: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
+ */
+static const u8 dh_group5_generator[1] = { 0x02 };
+static const u8 dh_group5_prime[192] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#ifdef ALL_DH_GROUPS
+
+/* RFC 3526, 3. Group 14 - 2048 Bit MODP
+ * Generator: 2
+ * Prime: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
+ */
+static const u8 dh_group14_generator[1] = { 0x02 };
+static const u8 dh_group14_prime[256] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 4. Group 15 - 3072 Bit MODP
+ * Generator: 2
+ * Prime: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
+ */
+static const u8 dh_group15_generator[1] = { 0x02 };
+static const u8 dh_group15_prime[384] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+    0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+    0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+    0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+    0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+    0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 5. Group 16 - 4096 Bit MODP
+ * Generator: 2
+ * Prime: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
+ */
+static const u8 dh_group16_generator[1] = { 0x02 };
+static const u8 dh_group16_prime[512] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+    0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+    0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+    0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+    0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+    0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+    0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+    0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+    0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+    0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+    0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+    0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+    0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+    0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+    0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+    0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+    0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 6. Group 17 - 6144 Bit MODP
+ * Generator: 2
+ * Prime: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }
+ */
+static const u8 dh_group17_generator[1] = { 0x02 };
+static const u8 dh_group17_prime[768] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+    0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+    0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+    0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+    0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+    0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+    0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+    0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+    0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+    0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+    0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+    0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+    0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+    0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+    0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+    0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+    0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+    0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
+    0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
+    0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+    0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
+    0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
+    0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+    0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
+    0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
+    0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+    0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
+    0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
+    0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+    0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
+    0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
+    0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+    0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
+    0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
+    0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+    0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
+    0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
+    0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+    0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
+    0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
+    0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+    0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
+    0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
+    0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+    0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
+    0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
+    0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+    0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
+    0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+/* RFC 3526, 7. Group 18 - 8192 Bit MODP
+ * Generator: 2
+ * Prime: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }
+ */
+static const u8 dh_group18_generator[1] = { 0x02 };
+static const u8 dh_group18_prime[1024] = {
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+    0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
+    0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
+    0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
+    0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
+    0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
+    0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
+    0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
+    0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
+    0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
+    0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
+    0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
+    0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
+    0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
+    0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
+    0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
+    0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
+    0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
+    0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
+    0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
+    0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
+    0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
+    0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
+    0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
+    0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
+    0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
+    0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
+    0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
+    0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
+    0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
+    0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
+    0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
+    0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
+    0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
+    0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
+    0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
+    0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
+    0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
+    0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
+    0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
+    0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
+    0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
+    0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
+    0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
+    0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
+    0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
+    0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
+    0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
+    0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
+    0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
+    0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
+    0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
+    0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
+    0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
+    0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
+    0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
+    0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
+    0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
+    0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
+    0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
+    0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
+    0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
+    0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
+    0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
+    0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
+    0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
+    0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
+    0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
+    0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
+    0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
+    0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
+    0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
+    0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
+    0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
+    0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
+    0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
+    0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
+    0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
+    0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
+    0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
+    0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
+    0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
+    0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
+    0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
+    0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
+    0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
+    0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
+    0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
+    0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
+    0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
+    0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
+    0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
+    0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
+    0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
+    0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59,
+    0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
+    0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C,
+    0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
+    0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
+    0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
+    0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66,
+    0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
+    0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78,
+    0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
+    0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
+    0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
+    0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7,
+    0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
+    0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD,
+    0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
+    0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
+    0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
+    0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D,
+    0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
+    0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1,
+    0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
+    0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
+    0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
+    0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68,
+    0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
+    0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7,
+    0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
+    0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
+    0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
+    0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF,
+    0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
+    0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF,
+    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
+};
+
+#endif /* ALL_DH_GROUPS */
+
+
+#define DH_GROUP(id) \
+{ id, dh_group ## id ## _generator, sizeof(dh_group ## id ## _generator), \
+dh_group ## id ## _prime, sizeof(dh_group ## id ## _prime) }
+
+
+static struct dh_group dh_groups[] = {
+    DH_GROUP(5),
+#ifdef ALL_DH_GROUPS
+    DH_GROUP(1),
+    DH_GROUP(2),
+    DH_GROUP(14),
+    DH_GROUP(15),
+    DH_GROUP(16),
+    DH_GROUP(17),
+    DH_GROUP(18)
+#endif /* ALL_DH_GROUPS */
+};
+
+#define NUM_DH_GROUPS (sizeof(dh_groups) / sizeof(dh_groups[0]))
+
+
+const struct dh_group *
+dh_groups_get(int id)
+{
+    size_t i;
+
+    for (i = 0; i < NUM_DH_GROUPS; i++) {
+        if (dh_groups[i].id == id)
+            return &dh_groups[i];
+    }
+    return NULL;
+}
+
+/**
+ * dh_init - Initialize Diffie-Hellman handshake
+ * @dh: Selected Diffie-Hellman group
+ * @priv: Pointer for returning Diffie-Hellman private key
+ * Returns: Diffie-Hellman public value
+ */
+struct wpabuf *
+dh_init(const struct dh_group *dh, struct wpabuf **priv)
+{
+    struct wpabuf *pv;
+    size_t pv_len;
+
+    if (dh == NULL)
+        return NULL;
+
+    wpabuf_free(*priv);
+    *priv = wpabuf_alloc(dh->prime_len);
+    if (*priv == NULL)
+        return NULL;
+
+    if (random_get_bytes(wpabuf_put(*priv, dh->prime_len), dh->prime_len))
+    {
+        wpabuf_free(*priv);
+        *priv = NULL;
+        return NULL;
+    }
+
+    if (os_memcmp(wpabuf_head(*priv), dh->prime, dh->prime_len) > 0) {
+        /* Make sure private value is smaller than prime */
+        *(wpabuf_mhead_u8(*priv)) = 0;
+    }
+    wpa_hexdump_buf_key(MSG_DEBUG, "DH: private value", *priv);
+
+    pv_len = dh->prime_len;
+    pv = wpabuf_alloc(pv_len);
+    if (pv == NULL)
+        return NULL;
+
+    if (wps_crypto_funcs.crypto_mod_exp) {
+        if (wps_crypto_funcs.crypto_mod_exp(dh->generator, dh->generator_len,
+                            wpabuf_head(*priv), wpabuf_len(*priv),
+                            dh->prime, dh->prime_len, wpabuf_mhead(pv),
+                            &pv_len)) {
+            wpabuf_free(pv);
+            wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+            return NULL;
+        }
+    } else {
+        wpabuf_free(pv);
+        wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+        return NULL;
+    }
+    wpabuf_put(pv, pv_len);
+    wpa_hexdump_buf(MSG_DEBUG, "DH: public value", pv);
+
+    return pv;
+}
+
+
+/**
+ * dh_derive_shared - Derive shared Diffie-Hellman key
+ * @peer_public: Diffie-Hellman public value from peer
+ * @own_private: Diffie-Hellman private key from dh_init()
+ * @dh: Selected Diffie-Hellman group
+ * Returns: Diffie-Hellman shared key
+ */
+struct wpabuf *
+dh_derive_shared(const struct wpabuf *peer_public,
+                 const struct wpabuf *own_private,
+                 const struct dh_group *dh)
+{
+    struct wpabuf *shared;
+    size_t shared_len;
+
+    if (dh == NULL || peer_public == NULL || own_private == NULL)
+        return NULL;
+
+    shared_len = dh->prime_len;
+    shared = wpabuf_alloc(shared_len);
+    if (shared == NULL)
+        return NULL;
+
+    if (wps_crypto_funcs.crypto_mod_exp) {
+        if (wps_crypto_funcs.crypto_mod_exp(wpabuf_head(peer_public), wpabuf_len(peer_public),
+                            wpabuf_head(own_private), wpabuf_len(own_private),
+                            dh->prime, dh->prime_len,
+                            wpabuf_mhead(shared), &shared_len)) {
+            wpabuf_free(shared);
+            wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+            return NULL;
+        }
+    } else {
+        wpabuf_free(shared);
+        wpa_printf(MSG_INFO, "DH: crypto_mod_exp failed");
+        return NULL;
+    }
+
+    wpabuf_put(shared, shared_len);
+    wpa_hexdump_buf_key(MSG_DEBUG, "DH: shared key", shared);
+
+    return shared;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/libtommath.h b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/libtommath.h
new file mode 100644
index 0000000000000000000000000000000000000000..1d16f95e5435a9fa19d44d8f9a82667599972e84
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/libtommath.h
@@ -0,0 +1,3454 @@
+/*
+ * Minimal code for RSA support from LibTomMath 0.41
+ * http://libtom.org/
+ * http://libtom.org/files/ltm-0.41.tar.bz2
+ * This library was released in public domain by Tom St Denis.
+ *
+ * The combination in this file may not use all of the optimized algorithms
+ * from LibTomMath and may be considerable slower than the LibTomMath with its
+ * default settings. The main purpose of having this version here is to make it
+ * easier to build bignum.c wrapper without having to install and build an
+ * external library.
+ *
+ * If CONFIG_INTERNAL_LIBTOMMATH is defined, bignum.c includes this
+ * libtommath.c file instead of using the external LibTomMath library.
+ */
+
+#ifndef LIBTOMMATH_H
+#define LIBTOMMATH_H
+
+//#include "c_types.h"
+#include "os.h"
+#include "stdarg.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef CHAR_BIT
+#define CHAR_BIT 8
+#endif
+
+#define BN_MP_INVMOD_C
+#define BN_S_MP_EXPTMOD_C /* Note: #undef in tommath_superclass.h; this would
+               * require BN_MP_EXPTMOD_FAST_C instead */
+#define BN_S_MP_MUL_DIGS_C
+#define BN_MP_INVMOD_SLOW_C
+#define BN_S_MP_SQR_C
+#define BN_S_MP_MUL_HIGH_DIGS_C /* Note: #undef in tommath_superclass.h; this
+                 * would require other than mp_reduce */
+
+#ifdef LTM_FAST
+
+/* Use faster div at the cost of about 1 kB */
+#define BN_MP_MUL_D_C
+
+/* Include faster exptmod (Montgomery) at the cost of about 2.5 kB in code */
+#define BN_MP_EXPTMOD_FAST_C
+#define BN_MP_MONTGOMERY_SETUP_C
+#define BN_FAST_MP_MONTGOMERY_REDUCE_C
+#define BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+#define BN_MP_MUL_2_C
+
+/* Include faster sqr at the cost of about 0.5 kB in code */
+#define BN_FAST_S_MP_SQR_C
+
+#else /* LTM_FAST */
+
+#define BN_MP_DIV_SMALL
+#define BN_MP_INIT_MULTI_C
+#define BN_MP_CLEAR_MULTI_C
+#define BN_MP_ABS_C
+#endif /* LTM_FAST */
+
+/* Current uses do not require support for negative exponent in exptmod, so we
+ * can save about 1.5 kB in leaving out invmod. */
+#define LTM_NO_NEG_EXP
+
+/* from tommath.h */
+
+#ifndef MIN
+   #define MIN(x,y) ((x)<(y)?(x):(y))
+#endif
+
+#ifndef MAX
+   #define MAX(x,y) ((x)>(y)?(x):(y))
+#endif
+
+#define  OPT_CAST(x) (x *)
+
+typedef unsigned long mp_digit;
+typedef u64 mp_word;
+
+#define DIGIT_BIT          28
+#define MP_28BIT
+
+
+#define XMALLOC  os_malloc
+#define XFREE    os_free
+#define XREALLOC os_realloc
+
+
+#define MP_MASK          ((((mp_digit)1)<<((mp_digit)DIGIT_BIT))-((mp_digit)1))
+
+#define MP_LT        -1   /* less than */
+#define MP_EQ         0   /* equal to */
+#define MP_GT         1   /* greater than */
+
+#define MP_ZPOS       0   /* positive integer */
+#define MP_NEG        1   /* negative */
+
+#define MP_OKAY       0   /* ok result */
+#define MP_MEM        -2  /* out of mem */
+#define MP_VAL        -3  /* invalid input */
+
+#define MP_YES        1   /* yes response */
+#define MP_NO         0   /* no response */
+
+typedef int           mp_err;
+
+/* define this to use lower memory usage routines (exptmods mostly) */
+#define MP_LOW_MEM
+
+/* default precision */
+#ifndef MP_PREC
+   #ifndef MP_LOW_MEM
+      #define MP_PREC                 32     /* default digits of precision */
+   #else
+      #define MP_PREC                 8      /* default digits of precision */
+   #endif
+#endif
+
+/* size of comba arrays, should be at least 2 * 2**(BITS_PER_WORD - BITS_PER_DIGIT*2) */
+#define MP_WARRAY               (1 << (sizeof(mp_word) * CHAR_BIT - 2 * DIGIT_BIT + 1))
+
+/* the infamous mp_int structure */
+typedef struct  {
+    int used, alloc, sign;
+    mp_digit *dp;
+} mp_int;
+
+
+/* ---> Basic Manipulations <--- */
+#define mp_iszero(a) (((a)->used == 0) ? MP_YES : MP_NO)
+#define mp_iseven(a) (((a)->used > 0 && (((a)->dp[0] & 1) == 0)) ? MP_YES : MP_NO)
+#define mp_isodd(a)  (((a)->used > 0 && (((a)->dp[0] & 1) == 1)) ? MP_YES : MP_NO)
+
+
+/* prototypes for copied functions */
+#define s_mp_mul(a, b, c) s_mp_mul_digs(a, b, c, (a)->used + (b)->used + 1)
+static int s_mp_exptmod(mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+static int s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+static int s_mp_sqr(mp_int * a, mp_int * b);
+static int s_mp_mul_high_digs(mp_int * a, mp_int * b, mp_int * c, int digs);
+
+static int fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs);
+
+#ifdef BN_MP_INIT_MULTI_C
+static int mp_init_multi(mp_int *mp, ...);
+#endif
+#ifdef BN_MP_CLEAR_MULTI_C
+static void mp_clear_multi(mp_int *mp, ...);
+#endif
+static int mp_lshd(mp_int * a, int b);
+static void mp_set(mp_int * a, mp_digit b);
+static void mp_clamp(mp_int * a);
+static void mp_exch(mp_int * a, mp_int * b);
+static void mp_rshd(mp_int * a, int b);
+static void mp_zero(mp_int * a);
+static int mp_mod_2d(mp_int * a, int b, mp_int * c);
+static int mp_div_2d(mp_int * a, int b, mp_int * c, mp_int * d);
+static int mp_init_copy(mp_int * a, mp_int * b);
+static int mp_mul_2d(mp_int * a, int b, mp_int * c);
+#ifndef LTM_NO_NEG_EXP
+static int mp_div_2(mp_int * a, mp_int * b);
+static int mp_invmod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_invmod_slow(mp_int * a, mp_int * b, mp_int * c);
+#endif /* LTM_NO_NEG_EXP */
+static int mp_copy(mp_int * a, mp_int * b);
+static int mp_count_bits(mp_int * a);
+static int mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d);
+static int mp_mod(mp_int * a, mp_int * b, mp_int * c);
+static int mp_grow(mp_int * a, int size);
+static int mp_cmp_mag(mp_int * a, mp_int * b);
+#ifdef BN_MP_ABS_C
+static int mp_abs(mp_int * a, mp_int * b);
+#endif
+static int mp_sqr(mp_int * a, mp_int * b);
+static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d);
+static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d);
+static int mp_2expt(mp_int * a, int b);
+static int mp_reduce_setup(mp_int * a, mp_int * b);
+static int mp_reduce(mp_int * x, mp_int * m, mp_int * mu);
+static int mp_init_size(mp_int * a, int size);
+#ifdef BN_MP_EXPTMOD_FAST_C
+static int mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode);
+#endif /* BN_MP_EXPTMOD_FAST_C */
+#ifdef BN_FAST_S_MP_SQR_C
+static int fast_s_mp_sqr (mp_int * a, mp_int * b);
+#endif /* BN_FAST_S_MP_SQR_C */
+#ifdef BN_MP_MUL_D_C
+static int mp_mul_d (mp_int * a, mp_digit b, mp_int * c);
+#endif /* BN_MP_MUL_D_C */
+
+
+
+/* functions from bn_<func name>.c */
+
+
+/* reverse an array, used for radix code */
+static void
+bn_reverse (unsigned char *s, int len)
+{
+  int     ix, iy;
+  unsigned char t;
+
+  ix = 0;
+  iy = len - 1;
+  while (ix < iy) {
+    t     = s[ix];
+    s[ix] = s[iy];
+    s[iy] = t;
+    ++ix;
+    --iy;
+  }
+}
+
+
+/* low level addition, based on HAC pp.594, Algorithm 14.7 */
+static int
+s_mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int *x;
+  int     olduse, res, min, max;
+
+  /* find sizes, we let |a| <= |b| which means we have to sort
+   * them.  "x" will point to the input with the most digits
+   */
+  if (a->used > b->used) {
+    min = b->used;
+    max = a->used;
+    x = a;
+  } else {
+    min = a->used;
+    max = b->used;
+    x = b;
+  }
+
+  /* init result */
+  if (c->alloc < max + 1) {
+    if ((res = mp_grow (c, max + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get old used digit count and set new one */
+  olduse = c->used;
+  c->used = max + 1;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+
+    /* first input */
+    tmpa = a->dp;
+
+    /* second input */
+    tmpb = b->dp;
+
+    /* destination */
+    tmpc = c->dp;
+
+    /* zero the carry */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* Compute the sum at one digit, T[i] = A[i] + B[i] + U */
+      *tmpc = *tmpa++ + *tmpb++ + u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+      /* take away carry bit from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, that is in A+B
+     * if A or B has more digits add those in
+     */
+    if (min != max) {
+      for (; i < max; i++) {
+        /* T[i] = X[i] + U */
+        *tmpc = x->dp[i] + u;
+
+        /* U = carry bit of T[i] */
+        u = *tmpc >> ((mp_digit)DIGIT_BIT);
+
+        /* take away carry bit from T[i] */
+        *tmpc++ &= MP_MASK;
+      }
+    }
+
+    /* add carry */
+    *tmpc++ = u;
+
+    /* clear digits above oldused */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* low level subtraction (assumes |a| > |b|), HAC pp.595 Algorithm 14.9 */
+static int
+s_mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     olduse, res, min, max;
+
+  /* find sizes */
+  min = b->used;
+  max = a->used;
+
+  /* init result */
+  if (c->alloc < max) {
+    if ((res = mp_grow (c, max)) != MP_OKAY) {
+      return res;
+    }
+  }
+  olduse = c->used;
+  c->used = max;
+
+  {
+    register mp_digit u, *tmpa, *tmpb, *tmpc;
+    register int i;
+
+    /* alias for digit pointers */
+    tmpa = a->dp;
+    tmpb = b->dp;
+    tmpc = c->dp;
+
+    /* set carry to zero */
+    u = 0;
+    for (i = 0; i < min; i++) {
+      /* T[i] = A[i] - B[i] - U */
+      *tmpc = *tmpa++ - *tmpb++ - u;
+
+      /* U = carry bit of T[i]
+       * Note this saves performing an AND operation since
+       * if a carry does occur it will propagate all the way to the
+       * MSB.  As a result a single shift is enough to get the carry
+       */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* now copy higher words if any, e.g. if A has more digits than B  */
+    for (; i < max; i++) {
+      /* T[i] = A[i] - U */
+      *tmpc = *tmpa++ - u;
+
+      /* U = carry bit of T[i] */
+      u = *tmpc >> ((mp_digit)(CHAR_BIT * sizeof (mp_digit) - 1));
+
+      /* Clear carry from T[i] */
+      *tmpc++ &= MP_MASK;
+    }
+
+    /* clear digits above used (since we may not have grown result above) */
+    for (i = c->used; i < olduse; i++) {
+      *tmpc++ = 0;
+    }
+  }
+
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* init a new mp_int */
+static int
+mp_init (mp_int * a)
+{
+  int i;
+
+  /* allocate memory required and clear it */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * MP_PREC);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the digits to zero */
+  for (i = 0; i < MP_PREC; i++) {
+      a->dp[i] = 0;
+  }
+
+  /* set the used to zero, allocated digits to the default precision
+   * and sign to positive */
+  a->used  = 0;
+  a->alloc = MP_PREC;
+  a->sign  = MP_ZPOS;
+
+  return MP_OKAY;
+}
+
+
+/* clear one (frees)  */
+static void
+mp_clear (mp_int * a)
+{
+  int i;
+
+  /* only do anything if a hasn't been freed previously */
+  if (a->dp != NULL) {
+    /* first zero the digits */
+    for (i = 0; i < a->used; i++) {
+        a->dp[i] = 0;
+    }
+
+    /* free ram */
+    XFREE(a->dp);
+
+    /* reset members to make debugging easier */
+    a->dp    = NULL;
+    a->alloc = a->used = 0;
+    a->sign  = MP_ZPOS;
+  }
+}
+
+
+/* high level addition (handles signs) */
+static int
+mp_add (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  /* get sign of both inputs */
+  sa = a->sign;
+  sb = b->sign;
+
+  /* handle two cases, not four */
+  if (sa == sb) {
+    /* both positive or both negative */
+    /* add their magnitudes, copy the sign */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* one positive, the other negative */
+    /* subtract the one with the greater magnitude from */
+    /* the one of the lesser magnitude.  The result gets */
+    /* the sign of the one with the greater magnitude. */
+    if (mp_cmp_mag (a, b) == MP_LT) {
+      c->sign = sb;
+      res = s_mp_sub (b, a, c);
+    } else {
+      c->sign = sa;
+      res = s_mp_sub (a, b, c);
+    }
+  }
+  return res;
+}
+
+
+/* high level subtraction (handles signs) */
+static int
+mp_sub (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     sa, sb, res;
+
+  sa = a->sign;
+  sb = b->sign;
+
+  if (sa != sb) {
+    /* subtract a negative from a positive, OR */
+    /* subtract a positive from a negative. */
+    /* In either case, ADD their magnitudes, */
+    /* and use the sign of the first number. */
+    c->sign = sa;
+    res = s_mp_add (a, b, c);
+  } else {
+    /* subtract a positive from a positive, OR */
+    /* subtract a negative from a negative. */
+    /* First, take the difference between their */
+    /* magnitudes, then... */
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      /* Copy the sign from the first */
+      c->sign = sa;
+      /* The first has a larger or equal magnitude */
+      res = s_mp_sub (a, b, c);
+    } else {
+      /* The result has the *opposite* sign from */
+      /* the first number. */
+      c->sign = (sa == MP_ZPOS) ? MP_NEG : MP_ZPOS;
+      /* The second has a larger magnitude */
+      res = s_mp_sub (b, a, c);
+    }
+  }
+  return res;
+}
+
+
+/* high level multiplication (handles sign) */
+static int
+mp_mul (mp_int * a, mp_int * b, mp_int * c)
+{
+  int     res, neg;
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+
+  /* use Toom-Cook? */
+#ifdef BN_MP_TOOM_MUL_C
+  if (MIN (a->used, b->used) >= TOOM_MUL_CUTOFF) {
+    res = mp_toom_mul(a, b, c);
+  } else
+#endif
+#ifdef BN_MP_KARATSUBA_MUL_C
+  /* use Karatsuba? */
+  if (MIN (a->used, b->used) >= KARATSUBA_MUL_CUTOFF) {
+    res = mp_karatsuba_mul (a, b, c);
+  } else
+#endif
+  {
+    /* can we use the fast multiplier?
+     *
+     * The fast multiplier can be used if the output will
+     * have less than MP_WARRAY digits and the number of
+     * digits won't affect carry propagation
+     */
+#ifdef BN_FAST_S_MP_MUL_DIGS_C
+    int     digs = a->used + b->used + 1;
+
+    if ((digs < MP_WARRAY) &&
+        MIN(a->used, b->used) <=
+        (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+      res = fast_s_mp_mul_digs (a, b, c, digs);
+    } else
+#endif
+#ifdef BN_S_MP_MUL_DIGS_C
+      res = s_mp_mul (a, b, c); /* uses s_mp_mul_digs */
+#else
+#error mp_mul could fail
+      res = MP_VAL;
+#endif
+
+  }
+  c->sign = (c->used > 0) ? neg : MP_ZPOS;
+  return res;
+}
+
+
+/* d = a * b (mod c) */
+static int
+mp_mulmod (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  int     res;
+  mp_int  t;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_mul (a, b, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+  res = mp_mod (&t, c, d);
+  mp_clear (&t);
+  return res;
+}
+
+
+/* c = a mod b, 0 <= c < b */
+static int
+mp_mod (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  t;
+  int     res;
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  if ((res = mp_div (a, b, NULL, &t)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  if (t.sign != b->sign) {
+    res = mp_add (b, &t, c);
+  } else {
+    res = MP_OKAY;
+    mp_exch (&t, c);
+  }
+
+  mp_clear (&t);
+  return res;
+}
+
+
+/* this is a shell function that calls either the normal or Montgomery
+ * exptmod functions.  Originally the call to the montgomery code was
+ * embedded in the normal function but that wasted a lot of stack space
+ * for nothing (since 99% of the time the Montgomery code would be called)
+ */
+static int
+mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y)
+{
+  int dr;
+
+  /* modulus P must be positive */
+  if (P->sign == MP_NEG) {
+     return MP_VAL;
+  }
+
+  /* if exponent X is negative we have to recurse */
+  if (X->sign == MP_NEG) {
+#ifdef LTM_NO_NEG_EXP
+        return MP_VAL;
+#else /* LTM_NO_NEG_EXP */
+#ifdef BN_MP_INVMOD_C
+     mp_int tmpG, tmpX;
+     int err;
+
+     /* first compute 1/G mod P */
+     if ((err = mp_init(&tmpG)) != MP_OKAY) {
+        return err;
+     }
+     if ((err = mp_invmod(G, P, &tmpG)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+
+     /* now get |X| */
+     if ((err = mp_init(&tmpX)) != MP_OKAY) {
+        mp_clear(&tmpG);
+        return err;
+     }
+     if ((err = mp_abs(X, &tmpX)) != MP_OKAY) {
+        mp_clear_multi(&tmpG, &tmpX, NULL);
+        return err;
+     }
+
+     /* and now compute (1/G)**|X| instead of G**X [X < 0] */
+     err = mp_exptmod(&tmpG, &tmpX, P, Y);
+     mp_clear_multi(&tmpG, &tmpX, NULL);
+     return err;
+#else
+#error mp_exptmod would always fail
+     /* no invmod */
+     return MP_VAL;
+#endif
+#endif /* LTM_NO_NEG_EXP */
+  }
+
+/* modified diminished radix reduction */
+#if defined(BN_MP_REDUCE_IS_2K_L_C) && defined(BN_MP_REDUCE_2K_L_C) && defined(BN_S_MP_EXPTMOD_C)
+  if (mp_reduce_is_2k_l(P) == MP_YES) {
+     return s_mp_exptmod(G, X, P, Y, 1);
+  }
+#endif
+
+#ifdef BN_MP_DR_IS_MODULUS_C
+  /* is it a DR modulus? */
+  dr = mp_dr_is_modulus(P);
+#else
+  /* default to no */
+  dr = 0;
+#endif
+
+#ifdef BN_MP_REDUCE_IS_2K_C
+  /* if not, is it a unrestricted DR modulus? */
+  if (dr == 0) {
+     dr = mp_reduce_is_2k(P) << 1;
+  }
+#endif
+
+  /* if the modulus is odd or dr != 0 use the montgomery method */
+#ifdef BN_MP_EXPTMOD_FAST_C
+  if (mp_isodd (P) == 1 || dr !=  0) {
+    return mp_exptmod_fast (G, X, P, Y, dr);
+  } else {
+#endif
+#ifdef BN_S_MP_EXPTMOD_C
+    (void) dr;
+    /* otherwise use the generic Barrett reduction technique */
+    return s_mp_exptmod (G, X, P, Y, 0);
+#else
+#error mp_exptmod could fail
+    /* no exptmod for evens */
+    return MP_VAL;
+#endif
+#ifdef BN_MP_EXPTMOD_FAST_C
+  }
+#endif
+}
+
+
+/* compare two ints (signed)*/
+static int
+mp_cmp (mp_int * a, mp_int * b)
+{
+  /* compare based on sign */
+  if (a->sign != b->sign) {
+     if (a->sign == MP_NEG) {
+        return MP_LT;
+     } else {
+        return MP_GT;
+     }
+  }
+
+  /* compare digits */
+  if (a->sign == MP_NEG) {
+     /* if negative compare opposite direction */
+     return mp_cmp_mag(b, a);
+  } else {
+     return mp_cmp_mag(a, b);
+  }
+}
+
+
+/* compare a digit */
+static int
+mp_cmp_d(mp_int * a, mp_digit b)
+{
+  /* compare based on sign */
+  if (a->sign == MP_NEG) {
+    return MP_LT;
+  }
+
+  /* compare based on magnitude */
+  if (a->used > 1) {
+    return MP_GT;
+  }
+
+  /* compare the only digit of a to b */
+  if (a->dp[0] > b) {
+    return MP_GT;
+  } else if (a->dp[0] < b) {
+    return MP_LT;
+  } else {
+    return MP_EQ;
+  }
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* hac 14.61, pp608 */
+static int
+mp_invmod (mp_int * a, mp_int * b, mp_int * c)
+{
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+#ifdef BN_FAST_MP_INVMOD_C
+  /* if the modulus is odd we can use a faster routine instead */
+  if (mp_isodd (b) == 1) {
+    return fast_mp_invmod (a, b, c);
+  }
+#endif
+
+#ifdef BN_MP_INVMOD_SLOW_C
+  return mp_invmod_slow(a, b, c);
+#endif
+
+#ifndef BN_FAST_MP_INVMOD_C
+#ifndef BN_MP_INVMOD_SLOW_C
+#error mp_invmod would always fail
+#endif
+#endif
+  return MP_VAL;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* get the size for an unsigned equivalent */
+static int
+mp_unsigned_bin_size (mp_int * a)
+{
+  int     size = mp_count_bits (a);
+  return (size / 8 + ((size & 7) != 0 ? 1 : 0));
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* hac 14.61, pp608 */
+static int
+mp_invmod_slow (mp_int * a, mp_int * b, mp_int * c)
+{
+  mp_int  x, y, u, v, A, B, C, D;
+  int     res;
+
+  /* b cannot be negative */
+  if (b->sign == MP_NEG || mp_iszero(b) == 1) {
+    return MP_VAL;
+  }
+
+  /* init temps */
+  if ((res = mp_init_multi(&x, &y, &u, &v,
+                           &A, &B, &C, &D, NULL)) != MP_OKAY) {
+     return res;
+  }
+
+  /* x = a, y = b */
+  if ((res = mp_mod(a, b, &x)) != MP_OKAY) {
+      goto LBL_ERR;
+  }
+  if ((res = mp_copy (b, &y)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+
+  /* 2. [modified] if x,y are both even then return an error! */
+  if (mp_iseven (&x) == 1 && mp_iseven (&y) == 1) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
+  if ((res = mp_copy (&x, &u)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  if ((res = mp_copy (&y, &v)) != MP_OKAY) {
+    goto LBL_ERR;
+  }
+  mp_set (&A, 1);
+  mp_set (&D, 1);
+
+top:
+  /* 4.  while u is even do */
+  while (mp_iseven (&u) == 1) {
+    /* 4.1 u = u/2 */
+    if ((res = mp_div_2 (&u, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 4.2 if A or B is odd then */
+    if (mp_isodd (&A) == 1 || mp_isodd (&B) == 1) {
+      /* A = (A+y)/2, B = (B-x)/2 */
+      if ((res = mp_add (&A, &y, &A)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&B, &x, &B)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* A = A/2, B = B/2 */
+    if ((res = mp_div_2 (&A, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&B, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 5.  while v is even do */
+  while (mp_iseven (&v) == 1) {
+    /* 5.1 v = v/2 */
+    if ((res = mp_div_2 (&v, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    /* 5.2 if C or D is odd then */
+    if (mp_isodd (&C) == 1 || mp_isodd (&D) == 1) {
+      /* C = (C+y)/2, D = (D-x)/2 */
+      if ((res = mp_add (&C, &y, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+      if ((res = mp_sub (&D, &x, &D)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+    }
+    /* C = C/2, D = D/2 */
+    if ((res = mp_div_2 (&C, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+    if ((res = mp_div_2 (&D, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* 6.  if u >= v then */
+  if (mp_cmp (&u, &v) != MP_LT) {
+    /* u = u - v, A = A - C, B = B - D */
+    if ((res = mp_sub (&u, &v, &u)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&A, &C, &A)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&B, &D, &B)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  } else {
+    /* v - v - u, C = C - A, D = D - B */
+    if ((res = mp_sub (&v, &u, &v)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&C, &A, &C)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+
+    if ((res = mp_sub (&D, &B, &D)) != MP_OKAY) {
+      goto LBL_ERR;
+    }
+  }
+
+  /* if not zero goto step 4 */
+  if (mp_iszero (&u) == 0)
+    goto top;
+
+  /* now a = C, b = D, gcd == g*v */
+
+  /* if v != 1 then there is no inverse */
+  if (mp_cmp_d (&v, 1) != MP_EQ) {
+    res = MP_VAL;
+    goto LBL_ERR;
+  }
+
+  /* if its too low */
+  while (mp_cmp_d(&C, 0) == MP_LT) {
+      if ((res = mp_add(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+
+  /* too big */
+  while (mp_cmp_mag(&C, b) != MP_LT) {
+      if ((res = mp_sub(&C, b, &C)) != MP_OKAY) {
+         goto LBL_ERR;
+      }
+  }
+
+  /* C is now the inverse */
+  mp_exch (&C, c);
+  res = MP_OKAY;
+LBL_ERR:mp_clear_multi (&x, &y, &u, &v, &A, &B, &C, &D, NULL);
+  return res;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* compare maginitude of two ints (unsigned) */
+static int
+mp_cmp_mag (mp_int * a, mp_int * b)
+{
+  int     n;
+  mp_digit *tmpa, *tmpb;
+
+  /* compare based on # of non-zero digits */
+  if (a->used > b->used) {
+    return MP_GT;
+  }
+
+  if (a->used < b->used) {
+    return MP_LT;
+  }
+
+  /* alias for a */
+  tmpa = a->dp + (a->used - 1);
+
+  /* alias for b */
+  tmpb = b->dp + (a->used - 1);
+
+  /* compare based on digits  */
+  for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
+    if (*tmpa > *tmpb) {
+      return MP_GT;
+    }
+
+    if (*tmpa < *tmpb) {
+      return MP_LT;
+    }
+  }
+  return MP_EQ;
+}
+
+
+/* reads a unsigned char array, assumes the msb is stored first [big endian] */
+static int
+mp_read_unsigned_bin (mp_int * a, const unsigned char *b, int c)
+{
+  int     res;
+
+  /* make sure there are at least two digits */
+  if (a->alloc < 2) {
+     if ((res = mp_grow(a, 2)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero the int */
+  mp_zero (a);
+
+  /* read the bytes in */
+  while (c-- > 0) {
+    if ((res = mp_mul_2d (a, 8, a)) != MP_OKAY) {
+      return res;
+    }
+
+#ifndef MP_8BIT
+      a->dp[0] |= *b++;
+      a->used += 1;
+#else
+      a->dp[0] = (*b & MP_MASK);
+      a->dp[1] |= ((*b++ >> 7U) & 1);
+      a->used += 2;
+#endif
+  }
+  mp_clamp (a);
+  return MP_OKAY;
+}
+
+
+/* store in unsigned [big endian] format */
+static int
+mp_to_unsigned_bin (mp_int * a, unsigned char *b)
+{
+  int     x, res;
+  mp_int  t;
+
+  if ((res = mp_init_copy (&t, a)) != MP_OKAY) {
+    return res;
+  }
+
+  x = 0;
+  while (mp_iszero (&t) == 0) {
+#ifndef MP_8BIT
+      b[x++] = (unsigned char) (t.dp[0] & 255);
+#else
+      b[x++] = (unsigned char) (t.dp[0] | ((t.dp[1] & 0x01) << 7));
+#endif
+    if ((res = mp_div_2d (&t, 8, &t, NULL)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+  bn_reverse (b, x);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* shift right by a certain bit count (store quotient in c, optional remainder in d) */
+static int
+mp_div_2d (mp_int * a, int b, mp_int * c, mp_int * d)
+{
+  mp_digit D, r, rr;
+  int     x, res;
+  mp_int  t;
+
+
+  /* if the shift count is <= 0 then we do no work */
+  if (b <= 0) {
+    res = mp_copy (a, c);
+    if (d != NULL) {
+      mp_zero (d);
+    }
+    return res;
+  }
+
+  if ((res = mp_init (&t)) != MP_OKAY) {
+    return res;
+  }
+
+  /* get the remainder */
+  if (d != NULL) {
+    if ((res = mp_mod_2d (a, b, &t)) != MP_OKAY) {
+      mp_clear (&t);
+      return res;
+    }
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    mp_clear (&t);
+    return res;
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    mp_rshd (c, b / DIGIT_BIT);
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  D = (mp_digit) (b % DIGIT_BIT);
+  if (D != 0) {
+    register mp_digit *tmpc, mask, shift;
+
+    /* mask */
+    mask = (((mp_digit)1) << D) - 1;
+
+    /* shift for lsb */
+    shift = DIGIT_BIT - D;
+
+    /* alias */
+    tmpc = c->dp + (c->used - 1);
+
+    /* carry */
+    r = 0;
+    for (x = c->used - 1; x >= 0; x--) {
+      /* get the lower  bits of this word in a temp */
+      rr = *tmpc & mask;
+
+      /* shift the current word and mix in the carry bits from the previous word */
+      *tmpc = (*tmpc >> D) | (r << shift);
+      --tmpc;
+
+      /* set the carry to the carry bits of the current word found above */
+      r = rr;
+    }
+  }
+  mp_clamp (c);
+  if (d != NULL) {
+    mp_exch (&t, d);
+  }
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+static int
+mp_init_copy (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_init (a)) != MP_OKAY) {
+    return res;
+  }
+  return mp_copy (b, a);
+}
+
+
+/* set to zero */
+static void
+mp_zero (mp_int * a)
+{
+  int       n;
+  mp_digit *tmp;
+
+  a->sign = MP_ZPOS;
+  a->used = 0;
+
+  tmp = a->dp;
+  for (n = 0; n < a->alloc; n++) {
+     *tmp++ = 0;
+  }
+}
+
+
+/* copy, b = a */
+static int
+mp_copy (mp_int * a, mp_int * b)
+{
+  int     res, n;
+
+  /* if dst == src do nothing */
+  if (a == b) {
+    return MP_OKAY;
+  }
+
+  /* grow dest */
+  if (b->alloc < a->used) {
+     if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+        return res;
+     }
+  }
+
+  /* zero b and copy the parameters over */
+  {
+    register mp_digit *tmpa, *tmpb;
+
+    /* pointer aliases */
+
+    /* source */
+    tmpa = a->dp;
+
+    /* destination */
+    tmpb = b->dp;
+
+    /* copy all the digits */
+    for (n = 0; n < a->used; n++) {
+      *tmpb++ = *tmpa++;
+    }
+
+    /* clear high digits */
+    for (; n < b->used; n++) {
+      *tmpb++ = 0;
+    }
+  }
+
+  /* copy used count and sign */
+  b->used = a->used;
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+
+
+/* shift right a certain amount of digits */
+static void
+mp_rshd (mp_int * a, int b)
+{
+  int     x;
+
+  /* if b <= 0 then ignore it */
+  if (b <= 0) {
+    return;
+  }
+
+  /* if b > used then simply zero it and return */
+  if (a->used <= b) {
+    mp_zero (a);
+    return;
+  }
+
+  {
+    register mp_digit *bottom, *top;
+
+    /* shift the digits down */
+
+    /* bottom */
+    bottom = a->dp;
+
+    /* top [offset into digits] */
+    top = a->dp + b;
+
+    /* this is implemented as a sliding window where
+     * the window is b-digits long and digits from
+     * the top of the window are copied to the bottom
+     *
+     * e.g.
+
+     b-2 | b-1 | b0 | b1 | b2 | ... | bb |   ---->
+                 /\                   |      ---->
+                  \-------------------/      ---->
+     */
+    for (x = 0; x < (a->used - b); x++) {
+      *bottom++ = *top++;
+    }
+
+    /* zero the top digits */
+    for (; x < a->used; x++) {
+      *bottom++ = 0;
+    }
+  }
+
+  /* remove excess digits */
+  a->used -= b;
+}
+
+
+/* swap the elements of two integers, for cases where you can't simply swap the
+ * mp_int pointers around
+ */
+static void
+mp_exch (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+
+  t  = *a;
+  *a = *b;
+  *b = t;
+}
+
+
+/* trim unused digits
+ *
+ * This is used to ensure that leading zero digits are
+ * trimed and the leading "used" digit will be non-zero
+ * Typically very fast.  Also fixes the sign if there
+ * are no more leading digits
+ */
+static void
+mp_clamp (mp_int * a)
+{
+  /* decrease used while the most significant digit is
+   * zero.
+   */
+  while (a->used > 0 && a->dp[a->used - 1] == 0) {
+    --(a->used);
+  }
+
+  /* reset the sign flag if used == 0 */
+  if (a->used == 0) {
+    a->sign = MP_ZPOS;
+  }
+}
+
+
+/* grow as required */
+static int
+mp_grow (mp_int * a, int size)
+{
+  int     i;
+  mp_digit *tmp;
+
+  /* if the alloc size is smaller alloc more ram */
+  if (a->alloc < size) {
+    /* ensure there are always at least MP_PREC digits extra on top */
+    size += (MP_PREC * 2) - (size % MP_PREC);
+
+    /* reallocate the array a->dp
+     *
+     * We store the return in a temporary variable
+     * in case the operation failed we don't want
+     * to overwrite the dp member of a.
+     */
+    tmp = OPT_CAST(mp_digit) XREALLOC (a->dp, sizeof (mp_digit) * size);
+    if (tmp == NULL) {
+      /* reallocation failed but "a" is still valid [can be freed] */
+      return MP_MEM;
+    }
+
+    /* reallocation succeeded so set a->dp */
+    a->dp = tmp;
+
+    /* zero excess digits */
+    i        = a->alloc;
+    a->alloc = size;
+    for (; i < a->alloc; i++) {
+      a->dp[i] = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_ABS_C
+/* b = |a|
+ *
+ * Simple function copies the input and fixes the sign to positive
+ */
+static int
+mp_abs (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  /* copy a to b */
+  if (a != b) {
+     if ((res = mp_copy (a, b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* force the sign of b to positive */
+  b->sign = MP_ZPOS;
+
+  return MP_OKAY;
+}
+#endif
+
+
+/* set to a digit */
+static void
+mp_set (mp_int * a, mp_digit b)
+{
+  mp_zero (a);
+  a->dp[0] = b & MP_MASK;
+  a->used  = (a->dp[0] != 0) ? 1 : 0;
+}
+
+
+#ifndef LTM_NO_NEG_EXP
+/* b = a/2 */
+static int
+mp_div_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* copy */
+  if (b->alloc < a->used) {
+    if ((res = mp_grow (b, a->used)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* source alias */
+    tmpa = a->dp + b->used - 1;
+
+    /* dest alias */
+    tmpb = b->dp + b->used - 1;
+
+    /* carry */
+    r = 0;
+    for (x = b->used - 1; x >= 0; x--) {
+      /* get the carry for the next iteration */
+      rr = *tmpa & 1;
+
+      /* shift the current digit, add in carry and store */
+      *tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
+
+      /* forward carry to next iteration */
+      r = rr;
+    }
+
+    /* zero excess digits */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif /* LTM_NO_NEG_EXP */
+
+
+/* shift left by a certain bit count */
+static int
+mp_mul_2d (mp_int * a, int b, mp_int * c)
+{
+  mp_digit d;
+  int      res;
+
+  /* copy */
+  if (a != c) {
+     if ((res = mp_copy (a, c)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  if (c->alloc < (int)(c->used + b/DIGIT_BIT + 1)) {
+     if ((res = mp_grow (c, c->used + b / DIGIT_BIT + 1)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  /* shift by as many digits in the bit count */
+  if (b >= (int)DIGIT_BIT) {
+    if ((res = mp_lshd (c, b / DIGIT_BIT)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* shift any bit count < DIGIT_BIT */
+  d = (mp_digit) (b % DIGIT_BIT);
+  if (d != 0) {
+    register mp_digit *tmpc, shift, mask, r, rr;
+    register int x;
+
+    /* bitmask for carries */
+    mask = (((mp_digit)1) << d) - 1;
+
+    /* shift for msbs */
+    shift = DIGIT_BIT - d;
+
+    /* alias */
+    tmpc = c->dp;
+
+    /* carry */
+    r    = 0;
+    for (x = 0; x < c->used; x++) {
+      /* get the higher bits of the current word */
+      rr = (*tmpc >> shift) & mask;
+
+      /* shift the current word and OR in the carry */
+      *tmpc = ((*tmpc << d) | r) & MP_MASK;
+      ++tmpc;
+
+      /* set the carry to the carry bits of the current word */
+      r = rr;
+    }
+
+    /* set final carry */
+    if (r != 0) {
+       c->dp[(c->used)++] = r;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_INIT_MULTI_C
+static int
+mp_init_multi(mp_int *mp, ...)
+{
+    mp_err res = MP_OKAY;      /* Assume ok until proven otherwise */
+    int n = 0;                 /* Number of ok inits */
+    mp_int* cur_arg = mp;
+    va_list args;
+
+    va_start(args, mp);        /* init args to next argument from caller */
+    while (cur_arg != NULL) {
+        if (mp_init(cur_arg) != MP_OKAY) {
+            /* Oops - error! Back-track and mp_clear what we already
+               succeeded in init-ing, then return error.
+            */
+            va_list clean_args;
+
+            /* end the current list */
+            va_end(args);
+
+            /* now start cleaning up */
+            cur_arg = mp;
+            va_start(clean_args, mp);
+            while (n--) {
+                mp_clear(cur_arg);
+                cur_arg = va_arg(clean_args, mp_int*);
+            }
+            va_end(clean_args);
+            res = MP_MEM;
+            break;
+        }
+        n++;
+        cur_arg = va_arg(args, mp_int*);
+    }
+    va_end(args);
+    return res;                /* Assumed ok, if error flagged above. */
+}
+#endif
+
+
+#ifdef BN_MP_CLEAR_MULTI_C
+static void
+mp_clear_multi(mp_int *mp, ...)
+{
+    mp_int* next_mp = mp;
+    va_list args;
+    va_start(args, mp);
+    while (next_mp != NULL) {
+        mp_clear(next_mp);
+        next_mp = va_arg(args, mp_int*);
+    }
+    va_end(args);
+}
+#endif
+
+
+/* shift left a certain amount of digits */
+static int
+mp_lshd (mp_int * a, int b)
+{
+  int     x, res;
+
+  /* if its less than zero return */
+  if (b <= 0) {
+    return MP_OKAY;
+  }
+
+  /* grow to fit the new digits */
+  if (a->alloc < a->used + b) {
+     if ((res = mp_grow (a, a->used + b)) != MP_OKAY) {
+       return res;
+     }
+  }
+
+  {
+    register mp_digit *top, *bottom;
+
+    /* increment the used by the shift amount then copy upwards */
+    a->used += b;
+
+    /* top */
+    top = a->dp + a->used - 1;
+
+    /* base */
+    bottom = a->dp + a->used - 1 - b;
+
+    /* much like mp_rshd this is implemented using a sliding window
+     * except the window goes the otherway around.  Copying from
+     * the bottom to the top.  see bn_mp_rshd.c for more info.
+     */
+    for (x = a->used - 1; x >= b; x--) {
+      *top-- = *bottom--;
+    }
+
+    /* zero the lower digits */
+    top = a->dp;
+    for (x = 0; x < b; x++) {
+      *top++ = 0;
+    }
+  }
+  return MP_OKAY;
+}
+
+
+/* returns the number of bits in an int */
+static int
+mp_count_bits (mp_int * a)
+{
+  int     r;
+  mp_digit q;
+
+  /* shortcut */
+  if (a->used == 0) {
+    return 0;
+  }
+
+  /* get number of digits and add that */
+  r = (a->used - 1) * DIGIT_BIT;
+
+  /* take the last digit and count the bits in it */
+  q = a->dp[a->used - 1];
+  while (q > ((mp_digit) 0)) {
+    ++r;
+    q >>= ((mp_digit) 1);
+  }
+  return r;
+}
+
+
+/* calc a value mod 2**b */
+static int
+mp_mod_2d (mp_int * a, int b, mp_int * c)
+{
+  int     x, res;
+
+  /* if b is <= 0 then zero the int */
+  if (b <= 0) {
+    mp_zero (c);
+    return MP_OKAY;
+  }
+
+  /* if the modulus is larger than the value than return */
+  if (b >= (int) (a->used * DIGIT_BIT)) {
+    res = mp_copy (a, c);
+    return res;
+  }
+
+  /* copy */
+  if ((res = mp_copy (a, c)) != MP_OKAY) {
+    return res;
+  }
+
+  /* zero digits above the last digit of the modulus */
+  for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++) {
+    c->dp[x] = 0;
+  }
+  /* clear the digit that is not completely outside/inside the modulus */
+  c->dp[b / DIGIT_BIT] &=
+    (mp_digit) ((((mp_digit) 1) << (((mp_digit) b) % DIGIT_BIT)) - ((mp_digit) 1));
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_DIV_SMALL
+
+/* slower bit-bang division... also smaller */
+static int
+mp_div(mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+   mp_int ta, tb, tq, q;
+   int    res, n, n2;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  /* init our temps */
+  if ((res = mp_init_multi(&ta, &tb, &tq, &q, NULL) != MP_OKAY)) {
+     return res;
+  }
+
+
+  mp_set(&tq, 1);
+  n = mp_count_bits(a) - mp_count_bits(b);
+  if (((res = mp_abs(a, &ta)) != MP_OKAY) ||
+      ((res = mp_abs(b, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tb, n, &tb)) != MP_OKAY) ||
+      ((res = mp_mul_2d(&tq, n, &tq)) != MP_OKAY)) {
+      goto LBL_ERR;
+  }
+
+  while (n-- >= 0) {
+     if (mp_cmp(&tb, &ta) != MP_GT) {
+        if (((res = mp_sub(&ta, &tb, &ta)) != MP_OKAY) ||
+            ((res = mp_add(&q, &tq, &q)) != MP_OKAY)) {
+           goto LBL_ERR;
+        }
+     }
+     if (((res = mp_div_2d(&tb, 1, &tb, NULL)) != MP_OKAY) ||
+         ((res = mp_div_2d(&tq, 1, &tq, NULL)) != MP_OKAY)) {
+           goto LBL_ERR;
+     }
+  }
+
+  /* now q == quotient and ta == remainder */
+  n  = a->sign;
+  n2 = (a->sign == b->sign ? MP_ZPOS : MP_NEG);
+  if (c != NULL) {
+     mp_exch(c, &q);
+     c->sign  = (mp_iszero(c) == MP_YES) ? MP_ZPOS : n2;
+  }
+  if (d != NULL) {
+     mp_exch(d, &ta);
+     d->sign = (mp_iszero(d) == MP_YES) ? MP_ZPOS : n;
+  }
+LBL_ERR:
+   mp_clear_multi(&ta, &tb, &tq, &q, NULL);
+   return res;
+}
+
+#else
+
+/* integer signed division.
+ * c*b + d == a [e.g. a/b, c=quotient, d=remainder]
+ * HAC pp.598 Algorithm 14.20
+ *
+ * Note that the description in HAC is horribly
+ * incomplete.  For example, it doesn't consider
+ * the case where digits are removed from 'x' in
+ * the inner loop.  It also doesn't consider the
+ * case that y has fewer than three digits, etc..
+ *
+ * The overall algorithm is as described as
+ * 14.20 from HAC but fixed to treat these cases.
+*/
+static int
+mp_div (mp_int * a, mp_int * b, mp_int * c, mp_int * d)
+{
+  mp_int  q, x, y, t1, t2;
+  int     res, n, t, i, norm, neg;
+
+  /* is divisor zero ? */
+  if (mp_iszero (b) == 1) {
+    return MP_VAL;
+  }
+
+  /* if a < b then q=0, r = a */
+  if (mp_cmp_mag (a, b) == MP_LT) {
+    if (d != NULL) {
+      res = mp_copy (a, d);
+    } else {
+      res = MP_OKAY;
+    }
+    if (c != NULL) {
+      mp_zero (c);
+    }
+    return res;
+  }
+
+  if ((res = mp_init_size (&q, a->used + 2)) != MP_OKAY) {
+    return res;
+  }
+  q.used = a->used + 2;
+
+  if ((res = mp_init (&t1)) != MP_OKAY) {
+    goto LBL_Q;
+  }
+
+  if ((res = mp_init (&t2)) != MP_OKAY) {
+    goto LBL_T1;
+  }
+
+  if ((res = mp_init_copy (&x, a)) != MP_OKAY) {
+    goto LBL_T2;
+  }
+
+  if ((res = mp_init_copy (&y, b)) != MP_OKAY) {
+    goto LBL_X;
+  }
+
+  /* fix the sign */
+  neg = (a->sign == b->sign) ? MP_ZPOS : MP_NEG;
+  x.sign = y.sign = MP_ZPOS;
+
+  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
+  norm = mp_count_bits(&y) % DIGIT_BIT;
+  if (norm < (int)(DIGIT_BIT-1)) {
+     norm = (DIGIT_BIT-1) - norm;
+     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {
+       goto LBL_Y;
+     }
+  } else {
+     norm = 0;
+  }
+
+  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
+  n = x.used - 1;
+  t = y.used - 1;
+
+  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
+  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */
+    goto LBL_Y;
+  }
+
+  while (mp_cmp (&x, &y) != MP_LT) {
+    ++(q.dp[n - t]);
+    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+  }
+
+  /* reset y by shifting it back down */
+  mp_rshd (&y, n - t);
+
+  /* step 3. for i from n down to (t + 1) */
+  for (i = n; i >= (t + 1); i--) {
+    if (i > x.used) {
+      continue;
+    }
+
+    /* step 3.1 if xi == yt then set q{i-t-1} to b-1,
+     * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
+    if (x.dp[i] == y.dp[t]) {
+      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);
+    } else {
+      mp_word tmp;
+      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);
+      tmp |= ((mp_word) x.dp[i - 1]);
+      tmp /= ((mp_word) y.dp[t]);
+      if (tmp > (mp_word) MP_MASK)
+        tmp = MP_MASK;
+      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));
+    }
+
+    /* while (q{i-t-1} * (yt * b + y{t-1})) >
+             xi * b**2 + xi-1 * b + xi-2
+
+       do q{i-t-1} -= 1;
+    */
+    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;
+    do {
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;
+
+      /* find left hand */
+      mp_zero (&t1);
+      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
+      t1.dp[1] = y.dp[t];
+      t1.used = 2;
+      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      /* find right hand */
+      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
+      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
+      t2.dp[2] = x.dp[i];
+      t2.used = 3;
+    } while (mp_cmp_mag(&t1, &t2) == MP_GT);
+
+    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
+    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {
+      goto LBL_Y;
+    }
+
+    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
+    if (x.sign == MP_NEG) {
+      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {
+        goto LBL_Y;
+      }
+
+      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;
+    }
+  }
+
+  /* now q is the quotient and x is the remainder
+   * [which we have to normalize]
+   */
+
+  /* get sign before writing to c */
+  x.sign = x.used == 0 ? MP_ZPOS : a->sign;
+
+  if (c != NULL) {
+    mp_clamp (&q);
+    mp_exch (&q, c);
+    c->sign = neg;
+  }
+
+  if (d != NULL) {
+    mp_div_2d (&x, norm, &x, NULL);
+    mp_exch (&x, d);
+  }
+
+  res = MP_OKAY;
+
+LBL_Y:mp_clear (&y);
+LBL_X:mp_clear (&x);
+LBL_T2:mp_clear (&t2);
+LBL_T1:mp_clear (&t1);
+LBL_Q:mp_clear (&q);
+  return res;
+}
+
+#endif
+
+
+#ifdef MP_LOW_MEM
+   #define TAB_SIZE 32
+#else
+   #define TAB_SIZE 256
+#endif
+
+static int
+s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res, mu;
+  mp_digit buf;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+  int (*redux)(mp_int*,mp_int*,mp_int*);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+    if (winsize > 5) {
+       winsize = 5;
+    }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* create mu, used for Barrett reduction */
+  if ((err = mp_init (&mu)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  if (redmode == 0) {
+     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce;
+  } else {
+     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {
+        goto LBL_MU;
+     }
+     redux = mp_reduce_2k_l;
+  }
+
+  /* create M table
+   *
+   * The M table contains powers of the base,
+   * e.g. M[x] = G**x mod P
+   *
+   * The first half of the table is not
+   * computed though accept for M[0] and M[1]
+   */
+  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring
+   * M[1] (winsize-1) times
+   */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_MU;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    /* square it */
+    if ((err = mp_sqr (&M[1 << (winsize - 1)],
+                       &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+
+    /* reduce modulo P */
+    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)
+   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)
+   */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_MU;
+    }
+    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {
+      goto LBL_MU;
+    }
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_MU;
+  }
+  mp_set (&res, 1);
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset the bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int) DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, &mu)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_MU:mp_clear (&mu);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+
+
+/* computes b = a*a */
+static int
+mp_sqr (mp_int * a, mp_int * b)
+{
+  int     res;
+
+#ifdef BN_MP_TOOM_SQR_C
+  /* use Toom-Cook? */
+  if (a->used >= TOOM_SQR_CUTOFF) {
+    res = mp_toom_sqr(a, b);
+  /* Karatsuba? */
+  } else
+#endif
+#ifdef BN_MP_KARATSUBA_SQR_C
+if (a->used >= KARATSUBA_SQR_CUTOFF) {
+    res = mp_karatsuba_sqr (a, b);
+  } else
+#endif
+  {
+#ifdef BN_FAST_S_MP_SQR_C
+    /* can we use the fast comba multiplier? */
+    if ((a->used * 2 + 1) < MP_WARRAY &&
+         a->used <
+         (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {
+      res = fast_s_mp_sqr (a, b);
+    } else
+#endif
+#ifdef BN_S_MP_SQR_C
+      res = s_mp_sqr (a, b);
+#else
+#error mp_sqr could fail
+      res = MP_VAL;
+#endif
+  }
+  b->sign = MP_ZPOS;
+  return res;
+}
+
+
+/* reduces a modulo n where n is of the form 2**p - d
+   This differs from reduce_2k since "d" can be larger
+   than a single digit.
+*/
+static int
+mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d)
+{
+   mp_int q;
+   int    p, res;
+
+   if ((res = mp_init(&q)) != MP_OKAY) {
+      return res;
+   }
+
+   p = mp_count_bits(n);
+top:
+   /* q = a/2**p, a = a mod 2**p */
+   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   /* q = q * d */
+   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   /* a = a + q */
+   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {
+      goto ERR;
+   }
+
+   if (mp_cmp_mag(a, n) != MP_LT) {
+      s_mp_sub(a, n, a);
+      goto top;
+   }
+
+ERR:
+   mp_clear(&q);
+   return res;
+}
+
+
+/* determines the setup value */
+static int
+mp_reduce_2k_setup_l(mp_int *a, mp_int *d)
+{
+   int    res;
+   mp_int tmp;
+
+   if ((res = mp_init(&tmp)) != MP_OKAY) {
+      return res;
+   }
+
+   if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {
+      goto ERR;
+   }
+
+   if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {
+      goto ERR;
+   }
+
+ERR:
+   mp_clear(&tmp);
+   return res;
+}
+
+
+/* computes a = 2**b
+ *
+ * Simple algorithm which zeroes the int, grows it then just sets one bit
+ * as required.
+ */
+static int
+mp_2expt (mp_int * a, int b)
+{
+  int     res;
+
+  /* zero a as per default */
+  mp_zero (a);
+
+  /* grow a to accommodate the single bit */
+  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* set the used count of where the bit will go */
+  a->used = b / DIGIT_BIT + 1;
+
+  /* put the single bit in its place */
+  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);
+
+  return MP_OKAY;
+}
+
+
+/* pre-calculate the value required for Barrett reduction
+ * For a given modulus "b" it calulates the value required in "a"
+ */
+static int
+mp_reduce_setup (mp_int * a, mp_int * b)
+{
+  int     res;
+
+  if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {
+    return res;
+  }
+  return mp_div (a, b, a, NULL);
+}
+
+
+/* reduces x mod m, assumes 0 < x < m**2, mu is
+ * precomputed via mp_reduce_setup.
+ * From HAC pp.604 Algorithm 14.42
+ */
+static int
+mp_reduce (mp_int * x, mp_int * m, mp_int * mu)
+{
+  mp_int  q;
+  int     res, um = m->used;
+
+  /* q = x */
+  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {
+    return res;
+  }
+
+  /* q1 = x / b**(k-1)  */
+  mp_rshd (&q, um - 1);
+
+  /* according to HAC this optimization is ok */
+  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {
+    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  } else {
+#ifdef BN_S_MP_MUL_HIGH_DIGS_C
+    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)
+    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+#else
+    {
+#error mp_reduce would always fail
+      res = MP_VAL;
+      goto CLEANUP;
+    }
+#endif
+  }
+
+  /* q3 = q2 / b**(k+1) */
+  mp_rshd (&q, um + 1);
+
+  /* x = x mod b**(k+1), quick (no division) */
+  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* q = q * m mod b**(k+1), quick (no division) */
+  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* x = x - q */
+  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {
+    goto CLEANUP;
+  }
+
+  /* If x < 0, add b**(k+1) to it */
+  if (mp_cmp_d (x, 0) == MP_LT) {
+    mp_set (&q, 1);
+    if ((res = mp_lshd (&q, um + 1)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+    if ((res = mp_add (x, &q, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+
+  /* Back off if it's too big */
+  while (mp_cmp (x, m) != MP_LT) {
+    if ((res = s_mp_sub (x, m, x)) != MP_OKAY) {
+      goto CLEANUP;
+    }
+  }
+
+CLEANUP:
+  mp_clear (&q);
+
+  return res;
+}
+
+
+/* multiplies |a| * |b| and only computes up to digs digits of result
+ * HAC pp. 595, Algorithm 14.12  Modified so you can control how
+ * many digits of output are created.
+ */
+static int
+s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+  if (((digs) < MP_WARRAY) &&
+      MIN (a->used, b->used) <
+          (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_digs (a, b, c, digs);
+  }
+
+  if ((res = mp_init_size (&t, digs)) != MP_OKAY) {
+    return res;
+  }
+  t.used = digs;
+
+  /* compute the digits of the product directly */
+  pa = a->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* set the carry to zero */
+    u = 0;
+
+    /* limit ourselves to making digs digits of output */
+    pb = MIN (b->used, digs - ix);
+
+    /* setup some aliases */
+    /* copy of the digit from a used within the nested loop */
+    tmpx = a->dp[ix];
+
+    /* an alias for the destination shifted ix places */
+    tmpt = t.dp + ix;
+
+    /* an alias for the digits of b */
+    tmpy = b->dp;
+
+    /* compute the columns of the output and propagate the carry */
+    for (iy = 0; iy < pb; iy++) {
+      /* compute the column as a mp_word */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* the new column is the lower part of the result */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get the carry word from the result */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    /* set carry if it is placed below digs */
+    if (ix + iy < digs) {
+      *tmpt = u;
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, c);
+
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* Fast (comba) multiplier
+ *
+ * This is the fast column-array [comba] multiplier.  It is
+ * designed to compute the columns of the product first
+ * then handle the carries afterwards.  This has the effect
+ * of making the nested loops that compute the columns very
+ * simple and schedulable on super-scalar processors.
+ *
+ * This has been modified to produce a variable number of
+ * digits of output so if say only a half-product is required
+ * you don't have to compute the upper half (a feature
+ * required for fast Barrett reduction).
+ *
+ * Based on Algorithm 14.12 on pp.595 of HAC.
+ *
+ */
+static int
+fast_s_mp_mul_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  int     olduse, res, pa, ix, iz;
+  mp_digit W[MP_WARRAY];
+  register mp_word  _W;
+
+  /* grow the destination as required */
+  if (c->alloc < digs) {
+    if ((res = mp_grow (c, digs)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  pa = MIN(digs, a->used + b->used);
+
+  /* clear the carry */
+  _W = 0;
+  for (ix = 0; ix < pa; ix++) {
+      int      tx, ty;
+      int      iy;
+      mp_digit *tmpx, *tmpy;
+
+      /* get offsets into the two bignums */
+      ty = MIN(b->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = b->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; ++iz) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+
+      }
+
+      /* store term */
+      W[ix] = ((mp_digit)_W) & MP_MASK;
+
+      /* make next carry */
+      _W = _W >> ((mp_word)DIGIT_BIT);
+ }
+
+  /* setup dest */
+  olduse  = c->used;
+  c->used = pa;
+
+  {
+    register mp_digit *tmpc;
+    tmpc = c->dp;
+    for (ix = 0; ix < pa+1; ix++) {
+      /* now extract the previous digit [below the carry] */
+      *tmpc++ = W[ix];
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpc++ = 0;
+    }
+  }
+  mp_clamp (c);
+  return MP_OKAY;
+}
+
+
+/* init an mp_init for a given size */
+static int
+mp_init_size (mp_int * a, int size)
+{
+  int x;
+
+  /* pad size so there are always extra digits */
+  size += (MP_PREC * 2) - (size % MP_PREC);
+
+  /* alloc mem */
+  a->dp = OPT_CAST(mp_digit) XMALLOC (sizeof (mp_digit) * size);
+  if (a->dp == NULL) {
+    return MP_MEM;
+  }
+
+  /* set the members */
+  a->used  = 0;
+  a->alloc = size;
+  a->sign  = MP_ZPOS;
+
+  /* zero the digits */
+  for (x = 0; x < size; x++) {
+      a->dp[x] = 0;
+  }
+
+  return MP_OKAY;
+}
+
+
+/* low level squaring, b = a*a, HAC pp.596-597, Algorithm 14.16 */
+static int
+s_mp_sqr (mp_int * a, mp_int * b)
+{
+  mp_int  t;
+  int     res, ix, iy, pa;
+  mp_word r;
+  mp_digit u, tmpx, *tmpt;
+
+  pa = a->used;
+  if ((res = mp_init_size (&t, 2*pa + 1)) != MP_OKAY) {
+    return res;
+  }
+
+  /* default used is maximum possible size */
+  t.used = 2*pa + 1;
+
+  for (ix = 0; ix < pa; ix++) {
+    /* first calculate the digit at 2*ix */
+    /* calculate double precision result */
+    r = ((mp_word) t.dp[2*ix]) +
+        ((mp_word)a->dp[ix])*((mp_word)a->dp[ix]);
+
+    /* store lower part in result */
+    t.dp[ix+ix] = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* get the carry */
+    u           = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+
+    /* left hand side of A[ix] * A[iy] */
+    tmpx        = a->dp[ix];
+
+    /* alias for where to store the results */
+    tmpt        = t.dp + (2*ix + 1);
+
+    for (iy = ix + 1; iy < pa; iy++) {
+      /* first calculate the product */
+      r       = ((mp_word)tmpx) * ((mp_word)a->dp[iy]);
+
+      /* now calculate the double precision result, note we use
+       * addition instead of *2 since it's easier to optimize
+       */
+      r       = ((mp_word) *tmpt) + r + r + ((mp_word) u);
+
+      /* store lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* get carry */
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+    /* propagate upwards */
+    while (u != ((mp_digit) 0)) {
+      r       = ((mp_word) *tmpt) + ((mp_word) u);
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+      u       = (mp_digit)(r >> ((mp_word) DIGIT_BIT));
+    }
+  }
+
+  mp_clamp (&t);
+  mp_exch (&t, b);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+/* multiplies |a| * |b| and does not compute the lower digs digits
+ * [meant to get the higher part of the product]
+ */
+static int
+s_mp_mul_high_digs (mp_int * a, mp_int * b, mp_int * c, int digs)
+{
+  mp_int  t;
+  int     res, pa, pb, ix, iy;
+  mp_digit u;
+  mp_word r;
+  mp_digit tmpx, *tmpt, *tmpy;
+
+  /* can we use the fast multiplier? */
+#ifdef BN_FAST_S_MP_MUL_HIGH_DIGS_C
+  if (((a->used + b->used + 1) < MP_WARRAY)
+      && MIN (a->used, b->used) < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+    return fast_s_mp_mul_high_digs (a, b, c, digs);
+  }
+#endif
+
+  if ((res = mp_init_size (&t, a->used + b->used + 1)) != MP_OKAY) {
+    return res;
+  }
+  t.used = a->used + b->used + 1;
+
+  pa = a->used;
+  pb = b->used;
+  for (ix = 0; ix < pa; ix++) {
+    /* clear the carry */
+    u = 0;
+
+    /* left hand side of A[ix] * B[iy] */
+    tmpx = a->dp[ix];
+
+    /* alias to the address of where the digits will be stored */
+    tmpt = &(t.dp[digs]);
+
+    /* alias for where to read the right hand side from */
+    tmpy = b->dp + (digs - ix);
+
+    for (iy = digs - ix; iy < pb; iy++) {
+      /* calculate the double precision result */
+      r       = ((mp_word)*tmpt) +
+                ((mp_word)tmpx) * ((mp_word)*tmpy++) +
+                ((mp_word) u);
+
+      /* get the lower part */
+      *tmpt++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+      /* carry the carry */
+      u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+    }
+    *tmpt = u;
+  }
+  mp_clamp (&t);
+  mp_exch (&t, c);
+  mp_clear (&t);
+  return MP_OKAY;
+}
+
+
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+/* setups the montgomery reduction stuff */
+static int
+mp_montgomery_setup (mp_int * n, mp_digit * rho)
+{
+  mp_digit x, b;
+
+/* fast inversion mod 2**k
+ *
+ * Based on the fact that
+ *
+ * XA = 1 (mod 2**n)  =>  (X(2-XA)) A = 1 (mod 2**2n)
+ *                    =>  2*X*A - X*X*A*A = 1
+ *                    =>  2*(1) - (1)     = 1
+ */
+  b = n->dp[0];
+
+  if ((b & 1) == 0) {
+    return MP_VAL;
+  }
+
+  x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
+  x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
+#if !defined(MP_8BIT)
+  x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
+#endif
+#if defined(MP_64BIT) || !(defined(MP_8BIT) || defined(MP_16BIT))
+  x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
+#endif
+#ifdef MP_64BIT
+  x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
+#endif
+
+  /* rho = -1/m mod b */
+  *rho = (unsigned long)(((mp_word)1 << ((mp_word) DIGIT_BIT)) - x) & MP_MASK;
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+/* computes xR**-1 == x (mod N) via Montgomery Reduction
+ *
+ * This is an optimized implementation of montgomery_reduce
+ * which uses the comba method to quickly calculate the columns of the
+ * reduction.
+ *
+ * Based on Algorithm 14.32 on pp.601 of HAC.
+*/
+int
+fast_mp_montgomery_reduce (mp_int * x, mp_int * n, mp_digit rho)
+{
+  int     ix, res, olduse;
+  mp_word W[MP_WARRAY];
+
+  /* get old used count */
+  olduse = x->used;
+
+  /* grow a as required */
+  if (x->alloc < n->used + 1) {
+    if ((res = mp_grow (x, n->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* first we have to get the digits of the input into
+   * an array of double precision words W[...]
+   */
+  {
+    register mp_word *_W;
+    register mp_digit *tmpx;
+
+    /* alias for the W[] array */
+    _W   = W;
+
+    /* alias for the digits of  x*/
+    tmpx = x->dp;
+
+    /* copy the digits of a into W[0..a->used-1] */
+    for (ix = 0; ix < x->used; ix++) {
+      *_W++ = *tmpx++;
+    }
+
+    /* zero the high words of W[a->used..m->used*2] */
+    for (; ix < n->used * 2 + 1; ix++) {
+      *_W++ = 0;
+    }
+  }
+
+  /* now we proceed to zero successive digits
+   * from the least significant upwards
+   */
+  for (ix = 0; ix < n->used; ix++) {
+    /* mu = ai * m' mod b
+     *
+     * We avoid a double precision multiplication (which isn't required)
+     * by casting the value down to a mp_digit.  Note this requires
+     * that W[ix-1] have  the carry cleared (see after the inner loop)
+     */
+    register mp_digit mu;
+    mu = (mp_digit) (((W[ix] & MP_MASK) * rho) & MP_MASK);
+
+    /* a = a + mu * m * b**i
+     *
+     * This is computed in place and on the fly.  The multiplication
+     * by b**i is handled by offseting which columns the results
+     * are added to.
+     *
+     * Note the comba method normally doesn't handle carries in the
+     * inner loop In this case we fix the carry from the previous
+     * column since the Montgomery reduction requires digits of the
+     * result (so far) [see above] to work.  This is
+     * handled by fixing up one carry after the inner loop.  The
+     * carry fixups are done in order so after these loops the
+     * first m->used words of W[] have the carries fixed
+     */
+    {
+      register int iy;
+      register mp_digit *tmpn;
+      register mp_word *_W;
+
+      /* alias for the digits of the modulus */
+      tmpn = n->dp;
+
+      /* Alias for the columns set by an offset of ix */
+      _W = W + ix;
+
+      /* inner loop */
+      for (iy = 0; iy < n->used; iy++) {
+          *_W++ += ((mp_word)mu) * ((mp_word)*tmpn++);
+      }
+    }
+
+    /* now fix carry for next digit, W[ix+1] */
+    W[ix + 1] += W[ix] >> ((mp_word) DIGIT_BIT);
+  }
+
+  /* now we have to propagate the carries and
+   * shift the words downward [all those least
+   * significant digits we zeroed].
+   */
+  {
+    register mp_digit *tmpx;
+    register mp_word *_W, *_W1;
+
+    /* nox fix rest of carries */
+
+    /* alias for current word */
+    _W1 = W + ix;
+
+    /* alias for next word, where the carry goes */
+    _W = W + ++ix;
+
+    for (; ix <= n->used * 2 + 1; ix++) {
+      *_W++ += *_W1++ >> ((mp_word) DIGIT_BIT);
+    }
+
+    /* copy out, A = A/b**n
+     *
+     * The result is A/b**n but instead of converting from an
+     * array of mp_word to mp_digit than calling mp_rshd
+     * we just copy them in the right order
+     */
+
+    /* alias for destination word */
+    tmpx = x->dp;
+
+    /* alias for shifted double precision result */
+    _W = W + n->used;
+
+    for (ix = 0; ix < n->used + 1; ix++) {
+      *tmpx++ = (mp_digit)(*_W++ & ((mp_word) MP_MASK));
+    }
+
+    /* zero oldused digits, if the input a was larger than
+     * m->used+1 we'll have to clear the digits
+     */
+    for (; ix < olduse; ix++) {
+      *tmpx++ = 0;
+    }
+  }
+
+  /* set the max used and clamp */
+  x->used = n->used + 1;
+  mp_clamp (x);
+
+  /* if A >= m then A = A - m */
+  if (mp_cmp_mag (x, n) != MP_LT) {
+    return s_mp_sub (x, n, x);
+  }
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_2_C
+/* b = a*2 */
+static int
+mp_mul_2(mp_int * a, mp_int * b)
+{
+  int     x, res, oldused;
+
+  /* grow to accommodate result */
+  if (b->alloc < a->used + 1) {
+    if ((res = mp_grow (b, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  oldused = b->used;
+  b->used = a->used;
+
+  {
+    register mp_digit r, rr, *tmpa, *tmpb;
+
+    /* alias for source */
+    tmpa = a->dp;
+
+    /* alias for dest */
+    tmpb = b->dp;
+
+    /* carry */
+    r = 0;
+    for (x = 0; x < a->used; x++) {
+
+      /* get what will be the *next* carry bit from the
+       * MSB of the current digit
+       */
+      rr = *tmpa >> ((mp_digit)(DIGIT_BIT - 1));
+
+      /* now shift up this digit, add in the carry [from the previous] */
+      *tmpb++ = ((*tmpa++ << ((mp_digit)1)) | r) & MP_MASK;
+
+      /* copy the carry that would be from the source
+       * digit into the next iteration
+       */
+      r = rr;
+    }
+
+    /* new leading digit? */
+    if (r != 0) {
+      /* add a MSB which is always 1 at this point */
+      *tmpb = 1;
+      ++(b->used);
+    }
+
+    /* now zero any excess digits on the destination
+     * that we didn't write to
+     */
+    tmpb = b->dp + b->used;
+    for (x = b->used; x < oldused; x++) {
+      *tmpb++ = 0;
+    }
+  }
+  b->sign = a->sign;
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+/*
+ * shifts with subtractions when the result is greater than b.
+ *
+ * The method is slightly modified to shift B unconditionally up to just under
+ * the leading bit of b.  This saves a lot of multiple precision shifting.
+ */
+static int
+mp_montgomery_calc_normalization (mp_int * a, mp_int * b)
+{
+  int     x, bits, res;
+
+  /* how many bits of last digit does b use */
+  bits = mp_count_bits (b) % DIGIT_BIT;
+
+  if (b->used > 1) {
+     if ((res = mp_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) != MP_OKAY) {
+        return res;
+     }
+  } else {
+     mp_set(a, 1);
+     bits = 1;
+  }
+
+
+  /* now compute C = A * B mod b */
+  for (x = bits - 1; x < (int)DIGIT_BIT; x++) {
+    if ((res = mp_mul_2 (a, a)) != MP_OKAY) {
+      return res;
+    }
+    if (mp_cmp_mag (a, b) != MP_LT) {
+      if ((res = s_mp_sub (a, b, a)) != MP_OKAY) {
+        return res;
+      }
+    }
+  }
+
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_EXPTMOD_FAST_C
+/* computes Y == G**X mod P, HAC pp.616, Algorithm 14.85
+ *
+ * Uses a left-to-right k-ary sliding window to compute the modular exponentiation.
+ * The value of k changes based on the size of the exponent.
+ *
+ * Uses Montgomery or Diminished Radix reduction [whichever appropriate]
+ */
+
+static int
+mp_exptmod_fast (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode)
+{
+  mp_int  M[TAB_SIZE], res;
+  mp_digit buf, mp;
+  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;
+
+  /* use a pointer to the reduction algorithm.  This allows us to use
+   * one of many reduction algorithms without modding the guts of
+   * the code with if statements everywhere.
+   */
+  int     (*redux)(mp_int*,mp_int*,mp_digit);
+
+  /* find window size */
+  x = mp_count_bits (X);
+  if (x <= 7) {
+    winsize = 2;
+  } else if (x <= 36) {
+    winsize = 3;
+  } else if (x <= 140) {
+    winsize = 4;
+  } else if (x <= 450) {
+    winsize = 5;
+  } else if (x <= 1303) {
+    winsize = 6;
+  } else if (x <= 3529) {
+    winsize = 7;
+  } else {
+    winsize = 8;
+  }
+
+#ifdef MP_LOW_MEM
+  if (winsize > 5) {
+     winsize = 5;
+  }
+#endif
+
+  /* init M array */
+  /* init first cell */
+  if ((err = mp_init(&M[1])) != MP_OKAY) {
+     return err;
+  }
+
+  /* now init the second half of the array */
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    if ((err = mp_init(&M[x])) != MP_OKAY) {
+      for (y = 1<<(winsize-1); y < x; y++) {
+        mp_clear (&M[y]);
+      }
+      mp_clear(&M[1]);
+      return err;
+    }
+  }
+
+  /* determine and setup reduction code */
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_SETUP_C
+     /* now setup montgomery  */
+     if ((err = mp_montgomery_setup (P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+
+     /* automatically pick the comba one if available (saves quite a few calls/ifs) */
+#ifdef BN_FAST_MP_MONTGOMERY_REDUCE_C
+     if (((P->used * 2 + 1) < MP_WARRAY) &&
+          P->used < (1 << ((CHAR_BIT * sizeof (mp_word)) - (2 * DIGIT_BIT)))) {
+        redux = fast_mp_montgomery_reduce;
+     } else
+#endif
+     {
+#ifdef BN_MP_MONTGOMERY_REDUCE_C
+        /* use slower baseline Montgomery method */
+        redux = mp_montgomery_reduce;
+#else
+        err = MP_VAL;
+        goto LBL_M;
+#endif
+     }
+  } else if (redmode == 1) {
+#if defined(BN_MP_DR_SETUP_C) && defined(BN_MP_DR_REDUCE_C)
+     /* setup DR reduction for moduli of the form B**k - b */
+     mp_dr_setup(P, &mp);
+     redux = mp_dr_reduce;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  } else {
+#if defined(BN_MP_REDUCE_2K_SETUP_C) && defined(BN_MP_REDUCE_2K_C)
+     /* setup DR reduction for moduli of the form 2**k - b */
+     if ((err = mp_reduce_2k_setup(P, &mp)) != MP_OKAY) {
+        goto LBL_M;
+     }
+     redux = mp_reduce_2k;
+#else
+     err = MP_VAL;
+     goto LBL_M;
+#endif
+  }
+
+  /* setup result */
+  if ((err = mp_init (&res)) != MP_OKAY) {
+    goto LBL_M;
+  }
+
+  /* create M table
+   *
+
+   *
+   * The first half of the table is not computed though accept for M[0] and M[1]
+   */
+
+  if (redmode == 0) {
+#ifdef BN_MP_MONTGOMERY_CALC_NORMALIZATION_C
+     /* now we need R mod m */
+     if ((err = mp_montgomery_calc_normalization (&res, P)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+#else
+     err = MP_VAL;
+     goto LBL_RES;
+#endif
+
+     /* now set M[1] to G * R mod m */
+     if ((err = mp_mulmod (G, &res, P, &M[1])) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  } else {
+     mp_set(&res, 1);
+     if ((err = mp_mod(G, P, &M[1])) != MP_OKAY) {
+        goto LBL_RES;
+     }
+  }
+
+  /* compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times */
+  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {
+    goto LBL_RES;
+  }
+
+  for (x = 0; x < (winsize - 1); x++) {
+    if ((err = mp_sqr (&M[1 << (winsize - 1)], &M[1 << (winsize - 1)])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[1 << (winsize - 1)], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* create upper table */
+  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
+    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {
+      goto LBL_RES;
+    }
+    if ((err = redux (&M[x], P, mp)) != MP_OKAY) {
+      goto LBL_RES;
+    }
+  }
+
+  /* set initial mode and bit cnt */
+  mode   = 0;
+  bitcnt = 1;
+  buf    = 0;
+  digidx = X->used - 1;
+  bitcpy = 0;
+  bitbuf = 0;
+
+  for (;;) {
+    /* grab next digit as required */
+    if (--bitcnt == 0) {
+      /* if digidx == -1 we are out of digits so break */
+      if (digidx == -1) {
+        break;
+      }
+      /* read next digit and reset bitcnt */
+      buf    = X->dp[digidx--];
+      bitcnt = (int)DIGIT_BIT;
+    }
+
+    /* grab the next msb from the exponent */
+    y     = (mp_digit)(buf >> (DIGIT_BIT - 1)) & 1;
+    buf <<= (mp_digit)1;
+
+    /* if the bit is zero and mode == 0 then we ignore it
+     * These represent the leading zero bits before the first 1 bit
+     * in the exponent.  Technically this opt is not required but it
+     * does lower the # of trivial squaring/reductions used
+     */
+    if (mode == 0 && y == 0) {
+      continue;
+    }
+
+    /* if the bit is zero and mode == 1 then we square */
+    if (mode == 1 && y == 0) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      continue;
+    }
+
+    /* else we add it to the window */
+    bitbuf |= (y << (winsize - ++bitcpy));
+    mode    = 2;
+
+    if (bitcpy == winsize) {
+      /* ok window is filled so square as required and multiply  */
+      /* square first */
+      for (x = 0; x < winsize; x++) {
+        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+
+      /* then multiply */
+      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* empty window and reset */
+      bitcpy = 0;
+      bitbuf = 0;
+      mode   = 1;
+    }
+  }
+
+  /* if bits remain then square/multiply */
+  if (mode == 2 && bitcpy > 0) {
+    /* square then multiply if the bit is set */
+    for (x = 0; x < bitcpy; x++) {
+      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+      if ((err = redux (&res, P, mp)) != MP_OKAY) {
+        goto LBL_RES;
+      }
+
+      /* get next bit of the window */
+      bitbuf <<= 1;
+      if ((bitbuf & (1 << winsize)) != 0) {
+        /* then multiply */
+        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+        if ((err = redux (&res, P, mp)) != MP_OKAY) {
+          goto LBL_RES;
+        }
+      }
+    }
+  }
+
+  if (redmode == 0) {
+     /* fixup result if Montgomery reduction is used
+      * recall that any value in a Montgomery system is
+      * actually multiplied by R mod n.  So we have
+      * to reduce one more time to cancel out the factor
+      * of R.
+      */
+     if ((err = redux(&res, P, mp)) != MP_OKAY) {
+       goto LBL_RES;
+     }
+  }
+
+  /* swap res with Y */
+  mp_exch (&res, Y);
+  err = MP_OKAY;
+LBL_RES:mp_clear (&res);
+LBL_M:
+  mp_clear(&M[1]);
+  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
+    mp_clear (&M[x]);
+  }
+  return err;
+}
+#endif
+
+
+#ifdef BN_FAST_S_MP_SQR_C
+/* the jist of squaring...
+ * you do like mult except the offset of the tmpx [one that
+ * starts closer to zero] can't equal the offset of tmpy.
+ * So basically you set up iy like before then you min it with
+ * (ty-tx) so that it never happens.  You double all those
+ * you add in the inner loop
+
+After that loop you do the squares and add them in.
+*/
+
+static int
+fast_s_mp_sqr (mp_int * a, mp_int * b)
+{
+  int       olduse, res, pa, ix, iz;
+  mp_digit   W[MP_WARRAY], *tmpx;
+  mp_word   W1;
+
+  /* grow the destination as required */
+  pa = a->used + a->used;
+  if (b->alloc < pa) {
+    if ((res = mp_grow (b, pa)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* number of output digits to produce */
+  W1 = 0;
+  for (ix = 0; ix < pa; ix++) {
+      int      tx, ty, iy;
+      mp_word  _W;
+      mp_digit *tmpy;
+
+      /* clear counter */
+      _W = 0;
+
+      /* get offsets into the two bignums */
+      ty = MIN(a->used-1, ix);
+      tx = ix - ty;
+
+      /* setup temp aliases */
+      tmpx = a->dp + tx;
+      tmpy = a->dp + ty;
+
+      /* this is the number of times the loop will iterrate, essentially
+         while (tx++ < a->used && ty-- >= 0) { ... }
+       */
+      iy = MIN(a->used-tx, ty+1);
+
+      /* now for squaring tx can never equal ty
+       * we halve the distance since they approach at a rate of 2x
+       * and we have to round because odd cases need to be executed
+       */
+      iy = MIN(iy, (ty-tx+1)>>1);
+
+      /* execute loop */
+      for (iz = 0; iz < iy; iz++) {
+         _W += ((mp_word)*tmpx++)*((mp_word)*tmpy--);
+      }
+
+      /* double the inner product and add carry */
+      _W = _W + _W + W1;
+
+      /* even columns have the square term in them */
+      if ((ix&1) == 0) {
+         _W += ((mp_word)a->dp[ix>>1])*((mp_word)a->dp[ix>>1]);
+      }
+
+      /* store it */
+      W[ix] = (mp_digit)(_W & MP_MASK);
+
+      /* make next carry */
+      W1 = _W >> ((mp_word)DIGIT_BIT);
+  }
+
+  /* setup dest */
+  olduse  = b->used;
+  b->used = a->used+a->used;
+
+  {
+    mp_digit *tmpb;
+    tmpb = b->dp;
+    for (ix = 0; ix < pa; ix++) {
+      *tmpb++ = W[ix] & MP_MASK;
+    }
+
+    /* clear unused digits [that existed in the old copy of c] */
+    for (; ix < olduse; ix++) {
+      *tmpb++ = 0;
+    }
+  }
+  mp_clamp (b);
+  return MP_OKAY;
+}
+#endif
+
+
+#ifdef BN_MP_MUL_D_C
+/* multiply by a digit */
+static int
+mp_mul_d (mp_int * a, mp_digit b, mp_int * c)
+{
+  mp_digit u, *tmpa, *tmpc;
+  mp_word  r;
+  int      ix, res, olduse;
+
+  /* make sure c is big enough to hold a*b */
+  if (c->alloc < a->used + 1) {
+    if ((res = mp_grow (c, a->used + 1)) != MP_OKAY) {
+      return res;
+    }
+  }
+
+  /* get the original destinations used count */
+  olduse = c->used;
+
+  /* set the sign */
+  c->sign = a->sign;
+
+  /* alias for a->dp [source] */
+  tmpa = a->dp;
+
+  /* alias for c->dp [dest] */
+  tmpc = c->dp;
+
+  /* zero carry */
+  u = 0;
+
+  /* compute columns */
+  for (ix = 0; ix < a->used; ix++) {
+    /* compute product and carry sum for this term */
+    r       = ((mp_word) u) + ((mp_word)*tmpa++) * ((mp_word)b);
+
+    /* mask off higher bits to get a single digit */
+    *tmpc++ = (mp_digit) (r & ((mp_word) MP_MASK));
+
+    /* send carry into next iteration */
+    u       = (mp_digit) (r >> ((mp_word) DIGIT_BIT));
+  }
+
+  /* store final carry [if any] and increment ix offset  */
+  *tmpc++ = u;
+  ++ix;
+
+  /* now zero digits above the top */
+  while (ix++ < olduse) {
+     *tmpc++ = 0;
+  }
+
+  /* set used count */
+  c->used = a->used + 1;
+  mp_clamp(c);
+
+  return MP_OKAY;
+}
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* LIBTOMMATH_H */
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md4-internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md4-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..d1e52d64b794396b7e570eb08b374f6dc4f8de64
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md4-internal.c
@@ -0,0 +1,201 @@
+/*
+ * MD4 hash implementation
+ *
+ * This software may be distributed under the terms of BSD license.
+ */
+
+#include "crypto/includes.h"
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+
+#define MD4_BLOCK_LENGTH    64
+#define MD4_DIGEST_LENGTH    16
+
+typedef struct MD4Context {
+    u32 state[4];
+    u64 count;
+    u8 buffer[MD4_BLOCK_LENGTH];
+} MD4_CTX;
+
+static void MD4Init(MD4_CTX *ctx);
+static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len);
+static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx);
+
+int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+    MD4_CTX ctx;
+    size_t i;
+
+    MD4Init(&ctx);
+    for (i = 0; i < num_elem; i++)
+        MD4Update(&ctx, addr[i], len[i]);
+    MD4Final(mac, &ctx);
+    return 0;
+}
+
+#define MD4_DIGEST_STRING_LENGTH    (MD4_DIGEST_LENGTH * 2 + 1)
+
+static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH]);
+
+#define PUT_64BIT_LE(cp, value) do {    \
+    (cp)[7] = (value) >> 56;    \
+    (cp)[6] = (value) >> 48;    \
+    (cp)[5] = (value) >> 40;    \
+    (cp)[4] = (value) >> 32;    \
+    (cp)[3] = (value) >> 24;    \
+    (cp)[2] = (value) >> 16;    \
+    (cp)[1] = (value) >> 8;        \
+    (cp)[0] = (value); } while (0)
+
+#define PUT_32BIT_LE(cp, value) do {    \
+    (cp)[3] = (value) >> 24;    \
+    (cp)[2] = (value) >> 16;    \
+    (cp)[1] = (value) >> 8;        \
+    (cp)[0] = (value); } while (0)
+
+static u8 PADDING[MD4_BLOCK_LENGTH] = {
+    0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0,    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static void MD4Init(MD4_CTX *ctx)
+{
+    ctx->count = 0;
+    ctx->state[0] = 0x67452301;
+    ctx->state[1] = 0xefcdab89;
+    ctx->state[2] = 0x98badcfe;
+    ctx->state[3] = 0x10325476;
+}
+
+static void MD4Update(MD4_CTX *ctx, const unsigned char *input, size_t len)
+{
+    size_t have, need;
+
+    have = (size_t)((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
+    need = MD4_BLOCK_LENGTH - have;
+
+    ctx->count += (u64)len << 3;
+
+    if (len >= need) {
+        if (have != 0) {
+            os_memcpy(ctx->buffer + have, input, need);
+            MD4Transform(ctx->state, ctx->buffer);
+            input += need;
+            len -= need;
+            have = 0;
+        }
+
+        while (len >= MD4_BLOCK_LENGTH) {
+            MD4Transform(ctx->state, input);
+            input += MD4_BLOCK_LENGTH;
+            len -= MD4_BLOCK_LENGTH;
+        }
+    }
+
+    if (len != 0)
+        os_memcpy(ctx->buffer + have, input, len);
+}
+
+static void MD4Pad(MD4_CTX *ctx)
+{
+    u8 count[8];
+    size_t padlen;
+
+    PUT_64BIT_LE(count, ctx->count);
+
+    padlen = MD4_BLOCK_LENGTH -
+        ((ctx->count >> 3) & (MD4_BLOCK_LENGTH - 1));
+    if (padlen < 1 + 8)
+        padlen += MD4_BLOCK_LENGTH;
+    MD4Update(ctx, PADDING, padlen - 8);
+    MD4Update(ctx, count, 8);
+}
+
+static void MD4Final(unsigned char digest[MD4_DIGEST_LENGTH], MD4_CTX *ctx)
+{
+    int i;
+
+    MD4Pad(ctx);
+    if (digest != NULL) {
+        for (i = 0; i < 4; i ++)
+            PUT_32BIT_LE(digest + i * 4, ctx->state[i]);
+        os_memset(ctx, 0, sizeof(*ctx));
+    }
+}
+
+#define F1(x, y, z)    (z ^ (x & (y ^ z)))
+#define F2(x, y, z)    ((x & y) | (x & z) | (y & z))
+#define F3(x, y, z)    (x ^ y ^ z)
+
+#define MD4SETP(f, w, x, y, z, data, s)    \
+    ( w += f(x, y, z) + data, w = w<<s | w>>(32-s) )
+
+static void MD4Transform(u32 state[4], const u8 block[MD4_BLOCK_LENGTH])
+{
+    u32 a, b, c, d, in[MD4_BLOCK_LENGTH / 4];
+
+    os_memcpy(in, block, sizeof(in));
+
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+
+    MD4SETP(F1, a, b, c, d, in[ 0], 3);
+    MD4SETP(F1, d, a, b, c, in[ 1], 7);
+    MD4SETP(F1, c, d, a, b, in[ 2], 11);
+    MD4SETP(F1, b, c, d, a, in[ 3], 19);
+    MD4SETP(F1, a, b, c, d, in[ 4], 3);
+    MD4SETP(F1, d, a, b, c, in[ 5], 7);
+    MD4SETP(F1, c, d, a, b, in[ 6], 11);
+    MD4SETP(F1, b, c, d, a, in[ 7], 19);
+    MD4SETP(F1, a, b, c, d, in[ 8], 3);
+    MD4SETP(F1, d, a, b, c, in[ 9], 7);
+    MD4SETP(F1, c, d, a, b, in[10], 11);
+    MD4SETP(F1, b, c, d, a, in[11], 19);
+    MD4SETP(F1, a, b, c, d, in[12], 3);
+    MD4SETP(F1, d, a, b, c, in[13], 7);
+    MD4SETP(F1, c, d, a, b, in[14], 11);
+    MD4SETP(F1, b, c, d, a, in[15], 19);
+
+    MD4SETP(F2, a, b, c, d, in[ 0] + 0x5a827999, 3);
+    MD4SETP(F2, d, a, b, c, in[ 4] + 0x5a827999, 5);
+    MD4SETP(F2, c, d, a, b, in[ 8] + 0x5a827999, 9);
+    MD4SETP(F2, b, c, d, a, in[12] + 0x5a827999, 13);
+    MD4SETP(F2, a, b, c, d, in[ 1] + 0x5a827999, 3);
+    MD4SETP(F2, d, a, b, c, in[ 5] + 0x5a827999, 5);
+    MD4SETP(F2, c, d, a, b, in[ 9] + 0x5a827999, 9);
+    MD4SETP(F2, b, c, d, a, in[13] + 0x5a827999, 13);
+    MD4SETP(F2, a, b, c, d, in[ 2] + 0x5a827999, 3);
+    MD4SETP(F2, d, a, b, c, in[ 6] + 0x5a827999, 5);
+    MD4SETP(F2, c, d, a, b, in[10] + 0x5a827999, 9);
+    MD4SETP(F2, b, c, d, a, in[14] + 0x5a827999, 13);
+    MD4SETP(F2, a, b, c, d, in[ 3] + 0x5a827999, 3);
+    MD4SETP(F2, d, a, b, c, in[ 7] + 0x5a827999, 5);
+    MD4SETP(F2, c, d, a, b, in[11] + 0x5a827999, 9);
+    MD4SETP(F2, b, c, d, a, in[15] + 0x5a827999, 13);
+
+    MD4SETP(F3, a, b, c, d, in[ 0] + 0x6ed9eba1,  3);
+    MD4SETP(F3, d, a, b, c, in[ 8] + 0x6ed9eba1,  9);
+    MD4SETP(F3, c, d, a, b, in[ 4] + 0x6ed9eba1, 11);
+    MD4SETP(F3, b, c, d, a, in[12] + 0x6ed9eba1, 15);
+    MD4SETP(F3, a, b, c, d, in[ 2] + 0x6ed9eba1,  3);
+    MD4SETP(F3, d, a, b, c, in[10] + 0x6ed9eba1,  9);
+    MD4SETP(F3, c, d, a, b, in[ 6] + 0x6ed9eba1, 11);
+    MD4SETP(F3, b, c, d, a, in[14] + 0x6ed9eba1, 15);
+    MD4SETP(F3, a, b, c, d, in[ 1] + 0x6ed9eba1,  3);
+    MD4SETP(F3, d, a, b, c, in[ 9] + 0x6ed9eba1,  9);
+    MD4SETP(F3, c, d, a, b, in[ 5] + 0x6ed9eba1, 11);
+    MD4SETP(F3, b, c, d, a, in[13] + 0x6ed9eba1, 15);
+    MD4SETP(F3, a, b, c, d, in[ 3] + 0x6ed9eba1,  3);
+    MD4SETP(F3, d, a, b, c, in[11] + 0x6ed9eba1,  9);
+    MD4SETP(F3, c, d, a, b, in[ 7] + 0x6ed9eba1, 11);
+    MD4SETP(F3, b, c, d, a, in[15] + 0x6ed9eba1, 15);
+
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md5-internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md5-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..8098dc8e2ff82d631cbc46ec03b64885ad07613c
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md5-internal.c
@@ -0,0 +1,298 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/md5.h"
+#include "crypto/md5_i.h"
+#include "crypto/crypto.h"
+
+
+static void MD5Transform(u32 buf[4], u32 const in[16]);
+
+
+typedef struct MD5Context MD5_CTX;
+
+
+/**
+ * md5_vector - MD5 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int
+md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+    MD5_CTX ctx;
+    size_t i;
+
+    MD5Init(&ctx);
+    for (i = 0; i < num_elem; i++)
+        MD5Update(&ctx, addr[i], len[i]);
+    MD5Final(mac, &ctx);
+    return 0;
+}
+
+
+/* ===== start - public domain MD5 implementation ===== */
+/*
+ * This code implements the MD5 message-digest algorithm.
+ * The algorithm is due to Ron Rivest.  This code was
+ * written by Colin Plumb in 1993, no copyright is claimed.
+ * This code is in the public domain; do with it what you wish.
+ *
+ * Equivalent code is available from RSA Data Security, Inc.
+ * This code has been tested against that, and is equivalent,
+ * except that you don't need to include two pages of legalese
+ * with every copy.
+ *
+ * To compute the message digest of a chunk of bytes, declare an
+ * MD5Context structure, pass it to MD5Init, call MD5Update as
+ * needed on buffers full of bytes, and then call MD5Final, which
+ * will fill a supplied 16-byte array with the digest.
+ */
+
+#ifndef WORDS_BIGENDIAN
+#define byteReverse(buf, len)    /* Nothing */
+#else
+/*
+ * Note: this code is harmless on little-endian machines.
+ */
+static void byteReverse(unsigned char *buf, unsigned longs)
+{
+    u32 t;
+    do {
+    t = (u32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
+        ((unsigned) buf[1] << 8 | buf[0]);
+    *(u32 *) buf = t;
+    buf += 4;
+    } while (--longs);
+}
+#endif
+
+/*
+ * Start MD5 accumulation.  Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void
+MD5Init(struct MD5Context *ctx)
+{
+    ctx->buf[0] = 0x67452301;
+    ctx->buf[1] = 0xefcdab89;
+    ctx->buf[2] = 0x98badcfe;
+    ctx->buf[3] = 0x10325476;
+
+    ctx->bits[0] = 0;
+    ctx->bits[1] = 0;
+}
+
+/*
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void
+MD5Update(struct MD5Context *ctx, unsigned char const *buf, unsigned len)
+{
+    u32 t;
+
+    /* Update bitcount */
+
+    t = ctx->bits[0];
+    if ((ctx->bits[0] = t + ((u32) len << 3)) < t)
+    ctx->bits[1]++;        /* Carry from low to high */
+    ctx->bits[1] += len >> 29;
+
+    t = (t >> 3) & 0x3f;    /* Bytes already in shsInfo->data */
+
+    /* Handle any leading odd-sized chunks */
+
+    if (t) {
+    unsigned char *p = (unsigned char *) ctx->in + t;
+
+    t = 64 - t;
+    if (len < t) {
+        os_memcpy(p, buf, len);
+        return;
+    }
+    os_memcpy(p, buf, t);
+    byteReverse(ctx->in, 16);
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    buf += t;
+    len -= t;
+    }
+    /* Process data in 64-byte chunks */
+
+    while (len >= 64) {
+    os_memcpy(ctx->in, buf, 64);
+    byteReverse(ctx->in, 16);
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    buf += 64;
+    len -= 64;
+    }
+
+    /* Handle any remaining bytes of data. */
+
+    os_memcpy(ctx->in, buf, len);
+}
+
+/*
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void
+MD5Final(unsigned char digest[16], struct MD5Context *ctx)
+{
+    unsigned count;
+    unsigned char *p;
+
+    /* Compute number of bytes mod 64 */
+    count = (ctx->bits[0] >> 3) & 0x3F;
+
+    /* Set the first char of padding to 0x80.  This is safe since there is
+       always at least one byte free */
+    p = ctx->in + count;
+    *p++ = 0x80;
+
+    /* Bytes of padding needed to make 64 bytes */
+    count = 64 - 1 - count;
+
+    /* Pad out to 56 mod 64 */
+    if (count < 8) {
+    /* Two lots of padding:  Pad the first block to 64 bytes */
+    os_memset(p, 0, count);
+    byteReverse(ctx->in, 16);
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+
+    /* Now fill the next block with 56 bytes */
+    os_memset(ctx->in, 0, 56);
+    } else {
+    /* Pad block to 56 bytes */
+    os_memset(p, 0, count - 8);
+    }
+    byteReverse(ctx->in, 14);
+
+    /* Append length in bits and transform */
+    ((u32 *) ctx->in)[14] = ctx->bits[0];
+    ((u32 *) ctx->in)[15] = ctx->bits[1];
+
+    MD5Transform(ctx->buf, (u32 *) ctx->in);
+    byteReverse((unsigned char *) ctx->buf, 4);
+    os_memcpy(digest, ctx->buf, 16);
+    os_memset(ctx, 0, sizeof(struct MD5Context));    /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f, w, x, y, z, data, s) \
+    ( w += f(x, y, z) + data,  w = w<<s | w>>(32-s),  w += x )
+
+/*
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data.  MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+static void
+MD5Transform(u32 buf[4], u32 const in[16])
+{
+    register u32 a, b, c, d;
+
+    a = buf[0];
+    b = buf[1];
+    c = buf[2];
+    d = buf[3];
+
+    MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+    MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+    MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+    MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+    MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+    MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+    MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+    MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+    MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+    MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+    MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+    MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+    MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+    MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+    MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+    MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+    MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+    MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+    MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+    MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+    MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+    MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+    MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+    MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+    MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+    MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+    MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+    MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+    MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+    MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+    MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+    MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+    MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+    MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+    MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+    MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+    MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+    MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+    MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+    MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+    MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+    MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+    MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+    MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+    MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+    MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+    MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+    MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+    MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+    MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+    MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+    MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+    MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+    MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+    MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+    MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+    MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+    MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+    MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+    MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+    MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+    MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+    MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+    MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+    buf[0] += a;
+    buf[1] += b;
+    buf[2] += c;
+    buf[3] += d;
+}
+/* ===== end - public domain MD5 implementation ===== */
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md5.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md5.c
new file mode 100644
index 0000000000000000000000000000000000000000..9b086a7c80e773932fcde82a68c7186c70fad834
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/md5.c
@@ -0,0 +1,113 @@
+/*
+ * MD5 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+
+
+/**
+ * hmac_md5_vector - HMAC-MD5 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+hmac_md5_vector(const u8 *key, size_t key_len, size_t num_elem,
+            const u8 *addr[], const size_t *len, u8 *mac)
+{
+    u8 k_pad[64]; /* padding - key XORd with ipad/opad */
+    u8 tk[16];
+    const u8 *_addr[6];
+    size_t i, _len[6];
+
+    if (num_elem > 5) {
+        /*
+         * Fixed limit on the number of fragments to avoid having to
+         * allocate memory (which could fail).
+         */
+        return -1;
+    }
+
+        /* if key is longer than 64 bytes reset it to key = MD5(key) */
+        if (key_len > 64) {
+        if (md5_vector(1, &key, &key_len, tk))
+            return -1;
+        key = tk;
+        key_len = 16;
+        }
+
+    /* the HMAC_MD5 transform looks like:
+     *
+     * MD5(K XOR opad, MD5(K XOR ipad, text))
+     *
+     * where K is an n byte key
+     * ipad is the byte 0x36 repeated 64 times
+     * opad is the byte 0x5c repeated 64 times
+     * and text is the data being protected */
+
+    /* start out by storing key in ipad */
+    os_memset(k_pad, 0, sizeof(k_pad));
+    os_memcpy(k_pad, key, key_len);
+
+    /* XOR key with ipad values */
+    for (i = 0; i < 64; i++)
+        k_pad[i] ^= 0x36;
+
+    /* perform inner MD5 */
+    _addr[0] = k_pad;
+    _len[0] = 64;
+    for (i = 0; i < num_elem; i++) {
+        _addr[i + 1] = addr[i];
+        _len[i + 1] = len[i];
+    }
+    if (md5_vector(1 + num_elem, _addr, _len, mac))
+        return -1;
+
+    os_memset(k_pad, 0, sizeof(k_pad));
+    os_memcpy(k_pad, key, key_len);
+    /* XOR key with opad values */
+    for (i = 0; i < 64; i++)
+        k_pad[i] ^= 0x5c;
+
+    /* perform outer MD5 */
+    _addr[0] = k_pad;
+    _len[0] = 64;
+    _addr[1] = mac;
+    _len[1] = MD5_MAC_LEN;
+    return md5_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_md5 - HMAC-MD5 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (16 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+hmac_md5(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+          u8 *mac)
+{
+    return hmac_md5_vector(key, key_len, 1, &data, &data_len, mac);
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/ms_funcs.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/ms_funcs.c
new file mode 100644
index 0000000000000000000000000000000000000000..40e534f9a5a3650d2773914be670f3744c66004a
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/ms_funcs.c
@@ -0,0 +1,527 @@
+/*
+ * WPA Supplicant / shared MSCHAPV2 helper functions / RFC 2433 / RFC 2759
+ * Copyright (c) 2004-2012, Jouni Malinen <j@w1.fi>
+ *
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
+ */
+
+
+#include "wpa/includes.h"
+
+#include "wpa/common.h"
+#include "crypto/sha1.h"
+#include "crypto/ms_funcs.h"
+#include "crypto/crypto.h"
+
+/**
+ * utf8_to_ucs2 - Convert UTF-8 string to UCS-2 encoding
+ * @utf8_string: UTF-8 string (IN)
+ * @utf8_string_len: Length of utf8_string (IN)
+ * @ucs2_buffer: UCS-2 buffer (OUT)
+ * @ucs2_buffer_size: Length of UCS-2 buffer (IN)
+ * @ucs2_string_size: Number of 2-byte words in the resulting UCS-2 string
+ * Returns: 0 on success, -1 on failure
+ */
+static int utf8_to_ucs2(const u8 *utf8_string, size_t utf8_string_len,
+         u8 *ucs2_buffer, size_t ucs2_buffer_size,
+         size_t *ucs2_string_size)
+{
+    size_t i, j;
+
+    for (i = 0, j = 0; i < utf8_string_len; i++) {
+        u8 c = utf8_string[i];
+        if (j >= ucs2_buffer_size) {
+            /* input too long */
+            return -1;
+        }
+        if (c <= 0x7F) {
+            WPA_PUT_LE16(ucs2_buffer + j, c);
+            j += 2;
+        } else if (i == utf8_string_len - 1 ||
+               j >= ucs2_buffer_size - 1) {
+            /* incomplete surrogate */
+            return -1;
+        } else {
+            u8 c2 = utf8_string[++i];
+            if ((c & 0xE0) == 0xC0) {
+                /* two-byte encoding */
+                WPA_PUT_LE16(ucs2_buffer + j,
+                         ((c & 0x1F) << 6) | (c2 & 0x3F));
+                j += 2;
+            } else if (i == utf8_string_len ||
+                   j >= ucs2_buffer_size - 1) {
+                /* incomplete surrogate */
+                return -1;
+            } else {
+                /* three-byte encoding */
+                u8 c3 = utf8_string[++i];
+                WPA_PUT_LE16(ucs2_buffer + j,
+                         ((c & 0xF) << 12) |
+                         ((c2 & 0x3F) << 6) | (c3 & 0x3F));
+            }
+        }
+    }
+
+    if (ucs2_string_size)
+        *ucs2_string_size = j / 2;
+    return 0;
+}
+
+
+/**
+ * challenge_hash - ChallengeHash() - RFC 2759, Sect. 8.2
+ * @peer_challenge: 16-octet PeerChallenge (IN)
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @challenge: 8-octet Challenge (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+static int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge,
+           const u8 *username, size_t username_len,
+           u8 *challenge)
+{
+    u8 hash[SHA1_MAC_LEN];
+    const unsigned char *addr[3];
+    size_t len[3];
+
+    addr[0] = peer_challenge;
+    len[0] = 16;
+    addr[1] = auth_challenge;
+    len[1] = 16;
+    addr[2] = username;
+    len[2] = username_len;
+
+    if (sha1_vector(3, addr, len, hash))
+        return -1;
+    os_memcpy(challenge, hash, 8);
+    return 0;
+}
+
+
+/**
+ * nt_password_hash - NtPasswordHash() - RFC 2759, Sect. 8.3
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
+ * @password_len: Length of password
+ * @password_hash: 16-octet PasswordHash (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int nt_password_hash(const u8 *password, size_t password_len,
+         u8 *password_hash)
+{
+    u8 buf[512], *pos;
+    size_t len, max_len;
+
+    max_len = sizeof(buf);
+    if (utf8_to_ucs2(password, password_len, buf, max_len, &len) < 0)
+        return -1;
+
+    len *= 2;
+    pos = buf;
+    return md4_vector(1, (const u8 **) &pos, &len, password_hash);
+}
+
+
+/**
+ * hash_nt_password_hash - HashNtPasswordHash() - RFC 2759, Sect. 8.4
+ * @password_hash: 16-octet PasswordHash (IN)
+ * @password_hash_hash: 16-octet PasswordHashHash (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int hash_nt_password_hash(const u8 *password_hash, u8 *password_hash_hash)
+{
+    size_t len = 16;
+    return md4_vector(1, &password_hash, &len, password_hash_hash);
+}
+
+
+/**
+ * challenge_response - ChallengeResponse() - RFC 2759, Sect. 8.5
+ * @challenge: 8-octet Challenge (IN)
+ * @password_hash: 16-octet PasswordHash (IN)
+ * @response: 24-octet Response (OUT)
+ */
+void challenge_response(const u8 *challenge, const u8 *password_hash,
+           u8 *response)
+{
+    u8 zpwd[7];
+    des_encrypt(challenge, password_hash, response);
+    des_encrypt(challenge, password_hash + 7, response + 8);
+    zpwd[0] = password_hash[14];
+    zpwd[1] = password_hash[15];
+    os_memset(zpwd + 2, 0, 5);
+    des_encrypt(challenge, zpwd, response + 16);
+}
+
+
+/**
+ * generate_nt_response - GenerateNTResponse() - RFC 2759, Sect. 8.1
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @peer_challenge: 16-octet PeerChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
+ * @password_len: Length of password
+ * @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge,
+             const u8 *username, size_t username_len,
+             const u8 *password, size_t password_len,
+             u8 *response)
+{
+    u8 challenge[8];
+    u8 password_hash[16];
+
+    if (challenge_hash(peer_challenge, auth_challenge, username,
+               username_len, challenge))
+        return -1;
+    if (nt_password_hash(password, password_len, password_hash))
+        return -1;
+    challenge_response(challenge, password_hash, response);
+    return 0;
+}
+
+
+/**
+ * generate_nt_response_pwhash - GenerateNTResponse() - RFC 2759, Sect. 8.1
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @peer_challenge: 16-octet PeerChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @password_hash: 16-octet PasswordHash (IN)
+ * @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int generate_nt_response_pwhash(const u8 *auth_challenge,
+                const u8 *peer_challenge,
+                const u8 *username, size_t username_len,
+                const u8 *password_hash,
+                u8 *response)
+{
+    u8 challenge[8];
+
+    if (challenge_hash(peer_challenge, auth_challenge,
+               username, username_len,
+               challenge))
+        return -1;
+    challenge_response(challenge, password_hash, response);
+    return 0;
+}
+
+
+/**
+ * generate_authenticator_response_pwhash - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
+ * @password_hash: 16-octet PasswordHash (IN)
+ * @nt_response: 24-octet NT-Response (IN)
+ * @peer_challenge: 16-octet PeerChallenge (IN)
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
+ * encoded as a 42-octet ASCII string (S=hexdump_of_response)
+ * Returns: 0 on success, -1 on failure
+ */
+int generate_authenticator_response_pwhash(
+    const u8 *password_hash,
+    const u8 *peer_challenge, const u8 *auth_challenge,
+    const u8 *username, size_t username_len,
+    const u8 *nt_response, u8 *response)
+{
+    static const u8 magic1[39] = {
+        0x4D, 0x61, 0x67, 0x69, 0x63, 0x20, 0x73, 0x65, 0x72, 0x76,
+        0x65, 0x72, 0x20, 0x74, 0x6F, 0x20, 0x63, 0x6C, 0x69, 0x65,
+        0x6E, 0x74, 0x20, 0x73, 0x69, 0x67, 0x6E, 0x69, 0x6E, 0x67,
+        0x20, 0x63, 0x6F, 0x6E, 0x73, 0x74, 0x61, 0x6E, 0x74
+    };
+    static const u8 magic2[41] = {
+        0x50, 0x61, 0x64, 0x20, 0x74, 0x6F, 0x20, 0x6D, 0x61, 0x6B,
+        0x65, 0x20, 0x69, 0x74, 0x20, 0x64, 0x6F, 0x20, 0x6D, 0x6F,
+        0x72, 0x65, 0x20, 0x74, 0x68, 0x61, 0x6E, 0x20, 0x6F, 0x6E,
+        0x65, 0x20, 0x69, 0x74, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6F,
+        0x6E
+    };
+
+    u8 password_hash_hash[16], challenge[8];
+    const unsigned char *addr1[3];
+    const size_t len1[3] = { 16, 24, sizeof(magic1) };
+    const unsigned char *addr2[3];
+    const size_t len2[3] = { SHA1_MAC_LEN, 8, sizeof(magic2) };
+
+    addr1[0] = password_hash_hash;
+    addr1[1] = nt_response;
+    addr1[2] = magic1;
+
+    addr2[0] = response;
+    addr2[1] = challenge;
+    addr2[2] = magic2;
+
+    if (hash_nt_password_hash(password_hash, password_hash_hash))
+        return -1;
+    if (sha1_vector(3, addr1, len1, response))
+        return -1;
+
+    if (challenge_hash(peer_challenge, auth_challenge, username,
+               username_len, challenge))
+        return -1;
+    return sha1_vector(3, addr2, len2, response);
+}
+
+
+/**
+ * generate_authenticator_response - GenerateAuthenticatorResponse() - RFC 2759, Sect. 8.7
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
+ * @password_len: Length of password
+ * @nt_response: 24-octet NT-Response (IN)
+ * @peer_challenge: 16-octet PeerChallenge (IN)
+ * @auth_challenge: 16-octet AuthenticatorChallenge (IN)
+ * @username: 0-to-256-char UserName (IN)
+ * @username_len: Length of username
+ * @response: 20-octet AuthenticatorResponse (OUT) (note: this value is usually
+ * encoded as a 42-octet ASCII string (S=hexdump_of_response)
+ * Returns: 0 on success, -1 on failure
+ */
+int generate_authenticator_response(const u8 *password, size_t password_len,
+                const u8 *peer_challenge,
+                const u8 *auth_challenge,
+                const u8 *username, size_t username_len,
+                const u8 *nt_response, u8 *response)
+{
+    u8 password_hash[16];
+    if (nt_password_hash(password, password_len, password_hash))
+        return -1;
+    return generate_authenticator_response_pwhash(
+        password_hash, peer_challenge, auth_challenge,
+        username, username_len, nt_response, response);
+}
+
+
+/**
+ * nt_challenge_response - NtChallengeResponse() - RFC 2433, Sect. A.5
+ * @challenge: 8-octet Challenge (IN)
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
+ * @password_len: Length of password
+ * @response: 24-octet Response (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int nt_challenge_response(const u8 *challenge, const u8 *password,
+              size_t password_len, u8 *response)
+{
+    u8 password_hash[16];
+    if (nt_password_hash(password, password_len, password_hash))
+        return -1;
+    challenge_response(challenge, password_hash, response);
+    return 0;
+}
+
+
+/**
+ * get_master_key - GetMasterKey() - RFC 3079, Sect. 3.4
+ * @password_hash_hash: 16-octet PasswordHashHash (IN)
+ * @nt_response: 24-octet NTResponse (IN)
+ * @master_key: 16-octet MasterKey (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int get_master_key(const u8 *password_hash_hash, const u8 *nt_response,
+           u8 *master_key)
+{
+    static const u8 magic1[27] = {
+        0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74,
+        0x68, 0x65, 0x20, 0x4d, 0x50, 0x50, 0x45, 0x20, 0x4d,
+        0x61, 0x73, 0x74, 0x65, 0x72, 0x20, 0x4b, 0x65, 0x79
+    };
+    const unsigned char *addr[3];
+    const size_t len[3] = { 16, 24, sizeof(magic1) };
+    u8 hash[SHA1_MAC_LEN];
+
+    addr[0] = password_hash_hash;
+    addr[1] = nt_response;
+    addr[2] = magic1;
+
+    if (sha1_vector(3, addr, len, hash))
+        return -1;
+    os_memcpy(master_key, hash, 16);
+    return 0;
+}
+
+
+/**
+ * get_asymetric_start_key - GetAsymetricStartKey() - RFC 3079, Sect. 3.4
+ * @master_key: 16-octet MasterKey (IN)
+ * @session_key: 8-to-16 octet SessionKey (OUT)
+ * @session_key_len: SessionKeyLength (Length of session_key) (IN)
+ * @is_send: IsSend (IN, BOOLEAN)
+ * @is_server: IsServer (IN, BOOLEAN)
+ * Returns: 0 on success, -1 on failure
+ */
+int get_asymetric_start_key(const u8 *master_key, u8 *session_key,
+            size_t session_key_len, int is_send,
+            int is_server)
+{
+    static const u8 magic2[84] = {
+        0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+        0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+        0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+        0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20, 0x6b, 0x65, 0x79,
+        0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x73,
+        0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73, 0x69, 0x64, 0x65,
+        0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+        0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+        0x6b, 0x65, 0x79, 0x2e
+    };
+    static const u8 magic3[84] = {
+        0x4f, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x63, 0x6c, 0x69,
+        0x65, 0x6e, 0x74, 0x20, 0x73, 0x69, 0x64, 0x65, 0x2c, 0x20,
+        0x74, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x74, 0x68,
+        0x65, 0x20, 0x72, 0x65, 0x63, 0x65, 0x69, 0x76, 0x65, 0x20,
+        0x6b, 0x65, 0x79, 0x3b, 0x20, 0x6f, 0x6e, 0x20, 0x74, 0x68,
+        0x65, 0x20, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x20, 0x73,
+        0x69, 0x64, 0x65, 0x2c, 0x20, 0x69, 0x74, 0x20, 0x69, 0x73,
+        0x20, 0x74, 0x68, 0x65, 0x20, 0x73, 0x65, 0x6e, 0x64, 0x20,
+        0x6b, 0x65, 0x79, 0x2e
+    };
+    static const u8 shs_pad1[40] = {
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+    };
+
+    static const u8 shs_pad2[40] = {
+        0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+        0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+        0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2,
+        0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2, 0xf2
+    };
+    u8 digest[SHA1_MAC_LEN];
+    const unsigned char *addr[4];
+    const size_t len[4] = { 16, 40, 84, 40 };
+
+    addr[0] = master_key;
+    addr[1] = shs_pad1;
+    if (is_send) {
+        addr[2] = is_server ? magic3 : magic2;
+    } else {
+        addr[2] = is_server ? magic2 : magic3;
+    }
+    addr[3] = shs_pad2;
+
+    if (sha1_vector(4, addr, len, digest))
+        return -1;
+
+    if (session_key_len > SHA1_MAC_LEN)
+        session_key_len = SHA1_MAC_LEN;
+    os_memcpy(session_key, digest, session_key_len);
+    return 0;
+}
+
+
+#define PWBLOCK_LEN 516
+
+/**
+ * encrypt_pw_block_with_password_hash - EncryptPwBlockWithPasswordHash() - RFC 2759, Sect. 8.10
+ * @password: 0-to-256-unicode-char Password (IN; UTF-8)
+ * @password_len: Length of password
+ * @password_hash: 16-octet PasswordHash (IN)
+ * @pw_block: 516-byte PwBlock (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int encrypt_pw_block_with_password_hash(
+    const u8 *password, size_t password_len,
+    const u8 *password_hash, u8 *pw_block)
+{
+    size_t ucs2_len, offset;
+    u8 *pos;
+
+    os_memset(pw_block, 0, PWBLOCK_LEN);
+
+    if (utf8_to_ucs2(password, password_len, pw_block, 512, &ucs2_len) < 0)
+        return -1;
+
+    if (ucs2_len > 256)
+        return -1;
+
+    offset = (256 - ucs2_len) * 2;
+    if (offset != 0) {
+        os_memmove(pw_block + offset, pw_block, ucs2_len * 2);
+        if (os_get_random(pw_block, offset) < 0)
+            return -1;
+    }
+    /*
+     * PasswordLength is 4 octets, but since the maximum password length is
+     * 256, only first two (in little endian byte order) can be non-zero.
+     */
+    pos = &pw_block[2 * 256];
+    WPA_PUT_LE16(pos, password_len * 2);
+    rc4_skip(password_hash, 16, 0, pw_block, PWBLOCK_LEN);
+    return 0;
+}
+
+
+/**
+ * new_password_encrypted_with_old_nt_password_hash - NewPasswordEncryptedWithOldNtPasswordHash() - RFC 2759, Sect. 8.9
+ * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
+ * @new_password_len: Length of new_password
+ * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
+ * @old_password_len: Length of old_password
+ * @encrypted_pw_block: 516-octet EncryptedPwBlock (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int new_password_encrypted_with_old_nt_password_hash(
+    const u8 *new_password, size_t new_password_len,
+    const u8 *old_password, size_t old_password_len,
+    u8 *encrypted_pw_block)
+{
+    u8 password_hash[16];
+
+    if (nt_password_hash(old_password, old_password_len, password_hash))
+        return -1;
+    if (encrypt_pw_block_with_password_hash(new_password, new_password_len,
+                        password_hash,
+                        encrypted_pw_block))
+        return -1;
+    return 0;
+}
+
+
+/**
+ * nt_password_hash_encrypted_with_block - NtPasswordHashEncryptedWithBlock() - RFC 2759, Sect 8.13
+ * @password_hash: 16-octer PasswordHash (IN)
+ * @block: 16-octet Block (IN)
+ * @cypher: 16-octer Cypher (OUT)
+ */
+void nt_password_hash_encrypted_with_block(const u8 *password_hash,
+                      const u8 *block, u8 *cypher)
+{
+    des_encrypt(password_hash, block, cypher);
+    des_encrypt(password_hash + 8, block + 7, cypher + 8);
+}
+
+
+/**
+ * old_nt_password_hash_encrypted_with_new_nt_password_hash - OldNtPasswordHashEncryptedWithNewNtPasswordHash() - RFC 2759, Sect. 8.12
+ * @new_password: 0-to-256-unicode-char NewPassword (IN; UTF-8)
+ * @new_password_len: Length of new_password
+ * @old_password: 0-to-256-unicode-char OldPassword (IN; UTF-8)
+ * @old_password_len: Length of old_password
+ * @encrypted_password_hash: 16-octet EncryptedPasswordHash (OUT)
+ * Returns: 0 on success, -1 on failure
+ */
+int old_nt_password_hash_encrypted_with_new_nt_password_hash(
+    const u8 *new_password, size_t new_password_len,
+    const u8 *old_password, size_t old_password_len,
+    u8 *encrypted_password_hash)
+{
+    u8 old_password_hash[16], new_password_hash[16];
+
+    if (nt_password_hash(old_password, old_password_len,
+                 old_password_hash) ||
+        nt_password_hash(new_password, new_password_len,
+                 new_password_hash))
+        return -1;
+    nt_password_hash_encrypted_with_block(old_password_hash,
+                          new_password_hash,
+                          encrypted_password_hash);
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/rc4.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/rc4.c
new file mode 100644
index 0000000000000000000000000000000000000000..7a095cd0285de3e255bb9cab0fc84b5b40228261
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/rc4.c
@@ -0,0 +1,61 @@
+/*
+ * RC4 stream cipher
+ * Copyright (c) 2002-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/crypto.h"
+
+#define S_SWAP(a,b) do { u8 t = S[a]; S[a] = S[b]; S[b] = t; } while(0)
+
+int
+rc4_skip(const u8 *key, size_t keylen, size_t skip,
+         u8 *data, size_t data_len)
+{
+    u32 i, j, k;
+    u8 S[256], *pos;
+    size_t kpos;
+
+    /* Setup RC4 state */
+    for (i = 0; i < 256; i++)
+        S[i] = i;
+    j = 0;
+    kpos = 0;
+    for (i = 0; i < 256; i++) {
+        j = (j + S[i] + key[kpos]) & 0xff;
+        kpos++;
+        if (kpos >= keylen)
+            kpos = 0;
+        S_SWAP(i, j);
+    }
+
+    /* Skip the start of the stream */
+    i = j = 0;
+    for (k = 0; k < skip; k++) {
+        i = (i + 1) & 0xff;
+        j = (j + S[i]) & 0xff;
+        S_SWAP(i, j);
+    }
+
+    /* Apply RC4 to data */
+    pos = data;
+    for (k = 0; k < data_len; k++) {
+        i = (i + 1) & 0xff;
+        j = (j + S[i]) & 0xff;
+        S_SWAP(i, j);
+        *pos++ ^= S[(S[i] + S[j]) & 0xff];
+    }
+
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1-internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..a37acc615409d123a981db0f56dc5e665ca18e75
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1-internal.c
@@ -0,0 +1,313 @@
+/*
+ * SHA1 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha1.h"
+#include "crypto/sha1_i.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+
+typedef struct SHA1Context SHA1_CTX;
+
+void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
+
+
+/**
+ * sha1_vector - SHA-1 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int
+sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
+{
+    SHA1_CTX ctx;
+    size_t i;
+
+    SHA1Init(&ctx);
+    for (i = 0; i < num_elem; i++)
+        SHA1Update(&ctx, addr[i], len[i]);
+    SHA1Final(mac, &ctx);
+    return 0;
+}
+
+
+/* ===== start - public domain SHA1 implementation ===== */
+
+/*
+SHA-1 in C
+By Steve Reid <sreid@sea-to-sky.net>
+100% Public Domain
+
+-----------------
+Modified 7/98
+By James H. Brown <jbrown@burgoyne.com>
+Still 100% Public Domain
+
+Corrected a problem which generated improper hash values on 16 bit machines
+Routine SHA1Update changed from
+    void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
+len)
+to
+    void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
+long len)
+
+The 'len' parameter was declared an int which works fine on 32 bit machines.
+However, on 16 bit machines an int is too small for the shifts being done
+against
+it.  This caused the hash function to generate incorrect values if len was
+greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
+
+Since the file IO in main() reads 16K at a time, any file 8K or larger would
+be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
+"a"s).
+
+I also changed the declaration of variables i & j in SHA1Update to
+unsigned long from unsigned int for the same reason.
+
+These changes should make no difference to any 32 bit implementations since
+an
+int and a long are the same size in those environments.
+
+--
+I also corrected a few compiler warnings generated by Borland C.
+1. Added #include <process.h> for exit() prototype
+2. Removed unused variable 'j' in SHA1Final
+3. Changed exit(0) to return(0) at end of main.
+
+ALL changes I made can be located by searching for comments containing 'JHB'
+-----------------
+Modified 8/98
+By Steve Reid <sreid@sea-to-sky.net>
+Still 100% public domain
+
+1- Removed #include <process.h> and used return() instead of exit()
+2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
+3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
+
+-----------------
+Modified 4/01
+By Saul Kravitz <Saul.Kravitz@celera.com>
+Still 100% PD
+Modified to run on Compaq Alpha hardware.
+
+-----------------
+Modified 4/01
+By Jouni Malinen <j@w1.fi>
+Minor changes to match the coding style used in Dynamics.
+
+Modified September 24, 2004
+By Jouni Malinen <j@w1.fi>
+Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
+
+*/
+
+/*
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+#define SHA1HANDSOFF
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#ifndef WORDS_BIGENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
+    (rol(block->l[i], 8) & 0x00FF00FF))
+#else
+#define blk0(i) block->l[i]
+#endif
+#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
+    block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) \
+    z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
+    w = rol(w, 30);
+#define R1(v,w,x,y,z,i) \
+    z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
+    w = rol(w, 30);
+#define R2(v,w,x,y,z,i) \
+    z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
+#define R3(v,w,x,y,z,i) \
+    z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
+    w = rol(w, 30);
+#define R4(v,w,x,y,z,i) \
+    z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
+    w=rol(w, 30);
+
+
+#ifdef VERBOSE  /* SAK */
+void SHAPrintContext(SHA1_CTX *context, char *msg)
+{
+    printf("%s (%d,%d) %x %x %x %x %x\n",
+           msg,
+           context->count[0], context->count[1],
+           context->state[0],
+           context->state[1],
+           context->state[2],
+           context->state[3],
+           context->state[4]);
+}
+#endif
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void
+SHA1Transform(u32 state[5], const unsigned char buffer[64])
+{
+    u32 a, b, c, d, e;
+    typedef union {
+        unsigned char c[64];
+        u32 l[16];
+    } CHAR64LONG16;
+    CHAR64LONG16* block;
+#ifdef SHA1HANDSOFF
+    CHAR64LONG16 workspace;
+    block = &workspace;
+    os_memcpy(block, buffer, 64);
+#else
+    block = (CHAR64LONG16 *) buffer;
+#endif
+    /* Copy context->state[] to working vars */
+    a = state[0];
+    b = state[1];
+    c = state[2];
+    d = state[3];
+    e = state[4];
+    /* 4 rounds of 20 operations each. Loop unrolled. */
+    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+    /* Add the working vars back into context.state[] */
+    state[0] += a;
+    state[1] += b;
+    state[2] += c;
+    state[3] += d;
+    state[4] += e;
+    /* Wipe variables */
+    a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+    os_memset(block, 0, 64);
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void
+SHA1Init(SHA1_CTX* context)
+{
+    /* SHA1 initialization constants */
+    context->state[0] = 0x67452301;
+    context->state[1] = 0xEFCDAB89;
+    context->state[2] = 0x98BADCFE;
+    context->state[3] = 0x10325476;
+    context->state[4] = 0xC3D2E1F0;
+    context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void
+SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
+{
+    u32 i, j;
+    const unsigned char *data = _data;
+
+#ifdef VERBOSE
+    SHAPrintContext(context, "before");
+#endif
+    j = (context->count[0] >> 3) & 63;
+    if ((context->count[0] += len << 3) < (len << 3))
+        context->count[1]++;
+    context->count[1] += (len >> 29);
+    if ((j + len) > 63) {
+        os_memcpy(&context->buffer[j], data, (i = 64-j));
+        SHA1Transform(context->state, context->buffer);
+        for ( ; i + 63 < len; i += 64) {
+            SHA1Transform(context->state, &data[i]);
+        }
+        j = 0;
+    }
+    else i = 0;
+    os_memcpy(&context->buffer[j], &data[i], len - i);
+#ifdef VERBOSE
+    SHAPrintContext(context, "after ");
+#endif
+}
+
+
+/* Add padding and return the message digest. */
+
+void
+SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+    u32 i;
+    unsigned char finalcount[8];
+
+    for (i = 0; i < 8; i++) {
+        finalcount[i] = (unsigned char)
+            ((context->count[(i >= 4 ? 0 : 1)] >>
+              ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
+    }
+    SHA1Update(context, (unsigned char *) "\200", 1);
+    while ((context->count[0] & 504) != 448) {
+        SHA1Update(context, (unsigned char *) "\0", 1);
+    }
+    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform()
+                          */
+    for (i = 0; i < 20; i++) {
+        digest[i] = (unsigned char)
+            ((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
+             255);
+    }
+    /* Wipe variables */
+    i = 0;
+    os_memset(context->buffer, 0, 64);
+    os_memset(context->state, 0, 20);
+    os_memset(context->count, 0, 8);
+    os_memset(finalcount, 0, 8);
+}
+
+/* ===== end - public domain SHA1 implementation ===== */
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1-pbkdf2.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1-pbkdf2.c
new file mode 100644
index 0000000000000000000000000000000000000000..d42582863f0d3778a6c1993cef33470def77af4e
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1-pbkdf2.c
@@ -0,0 +1,101 @@
+/*
+ * SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+#include "crypto/common.h"
+#include "crypto/sha1.h"
+#include "crypto/md5.h"
+#include "crypto/crypto.h"
+
+static int
+pbkdf2_sha1_f(const char *passphrase, const char *ssid,
+             size_t ssid_len, int iterations, unsigned int count,
+             u8 *digest)
+{
+    unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
+    int i, j;
+    unsigned char count_buf[4];
+    const u8 *addr[2];
+    size_t len[2];
+    size_t passphrase_len = os_strlen(passphrase);
+
+    addr[0] = (u8 *) ssid;
+    len[0] = ssid_len;
+    addr[1] = count_buf;
+    len[1] = 4;
+
+    /* F(P, S, c, i) = U1 xor U2 xor ... Uc
+     * U1 = PRF(P, S || i)
+     * U2 = PRF(P, U1)
+     * Uc = PRF(P, Uc-1)
+     */
+
+    count_buf[0] = (count >> 24) & 0xff;
+    count_buf[1] = (count >> 16) & 0xff;
+    count_buf[2] = (count >> 8) & 0xff;
+    count_buf[3] = count & 0xff;
+    if (hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len,
+                 tmp))
+        return -1;
+    os_memcpy(digest, tmp, SHA1_MAC_LEN);
+
+    for (i = 1; i < iterations; i++) {
+        if (hmac_sha1((u8 *) passphrase, passphrase_len, tmp,
+                  SHA1_MAC_LEN, tmp2))
+            return -1;
+        os_memcpy(tmp, tmp2, SHA1_MAC_LEN);
+        for (j = 0; j < SHA1_MAC_LEN; j++)
+            digest[j] ^= tmp2[j];
+    }
+
+    return 0;
+}
+
+
+/**
+ * pbkdf2_sha1 - SHA1-based key derivation function (PBKDF2) for IEEE 802.11i
+ * @passphrase: ASCII passphrase
+ * @ssid: SSID
+ * @ssid_len: SSID length in bytes
+ * @iterations: Number of iterations to run
+ * @buf: Buffer for the generated key
+ * @buflen: Length of the buffer in bytes
+ * Returns: 0 on success, -1 of failure
+ *
+ * This function is used to derive PSK for WPA-PSK. For this protocol,
+ * iterations is set to 4096 and buflen to 32. This function is described in
+ * IEEE Std 802.11-2004, Clause H.4. The main construction is from PKCS#5 v2.0.
+ */
+int
+pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
+        int iterations, u8 *buf, size_t buflen)
+{
+    unsigned int count = 0;
+    unsigned char *pos = buf;
+    size_t left = buflen, plen;
+    unsigned char digest[SHA1_MAC_LEN];
+
+    while (left > 0) {
+        count++;
+        if (pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations,
+                  count, digest))
+            return -1;
+        plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
+        os_memcpy(pos, digest, plen);
+        pos += plen;
+        left -= plen;
+    }
+
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1.c
new file mode 100644
index 0000000000000000000000000000000000000000..701426c6b80e9b2af170aea5026f9d1dcafd2b69
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha1.c
@@ -0,0 +1,165 @@
+/*
+ * SHA1 hash implementation and interface functions
+ * Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha1.h"
+#include "crypto/crypto.h"
+
+
+/**
+ * hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (20 bytes)
+ * Returns: 0 on success, -1 on failure
+ */
+int
+hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
+             const u8 *addr[], const size_t *len, u8 *mac)
+{
+    unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
+    unsigned char tk[20];
+    const u8 *_addr[6];
+    size_t _len[6], i;
+
+    if (num_elem > 5) {
+        /*
+         * Fixed limit on the number of fragments to avoid having to
+         * allocate memory (which could fail).
+         */
+        return -1;
+    }
+
+        /* if key is longer than 64 bytes reset it to key = SHA1(key) */
+        if (key_len > 64) {
+        if (sha1_vector(1, &key, &key_len, tk))
+            return -1;
+        key = tk;
+        key_len = 20;
+        }
+
+    /* the HMAC_SHA1 transform looks like:
+     *
+     * SHA1(K XOR opad, SHA1(K XOR ipad, text))
+     *
+     * where K is an n byte key
+     * ipad is the byte 0x36 repeated 64 times
+     * opad is the byte 0x5c repeated 64 times
+     * and text is the data being protected */
+
+    /* start out by storing key in ipad */
+    os_memset(k_pad, 0, sizeof(k_pad));
+    os_memcpy(k_pad, key, key_len);
+    /* XOR key with ipad values */
+    for (i = 0; i < 64; i++)
+        k_pad[i] ^= 0x36;
+
+    /* perform inner SHA1 */
+    _addr[0] = k_pad;
+    _len[0] = 64;
+    for (i = 0; i < num_elem; i++) {
+        _addr[i + 1] = addr[i];
+        _len[i + 1] = len[i];
+    }
+    if (sha1_vector(1 + num_elem, _addr, _len, mac))
+        return -1;
+
+    os_memset(k_pad, 0, sizeof(k_pad));
+    os_memcpy(k_pad, key, key_len);
+    /* XOR key with opad values */
+    for (i = 0; i < 64; i++)
+        k_pad[i] ^= 0x5c;
+
+    /* perform outer SHA1 */
+    _addr[0] = k_pad;
+    _len[0] = 64;
+    _addr[1] = mac;
+    _len[1] = SHA1_MAC_LEN;
+    return sha1_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (20 bytes)
+ * Returns: 0 on success, -1 of failure
+ */
+int
+hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
+           u8 *mac)
+{
+    return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+/**
+ * sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1)
+ * @key: Key for PRF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bytes of key to generate
+ * Returns: 0 on success, -1 of failure
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key (e.g., PMK in IEEE 802.11i).
+ */
+int
+sha1_prf(const u8 *key, size_t key_len, const char *label,
+         const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
+{
+    u8 counter = 0;
+    size_t pos, plen;
+    u8 hash[SHA1_MAC_LEN];
+    size_t label_len = os_strlen(label) + 1;
+    const unsigned char *addr[3];
+    size_t len[3];
+
+    addr[0] = (u8 *) label;
+    len[0] = label_len;
+    addr[1] = data;
+    len[1] = data_len;
+    addr[2] = &counter;
+    len[2] = 1;
+
+    pos = 0;
+    while (pos < buf_len) {
+        plen = buf_len - pos;
+        if (plen >= SHA1_MAC_LEN) {
+            if (hmac_sha1_vector(key, key_len, 3, addr, len,
+                         &buf[pos]))
+                return -1;
+            pos += SHA1_MAC_LEN;
+        } else {
+            if (hmac_sha1_vector(key, key_len, 3, addr, len,
+                         hash))
+                return -1;
+            os_memcpy(&buf[pos], hash, plen);
+            break;
+        }
+        counter++;
+    }
+
+    return 0;
+}
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha256-internal.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha256-internal.c
new file mode 100644
index 0000000000000000000000000000000000000000..88f1950d6bd73fdb663ad647959d552bd7da8c66
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha256-internal.c
@@ -0,0 +1,249 @@
+/*
+ * SHA-256 hash implementation and interface functions
+ * Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
+
+#define SHA256_BLOCK_SIZE 64
+
+struct sha256_state {
+    u64 length;
+    u32 state[8], curlen;
+    u8 buf[SHA256_BLOCK_SIZE];
+};
+
+static void sha256_init(struct sha256_state *md);
+static int sha256_process(struct sha256_state *md, const unsigned char *in,
+              unsigned long inlen);
+static int sha256_done(struct sha256_state *md, unsigned char *out);
+
+
+/**
+ * sha256_vector - SHA256 hash for data vector
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash
+ * Returns: 0 on success, -1 of failure
+ */
+int
+sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
+          u8 *mac)
+{
+    struct sha256_state ctx;
+    size_t i;
+
+    sha256_init(&ctx);
+    for (i = 0; i < num_elem; i++)
+        if (sha256_process(&ctx, addr[i], len[i]))
+            return -1;
+    if (sha256_done(&ctx, mac))
+        return -1;
+    return 0;
+}
+
+
+/* ===== start - public domain SHA256 implementation ===== */
+
+/* This is based on SHA256 implementation in LibTomCrypt that was released into
+ * public domain by Tom St Denis. */
+
+/* the K array */
+static const unsigned long K[64] = {
+    0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
+    0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
+    0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
+    0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
+    0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
+    0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
+    0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
+    0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
+    0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
+    0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
+    0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
+    0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
+    0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
+};
+
+
+/* Various logical functions */
+#define RORc(x, y) \
+( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
+   ((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
+#define Ch(x,y,z)       (z ^ (x & (y ^ z)))
+#define Maj(x,y,z)      (((x | y) & z) | (x & y))
+#define S(x, n)         RORc((x), (n))
+#define R(x, n)         (((x)&0xFFFFFFFFUL)>>(n))
+#define Sigma0(x)       (S(x, 2) ^ S(x, 13) ^ S(x, 22))
+#define Sigma1(x)       (S(x, 6) ^ S(x, 11) ^ S(x, 25))
+#define Gamma0(x)       (S(x, 7) ^ S(x, 18) ^ R(x, 3))
+#define Gamma1(x)       (S(x, 17) ^ S(x, 19) ^ R(x, 10))
+#ifndef MIN
+#define MIN(x, y) (((x) < (y)) ? (x) : (y))
+#endif
+
+/* compress 512-bits */
+static int
+sha256_compress(struct sha256_state *md, unsigned char *buf)
+{
+    u32 S[8], W[64], t0, t1;
+    u32 t;
+    int i;
+
+    /* copy state into S */
+    for (i = 0; i < 8; i++) {
+        S[i] = md->state[i];
+    }
+
+    /* copy the state into 512-bits into W[0..15] */
+    for (i = 0; i < 16; i++)
+        W[i] = WPA_GET_BE32(buf + (4 * i));
+
+    /* fill W[16..63] */
+    for (i = 16; i < 64; i++) {
+        W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
+            W[i - 16];
+    }
+
+    /* Compress */
+#define RND(a,b,c,d,e,f,g,h,i)                          \
+    t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i];    \
+    t1 = Sigma0(a) + Maj(a, b, c);            \
+    d += t0;                    \
+    h  = t0 + t1;
+
+    for (i = 0; i < 64; ++i) {
+        RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
+        t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
+        S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
+    }
+
+    /* feedback */
+    for (i = 0; i < 8; i++) {
+        md->state[i] = md->state[i] + S[i];
+    }
+    return 0;
+}
+
+
+/* Initialize the hash state */
+static void
+sha256_init(struct sha256_state *md)
+{
+    md->curlen = 0;
+    md->length = 0;
+    md->state[0] = 0x6A09E667UL;
+    md->state[1] = 0xBB67AE85UL;
+    md->state[2] = 0x3C6EF372UL;
+    md->state[3] = 0xA54FF53AUL;
+    md->state[4] = 0x510E527FUL;
+    md->state[5] = 0x9B05688CUL;
+    md->state[6] = 0x1F83D9ABUL;
+    md->state[7] = 0x5BE0CD19UL;
+}
+
+/**
+   Process a block of memory though the hash
+   @param md     The hash state
+   @param in     The data to hash
+   @param inlen  The length of the data (octets)
+   @return CRYPT_OK if successful
+*/
+static int
+sha256_process(struct sha256_state *md, const unsigned char *in,
+              unsigned long inlen)
+{
+    unsigned long n;
+
+    if (md->curlen >= sizeof(md->buf))
+        return -1;
+
+    while (inlen > 0) {
+        if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
+            if (sha256_compress(md, (unsigned char *) in) < 0)
+                return -1;
+            md->length += SHA256_BLOCK_SIZE * 8;
+            in += SHA256_BLOCK_SIZE;
+            inlen -= SHA256_BLOCK_SIZE;
+        } else {
+            n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
+            os_memcpy(md->buf + md->curlen, in, n);
+            md->curlen += n;
+            in += n;
+            inlen -= n;
+            if (md->curlen == SHA256_BLOCK_SIZE) {
+                if (sha256_compress(md, md->buf) < 0)
+                    return -1;
+                md->length += 8 * SHA256_BLOCK_SIZE;
+                md->curlen = 0;
+            }
+        }
+    }
+
+    return 0;
+}
+
+
+/**
+   Terminate the hash to get the digest
+   @param md  The hash state
+   @param out [out] The destination of the hash (32 bytes)
+   @return CRYPT_OK if successful
+*/
+static int
+sha256_done(struct sha256_state *md, unsigned char *out)
+{
+    int i;
+
+    if (md->curlen >= sizeof(md->buf))
+        return -1;
+
+    /* increase the length of the message */
+    md->length += md->curlen * 8;
+
+    /* append the '1' bit */
+    md->buf[md->curlen++] = (unsigned char) 0x80;
+
+    /* if the length is currently above 56 bytes we append zeros
+     * then compress.  Then we can fall back to padding zeros and length
+     * encoding like normal.
+     */
+    if (md->curlen > 56) {
+        while (md->curlen < SHA256_BLOCK_SIZE) {
+            md->buf[md->curlen++] = (unsigned char) 0;
+        }
+        sha256_compress(md, md->buf);
+        md->curlen = 0;
+    }
+
+    /* pad up to 56 bytes of zeroes */
+    while (md->curlen < 56) {
+        md->buf[md->curlen++] = (unsigned char) 0;
+    }
+
+    /* store length */
+    WPA_PUT_BE64(md->buf + 56, md->length);
+    sha256_compress(md, md->buf);
+
+    /* copy output */
+    for (i = 0; i < 8; i++)
+        WPA_PUT_BE32(out + (4 * i), md->state[i]);
+
+    return 0;
+}
+
+/* ===== end - public domain SHA256 implementation ===== */
diff --git a/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha256.c b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha256.c
new file mode 100644
index 0000000000000000000000000000000000000000..30a9e1b3b955de0a3b3d3f6989c5d300cda6de64
--- /dev/null
+++ b/cpu/esp32/vendor/esp-idf/wpa_supplicant/src/crypto/sha256.c
@@ -0,0 +1,160 @@
+/*
+ * SHA-256 hash implementation and interface functions
+ * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Alternatively, this software may be distributed under the terms of BSD
+ * license.
+ *
+ * See README and COPYING for more details.
+ */
+
+#include "crypto/includes.h"
+
+#include "crypto/common.h"
+#include "crypto/sha256.h"
+#include "crypto/crypto.h"
+
+
+/**
+ * hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @num_elem: Number of elements in the data vector
+ * @addr: Pointers to the data areas
+ * @len: Lengths of the data blocks
+ * @mac: Buffer for the hash (32 bytes)
+ */
+void
+hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
+            const u8 *addr[], const size_t *len, u8 *mac)
+{
+    unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
+    unsigned char tk[32];
+    const u8 *_addr[6];
+    size_t _len[6], i;
+
+    if (num_elem > 5) {
+        /*
+         * Fixed limit on the number of fragments to avoid having to
+         * allocate memory (which could fail).
+         */
+        return;
+    }
+
+        /* if key is longer than 64 bytes reset it to key = SHA256(key) */
+        if (key_len > 64) {
+        sha256_vector(1, &key, &key_len, tk);
+        key = tk;
+        key_len = 32;
+        }
+
+    /* the HMAC_SHA256 transform looks like:
+     *
+     * SHA256(K XOR opad, SHA256(K XOR ipad, text))
+     *
+     * where K is an n byte key
+     * ipad is the byte 0x36 repeated 64 times
+     * opad is the byte 0x5c repeated 64 times
+     * and text is the data being protected */
+
+    /* start out by storing key in ipad */
+    os_memset(k_pad, 0, sizeof(k_pad));
+    os_memcpy(k_pad, key, key_len);
+    /* XOR key with ipad values */
+    for (i = 0; i < 64; i++)
+        k_pad[i] ^= 0x36;
+
+    /* perform inner SHA256 */
+    _addr[0] = k_pad;
+    _len[0] = 64;
+    for (i = 0; i < num_elem; i++) {
+        _addr[i + 1] = addr[i];
+        _len[i + 1] = len[i];
+    }
+    sha256_vector(1 + num_elem, _addr, _len, mac);
+
+    os_memset(k_pad, 0, sizeof(k_pad));
+    os_memcpy(k_pad, key, key_len);
+    /* XOR key with opad values */
+    for (i = 0; i < 64; i++)
+        k_pad[i] ^= 0x5c;
+
+    /* perform outer SHA256 */
+    _addr[0] = k_pad;
+    _len[0] = 64;
+    _addr[1] = mac;
+    _len[1] = SHA256_MAC_LEN;
+    sha256_vector(2, _addr, _len, mac);
+}
+
+
+/**
+ * hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
+ * @key: Key for HMAC operations
+ * @key_len: Length of the key in bytes
+ * @data: Pointers to the data area
+ * @data_len: Length of the data area
+ * @mac: Buffer for the hash (20 bytes)
+ */
+void
+hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
+         size_t data_len, u8 *mac)
+{
+    hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
+}
+
+
+/**
+ * sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
+ * @key: Key for PRF
+ * @key_len: Length of the key in bytes
+ * @label: A unique label for each purpose of the PRF
+ * @data: Extra data to bind into the key
+ * @data_len: Length of the data
+ * @buf: Buffer for the generated pseudo-random key
+ * @buf_len: Number of bytes of key to generate
+ *
+ * This function is used to derive new, cryptographically separate keys from a
+ * given key.
+ */
+void
+sha256_prf(const u8 *key, size_t key_len, const char *label,
+        const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
+{
+    u16 counter = 1;
+    size_t pos, plen;
+    u8 hash[SHA256_MAC_LEN];
+    const u8 *addr[4];
+    size_t len[4];
+    u8 counter_le[2], length_le[2];
+
+    addr[0] = counter_le;
+    len[0] = 2;
+    addr[1] = (u8 *) label;
+    len[1] = os_strlen(label);
+    addr[2] = data;
+    len[2] = data_len;
+    addr[3] = length_le;
+    len[3] = sizeof(length_le);
+
+    WPA_PUT_LE16(length_le, buf_len * 8);
+    pos = 0;
+    while (pos < buf_len) {
+        plen = buf_len - pos;
+        WPA_PUT_LE16(counter_le, counter);
+        if (plen >= SHA256_MAC_LEN) {
+            hmac_sha256_vector(key, key_len, 4, addr, len,
+                       &buf[pos]);
+            pos += SHA256_MAC_LEN;
+        } else {
+            hmac_sha256_vector(key, key_len, 4, addr, len, hash);
+            os_memcpy(&buf[pos], hash, plen);
+            break;
+        }
+        counter++;
+    }
+}
diff --git a/cpu/esp32/vendor/esp/LICENSE b/cpu/esp32/vendor/esp/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..08d96c4a598744b4424545e586bc646ad5ab9cdf
--- /dev/null
+++ b/cpu/esp32/vendor/esp/LICENSE
@@ -0,0 +1,12 @@
+Copyright (c) 2015, SuperHouse Automation Pty Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/cpu/esp32/vendor/esp/README.md b/cpu/esp32/vendor/esp/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..cc57fa847b3f081b4b4ce6dba3114b03e77e5818
--- /dev/null
+++ b/cpu/esp32/vendor/esp/README.md
@@ -0,0 +1,3 @@
+All files in this directory are part of [esp-open-rtos](https://github.com/SuperHouse/esp-open-rtos.git). They are under the copyright of their respective owners.
+
+All of these files are BSD Licensed as described in the file [LICENSE](https://github.com/SuperHouse/esp-open-rtos/blob/master/LICENSE).
diff --git a/cpu/esp32/vendor/esp/common_macros.h b/cpu/esp32/vendor/esp/common_macros.h
new file mode 100644
index 0000000000000000000000000000000000000000..9189f9e60e62e89b4effdb191d281621ec188cec
--- /dev/null
+++ b/cpu/esp32/vendor/esp/common_macros.h
@@ -0,0 +1,141 @@
+/* Some common compiler macros
+ *
+ * Not esp8266-specific.
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Superhouse Automation Pty Ltd
+ * BSD Licensed as described in the file LICENSE
+ */
+
+/*
+Copyright (c) 2015, SuperHouse Automation Pty Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef COMMON_MACROS_H
+#define COMMON_MACROS_H
+
+#include <sys/cdefs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UNUSED __attributed((unused))
+
+/* These macros convert values to/from bitfields specified by *_M and *_S (mask
+ * and shift) constants.  Used primarily with ESP8266 register access.
+ */
+
+#define VAL2FIELD(fieldname, value) ((value) << fieldname##_S)
+#define FIELD2VAL(fieldname, regbits) (((regbits) >> fieldname##_S) & fieldname##_M)
+
+#define FIELD_MASK(fieldname) (fieldname##_M << fieldname##_S)
+#define SET_FIELD(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD(fieldname, value))
+
+/* VAL2FIELD/SET_FIELD do not normally check to make sure that the passed value
+ * will fit in the specified field (without clobbering other bits).  This makes
+ * them faster and is usually fine.  If you do need to make sure that the value
+ * will not overflow the field, use VAL2FIELD_M or SET_FIELD_M (which will
+ * first mask the supplied value to only the allowed number of bits) instead.
+ */
+#define VAL2FIELD_M(fieldname, value) (((value) & fieldname##_M) << fieldname##_S)
+#define SET_FIELD_M(regbits, fieldname, value) (((regbits) & ~FIELD_MASK(fieldname)) | VAL2FIELD_M(fieldname, value))
+
+/* Set bits in reg with specified mask.
+ */
+#define SET_MASK_BITS(reg, mask) (reg) |= (mask)
+
+/* Clear bits in reg with specified mask
+ */
+#define CLEAR_MASK_BITS(reg, mask) (reg) &= ~(mask)
+
+/* Use the IRAM macro to place functions into Instruction RAM (IRAM)
+   instead of flash (aka irom).
+
+   (This is the opposite to the Espressif SDK, where functions default
+   to being placed in IRAM but the ICACHE_FLASH_ATTR attribute will
+   place them in flash.)
+
+   Use the IRAM attribute for functions which are called when the
+   flash may not be available (for example during NMI exceptions), or
+   for functions which are called very frequently and need high
+   performance.
+
+   Usage example:
+
+   void IRAM high_performance_function(void)
+   {
+       // do important thing here
+   }
+
+   Bear in mind IRAM is limited (32KB), compared to up to 1MB of flash.
+*/
+#define IRAM __attribute__((section(".iram1.text")))
+
+/* Use the RAM macro to place constant data (rodata) into RAM (data
+   RAM) instead of the default placement in flash. This is useful for
+   constant data which needs high performance access.
+
+   Usage example:
+
+   const RAM uint8_t constants[] = { 1, 2, 3, 7 };
+
+   When placing string literals in RAM, they need to be declared with
+   the type "const char[]" not "const char *"
+
+   Usage example:
+
+   const RAM char hello_world[] = "Hello World";
+*/
+#define RAM __attribute__((section(".data")))
+
+/* Use the IRAM_DATA macro to place data into Instruction RAM (IRAM)
+   instead of the default of flash (for constant data) or data RAM
+   (for non-constant data).
+
+   This may be useful to free up data RAM. However all data read from
+   any instruction space (either IRAM or Flash) must be 32-bit aligned
+   word reads. Reading unaligned data stored with IRAM_DATA will be
+   slower than reading data stored in RAM. You can't perform unaligned
+   writes to IRAM.
+*/
+#define IRAM_DATA __attribute__((section(".iram1.data")))
+
+/* Use the IROM macro to store constant values in IROM flash. In
+  esp-open-rtos this is already the default location for most constant
+  data (rodata), so you don't need this attribute in 99% of cases.
+
+  The exceptions are to mark data in the core & freertos libraries,
+  where the default for constant data storage is RAM.
+
+  (Unlike the Espressif SDK you don't need to use an attribute like
+  ICACHE_FLASH_ATTR for functions, they go into flash by default.)
+
+  Important to note: IROM flash is accessed via 32-bit word aligned
+  reads. esp-open-rtos does some magic to "fix" unaligned reads, but
+  performance is reduced.
+*/
+#ifdef    __cplusplus
+    #define IROM __attribute__((section(".irom0.text")))
+    #define IROM_LIT __attribute__((section(".irom0.literal")))
+#else
+    #define IROM __attribute__((section(".irom0.text")))
+    #define IROM_LIT __attribute__((section(".irom0.literal"))) const
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* COMMON_MACROS_H */
diff --git a/cpu/esp32/vendor/esp/xtensa_ops.h b/cpu/esp32/vendor/esp/xtensa_ops.h
new file mode 100644
index 0000000000000000000000000000000000000000..12006843aab3a3df2977aa7e9f5c8090e28d5b33
--- /dev/null
+++ b/cpu/esp32/vendor/esp/xtensa_ops.h
@@ -0,0 +1,65 @@
+/** xtensa_ops.h
+ *
+ * Special macros/etc which deal with Xtensa-specific architecture/CPU
+ * considerations.
+ *
+ * Part of esp-open-rtos
+ * Copyright (C) 2015 Superhouse Automation Pty Ltd
+ * BSD Licensed as described in the file LICENSE
+ */
+
+/*
+Copyright (c) 2015, SuperHouse Automation Pty Ltd
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef XTENSA_OPS_H
+#define XTENSA_OPS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Read stack pointer to variable.
+ *
+ * Note that the compiler will push a stack frame (minimum 16 bytes)
+ * in the prelude of a C function that calls any other functions.
+ */
+#define SP(var) __asm__ volatile ("mov %0, a1" : "=r" (var))
+
+/* Read the function return address to a variable.
+ *
+ * Depends on the containing function being simple enough that a0 is
+ * being used as a working register.
+ */
+#define RETADDR(var) __asm__ volatile ("mov %0, a0" : "=r" (var))
+
+// GCC macros for reading, writing, and exchanging Xtensa processor special
+// registers:
+
+#define RSR(var, reg) __asm__ volatile ("rsr %0, " #reg : "=r" (var));
+#define WSR(var, reg) __asm__ volatile ("wsr %0, " #reg : : "r" (var));
+#define XSR(var, reg) __asm__ volatile ("xsr %0, " #reg : "+r" (var));
+
+// GCC macros for performing associated "*sync" opcodes
+
+#define ISYNC() __asm__ volatile ( "isync" )
+#define RSYNC() __asm__ volatile ( "rsync" )
+#define ESYNC() __asm__ volatile ( "esync" )
+#define DSYNC() __asm__ volatile ( "dsync" )
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* XTENSA_OPS_H */
diff --git a/cpu/esp32/vendor/xtensa/Makefile b/cpu/esp32/vendor/xtensa/Makefile
new file mode 100644
index 0000000000000000000000000000000000000000..350d5aaf0c8331a6c82895952ec58bcb30c79cd3
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/Makefile
@@ -0,0 +1,3 @@
+MODULE=xtensa
+
+include $(RIOTBASE)/Makefile.base
diff --git a/cpu/esp32/vendor/xtensa/README.md b/cpu/esp32/vendor/xtensa/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..6cce4e5f16ffba534b9362b19aa5e5deccc11ee1
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/README.md
@@ -0,0 +1,30 @@
+All files in this directory are from the [FreeRTOS port for Xtensa](https://github.com/tensilica/freertos) configurable processors and Diamond processors. All of these files are copyright of Cadence Design Systems Inc., see below.
+
+Some of the files are slightly modified for the RIOT OS port.
+
+Please note the following copyright notices for all these files:
+
+```
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+```
diff --git a/cpu/esp32/vendor/xtensa/portasm.S b/cpu/esp32/vendor/xtensa/portasm.S
new file mode 100644
index 0000000000000000000000000000000000000000..db0da672f1520ade0f0ce2f87022465f42b4f239
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/portasm.S
@@ -0,0 +1,636 @@
+/*
+//-----------------------------------------------------------------------------
+// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+*/
+
+#ifdef RIOT_OS
+#include "xtensa_conf.h"
+
+#define pxCurrentTCB            sched_active_thread
+#define port_xSchedulerRunning  sched_num_threads
+#define port_switch_flag        sched_context_switch_request
+#define port_interruptNesting   irq_interrupt_nesting
+#define vTaskSwitchContext      sched_run
+#define configISR_STACK_SIZE    ISR_STACKSIZE
+
+.extern sched_active_thread
+.extern sched_num_threads
+.extern sched_context_switch_request
+.extern irq_interrupt_nesting
+#endif
+
+#include "xtensa_context.h"
+
+#define TOPOFSTACK_OFFS                 0x00    /* StackType_t *pxTopOfStack */
+#define CP_TOPOFSTACK_OFFS              0x04    /* xMPU_SETTINGS.coproc_area */
+
+/*
+*******************************************************************************
+* Interrupt stack. The size of the interrupt stack is determined by the config
+* parameter "configISR_STACK_SIZE" in FreeRTOSConfig.h
+*******************************************************************************
+*/
+    .data
+    .align      16
+    .global     port_IntStack
+port_IntStack:
+    .space      configISR_STACK_SIZE
+    .global     port_IntStackTop
+port_IntStackTop:
+    .word       0
+
+#ifndef RIOT_OS
+port_switch_flag:
+    .word       0
+#endif
+
+    .text
+    .literal_position
+
+/*
+*******************************************************************************
+* _frxt_setup_switch
+* void _frxt_setup_switch(void);
+*
+* Sets an internal flag indicating that a task switch is required on return
+* from interrupt handling.
+*
+*******************************************************************************
+*/
+    .global     _frxt_setup_switch
+    .type       _frxt_setup_switch,@function
+    .align      4
+_frxt_setup_switch:
+
+    ENTRY(16)
+
+    movi    a2, port_switch_flag
+    movi    a3, 1
+    s32i    a3, a2, 0
+
+    RET(16)
+
+/*
+*******************************************************************************
+*                                            _frxt_int_enter
+*                                       void _frxt_int_enter(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_ENTER function for
+* freeRTOS. Saves the rest of the interrupt context (not already saved).
+* May only be called from assembly code by the 'call0' instruction, with
+* interrupts disabled.
+* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+*******************************************************************************
+*/
+    .globl  _frxt_int_enter
+    .type   _frxt_int_enter,@function
+    .align  4
+_frxt_int_enter:
+
+    /* Save a12-13 in the stack frame as required by _xt_context_save. */
+    s32i    a12, a1, XT_STK_A12
+    s32i    a13, a1, XT_STK_A13
+
+    /* Save return address in a safe place (free a0). */
+    mov     a12, a0
+
+    /* Save the rest of the interrupted context (preserves A12-13). */
+    call0   _xt_context_save
+
+    /*
+    Save interrupted task's SP in TCB only if not nesting.
+    Manage nesting directly rather than call the generic IntEnter()
+    (in windowed ABI we can't call a C function here anyway because PS.EXCM is still set).
+    */
+
+    movi    a2,  port_xSchedulerRunning
+    movi    a3,  port_interruptNesting
+    l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */
+    beqz    a2,  1f                     /* scheduler not running, no tasks */
+    l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */
+    addi    a2,  a2, 1                  /* increment nesting count         */
+    s32i    a2,  a3, 0                  /* save nesting count              */
+    bnei    a2,  1, .Lnested            /* !=0 before incr, so nested      */
+
+    movi    a2,  pxCurrentTCB
+    l32i    a2,  a2, 0                  /* a2 = current TCB                */
+    beqz    a2,  1f
+    s32i    a1,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP */
+    movi    a1,  port_IntStackTop       /* a1 = top of intr stack          */
+
+.Lnested:
+1:
+    mov     a0,  a12                    /* restore return addr and return  */
+    ret
+
+/*
+*******************************************************************************
+*                                            _frxt_int_exit
+*                                       void _frxt_int_exit(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_EXIT function for
+* FreeRTOS. If required, calls vPortYieldFromInt() to perform task context
+* switching, restore the (possibly) new task's context, and return to the
+* exit dispatcher saved in the task's stack frame at XT_STK_EXIT.
+* May only be called from assembly code by the 'call0' instruction. Does not
+* return to caller.
+* See the description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+*******************************************************************************
+*/
+    .globl  _frxt_int_exit
+    .type   _frxt_int_exit,@function
+    .align  4
+_frxt_int_exit:
+
+    movi    a2,  port_xSchedulerRunning
+    movi    a3,  port_interruptNesting
+    rsil    a0,  XCHAL_EXCM_LEVEL       /* lock out interrupts             */
+    l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */
+    beqz    a2,  .Lnoswitch             /* scheduler not running, no tasks */
+    l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */
+    addi    a2,  a2, -1                 /* decrement nesting count         */
+    s32i    a2,  a3, 0                  /* save nesting count              */
+    bnez    a2,  .Lnesting              /* !=0 after decr so still nested  */
+
+    movi    a2,  pxCurrentTCB
+    l32i    a2,  a2, 0                  /* a2 = current TCB                */
+    beqz    a2,  1f                     /* no task ? go to dispatcher      */
+    l32i    a1,  a2, TOPOFSTACK_OFFS    /* SP = pxCurrentTCB->pxTopOfStack */
+
+    movi    a2,  port_switch_flag       /* address of switch flag          */
+    l32i    a3,  a2, 0                  /* a3 = port_switch_flag           */
+    beqz    a3,  .Lnoswitch             /* flag = 0 means no switch reqd   */
+    movi    a3,  0
+    s32i    a3,  a2, 0                  /* zero out the flag for next time */
+
+1:
+    /*
+    Call0 ABI callee-saved regs a12-15 need to be saved before possible preemption.
+    However a12-13 were already saved by _frxt_int_enter().
+    */
+    #ifdef __XTENSA_CALL0_ABI__
+    s32i    a14, a1, XT_STK_A14
+    s32i    a15, a1, XT_STK_A15
+    #endif
+
+    #ifdef __XTENSA_CALL0_ABI__
+    call0   vPortYieldFromInt       /* call dispatch inside the function; never returns */
+    #else
+    call4   vPortYieldFromInt       /* this one returns */
+    call0   _frxt_dispatch          /* tail-call dispatcher */
+    /* Never returns here. */
+    #endif
+
+.Lnoswitch:
+    /*
+    If we came here then about to resume the interrupted task.
+    */
+
+.Lnesting:
+    /*
+    We come here only if there was no context switch, that is if this
+    is a nested interrupt, or the interrupted task was not preempted.
+    In either case there's no need to load the SP.
+    */
+
+    /* Restore full context from interrupt stack frame */
+    call0   _xt_context_restore
+
+    /*
+    Must return via the exit dispatcher corresponding to the entrypoint from which
+    this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt
+    stack frame is deallocated in the exit dispatcher.
+    */
+    l32i    a0,  a1, XT_STK_EXIT
+    ret
+
+/*
+**********************************************************************************************************
+*                                           _frxt_timer_int
+*                                      void _frxt_timer_int(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for FreeRTOS.
+* Called every timer interrupt.
+* Manages the tick timer and calls xPortSysTickHandler() every tick.
+* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance.
+*
+**********************************************************************************************************
+*/
+    .globl  _frxt_timer_int
+    .type   _frxt_timer_int,@function
+    .align  4
+_frxt_timer_int:
+
+    /*
+    Xtensa timers work by comparing a cycle counter with a preset value.  Once the match occurs
+    an interrupt is generated, and the handler has to set a new cycle count into the comparator.
+    To avoid clock drift due to interrupt latency, the new cycle count is computed from the old,
+    not the time the interrupt was serviced. However if a timer interrupt is ever serviced more
+    than one tick late, it is necessary to process multiple ticks until the new cycle count is
+    in the future, otherwise the next timer interrupt would not occur until after the cycle
+    counter had wrapped (2^32 cycles later).
+
+    do {
+        ticks++;
+        old_ccompare = read_ccompare_i();
+        write_ccompare_i( old_ccompare + divisor );
+        service one tick;
+        diff = read_ccount() - old_ccompare;
+    } while ( diff > divisor );
+    */
+
+    ENTRY(16)
+    /* In RIOT-OS the timer is used in a different way and is realized in C functions. */
+    #if 0
+
+.L_xt_timer_int_catchup:
+
+    /* Update the timer comparator for the next tick. */
+    #ifdef XT_CLOCK_FREQ
+    movi    a2, XT_TICK_DIVISOR         /* a2 = comparator increment          */
+    #else
+    movi    a3, _xt_tick_divisor
+    l32i    a2, a3, 0                   /* a2 = comparator increment          */
+    #endif
+    rsr     a3, XT_CCOMPARE             /* a3 = old comparator value          */
+    add     a4, a3, a2                  /* a4 = new comparator value          */
+    wsr     a4, XT_CCOMPARE             /* update comp. and clear interrupt   */
+    esync
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /* Preserve a2 and a3 across C calls. */
+    s32i    a2, sp, 4
+    s32i    a3, sp, 8
+    #endif
+
+    /* Call the FreeRTOS tick handler (see port.c). */
+    #ifdef __XTENSA_CALL0_ABI__
+    call0   xPortSysTickHandler
+    #else
+    call4   xPortSysTickHandler
+    #endif
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /* Restore a2 and a3. */
+    l32i    a2, sp, 4
+    l32i    a3, sp, 8
+    #endif
+
+    /* Check if we need to process more ticks to catch up. */
+    esync                               /* ensure comparator update complete  */
+    rsr     a4, CCOUNT                  /* a4 = cycle count                   */
+    sub     a4, a4, a3                  /* diff = ccount - old comparator     */
+    blt     a2, a4, .L_xt_timer_int_catchup  /* repeat while diff > divisor */
+
+    #endif
+    RET(16)
+
+    /*
+**********************************************************************************************************
+*                                           _frxt_tick_timer_init
+*                                      void _frxt_tick_timer_init(void)
+*
+* Initialize timer and timer interrrupt handler (_xt_tick_divisor_init() has already been been called).
+* Callable from C (obeys ABI conventions on entry).
+*
+**********************************************************************************************************
+*/
+#if 0
+    .globl  _frxt_tick_timer_init
+    .type   _frxt_tick_timer_init,@function
+    .align  4
+_frxt_tick_timer_init:
+
+    ENTRY(16)
+
+    /* Set up the periodic tick timer (assume enough time to complete init). */
+    #ifdef XT_CLOCK_FREQ
+    movi    a3, XT_TICK_DIVISOR
+    #else
+    movi    a2, _xt_tick_divisor
+    l32i    a3, a2, 0
+    #endif
+    rsr     a2, CCOUNT              /* current cycle count */
+    add     a2, a2, a3              /* time of first timer interrupt */
+    wsr     a2, XT_CCOMPARE         /* set the comparator */
+
+    /*
+    Enable the timer interrupt at the device level. Don't write directly
+    to the INTENABLE register because it may be virtualized.
+    */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a2, XT_TIMER_INTEN
+    call0   xt_ints_on
+    #else
+    movi    a6, XT_TIMER_INTEN
+    call4   xt_ints_on
+    #endif
+
+    RET(16)
+#endif
+
+/*
+**********************************************************************************************************
+*                                    DISPATCH THE HIGH READY TASK
+*                                     void _frxt_dispatch(void)
+*
+* Switch context to the highest priority ready task, restore its state and dispatch control to it.
+*
+* This is a common dispatcher that acts as a shared exit path for all the context switch functions
+* including vPortYield() and vPortYieldFromInt(), all of which tail-call this dispatcher
+* (for windowed ABI vPortYieldFromInt() calls it indirectly via _frxt_int_exit() ).
+*
+* The Xtensa port uses different stack frames for solicited and unsolicited task suspension (see
+* comments on stack frames in xtensa_context.h). This function restores the state accordingly.
+* If restoring a task that solicited entry, restores the minimal state and leaves CPENABLE clear.
+* If restoring a task that was preempted, restores all state including the task's CPENABLE.
+*
+* Entry:
+*   pxCurrentTCB  points to the TCB of the task to suspend,
+*   Because it is tail-called without a true function entrypoint, it needs no 'entry' instruction.
+*
+* Exit:
+*   If incoming task called vPortYield() (solicited), this function returns as if from vPortYield().
+*   If incoming task was preempted by an interrupt, this function jumps to exit dispatcher.
+*
+**********************************************************************************************************
+*/
+    .globl  _frxt_dispatch
+    .type   _frxt_dispatch,@function
+    .align  4
+_frxt_dispatch:
+
+    #ifdef __XTENSA_CALL0_ABI__
+    call0   vTaskSwitchContext  // Get next TCB to resume
+    movi    a2, pxCurrentTCB
+    #else
+    movi    a2, pxCurrentTCB
+    call4   vTaskSwitchContext  // Get next TCB to resume
+    #endif
+    l32i    a3,  a2, 0
+    l32i    sp,  a3, TOPOFSTACK_OFFS     /* SP = next_TCB->pxTopOfStack;  */
+    s32i    a3,  a2, 0
+
+    /* Determine the type of stack frame. */
+    l32i    a2,  sp, XT_STK_EXIT        /* exit dispatcher or solicited flag */
+    bnez    a2,  .L_frxt_dispatch_stk
+
+.L_frxt_dispatch_sol:
+
+    /* Solicited stack frame. Restore minimal context and return from vPortYield(). */
+    l32i    a3,  sp, XT_SOL_PS
+    #ifdef __XTENSA_CALL0_ABI__
+    l32i    a12, sp, XT_SOL_A12
+    l32i    a13, sp, XT_SOL_A13
+    l32i    a14, sp, XT_SOL_A14
+    l32i    a15, sp, XT_SOL_A15
+    #endif
+    l32i    a0,  sp, XT_SOL_PC
+    #if XCHAL_CP_NUM > 0
+    /* Ensure wsr.CPENABLE is complete (should be, it was cleared on entry). */
+    rsync
+    #endif
+    /* As soons as PS is restored, interrupts can happen. No need to sync PS. */
+    wsr     a3,  PS
+    #ifdef __XTENSA_CALL0_ABI__
+    addi    sp,  sp, XT_SOL_FRMSZ
+    ret
+    #else
+    retw
+    #endif
+
+.L_frxt_dispatch_stk:
+
+    #if XCHAL_CP_NUM > 0
+    /* Restore CPENABLE from task's co-processor save area. */
+    movi    a3, pxCurrentTCB
+    l32i    a3, a3, 0                   /* a3 = pxCurrentTCB                */
+    #if 0      /* TODO when architecture dependent thread data are possible */
+    l32i    a2, a3, CP_TOPOFSTACK_OFFS  /* StackType_t *pxStack;            */
+    #else
+    addi    a2, a3, -XT_CP_SIZE         /* a2 = cp_state                    */
+    #endif
+    l16ui   a3, a2, XT_CPENABLE         /* CPENABLE = cpenable;             */
+    wsr     a3, CPENABLE
+    #endif
+
+    /* Interrupt stack frame. Restore full context and return to exit dispatcher. */
+    call0   _xt_context_restore
+
+    /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */
+    #ifdef __XTENSA_CALL0_ABI__
+    l32i    a14, sp, XT_STK_A14
+    l32i    a15, sp, XT_STK_A15
+    #endif
+
+    #if XCHAL_CP_NUM > 0
+    /* Ensure wsr.CPENABLE has completed. */
+    rsync
+    #endif
+
+    /*
+    Must return via the exit dispatcher corresponding to the entrypoint from which
+    this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt
+    stack frame is deallocated in the exit dispatcher.
+    */
+    l32i    a0, sp, XT_STK_EXIT
+    ret
+
+
+/*
+**********************************************************************************************************
+*                            PERFORM A SOLICTED CONTEXT SWITCH (from a task)
+*                                        void vPortYield(void)
+*
+* This function saves the minimal state needed for a solicited task suspension, clears CPENABLE,
+* then tail-calls the dispatcher _frxt_dispatch() to perform the actual context switch
+*
+* At Entry:
+*   pxCurrentTCB  points to the TCB of the task to suspend
+*   Callable from C (obeys ABI conventions on entry).
+*
+* Does not return to caller.
+*
+**********************************************************************************************************
+*/
+    .globl  vPortYield
+    .type   vPortYield,@function
+    .align  4
+vPortYield:
+
+    #ifdef __XTENSA_CALL0_ABI__
+    addi    sp,  sp, -XT_SOL_FRMSZ
+    #else
+    entry   sp,  XT_SOL_FRMSZ
+    #endif
+
+    rsr     a2,  PS
+    s32i    a0,  sp, XT_SOL_PC
+    s32i    a2,  sp, XT_SOL_PS
+    #ifdef __XTENSA_CALL0_ABI__
+    s32i    a12, sp, XT_SOL_A12         /* save callee-saved registers      */
+    s32i    a13, sp, XT_SOL_A13
+    s32i    a14, sp, XT_SOL_A14
+    s32i    a15, sp, XT_SOL_A15
+    #else
+    /* Spill register windows. Calling xthal_window_spill() causes extra    */
+    /* spills and reloads, so we will set things up to call the _nw version */
+    /* instead to save cycles.                                              */
+    movi    a6,  ~(PS_WOE_MASK|PS_INTLEVEL_MASK)  /* spills a4-a7 if needed */
+    and     a2,  a2, a6                           /* clear WOE, INTLEVEL    */
+    addi    a2,  a2, XCHAL_EXCM_LEVEL             /* set INTLEVEL           */
+    wsr     a2,  PS
+    rsync
+    call0   xthal_window_spill_nw
+    l32i    a2,  sp, XT_SOL_PS                    /* restore PS             */
+    wsr     a2,  PS
+    #endif
+
+    rsil    a2,  XCHAL_EXCM_LEVEL       /* disable low/med interrupts       */
+
+    #if XCHAL_CP_NUM > 0
+    /* Save coprocessor callee-saved state (if any). At this point CPENABLE */
+    /* should still reflect which CPs were in use (enabled).                */
+    call0   _xt_coproc_savecs
+    #endif
+
+    movi    a2,  pxCurrentTCB
+    movi    a3,  0
+    l32i    a2,  a2, 0                  /* a2 = pxCurrentTCB                */
+    s32i    a3,  sp, XT_SOL_EXIT        /* 0 to flag as solicited frame     */
+    s32i    sp,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP  */
+
+    #if XCHAL_CP_NUM > 0
+    /* Clear CPENABLE, also in task's co-processor state save area. */
+    #if 0      /* TODO when architecture dependent thread data are possible */
+    l32i    a2,  a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state      */
+    #else
+    addi    a2,  a2, -XT_CP_SIZE        /* a2 = cp_state                    */
+    #endif
+    movi    a3,  0
+    wsr     a3,  CPENABLE
+    beqz    a2,  1f
+    s16i    a3,  a2, XT_CPENABLE        /* clear saved cpenable             */
+1:
+    #endif
+
+    /* Tail-call dispatcher. */
+    call0   _frxt_dispatch
+    /* Never reaches here. */
+
+
+/*
+**********************************************************************************************************
+*                         PERFORM AN UNSOLICITED CONTEXT SWITCH (from an interrupt)
+*                                        void vPortYieldFromInt(void)
+*
+* This calls the context switch hook (removed), saves and clears CPENABLE, then tail-calls the dispatcher
+* _frxt_dispatch() to perform the actual context switch.
+*
+* At Entry:
+*   Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCB->pxTopOfStack.
+*   pxCurrentTCB  points to the TCB of the task to suspend,
+*   Callable from C (obeys ABI conventions on entry).
+*
+* At Exit:
+*   Windowed ABI defers the actual context switch until the stack is unwound to interrupt entry.
+*   Call0 ABI tail-calls the dispatcher directly (no need to unwind) so does not return to caller.
+*
+**********************************************************************************************************
+*/
+    .globl  vPortYieldFromInt
+    .type   vPortYieldFromInt,@function
+    .align  4
+vPortYieldFromInt:
+
+    ENTRY(16)
+
+    #if XCHAL_CP_NUM > 0
+    /* Save CPENABLE in task's co-processor save area, and clear CPENABLE.  */
+    movi    a3, pxCurrentTCB
+    l32i    a3, a3, 0                   /* a3 = pxCurrentTCB                */
+    #if 0      /* TODO when architecture dependent thread data are possible */
+    l32i    a2, a3, CP_TOPOFSTACK_OFFS
+    #else
+    addi    a2, a3, -XT_CP_SIZE         /* a2 = cp_state                    */
+    #endif
+
+    rsr     a3, CPENABLE
+    s16i    a3, a2, XT_CPENABLE         /* cp_state->cpenable = CPENABLE;   */
+    movi    a3, 0
+    wsr     a3, CPENABLE                /* disable all co-processors        */
+    #endif
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /* Tail-call dispatcher. */
+    call0   _frxt_dispatch
+    /* Never reaches here. */
+    #else
+    RET(16)
+    #endif
+
+/*
+**********************************************************************************************************
+*                                        _frxt_task_coproc_state
+*                                   void _frxt_task_coproc_state(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_CP_STATE function for FreeRTOS.
+*
+* May only be called when a task is running, not within an interrupt handler (returns 0 in that case).
+* May only be called from assembly code by the 'call0' instruction. Does NOT obey ABI conventions.
+* Returns in A15 a pointer to the base of the co-processor state save area for the current task.
+* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+**********************************************************************************************************
+*/
+#if XCHAL_CP_NUM > 0
+
+    .globl  _frxt_task_coproc_state
+    .type   _frxt_task_coproc_state,@function
+    .align  4
+_frxt_task_coproc_state:
+
+    movi    a15, port_xSchedulerRunning /* if (port_xSchedulerRunning              */
+    l32i    a15, a15, 0
+    beqz    a15, 1f
+    movi    a15, port_interruptNesting  /* && port_interruptNesting == 0           */
+    l32i    a15, a15, 0
+    bnez    a15, 1f
+    movi    a15, pxCurrentTCB
+    l32i    a15, a15, 0                 /* && pxCurrentTCB != 0) {                 */
+    beqz    a15, 2f
+    #if 0             /* TODO when architecture dependent thread data are possible */
+    l32i    a15, a15, CP_TOPOFSTACK_OFFS
+    #else
+    addi    a15, a15, -XT_CP_SIZE       /* cp_state                                */
+    #endif
+    ret
+
+1:  movi    a15, 0
+2:  ret
+
+#endif /* XCHAL_CP_NUM > 0 */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_api.h b/cpu/esp32/vendor/xtensa/xtensa_api.h
new file mode 100644
index 0000000000000000000000000000000000000000..025b3d1676ce0f29066291ac9da5cf3dd032b7ab
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_api.h
@@ -0,0 +1,127 @@
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+/******************************************************************************
+  Xtensa-specific API for RTOS ports.
+******************************************************************************/
+
+#ifndef XTENSA_API_H
+#define XTENSA_API_H
+
+#include <xtensa/hal.h>
+
+#include "xtensa_context.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Typedef for C-callable interrupt handler function */
+typedef void (*xt_handler)(void *);
+
+/* Typedef for C-callable exception handler function */
+typedef void (*xt_exc_handler)(XtExcFrame *);
+
+
+/*
+-------------------------------------------------------------------------------
+  Call this function to set a handler for the specified exception.
+
+    n        - Exception number (type)
+    f        - Handler function address, NULL to uninstall handler.
+
+  The handler will be passed a pointer to the exception frame, which is created
+  on the stack of the thread that caused the exception.
+
+  If the handler returns, the thread context will be restored and the faulting
+  instruction will be retried. Any values in the exception frame that are
+  modified by the handler will be restored as part of the context. For details
+  of the exception frame structure see xtensa_context.h.
+-------------------------------------------------------------------------------
+*/
+extern xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f);
+
+
+/*
+-------------------------------------------------------------------------------
+  Call this function to set a handler for the specified interrupt.
+
+    n        - Interrupt number.
+    f        - Handler function address, NULL to uninstall handler.
+    arg      - Argument to be passed to handler.
+-------------------------------------------------------------------------------
+*/
+extern xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg);
+
+
+/*
+-------------------------------------------------------------------------------
+  Call this function to enable the specified interrupts.
+
+    mask     - Bit mask of interrupts to be enabled.
+
+  Returns the previous state of the interrupt enables.
+-------------------------------------------------------------------------------
+*/
+extern unsigned int xt_ints_on(unsigned int mask);
+
+
+/*
+-------------------------------------------------------------------------------
+  Call this function to disable the specified interrupts.
+
+    mask     - Bit mask of interrupts to be disabled.
+
+  Returns the previous state of the interrupt enables.
+-------------------------------------------------------------------------------
+*/
+extern unsigned int xt_ints_off(unsigned int mask);
+
+
+/*
+-------------------------------------------------------------------------------
+  Call this function to set the specified (s/w) interrupt.
+-------------------------------------------------------------------------------
+*/
+static inline void xt_set_intset(unsigned int arg)
+{
+    xthal_set_intset(arg);
+}
+
+
+/*
+-------------------------------------------------------------------------------
+  Call this function to clear the specified (s/w or edge-triggered)
+  interrupt.
+-------------------------------------------------------------------------------
+*/
+static inline void xt_set_intclear(unsigned int arg)
+{
+    xthal_set_intclear(arg);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* XTENSA_API_H */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_context.S b/cpu/esp32/vendor/xtensa/xtensa_context.S
new file mode 100644
index 0000000000000000000000000000000000000000..3a56258eed7136e777220c176488f167fd09fa31
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_context.S
@@ -0,0 +1,624 @@
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------------------------------------------------------------------
+
+        XTENSA CONTEXT SAVE AND RESTORE ROUTINES
+
+Low-level Call0 functions for handling generic context save and restore of
+registers not specifically addressed by the interrupt vectors and handlers.
+Those registers (not handled by these functions) are PC, PS, A0, A1 (SP).
+Except for the calls to RTOS functions, this code is generic to Xtensa.
+
+Note that in Call0 ABI, interrupt handlers are expected to preserve the callee-
+save regs (A12-A15), which is always the case if the handlers are coded in C.
+However A12, A13 are made available as scratch registers for interrupt dispatch
+code, so are presumed saved anyway, and are always restored even in Call0 ABI.
+Only A14, A15 are truly handled as callee-save regs.
+
+Because Xtensa is a configurable architecture, this port supports all user
+generated configurations (except restrictions stated in the release notes).
+This is accomplished by conditional compilation using macros and functions
+defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
+Only the processor state included in your configuration is saved and restored,
+including any processor state added by user configuration options or TIE.
+
+*******************************************************************************/
+
+/*  Warn nicely if this file gets named with a lowercase .s instead of .S:  */
+#define NOERROR #
+NOERROR: .error "C preprocessor needed for this file: make sure its filename\
+ ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option."
+
+#include "xtensa_rtos.h"
+#include "xtensa_context.h"
+
+#ifdef XT_USE_OVLY
+#include <xtensa/overlay_os_asm.h>
+#endif
+
+    .text
+    .literal_position
+
+/*******************************************************************************
+
+_xt_context_save
+
+    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
+
+Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the
+interrupt stack frame defined in xtensa_rtos.h.
+Its counterpart is _xt_context_restore (which also restores A12, A13).
+
+Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame.
+This function preserves A12 & A13 in order to provide the caller with 2 scratch
+regs that need not be saved over the call to this function. The choice of which
+2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw,
+to avoid moving data more than necessary. Caller can assign regs accordingly.
+
+Entry Conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+    Original A12, A13 have already been saved in the interrupt stack frame.
+    Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the
+    point of interruption.
+    If windowed ABI, PS.EXCM = 1 (exceptions disabled).
+
+Exit conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+    A12, A13 as at entry (preserved).
+    If windowed ABI, PS.EXCM = 1 (exceptions disabled).
+
+*******************************************************************************/
+
+    .global _xt_context_save
+    .type   _xt_context_save,@function
+    .align  4
+_xt_context_save:
+
+    s32i    a2,  sp, XT_STK_A2
+    s32i    a3,  sp, XT_STK_A3
+    s32i    a4,  sp, XT_STK_A4
+    s32i    a5,  sp, XT_STK_A5
+    s32i    a6,  sp, XT_STK_A6
+    s32i    a7,  sp, XT_STK_A7
+    s32i    a8,  sp, XT_STK_A8
+    s32i    a9,  sp, XT_STK_A9
+    s32i    a10, sp, XT_STK_A10
+    s32i    a11, sp, XT_STK_A11
+
+    /*
+    Call0 ABI callee-saved regs a12-15 do not need to be saved here.
+    a12-13 are the caller's responsibility so it can use them as scratch.
+    So only need to save a14-a15 here for Windowed ABI (not Call0).
+    */
+    #ifndef __XTENSA_CALL0_ABI__
+    s32i    a14, sp, XT_STK_A14
+    s32i    a15, sp, XT_STK_A15
+    #endif
+
+    rsr     a3,  SAR
+    s32i    a3,  sp, XT_STK_SAR
+
+    #if XCHAL_HAVE_LOOPS
+    rsr     a3,  LBEG
+    s32i    a3,  sp, XT_STK_LBEG
+    rsr     a3,  LEND
+    s32i    a3,  sp, XT_STK_LEND
+    rsr     a3,  LCOUNT
+    s32i    a3,  sp, XT_STK_LCOUNT
+    #endif
+
+    #if XT_USE_SWPRI
+    /* Save virtual priority mask */
+    movi    a3,  _xt_vpri_mask
+    l32i    a3,  a3, 0
+    s32i    a3,  sp, XT_STK_VPRI
+    #endif
+
+    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
+    mov     a9,  a0                     /* preserve ret addr */
+    #endif
+
+    #ifndef __XTENSA_CALL0_ABI__
+    /*
+    To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15.
+    Need to save a9,12,13 temporarily (in frame temps) and recover originals.
+    Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow
+    and underflow exceptions disabled (assured by PS.EXCM == 1).
+    */
+    s32i    a12, sp, XT_STK_TMP0        /* temp. save stuff in stack frame */
+    s32i    a13, sp, XT_STK_TMP1
+    s32i    a9,  sp, XT_STK_TMP2
+
+    /*
+    Save the overlay state if we are supporting overlays. Since we just saved
+    three registers, we can conveniently use them here. Note that as of now,
+    overlays only work for windowed calling ABI.
+    */
+    #ifdef XT_USE_OVLY
+    l32i    a9,  sp, XT_STK_PC          /* recover saved PC */
+    _xt_overlay_get_state    a9, a12, a13
+    s32i    a9,  sp, XT_STK_OVLY        /* save overlay state */
+    #endif
+
+    l32i    a12, sp, XT_STK_A12         /* recover original a9,12,13 */
+    l32i    a13, sp, XT_STK_A13
+    l32i    a9,  sp, XT_STK_A9
+    addi    sp,  sp, XT_STK_FRMSZ       /* restore the interruptee's SP */
+    call0   xthal_window_spill_nw       /* preserves only a4,5,8,9,12,13 */
+    addi    sp,  sp, -XT_STK_FRMSZ
+    l32i    a12, sp, XT_STK_TMP0        /* recover stuff from stack frame */
+    l32i    a13, sp, XT_STK_TMP1
+    l32i    a9,  sp, XT_STK_TMP2
+    #endif
+
+    #if XCHAL_EXTRA_SA_SIZE > 0
+    /*
+    NOTE: Normally the xthal_save_extra_nw macro only affects address
+    registers a2-a5. It is theoretically possible for Xtensa processor
+    designers to write TIE that causes more address registers to be
+    affected, but it is generally unlikely. If that ever happens,
+    more registers need to be saved/restored around this macro invocation.
+    Here we assume a9,12,13 are preserved.
+    Future Xtensa tools releases might limit the regs that can be affected.
+    */
+    addi    a2,  sp, XT_STK_EXTRA       /* where to save it */
+    # if XCHAL_EXTRA_SA_ALIGN > 16
+    movi    a3, -XCHAL_EXTRA_SA_ALIGN
+    and     a2, a2, a3                  /* align dynamically >16 bytes */
+    # endif
+    call0   xthal_save_extra_nw         /* destroys a0,2,3,4,5 */
+    #endif
+
+    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
+    mov     a0, a9                      /* retrieve ret addr */
+    #endif
+
+    ret
+
+/*******************************************************************************
+
+_xt_context_restore
+
+    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
+
+Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0
+ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt
+stack frame defined in xtensa_rtos.h .
+Its counterpart is _xt_context_save (whose caller saved A12, A13).
+
+Caller is responsible to restore PC, PS, A0, A1 (SP).
+
+Entry Conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+
+Exit conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+    Other processor state except PC, PS, A0, A1 (SP), is as at the point
+    of interruption.
+
+*******************************************************************************/
+
+    .global _xt_context_restore
+    .type   _xt_context_restore,@function
+    .align  4
+_xt_context_restore:
+
+    #if XCHAL_EXTRA_SA_SIZE > 0
+    /*
+    NOTE: Normally the xthal_restore_extra_nw macro only affects address
+    registers a2-a5. It is theoretically possible for Xtensa processor
+    designers to write TIE that causes more address registers to be
+    affected, but it is generally unlikely. If that ever happens,
+    more registers need to be saved/restored around this macro invocation.
+    Here we only assume a13 is preserved.
+    Future Xtensa tools releases might limit the regs that can be affected.
+    */
+    mov     a13, a0                     /* preserve ret addr */
+    addi    a2,  sp, XT_STK_EXTRA       /* where to find it */
+    # if XCHAL_EXTRA_SA_ALIGN > 16
+    movi    a3, -XCHAL_EXTRA_SA_ALIGN
+    and     a2, a2, a3                  /* align dynamically >16 bytes */
+    # endif
+    call0   xthal_restore_extra_nw      /* destroys a0,2,3,4,5 */
+    mov     a0,  a13                    /* retrieve ret addr */
+    #endif
+
+    #if XCHAL_HAVE_LOOPS
+    l32i    a2,  sp, XT_STK_LBEG
+    l32i    a3,  sp, XT_STK_LEND
+    wsr     a2,  LBEG
+    l32i    a2,  sp, XT_STK_LCOUNT
+    wsr     a3,  LEND
+    wsr     a2,  LCOUNT
+    #endif
+
+    #ifdef XT_USE_OVLY
+    /*
+    If we are using overlays, this is a good spot to check if we need
+    to restore an overlay for the incoming task. Here we have a bunch
+    of registers to spare. Note that this step is going to use a few
+    bytes of storage below SP (SP-20 to SP-32) if an overlay is going
+    to be restored.
+    */
+    l32i    a2,  sp, XT_STK_PC          /* retrieve PC */
+    l32i    a3,  sp, XT_STK_PS          /* retrieve PS */
+    l32i    a4,  sp, XT_STK_OVLY        /* retrieve overlay state */
+    l32i    a5,  sp, XT_STK_A1          /* retrieve stack ptr */
+    _xt_overlay_check_map    a2, a3, a4, a5, a6
+    s32i    a2,  sp, XT_STK_PC          /* save updated PC */
+    s32i    a3,  sp, XT_STK_PS          /* save updated PS */
+    #endif
+
+    #ifdef XT_USE_SWPRI
+    /* Restore virtual interrupt priority and interrupt enable */
+    movi    a3,  _xt_intdata
+    l32i    a4,  a3, 0                  /* a4 = _xt_intenable */
+    l32i    a5,  sp, XT_STK_VPRI        /* a5 = saved _xt_vpri_mask */
+    and     a4,  a4, a5
+    wsr     a4,  INTENABLE              /* update INTENABLE */
+    s32i    a5,  a3, 4                  /* restore _xt_vpri_mask */
+    #endif
+
+    l32i    a3,  sp, XT_STK_SAR
+    l32i    a2,  sp, XT_STK_A2
+    wsr     a3,  SAR
+    l32i    a3,  sp, XT_STK_A3
+    l32i    a4,  sp, XT_STK_A4
+    l32i    a5,  sp, XT_STK_A5
+    l32i    a6,  sp, XT_STK_A6
+    l32i    a7,  sp, XT_STK_A7
+    l32i    a8,  sp, XT_STK_A8
+    l32i    a9,  sp, XT_STK_A9
+    l32i    a10, sp, XT_STK_A10
+    l32i    a11, sp, XT_STK_A11
+
+    /*
+    Call0 ABI callee-saved regs a12-15 do not need to be restored here.
+    However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(),
+    so need to be restored anyway, despite being callee-saved in Call0.
+    */
+    l32i    a12, sp, XT_STK_A12
+    l32i    a13, sp, XT_STK_A13
+    #ifndef __XTENSA_CALL0_ABI__
+    l32i    a14, sp, XT_STK_A14
+    l32i    a15, sp, XT_STK_A15
+    #endif
+
+    ret
+
+
+/*******************************************************************************
+
+_xt_coproc_init
+
+Initializes global co-processor management data, setting all co-processors
+to "unowned". Leaves CPENABLE as it found it (does NOT clear it).
+
+Called during initialization of the RTOS, before any threads run.
+
+This may be called from normal Xtensa single-threaded application code which
+might use co-processors. The Xtensa run-time initialization enables all
+co-processors. They must remain enabled here, else a co-processor exception
+might occur outside of a thread, which the exception handler doesn't expect.
+
+Entry Conditions:
+    Xtensa single-threaded run-time environment is in effect.
+    No thread is yet running.
+
+Exit conditions:
+    None.
+
+Obeys ABI conventions per prototype:
+    void _xt_coproc_init(void)
+
+*******************************************************************************/
+
+#if XCHAL_CP_NUM > 0
+
+    .global _xt_coproc_init
+    .type   _xt_coproc_init,@function
+    .align  4
+_xt_coproc_init:
+    ENTRY0
+
+    /* Initialize thread co-processor ownerships to 0 (unowned). */
+    movi    a2, _xt_coproc_owner_sa         /* a2 = base of owner array */
+    addi    a3, a2, XCHAL_CP_MAX << 2       /* a3 = top+1 of owner array */
+    movi    a4, 0                           /* a4 = 0 (unowned) */
+1:  s32i    a4, a2, 0
+    addi    a2, a2, 4
+    bltu    a2, a3, 1b
+
+    RET0
+
+#endif
+
+
+/*******************************************************************************
+
+_xt_coproc_release
+
+Releases any and all co-processors owned by a given thread. The thread is
+identified by it's co-processor state save area defined in xtensa_context.h .
+
+Must be called before a thread's co-proc save area is deleted to avoid
+memory corruption when the exception handler tries to save the state.
+May be called when a thread terminates or completes but does not delete
+the co-proc save area, to avoid the exception handler having to save the
+thread's co-proc state before another thread can use it (optimization).
+
+Entry Conditions:
+    A2  = Pointer to base of co-processor state save area.
+
+Exit conditions:
+    None.
+
+Obeys ABI conventions per prototype:
+    void _xt_coproc_release(void * coproc_sa_base)
+
+*******************************************************************************/
+
+#if XCHAL_CP_NUM > 0
+
+    .global _xt_coproc_release
+    .type   _xt_coproc_release,@function
+    .align  4
+_xt_coproc_release:
+    ENTRY0                                  /* a2 = base of save area */
+
+    movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */
+    addi    a4, a3, XCHAL_CP_MAX << 2       /* a4 = top+1 of owner array */
+    movi    a5, 0                           /* a5 = 0 (unowned) */
+
+    rsil    a6, XCHAL_EXCM_LEVEL            /* lock interrupts */
+
+1:  l32i    a7, a3, 0                       /* a7 = owner at a3 */
+    bne     a2, a7, 2f                      /* if (coproc_sa_base == owner) */
+    s32i    a5, a3, 0                       /*   owner = unowned */
+2:  addi    a3, a3, 1<<2                    /* a3 = next entry in owner array */
+    bltu    a3, a4, 1b                      /* repeat until end of array */
+
+3:  wsr     a6, PS                          /* restore interrupts */
+
+    RET0
+
+#endif
+
+
+/*******************************************************************************
+_xt_coproc_savecs
+
+If there is a current thread and it has a coprocessor state save area, then
+save all callee-saved state into this area. This function is called from the
+solicited context switch handler. It calls a system-specific function to get
+the coprocessor save area base address.
+
+Entry conditions:
+    - The thread being switched out is still the current thread.
+    - CPENABLE state reflects which coprocessors are active.
+    - Registers have been saved/spilled already.
+
+Exit conditions:
+    - All necessary CP callee-saved state has been saved.
+    - Registers a2-a7, a13-a15 have been trashed.
+
+Must be called from assembly code only, using CALL0.
+*******************************************************************************/
+#if XCHAL_CP_NUM > 0
+
+    .extern     _xt_coproc_sa_offset   /* external reference */
+
+    .global     _xt_coproc_savecs
+    .type       _xt_coproc_savecs,@function
+    .align      4
+_xt_coproc_savecs:
+
+    /* At entry, CPENABLE should be showing which CPs are enabled. */
+
+    rsr     a2, CPENABLE                /* a2 = which CPs are enabled      */
+    beqz    a2, .Ldone                  /* quick exit if none              */
+    mov     a14, a0                     /* save return address             */
+    call0   XT_RTOS_CP_STATE            /* get address of CP save area     */
+    mov     a0, a14                     /* restore return address          */
+    beqz    a15, .Ldone                 /* if none then nothing to do      */
+    s16i    a2, a15, XT_CP_CS_ST        /* save mask of CPs being stored   */
+    movi    a13, _xt_coproc_sa_offset   /* array of CP save offsets        */
+    l32i    a15, a15, XT_CP_ASA         /* a15 = base of aligned save area */
+
+#if XCHAL_CP0_SA_SIZE
+    bbci.l  a2, 0, 2f                   /* CP 0 not enabled                */
+    l32i    a14, a13, 0                 /* a14 = _xt_coproc_sa_offset[0]   */
+    add     a3, a14, a15                /* a3 = save area for CP 0         */
+    xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP1_SA_SIZE
+    bbci.l  a2, 1, 2f                   /* CP 1 not enabled                */
+    l32i    a14, a13, 4                 /* a14 = _xt_coproc_sa_offset[1]   */
+    add     a3, a14, a15                /* a3 = save area for CP 1         */
+    xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP2_SA_SIZE
+    bbci.l  a2, 2, 2f
+    l32i    a14, a13, 8
+    add     a3, a14, a15
+    xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP3_SA_SIZE
+    bbci.l  a2, 3, 2f
+    l32i    a14, a13, 12
+    add     a3, a14, a15
+    xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP4_SA_SIZE
+    bbci.l  a2, 4, 2f
+    l32i    a14, a13, 16
+    add     a3, a14, a15
+    xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP5_SA_SIZE
+    bbci.l  a2, 5, 2f
+    l32i    a14, a13, 20
+    add     a3, a14, a15
+    xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP6_SA_SIZE
+    bbci.l  a2, 6, 2f
+    l32i    a14, a13, 24
+    add     a3, a14, a15
+    xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP7_SA_SIZE
+    bbci.l  a2, 7, 2f
+    l32i    a14, a13, 28
+    add     a3, a14, a15
+    xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+.Ldone:
+    ret
+#endif
+
+
+/*******************************************************************************
+_xt_coproc_restorecs
+
+Restore any callee-saved coprocessor state for the incoming thread.
+This function is called from coprocessor exception handling, when giving
+ownership to a thread that solicited a context switch earlier. It calls a
+system-specific function to get the coprocessor save area base address.
+
+Entry conditions:
+    - The incoming thread is set as the current thread.
+    - CPENABLE is set up correctly for all required coprocessors.
+    - a2 = mask of coprocessors to be restored.
+
+Exit conditions:
+    - All necessary CP callee-saved state has been restored.
+    - CPENABLE - unchanged.
+    - Registers a2-a7, a13-a15 have been trashed.
+
+Must be called from assembly code only, using CALL0.
+*******************************************************************************/
+#if XCHAL_CP_NUM > 0
+
+    .global     _xt_coproc_restorecs
+    .type       _xt_coproc_restorecs,@function
+    .align      4
+_xt_coproc_restorecs:
+
+    mov     a14, a0                     /* save return address             */
+    call0   XT_RTOS_CP_STATE            /* get address of CP save area     */
+    mov     a0, a14                     /* restore return address          */
+    beqz    a15, .Ldone2                /* if none then nothing to do      */
+    l16ui   a3, a15, XT_CP_CS_ST        /* a3 = which CPs have been saved  */
+    xor     a3, a3, a2                  /* clear the ones being restored   */
+    s32i    a3, a15, XT_CP_CS_ST        /* update saved CP mask            */
+    movi    a13, _xt_coproc_sa_offset   /* array of CP save offsets        */
+    l32i    a15, a15, XT_CP_ASA         /* a15 = base of aligned save area */
+
+#if XCHAL_CP0_SA_SIZE
+    bbci.l  a2, 0, 2f                   /* CP 0 not enabled                */
+    l32i    a14, a13, 0                 /* a14 = _xt_coproc_sa_offset[0]   */
+    add     a3, a14, a15                /* a3 = save area for CP 0         */
+    xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP1_SA_SIZE
+    bbci.l  a2, 1, 2f                   /* CP 1 not enabled                */
+    l32i    a14, a13, 4                 /* a14 = _xt_coproc_sa_offset[1]   */
+    add     a3, a14, a15                /* a3 = save area for CP 1         */
+    xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP2_SA_SIZE
+    bbci.l  a2, 2, 2f
+    l32i    a14, a13, 8
+    add     a3, a14, a15
+    xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP3_SA_SIZE
+    bbci.l  a2, 3, 2f
+    l32i    a14, a13, 12
+    add     a3, a14, a15
+    xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP4_SA_SIZE
+    bbci.l  a2, 4, 2f
+    l32i    a14, a13, 16
+    add     a3, a14, a15
+    xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP5_SA_SIZE
+    bbci.l  a2, 5, 2f
+    l32i    a14, a13, 20
+    add     a3, a14, a15
+    xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP6_SA_SIZE
+    bbci.l  a2, 6, 2f
+    l32i    a14, a13, 24
+    add     a3, a14, a15
+    xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP7_SA_SIZE
+    bbci.l  a2, 7, 2f
+    l32i    a14, a13, 28
+    add     a3, a14, a15
+    xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+.Ldone2:
+    ret
+
+#endif
diff --git a/cpu/esp32/vendor/xtensa/xtensa_context.h b/cpu/esp32/vendor/xtensa/xtensa_context.h
new file mode 100644
index 0000000000000000000000000000000000000000..e331d62482845c554b4df5063b23c064c5ee9233
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_context.h
@@ -0,0 +1,355 @@
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------------------------------------------------------------------
+
+        XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
+
+This header contains definitions and macros for use primarily by Xtensa
+RTOS assembly coded source files. It includes and uses the Xtensa hardware
+abstraction layer (HAL) to deal with config specifics. It may also be
+included in C source files.
+
+!! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !!
+
+NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
+
+*******************************************************************************/
+
+#ifndef XTENSA_CONTEXT_H
+#define XTENSA_CONTEXT_H
+
+#ifdef __ASSEMBLER__
+#include    <xtensa/coreasm.h>
+#endif
+
+#include    <xtensa/config/tie.h>
+#include    <xtensa/corebits.h>
+#include    <xtensa/config/system.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Align a value up to nearest n-byte boundary, where n is a power of 2. */
+#define ALIGNUP(n, val) (((val) + (n)-1) & -(n))
+
+
+/*
+-------------------------------------------------------------------------------
+  Macros that help define structures for both C and assembler.
+-------------------------------------------------------------------------------
+*/
+#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
+
+#define STRUCT_BEGIN            .pushsection .text; .struct 0
+#define STRUCT_FIELD(ctype,size,asname,name)    asname: .space  size
+#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space  (size)*(n)
+#define STRUCT_END(sname)       sname##Size:; .popsection
+
+#else
+
+#define STRUCT_BEGIN            typedef struct {
+#define STRUCT_FIELD(ctype,size,asname,name)    ctype   name;
+#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype   name[n];
+#define STRUCT_END(sname)       } sname;
+
+#endif //_ASMLANGUAGE || __ASSEMBLER__
+
+
+/*
+-------------------------------------------------------------------------------
+  INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
+
+  A stack frame of this structure is allocated for any interrupt or exception.
+  It goes on the current stack. If the RTOS has a system stack for handling
+  interrupts, every thread stack must allow space for just one interrupt stack
+  frame, then nested interrupt stack frames go on the system stack.
+
+  The frame includes basic registers (explicit) and "extra" registers introduced
+  by user TIE or the use of the MAC16 option in the user's Xtensa config.
+  The frame size is minimized by omitting regs not applicable to user's config.
+
+  For Windowed ABI, this stack frame includes the interruptee's base save area,
+  another base save area to manage gcc nested functions, and a little temporary
+  space to help manage the spilling of the register windows.
+-------------------------------------------------------------------------------
+*/
+
+STRUCT_BEGIN
+STRUCT_FIELD (long, 4, XT_STK_EXIT,     exit) /* exit point for dispatch */
+STRUCT_FIELD (long, 4, XT_STK_PC,       pc)   /* return PC */
+STRUCT_FIELD (long, 4, XT_STK_PS,       ps)   /* return PS */
+STRUCT_FIELD (long, 4, XT_STK_A0,       a0)
+STRUCT_FIELD (long, 4, XT_STK_A1,       a1)   /* stack pointer before interrupt */
+STRUCT_FIELD (long, 4, XT_STK_A2,       a2)
+STRUCT_FIELD (long, 4, XT_STK_A3,       a3)
+STRUCT_FIELD (long, 4, XT_STK_A4,       a4)
+STRUCT_FIELD (long, 4, XT_STK_A5,       a5)
+STRUCT_FIELD (long, 4, XT_STK_A6,       a6)
+STRUCT_FIELD (long, 4, XT_STK_A7,       a7)
+STRUCT_FIELD (long, 4, XT_STK_A8,       a8)
+STRUCT_FIELD (long, 4, XT_STK_A9,       a9)
+STRUCT_FIELD (long, 4, XT_STK_A10,      a10)
+STRUCT_FIELD (long, 4, XT_STK_A11,      a11)
+STRUCT_FIELD (long, 4, XT_STK_A12,      a12)
+STRUCT_FIELD (long, 4, XT_STK_A13,      a13)
+STRUCT_FIELD (long, 4, XT_STK_A14,      a14)
+STRUCT_FIELD (long, 4, XT_STK_A15,      a15)
+STRUCT_FIELD (long, 4, XT_STK_SAR,      sar)
+STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
+STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
+#if XCHAL_HAVE_LOOPS
+STRUCT_FIELD (long, 4, XT_STK_LBEG,   lbeg)
+STRUCT_FIELD (long, 4, XT_STK_LEND,   lend)
+STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
+#endif
+#ifndef __XTENSA_CALL0_ABI__
+/* Temporary space for saving stuff during window spill */
+STRUCT_FIELD (long, 4, XT_STK_TMP0,   tmp0)
+STRUCT_FIELD (long, 4, XT_STK_TMP1,   tmp1)
+STRUCT_FIELD (long, 4, XT_STK_TMP2,   tmp2)
+#endif
+#ifdef XT_USE_SWPRI
+/* Storage for virtual priority mask */
+STRUCT_FIELD (long, 4, XT_STK_VPRI,   vpri)
+#endif
+#ifdef XT_USE_OVLY
+/* Storage for overlay state */
+STRUCT_FIELD (long, 4, XT_STK_OVLY,   ovly)
+#endif
+STRUCT_END(XtExcFrame)
+
+#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
+#define XT_STK_NEXT1      XtExcFrameSize
+#else
+#define XT_STK_NEXT1      sizeof(XtExcFrame)
+#endif
+
+/* Allocate extra storage if needed */
+#if XCHAL_EXTRA_SA_SIZE != 0
+
+#if XCHAL_EXTRA_SA_ALIGN <= 16
+#define XT_STK_EXTRA            ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
+#else
+/* If need more alignment than stack, add space for dynamic alignment */
+#define XT_STK_EXTRA            (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN)
+#endif
+#define XT_STK_NEXT2            (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
+
+#else
+
+#define XT_STK_NEXT2            XT_STK_NEXT1
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+  This is the frame size. Add space for 4 registers (interruptee's base save
+  area) and some space for gcc nested functions if any.
+-------------------------------------------------------------------------------
+*/
+#define XT_STK_FRMSZ            (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20)
+
+
+/*
+-------------------------------------------------------------------------------
+  SOLICITED STACK FRAME FOR A THREAD
+
+  A stack frame of this structure is allocated whenever a thread enters the
+  RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
+  It goes on the current thread's stack.
+
+  The solicited frame only includes registers that are required to be preserved
+  by the callee according to the compiler's ABI conventions, some space to save
+  the return address for returning to the caller, and the caller's PS register.
+
+  For Windowed ABI, this stack frame includes the caller's base save area.
+
+  Note on XT_SOL_EXIT field:
+      It is necessary to distinguish a solicited from an interrupt stack frame.
+      This field corresponds to XT_STK_EXIT in the interrupt stack frame and is
+      always at the same offset (0). It can be written with a code (usually 0)
+      to distinguish a solicted frame from an interrupt frame. An RTOS port may
+      opt to ignore this field if it has another way of distinguishing frames.
+-------------------------------------------------------------------------------
+*/
+
+STRUCT_BEGIN
+#ifdef __XTENSA_CALL0_ABI__
+STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
+STRUCT_FIELD (long, 4, XT_SOL_PC,   pc)
+STRUCT_FIELD (long, 4, XT_SOL_PS,   ps)
+STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
+STRUCT_FIELD (long, 4, XT_SOL_A12,  a12)    /* should be on 16-byte alignment */
+STRUCT_FIELD (long, 4, XT_SOL_A13,  a13)
+STRUCT_FIELD (long, 4, XT_SOL_A14,  a14)
+STRUCT_FIELD (long, 4, XT_SOL_A15,  a15)
+#else
+STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
+STRUCT_FIELD (long, 4, XT_SOL_PC,   pc)
+STRUCT_FIELD (long, 4, XT_SOL_PS,   ps)
+STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
+STRUCT_FIELD (long, 4, XT_SOL_A0,   a0)    /* should be on 16-byte alignment */
+STRUCT_FIELD (long, 4, XT_SOL_A1,   a1)
+STRUCT_FIELD (long, 4, XT_SOL_A2,   a2)
+STRUCT_FIELD (long, 4, XT_SOL_A3,   a3)
+#endif
+STRUCT_END(XtSolFrame)
+
+/* Size of solicited stack frame */
+#define XT_SOL_FRMSZ            ALIGNUP(0x10, XtSolFrameSize)
+
+
+/*
+-------------------------------------------------------------------------------
+  CO-PROCESSOR STATE SAVE AREA FOR A THREAD
+
+  The RTOS must provide an area per thread to save the state of co-processors
+  when that thread does not have control. Co-processors are context-switched
+  lazily (on demand) only when a new thread uses a co-processor instruction,
+  otherwise a thread retains ownership of the co-processor even when it loses
+  control of the processor. An Xtensa co-processor exception is triggered when
+  any co-processor instruction is executed by a thread that is not the owner,
+  and the context switch of that co-processor is then peformed by the handler.
+  Ownership represents which thread's state is currently in the co-processor.
+
+  Co-processors may not be used by interrupt or exception handlers. If an
+  co-processor instruction is executed by an interrupt or exception handler,
+  the co-processor exception handler will trigger a kernel panic and freeze.
+  This restriction is introduced to reduce the overhead of saving and restoring
+  co-processor state (which can be quite large) and in particular remove that
+  overhead from interrupt handlers.
+
+  The co-processor state save area may be in any convenient per-thread location
+  such as in the thread control block or above the thread stack area. It need
+  not be in the interrupt stack frame since interrupts don't use co-processors.
+
+  Along with the save area for each co-processor, two bitmasks with flags per
+  co-processor (laid out as in the CPENABLE reg) help manage context-switching
+  co-processors as efficiently as possible:
+
+  XT_CPENABLE
+    The contents of a non-running thread's CPENABLE register.
+    It represents the co-processors owned (and whose state is still needed)
+    by the thread. When a thread is preempted, its CPENABLE is saved here.
+    When a thread solicits a context-swtich, its CPENABLE is cleared - the
+    compiler has saved the (caller-saved) co-proc state if it needs to.
+    When a non-running thread loses ownership of a CP, its bit is cleared.
+    When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg.
+    Avoids co-processor exceptions when no change of ownership is needed.
+
+  XT_CPSTORED
+    A bitmask with the same layout as CPENABLE, a bit per co-processor.
+    Indicates whether the state of each co-processor is saved in the state
+    save area. When a thread enters the kernel, only the state of co-procs
+    still enabled in CPENABLE is saved. When the co-processor exception
+    handler assigns ownership of a co-processor to a thread, it restores
+    the saved state only if this bit is set, and clears this bit.
+
+  XT_CP_CS_ST
+    A bitmask with the same layout as CPENABLE, a bit per co-processor.
+    Indicates whether callee-saved state is saved in the state save area.
+    Callee-saved state is saved by itself on a solicited context switch,
+    and restored when needed by the coprocessor exception handler.
+    Unsolicited switches will cause the entire coprocessor to be saved
+    when necessary.
+
+  XT_CP_ASA
+    Pointer to the aligned save area.  Allows it to be aligned more than
+    the overall save area (which might only be stack-aligned or TCB-aligned).
+    Especially relevant for Xtensa cores configured with a very large data
+    path that requires alignment greater than 16 bytes (ABI stack alignment).
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_CP_NUM > 0
+
+/*  Offsets of each coprocessor save area within the 'aligned save area':  */
+#define XT_CP0_SA   0
+#define XT_CP1_SA   ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE)
+#define XT_CP2_SA   ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE)
+#define XT_CP3_SA   ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE)
+#define XT_CP4_SA   ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE)
+#define XT_CP5_SA   ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE)
+#define XT_CP6_SA   ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE)
+#define XT_CP7_SA   ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE)
+#define XT_CP_SA_SIZE   ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE)
+
+/*  Offsets within the overall save area:  */
+#define XT_CPENABLE 0   /* (2 bytes) coprocessors active for this thread */
+#define XT_CPSTORED 2   /* (2 bytes) coprocessors saved for this thread */
+#define XT_CP_CS_ST 4   /* (2 bytes) coprocessor callee-saved regs stored for this thread */
+#define XT_CP_ASA   8   /* (4 bytes) ptr to aligned save area */
+/*  Overall size allows for dynamic alignment:  */
+#define XT_CP_SIZE  (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)
+#else
+#define XT_CP_SIZE  0
+#endif
+
+
+/*
+-------------------------------------------------------------------------------
+  MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
+
+  Convenient where the frame size requirements are the same for both ABIs.
+    ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
+    ENTRY0,    RET0    are for frameless functions (no locals, no calls).
+
+  where size = size of stack frame in bytes (must be >0 and aligned to 16).
+  For framed functions the frame is created and the return address saved at
+  base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
+  For frameless functions, there is no frame and return address remains in a0.
+  Note: Because CPP macros expand to a single line, macros requiring multi-line
+  expansions are implemented as assembler macros.
+-------------------------------------------------------------------------------
+*/
+
+#ifdef __ASSEMBLER__
+#ifdef __XTENSA_CALL0_ABI__
+  /* Call0 */
+  #define ENTRY(sz)     entry1  sz
+    .macro  entry1 size=0x10
+    addi    sp, sp, -\size
+    s32i    a0, sp, 0
+    .endm
+  #define ENTRY0
+  #define RET(sz)       ret1    sz
+    .macro  ret1 size=0x10
+    l32i    a0, sp, 0
+    addi    sp, sp, \size
+    ret
+    .endm
+  #define RET0          ret
+#else
+  /* Windowed */
+  #define ENTRY(sz)     entry   sp, sz
+  #define ENTRY0        entry   sp, 0x10
+  #define RET(sz)       retw
+  #define RET0          retw
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* XTENSA_CONTEXT_H */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_intr.c b/cpu/esp32/vendor/xtensa/xtensa_intr.c
new file mode 100644
index 0000000000000000000000000000000000000000..f33b8d36f00bacff412e5ed62e07e2285144f8f6
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_intr.c
@@ -0,0 +1,141 @@
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+/******************************************************************************
+  Xtensa-specific interrupt and exception functions for RTOS ports.
+  Also see xtensa_intr_asm.S.
+******************************************************************************/
+
+#ifndef SDK_INT_HANDLING /* not needed in SDK task handling version of RIOT */
+
+#include <stdlib.h>
+
+#include <xtensa/config/core.h>
+
+#include "xtensa_api.h"
+
+
+#if XCHAL_HAVE_EXCEPTIONS
+
+/* Handler table is in xtensa_intr_asm.S */
+
+extern xt_exc_handler _xt_exception_table[XCHAL_EXCCAUSE_NUM];
+
+
+/*
+  Default handler for unhandled exceptions.
+*/
+void xt_unhandled_exception(XtExcFrame *frame)
+{
+    exit(-1);
+}
+
+
+/*
+  This function registers a handler for the specified exception.
+  The function returns the address of the previous handler.
+  On error, it returns 0.
+*/
+xt_exc_handler xt_set_exception_handler(int n, xt_exc_handler f)
+{
+    xt_exc_handler old;
+
+    if( n < 0 || n >= XCHAL_EXCCAUSE_NUM )
+        return 0;       /* invalid exception number */
+
+    old = _xt_exception_table[n];
+
+    if (f) {
+        _xt_exception_table[n] = f;
+    }
+    else {
+        _xt_exception_table[n] = &xt_unhandled_exception;
+    }
+
+    return ((old == &xt_unhandled_exception) ? 0 : old);
+}
+
+#endif
+
+#if XCHAL_HAVE_INTERRUPTS
+
+/* Handler table is in xtensa_intr_asm.S */
+
+typedef struct xt_handler_table_entry {
+    void * handler;
+    void * arg;
+} xt_handler_table_entry;
+
+extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS];
+
+
+/*
+  Default handler for unhandled interrupts.
+*/
+void xt_unhandled_interrupt(void * arg)
+{
+    exit(-1);
+}
+
+
+/*
+  This function registers a handler for the specified interrupt. The "arg"
+  parameter specifies the argument to be passed to the handler when it is
+  invoked. The function returns the address of the previous handler.
+  On error, it returns 0.
+*/
+xt_handler xt_set_interrupt_handler(int n, xt_handler f, void * arg)
+{
+    xt_handler_table_entry * entry;
+    xt_handler               old;
+
+    if( n < 0 || n >= XCHAL_NUM_INTERRUPTS )
+        return 0;       /* invalid interrupt number */
+    if( Xthal_intlevel[n] > XCHAL_EXCM_LEVEL )
+        return 0;       /* priority level too high to safely handle in C */
+
+    #ifdef SDK_USED
+    // for compatibility reasons with SDK, we use _xtos_interrupt_table
+    // in reverse order
+    entry = _xt_interrupt_table + (XCHAL_NUM_INTERRUPTS - n);
+    #else
+    entry = _xt_interrupt_table + n;
+    #endif
+    old   = entry->handler;
+
+    if (f) {
+        entry->handler = f;
+        entry->arg     = arg;
+    }
+    else {
+        entry->handler = &xt_unhandled_interrupt;
+        entry->arg     = (void*)n;
+    }
+
+    return ((old == &xt_unhandled_interrupt) ? 0 : old);
+}
+
+
+#endif /* XCHAL_HAVE_INTERRUPTS */
+
+#endif /* SDK_INT_HANDLING */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_intr_asm.S b/cpu/esp32/vendor/xtensa/xtensa_intr_asm.S
new file mode 100644
index 0000000000000000000000000000000000000000..5c89b558dc3db727306be05e72f0f4b95d957c42
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_intr_asm.S
@@ -0,0 +1,187 @@
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+******************************************************************************/
+
+/******************************************************************************
+  Xtensa interrupt handling data and assembly routines.
+  Also see xtensa_intr.c and xtensa_vectors.S.
+******************************************************************************/
+
+#ifndef SDK_INT_HANDLING /* not needed in SDK version of RIOT */
+
+#include <xtensa/hal.h>
+#include <xtensa/config/core.h>
+
+#include "xtensa_context.h"
+
+#if XCHAL_HAVE_INTERRUPTS
+
+    .literal_position
+
+/*
+-------------------------------------------------------------------------------
+  INTENABLE virtualization information.
+-------------------------------------------------------------------------------
+*/
+    .data
+    .global _xt_intdata
+    .align  8
+_xt_intdata:
+    .global _xt_intenable
+    .type   _xt_intenable,@object
+    .size   _xt_intenable,4
+    .global _xt_vpri_mask
+    .type   _xt_vpri_mask,@object
+    .size   _xt_vpri_mask,4
+
+_xt_intenable:     .word   0             /* Virtual INTENABLE     */
+_xt_vpri_mask:     .word   0xFFFFFFFF    /* Virtual priority mask */
+
+
+/*
+-------------------------------------------------------------------------------
+  Table of C-callable interrupt handlers for each interrupt. Note that not all
+  slots can be filled, because interrupts at level > EXCM_LEVEL will not be
+  dispatched to a C handler by default.
+-------------------------------------------------------------------------------
+*/
+/*
+    in SDK we use _xtos_interrupt_table_ which is provided as symbol
+    _xt_interrupt_table_ by ld script
+*/
+#ifdef SDK_NOT_USED
+    .data
+    .global _xt_interrupt_table
+    .align  8
+
+_xt_interrupt_table:
+
+    .set    i, 0
+    .rept   XCHAL_NUM_INTERRUPTS
+    .word   xt_unhandled_interrupt      /* handler address               */
+    .word   i                           /* handler arg (default: intnum) */
+    .set    i, i+1
+    .endr
+#endif
+
+#endif /* XCHAL_HAVE_INTERRUPTS */
+
+
+#if XCHAL_HAVE_EXCEPTIONS
+
+/*
+-------------------------------------------------------------------------------
+  Table of C-callable exception handlers for each exception. Note that not all
+  slots will be active, because some exceptions (e.g. coprocessor exceptions)
+  are always handled by the OS and cannot be hooked by user handlers.
+-------------------------------------------------------------------------------
+*/
+
+    .data
+    .global _xt_exception_table
+    .align  4
+
+_xt_exception_table:
+    .rept   XCHAL_EXCCAUSE_NUM
+    .word   xt_unhandled_exception    /* handler address */
+    .endr
+
+#endif
+
+
+/*
+-------------------------------------------------------------------------------
+  unsigned int xt_ints_on ( unsigned int mask )
+
+  Enables a set of interrupts. Does not simply set INTENABLE directly, but
+  computes it as a function of the current virtual priority.
+  Can be called from interrupt handlers.
+-------------------------------------------------------------------------------
+*/
+
+    .text
+    .align  4
+    .global xt_ints_on
+    .type   xt_ints_on,@function
+
+xt_ints_on:
+
+    ENTRY0
+#if XCHAL_HAVE_INTERRUPTS
+    movi    a3, 0
+    movi    a4, _xt_intdata
+    xsr     a3, INTENABLE        /* Disables all interrupts   */
+    rsync
+    l32i    a3, a4, 0            /* a3 = _xt_intenable        */
+    l32i    a6, a4, 4            /* a6 = _xt_vpri_mask        */
+    or      a5, a3, a2           /* a5 = _xt_intenable | mask */
+    s32i    a5, a4, 0            /* _xt_intenable |= mask     */
+    and     a5, a5, a6           /* a5 = _xt_intenable & _xt_vpri_mask */
+    wsr     a5, INTENABLE        /* Reenable interrupts       */
+    mov     a2, a3               /* Previous mask             */
+#else
+    movi    a2, 0                /* Return zero */
+#endif
+    RET0
+
+    .size   xt_ints_on, . - xt_ints_on
+
+
+/*
+-------------------------------------------------------------------------------
+  unsigned int xt_ints_off ( unsigned int mask )
+
+  Disables a set of interrupts. Does not simply set INTENABLE directly,
+  but computes it as a function of the current virtual priority.
+  Can be called from interrupt handlers.
+-------------------------------------------------------------------------------
+*/
+
+    .text
+    .align  4
+    .global xt_ints_off
+    .type   xt_ints_off,@function
+
+xt_ints_off:
+
+    ENTRY0
+#if XCHAL_HAVE_INTERRUPTS
+    movi    a3, 0
+    movi    a4, _xt_intdata
+    xsr     a3, INTENABLE        /* Disables all interrupts    */
+    rsync
+    l32i    a3, a4, 0            /* a3 = _xt_intenable         */
+    l32i    a6, a4, 4            /* a6 = _xt_vpri_mask         */
+    or      a5, a3, a2           /* a5 = _xt_intenable | mask  */
+    xor     a5, a5, a2           /* a5 = _xt_intenable & ~mask */
+    s32i    a5, a4, 0            /* _xt_intenable &= ~mask     */
+    and     a5, a5, a6           /* a5 = _xt_intenable & _xt_vpri_mask */
+    wsr     a5, INTENABLE        /* Reenable interrupts        */
+    mov     a2, a3               /* Previous mask              */
+#else
+    movi    a2, 0                /* return zero */
+#endif
+    RET0
+
+    .size   xt_ints_off, . - xt_ints_off
+
+#endif /* SDK_INT_HANDLING */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_rtos.h b/cpu/esp32/vendor/xtensa/xtensa_rtos.h
new file mode 100644
index 0000000000000000000000000000000000000000..7d27df21c8464a2943dbf1a9b7a2b3fe1ede3201
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_rtos.h
@@ -0,0 +1,247 @@
+/*******************************************************************************
+// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------------------------------------------------------------------
+
+        RTOS-SPECIFIC INFORMATION FOR XTENSA RTOS ASSEMBLER SOURCES
+                            (FreeRTOS Port)
+
+This header is the primary glue between generic Xtensa RTOS support
+sources and a specific RTOS port for Xtensa.  It contains definitions
+and macros for use primarily by Xtensa assembly coded source files.
+
+Macros in this header map callouts from generic Xtensa files to specific
+RTOS functions. It may also be included in C source files.
+
+Xtensa RTOS ports support all RTOS-compatible configurations of the Xtensa
+architecture, using the Xtensa hardware abstraction layer (HAL) to deal
+with configuration specifics.
+
+Should be included by all Xtensa generic and RTOS port-specific sources.
+
+*******************************************************************************/
+
+#ifndef XTENSA_RTOS_H
+#define XTENSA_RTOS_H
+
+#ifdef __ASSEMBLER__
+#include    <xtensa/coreasm.h>
+#else
+#include    <xtensa/config/core.h>
+#endif
+
+#include    <xtensa/corebits.h>
+#include    <xtensa/config/system.h>
+#ifndef RIOT_OS
+#include    <xtensa/simcall.h>
+#endif
+#define XT_BOARD 1
+
+/*
+Include any RTOS specific definitions that are needed by this header.
+*/
+#ifndef RIOT_OS
+#include    <FreeRTOSConfig.h>
+#endif
+
+/*
+Convert FreeRTOSConfig definitions to XTENSA definitions.
+However these can still be overridden from the command line.
+*/
+
+#ifndef XT_SIMULATOR
+  #if configXT_SIMULATOR
+    #define XT_SIMULATOR             1  /* Simulator mode */
+  #endif
+#endif
+
+#ifndef XT_BOARD
+  #if configXT_BOARD
+    #define XT_BOARD                 1  /* Board mode */
+  #endif
+#endif
+
+#ifndef XT_TIMER_INDEX
+  #if defined configXT_TIMER_INDEX
+    #define XT_TIMER_INDEX           configXT_TIMER_INDEX  /* Index of hardware timer to be used */
+  #endif
+#endif
+
+#ifndef XT_INTEXC_HOOKS
+  #if configXT_INTEXC_HOOKS
+    #define XT_INTEXC_HOOKS          1  /* Enables exception hooks */
+  #endif
+#endif
+
+#if (!XT_SIMULATOR) && (!XT_BOARD)
+  #error Either XT_SIMULATOR or XT_BOARD must be defined.
+#endif
+
+
+/*
+Name of RTOS (for messages).
+*/
+#define XT_RTOS_NAME    RIOT-OS
+
+/*
+Check some Xtensa configuration requirements and report error if not met.
+Error messages can be customize to the RTOS port.
+*/
+
+#if !XCHAL_HAVE_XEA2
+#error "RIOT-OS/Xtensa requires XEA2 (exception architecture 2)."
+#endif
+
+
+/*******************************************************************************
+
+RTOS CALLOUT MACROS MAPPED TO RTOS PORT-SPECIFIC FUNCTIONS.
+
+Define callout macros used in generic Xtensa code to interact with the RTOS.
+The macros are simply the function names for use in calls from assembler code.
+Some of these functions may call back to generic functions in xtensa_context.h .
+
+*******************************************************************************/
+
+/*
+Inform RTOS of entry into an interrupt handler that will affect it.
+Allows RTOS to manage switch to any system stack and count nesting level.
+Called after minimal context has been saved, with interrupts disabled.
+RTOS port can call0 _xt_context_save to save the rest of the context.
+May only be called from assembly code by the 'call0' instruction.
+*/
+// void XT_RTOS_INT_ENTER(void)
+#define XT_RTOS_INT_ENTER   _frxt_int_enter
+
+/*
+Inform RTOS of completion of an interrupt handler, and give control to
+RTOS to perform thread/task scheduling, switch back from any system stack
+and restore the context, and return to the exit dispatcher saved in the
+stack frame at XT_STK_EXIT. RTOS port can call0 _xt_context_restore
+to save the context saved in XT_RTOS_INT_ENTER via _xt_context_save,
+leaving only a minimal part of the context to be restored by the exit
+dispatcher. This function does not return to the place it was called from.
+May only be called from assembly code by the 'call0' instruction.
+*/
+// void XT_RTOS_INT_EXIT(void)
+#define XT_RTOS_INT_EXIT    _frxt_int_exit
+
+/*
+Inform RTOS of the occurrence of a tick timer interrupt.
+If RTOS has no tick timer, leave XT_RTOS_TIMER_INT undefined.
+May be coded in or called from C or assembly, per ABI conventions.
+RTOS may optionally define XT_TICK_PER_SEC in its own way (eg. macro).
+*/
+// void XT_RTOS_TIMER_INT(void)
+#define XT_RTOS_TIMER_INT   _frxt_timer_int
+#ifndef RIOT_OS
+    #define XT_TICK_PER_SEC     configTICK_RATE_HZ
+#endif
+
+/*
+Return in a15 the base address of the co-processor state save area for the
+thread that triggered a co-processor exception, or 0 if no thread was running.
+The state save area is structured as defined in xtensa_context.h and has size
+XT_CP_SIZE. Co-processor instructions should only be used in thread code, never
+in interrupt handlers or the RTOS kernel. May only be called from assembly code
+and by the 'call0' instruction. A result of 0 indicates an unrecoverable error.
+The implementation may use only a2-4, a15 (all other regs must be preserved).
+*/
+// void* XT_RTOS_CP_STATE(void)
+#define XT_RTOS_CP_STATE    _frxt_task_coproc_state
+
+
+/*******************************************************************************
+
+HOOKS TO DYNAMICALLY INSTALL INTERRUPT AND EXCEPTION HANDLERS PER LEVEL.
+
+This Xtensa RTOS port provides hooks for dynamically installing exception
+and interrupt handlers to facilitate automated testing where each test
+case can install its own handler for user exceptions and each interrupt
+priority (level). This consists of an array of function pointers indexed
+by interrupt priority, with index 0 being the user exception handler hook.
+Each entry in the array is initially 0, and may be replaced by a function
+pointer of type XT_INTEXC_HOOK. A handler may be uninstalled by installing 0.
+
+The handler for low and medium priority obeys ABI conventions so may be coded
+in C. For the exception handler, the cause is the contents of the EXCCAUSE
+reg, and the result is -1 if handled, else the cause (still needs handling).
+For interrupt handlers, the cause is a mask of pending enabled interrupts at
+that level, and the result is the same mask with the bits for the handled
+interrupts cleared (those not cleared still need handling). This allows a test
+case to either pre-handle or override the default handling for the exception
+or interrupt level (see xtensa_vectors.S).
+
+High priority handlers (including NMI) must be coded in assembly, are always
+called by 'call0' regardless of ABI, must preserve all registers except a0,
+and must not use or modify the interrupted stack. The hook argument 'cause'
+is not passed and the result is ignored, so as not to burden the caller with
+saving and restoring a2 (it assumes only one interrupt per level - see the
+discussion in high priority interrupts in xtensa_vectors.S). The handler
+therefore should be coded to prototype 'void h(void)' even though it plugs
+into an array of handlers of prototype 'unsigned h(unsigned)'.
+
+To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'.
+
+*******************************************************************************/
+
+#define XT_INTEXC_HOOK_NUM  (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI)
+
+#ifndef __ASSEMBLER__
+typedef unsigned (*XT_INTEXC_HOOK)(unsigned cause);
+extern  volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
+#endif
+
+
+/*******************************************************************************
+
+CONVENIENCE INCLUSIONS.
+
+Ensures RTOS specific files need only include this one Xtensa-generic header.
+These headers are included last so they can use the RTOS definitions above.
+
+*******************************************************************************/
+
+#include    "xtensa_context.h"
+
+#ifdef XT_RTOS_TIMER_INT
+#include    "xtensa_timer.h"
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/*******************************************************************************
+
+Xtensa Port Version.
+
+*******************************************************************************/
+
+#define XTENSA_PORT_VERSION             1.5
+#define XTENSA_PORT_VERSION_STRING      "1.5"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* XTENSA_RTOS_H */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_timer.h b/cpu/esp32/vendor/xtensa/xtensa_timer.h
new file mode 100644
index 0000000000000000000000000000000000000000..28141a49d1ab03e7239dde3bfcb050ec3624fabf
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_timer.h
@@ -0,0 +1,170 @@
+/*******************************************************************************
+// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------------------------------------------------------------------
+
+        XTENSA INFORMATION FOR RTOS TICK TIMER AND CLOCK FREQUENCY
+
+This header contains definitions and macros for use primarily by Xtensa
+RTOS assembly coded source files. It includes and uses the Xtensa hardware
+abstraction layer (HAL) to deal with config specifics. It may also be
+included in C source files.
+
+User may edit to modify timer selection and to specify clock frequency and
+tick duration to match timer interrupt to the real-time tick duration.
+
+If the RTOS has no timer interrupt, then there is no tick timer and the
+clock frequency is irrelevant, so all of these macros are left undefined
+and the Xtensa core configuration need not have a timer.
+
+*******************************************************************************/
+
+#ifndef XTENSA_TIMER_H
+#define XTENSA_TIMER_H
+
+#ifdef __ASSEMBLER__
+#include    <xtensa/coreasm.h>
+#endif
+
+#include    <xtensa/corebits.h>
+#include    <xtensa/config/system.h>
+
+#ifndef RIOT_OS
+#include    "xtensa_rtos.h"     /* in case this wasn't included directly */
+#include    <FreeRTOSConfig.h>
+#endif /* ifndef RIOT_OS */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+Select timer to use for periodic tick, and determine its interrupt number
+and priority. User may specify a timer by defining XT_TIMER_INDEX with -D,
+in which case its validity is checked (it must exist in this core and must
+not be on a high priority interrupt - an error will be reported in invalid).
+Otherwise select the first low or medium priority interrupt timer available.
+*/
+#if XCHAL_NUM_TIMERS == 0
+
+  #error "This Xtensa configuration is unsupported, it has no timers."
+
+#else
+
+#ifndef XT_TIMER_INDEX
+  #if XCHAL_TIMER3_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+    #if XCHAL_INT_LEVEL(XCHAL_TIMER3_INTERRUPT) <= XCHAL_EXCM_LEVEL
+      #undef  XT_TIMER_INDEX
+      #define XT_TIMER_INDEX    3
+    #endif
+  #endif
+  #if XCHAL_TIMER2_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+    #if XCHAL_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
+      #undef  XT_TIMER_INDEX
+      #define XT_TIMER_INDEX    2
+    #endif
+  #endif
+  #if XCHAL_TIMER1_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+    #if XCHAL_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
+      #undef  XT_TIMER_INDEX
+      #define XT_TIMER_INDEX    1
+    #endif
+  #endif
+  #if XCHAL_TIMER0_INTERRUPT != XTHAL_TIMER_UNCONFIGURED
+    #if XCHAL_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
+      #undef  XT_TIMER_INDEX
+      #define XT_TIMER_INDEX    0
+    #endif
+  #endif
+#endif
+#ifndef XT_TIMER_INDEX
+  #error "There is no suitable timer in this Xtensa configuration."
+#endif
+
+#define XT_CCOMPARE             (CCOMPARE + XT_TIMER_INDEX)
+#define XT_TIMER_INTNUM         XCHAL_TIMER_INTERRUPT(XT_TIMER_INDEX)
+#define XT_TIMER_INTPRI         XCHAL_INT_LEVEL(XT_TIMER_INTNUM)
+#define XT_TIMER_INTEN          (1 << XT_TIMER_INTNUM)
+
+#if XT_TIMER_INTNUM == XTHAL_TIMER_UNCONFIGURED
+  #error "The timer selected by XT_TIMER_INDEX does not exist in this core."
+#elif XT_TIMER_INTPRI > XCHAL_EXCM_LEVEL
+  #error "The timer interrupt cannot be high priority (use medium or low)."
+#endif
+
+#endif /* XCHAL_NUM_TIMERS */
+
+#ifndef RIOT_OS
+/*
+Set processor clock frequency, used to determine clock divisor for timer tick.
+User should BE SURE TO ADJUST THIS for the Xtensa platform being used.
+If using a supported board via the board-independent API defined in xtbsp.h,
+this may be left undefined and frequency and tick divisor will be computed
+and cached during run-time initialization.
+
+NOTE ON SIMULATOR:
+Under the Xtensa instruction set simulator, the frequency can only be estimated
+because it depends on the speed of the host and the version of the simulator.
+Also because it runs much slower than hardware, it is not possible to achieve
+real-time performance for most applications under the simulator. A frequency
+too low does not allow enough time between timer interrupts, starving threads.
+To obtain a more convenient but non-real-time tick duration on the simulator,
+compile with xt-xcc option "-DXT_SIMULATOR".
+Adjust this frequency to taste (it's not real-time anyway!).
+*/
+#if defined(XT_SIMULATOR) && !defined(XT_CLOCK_FREQ)
+#define XT_CLOCK_FREQ       configCPU_CLOCK_HZ
+#endif
+
+#if !defined(XT_CLOCK_FREQ) && !defined(XT_BOARD)
+  #error "XT_CLOCK_FREQ must be defined for the target platform."
+#endif
+
+/*
+Default number of timer "ticks" per second (default 100 for 10ms tick).
+RTOS may define this in its own way (if applicable) in xtensa_rtos.h.
+User may redefine this to an optimal value for the application, either by
+editing this here or in xtensa_rtos.h, or compiling with xt-xcc option
+"-DXT_TICK_PER_SEC=<value>" where <value> is a suitable number.
+*/
+
+#ifndef XT_TICK_PER_SEC
+#define XT_TICK_PER_SEC    configTICK_RATE_HZ        /* 10 ms tick = 100 ticks per second */
+#endif
+
+/*
+Derivation of clock divisor for timer tick and interrupt (one per tick).
+*/
+#ifdef XT_CLOCK_FREQ
+#define XT_TICK_DIVISOR     (XT_CLOCK_FREQ / XT_TICK_PER_SEC)
+#endif
+#endif /* ifndef RIOT_OS */
+
+#ifndef __ASSEMBLER__
+extern unsigned _xt_tick_divisor;
+extern void     _xt_tick_divisor_init(void);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* XTENSA_TIMER_H */
diff --git a/cpu/esp32/vendor/xtensa/xtensa_vectors.S b/cpu/esp32/vendor/xtensa/xtensa_vectors.S
new file mode 100644
index 0000000000000000000000000000000000000000..39ea5b00e021013417801a041779dbf08c163559
--- /dev/null
+++ b/cpu/esp32/vendor/xtensa/xtensa_vectors.S
@@ -0,0 +1,1945 @@
+/*******************************************************************************
+Copyright (c) 2006-2015 Cadence Design Systems Inc.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------------------------------------------------------------------
+
+        XTENSA VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS
+
+  Xtensa low level exception and interrupt vectors and handlers for an RTOS.
+
+  Interrupt handlers and user exception handlers support interaction with
+  the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and
+  after user's specific interrupt handlers. These macros are defined in
+  xtensa_<rtos>.h to call suitable functions in a specific RTOS.
+
+  Users can install application-specific interrupt handlers for low and
+  medium level interrupts, by calling xt_set_interrupt_handler(). These
+  handlers can be written in C, and must obey C calling convention. The
+  handler table is indexed by the interrupt number. Each handler may be
+  provided with an argument.
+
+  Note that the system timer interrupt is handled specially, and is
+  dispatched to the RTOS-specific handler. This timer cannot be hooked
+  by application code.
+
+  Optional hooks are also provided to install a handler per level at
+  run-time, made available by compiling this source file with
+  '-DXT_INTEXC_HOOKS' (useful for automated testing).
+
+!!  This file is a template that usually needs to be modified to handle       !!
+!!  application specific interrupts. Search USER_EDIT for helpful comments    !!
+!!  on where to insert handlers and how to write them.                        !!
+
+  Users can also install application-specific exception handlers in the
+  same way, by calling xt_set_exception_handler(). One handler slot is
+  provided for each exception type. Note that some exceptions are handled
+  by the porting layer itself, and cannot be taken over by application
+  code in this manner. These are the alloca, syscall, and coprocessor
+  exceptions.
+
+  The exception handlers can be written in C, and must follow C calling
+  convention. Each handler is passed a pointer to an exception frame as
+  its single argument. The exception frame is created on the stack, and
+  holds the saved context of the thread that took the exception. If the
+  handler returns, the context will be restored and the instruction that
+  caused the exception will be retried. If the handler makes any changes
+  to the saved state in the exception frame, the changes will be applied
+  when restoring the context.
+
+  Because Xtensa is a configurable architecture, this port supports all user
+  generated configurations (except restrictions stated in the release notes).
+  This is accomplished by conditional compilation using macros and functions
+  defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
+  Only the relevant parts of this file will be included in your RTOS build.
+  For example, this file provides interrupt vector templates for all types and
+  all priority levels, but only the ones in your configuration are built.
+
+  NOTES on the use of 'call0' for long jumps instead of 'j':
+   1. This file should be assembled with the -mlongcalls option to xt-xcc.
+   2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
+      a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
+      distance from the call to the destination. The linker then relaxes
+      it back to 'call0 dest' if it determines that dest is within range.
+      This allows more flexibility in locating code without the performance
+      overhead of the 'l32r' literal data load in cases where the destination
+      is in range of 'call0'. There is an additional benefit in that 'call0'
+      has a longer range than 'j' due to the target being word-aligned, so
+      the 'l32r' sequence is less likely needed.
+   3. The use of 'call0' with -mlongcalls requires that register a0 not be
+      live at the time of the call, which is always the case for a function
+      call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
+   4. This use of 'call0' is independent of the C function call ABI.
+
+*******************************************************************************/
+
+#include "xtensa_context.h"
+
+#ifndef SDK_INT_HANDLING
+
+#include "xtensa_rtos.h"
+
+/* Enable stack backtrace across exception/interrupt - see below */
+#define XT_DEBUG_BACKTRACE    1
+
+
+/*
+--------------------------------------------------------------------------------
+  Defines used to access _xtos_interrupt_table.
+--------------------------------------------------------------------------------
+*/
+#define XIE_HANDLER     0
+#define XIE_ARG         4
+#define XIE_SIZE        8
+
+/*
+--------------------------------------------------------------------------------
+  Macro extract_msb - return the input with only the highest bit set.
+
+  Input  : "ain"  - Input value, clobbered.
+  Output : "aout" - Output value, has only one bit set, MSB of "ain".
+  The two arguments must be different AR registers.
+--------------------------------------------------------------------------------
+*/
+
+    .macro  extract_msb     aout ain
+1:
+    addi    \aout, \ain, -1         /* aout = ain - 1        */
+    and     \ain, \ain, \aout       /* ain  = ain & aout     */
+    bnez    \ain, 1b                /* repeat until ain == 0 */
+    addi    \aout, \aout, 1         /* return aout + 1       */
+    .endm
+
+/*
+--------------------------------------------------------------------------------
+  Macro dispatch_c_isr - dispatch interrupts to user ISRs.
+  This will dispatch to user handlers (if any) that are registered in the
+  XTOS dispatch table (_xtos_interrupt_table). These handlers would have
+  been registered by calling _xtos_set_interrupt_handler(). There is one
+  exception - the timer interrupt used by the OS will not be dispatched
+  to a user handler - this must be handled by the caller of this macro.
+
+  Level triggered and software interrupts are automatically deasserted by
+  this code.
+
+  ASSUMPTIONS:
+    -- PS.INTLEVEL is set to "level" at entry
+    -- PS.EXCM = 0, C calling enabled
+
+  NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
+
+  NOTE: This macro will use registers a0 and a2-a6. The arguments are:
+    level -- interrupt level
+    mask  -- interrupt bitmask for this level
+--------------------------------------------------------------------------------
+*/
+
+    .macro  dispatch_c_isr    level  mask
+
+    /* Get mask of pending, enabled interrupts at this level into a2. */
+
+.L_xt_user_int_&level&:
+    rsr     a2, INTENABLE
+    rsr     a3, INTERRUPT
+    movi    a4, \mask
+    and     a2, a2, a3
+    and     a2, a2, a4
+    beqz    a2, 9f                          /* nothing to do */
+
+    /* This bit of code provides a nice debug backtrace in the debugger.
+       It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
+       if you want to save the cycles.
+    */
+    #if XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    rsr     a0, EPC_1 + \level - 1          /* return address */
+    movi    a4, 0xC0000000                  /* constant with top 2 bits set (call size) */
+    or      a0, a0, a4                      /* set top 2 bits */
+    addx2   a0, a4, a0                      /* clear top bit -- simulating call4 size   */
+    #endif
+    #endif
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a4, _xt_intexc_hooks
+    l32i    a4, a4, \level << 2
+    beqz    a4, 2f
+    #ifdef __XTENSA_CALL0_ABI__
+    callx0  a4
+    beqz    a2, 9f
+    #else
+    mov     a6, a2
+    callx4  a4
+    beqz    a6, 9f
+    mov     a2, a6
+    #endif
+2:
+    #endif
+
+    /* Now look up in the dispatch table and call user ISR if any. */
+    /* If multiple bits are set then MSB has highest priority.     */
+
+    extract_msb  a4, a2                     /* a4 = MSB of a2, a2 trashed */
+
+    #ifdef XT_USE_SWPRI
+    /* Enable all interrupts at this level that are numerically higher
+       than the one we just selected, since they are treated as higher
+       priority.
+    */
+    movi    a3, \mask                       /* a3 = all interrupts at this level */
+    add     a2, a4, a4                      /* a2 = a4 << 1 */
+    addi    a2, a2, -1                      /* a2 = mask of 1's <= a4 bit */
+    and     a2, a2, a3                      /* a2 = mask of all bits <= a4 at this level */
+    movi    a3, _xt_intdata
+    l32i    a6, a3, 4                       /* a6 = _xt_vpri_mask */
+    neg     a2, a2
+    addi    a2, a2, -1                      /* a2 = mask to apply */
+    and     a5, a6, a2                      /* mask off all bits <= a4 bit */
+    s32i    a5, a3, 4                       /* update _xt_vpri_mask */
+    rsr     a3, INTENABLE
+    and     a3, a3, a2                      /* mask off all bits <= a4 bit */
+    wsr     a3, INTENABLE
+    rsil    a3, \level - 1                  /* lower interrupt level by 1 */
+    #endif
+
+    movi    a3, XT_TIMER_INTEN              /* a3 = timer interrupt bit */
+    wsr     a4, INTCLEAR                    /* clear sw or edge-triggered interrupt */
+
+    #ifndef RIOT_OS                         /* we use it as hardware timer in RIOT OS */
+    beq     a3, a4, 7f                      /* if timer interrupt then skip table */
+    #endif
+
+    find_ms_setbit a3, a4, a3, 0            /* a3 = interrupt number */
+
+#if SDK_USED                                /* _xtos_interrupt_table is in reverse order */
+    movi    a4, XCHAL_NUM_INTERRUPTS        /* intnum = XCHAL_NUM_INTERRUPTS - intnum */
+    sub     a3, a4, a3
+#endif
+    movi    a4, _xt_interrupt_table
+    addx8   a3, a3, a4                      /* a3 = address of interrupt table entry */
+    l32i    a4, a3, XIE_HANDLER             /* a4 = handler address */
+    #ifdef __XTENSA_CALL0_ABI__
+    mov     a12, a6                         /* save in callee-saved reg */
+    l32i    a2, a3, XIE_ARG                 /* a2 = handler arg */
+    callx0  a4                              /* call handler */
+    mov     a2, a12
+    #else
+    mov     a2, a6                          /* save in windowed reg */
+    l32i    a6, a3, XIE_ARG                 /* a6 = handler arg */
+    callx4  a4                              /* call handler */
+    #endif
+
+    #ifdef XT_USE_SWPRI
+    j       8f
+    #else
+    j       .L_xt_user_int_&level&          /* check for more interrupts */
+    #endif
+
+7:
+
+    .ifeq XT_TIMER_INTPRI - \level
+.L_xt_user_int_timer_&level&:
+    /*
+    Interrupt handler for the RTOS tick timer if at this level.
+    We'll be reading the interrupt state again after this call
+    so no need to preserve any registers except a6 (vpri_mask).
+    */
+    #ifdef __XTENSA_CALL0_ABI__
+    mov     a12, a6
+    call0   XT_RTOS_TIMER_INT
+    mov     a2, a12
+    #else
+    mov     a2, a6
+    call4   XT_RTOS_TIMER_INT
+    #endif
+    .endif
+
+    #ifdef XT_USE_SWPRI
+    j       8f
+    #else
+    j       .L_xt_user_int_&level&          /* check for more interrupts */
+    #endif
+
+    #ifdef XT_USE_SWPRI
+8:
+    /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
+       virtual _xt_intenable which _could_ have changed during interrupt
+       processing. */
+
+    movi    a3, _xt_intdata
+    l32i    a4, a3, 0                       /* a4 = _xt_intenable    */
+    s32i    a2, a3, 4                       /* update _xt_vpri_mask  */
+    and     a4, a4, a2                      /* a4 = masked intenable */
+    wsr     a4, INTENABLE                   /* update INTENABLE      */
+    #endif
+
+9:
+    /* done */
+
+    .endm
+
+
+/*
+--------------------------------------------------------------------------------
+  Panic handler.
+  Should be reached by call0 (preferable) or jump only. If call0, a0 says where
+  from. If on simulator, display panic message and abort, else loop indefinitely.
+--------------------------------------------------------------------------------
+*/
+
+    .text
+    .global     _xt_panic
+    .type       _xt_panic,@function
+    .align      4
+
+_xt_panic:
+    #ifdef XT_SIMULATOR
+    addi    a4, a0, -3                      /* point to call0 */
+    movi    a3, _xt_panic_message
+    movi    a2, SYS_log_msg
+    simcall
+    movi    a2, SYS_gdb_abort
+    simcall
+    #else
+    rsil    a2, XCHAL_EXCM_LEVEL            /* disable all low & med ints */
+1:  j       1b                              /* loop infinitely */
+    #endif
+
+    .section    .rodata, "a"
+    .align      4
+
+_xt_panic_message:
+    .string "\n*** _xt_panic() was called from 0x%08x or jumped to. ***\n"
+
+
+/*
+--------------------------------------------------------------------------------
+    Hooks to dynamically install handlers for exceptions and interrupts.
+    Allows automated regression frameworks to install handlers per test.
+    Consists of an array of function pointers indexed by interrupt level,
+    with index 0 containing the entry for user exceptions.
+    Initialized with all 0s, meaning no handler is installed at each level.
+    See comment in xtensa_rtos.h for more details.
+--------------------------------------------------------------------------------
+*/
+
+    #ifdef XT_INTEXC_HOOKS
+    .data
+    .global     _xt_intexc_hooks
+    .type       _xt_intexc_hooks,@object
+    .align      4
+
+_xt_intexc_hooks:
+    .fill       XT_INTEXC_HOOK_NUM, 4, 0
+    #endif
+
+
+/*
+--------------------------------------------------------------------------------
+  EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
+  (except window exception vectors).
+
+  Each vector goes at a predetermined location according to the Xtensa
+  hardware configuration, which is ensured by its placement in a special
+  section known to the Xtensa linker support package (LSP). It performs
+  the minimum necessary before jumping to the handler in the .text section.
+
+  The corresponding handler goes in the normal .text section. It sets up
+  the appropriate stack frame, saves a few vector-specific registers and
+  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
+  and enter the RTOS, then sets up a C environment. It then calls the
+  user's interrupt handler code (which may be coded in C) and finally
+  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
+
+  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
+  eventually the RTOS scheduler will want to dispatch the interrupted
+  task or handler. The scheduler will return to the exit point that was
+  saved in the interrupt stack frame at XT_STK_EXIT.
+--------------------------------------------------------------------------------
+*/
+
+
+/*
+--------------------------------------------------------------------------------
+Debug Exception.
+--------------------------------------------------------------------------------
+*/
+
+#if XCHAL_HAVE_DEBUG
+
+    .begin      literal_prefix .DebugExceptionVector
+    .section    .DebugExceptionVector.text, "ax"
+    .global     _DebugExceptionVector
+    .literal_position
+    .align      4
+
+_DebugExceptionVector:
+
+    #ifdef XT_SIMULATOR
+    /*
+    In the simulator, let the debugger (if any) handle the debug exception,
+    or simply stop the simulation:
+    */
+    wsr     a2, EXCSAVE+XCHAL_DEBUGLEVEL    /* save a2 where sim expects it */
+    movi    a2, SYS_gdb_enter_sktloop
+    simcall                                 /* have ISS handle debug exc. */
+    #elif 0 /* change condition to 1 to use the HAL minimal debug handler */
+    wsr     a3, EXCSAVE+XCHAL_DEBUGLEVEL
+    movi    a3, xthal_debugexc_defhndlr_nw  /* use default debug handler */
+    jx      a3
+    #else
+    wsr     a0, EXCSAVE+XCHAL_DEBUGLEVEL    /* save original a0 somewhere */
+    call0   _xt_panic                       /* does not return */
+    rfi     XCHAL_DEBUGLEVEL                /* make a0 point here not later */
+    #endif
+
+    .end        literal_prefix
+
+#endif
+
+/*
+--------------------------------------------------------------------------------
+Double Exception.
+Double exceptions are not a normal occurrence. They indicate a bug of some kind.
+--------------------------------------------------------------------------------
+*/
+
+#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
+
+    .begin      literal_prefix .DoubleExceptionVector
+    .section    .DoubleExceptionVector.text, "ax"
+    .global     _DoubleExceptionVector
+    .literal_position
+    .align      4
+
+_DoubleExceptionVector:
+
+    #if XCHAL_HAVE_DEBUG
+    break   1, 4                            /* unhandled double exception */
+    #endif
+    call0   _xt_panic                       /* does not return */
+    rfde                                    /* make a0 point here not later */
+
+    .end        literal_prefix
+
+#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
+
+/*
+--------------------------------------------------------------------------------
+Kernel Exception (including Level 1 Interrupt from kernel mode).
+--------------------------------------------------------------------------------
+*/
+
+    .begin      literal_prefix .KernelExceptionVector
+    .section    .KernelExceptionVector.text, "ax"
+    .global     _KernelExceptionVector
+    .literal_position
+    .align      4
+
+_KernelExceptionVector:
+
+    wsr     a0, EXCSAVE_1                   /* preserve a0 */
+    call0   _xt_kernel_exc                  /* kernel exception handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .literal_position
+    .align      4
+
+_xt_kernel_exc:
+    #if XCHAL_HAVE_DEBUG
+    break   1, 0                            /* unhandled kernel exception */
+    #endif
+    call0   _xt_panic                       /* does not return */
+    rfe                                     /* make a0 point here not there */
+
+
+/*
+--------------------------------------------------------------------------------
+User Exception (including Level 1 Interrupt from user mode).
+--------------------------------------------------------------------------------
+*/
+
+    .begin      literal_prefix .UserExceptionVector
+    .section    .UserExceptionVector.text, "ax"
+    .global     _UserExceptionVector
+    .type       _UserExceptionVector,@function
+    .literal_position
+    .align      4
+
+_UserExceptionVector:
+
+    wsr     a0, EXCSAVE_1                   /* preserve a0 */
+    call0   _xt_user_exc                    /* user exception handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+/*
+--------------------------------------------------------------------------------
+  Insert some waypoints for jumping beyond the signed 8-bit range of
+  conditional branch instructions, so the conditional branchces to specific
+  exception handlers are not taken in the mainline. Saves some cycles in the
+  mainline.
+--------------------------------------------------------------------------------
+*/
+
+    .text
+
+    #if XCHAL_HAVE_WINDOWED
+    .align      4
+_xt_to_alloca_exc:
+    call0   _xt_alloca_exc                  /* in window vectors section */
+    /* never returns here - call0 is used as a jump (see note at top) */
+    #endif
+
+    .align      4
+_xt_to_syscall_exc:
+    call0   _xt_syscall_exc
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    #if XCHAL_CP_NUM > 0
+    .align      4
+_xt_to_coproc_exc:
+    call0   _xt_coproc_exc
+    /* never returns here - call0 is used as a jump (see note at top) */
+    #endif
+
+
+/*
+--------------------------------------------------------------------------------
+  User exception handler.
+--------------------------------------------------------------------------------
+*/
+
+    .type       _xt_user_exc,@function
+    .align      4
+
+_xt_user_exc:
+
+    /* If level 1 interrupt then jump to the dispatcher */
+    rsr     a0, EXCCAUSE
+    beqi    a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1
+
+    /* Handle any coprocessor exceptions. Rely on the fact that exception
+       numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
+    */
+    #if XCHAL_CP_NUM > 0
+    bgeui   a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
+    #endif
+
+    /* Handle alloca and syscall exceptions */
+    #if XCHAL_HAVE_WINDOWED
+    beqi    a0, EXCCAUSE_ALLOCA,  _xt_to_alloca_exc
+    #endif
+    beqi    a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
+
+    /* Handle all other exceptions. All can have user-defined handlers. */
+    /* NOTE: we'll stay on the user stack for exception handling.       */
+
+    /* Allocate exception frame and save minimal context. */
+    mov     a0, sp
+    addi    sp, sp, -XT_STK_FRMSZ
+    s32i    a0, sp, XT_STK_A1
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -12                     /* for debug backtrace */
+    #endif
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -16                     /* for debug backtrace */
+    #endif
+    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
+    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
+    call0   _xt_context_save
+
+    /* Save exc cause and vaddr into exception frame */
+    rsr     a0, EXCCAUSE
+    s32i    a0, sp, XT_STK_EXCCAUSE
+    rsr     a0, EXCVADDR
+    s32i    a0, sp, XT_STK_EXCVADDR
+
+    /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    rsr     a0, EPC_1                       /* return address for debug backtrace */
+    movi    a5, 0xC0000000                  /* constant with top 2 bits set (call size) */
+    rsync                                   /* wait for WSR.PS to complete */
+    or      a0, a0, a5                      /* set top 2 bits */
+    addx2   a0, a5, a0                      /* clear top bit -- thus simulating call4 size */
+    #else
+    rsync                                   /* wait for WSR.PS to complete */
+    #endif
+    #endif
+
+    rsr     a2, EXCCAUSE                    /* recover exc cause */
+
+    #ifdef XT_INTEXC_HOOKS
+    /*
+    Call exception hook to pre-handle exceptions (if installed).
+    Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
+    */
+    movi    a4, _xt_intexc_hooks
+    l32i    a4, a4, 0                       /* user exception hook index 0 */
+    beqz    a4, 1f
+.Ln_xt_user_exc_call_hook:
+    #ifdef __XTENSA_CALL0_ABI__
+    callx0  a4
+    beqi    a2, -1, .L_xt_user_done
+    #else
+    mov     a6, a2
+    callx4  a4
+    beqi    a6, -1, .L_xt_user_done
+    mov     a2, a6
+    #endif
+1:
+    #endif
+
+    rsr     a2, EXCCAUSE                    /* recover exc cause */
+    movi    a3, _xt_exception_table
+    addx4   a4, a2, a3                      /* a4 = address of exception table entry */
+    l32i    a4, a4, 0                       /* a4 = handler address */
+    #ifdef __XTENSA_CALL0_ABI__
+    mov     a2, sp                          /* a2 = pointer to exc frame */
+    callx0  a4                              /* call handler */
+    #else
+    mov     a6, sp                          /* a6 = pointer to exc frame */
+    callx4  a4                              /* call handler */
+    #endif
+
+.L_xt_user_done:
+
+    /* Restore context and return */
+    call0   _xt_context_restore
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, PS
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_1
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove exception frame */
+    rsync                                   /* ensure PS and EPC written */
+    rfe                                     /* PS.EXCM is cleared */
+
+#else
+
+    .text
+
+#endif /* SDK_INT_HANDLING */
+
+/*
+--------------------------------------------------------------------------------
+  Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+  on entry and used to return to a thread or interrupted interrupt handler.
+--------------------------------------------------------------------------------
+*/
+
+    .global     _xt_user_exit
+    .type       _xt_user_exit,@function
+    .align      4
+_xt_user_exit:
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, PS
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_1
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure PS and EPC written */
+    rfe                                     /* PS.EXCM is cleared */
+
+#ifndef SDK_INT_HANDLING
+/*
+--------------------------------------------------------------------------------
+Syscall Exception Handler (jumped to from User Exception Handler).
+Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
+Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
+--------------------------------------------------------------------------------
+*/
+
+    .text
+    .type       _xt_syscall_exc,@function
+    .align      4
+_xt_syscall_exc:
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /*
+    Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
+    Use a minimal stack frame (16B) to save A2 & A3 for scratch.
+    PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
+    rsr     a0, PS
+    addi    a0, a0, -PS_EXCM_MASK
+    wsr     a0, PS
+    */
+    addi    sp, sp, -16
+    s32i    a2, sp, 8
+    s32i    a3, sp, 12
+    #else   /* Windowed ABI */
+    /*
+    Save necessary context and spill the register windows.
+    PS.EXCM is still set and must remain set until after the spill.
+    Reuse context save function though it saves more than necessary.
+    For this reason, a full interrupt stack frame is allocated.
+    */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
+    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
+    call0   _xt_context_save
+    #endif
+
+    /*
+    Grab the interruptee's PC and skip over the 'syscall' instruction.
+    If it's at the end of a zero-overhead loop and it's not on the last
+    iteration, decrement loop counter and skip to beginning of loop.
+    */
+    rsr     a2, EPC_1                       /* a2 = PC of 'syscall' */
+    addi    a3, a2, 3                       /* ++PC                 */
+    #if XCHAL_HAVE_LOOPS
+    rsr     a0, LEND                        /* if (PC == LEND       */
+    bne     a3, a0, 1f
+    rsr     a0, LCOUNT                      /*     && LCOUNT != 0)  */
+    beqz    a0, 1f                          /* {                    */
+    addi    a0, a0, -1                      /*   --LCOUNT           */
+    rsr     a3, LBEG                        /*   PC = LBEG          */
+    wsr     a0, LCOUNT                      /* }                    */
+    #endif
+1:  wsr     a3, EPC_1                       /* update PC            */
+
+    /* Restore interruptee's context and return from exception. */
+    #ifdef __XTENSA_CALL0_ABI__
+    l32i    a2, sp, 8
+    l32i    a3, sp, 12
+    addi    sp, sp, 16
+    #else
+    call0   _xt_context_restore
+    addi    sp, sp, XT_STK_FRMSZ
+    #endif
+    movi    a0, -1
+    movnez  a2, a0, a2                      /* return -1 if not syscall 0 */
+    rsr     a0, EXCSAVE_1
+    rfe
+
+/*
+--------------------------------------------------------------------------------
+Co-Processor Exception Handler (jumped to from User Exception Handler).
+These exceptions are generated by co-processor instructions, which are only
+allowed in thread code (not in interrupts or kernel code). This restriction is
+deliberately imposed to reduce the burden of state-save/restore in interrupts.
+--------------------------------------------------------------------------------
+*/
+#if XCHAL_CP_NUM > 0
+
+    .section .rodata, "a"
+
+/* Offset to CP n save area in thread's CP save area. */
+    .global _xt_coproc_sa_offset
+    .type   _xt_coproc_sa_offset,@object
+    .align  16                      /* minimize crossing cache boundaries */
+_xt_coproc_sa_offset:
+    .word   XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
+    .word   XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
+
+/* Bitmask for CP n's CPENABLE bit. */
+    .type   _xt_coproc_mask,@object
+    .align  16,,8                   /* try to keep it all in one cache line */
+    .set    i, 0
+_xt_coproc_mask:
+    .rept   XCHAL_CP_MAX
+    .long   (i<<16) | (1<<i)    // upper 16-bits = i, lower = bitmask
+    .set    i, i+1
+    .endr
+
+    .data
+
+/* Owner thread of CP n, identified by thread's CP save area (0 = unowned). */
+    .global _xt_coproc_owner_sa
+    .type   _xt_coproc_owner_sa,@object
+    .align  16,,XCHAL_CP_MAX<<2     /* minimize crossing cache boundaries */
+_xt_coproc_owner_sa:
+    .space  XCHAL_CP_MAX << 2
+
+    .text
+
+
+    .align  4
+.L_goto_invalid:
+    j   .L_xt_coproc_invalid    /* not in a thread (invalid) */
+    .align  4
+.L_goto_done:
+    j   .L_xt_coproc_done
+
+
+/*
+--------------------------------------------------------------------------------
+  Coprocessor exception handler.
+  At entry, only a0 has been saved (in EXCSAVE_1).
+--------------------------------------------------------------------------------
+*/
+
+    .type   _xt_coproc_exc,@function
+    .align  4
+
+_xt_coproc_exc:
+
+    /* Allocate interrupt stack frame and save minimal context. */
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -12                     /* for debug backtrace */
+    #endif
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -16                     /* for debug backtrace */
+    #endif
+    movi    a0, _xt_user_exit               /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    rsr     a0, EXCCAUSE
+    s32i    a5, sp, XT_STK_A5               /* save a5 */
+    addi    a5, a0, -EXCCAUSE_CP0_DISABLED  /* a5 = CP index */
+
+    /* Save a few more of interruptee's registers (a5 was already saved). */
+    s32i    a2,  sp, XT_STK_A2
+    s32i    a3,  sp, XT_STK_A3
+    s32i    a4,  sp, XT_STK_A4
+    s32i    a15, sp, XT_STK_A15
+
+    /* Get co-processor state save area of new owner thread. */
+    call0   XT_RTOS_CP_STATE                /* a15 = new owner's save area */
+    beqz    a15, .L_goto_invalid            /* not in a thread (invalid) */
+
+    /* Enable the co-processor's bit in CPENABLE. */
+    movi    a0, _xt_coproc_mask
+    rsr     a4, CPENABLE                    /* a4 = CPENABLE */
+    addx4   a0, a5, a0                      /* a0 = &_xt_coproc_mask[n] */
+    l32i    a0, a0, 0                       /* a0 = (n << 16) | (1 << n) */
+    movi    a3, _xt_coproc_owner_sa     /* (placed here for load slot) */
+    extui   a2, a0, 0, 16                   /* coprocessor bitmask portion */
+    or      a4, a4, a2                      /* a4 = CPENABLE | (1 << n) */
+    wsr     a4, CPENABLE
+
+    /* Get old coprocessor owner thread (save area ptr) and assign new one.  */
+    addx4   a3,  a5, a3                      /* a3 = &_xt_coproc_owner_sa[n] */
+    l32i    a2,  a3, 0                       /* a2 = old owner's save area */
+    s32i    a15, a3, 0                       /* _xt_coproc_owner_sa[n] = new */
+    rsync                                    /* ensure wsr.CPENABLE is complete */
+
+    /* Only need to context switch if new owner != old owner. */
+    beq     a15, a2, .L_goto_done           /* new owner == old, we're done */
+
+    /* If no old owner then nothing to save. */
+    beqz    a2, .L_check_new
+
+    /* If old owner not actively using CP then nothing to save. */
+    l16ui   a4,  a2,  XT_CPENABLE           /* a4 = old owner's CPENABLE */
+    bnone   a4,  a0,  .L_check_new          /* old owner not using CP    */
+
+.L_save_old:
+    /* Save old owner's coprocessor state. */
+
+    movi    a5, _xt_coproc_sa_offset
+
+    /* Mark old owner state as no longer active (CPENABLE bit n clear). */
+    xor     a4,  a4,  a0                    /* clear CP bit in CPENABLE    */
+    s16i    a4,  a2,  XT_CPENABLE           /* update old owner's CPENABLE */
+
+    extui   a4,  a0,  16,  5                /* a4 = CP index = n */
+    addx4   a5,  a4,  a5                    /* a5 = &_xt_coproc_sa_offset[n] */
+
+    /* Mark old owner state as saved (CPSTORED bit n set). */
+    l16ui   a4,  a2,  XT_CPSTORED           /* a4 = old owner's CPSTORED */
+    l32i    a5,  a5,  0                     /* a5 = XT_CP[n]_SA offset */
+    or      a4,  a4,  a0                    /* set CP in old owner's CPSTORED */
+    s16i    a4,  a2,  XT_CPSTORED           /* update old owner's CPSTORED */
+    l32i    a2, a2, XT_CP_ASA               /* ptr to actual (aligned) save area */
+    extui   a3, a0, 16, 5                   /* a3 = CP index = n */
+    add     a2, a2, a5                      /* a2 = old owner's area for CP n */
+
+    /*
+    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
+    It is theoretically possible for Xtensa processor designers to write TIE
+    that causes more address registers to be affected, but it is generally
+    unlikely. If that ever happens, more registers needs to be saved/restored
+    around this macro invocation, and the value in a15 needs to be recomputed.
+    */
+    xchal_cpi_store_funcbody
+
+.L_check_new:
+    /* Check if any state has to be restored for new owner. */
+    /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */
+
+    l16ui   a3,  a15, XT_CPSTORED           /* a3 = new owner's CPSTORED */
+    movi    a4, _xt_coproc_sa_offset
+    bnone   a3,  a0,  .L_check_cs           /* full CP not saved, check callee-saved */
+    xor     a3,  a3,  a0                    /* CPSTORED bit is set, clear it */
+    s16i    a3,  a15, XT_CPSTORED           /* update new owner's CPSTORED */
+
+    /* Adjust new owner's save area pointers to area for CP n. */
+    extui   a3,  a0, 16, 5                  /* a3 = CP index = n */
+    addx4   a4,  a3, a4                     /* a4 = &_xt_coproc_sa_offset[n] */
+    l32i    a4,  a4, 0                      /* a4 = XT_CP[n]_SA */
+    l32i    a5, a15, XT_CP_ASA              /* ptr to actual (aligned) save area */
+    add     a2,  a4, a5                     /* a2 = new owner's area for CP */
+
+    /*
+    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
+    It is theoretically possible for Xtensa processor designers to write TIE
+    that causes more address registers to be affected, but it is generally
+    unlikely. If that ever happens, more registers needs to be saved/restored
+    around this macro invocation.
+    */
+    xchal_cpi_load_funcbody
+
+    /* Restore interruptee's saved registers. */
+    /* Can omit rsync for wsr.CPENABLE here because _xt_user_exit does it. */
+.L_xt_coproc_done:
+    l32i    a15, sp, XT_STK_A15
+    l32i    a5,  sp, XT_STK_A5
+    l32i    a4,  sp, XT_STK_A4
+    l32i    a3,  sp, XT_STK_A3
+    l32i    a2,  sp, XT_STK_A2
+    call0   _xt_user_exit                   /* return via exit dispatcher */
+    /* Never returns here - call0 is used as a jump (see note at top) */
+
+.L_check_cs:
+    /* a0 = CP mask in low bits, a15 = new owner's save area */
+    l16ui   a2, a15, XT_CP_CS_ST            /* a2 = mask of CPs saved    */
+    bnone   a2,  a0, .L_xt_coproc_done      /* if no match then done     */
+    and     a2,  a2, a0                     /* a2 = which CPs to restore */
+    extui   a2,  a2, 0, 8                   /* extract low 8 bits        */
+    s32i    a6,  sp, XT_STK_A6              /* save extra needed regs    */
+    s32i    a7,  sp, XT_STK_A7
+    s32i    a13, sp, XT_STK_A13
+    s32i    a14, sp, XT_STK_A14
+    call0   _xt_coproc_restorecs            /* restore CP registers      */
+    l32i    a6,  sp, XT_STK_A6              /* restore saved registers   */
+    l32i    a7,  sp, XT_STK_A7
+    l32i    a13, sp, XT_STK_A13
+    l32i    a14, sp, XT_STK_A14
+    j       .L_xt_coproc_done
+
+    /* Co-processor exception occurred outside a thread (not supported). */
+.L_xt_coproc_invalid:
+    #if XCHAL_HAVE_DEBUG
+    break   1, 1                            /* unhandled user exception */
+    #endif
+    call0   _xt_panic                       /* not in a thread (invalid) */
+    /* never returns */
+
+
+#endif /* XCHAL_CP_NUM */
+
+
+/*
+-------------------------------------------------------------------------------
+  Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet.
+-------------------------------------------------------------------------------
+*/
+
+    .text
+    .type       _xt_lowint1,@function
+    .align      4
+
+_xt_lowint1:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_user_exit               /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(1) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(1) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+
+/*
+-------------------------------------------------------------------------------
+  MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS.
+
+  Medium priority interrupts are by definition those with priority greater
+  than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by
+  setting PS.EXCM and therefore can easily support a C environment for
+  handlers in C, and interact safely with an RTOS.
+
+  Each vector goes at a predetermined location according to the Xtensa
+  hardware configuration, which is ensured by its placement in a special
+  section known to the Xtensa linker support package (LSP). It performs
+  the minimum necessary before jumping to the handler in the .text section.
+
+  The corresponding handler goes in the normal .text section. It sets up
+  the appropriate stack frame, saves a few vector-specific registers and
+  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
+  and enter the RTOS, then sets up a C environment. It then calls the
+  user's interrupt handler code (which may be coded in C) and finally
+  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
+
+  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
+  eventually the RTOS scheduler will want to dispatch the interrupted
+  task or handler. The scheduler will return to the exit point that was
+  saved in the interrupt stack frame at XT_STK_EXIT.
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_EXCM_LEVEL >= 2
+
+    .begin      literal_prefix .Level2InterruptVector
+    .section    .Level2InterruptVector.text, "ax"
+    .global     _Level2Vector
+    .type       _Level2Vector,@function
+    .literal_position
+
+    .align      4
+_Level2Vector:
+    wsr     a0, EXCSAVE_2                   /* preserve a0 */
+    call0   _xt_medint2                     /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_medint2,@function
+    .align      4
+_xt_medint2:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_2                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_2                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_2                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint2_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(2) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint2_exit
+    .type       _xt_medint2_exit,@function
+    .align      4
+_xt_medint2_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_2
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_2
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     2
+
+#endif  /* Level 2 */
+
+#if XCHAL_EXCM_LEVEL >= 3
+
+    .begin      literal_prefix .Level3InterruptVector
+    .section    .Level3InterruptVector.text, "ax"
+    .global     _Level3Vector
+    .type       _Level3Vector,@function
+    .literal_position
+
+    .align      4
+_Level3Vector:
+    wsr     a0, EXCSAVE_3                   /* preserve a0 */
+    call0   _xt_medint3                     /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_medint3,@function
+    .align      4
+_xt_medint3:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_3                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_3                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_3                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint3_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(3) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint3_exit
+    .type       _xt_medint3_exit,@function
+    .align      4
+_xt_medint3_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_3
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_3
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     3
+
+#endif  /* Level 3 */
+
+#if XCHAL_EXCM_LEVEL >= 4
+
+    .begin      literal_prefix .Level4InterruptVector
+    .section    .Level4InterruptVector.text, "ax"
+    .global     _Level4Vector
+    .type       _Level4Vector,@function
+    .literal_position
+
+    .align      4
+_Level4Vector:
+    wsr     a0, EXCSAVE_4                   /* preserve a0 */
+    call0   _xt_medint4                     /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_medint4,@function
+    .align      4
+_xt_medint4:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_4                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_4                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_4                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint4_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(4) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint4_exit
+    .type       _xt_medint4_exit,@function
+    .align      4
+_xt_medint4_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_4
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_4
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     4
+
+#endif  /* Level 4 */
+
+#if XCHAL_EXCM_LEVEL >= 5
+
+    .begin      literal_prefix .Level5InterruptVector
+    .section    .Level5InterruptVector.text, "ax"
+    .global     _Level5Vector
+    .type       _Level5Vector,@function
+    .literal_position
+
+    .align      4
+_Level5Vector:
+    wsr     a0, EXCSAVE_5                   /* preserve a0 */
+    call0   _xt_medint5                     /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_medint5,@function
+    .align      4
+_xt_medint5:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_5                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_5                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_5                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint5_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(5) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint5_exit
+    .type       _xt_medint5_exit,@function
+    .align      4
+_xt_medint5_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_5
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_5
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     5
+
+#endif  /* Level 5 */
+
+#if XCHAL_EXCM_LEVEL >= 6
+
+    .begin      literal_prefix .Level6InterruptVector
+    .section    .Level6InterruptVector.text, "ax"
+    .global     _Level6Vector
+    .type       _Level6Vector,@function
+    .literal_position
+
+    .align      4
+_Level6Vector:
+    wsr     a0, EXCSAVE_6                   /* preserve a0 */
+    call0   _xt_medint6                     /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_medint6,@function
+    .align      4
+_xt_medint6:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_6                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_6                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_6                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint6_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(6) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint6_exit
+    .type       _xt_medint6_exit,@function
+    .align      4
+_xt_medint6_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_6
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_6
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     6
+
+#endif  /* Level 6 */
+
+
+/*******************************************************************************
+
+HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
+
+High priority interrupts are by definition those with priorities greater
+than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
+interrupts cannot interact with the RTOS, that is they must save all regs
+they use and not call any RTOS function.
+
+A further restriction imposed by the Xtensa windowed architecture is that
+high priority interrupts must not modify the stack area even logically
+"above" the top of the interrupted stack (they need to provide their
+own stack or static save area).
+
+Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
+and used for purposes requiring very short service times.
+
+Here are templates for high priority (level 2+) interrupt vectors.
+They assume only one interrupt per level to avoid the burden of identifying
+which interrupts at this level are pending and enabled. This allows for
+minimum latency and avoids having to save/restore a2 in addition to a0.
+If more than one interrupt per high priority level is configured, this burden
+is on the handler which in any case must provide a way to save and restore
+registers it uses without touching the interrupted stack.
+
+Each vector goes at a predetermined location according to the Xtensa
+hardware configuration, which is ensured by its placement in a special
+section known to the Xtensa linker support package (LSP). It performs
+the minimum necessary before jumping to the handler in the .text section.
+
+*******************************************************************************/
+
+/*
+Currently only shells for high priority interrupt handlers are provided
+here. However a template and example can be found in the Cadence Design Systems tools
+documentation: "Microprocessor Programmer's Guide".
+*/
+
+#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
+
+    .begin      literal_prefix .Level2InterruptVector
+    .section    .Level2InterruptVector.text, "ax"
+    .global     _Level2Vector
+    .type       _Level2Vector,@function
+    .literal_position
+
+    .align      4
+_Level2Vector:
+    wsr     a0, EXCSAVE_2                   /* preserve a0 */
+    call0   _xt_highint2                    /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_highint2,@function
+    .align      4
+_xt_highint2:
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a0, _xt_intexc_hooks
+    l32i    a0, a0, 2<<2
+    beqz    a0, 1f
+.Ln_xt_highint2_call_hook:
+    callx0  a0                              /* must NOT disturb stack! */
+1:
+    #endif
+
+    /* USER_EDIT:
+    ADD HIGH PRIORITY LEVEL 2 INTERRUPT HANDLER CODE HERE.
+    */
+
+    .align  4
+.L_xt_highint2_exit:
+    rsr     a0, EXCSAVE_2                   /* restore a0 */
+    rfi     2
+
+#endif  /* Level 2 */
+
+#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
+
+    .begin      literal_prefix .Level3InterruptVector
+    .section    .Level3InterruptVector.text, "ax"
+    .global     _Level3Vector
+    .type       _Level3Vector,@function
+    .literal_position
+
+    .align      4
+_Level3Vector:
+    wsr     a0, EXCSAVE_3                   /* preserve a0 */
+    call0   _xt_highint3                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_highint3,@function
+    .align      4
+_xt_highint3:
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a0, _xt_intexc_hooks
+    l32i    a0, a0, 3<<2
+    beqz    a0, 1f
+.Ln_xt_highint3_call_hook:
+    callx0  a0                              /* must NOT disturb stack! */
+1:
+    #endif
+
+    /* USER_EDIT:
+    ADD HIGH PRIORITY LEVEL 3 INTERRUPT HANDLER CODE HERE.
+    */
+
+    .align  4
+.L_xt_highint3_exit:
+    rsr     a0, EXCSAVE_3                   /* restore a0 */
+    rfi     3
+
+#endif  /* Level 3 */
+
+#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
+
+    .begin      literal_prefix .Level4InterruptVector
+    .section    .Level4InterruptVector.text, "ax"
+    .global     _Level4Vector
+    .type       _Level4Vector,@function
+    .literal_position
+
+    .align      4
+_Level4Vector:
+    wsr     a0, EXCSAVE_4                   /* preserve a0 */
+    call0   _xt_highint4                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_highint4,@function
+    .align      4
+_xt_highint4:
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a0, _xt_intexc_hooks
+    l32i    a0, a0, 4<<2
+    beqz    a0, 1f
+.Ln_xt_highint4_call_hook:
+    callx0  a0                              /* must NOT disturb stack! */
+1:
+    #endif
+
+    /* USER_EDIT:
+    ADD HIGH PRIORITY LEVEL 4 INTERRUPT HANDLER CODE HERE.
+    */
+
+    .align  4
+.L_xt_highint4_exit:
+    rsr     a0, EXCSAVE_4                   /* restore a0 */
+    rfi     4
+
+#endif  /* Level 4 */
+
+#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
+
+    .begin      literal_prefix .Level5InterruptVector
+    .section    .Level5InterruptVector.text, "ax"
+    .global     _Level5Vector
+    .type       _Level5Vector,@function
+    .literal_position
+
+    .align      4
+_Level5Vector:
+    wsr     a0, EXCSAVE_5                   /* preserve a0 */
+    call0   _xt_highint5                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_highint5,@function
+    .align      4
+_xt_highint5:
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a0, _xt_intexc_hooks
+    l32i    a0, a0, 5<<2
+    beqz    a0, 1f
+.Ln_xt_highint5_call_hook:
+    callx0  a0                              /* must NOT disturb stack! */
+1:
+    #endif
+
+    /* USER_EDIT:
+    ADD HIGH PRIORITY LEVEL 5 INTERRUPT HANDLER CODE HERE.
+    */
+
+    .align  4
+.L_xt_highint5_exit:
+    rsr     a0, EXCSAVE_5                   /* restore a0 */
+    rfi     5
+
+#endif  /* Level 5 */
+
+#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
+
+    .begin      literal_prefix .Level6InterruptVector
+    .section    .Level6InterruptVector.text, "ax"
+    .global     _Level6Vector
+    .type       _Level6Vector,@function
+    .literal_position
+
+    .align      4
+_Level6Vector:
+    wsr     a0, EXCSAVE_6                   /* preserve a0 */
+    call0   _xt_highint6                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_highint6,@function
+    .align      4
+_xt_highint6:
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a0, _xt_intexc_hooks
+    l32i    a0, a0, 6<<2
+    beqz    a0, 1f
+.Ln_xt_highint6_call_hook:
+    callx0  a0                              /* must NOT disturb stack! */
+1:
+    #endif
+
+    /* USER_EDIT:
+    ADD HIGH PRIORITY LEVEL 6 INTERRUPT HANDLER CODE HERE.
+    */
+
+    .align  4
+.L_xt_highint6_exit:
+    rsr     a0, EXCSAVE_6                   /* restore a0 */
+    rfi     6
+
+#endif  /* Level 6 */
+
+#if XCHAL_HAVE_NMI
+
+    .begin      literal_prefix .NMIExceptionVector
+    .section    .NMIExceptionVector.text, "ax"
+    .global     _NMIExceptionVector
+    .type       _NMIExceptionVector,@function
+    .literal_position
+
+    .align      4
+_NMIExceptionVector:
+    wsr     a0, EXCSAVE + XCHAL_NMILEVEL  _ /* preserve a0 */
+    call0   _xt_nmi                         /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .text
+    .type       _xt_nmi,@function
+    .align      4
+_xt_nmi:
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a0, _xt_intexc_hooks
+    l32i    a0, a0, XCHAL_NMILEVEL<<2
+    beqz    a0, 1f
+.Ln_xt_nmi_call_hook:
+    callx0  a0                              /* must NOT disturb stack! */
+1:
+    #endif
+
+    /* USER_EDIT:
+    ADD HIGH PRIORITY NON-MASKABLE INTERRUPT (NMI) HANDLER CODE HERE.
+    */
+
+    .align  4
+.L_xt_nmi_exit:
+    rsr     a0, EXCSAVE + XCHAL_NMILEVEL    /* restore a0 */
+    rfi     XCHAL_NMILEVEL
+
+#endif  /* NMI */
+
+
+/*******************************************************************************
+
+WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
+
+Here is the code for each window overflow/underflow exception vector and
+(interspersed) efficient code for handling the alloca exception cause.
+Window exceptions are handled entirely in the vector area and are very
+tight for performance. The alloca exception is also handled entirely in
+the window vector area so comes at essentially no cost in code size.
+Users should never need to modify them and Cadence Design Systems recommends
+they do not.
+
+Window handlers go at predetermined vector locations according to the
+Xtensa hardware configuration, which is ensured by their placement in a
+special section known to the Xtensa linker support package (LSP). Since
+their offsets in that section are always the same, the LSPs do not define
+a section per vector.
+
+These things are coded for XEA2 only (XEA1 is not supported).
+
+Note on Underflow Handlers:
+The underflow handler for returning from call[i+1] to call[i]
+must preserve all the registers from call[i+1]'s window.
+In particular, a0 and a1 must be preserved because the RETW instruction
+will be reexecuted (and may even underflow if an intervening exception
+has flushed call[i]'s registers).
+Registers a2 and up may contain return values.
+
+*******************************************************************************/
+
+#if XCHAL_HAVE_WINDOWED
+
+    .section .WindowVectors.text, "ax"
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call4.
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call4 to call[j+1].
+On entry here:
+    window rotated to call[j] start point;
+        a0-a3 are registers to be saved;
+        a4-a15 must be preserved;
+        a5 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x0
+    .global _WindowOverflow4
+_WindowOverflow4:
+
+    s32e    a0, a5, -16     /* save a0 to call[j+1]'s stack frame */
+    s32e    a1, a5, -12     /* save a1 to call[j+1]'s stack frame */
+    s32e    a2, a5,  -8     /* save a2 to call[j+1]'s stack frame */
+    s32e    a3, a5,  -4     /* save a3 to call[j+1]'s stack frame */
+    rfwo                    /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call4
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call4 to call[i+1].
+On entry here:
+        window rotated to call[i] start point;
+        a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
+        a4-a15 must be preserved (they are call[i+1].reg[0..11]);
+        a5 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x40
+    .global _WindowUnderflow4
+_WindowUnderflow4:
+
+    l32e    a0, a5, -16     /* restore a0 from call[i+1]'s stack frame */
+    l32e    a1, a5, -12     /* restore a1 from call[i+1]'s stack frame */
+    l32e    a2, a5,  -8     /* restore a2 from call[i+1]'s stack frame */
+    l32e    a3, a5,  -4     /* restore a3 from call[i+1]'s stack frame */
+    rfwu
+
+/*
+--------------------------------------------------------------------------------
+Handle alloca exception generated by interruptee executing 'movsp'.
+This uses space between the window vectors, so is essentially "free".
+All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
+and PS.EXCM has been set by the exception hardware (can't be interrupted).
+The fact the alloca exception was taken means the registers associated with
+the base-save area have been spilled and will be restored by the underflow
+handler, so those 4 registers are available for scratch.
+The code is optimized to avoid unaligned branches and minimize cache misses.
+--------------------------------------------------------------------------------
+*/
+
+    .align  4
+    .global _xt_alloca_exc
+_xt_alloca_exc:
+
+    rsr     a0, WINDOWBASE  /* grab WINDOWBASE before rotw changes it */
+    rotw    -1              /* WINDOWBASE goes to a4, new a0-a3 are scratch */
+    rsr     a2, PS
+    extui   a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+    xor     a3, a3, a4      /* bits changed from old to current windowbase */
+    rsr     a4, EXCSAVE_1   /* restore original a0 (now in a4) */
+    slli    a3, a3, XCHAL_PS_OWB_SHIFT
+    xor     a2, a2, a3      /* flip changed bits in old window base */
+    wsr     a2, PS          /* update PS.OWB to new window base */
+    rsync
+
+    _bbci.l a4, 31, _WindowUnderflow4
+    rotw    -1              /* original a0 goes to a8 */
+    _bbci.l a8, 30, _WindowUnderflow8
+    rotw    -1
+    j               _WindowUnderflow12
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call8
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call8 to call[j+1].
+On entry here:
+    window rotated to call[j] start point;
+        a0-a7 are registers to be saved;
+        a8-a15 must be preserved;
+        a9 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x80
+    .global _WindowOverflow8
+_WindowOverflow8:
+
+    s32e    a0, a9, -16     /* save a0 to call[j+1]'s stack frame */
+    l32e    a0, a1, -12     /* a0 <- call[j-1]'s sp
+                               (used to find end of call[j]'s frame) */
+    s32e    a1, a9, -12     /* save a1 to call[j+1]'s stack frame */
+    s32e    a2, a9,  -8     /* save a2 to call[j+1]'s stack frame */
+    s32e    a3, a9,  -4     /* save a3 to call[j+1]'s stack frame */
+    s32e    a4, a0, -32     /* save a4 to call[j]'s stack frame */
+    s32e    a5, a0, -28     /* save a5 to call[j]'s stack frame */
+    s32e    a6, a0, -24     /* save a6 to call[j]'s stack frame */
+    s32e    a7, a0, -20     /* save a7 to call[j]'s stack frame */
+    rfwo                    /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call8
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call8 to call[i+1].
+On entry here:
+        window rotated to call[i] start point;
+        a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
+        a8-a15 must be preserved (they are call[i+1].reg[0..7]);
+        a9 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0xC0
+    .global _WindowUnderflow8
+_WindowUnderflow8:
+
+    l32e    a0, a9, -16     /* restore a0 from call[i+1]'s stack frame */
+    l32e    a1, a9, -12     /* restore a1 from call[i+1]'s stack frame */
+    l32e    a2, a9,  -8     /* restore a2 from call[i+1]'s stack frame */
+    l32e    a7, a1, -12     /* a7 <- call[i-1]'s sp
+                               (used to find end of call[i]'s frame) */
+    l32e    a3, a9,  -4     /* restore a3 from call[i+1]'s stack frame */
+    l32e    a4, a7, -32     /* restore a4 from call[i]'s stack frame */
+    l32e    a5, a7, -28     /* restore a5 from call[i]'s stack frame */
+    l32e    a6, a7, -24     /* restore a6 from call[i]'s stack frame */
+    l32e    a7, a7, -20     /* restore a7 from call[i]'s stack frame */
+    rfwu
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call12
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call12 to call[j+1].
+On entry here:
+    window rotated to call[j] start point;
+        a0-a11 are registers to be saved;
+        a12-a15 must be preserved;
+        a13 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x100
+    .global _WindowOverflow12
+_WindowOverflow12:
+
+    s32e    a0,  a13, -16   /* save a0 to call[j+1]'s stack frame */
+    l32e    a0,  a1,  -12   /* a0 <- call[j-1]'s sp
+                               (used to find end of call[j]'s frame) */
+    s32e    a1,  a13, -12   /* save a1 to call[j+1]'s stack frame */
+    s32e    a2,  a13,  -8   /* save a2 to call[j+1]'s stack frame */
+    s32e    a3,  a13,  -4   /* save a3 to call[j+1]'s stack frame */
+    s32e    a4,  a0,  -48   /* save a4 to end of call[j]'s stack frame */
+    s32e    a5,  a0,  -44   /* save a5 to end of call[j]'s stack frame */
+    s32e    a6,  a0,  -40   /* save a6 to end of call[j]'s stack frame */
+    s32e    a7,  a0,  -36   /* save a7 to end of call[j]'s stack frame */
+    s32e    a8,  a0,  -32   /* save a8 to end of call[j]'s stack frame */
+    s32e    a9,  a0,  -28   /* save a9 to end of call[j]'s stack frame */
+    s32e    a10, a0,  -24   /* save a10 to end of call[j]'s stack frame */
+    s32e    a11, a0,  -20   /* save a11 to end of call[j]'s stack frame */
+    rfwo                    /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call12
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call12 to call[i+1].
+On entry here:
+        window rotated to call[i] start point;
+        a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
+        a12-a15 must be preserved (they are call[i+1].reg[0..3]);
+        a13 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org 0x140
+    .global _WindowUnderflow12
+_WindowUnderflow12:
+
+    l32e    a0,  a13, -16   /* restore a0 from call[i+1]'s stack frame */
+    l32e    a1,  a13, -12   /* restore a1 from call[i+1]'s stack frame */
+    l32e    a2,  a13,  -8   /* restore a2 from call[i+1]'s stack frame */
+    l32e    a11, a1,  -12   /* a11 <- call[i-1]'s sp
+                               (used to find end of call[i]'s frame) */
+    l32e    a3,  a13,  -4   /* restore a3 from call[i+1]'s stack frame */
+    l32e    a4,  a11, -48   /* restore a4 from end of call[i]'s stack frame */
+    l32e    a5,  a11, -44   /* restore a5 from end of call[i]'s stack frame */
+    l32e    a6,  a11, -40   /* restore a6 from end of call[i]'s stack frame */
+    l32e    a7,  a11, -36   /* restore a7 from end of call[i]'s stack frame */
+    l32e    a8,  a11, -32   /* restore a8 from end of call[i]'s stack frame */
+    l32e    a9,  a11, -28   /* restore a9 from end of call[i]'s stack frame */
+    l32e    a10, a11, -24   /* restore a10 from end of call[i]'s stack frame */
+    l32e    a11, a11, -20   /* restore a11 from end of call[i]'s stack frame */
+    rfwu
+
+#endif /* XCHAL_HAVE_WINDOWED */
+
+#endif /* SDK_INT_HANDLING */
diff --git a/dist/tools/licenses/patterns/Apache2.0 b/dist/tools/licenses/patterns/Apache2.0
new file mode 100644
index 0000000000000000000000000000000000000000..51fca54c2a05e9f562b19919318daecd451de12f
--- /dev/null
+++ b/dist/tools/licenses/patterns/Apache2.0
@@ -0,0 +1,11 @@
+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.
diff --git a/dist/tools/licenses/patterns/bsd-short b/dist/tools/licenses/patterns/bsd-short
new file mode 100644
index 0000000000000000000000000000000000000000..da5873a369c60daf95c49073f69cbb8a83d9a59d
--- /dev/null
+++ b/dist/tools/licenses/patterns/bsd-short
@@ -0,0 +1 @@
+This software may be distributed under the terms of.*BSD license\.
diff --git a/dist/tools/licenses/patterns/gplv2-short-alt b/dist/tools/licenses/patterns/gplv2-short-alt
new file mode 100644
index 0000000000000000000000000000000000000000..42905b8d47dc62c9b26a650e0171e61cd63e7f90
--- /dev/null
+++ b/dist/tools/licenses/patterns/gplv2-short-alt
@@ -0,0 +1,3 @@
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License version 2 as
+published by the Free Software Foundation.
diff --git a/dist/tools/licenses/patterns/publicdomain-short b/dist/tools/licenses/patterns/publicdomain-short
new file mode 100644
index 0000000000000000000000000000000000000000..96f68e21abe8bc3b6d86ec3a0cd2b8bd2ccd6cdb
--- /dev/null
+++ b/dist/tools/licenses/patterns/publicdomain-short
@@ -0,0 +1 @@
+This.*was released in public domain