Răsfoiți Sursa

Merge branch 'bugfix/deep_sleep_skip_verify_rtc_mem_heap' into 'master'

Fix bootloader "skip validate on exiting deep sleep" option if "use RTC memory as heap" is enabled

See merge request espressif/esp-idf!12032
Angus Gratton 4 ani în urmă
părinte
comite
bc3d45026c

+ 1 - 0
.gitlab/ci/target-test.yml

@@ -330,6 +330,7 @@ test_app_test_003:
 
 test_app_test_004:
   extends: .test_app_esp32s2_template
+  parallel: 2
   tags:
     - ESP32S2
     - Example_GENERIC

+ 13 - 1
components/bootloader_support/src/bootloader_common_loader.c

@@ -30,6 +30,7 @@
 #include "soc/gpio_periph.h"
 #include "soc/rtc.h"
 #include "soc/efuse_reg.h"
+#include "soc/soc_memory_layout.h"
 #include "hal/gpio_ll.h"
 #include "esp_image_format.h"
 #include "bootloader_sha.h"
@@ -138,7 +139,18 @@ esp_err_t bootloader_common_get_partition_description(const esp_partition_pos_t
 
 #if defined( CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP ) || defined( CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC )
 
-rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)(SOC_RTC_DRAM_HIGH - sizeof(rtc_retain_mem_t));
+#define RTC_RETAIN_MEM_ADDR (SOC_RTC_DATA_HIGH - sizeof(rtc_retain_mem_t))
+
+rtc_retain_mem_t *const rtc_retain_mem = (rtc_retain_mem_t *)RTC_RETAIN_MEM_ADDR;
+
+#if !IS_BOOTLOADER_BUILD
+/* The app needs to be told this memory is reserved, important if configured to use RTC memory as heap.
+
+   Note that keeping this macro here only works when other symbols in this file are referenced by the app, as
+   this feature is otherwise 100% part of the bootloader. However this seems to happen in all apps.
+ */
+SOC_RESERVE_MEMORY_REGION(RTC_RETAIN_MEM_ADDR, RTC_RETAIN_MEM_ADDR + sizeof(rtc_retain_mem_t), rtc_retain_mem);
+#endif
 
 static bool check_rtc_retain_mem(void)
 {

+ 9 - 1
components/esp32c3/ld/esp32c3.ld

@@ -8,6 +8,14 @@
 
 #include "sdkconfig.h"
 
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
+#else
+#define ESP_BOOTLOADER_RESERVE_RTC 0
+#endif
+
 #define SRAM_IRAM_START     0x4037C000
 #define SRAM_DRAM_START     0x3FC7C000
 #define ICACHE_SIZE         0x4000 /* ICache size is fixed to 16KB on ESP32-C3 */
@@ -65,7 +73,7 @@ MEMORY
   /**
    * RTC fast memory (executable). Persists over deep sleep.
    */
-  rtc_iram_seg(RWX) :                org = 0x50000000, len = 0x2000
+  rtc_iram_seg(RWX) :                org = 0x50000000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC
 }
 
 #if CONFIG_ESP32C3_USE_FIXED_STATIC_RAM_SIZE

+ 9 - 1
components/esp32s3/ld/esp32s3.ld

@@ -8,6 +8,14 @@
 
 #include "sdkconfig.h"
 
+#ifdef CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE + CONFIG_BOOTLOADER_CUSTOM_RESERVE_RTC_SIZE)
+#elif defined(CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP)
+#define ESP_BOOTLOADER_RESERVE_RTC (CONFIG_BOOTLOADER_RESERVE_RTC_SIZE)
+#else
+#define ESP_BOOTLOADER_RESERVE_RTC 0
+#endif
+
 #define SRAM_IRAM_START     0x40370000
 #define SRAM_DRAM_START     0x3FC80000
 #define I_D_SRAM_OFFSET     (SRAM_IRAM_START - SRAM_DRAM_START)
@@ -65,7 +73,7 @@ MEMORY
   /**
    * RTC fast memory (executable). Persists over deep sleep.
    */
