Explorar el Código

Merge branch 'feature/ulp_riscv_test_multiple_firmware' into 'master'

ulp-riscv: Added API ulp_riscv_reset to reset the ULP core

See merge request espressif/esp-idf!22165
Sudeep Mohanty hace 3 años
padre
commit
27be8a1ebb

+ 6 - 0
components/ulp/test_apps/ulp_riscv/main/CMakeLists.txt

@@ -1,5 +1,7 @@
 set(app_sources "test_app_main.c" "test_ulp_riscv.c")
 set(ulp_sources "ulp/test_main.c")
+set(ulp_sources2 "ulp/test_main_second_cocpu_firmware.c")
+set(ulp_sources3 "ulp/test_main_cocpu_crash.c")
 
 idf_component_register(SRCS ${app_sources}
                        INCLUDE_DIRS "ulp"
@@ -7,5 +9,9 @@ idf_component_register(SRCS ${app_sources}
                        WHOLE_ARCHIVE)
 
 set(ulp_app_name ulp_test_app)
+set(ulp_app_name2 ulp_test_app2)
+set(ulp_app_name3 ulp_test_app3)
 set(ulp_exp_dep_srcs ${app_sources})
 ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}")
+ulp_embed_binary(${ulp_app_name2} "${ulp_sources2}" "${ulp_exp_dep_srcs}")
+ulp_embed_binary(${ulp_app_name3} "${ulp_sources3}" "${ulp_exp_dep_srcs}")

+ 98 - 20
components/ulp/test_apps/ulp_riscv/main/test_ulp_riscv.c

@@ -14,6 +14,7 @@
 #include "ulp_riscv.h"
 #include "ulp_riscv_lock.h"
 #include "ulp_test_app.h"
+#include "ulp_test_app2.h"
 #include "ulp_test_shared.h"
 #include "unity.h"
 #include <sys/time.h>
@@ -22,20 +23,28 @@
 
 #define ULP_WAKEUP_PERIOD 1000000 // 1 second
 
+// First ULP firmware
 extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_test_app_bin_start");
-extern const uint8_t ulp_main_bin_end[]   asm("_binary_ulp_test_app_bin_end");
+extern const size_t ulp_main_bin_length asm("ulp_test_app_bin_length");
 static bool  firmware_loaded = false;
 
-static void load_and_start_ulp_firmware(void)
+// Second ULP firmware
+extern const uint8_t ulp_test_app2_bin_start[] asm("_binary_ulp_test_app2_bin_start");
+extern const size_t ulp_test_app2_bin_length asm("ulp_test_app2_bin_length");
+
+// Faulty ULP firmware
+extern const uint8_t ulp_test_app3_bin_start[] asm("_binary_ulp_test_app3_bin_start");
+extern const size_t ulp_test_app3_bin_length asm("ulp_test_app3_bin_length");
+
+static void load_and_start_ulp_firmware(const uint8_t* ulp_bin, size_t ulp_bin_len)
 {
     if (!firmware_loaded) {
-        TEST_ASSERT(ulp_riscv_load_binary(ulp_main_bin_start,
-                            (ulp_main_bin_end - ulp_main_bin_start)) == ESP_OK);
-
+        TEST_ASSERT(ulp_riscv_load_binary(ulp_bin, ulp_bin_len) == ESP_OK);
         TEST_ASSERT(ulp_set_wakeup_period(0, ULP_WAKEUP_PERIOD) == ESP_OK);
         TEST_ASSERT(ulp_riscv_run() == ESP_OK);
 
         firmware_loaded = true;
+        printf("New ULP firmware loaded\n");
     }
 }
 
@@ -45,7 +54,7 @@ TEST_CASE("ULP-RISC-V and main CPU are able to exchange data", "[ulp]")
     struct timeval start, end;
 
     /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
-    load_and_start_ulp_firmware();
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
 
     /* Setup wakeup triggers */
     TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
