From 75658ee29b67712e0c91d987865e306a89dca0f1 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Jun 2017 17:56:32 +0800 Subject: [PATCH 1/7] bootloader: workaround for clock switching bug in ESP32 rev. 0 In ESP32 rev. 0, switching between 240MHz and 80MHz (even via an intermediate frequency of 40MHz) may cause the chip to lock up. The bootloader used to enable 80MHz CPU clock at startup, which could cause lock up after software reset. With this change, if 240MHz CPU clock is enabled in menuconfig, bootloader will also use 240MHz to avoid lock-up. --- components/bootloader/src/main/bootloader_start.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/components/bootloader/src/main/bootloader_start.c b/components/bootloader/src/main/bootloader_start.c index de038d4bc..fd062a5f9 100644 --- a/components/bootloader/src/main/bootloader_start.c +++ b/components/bootloader/src/main/bootloader_start.c @@ -701,10 +701,23 @@ void print_flash_info(const esp_image_header_t* phdr) static void clock_configure(void) { /* Set CPU to 80MHz. Keep other clocks unmodified. */ + rtc_cpu_freq_t cpu_freq = RTC_CPU_FREQ_80M; + + /* On ESP32 rev 0, switching to 80MHz if clock was previously set to + * 240 MHz may cause the chip to lock up (see section 3.5 of the errata + * document). For rev. 0, switch to 240 instead if it was chosen in + * menuconfig. + */ + uint32_t chip_ver_reg = REG_READ(EFUSE_BLK0_RDATA3_REG); + if ((chip_ver_reg & EFUSE_RD_CHIP_VER_REV1_M) == 0 && + CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ == 240) { + cpu_freq = RTC_CPU_FREQ_240M; + } + uart_tx_wait_idle(0); rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT(); clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ; - clk_cfg.cpu_freq = RTC_CPU_FREQ_80M; + clk_cfg.cpu_freq = cpu_freq; clk_cfg.slow_freq = rtc_clk_slow_freq_get(); clk_cfg.fast_freq = rtc_clk_fast_freq_get(); rtc_clk_init(clk_cfg); From a72b1abc51e5eaeba5b7f0a0ad864df7e80d7a48 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Jun 2017 18:00:26 +0800 Subject: [PATCH 2/7] esp32: disable DPORT access protection when doing esp_restart DPORT access protection can not work when the other CPU is stalled. Writes to DPORT registers in esp_restart caused the program to hang due to access protection, and the reset happened due to RTC_WDT, not SW_RST. This change adds esp_dport_access_int_deinit function and calls it from esp_restart once the other core is stalled. --- components/esp32/dport_access.c | 10 ++++++++++ components/esp32/include/esp_dport_access.h | 1 + components/esp32/system_api.c | 4 +++- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/components/esp32/dport_access.c b/components/esp32/dport_access.c index aa4bdbea0..dbb956e82 100644 --- a/components/esp32/dport_access.c +++ b/components/esp32/dport_access.c @@ -193,3 +193,13 @@ void esp_dport_access_int_init(void) xTaskCreatePinnedToCore(&dport_access_init_core1, "dport1", 512, NULL, 5, NULL, 1); } } + +void esp_dport_access_int_deinit(void) +{ + portENTER_CRITICAL_ISR(&g_dport_mux); + dport_core_state[0] = DPORT_CORE_STATE_IDLE; +#ifndef CONFIG_FREERTOS_UNICORE + dport_core_state[1] = DPORT_CORE_STATE_IDLE; +#endif + portEXIT_CRITICAL_ISR(&g_dport_mux); +} diff --git a/components/esp32/include/esp_dport_access.h b/components/esp32/include/esp_dport_access.h index 7e6f73247..8b081c5ae 100644 --- a/components/esp32/include/esp_dport_access.h +++ b/components/esp32/include/esp_dport_access.h @@ -22,6 +22,7 @@ extern "C" { 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); #if defined(BOOTLOADER_BUILD) || defined(CONFIG_FREERTOS_UNICORE) || !defined(ESP_PLATFORM) #define DPORT_STALL_OTHER_CPU_START() diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index a7193548b..942807600 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -246,11 +246,13 @@ 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); + // 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 REG_WRITE(RTC_CNTL_WDTWPROTECT_REG, RTC_CNTL_WDT_WKEY_VALUE); From 9353666cc14be63826fdff7ccedb883339e318a0 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 14 Jun 2017 18:07:15 +0800 Subject: [PATCH 3/7] esp32: reset APP CPU when doing esp_restart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes a bug introduced by !848, where APP CPU would not be reset during esp_restart, if esp_restart was called from a task running on APP CPU, and wouldn’t be reset by PRO CPU on startup. This change replaces stalling APP CPU with resetting it. Also adds a non-automated esp_restart tests. --- components/esp32/system_api.c | 7 +++++-- components/esp32/test/test_restart.c | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 components/esp32/test/test_restart.c diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 942807600..30f6a684c 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -298,6 +298,9 @@ void IRAM_ATTR esp_restart_noos() // 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. @@ -305,10 +308,10 @@ void IRAM_ATTR esp_restart_noos() RTC_CNTL_SW_PROCPU_RST_M | RTC_CNTL_SW_APPCPU_RST_M); } else { // Running on APP CPU: need to reset PRO CPU and unstall it, - // then stall APP CPU + // then reset APP CPU SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_PROCPU_RST_M); esp_cpu_unstall(0); - esp_cpu_stall(1); + SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_APPCPU_RST_M); } while(true) { ; diff --git a/components/esp32/test/test_restart.c b/components/esp32/test/test_restart.c new file mode 100644 index 000000000..94f5741af --- /dev/null +++ b/components/esp32/test/test_restart.c @@ -0,0 +1,26 @@ +#include "unity.h" +#include "esp_system.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + + +TEST_CASE("restart from PRO CPU", "[restart][ignore]") +{ + esp_restart(); +} + +static void restart_task(void* arg) +{ + esp_restart(); +} + +TEST_CASE("restart from APP CPU", "[restart][ignore]") +{ + xTaskCreatePinnedToCore(&restart_task, "restart", 2048, NULL, 5, NULL, 1); + + while(true) { + ; + } +} + + From b78a8ae035d1dacdd15ab75805021a3824e6bfe7 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 15 Jun 2017 17:58:19 +0800 Subject: [PATCH 4/7] unit-test-app: increase space for factory partition to 1280K --- tools/unit-test-app/partition_table_unit_test_app.csv | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/unit-test-app/partition_table_unit_test_app.csv b/tools/unit-test-app/partition_table_unit_test_app.csv index 279f5b69d..ea43d0791 100644 --- a/tools/unit-test-app/partition_table_unit_test_app.csv +++ b/tools/unit-test-app/partition_table_unit_test_app.csv @@ -5,11 +5,11 @@ nvs, data, nvs, 0x9000, 0x4000 otadata, data, ota, 0xd000, 0x2000 phy_init, data, phy, 0xf000, 0x1000 -factory, 0, 0, 0x10000, 1M +factory, 0, 0, 0x10000, 0x140000 # these OTA partitions are used for tests, but can't fit real OTA apps in them # (done this way so tests can run in 2MB of flash.) -ota_0, 0, ota_0, , 128K -ota_1, 0, ota_1, , 128K +ota_0, 0, ota_0, , 64K +ota_1, 0, ota_1, , 64K # flash_test partition used for SPI flash tests and WL FAT partition # 528K is the minimal size needed to create a FAT partition # (128 sectors for FAT + 4 sectors for WL) From 6538ebe8ad97d3fd01dd9b1dbb57e6219ce4c99a Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 15 Jun 2017 17:58:57 +0800 Subject: [PATCH 5/7] =?UTF-8?q?cxx:=20don=E2=80=99t=20pull=20libstdc++=20l?= =?UTF-8?q?ocal=20support=20in=20unit=20tests?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- components/cxx/test/test_cxx.cpp | 38 ++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/components/cxx/test/test_cxx.cpp b/components/cxx/test/test_cxx.cpp index 3b653361f..5d5ff1595 100644 --- a/components/cxx/test/test_cxx.cpp +++ b/components/cxx/test/test_cxx.cpp @@ -1,7 +1,5 @@ -#include #include #include -#include #include "unity.h" #include "esp_log.h" #include "freertos/FreeRTOS.h" @@ -59,20 +57,6 @@ TEST_CASE("can use static initializers for non-POD types", "[cxx]") TEST_ASSERT_EQUAL(1, non_pod_test_helper(0)); } -TEST_CASE("can call std::function and bind", "[cxx]") -{ - int outer = 1; - std::function fn = [&outer](int x) -> int { - return x + outer; - }; - outer = 5; - TEST_ASSERT_EQUAL(6, fn(1)); - - auto bound = std::bind(fn, outer); - outer = 10; - TEST_ASSERT_EQUAL(15, bound()); -} - TEST_CASE("can use std::vector", "[cxx]") { std::vector v(10, 1); @@ -203,8 +187,30 @@ TEST_CASE("before scheduler has started, static initializers work correctly", "[ TEST_ASSERT_EQUAL(2, StaticInitTestBeforeScheduler::order); } +/* These test cases pull a lot of code from libstdc++ and are disabled for now + */ +#if 0 +#include +#include TEST_CASE("can use iostreams", "[cxx]") { std::cout << "hello world"; } + +TEST_CASE("can call std::function and bind", "[cxx]") +{ + int outer = 1; + std::function fn = [&outer](int x) -> int { + return x + outer; + }; + outer = 5; + TEST_ASSERT_EQUAL(6, fn(1)); + + auto bound = std::bind(fn, outer); + outer = 10; + TEST_ASSERT_EQUAL(15, bound()); +} + +#endif + From 8cb0d52c4303dbb12af2e928e9391dafb112fdd4 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 15 Jun 2017 18:00:49 +0800 Subject: [PATCH 6/7] esp_system: remove link time dependency on WiFi stack - esp_restart will not pull in WiFi stack (if it is not used otherwise) - esp_restore is moved into a separate file to break link time dependency --- components/esp32/restore.c | 24 ++++++++++++++++++++++++ components/esp32/system_api.c | 15 ++++++++++----- 2 files changed, 34 insertions(+), 5 deletions(-) create mode 100644 components/esp32/restore.c diff --git a/components/esp32/restore.c b/components/esp32/restore.c new file mode 100644 index 000000000..e17f1ab77 --- /dev/null +++ b/components/esp32/restore.c @@ -0,0 +1,24 @@ +// 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 "esp_system.h" +#include "esp_wifi.h" + +/* This function is in a separate file from the reset of system APIs because + * it causes link time dependency on WiFi stack. + */ +void system_restore(void) +{ + esp_wifi_restore(); +} diff --git a/components/esp32/system_api.c b/components/esp32/system_api.c index 30f6a684c..c797f30bd 100644 --- a/components/esp32/system_api.c +++ b/components/esp32/system_api.c @@ -228,6 +228,16 @@ esp_err_t esp_read_mac(uint8_t* mac, esp_mac_type_t type) void esp_restart_noos() __attribute__ ((noreturn)); +/* Dummy function to be used instead of esp_wifi_stop if WiFi stack is not + * linked in (even though CONFIG_WIFI_ENABLED is set). + */ +esp_err_t wifi_stop_noop() +{ + return ESP_OK; +} + +esp_err_t esp_wifi_stop(void) __attribute((weak, alias("wifi_stop_noop"))); + void IRAM_ATTR esp_restart(void) { #ifdef CONFIG_WIFI_ENABLED @@ -320,11 +330,6 @@ void IRAM_ATTR esp_restart_noos() void system_restart(void) __attribute__((alias("esp_restart"))); -void system_restore(void) -{ - esp_wifi_restore(); -} - uint32_t esp_get_free_heap_size(void) { return xPortGetFreeHeapSize(); From ffdcbc535598c44675f59f9ca44e4125da5f4633 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 15 Jun 2017 18:11:58 +0800 Subject: [PATCH 7/7] =?UTF-8?q?libsodium:=20don=E2=80=99t=20link=20tests?= =?UTF-8?q?=20when=20TEST=5FALL=3D1=20is=20used?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently libsodium tests add about 800kB to the binary, which is too much for a partition table constrained to 2MB. Disable libsodium tests until we start building multiple unit test apps for different subsets. --- components/libsodium/test/component.mk | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/libsodium/test/component.mk b/components/libsodium/test/component.mk index c23c32b6e..ec8a3e932 100644 --- a/components/libsodium/test/component.mk +++ b/components/libsodium/test/component.mk @@ -4,7 +4,11 @@ LS_TESTDIR := ../libsodium/test/default +ifdef TESTS_ALL +$(info not linking libsodium tests, use 'TEST_COMPONENTS=libsodium' to test it) +else COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive +endif # TESTS_ALL COMPONENT_SRCDIRS := . $(LS_TESTDIR)