-  rtc_iram_seg(RWX) :                org = 0x600fe000, len = 0x2000
+  rtc_iram_seg(RWX) :                org = 0x600fe000, len = 0x2000 - ESP_BOOTLOADER_RESERVE_RTC
 
   /**
    * RTC fast memory (same block as above), viewed from data bus

+ 3 - 0
components/soc/esp32s3/soc_memory_layout.c

@@ -72,6 +72,9 @@ const soc_memory_region_t soc_memory_regions[] = {
 #if CONFIG_ESP32S3_DATA_CACHE_32KB
     { 0x3FCF0000, 0x8000,  0, 0},          //Level 9, DRAM
 #endif
+#ifdef CONFIG_ESP_SYSTEM_ALLOW_RTC_FAST_MEM_AS_HEAP
+    { 0x50000000, 0x2000,  4, 0}, //Fast RTC memory
+#endif
 };
 
 const size_t soc_memory_region_count = sizeof(soc_memory_regions) / sizeof(soc_memory_region_t);

+ 32 - 10
examples/system/deep_sleep/example_test.py

@@ -1,25 +1,35 @@
 from __future__ import unicode_literals
 
 import re
+import time
 
 import ttfw_idf
 
-touch_wake_up_support = ['esp32']
+touch_wake_up_support = ['esp32', 'esp32s2']
 
 
-@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32c3'])
+@ttfw_idf.idf_example_test(env_tag='Example_GENERIC', target=['esp32', 'esp32s2', 'esp32c3'])
 def test_examples_deep_sleep(env, extra_data):
 
     dut = env.get_dut('deep_sleep', 'examples/system/deep_sleep')
     dut.start_app()
 
     def expect_enable_deep_sleep_touch():
-        dut.expect_all('Enabling timer wakeup, 20s',
-                       re.compile(r'Touch pad #8 average: \d+, wakeup threshold set to \d+.'),
-                       re.compile(r'Touch pad #9 average: \d+, wakeup threshold set to \d+.'),
-                       'Enabling touch pad wakeup',
-                       'Entering deep sleep',
-                       timeout=10)
+        # different targets configure different wake pin(s)
+        wake_pads = {
+            'esp32': [8,9],
+            'esp32s2': [9],
+        }[dut.TARGET]
+
+        print('Expecting to see wakeup configured on pad(s): {}'.format(wake_pads))
+
+        expect_items = ['Enabling timer wakeup, 20s']
+        for pad in wake_pads:
+            expect_items += [re.compile(r'Touch pad #{} average: \d+, wakeup threshold set to \d+.'.format(pad))]
+        expect_items += ['Enabling touch pad wakeup',
+                         'Entering deep sleep']
+
+        dut.expect_all(*expect_items, timeout=10)
 
     def expect_enable_deep_sleep_no_touch():
         dut.expect_all('Enabling timer wakeup, 20s',
@@ -34,8 +44,20 @@ def test_examples_deep_sleep(env, extra_data):
     dut.expect('Not a deep sleep reset', timeout=30)
     expect_enable_deep_sleep()
 
-    # Check that it spent 2xxxxms in deep sleep, i.e at least 20 seconds:
-    dut.expect(re.compile(r'Wake up from timer. Time spent in deep sleep: 2\d{4}ms'), timeout=30)
+    start_sleep = time.time()
+    print('Waiting for wakeup...')
+    dut.expect('boot: ESP-IDF', timeout=30)  # first output that's the same on all chips
+
+    sleep_time = time.time() - start_sleep
+    print('Host measured sleep time at {:.2f}s'.format(sleep_time))
+    assert 19 < sleep_time < 22  # note: high tolerance as measuring time on the host may have some timing skew
+
+    # This line indicates that the CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP option set in sdkconfig.defaults
+    # has correctly allowed skipping verification on wakeup
+    dut.expect('boot: Fast booting app from partition', timeout=2)
+
+    # Check that it measured 2xxxxms in deep sleep, i.e at least 20 seconds:
+    dut.expect(re.compile(r'Wake up from timer. Time spent in deep sleep: 2\d{4}ms'), timeout=2)
     expect_enable_deep_sleep()
 
 

+ 6 - 4
examples/system/deep_sleep/main/deep_sleep_example_main.c

@@ -245,11 +245,13 @@ void app_main(void)
     touch_pad_set_fsm_mode(TOUCH_FSM_MODE_TIMER);
     touch_pad_fsm_start();
     vTaskDelay(100 / portTICK_RATE_MS);
-    /* read sleep touch pad value */
-    uint32_t touch_value;
+
+    /* set touchpad wakeup threshold */
+    uint32_t touch_value, wake_threshold;
     touch_pad_sleep_channel_read_smooth(TOUCH_PAD_NUM9, &touch_value);