@@ -79,7 +88,7 @@ TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp]")
     struct timeval start, end;
 
     /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
-    load_and_start_ulp_firmware();
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
 
     /* Setup wakeup triggers */
     TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
@@ -119,14 +128,14 @@ TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp]")
     ulp_main_cpu_command = RISCV_NO_COMMAND;
 }
 
-static bool ulp_riscv_is_running(void)
+static bool ulp_riscv_is_running(uint32_t *counter_variable)
 {
-    uint32_t start_cnt = ulp_riscv_counter;
+    uint32_t start_cnt = *counter_variable;
 
     /* Wait a few ULP wakeup cycles to ensure ULP has run */
     vTaskDelay((5 * ULP_WAKEUP_PERIOD / 1000) / portTICK_PERIOD_MS);
 
-    uint32_t end_cnt = ulp_riscv_counter;
+    uint32_t end_cnt = *counter_variable;
     printf("start run count: %" PRIu32 ", end run count %" PRIu32 "\n", start_cnt, end_cnt);
 
     /* If the ulp is running the counter should have been incremented */
@@ -136,20 +145,89 @@ static bool ulp_riscv_is_running(void)
 TEST_CASE("ULP-RISC-V can be stopped and resumed from main CPU", "[ulp]")
 {
     /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
-    load_and_start_ulp_firmware();
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
 
-    TEST_ASSERT(ulp_riscv_is_running());
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
 
     printf("Stopping the ULP\n");
     ulp_riscv_timer_stop();
     ulp_riscv_halt();
 
-    TEST_ASSERT(!ulp_riscv_is_running());
+    TEST_ASSERT(!ulp_riscv_is_running(&ulp_riscv_counter));
 
     printf("Resuming the ULP\n");
     ulp_riscv_timer_resume();
 
-    TEST_ASSERT(ulp_riscv_is_running());
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
+}
+
+TEST_CASE("ULP-RISC-V can be loaded with and run multiple firmwares", "[ulp]")
+{
+    /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
+
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
+
+    printf("Stopping the ULP\n");
+    ulp_riscv_timer_stop();
+    ulp_riscv_halt();
+
+    TEST_ASSERT(!ulp_riscv_is_running(&ulp_riscv_counter));
+
+    printf("Loading second firmware on the ULP\n");
+    firmware_loaded = false;
+    load_and_start_ulp_firmware(ulp_test_app2_bin_start, ulp_test_app2_bin_length);
+
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter2));
+
+    printf("Stopping the ULP\n");
+    ulp_riscv_timer_stop();
+    ulp_riscv_halt();
+
+    TEST_ASSERT(!ulp_riscv_is_running(&ulp_riscv_counter2));
+
+    printf("Loading the first firmware again on the ULP\n");
+    firmware_loaded = false;
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
+
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
+}
+
+TEST_CASE("ULP-RISC-V can be reloaded with a good fimware after a crash", "[ulp]")
+{
+    /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
+
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
+
+    printf("Stopping the ULP\n");
+    ulp_riscv_timer_stop();
+    ulp_riscv_halt();
+
+    TEST_ASSERT(!ulp_riscv_is_running(&ulp_riscv_counter));
+
+    /* Enable ULP wakeup */
+    TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);
+
+    printf("Loading faulty firmware on the ULP and go into light sleep\n");
+    firmware_loaded = false;
+    load_and_start_ulp_firmware(ulp_test_app3_bin_start, ulp_test_app3_bin_length);
+    esp_light_sleep_start();
+
+    /* Verify that main CPU wakes up by a COCPU trap signal trigger */
+    esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
+    TEST_ASSERT(cause != ESP_SLEEP_WAKEUP_COCPU);
+
+    printf("Resetting the ULP\n");
+    ulp_riscv_reset();
+
+    esp_rom_delay_us(20);
+
+    printf("Loading the good firmware on ULP\n");
+    firmware_loaded = false;
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
+
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
 }
 
 TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]")
