Skip to content

Commit

Permalink
Merge branch 'feature/ulp_riscv_test_multiple_firmware' into 'master'
Browse files Browse the repository at this point in the history
ulp-riscv: Added API ulp_riscv_reset to reset the ULP core

See merge request espressif/esp-idf!22165
  • Loading branch information
sudeep-mohanty committed Feb 13, 2023
2 parents a630f06 + 3cc399f commit 27be8a1
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 20 deletions.
6 changes: 6 additions & 0 deletions components/ulp/test_apps/ulp_riscv/main/CMakeLists.txt
@@ -1,11 +1,17 @@
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"
REQUIRES ulp unity
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}")
118 changes: 98 additions & 20 deletions components/ulp/test_apps/ulp_riscv/main/test_ulp_riscv.c
Expand Up @@ -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>
Expand All @@ -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");
}
}

Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 */
Expand All @@ -136,30 +145,99 @@ 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]")
{
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 */
Expand All @@ -171,21 +249,21 @@ 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));
}



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;
Expand Down Expand Up @@ -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);
Expand Down
@@ -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;
}
@@ -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 changes: 9 additions & 0 deletions components/ulp/ulp_riscv/include/ulp_riscv.h
Expand Up @@ -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 changes: 9 additions & 0 deletions components/ulp/ulp_riscv/ulp_riscv.c
Expand Up @@ -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) {
Expand Down

0 comments on commit 27be8a1

Please sign in to comment.