diff --git a/components/bootloader/Kconfig.projbuild b/components/bootloader/Kconfig.projbuild index ac4d1d14b..1a091a49f 100644 --- a/components/bootloader/Kconfig.projbuild +++ b/components/bootloader/Kconfig.projbuild @@ -28,8 +28,17 @@ config LOG_BOOTLOADER_LEVEL default 4 if LOG_BOOTLOADER_LEVEL_DEBUG default 5 if LOG_BOOTLOADER_LEVEL_VERBOSE -endmenu +config BOOTLOADER_VDDSDIO_BOOST + bool "Increase VDDSDIO LDO voltage to 1.9V" + default y + help + If this option is enabled, and VDDSDIO LDO is set to 1.8V (using EFUSE + or MTDI bootstrapping pin), bootloader will change LDO settings to + output 1.9V instead. This helps prevent flash chip from browning out + during flash programming operations. + For 3.3V flash, this option has no effect. +endmenu # Bootloader menu "Security features" diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index fd062a5f9..4274fe840 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -72,6 +72,8 @@ static void set_cache_and_start_app(uint32_t drom_addr, uint32_t irom_size, uint32_t entry_addr); static void update_flash_config(const esp_image_header_t* pfhdr); +static void vddsdio_configure(); +static void flash_gpio_configure(); static void clock_configure(void); static void uart_console_configure(void); static void wdt_reset_check(void); @@ -237,6 +239,8 @@ static bool ota_select_valid(const esp_ota_select_entry_t *s) void bootloader_main() { + vddsdio_configure(); + flash_gpio_configure(); clock_configure(); uart_console_configure(); wdt_reset_check(); @@ -697,6 +701,104 @@ void print_flash_info(const esp_image_header_t* phdr) #endif } +static void vddsdio_configure() +{ +#if CONFIG_BOOTLOADER_VDDSDIO_BOOST + rtc_vddsdio_config_t cfg = rtc_vddsdio_get_config(); + if (cfg.tieh == 0) { // 1.8V is used + cfg.drefh = 3; + cfg.drefm = 3; + cfg.drefl = 3; + cfg.force = 1; + cfg.enable = 1; + rtc_vddsdio_set_config(cfg); + ets_delay_us(10); // wait for regulator to become stable + } +#endif // CONFIG_BOOTLOADER_VDDSDIO_BOOST +} + + +#define FLASH_CLK_IO 6 +#define FLASH_CS_IO 11 +#define FLASH_SPIQ_IO 7 +#define FLASH_SPID_IO 8 +#define FLASH_SPIWP_IO 10 +#define FLASH_SPIHD_IO 9 +#define FLASH_IO_MATRIX_DUMMY_40M 1 +#define FLASH_IO_MATRIX_DUMMY_80M 2 +static void IRAM_ATTR flash_gpio_configure() +{ + int spi_cache_dummy = 0; + int drv = 2; +#if CONFIG_FLASHMODE_QIO + spi_cache_dummy = SPI0_R_QIO_DUMMY_CYCLELEN; //qio 3 +#elif CONFIG_FLASHMODE_QOUT + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //qout 7 +#elif CONFIG_FLASHMODE_DIO + spi_cache_dummy = SPI0_R_DIO_DUMMY_CYCLELEN; //dio 3 +#elif CONFIG_FLASHMODE_DOUT + spi_cache_dummy = SPI0_R_FAST_DUMMY_CYCLELEN; //dout 7 +#endif + /* dummy_len_plus values defined in ROM for SPI flash configuration */ + extern uint8_t g_rom_spiflash_dummy_len_plus[]; +#if CONFIG_ESPTOOLPY_FLASHFREQ_40M + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_40M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_40M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_40M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY +#elif CONFIG_ESPTOOLPY_FLASHFREQ_80M + g_rom_spiflash_dummy_len_plus[0] = FLASH_IO_MATRIX_DUMMY_80M; + g_rom_spiflash_dummy_len_plus[1] = FLASH_IO_MATRIX_DUMMY_80M; + SET_PERI_REG_BITS(SPI_USER1_REG(0), SPI_USR_DUMMY_CYCLELEN_V, spi_cache_dummy + FLASH_IO_MATRIX_DUMMY_80M, SPI_USR_DUMMY_CYCLELEN_S); //DUMMY + drv = 3; +#endif + + uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); + uint32_t pkg_ver = chip_ver & 0x7; + + if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) { + // For ESP32D2WD the SPI pins are already configured + ESP_LOGI(TAG, "Detected ESP32D2WD"); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2) { + // For ESP32PICOD2 the SPI pins are already configured + ESP_LOGI(TAG, "Detected ESP32PICOD2"); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } else if (pkg_ver == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { + // For ESP32PICOD4 the SPI pins are already configured + ESP_LOGI(TAG, "Detected ESP32PICOD4"); + //flash clock signal should come from IO MUX. + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } else { + ESP_LOGI(TAG, "Detected ESP32"); + const uint32_t spiconfig = ets_efuse_get_spiconfig(); + if (spiconfig == EFUSE_SPICONFIG_SPI_DEFAULTS) { + gpio_matrix_out(FLASH_CS_IO, SPICS0_OUT_IDX, 0, 0); + gpio_matrix_out(FLASH_SPIQ_IO, SPIQ_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPIQ_IO, SPIQ_IN_IDX, 0); + gpio_matrix_out(FLASH_SPID_IO, SPID_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPID_IO, SPID_IN_IDX, 0); + gpio_matrix_out(FLASH_SPIWP_IO, SPIWP_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPIWP_IO, SPIWP_IN_IDX, 0); + gpio_matrix_out(FLASH_SPIHD_IO, SPIHD_OUT_IDX, 0, 0); + gpio_matrix_in(FLASH_SPIHD_IO, SPIHD_IN_IDX, 0); + //select pin function gpio + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA0_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA1_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA2_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_DATA3_U, PIN_FUNC_GPIO); + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CMD_U, PIN_FUNC_GPIO); + // flash clock signal should come from IO MUX. + // set drive ability for clock + PIN_FUNC_SELECT(PERIPHS_IO_MUX_SD_CLK_U, FUNC_SD_CLK_SPICLK); + SET_PERI_REG_BITS(PERIPHS_IO_MUX_SD_CLK_U, FUN_DRV, drv, FUN_DRV_S); + } + } +} static void clock_configure(void) { diff --git a/components/bootloader/src/main/flash_qio_mode.c b/components/bootloader/src/main/flash_qio_mode.c index cd288290c..4e4bb5d2c 100644 --- a/components/bootloader/src/main/flash_qio_mode.c +++ b/components/bootloader/src/main/flash_qio_mode.c @@ -163,7 +163,7 @@ static void enable_qio_mode(read_status_fn_t read_status_fn, // spiconfig specifies a custom efuse pin configuration. This config defines all pins -except- WP. // // For now, in this situation we only support Quad I/O mode for ESP32-D2WD where WP pin is known. - uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_RESERVE); + uint32_t chip_ver = REG_GET_FIELD(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_PKG); uint32_t pkg_ver = chip_ver & 0x7; const uint32_t PKG_VER_ESP32_D2WD = 2; // TODO: use chip detection API once available if (pkg_ver != PKG_VER_ESP32_D2WD) { diff --git a/components/bt/bluedroid/api/esp_gap_ble_api.c b/components/bt/bluedroid/api/esp_gap_ble_api.c index 6b4ba6801..3846cb877 100644 --- a/components/bt/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/bluedroid/api/esp_gap_ble_api.c @@ -262,7 +262,7 @@ esp_err_t esp_ble_gap_config_scan_rsp_data_raw(uint8_t *raw_data, uint32_t raw_d } - +#if (SMP_INCLUDED) esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param_type, void *value, uint8_t len) { @@ -392,6 +392,7 @@ esp_err_t esp_ble_get_bond_device_list(int *dev_num, esp_ble_bond_dev_t *dev_lis return (ret == BT_STATUS_SUCCESS ? ESP_OK : ESP_FAIL); } +#endif /* #if (SMP_INCLUDED) */ esp_err_t esp_ble_gap_disconnect(esp_bd_addr_t remote_device) { diff --git a/components/bt/bluedroid/btc/core/btc_dm.c b/components/bt/bluedroid/btc/core/btc_dm.c index 8699c0d6d..bb35315f2 100644 --- a/components/bt/bluedroid/btc/core/btc_dm.c +++ b/components/bt/bluedroid/btc/core/btc_dm.c @@ -460,6 +460,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) case BTA_DM_SP_KEY_NOTIF_EVT: break; case BTA_DM_DEV_UNPAIRED_EVT: { +#if (SMP_INCLUDED) bt_bdaddr_t bd_addr; rsp_app = true; LOG_ERROR("BTA_DM_DEV_UNPAIRED_EVT"); @@ -472,6 +473,7 @@ void btc_dm_sec_cb_handler(btc_msg_t *msg) ble_msg.act = ESP_GAP_BLE_REMOVE_BOND_DEV_COMPLETE_EVT; param.remove_bond_dev_cmpl.status = (p_data->link_down.status == HCI_SUCCESS) ? ESP_BT_STATUS_SUCCESS : ESP_BT_STATUS_FAIL; memcpy(param.remove_bond_dev_cmpl.bd_addr, p_data->link_down.bd_addr, sizeof(BD_ADDR)); +#endif /* #if (SMP_INCLUDED) */ break; } case BTA_DM_BUSY_LEVEL_EVT: diff --git a/components/bt/bluedroid/stack/btm/btm_ble.c b/components/bt/bluedroid/stack/btm/btm_ble.c index 8c90b9c33..95f15e3a6 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble.c +++ b/components/bt/bluedroid/stack/btm/btm_ble.c @@ -180,7 +180,11 @@ BOOLEAN BTM_SecAddBleKey (BD_ADDR bd_addr, tBTM_LE_KEY_VALUE *p_le_key, tBTM_LE_ #if (BLE_PRIVACY_SPT == TRUE) if (key_type == BTM_LE_KEY_PID || key_type == BTM_LE_KEY_LID) { - btm_ble_resolving_list_load_dev (p_dev_rec); + /* It will cause that scanner doesn't send scan request to advertiser + * which has sent IRK to us and we have stored the IRK in controller. + * It is a design problem of hardware. The temporal solution is not to + * send the key to the controller and then resolve the random address in host. */ + //btm_ble_resolving_list_load_dev (p_dev_rec); } #endif @@ -1898,7 +1902,11 @@ UINT8 btm_proc_smp_cback(tSMP_EVT event, BD_ADDR bd_addr, tSMP_EVT_DATA *p_data) p_dev_rec->sec_state = BTM_SEC_STATE_IDLE; #if (defined BLE_PRIVACY_SPT && BLE_PRIVACY_SPT == TRUE) /* add all bonded device into resolving list if IRK is available*/ - btm_ble_resolving_list_load_dev(p_dev_rec); + /* It will cause that scanner doesn't send scan request to advertiser + * which has sent IRK to us and we have stored the IRK in controller. + * It is a design problem of hardware. The temporal solution is not to + * send the key to the controller and then resolve the random address in host. */ + //btm_ble_resolving_list_load_dev(p_dev_rec); #endif } diff --git a/components/bt/bluedroid/stack/include/hcidefs.h b/components/bt/bluedroid/stack/include/hcidefs.h index faf04fd9f..87dec34a0 100644 --- a/components/bt/bluedroid/stack/include/hcidefs.h +++ b/components/bt/bluedroid/stack/include/hcidefs.h @@ -1469,7 +1469,8 @@ typedef struct { #define HCI_FEATURE_SWITCH_MASK 0x20 #define HCI_FEATURE_SWITCH_OFF 0 -#define HCI_SWITCH_SUPPORTED(x) ((x)[HCI_FEATURE_SWITCH_OFF] & HCI_FEATURE_SWITCH_MASK) +// temporarily disable ROLE_SWITCH since there is an issue to be fixed +#define HCI_SWITCH_SUPPORTED(x) (0 & ((x)[HCI_FEATURE_SWITCH_OFF] & HCI_FEATURE_SWITCH_MASK)) #define HCI_FEATURE_HOLD_MODE_MASK 0x40 #define HCI_FEATURE_HOLD_MODE_OFF 0 diff --git a/components/bt/lib b/components/bt/lib index 4c88c24ce..24f923314 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit 4c88c24ce7a21bf9b95fc3d7dc9f7b99595f0189 +Subproject commit 24f923314fea8e882e430f18007aa910c879b1c6 diff --git a/components/driver/include/driver/sdmmc_host.h b/components/driver/include/driver/sdmmc_host.h index dc3e9ef6b..f2e2d66d5 100644 --- a/components/driver/include/driver/sdmmc_host.h +++ b/components/driver/include/driver/sdmmc_host.h @@ -142,6 +142,8 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz); * can call sdmmc_host_do_transaction as long as other sdmmc_host_* * functions are not called. * + * @attention Data buffer passed in cmdinfo->data must be in DMA capable memory + * * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) * @param cmdinfo pointer to structure describing command and data to transfer * @return @@ -149,6 +151,8 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz); * - ESP_ERR_TIMEOUT if response or data transfer has timed out * - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed * - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response + * - ESP_ERR_INVALID_SIZE if the size of data transfer is not valid in SD protocol + * - ESP_ERR_INVALID_ARG if the data buffer is not in DMA capable memory */ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo); diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index 8de8ee249..b84194b64 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -70,7 +70,7 @@ const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //23 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //24 {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, RTC_IO_PDAC1_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, 6}, //25 - {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, 7}, //26 + {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC2_HOLD_FORCE_M, 7}, //26 {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, RTC_IO_TOUCH_PAD7_HOLD_M, RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_M, 17}, //27 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //28 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //29 diff --git a/components/driver/sdmmc_transaction.c b/components/driver/sdmmc_transaction.c index 3adc9ce68..744a24369 100644 --- a/components/driver/sdmmc_transaction.c +++ b/components/driver/sdmmc_transaction.c @@ -20,6 +20,7 @@ #include "freertos/semphr.h" #include "soc/sdmmc_reg.h" #include "soc/sdmmc_struct.h" +#include "esp_heap_alloc_caps.h" #include "driver/sdmmc_types.h" #include "driver/sdmmc_defs.h" #include "driver/sdmmc_host.h" @@ -105,9 +106,16 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo) // convert cmdinfo to hardware register value sdmmc_hw_cmd_t hw_cmd = make_hw_cmd(cmdinfo); if (cmdinfo->data) { - // these constraints should be handled by upper layer - assert(cmdinfo->datalen >= 4); - assert(cmdinfo->blklen % 4 == 0); + if (cmdinfo->datalen < 4 || cmdinfo->blklen % 4 != 0) { + ESP_LOGD(TAG, "%s: invalid size: total=%d block=%d", + __func__, cmdinfo->datalen, cmdinfo->blklen); + return ESP_ERR_INVALID_SIZE; + } + if ((intptr_t) cmdinfo->data % 4 != 0 || + !esp_ptr_dma_capable(cmdinfo->data)) { + ESP_LOGD(TAG, "%s: buffer %p can not be used for DMA", __func__, cmdinfo->data); + return ESP_ERR_INVALID_ARG; + } // this clears "owned by IDMAC" bits memset(s_dma_desc, 0, sizeof(s_dma_desc)); // initialize first descriptor diff --git a/components/driver/test/test_spi_master.c b/components/driver/test/test_spi_master.c index 86eea5cd4..027775fea 100644 --- a/components/driver/test/test_spi_master.c +++ b/components/driver/test/test_spi_master.c @@ -259,3 +259,64 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi][ignore]") { destroy_spi_bus(handle1); } +TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)", "[spi]") +{ + //spi config + spi_bus_config_t bus_config; + spi_device_interface_config_t device_config; + spi_device_handle_t spi; + spi_host_device_t host; + int dma = 1; + + memset(&bus_config, 0, sizeof(spi_bus_config_t)); + memset(&device_config, 0, sizeof(spi_device_interface_config_t)); + + bus_config.miso_io_num = -1; + bus_config.mosi_io_num = 26; + bus_config.sclk_io_num = 25; + bus_config.quadwp_io_num = -1; + bus_config.quadhd_io_num = -1; + + device_config.clock_speed_hz = 50000; + device_config.mode = 0; + device_config.spics_io_num = -1; + device_config.queue_size = 1; + device_config.flags = SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST; + + struct spi_transaction_t transaction = { + .flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA, + .length = 16, + .tx_buffer = NULL, + .rx_buffer = NULL, + .tx_data = {0x04, 0x00} + }; + + + //initialize for first host + host = 1; + + assert(spi_bus_initialize(host, &bus_config, dma) == ESP_OK); + assert(spi_bus_add_device(host, &device_config, &spi) == ESP_OK); + + printf("before first xmit\n"); + assert(spi_device_transmit(spi, &transaction) == ESP_OK); + printf("after first xmit\n"); + + assert(spi_bus_remove_device(spi) == ESP_OK); + assert(spi_bus_free(host) == ESP_OK); + + + //for second host and failed before + host = 2; + + assert(spi_bus_initialize(host, &bus_config, dma) == ESP_OK); + assert(spi_bus_add_device(host, &device_config, &spi) == ESP_OK); + + printf("before second xmit\n"); + // the original version (bit mis-written) stucks here. + assert(spi_device_transmit(spi, &transaction) == ESP_OK); + // test case success when see this. + printf("after second xmit\n"); + + +} diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index 473c43325..03ea68236 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -185,3 +185,12 @@ void esp_dport_access_int_deinit(void) #endif portEXIT_CRITICAL_ISR(&g_dport_mux); } + + +void esp_dport_access_int_abort(void) +{ + dport_core_state[0] = DPORT_CORE_STATE_IDLE; +#ifndef CONFIG_FREERTOS_UNICORE + dport_core_state[1] = DPORT_CORE_STATE_IDLE; +#endif +} diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 8b081c5ae..220516309 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/components/esp32/include/esp_dport_access.h @@ -23,6 +23,7 @@ void esp_dport_access_stall_other_cpu_start(void); void esp_dport_access_stall_other_cpu_end(void); void esp_dport_access_int_init(void); void esp_dport_access_int_deinit(void); +void esp_dport_access_int_abort(void); #if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() diff --git a/components/esp32/include/esp_phy_init.h b/components/esp32/include/esp_phy_init.h index 347d8acac..f6cea9242 100644 --- a/components/esp32/include/esp_phy_init.h +++ b/components/esp32/include/esp_phy_init.h @@ -30,112 +30,7 @@ extern "C" { * @brief Structure holding PHY init parameters */ typedef struct { - uint8_t param_ver_id; /*!< init_data structure version */ - uint8_t crystal_select; /*!< 0: 40MHz, 1: 26 MHz, 2: 24 MHz, 3: auto */ - uint8_t wifi_rx_gain_swp_step_1; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_2; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_3; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_4; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_5; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_6; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_7; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_8; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_9; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_10; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_11; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_12; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_13; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_14; /*!< do not change */ - uint8_t wifi_rx_gain_swp_step_15; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_1; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_2; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_3; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_4; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_5; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_6; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_7; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_8; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_9; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_10; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_11; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_12; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_13; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_14; /*!< do not change */ - uint8_t bt_rx_gain_swp_step_15; /*!< do not change */ - uint8_t gain_cmp_1; /*!< do not change */ - uint8_t gain_cmp_6; /*!< do not change */ - uint8_t gain_cmp_11; /*!< do not change */ - uint8_t gain_cmp_ext2_1; /*!< do not change */ - uint8_t gain_cmp_ext2_6; /*!< do not change */ - uint8_t gain_cmp_ext2_11; /*!< do not change */ - uint8_t gain_cmp_ext3_1; /*!< do not change */ - uint8_t gain_cmp_ext3_6; /*!< do not change */ - uint8_t gain_cmp_ext3_11; /*!< do not change */ - uint8_t gain_cmp_bt_ofs_1; /*!< do not change */ - uint8_t gain_cmp_bt_ofs_6; /*!< do not change */ - uint8_t gain_cmp_bt_ofs_11; /*!< do not change */ - uint8_t target_power_qdb_0; /*!< 78 means target power is 78/4=19.5dbm */ - uint8_t target_power_qdb_1; /*!< 76 means target power is 76/4=19dbm */ - uint8_t target_power_qdb_2; /*!< 74 means target power is 74/4=18.5dbm */ - uint8_t target_power_qdb_3; /*!< 68 means target power is 68/4=17dbm */ - uint8_t target_power_qdb_4; /*!< 64 means target power is 64/4=16dbm */ - uint8_t target_power_qdb_5; /*!< 52 means target power is 52/4=13dbm */ - uint8_t target_power_index_mcs0; /*!< target power index is 0, means target power is target_power_qdb_0 19.5dbm; (1m,2m,5.5m,11m,6m,9m) */ - uint8_t target_power_index_mcs1; /*!< target power index is 0, means target power is target_power_qdb_0 19.5dbm; (12m) */ - uint8_t target_power_index_mcs2; /*!< target power index is 1, means target power is target_power_qdb_1 19dbm; (18m) */ - uint8_t target_power_index_mcs3; /*!< target power index is 1, means target power is target_power_qdb_1 19dbm; (24m) */ - uint8_t target_power_index_mcs4; /*!< target power index is 2, means target power is target_power_qdb_2 18.5dbm; (36m) */ - uint8_t target_power_index_mcs5; /*!< target power index is 3, means target power is target_power_qdb_3 17dbm; (48m) */ - uint8_t target_power_index_mcs6; /*!< target power index is 4, means target power is target_power_qdb_4 16dbm; (54m) */ - uint8_t target_power_index_mcs7; /*!< target power index is 5, means target power is target_power_qdb_5 13dbm */ - uint8_t pwr_ind_11b_en; /*!< 0: 11b power is same as mcs0 and 6m, 1: 11b power different with OFDM */ - uint8_t pwr_ind_11b_0; /*!< 1m, 2m power index [0~5] */ - uint8_t pwr_ind_11b_1; /*!< 5.5m, 11m power index [0~5] */ - uint8_t chan_backoff_en; /*!< 0: channel backoff disable, 1:channel backoff enable */ - uint8_t chan1_power_backoff_qdb; /*!< 4 means backoff is 1db */ - uint8_t chan2_power_backoff_qdb; /*!< see chan1_power_backoff_qdb */ - uint8_t chan3_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan4_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan5_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan6_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan7_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan8_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan9_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan10_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan11_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan12_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan13_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan14_power_backoff_qdb; /*!< chan1_power_backoff_qdb */ - uint8_t chan1_rate_backoff_index; /*!< if bit i is set, backoff data rate is target_power_qdb_i */ - uint8_t chan2_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan3_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan4_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan5_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan6_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan7_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan8_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan9_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan10_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan11_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan12_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan13_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t chan14_rate_backoff_index; /*!< see chan1_rate_backoff_index */ - uint8_t spur_freq_cfg_msb_1; /*!< first spur: */ - uint8_t spur_freq_cfg_1; /*!< spur_freq_cfg = (spur_freq_cfg_msb_1 <<8) | spur_freq_cfg_1 */ - uint8_t spur_freq_cfg_div_1; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_1 */ - uint8_t spur_freq_en_h_1; /*!< the seventh bit for total enable */ - uint8_t spur_freq_en_l_1; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority */ - uint8_t spur_freq_cfg_msb_2; /*!< second spur: */ - uint8_t spur_freq_cfg_2; /*!< spur_freq_cfg = (spur_freq_cfg_msb_2 <<8) | spur_freq_cfg_2 */ - uint8_t spur_freq_cfg_div_2; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_2 */ - uint8_t spur_freq_en_h_2; /*!< the seventh bit for total enable */ - uint8_t spur_freq_en_l_2; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority */ - uint8_t spur_freq_cfg_msb_3; /*!< third spur: */ - uint8_t spur_freq_cfg_3; /*!< spur_freq_cfg = (spur_freq_cfg_msb_3 <<8) | spur_freq_cfg_3 */ - uint8_t spur_freq_cfg_div_3; /*!< spur_freq=spur_freq_cfg/spur_freq_cfg_div_3 */ - uint8_t spur_freq_en_h_3; /*!< the seventh bit for total enable */ - uint8_t spur_freq_en_l_3; /*!< each bit for 1 channel, and use [spur_freq_en_h, spur_freq_en_l] to select the spur's channel priority, */ - uint8_t reserved[23]; /*!< reserved for future expansion */ + uint8_t params[128]; /*!< opaque PHY initialization parameters */ } esp_phy_init_data_t; /** diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h index 81fa26c23..8f075392c 100644 --- a/components/esp32/include/rom/uart.h +++ b/components/esp32/include/rom/uart.h @@ -267,7 +267,7 @@ void uart_tx_flush(uint8_t uart_no); * The function defined in ROM code has a bug, so we define the correct version * here for compatibility. */ -static inline void uart_tx_wait_idle(uint8_t uart_no) { +static inline void IRAM_ATTR uart_tx_wait_idle(uint8_t uart_no) { while(REG_GET_FIELD(UART_STATUS_REG(uart_no), UART_ST_UTX_OUT)) { ; } diff --git a/components/esp32/ld/esp32.rom.ld b/components/esp32/ld/esp32.rom.ld index 6961854b4..7c228d725 100644 --- a/components/esp32/ld/esp32.rom.ld +++ b/components/esp32/ld/esp32.rom.ld @@ -432,6 +432,8 @@ PROVIDE ( r_ea_interval_delete = 0x400155a8 ); PROVIDE ( r_ea_interval_duration_req = 0x4001597c ); PROVIDE ( r_ea_interval_insert = 0x4001557c ); PROVIDE ( r_ea_interval_remove = 0x40015590 ); +PROVIDE ( ea_conflict_check = 0x40014e9c ); +PROVIDE ( ea_prog_timer = 0x40014f88 ); PROVIDE ( realloc = 0x4000becc ); PROVIDE ( _realloc_r = 0x4000bbe0 ); PROVIDE ( r_ea_offset_req = 0x40015748 ); @@ -1855,6 +1857,7 @@ PROVIDE ( ets_update_cpu_frequency_rom = 0x40008550 ); /* Updates g_ticks_per_u /* Following are static data, but can be used, not generated by script <<<<< btdm data */ PROVIDE ( hci_tl_env = 0x3ffb8154 ); PROVIDE ( ld_acl_env = 0x3ffb8258 ); +PROVIDE ( ea_env = 0x3ffb80ec ); PROVIDE ( ld_active_ch_map = 0x3ffb8334 ); PROVIDE ( ld_bcst_acl_env = 0x3ffb8274 ); PROVIDE ( ld_csb_rx_env = 0x3ffb8278 ); diff --git a/components/esp32/lib b/components/esp32/lib index f6701dcdd..a682a5b42 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit f6701dcdd52625ba3d84d27df0dd2d95e7891921 +Subproject commit a682a5b42af894a270e66f0c789d015fbdb4516e diff --git a/components/esp32/phy_init_data.h b/components/esp32/phy_init_data.h index ea6a761b3..0315519a5 100644 --- a/components/esp32/phy_init_data.h +++ b/components/esp32/phy_init_data.h @@ -26,114 +26,115 @@ static const char phy_init_magic_pre[] = PHY_INIT_MAGIC; /** * @brief Structure containing default recommended PHY initialization parameters. */ -static const esp_phy_init_data_t phy_init_data= { - .param_ver_id = 1, - .crystal_select = 3, - .wifi_rx_gain_swp_step_1 = 0x05, - .wifi_rx_gain_swp_step_2 = 0x04, - .wifi_rx_gain_swp_step_3 = 0x06, - .wifi_rx_gain_swp_step_4 = 0x05, - .wifi_rx_gain_swp_step_5 = 0x01, - .wifi_rx_gain_swp_step_6 = 0x06, - .wifi_rx_gain_swp_step_7 = 0x05, - .wifi_rx_gain_swp_step_8 = 0x04, - .wifi_rx_gain_swp_step_9 = 0x06, - .wifi_rx_gain_swp_step_10 = 0x04, - .wifi_rx_gain_swp_step_11 = 0x05, - .wifi_rx_gain_swp_step_12 = 0x00, - .wifi_rx_gain_swp_step_13 = 0x00, - .wifi_rx_gain_swp_step_14 = 0x00, - .wifi_rx_gain_swp_step_15 = 0x00, - .bt_rx_gain_swp_step_1 = 0x05, - .bt_rx_gain_swp_step_2 = 0x04, - .bt_rx_gain_swp_step_3 = 0x06, - .bt_rx_gain_swp_step_4 = 0x05, - .bt_rx_gain_swp_step_5 = 0x01, - .bt_rx_gain_swp_step_6 = 0x06, - .bt_rx_gain_swp_step_7 = 0x05, - .bt_rx_gain_swp_step_8 = 0x00, - .bt_rx_gain_swp_step_9 = 0x00, - .bt_rx_gain_swp_step_10 = 0x00, - .bt_rx_gain_swp_step_11 = 0x00, - .bt_rx_gain_swp_step_12 = 0x00, - .bt_rx_gain_swp_step_13 = 0x00, - .bt_rx_gain_swp_step_14 = 0x00, - .bt_rx_gain_swp_step_15 = 0x00, - .gain_cmp_1 = 0x0a, - .gain_cmp_6 = 0x0a, - .gain_cmp_11 = 0x0c, - .gain_cmp_ext2_1 = 0xf0, - .gain_cmp_ext2_6 = 0xf0, - .gain_cmp_ext2_11 = 0xf0, - .gain_cmp_ext3_1 = 0xe0, - .gain_cmp_ext3_6 = 0xe0, - .gain_cmp_ext3_11 = 0xe0, - .gain_cmp_bt_ofs_1 = 0x18, - .gain_cmp_bt_ofs_6 = 0x18, - .gain_cmp_bt_ofs_11 = 0x18, - .target_power_qdb_0 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 78), - .target_power_qdb_1 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 76), - .target_power_qdb_2 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 74), - .target_power_qdb_3 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 68), - .target_power_qdb_4 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 60), - .target_power_qdb_5 = LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 52), - .target_power_index_mcs0 = 0, - .target_power_index_mcs1 = 0, - .target_power_index_mcs2 = 1, - .target_power_index_mcs3 = 1, - .target_power_index_mcs4 = 2, - .target_power_index_mcs5 = 3, - .target_power_index_mcs6 = 4, - .target_power_index_mcs7 = 5, - .pwr_ind_11b_en = 0, - .pwr_ind_11b_0 = 0, - .pwr_ind_11b_1 = 0, - .chan_backoff_en = 0, - .chan1_power_backoff_qdb = 0, - .chan2_power_backoff_qdb = 0, - .chan3_power_backoff_qdb = 0, - .chan4_power_backoff_qdb = 0, - .chan5_power_backoff_qdb = 0, - .chan6_power_backoff_qdb = 0, - .chan7_power_backoff_qdb = 0, - .chan8_power_backoff_qdb = 0, - .chan9_power_backoff_qdb = 0, - .chan10_power_backoff_qdb = 0, - .chan11_power_backoff_qdb = 0, - .chan12_power_backoff_qdb = 0, - .chan13_power_backoff_qdb = 0, - .chan14_power_backoff_qdb = 0, - .chan1_rate_backoff_index = 0, - .chan2_rate_backoff_index = 0, - .chan3_rate_backoff_index = 0, - .chan4_rate_backoff_index = 0, - .chan5_rate_backoff_index = 0, - .chan6_rate_backoff_index = 0, - .chan7_rate_backoff_index = 0, - .chan8_rate_backoff_index = 0, - .chan9_rate_backoff_index = 0, - .chan10_rate_backoff_index = 0, - .chan11_rate_backoff_index = 0, - .chan12_rate_backoff_index = 0, - .chan13_rate_backoff_index = 0, - .chan14_rate_backoff_index = 0, - .spur_freq_cfg_msb_1 = 0, - .spur_freq_cfg_1 = 0, - .spur_freq_cfg_div_1 = 0, - .spur_freq_en_h_1 = 0, - .spur_freq_en_l_1 = 0, - .spur_freq_cfg_msb_2 = 0, - .spur_freq_cfg_2 = 0, - .spur_freq_cfg_div_2 = 0, - .spur_freq_en_h_2 = 0, - .spur_freq_en_l_2 = 0, - .spur_freq_cfg_msb_3 = 0, - .spur_freq_cfg_3 = 0, - .spur_freq_cfg_div_3 = 0, - .spur_freq_en_h_3 = 0, - .spur_freq_en_l_3 = 0, - .reserved = {0} -}; +static const esp_phy_init_data_t phy_init_data= { { + 3, + 3, + 0x05, + 0x09, + 0x06, + 0x05, + 0x03, + 0x06, + 0x05, + 0x04, + 0x06, + 0x04, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x05, + 0x09, + 0x06, + 0x05, + 0x03, + 0x06, + 0x05, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0xfc, + 0xfc, + 0xfe, + 0xf0, + 0xf0, + 0xf0, + 0xe0, + 0xe0, + 0xe0, + 0x18, + 0x18, + 0x18, + LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 78), + LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 72), + LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 66), + LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 60), + LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 56), + LIMIT(CONFIG_ESP32_PHY_MAX_TX_POWER * 4, 0, 52), + 0, + 1, + 1, + 2, + 2, + 3, + 4, + 5, + 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 const char phy_init_magic_post[] = PHY_INIT_MAGIC; diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index c79761fd7..4d7beb55e 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -256,22 +256,31 @@ void IRAM_ATTR esp_restart(void) */ void IRAM_ATTR esp_restart_noos() { - const uint32_t core_id = xPortGetCoreID(); - const uint32_t other_core_id = core_id == 0 ? 1 : 0; - esp_cpu_stall(other_core_id); + // Disable interrupts + xt_ints_off(0xFFFFFFFF); - // other core is now stalled, can access DPORT registers directly - esp_dport_access_int_deinit(); - - // We need to disable TG0/TG1 watchdogs - // First enable RTC watchdog to be on the safe side + // 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, 128000); + // 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 = xPortGetCoreID(); + 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; @@ -280,8 +289,6 @@ void IRAM_ATTR esp_restart_noos() TIMERG1.wdt_config0.en = 0; TIMERG1.wdt_wprotect=0; - // Disable all interrupts - xt_ints_off(0xFFFFFFFF); // Disable cache Cache_Read_Disable(0); @@ -291,6 +298,14 @@ void IRAM_ATTR esp_restart_noos() uart_tx_wait_idle(0); uart_tx_wait_idle(1); uart_tx_wait_idle(2); + // 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, @@ -314,14 +329,14 @@ void IRAM_ATTR esp_restart_noos() // Reset CPUs if (core_id == 0) { // Running on PRO CPU: APP CPU is stalled. Can reset both CPUs. - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, - RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M); + 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 - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M); + esp_cpu_reset(0); esp_cpu_unstall(0); - SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_APPCPU_RST_M); + esp_cpu_reset(1); } while(true) { ; @@ -364,8 +379,10 @@ static void get_chip_info_esp32(esp_chip_info_t* out_info) if ((reg & EFUSE_RD_CHIP_VER_DIS_BT_M) == 0) { out_info->features |= CHIP_FEATURE_BT | CHIP_FEATURE_BLE; } - if (((reg & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S) == - EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5) { + int package = (reg & EFUSE_RD_CHIP_VER_PKG_M) >> EFUSE_RD_CHIP_VER_PKG_S; + if (package == EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 || + package == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 || + package == EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4) { out_info->features |= CHIP_FEATURE_EMB_FLASH; } } diff --git a/components/freertos/FreeRTOS-openocd.c b/components/freertos/FreeRTOS-openocd.c index d74564495..2367d8273 100644 --- a/components/freertos/FreeRTOS-openocd.c +++ b/components/freertos/FreeRTOS-openocd.c @@ -10,6 +10,7 @@ */ #include "FreeRTOS.h" +#include "esp_attr.h" #include "sdkconfig.h" #ifdef __GNUC__ @@ -19,5 +20,5 @@ #endif #ifdef CONFIG_ESP32_DEBUG_OCDAWARE -const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1; -#endif \ No newline at end of file +const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1; +#endif diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index d62ce01b7..d6afa3074 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -214,7 +214,7 @@ BaseType_t xPortInIsrContext(); #endif /* Multi-core: get current core ID */ -static inline uint32_t xPortGetCoreID() { +static inline uint32_t IRAM_ATTR xPortGetCoreID() { int id; asm volatile( "rsr.prid %0\n" diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index 00db60c91..e10c733d5 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -121,6 +121,7 @@ typedef unsigned portBASE_TYPE UBaseType_t; #include "portbenchmark.h" #include "sdkconfig.h" +#include "esp_attr.h" #define portFIRST_TASK_HOOK CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index e49b8e5ef..ec4322df8 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -337,7 +337,7 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { uint8_t *data=(uint8_t*)item; configASSERT(((int)rb->free_ptr&3)==0); configASSERT(data >= rb->data); - configASSERT(data < rb->data+rb->size); + configASSERT(data <= rb->data+rb->size); //Grab the buffer entry that preceeds the buffer buf_entry_hdr_t *hdr=(buf_entry_hdr_t*)(data-sizeof(buf_entry_hdr_t)); configASSERT(hdr->len < rb->size); diff --git a/components/freertos/test/test_ringbuf.c b/components/freertos/test/test_ringbuf.c index bb8fc7253..ac2e88fe5 100644 --- a/components/freertos/test/test_ringbuf.c +++ b/components/freertos/test/test_ringbuf.c @@ -195,3 +195,26 @@ TEST_CASE("FreeRTOS ringbuffer test, w/ splitting items", "[freertos][ignore]") testRingbuffer(1); } + +TEST_CASE("FreeRTOS ringbuffer test, check if zero-length items are handled correctly", "[freertos]") +{ + rb = xRingbufferCreate(32, 0); + int r; + void *v; + size_t sz; + for (int x=0; x<128; x++) { + if (x!=127) { + //Send an item + r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS); + assert(r==pdTRUE); + } + if (x!=0) { + //Receive an item + v=xRingbufferReceive(rb, &sz, 10000 / portTICK_PERIOD_MS); + assert(sz==0); + vRingbufferReturnItem(rb, v); //actually not needed for NULL data... + } + } + vRingbufferDelete(rb); +} + diff --git a/components/lwip/port/freertos/sys_arch.c b/components/lwip/port/freertos/sys_arch.c index b03fd6df5..68a12c4bf 100755 --- a/components/lwip/port/freertos/sys_arch.c +++ b/components/lwip/port/freertos/sys_arch.c @@ -446,7 +446,7 @@ sys_jiffies(void) u32_t sys_now(void) { - return xTaskGetTickCount(); + return (xTaskGetTickCount() * portTICK_PERIOD_MS); } /* diff --git a/components/nghttp/component.mk b/components/nghttp/component.mk index e9148acc9..2a69cd5e1 100644 --- a/components/nghttp/component.mk +++ b/components/nghttp/component.mk @@ -4,9 +4,6 @@ COMPONENT_ADD_INCLUDEDIRS := port/include nghttp2/lib/includes -COMPONENT_SRCDIRS := nghttp2/lib +COMPONENT_SRCDIRS := nghttp2/lib port -# nghttp2_session.c uses assert(0) in place of abort() in some functions, -# that miss a return statement if assertions are disabled. -# So it always needs assertions to be enabled -nghttp2/lib/nghttp2_session.o: CPPFLAGS := $(filter-out -DNDEBUG,$(CPPFLAGS)) +COMPONENT_SUBMODULES := nghttp2 diff --git a/components/nghttp/nghttp2 b/components/nghttp/nghttp2 index 2f146e4d4..3bcc416e1 160000 --- a/components/nghttp/nghttp2 +++ b/components/nghttp/nghttp2 @@ -1 +1 @@ -Subproject commit 2f146e4d4cfe895d65599b87df7d847435f0e1b4 +Subproject commit 3bcc416e13cc790e2fb45fcfe9111d38609c5032 diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 8f562dca4..11dcb17d1 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -577,6 +577,17 @@ esp_err_t Page::mLoadEntryTable() } mHashList.insert(item, i); + + if (item.crc32 != item.calculateCrc32()) { + err = eraseEntryAndSpan(i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + continue; + } + + assert(item.span > 0); size_t span = item.span; i += span - 1; diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index 22d4c3b70..d4ec585ed 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -1096,6 +1096,44 @@ TEST_CASE("recovery after failure to write data", "[nvs]") } } +TEST_CASE("crc errors in item header are handled", "[nvs]") +{ + SpiFlashEmulator emu(3); + Storage storage; + // prepare some data + TEST_ESP_OK(storage.init(0, 3)); + TEST_ESP_OK(storage.writeItem(0, "ns1", static_cast(1))); + TEST_ESP_OK(storage.writeItem(1, "value1", static_cast(1))); + TEST_ESP_OK(storage.writeItem(1, "value2", static_cast(2))); + + // corrupt item header + uint32_t val = 0; + emu.write(32 * 3, &val, 4); + + // check that storage can recover + TEST_ESP_OK(storage.init(0, 3)); + TEST_ESP_OK(storage.readItem(1, "value2", val)); + CHECK(val == 2); + // check that the corrupted item is no longer present + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, storage.readItem(1, "value1", val)); + + // add more items to make the page full + for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { + char item_name[Item::MAX_KEY_LENGTH + 1]; + snprintf(item_name, sizeof(item_name), "item_%ld", i); + TEST_ESP_OK(storage.writeItem(1, item_name, static_cast(i))); + } + + // corrupt another item on the full page + val = 0; + emu.write(32 * 4, &val, 4); + + // check that storage can recover + TEST_ESP_OK(storage.init(0, 3)); + // check that the corrupted item is no longer present + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, storage.readItem(1, "value2", val)); +} + TEST_CASE("crc error in variable length item is handled", "[nvs]") { SpiFlashEmulator emu(3); diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 659ff5dd6..85791ab27 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -46,6 +46,10 @@ static esp_err_t sdmmc_send_cmd_set_bus_width(sdmmc_card_t* card, int width); static esp_err_t sdmmc_send_cmd_stop_transmission(sdmmc_card_t* card, uint32_t* status); static esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status); static uint32_t get_host_ocr(float voltage); +static esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, + size_t start_block, size_t block_count); +static esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, + size_t start_block, size_t block_count); esp_err_t sdmmc_card_init(const sdmmc_host_t* config, @@ -486,6 +490,37 @@ static esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_st esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, size_t start_block, size_t block_count) +{ + esp_err_t err = ESP_OK; + size_t block_size = card->csd.sector_size; + if (esp_ptr_dma_capable(src) && (intptr_t)src % 4 == 0) { + err = sdmmc_write_sectors_dma(card, src, start_block, block_count); + } else { + // SDMMC peripheral needs DMA-capable buffers. Split the write into + // separate single block writes, if needed, and allocate a temporary + // DMA-capable buffer. + void* tmp_buf = pvPortMallocCaps(block_size, MALLOC_CAP_DMA); + if (tmp_buf == NULL) { + return ESP_ERR_NO_MEM; + } + const uint8_t* cur_src = (const uint8_t*) src; + for (size_t i = 0; i < block_count; ++i) { + memcpy(tmp_buf, cur_src, block_size); + cur_src += block_size; + err = sdmmc_write_sectors_dma(card, tmp_buf, start_block + i, 1); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d", + __func__, err, start_block, i); + break; + } + } + free(tmp_buf); + } + return err; +} + +static esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, + size_t start_block, size_t block_count) { if (start_block + block_count > card->csd.capacity) { return ESP_ERR_INVALID_SIZE; @@ -529,6 +564,37 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst, size_t start_block, size_t block_count) +{ + esp_err_t err = ESP_OK; + size_t block_size = card->csd.sector_size; + if (esp_ptr_dma_capable(dst) && (intptr_t)dst % 4 == 0) { + err = sdmmc_read_sectors_dma(card, dst, start_block, block_count); + } else { + // SDMMC peripheral needs DMA-capable buffers. Split the read into + // separate single block reads, if needed, and allocate a temporary + // DMA-capable buffer. + void* tmp_buf = pvPortMallocCaps(block_size, MALLOC_CAP_DMA); + if (tmp_buf == NULL) { + return ESP_ERR_NO_MEM; + } + uint8_t* cur_dst = (uint8_t*) dst; + for (size_t i = 0; i < block_count; ++i) { + err = sdmmc_read_sectors_dma(card, tmp_buf, start_block + i, 1); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d", + __func__, err, start_block, i); + break; + } + memcpy(cur_dst, tmp_buf, block_size); + cur_dst += block_size; + } + free(tmp_buf); + } + return err; +} + +static esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, + size_t start_block, size_t block_count) { if (start_block + block_count > card->csd.capacity) { return ESP_ERR_INVALID_SIZE; diff --git a/components/sdmmc/test/test_sd.c b/components/sdmmc/test/test_sd.c index 768fecc25..c0613326d 100644 --- a/components/sdmmc/test/test_sd.c +++ b/components/sdmmc/test/test_sd.c @@ -41,38 +41,59 @@ TEST_CASE("can probe SD", "[sd][ignore]") } +// Fill buffer pointed to by 'dst' with 'count' 32-bit ints generated +// from 'rand' with the starting value of 'seed' +static void fill_buffer(uint32_t seed, uint8_t* dst, size_t count) { + srand(seed); + for (size_t i = 0; i < count; ++i) { + uint32_t val = rand(); + memcpy(dst + i * sizeof(uint32_t), &val, sizeof(val)); + } +} + +// Check if the buffer pointed to by 'dst' contains 'count' 32-bit +// ints generated from 'rand' with the starting value of 'seed' +static void check_buffer(uint32_t seed, const uint8_t* src, size_t count) { + srand(seed); + for (size_t i = 0; i < count; ++i) { + uint32_t val; + memcpy(&val, src + i * sizeof(uint32_t), sizeof(val)); + TEST_ASSERT_EQUAL_HEX32(rand(), val); + } +} + static void do_single_write_read_test(sdmmc_card_t* card, - size_t start_block, size_t block_count) + size_t start_block, size_t block_count, size_t alignment) { size_t block_size = card->csd.sector_size; size_t total_size = block_size * block_count; - printf(" %8d | %3d | %4.1f ", start_block, block_count, total_size / 1024.0f); - uint32_t* buffer = pvPortMallocCaps(total_size, MALLOC_CAP_DMA); - srand(start_block); - for (size_t i = 0; i < total_size / sizeof(buffer[0]); ++i) { - buffer[i] = rand(); - } + printf(" %8d | %3d | %d | %4.1f ", start_block, block_count, alignment, total_size / 1024.0f); + + uint32_t* buffer = pvPortMallocCaps(total_size + 4, MALLOC_CAP_DMA); + size_t offset = alignment % 4; + uint8_t* c_buffer = (uint8_t*) buffer + offset; + fill_buffer(start_block, c_buffer, total_size / sizeof(buffer[0])); + struct timeval t_start_wr; gettimeofday(&t_start_wr, NULL); - TEST_ESP_OK(sdmmc_write_sectors(card, buffer, start_block, block_count)); + TEST_ESP_OK(sdmmc_write_sectors(card, c_buffer, start_block, block_count)); struct timeval t_stop_wr; gettimeofday(&t_stop_wr, NULL); float time_wr = 1e3f * (t_stop_wr.tv_sec - t_start_wr.tv_sec) + 1e-3f * (t_stop_wr.tv_usec - t_start_wr.tv_usec); - memset(buffer, 0xbb, total_size); + + memset(buffer, 0xbb, total_size + 4); + struct timeval t_start_rd; gettimeofday(&t_start_rd, NULL); - TEST_ESP_OK(sdmmc_read_sectors(card, buffer, start_block, block_count)); + TEST_ESP_OK(sdmmc_read_sectors(card, c_buffer, start_block, block_count)); struct timeval t_stop_rd; gettimeofday(&t_stop_rd, NULL); float time_rd = 1e3f * (t_stop_rd.tv_sec - t_start_rd.tv_sec) + 1e-3f * (t_stop_rd.tv_usec - t_start_rd.tv_usec); - printf(" | %6.2f | %.2f | %.2fs | %.2f\n", + printf(" | %6.2f | %5.2f | %6.2f | %5.2f\n", time_wr, total_size / (time_wr / 1000) / (1024 * 1024), time_rd, total_size / (time_rd / 1000) / (1024 * 1024)); - srand(start_block); - for (size_t i = 0; i < total_size / sizeof(buffer[0]); ++i) { - TEST_ASSERT_EQUAL_HEX32(rand(), buffer[i]); - } + check_buffer(start_block, c_buffer, total_size / sizeof(buffer[0])); free(buffer); } @@ -87,23 +108,61 @@ TEST_CASE("can write and read back blocks", "[sd][ignore]") TEST_ASSERT_NOT_NULL(card); TEST_ESP_OK(sdmmc_card_init(&config, card)); sdmmc_card_print_info(stdout, card); - printf(" sector | count | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); - do_single_write_read_test(card, 0, 1); - do_single_write_read_test(card, 0, 4); - do_single_write_read_test(card, 1, 16); - do_single_write_read_test(card, 16, 32); - do_single_write_read_test(card, 48, 64); - do_single_write_read_test(card, 128, 128); - do_single_write_read_test(card, card->csd.capacity - 64, 32); - do_single_write_read_test(card, card->csd.capacity - 64, 64); - do_single_write_read_test(card, card->csd.capacity - 8, 1); - do_single_write_read_test(card, card->csd.capacity/2, 1); - do_single_write_read_test(card, card->csd.capacity/2, 4); - do_single_write_read_test(card, card->csd.capacity/2, 8); - do_single_write_read_test(card, card->csd.capacity/2, 16); - do_single_write_read_test(card, card->csd.capacity/2, 32); - do_single_write_read_test(card, card->csd.capacity/2, 64); - do_single_write_read_test(card, card->csd.capacity/2, 128); + printf(" sector | count | align | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); + do_single_write_read_test(card, 0, 1, 4); + do_single_write_read_test(card, 0, 4, 4); + do_single_write_read_test(card, 1, 16, 4); + do_single_write_read_test(card, 16, 32, 4); + do_single_write_read_test(card, 48, 64, 4); + do_single_write_read_test(card, 128, 128, 4); + do_single_write_read_test(card, card->csd.capacity - 64, 32, 4); + do_single_write_read_test(card, card->csd.capacity - 64, 64, 4); + do_single_write_read_test(card, card->csd.capacity - 8, 1, 4); + do_single_write_read_test(card, card->csd.capacity/2, 1, 4); + do_single_write_read_test(card, card->csd.capacity/2, 4, 4); + do_single_write_read_test(card, card->csd.capacity/2, 8, 4); + do_single_write_read_test(card, card->csd.capacity/2, 16, 4); + do_single_write_read_test(card, card->csd.capacity/2, 32, 4); + do_single_write_read_test(card, card->csd.capacity/2, 64, 4); + do_single_write_read_test(card, card->csd.capacity/2, 128, 4); + do_single_write_read_test(card, card->csd.capacity/2, 1, 1); + do_single_write_read_test(card, card->csd.capacity/2, 8, 1); + do_single_write_read_test(card, card->csd.capacity/2, 128, 1); free(card); sdmmc_host_deinit(); } + +TEST_CASE("reads and writes with an unaligned buffer", "[sd][ignore]") +{ + sdmmc_host_t config = SDMMC_HOST_DEFAULT(); + TEST_ESP_OK(sdmmc_host_init()); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config)); + sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t)); + TEST_ASSERT_NOT_NULL(card); + TEST_ESP_OK(sdmmc_card_init(&config, card)); + + const size_t buffer_size = 4096; + const size_t block_count = buffer_size / 512; + const size_t extra = 4; + uint8_t* buffer = pvPortMallocCaps(buffer_size + extra, MALLOC_CAP_DMA); + + // Check read behavior: do aligned write, then unaligned read + const uint32_t seed = 0x89abcdef; + fill_buffer(seed, buffer, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, buffer, 0, block_count)); + memset(buffer, 0xcc, buffer_size + extra); + TEST_ESP_OK(sdmmc_read_sectors(card, buffer + 1, 0, block_count)); + check_buffer(seed, buffer + 1, buffer_size / sizeof(uint32_t)); + + // Check write behavior: do unaligned write, then aligned read + fill_buffer(seed, buffer + 1, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, buffer + 1, 8, block_count)); + memset(buffer, 0xcc, buffer_size + extra); + TEST_ESP_OK(sdmmc_read_sectors(card, buffer, 8, block_count)); + check_buffer(seed, buffer, buffer_size / sizeof(uint32_t)); + + free(buffer); + free(card); + TEST_ESP_OK(sdmmc_host_deinit()); +} diff --git a/components/soc/esp32/cpu_util.c b/components/soc/esp32/cpu_util.c index ecfcab4ba..bc052af98 100644 --- a/components/soc/esp32/cpu_util.c +++ b/components/soc/esp32/cpu_util.c @@ -44,6 +44,12 @@ void IRAM_ATTR esp_cpu_unstall(int cpu_id) } } +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() { #if CONFIG_ESP32_DEBUG_OCDAWARE diff --git a/components/soc/esp32/include/soc/cpu.h b/components/soc/esp32/include/soc/cpu.h index b56fb3dc8..05ec91776 100644 --- a/components/soc/esp32/include/soc/cpu.h +++ b/components/soc/esp32/include/soc/cpu.h @@ -85,6 +85,13 @@ void esp_cpu_stall(int cpu_id); */ 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. diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index 4e17363bc..360cb84ac 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -958,7 +958,7 @@ #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 (BIT(16)) +#define DPORT_SPI_CLK_EN_2 (BIT(16)) #define DPORT_TIMERGROUP1_CLK_EN (BIT(15)) #define DPORT_EFUSE_CLK_EN (BIT(14)) #define DPORT_TIMERGROUP_CLK_EN (BIT(13)) @@ -968,7 +968,7 @@ #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_2 (BIT(6)) +#define DPORT_SPI_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)) @@ -992,7 +992,7 @@ #define DPORT_CAN_RST (BIT(19)) #define DPORT_I2C_EXT1_RST (BIT(18)) #define DPORT_PWM0_RST (BIT(17)) -#define DPORT_SPI_RST (BIT(16)) +#define DPORT_SPI_RST_2 (BIT(16)) #define DPORT_TIMERGROUP1_RST (BIT(15)) #define DPORT_EFUSE_RST (BIT(14)) #define DPORT_TIMERGROUP_RST (BIT(13)) @@ -1002,7 +1002,7 @@ #define DPORT_RMT_RST (BIT(9)) #define DPORT_UHCI0_RST (BIT(8)) #define DPORT_I2C_EXT0_RST (BIT(7)) -#define DPORT_SPI_RST_2 (BIT(6)) +#define DPORT_SPI_RST (BIT(6)) #define DPORT_UART1_RST (BIT(5)) #define DPORT_I2S0_RST (BIT(4)) #define DPORT_WDG_RST (BIT(3)) diff --git a/components/soc/esp32/include/soc/efuse_reg.h b/components/soc/esp32/include/soc/efuse_reg.h index b9ad20ee6..5b16114d0 100644 --- a/components/soc/esp32/include/soc/efuse_reg.h +++ b/components/soc/esp32/include/soc/efuse_reg.h @@ -100,6 +100,9 @@ #define EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ6 0 #define EFUSE_RD_CHIP_VER_PKG_ESP32D0WDQ5 1 #define EFUSE_RD_CHIP_VER_PKG_ESP32D2WDQ5 2 +#define EFUSE_RD_CHIP_VER_PKG_ESP32PICOD2 4 +#define EFUSE_RD_CHIP_VER_PKG_ESP32PICOD4 5 + /* EFUSE_RD_SPI_PAD_CONFIG_HD : RO ;bitpos:[8:4] ;default: 5'b0 ; */ /*description: read for SPI_pad_config_hd*/ #define EFUSE_RD_SPI_PAD_CONFIG_HD 0x0000001F diff --git a/components/soc/esp32/include/soc/gpio_reg.h b/components/soc/esp32/include/soc/gpio_reg.h index 1f4b08d43..8168f4ba1 100644 --- a/components/soc/esp32/include/soc/gpio_reg.h +++ b/components/soc/esp32/include/soc/gpio_reg.h @@ -129,8 +129,7 @@ #define GPIO_STRAP_REG (DR_REG_GPIO_BASE + 0x0038) /* GPIO_STRAPPING : RO ;bitpos:[15:0] ;default: ; */ -/*description: GPIO strapping results: {2'd0 boot_sel_dig[7:1] vsdio_boot_sel - boot_sel_chip[5:0]}. Boot_sel_dig[7:1]: {U0RXD SD_CLK SD_CMD SD_DATA0 SD_DATA1 SD_DATA2 SD_DATA3}. vsdio_boot_sel: MTDI. boot_sel_chip[5:0]: {GPIO0 U0TXD GPIO2 GPIO4 MTDO GPIO5}*/ +/*description: {10'b0, MTDI, GPIO0, GPIO2, GPIO4, MTDO, GPIO5} */ #define GPIO_STRAPPING 0x0000FFFF #define GPIO_STRAPPING_M ((GPIO_STRAPPING_V)<<(GPIO_STRAPPING_S)) #define GPIO_STRAPPING_V 0xFFFF diff --git a/components/soc/esp32/include/soc/rtc.h b/components/soc/esp32/include/soc/rtc.h index a85265fdc..584196ea7 100644 --- a/components/soc/esp32/include/soc/rtc.h +++ b/components/soc/esp32/include/soc/rtc.h @@ -373,6 +373,15 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period); */ uint64_t rtc_time_get(); +/** + * @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(); + /** * @brief sleep configuration for rtc_sleep_init function */ @@ -524,6 +533,36 @@ typedef struct { */ void rtc_init(rtc_config_t cfg); +/** + * 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(); + +/** + * 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 } diff --git a/components/soc/esp32/include/soc/rtc_cntl_reg.h b/components/soc/esp32/include/soc/rtc_cntl_reg.h index 02f8dff2c..ffcbb3c03 100644 --- a/components/soc/esp32/include/soc/rtc_cntl_reg.h +++ b/components/soc/esp32/include/soc/rtc_cntl_reg.h @@ -1718,6 +1718,7 @@ #define RTC_WDT_STG_SEL_INT 1 #define RTC_WDT_STG_SEL_RESET_CPU 2 #define RTC_WDT_STG_SEL_RESET_SYSTEM 3 +#define RTC_WDT_STG_SEL_RESET_RTC 4 #define RTC_CNTL_WDTCONFIG1_REG (DR_REG_RTCCNTL_BASE + 0x90) /* RTC_CNTL_WDT_STG0_HOLD : R/W ;bitpos:[31:0] ;default: 32'd128000 ; */ diff --git a/components/soc/esp32/rtc_clk.c b/components/soc/esp32/rtc_clk.c index 7f6d99291..d8c0b7328 100644 --- a/components/soc/esp32/rtc_clk.c +++ b/components/soc/esp32/rtc_clk.c @@ -71,9 +71,6 @@ static const char* TAG = "rtc_clk"; * All values are in microseconds. * TODO: some of these are excessive, and should be reduced. */ -#define DELAY_CPU_FREQ_SWITCH_TO_XTAL_WITH_150K 80 -#define DELAY_CPU_FREQ_SWITCH_TO_XTAL_WITH_32K 160 -#define DELAY_CPU_FREQ_SWITCH_TO_PLL 10 #define DELAY_PLL_DBIAS_RAISE 3 #define DELAY_PLL_ENABLE_WITH_150K 80 #define DELAY_PLL_ENABLE_WITH_32K 160 @@ -86,6 +83,20 @@ static const char* TAG = "rtc_clk"; */ #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 + + static void rtc_clk_32k_enable_internal(int dac, int dres, int dbias) { @@ -231,6 +242,8 @@ void rtc_clk_bbpll_set(rtc_xtal_freq_t xtal_freq, rtc_cpu_freq_t cpu_freq) 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: @@ -270,7 +283,7 @@ void rtc_clk_bbpll_set(rtc_xtal_freq_t xtal_freq, rtc_cpu_freq_t cpu_freq) 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, RTC_CNTL_DBIAS_1V25); + 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) { @@ -326,13 +339,16 @@ 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, RTC_CNTL_DBIAS_1V10); + 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); - uint32_t delay_xtal_switch = (rtc_clk_slow_freq_get() == RTC_SLOW_FREQ_RTC) ? - DELAY_CPU_FREQ_SWITCH_TO_XTAL_WITH_150K : DELAY_CPU_FREQ_SWITCH_TO_XTAL_WITH_32K; - ets_delay_us(delay_xtal_switch); + + /* 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 | @@ -354,7 +370,7 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq) 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, RTC_CNTL_DBIAS_1V00); + 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, @@ -372,7 +388,7 @@ void rtc_clk_cpu_freq_set(rtc_cpu_freq_t cpu_freq) ets_update_cpu_frequency(240); } REG_SET_FIELD(RTC_CNTL_CLK_CONF_REG, RTC_CNTL_SOC_CLK_SEL, RTC_CNTL_SOC_CLK_SEL_PLL); - ets_delay_us(DELAY_CPU_FREQ_SWITCH_TO_PLL); + rtc_clk_wait_for_slow_cycle(); rtc_clk_apb_freq_update(80 * MHZ); } } diff --git a/components/soc/esp32/rtc_init.c b/components/soc/esp32/rtc_init.c index ff7b6b73c..44786fbcc 100644 --- a/components/soc/esp32/rtc_init.c +++ b/components/soc/esp32/rtc_init.c @@ -18,6 +18,8 @@ #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" void rtc_init(rtc_config_t cfg) @@ -94,3 +96,51 @@ void rtc_init(rtc_config_t cfg) CLEAR_PERI_REG_MASK(RTC_CNTL_DIG_ISO_REG, RTC_CNTL_DG_PAD_FORCE_NOISO); } } + +rtc_vddsdio_config_t rtc_vddsdio_get_config() +{ + 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; + // 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)) ? 0 : 1; + result.enable = result.tieh == 0; // only power on the regulator if VDD=1.8 + 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/components/soc/esp32/rtc_sleep.c b/components/soc/esp32/rtc_sleep.c index d8d643bb4..aef995cbf 100644 --- a/components/soc/esp32/rtc_sleep.c +++ b/components/soc/esp32/rtc_sleep.c @@ -193,6 +193,10 @@ void rtc_sleep_init(rtc_sleep_config_t cfg) SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_FORCE_NOSLEEP); } + /* enable VDDSDIO control by state machine */ + REG_CLR_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_FORCE); + REG_SET_BIT(RTC_CNTL_SDIO_CONF_REG, RTC_CNTL_SDIO_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); diff --git a/components/soc/esp32/rtc_time.c b/components/soc/esp32/rtc_time.c index 07a9337a3..6f354f884 100644 --- a/components/soc/esp32/rtc_time.c +++ b/components/soc/esp32/rtc_time.c @@ -135,3 +135,20 @@ uint64_t rtc_time_get() t |= ((uint64_t) READ_PERI_REG(RTC_CNTL_TIME1_REG)) << 32; return t; } + +void rtc_clk_wait_for_slow_cycle() +{ + 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/docs/api-guides/index.rst b/docs/api-guides/index.rst index e39f3f8f4..9e8723e93 100644 --- a/docs/api-guides/index.rst +++ b/docs/api-guides/index.rst @@ -14,4 +14,4 @@ API Guides Deep Sleep Wake Stubs ULP Coprocessor Unit Testing - Driver + WiFi Driver diff --git a/docs/api-guides/wifi.rst b/docs/api-guides/wifi.rst index 800f8ae05..5c7c33f1c 100644 --- a/docs/api-guides/wifi.rst +++ b/docs/api-guides/wifi.rst @@ -1,13 +1,6 @@ Wi-Fi Driver ============= -Important Notes ----------------- - -- This document describes the implementation of only the **latest** IDF release. Backward compatibility with older versions of ESP-IDF is not guaranteed. -- This document describes the features which have already been implemented in the **latest** IDF release. For features that are now in developing/testing status, we also provide brief descriptions, while indicating the release versions in which these features will be eventually implemented. -- If you find anything wrong/ambiguous/hard to understand or inconsistent with the implementation, feel free to let us know about it on our IDF GitHub page. - ESP32 Wi-Fi Feature List ------------------------- @@ -494,25 +487,13 @@ The scan type and other scan attributes are configured by esp_wifi_scan_start. T | | in the table below. Here, min is short for scan | | | time.active.min and max is short for scan_time.active.max. | | | | -| | +----+----+------------------------------------------------+ | -| | | min| max| Description | | -| | +====+====+================================================+ | -| | | 0 | 0 | scan dwells on each channel for 120 ms. | | -| | | | | | | -| | +----+----+------------------------------------------------+ | -| | | >0 | 0 | scan dwells on each channel for 120 ms. | | -| | | | | | | -| | +----+----+------------------------------------------------+ | -| | | >0 | >0 | The minimum time the scan dwells on each | | -| | | | | channel is min milliseconds. If no AP is found | | -| | | | | during this time frame, the scan switches | | -| | | | | to the next channel; otherwise, the scan dwells| | -| | | | | on the channel for max milliseconds. | | -| | | | | | | -| | +----+----+------------------------------------------------+ | -| | | 0 | >0 | The scan dwells on each channel for max | | -| | | | | milliseconds. | | -| | +----+----+------------------------------------------------+ | +| | - min=0, max=0: scan dwells on each channel for 120 ms. | +| | - min>0, max=0: scan dwells on each channel for 120 ms. | +| | - min=0, max>0: scan dwells on each channel for ``max`` ms. | +| | - min>0, max>0: the minimum time the scan dwells on each | +| | channel is ``min`` ms. If no AP is found during this time | +| | frame, the scan switches to the next channel. Otherwise, | +| | the scan dwells on the channel for ``max`` ms. | | | | | | If you want to improve the performance of the | | | the scan, you can try to modify these two parameters. | diff --git a/tools/windows/windows_install_prerequisites.sh b/tools/windows/windows_install_prerequisites.sh index b4d633768..e2a757eaa 100644 --- a/tools/windows/windows_install_prerequisites.sh +++ b/tools/windows/windows_install_prerequisites.sh @@ -35,6 +35,10 @@ pacman --noconfirm -Syu # This step may require the terminal to be closed and re pacman --noconfirm -S --needed gettext-devel gcc git make ncurses-devel flex bison gperf vim mingw-w64-i686-python2-pip unzip winpty +# Workaround for errors when running "git submodule" commands +# See https://github.com/Alexpux/MSYS2-packages/issues/735 +rm /mingw32/bin/envsubst.exe + python -m pip install --upgrade pip pip install pyserial