-    touch_pad_sleep_set_threshold(TOUCH_PAD_NUM9, touch_value * 0.1); //10%
-    printf("test init: touch pad [%d] slp %d, thresh %d\n",
+    wake_threshold = touch_value * 0.1; // wakeup when touch sensor crosses 10% of background level
+    touch_pad_sleep_set_threshold(TOUCH_PAD_NUM9, wake_threshold);
+    printf("Touch pad #%d average: %d, wakeup threshold set to %d\n",
         TOUCH_PAD_NUM9, touch_value, (uint32_t)(touch_value * 0.1));
 #endif
     printf("Enabling touch pad wakeup\n");

+ 17 - 3
examples/system/deep_sleep/sdkconfig.ci

@@ -1,12 +1,26 @@
+# Generic config
+CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
+CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP=n
+CONFIG_EXAMPLE_EXT1_WAKEUP=n
+
+# ESP32-specific config
 CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y
 CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=80
 CONFIG_ESP32_ULP_COPROC_ENABLED=y
 CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=512
 CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
 CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y
-CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
-CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP=n
-CONFIG_EXAMPLE_EXT1_WAKEUP=n
+
+# ESP32S2-specific config
+CONFIG_ESP32S2_DEFAULT_CPU_FREQ_80=y
+CONFIG_ESP32S2_DEFAULT_CPU_FREQ_MHZ=80
+CONFIG_ESP32S2_ULP_COPROC_ENABLED=y
+CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM=512
+CONFIG_ESP32S2_RTC_CLK_SRC_INT_RC=y
+
+# ESP32C3-specific config
+CONFIG_ESP32C3_DEFAULT_CPU_FREQ_80=y
+CONFIG_ESP32C3_DEFAULT_CPU_FREQ_MHZ=80
 # IDF-3090
 CONFIG_ESP32C3_REV_MIN_0=y
 CONFIG_ESP32C3_REV_MIN=0

+ 18 - 0
examples/system/deep_sleep/sdkconfig.ci.esp32_singlecore

@@ -0,0 +1,18 @@
+CONFIG_IDF_TARGET="esp32"
+CONFIG_FREERTOS_UNICORE=y
+
+## Below here should be same as these sections in sdkconfig.ci
+
+# Generic config
+CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y
+CONFIG_EXAMPLE_ULP_TEMPERATURE_WAKEUP=n
+CONFIG_EXAMPLE_EXT1_WAKEUP=n
+
+# ESP32-specific config
+CONFIG_ESP32_DEFAULT_CPU_FREQ_80=y
+CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=80
+CONFIG_ESP32_ULP_COPROC_ENABLED=y
+CONFIG_ESP32_ULP_COPROC_RESERVE_MEM=512
+CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y
+CONFIG_ESP32_RTC_CLK_SRC_INT_RC=y
+CONFIG_BOOTLOADER_SKIP_VALIDATE_IN_DEEP_SLEEP=y

+ 5 - 3
tools/test_apps/README.md

@@ -22,10 +22,12 @@ Test applications are treated the same way as ESP-IDF examples, so each project
 
 For each project in test_apps (and also examples):
 
-* If a file `sdkconfig.ci` exists then it's built as the `default` CI config (same as if this file was named `sdkconfig.ci.default`)
-* If any files `sdkconfig.ci.<CONFIG>` exist then these are built as alternative configs, with the specified `<CONFIG>` name.
+* If a file `sdkconfig.ci` exists then it's built as the `default` CI config.
+* If any additional files `sdkconfig.ci.<CONFIG>` exist then these are built as alternative configs, with the specified `<CONFIG>` name.
 
-* By default, every CI configurations is built for every target SoC (an `m * n` configuration matrix). However if any `sdkconfig.ci` file contains a line of the form `CONFIG_IDF_TARGET="targetname"` then that CI config is only built for that one target.
+The CI system expects to see at least a "default" config, so add `sdkconfig.ci` before adding any `sdkconfig.ci.CONFIG` files.
+
+* By default, every CI configurations is built for every target SoC (an `m * n` configuration matrix). However if any `sdkconfig.ci.*` file contains a line of the form `CONFIG_IDF_TARGET="targetname"` then that CI config is only built for that one target. This only works in `sdkconfig.ci.CONFIG`, not in the default `sdkconfig.ci`.
 * Each configuration is also built with the contents of any `sdkconfig.defaults` file or a file named `sdkconfig.defaults.<TARGET>` appended. (Same as a normal ESP-IDF project build.)
 
 ## Test Execution