@@ -157,9 +235,9 @@ TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]"
     volatile riscv_test_commands_t *command_resp = (riscv_test_commands_t*)&ulp_command_resp;
 
     /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
-    load_and_start_ulp_firmware();
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
 
-    TEST_ASSERT(ulp_riscv_is_running());
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
 
     printf("Stopping the ULP\n");
     /* Setup test data */
@@ -171,13 +249,13 @@ TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]"
     /* Wait a bit to ensure ULP finished shutting down */
     vTaskDelay(100 / portTICK_PERIOD_MS);
 
-    TEST_ASSERT(!ulp_riscv_is_running());
+    TEST_ASSERT(!ulp_riscv_is_running(&ulp_riscv_counter));
 
     printf("Resuming the ULP\n");
     ulp_main_cpu_command = RISCV_NO_COMMAND;
     ulp_riscv_timer_resume();
 
-    TEST_ASSERT(ulp_riscv_is_running());
+    TEST_ASSERT(ulp_riscv_is_running(&ulp_riscv_counter));
 }
 
 
@@ -185,7 +263,7 @@ TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]"
 TEST_CASE("ULP-RISC-V mutex", "[ulp]")
 {
     /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
-    load_and_start_ulp_firmware();
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
 
     /* Setup test data */
     ulp_riscv_incrementer = 0;
@@ -219,7 +297,7 @@ static void do_ulp_wakeup_deepsleep(riscv_test_commands_t ulp_cmd, bool rtc_peri
     }
 
     /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */
-    load_and_start_ulp_firmware();
+    load_and_start_ulp_firmware(ulp_main_bin_start, ulp_main_bin_length);
 
     /* Setup wakeup triggers */
     TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK);

+ 18 - 0
components/ulp/test_apps/ulp_riscv/main/ulp/test_main_cocpu_crash.c

@@ -0,0 +1,18 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+
+int main (void)
+{
+    /* Make sure ULP core crashes by doing a NULL pointer access */
+    uint32_t *null_ptr = NULL;
+    *null_ptr = 1;
+
+    /* ulp_riscv_halt() is called automatically when main exits */
+    return 0;
+}

+ 17 - 0
components/ulp/test_apps/ulp_riscv/main/ulp/test_main_second_cocpu_firmware.c

@@ -0,0 +1,17 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Espressif Systems (Shanghai) CO LTD
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include <stdint.h>
+
+volatile uint32_t riscv_counter2 = 0;
+
+int main (void)
+{
+    riscv_counter2++;
+
+    /* ulp_riscv_halt() is called automatically when main exits */
+    return 0;
+}

+ 9 - 0
components/ulp/ulp_riscv/include/ulp_riscv.h

@@ -92,6 +92,15 @@ void ulp_riscv_timer_resume(void);
  */
 void ulp_riscv_halt(void);
 
+/**
+ * @brief Resets the ULP-RISC-V core from the main CPU
+ *
+ * @note This will reset the ULP core from the main CPU. It is intended to be used when the
+ *       ULP is in a bad state and cannot run as intended due to a corrupt firmware or any other reason.
+ *       The main core can reset the ULP core with this API and then re-initilialize the ULP.
+ */
+void ulp_riscv_reset(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 9 - 0
components/ulp/ulp_riscv/ulp_riscv.c

@@ -142,6 +142,15 @@ void ulp_riscv_halt(void)
     SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
 }
 
+void ulp_riscv_reset()
+{
+    CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT | RTC_CNTL_COCPU_DONE);
+    CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
+    esp_rom_delay_us(20);
+    SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT | RTC_CNTL_COCPU_DONE);
+    SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN);
+}
+
 esp_err_t ulp_riscv_load_binary(const uint8_t* program_binary, size_t program_size_bytes)
 {
     if (program_binary == NULL) {