diff --git a/components/ulp/include/esp32s2/ulp_riscv.h b/components/ulp/include/esp32s2/ulp_riscv.h index dcb539d85c..1105e48701 100644 --- a/components/ulp/include/esp32s2/ulp_riscv.h +++ b/components/ulp/include/esp32s2/ulp_riscv.h @@ -33,3 +33,29 @@ esp_err_t ulp_riscv_run(void); * - ESP_ERR_INVALID_SIZE if program_size_bytes is more than 8KiB */ esp_err_t ulp_riscv_load_binary(const uint8_t* program_binary, size_t program_size_bytes); + +/** + * @brief Stop the ULP timer + * + * @note This will stop the ULP from waking up if halted, but will not abort any program + * currently executing on the ULP. + */ +void ulp_riscv_timer_stop(void); + + +/** + * @brief Resumes the ULP timer + * + * @note This will resume an already configured timer, but does no other configuration + * + */ +void ulp_riscv_timer_resume(void); + + +/** + * @brief Halts the program currently running on the ULP-RISC-V + * + * @note Program will restart at the next ULP timer trigger if timer is still running. + * If you want to stop the ULP from waking up then call ulp_riscv_timer_stop() first. + */ +void ulp_riscv_halt(void); diff --git a/components/ulp/include/esp32s3/ulp_riscv.h b/components/ulp/include/esp32s3/ulp_riscv.h index 7bfbb812c4..c0a24be787 100644 --- a/components/ulp/include/esp32s3/ulp_riscv.h +++ b/components/ulp/include/esp32s3/ulp_riscv.h @@ -38,6 +38,32 @@ esp_err_t ulp_riscv_run(void); */ esp_err_t ulp_riscv_load_binary(const uint8_t* program_binary, size_t program_size_bytes); +/** + * @brief Stop the ULP timer + * + * @note This will stop the ULP from waking up if halted, but will not abort any program + * currently executing on the ULP. + */ +void ulp_riscv_timer_stop(void); + + +/** + * @brief Resumes the ULP timer + * + * @note This will resume an already configured timer, but does no other configuration + * + */ +void ulp_riscv_timer_resume(void); + + +/** + * @brief Halts the program currently running on the ULP-RISC-V + * + * @note Program will restart at the next ULP timer trigger if timer is still running. + * If you want to stop the ULP from waking up then call ulp_riscv_timer_stop() first. + */ +void ulp_riscv_halt(void); + #ifdef __cplusplus } #endif diff --git a/components/ulp/test/ulp_riscv/test_ulp_riscv_main.c b/components/ulp/test/ulp_riscv/test_ulp_riscv_main.c index 6d8b51b4ce..3ad4ab2173 100644 --- a/components/ulp/test/ulp_riscv/test_ulp_riscv_main.c +++ b/components/ulp/test/ulp_riscv/test_ulp_riscv_main.c @@ -20,11 +20,14 @@ #include "ulp_test_app.h" #include "unity.h" #include +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" typedef enum{ RISCV_READ_WRITE_TEST = 1, RISCV_DEEP_SLEEP_WAKEUP_TEST, RISCV_LIGHT_SLEEP_WAKEUP_TEST, + RISCV_STOP_TEST, RISCV_NO_COMMAND, } riscv_test_commands_t; @@ -54,7 +57,7 @@ static void load_and_start_ulp_firmware(void) } } -TEST_CASE("ULP-RISC-V and main CPU are able to exchange data", "[ulp][ignore]") +TEST_CASE("ULP-RISC-V and main CPU are able to exchange data", "[ulp]") { const uint32_t test_data = 0x12345678; struct timeval start, end; @@ -92,7 +95,7 @@ TEST_CASE("ULP-RISC-V and main CPU are able to exchange data", "[ulp][ignore]") ulp_main_cpu_command = RISCV_NO_COMMAND; } -TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp][ignore]") +TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp]") { struct timeval start, end; @@ -141,3 +144,64 @@ TEST_CASE("ULP-RISC-V is able to wakeup main CPU from deep sleep", "[ulp][reset= esp_deep_sleep_start(); UNITY_TEST_FAIL(__LINE__, "Should not get here!"); } + +static bool ulp_riscv_is_running(void) +{ + uint32_t start_cnt = ulp_riscv_counter; + + /* 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; + printf("start run count: %d, end run count %d\n", start_cnt, end_cnt); + + /* If the ulp is running the counter should have been incremented */ + return (start_cnt != end_cnt); +} + +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(); + + TEST_ASSERT(ulp_riscv_is_running()); + + printf("Stopping the ULP\n"); + ulp_riscv_timer_stop(); + ulp_riscv_halt(); + + TEST_ASSERT(!ulp_riscv_is_running()); + + printf("Resuming the ULP\n"); + ulp_riscv_timer_resume(); + + TEST_ASSERT(ulp_riscv_is_running()); +} + +TEST_CASE("ULP-RISC-V can stop itself and be resumed from the main CPU", "[ulp]") +{ + volatile riscv_test_commands_t *command_resp = &ulp_command_resp; + + /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */ + load_and_start_ulp_firmware(); + + TEST_ASSERT(ulp_riscv_is_running()); + + printf("Stopping the ULP\n"); + /* Setup test data */ + ulp_main_cpu_command = RISCV_STOP_TEST; + + while (*command_resp != RISCV_STOP_TEST) { + } + + /* Wait a bit to ensure ULP finished shutting down */ + vTaskDelay(100 / portTICK_PERIOD_MS); + + TEST_ASSERT(!ulp_riscv_is_running()); + + printf("Resuming the ULP\n"); + ulp_main_cpu_command = RISCV_NO_COMMAND; + ulp_riscv_timer_resume(); + + TEST_ASSERT(ulp_riscv_is_running()); +} diff --git a/components/ulp/test/ulp_riscv/ulp/test_main.c b/components/ulp/test/ulp_riscv/ulp/test_main.c index 245a4c5b35..28a1774b4f 100644 --- a/components/ulp/test/ulp_riscv/ulp/test_main.c +++ b/components/ulp/test/ulp_riscv/ulp/test_main.c @@ -9,11 +9,13 @@ #include #include "ulp_riscv/ulp_riscv.h" #include "ulp_riscv/ulp_riscv_utils.h" +#include "ulp_riscv/ulp_riscv_gpio.h" typedef enum{ RISCV_READ_WRITE_TEST = 1, RISCV_DEEP_SLEEP_WAKEUP_TEST, RISCV_LIGHT_SLEEP_WAKEUP_TEST, + RISCV_STOP_TEST, RISCV_NO_COMMAND, } riscv_test_commands_t; @@ -30,9 +32,12 @@ volatile riscv_test_command_reply_t main_cpu_reply = RISCV_COMMAND_INVALID; volatile riscv_test_commands_t command_resp = RISCV_NO_COMMAND; volatile uint32_t riscv_test_data_in = 0; volatile uint32_t riscv_test_data_out = 0; +volatile uint32_t riscv_counter = 0; void handle_commands(riscv_test_commands_t cmd) { + riscv_counter++; + switch (cmd) { case RISCV_READ_WRITE_TEST: /* Echo the command ID back to the main CPU */ @@ -70,6 +75,19 @@ void handle_commands(riscv_test_commands_t cmd) ulp_riscv_wakeup_main_processor(); break; + case RISCV_STOP_TEST: + /* Echo the command ID back to the main CPU */ + command_resp = RISCV_STOP_TEST; + + /* Set the command reply status */ + main_cpu_reply = RISCV_COMMAND_OK; + + /* Will never return from here */ + ulp_riscv_timer_stop(); + ulp_riscv_halt(); + + break; + case RISCV_NO_COMMAND: main_cpu_reply = RISCV_COMMAND_OK; break; @@ -87,6 +105,6 @@ int main (void) break; } - /* ulp_riscv_shutdown() is called automatically when main exits */ + /* ulp_riscv_halt() is called automatically when main exits */ return 0; } diff --git a/components/ulp/ulp_riscv.c b/components/ulp/ulp_riscv.c index 3591b66c80..b9a4731457 100644 --- a/components/ulp/ulp_riscv.c +++ b/components/ulp/ulp_riscv.c @@ -97,6 +97,27 @@ esp_err_t ulp_riscv_run(void) #endif } +void ulp_riscv_timer_stop(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); +} + +void ulp_riscv_timer_resume(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); +} + +void ulp_riscv_halt(void) +{ + ulp_riscv_timer_stop(); + + /* suspends the ulp operation*/ + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE); + + /* Resets the processor */ + 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) { diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h index 3d9077d274..7b18917aa2 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h @@ -43,12 +43,34 @@ void ulp_riscv_rescue_from_monitor(void); * @note Returning from main() in the ULP program results on * calling this function. * + * @note To stop the ULP from waking up, call ulp_riscv_timer_stop() + * before halting. + * * This function should be called after the ULP program Finishes * its processing, it will trigger the timer for the next wakeup, * put the ULP in monitor mode and triggers a reset. * */ -void __attribute__((noreturn)) ulp_riscv_shutdown(void); +void __attribute__((noreturn)) ulp_riscv_halt(void); + +#define ulp_riscv_shutdown ulp_riscv_halt + +/** + * @brief Stop the ULP timer + * + * @note This will stop the ULP from waking up if halted, but will not abort any program + * currently executing on the ULP. + */ +void ulp_riscv_timer_stop(void); + + +/** + * @brief Resumes the ULP timer + * + * @note This will resume an already configured timer, but does no other configuration + * + */ +void ulp_riscv_timer_resume(void); #define ULP_RISCV_GET_CCOUNT() ({ int __ccount; \ asm volatile("rdcycle %0;" : "=r"(__ccount)); \ diff --git a/components/ulp/ulp_riscv/start.S b/components/ulp/ulp_riscv/start.S index 949fd7fb48..b1f4c334a1 100644 --- a/components/ulp/ulp_riscv/start.S +++ b/components/ulp/ulp_riscv/start.S @@ -18,6 +18,6 @@ __start: la sp, __stack_top call ulp_riscv_rescue_from_monitor call main - call ulp_riscv_shutdown + call ulp_riscv_halt loop: j loop diff --git a/components/ulp/ulp_riscv/ulp_riscv_utils.c b/components/ulp/ulp_riscv/ulp_riscv_utils.c index d6cbc60a46..f9e3cfe020 100644 --- a/components/ulp/ulp_riscv/ulp_riscv_utils.c +++ b/components/ulp/ulp_riscv/ulp_riscv_utils.c @@ -1,16 +1,8 @@ -// Copyright 2015-2020 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. +/* + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "ulp_riscv/ulp_riscv.h" #include "ulp_riscv/ulp_riscv_utils.h" @@ -26,7 +18,7 @@ void ulp_riscv_wakeup_main_processor(void) SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_SW_CPU_INT); } -void ulp_riscv_shutdown(void) +void ulp_riscv_halt(void) { /* Setting the delay time after RISCV recv `DONE` signal, Ensure that action `RESET` can be executed in time. */ REG_SET_FIELD(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_2_CLK_DIS, 0x3F); @@ -48,3 +40,13 @@ void ulp_riscv_delay_cycles(uint32_t cycles) /* Wait */ } } + +void ulp_riscv_timer_stop(void) +{ + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); +} + +void ulp_riscv_timer_resume(void) +{ + SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); +} diff --git a/examples/system/ulp_riscv/ds18b20_onewire/main/ulp/main.c b/examples/system/ulp_riscv/ds18b20_onewire/main/ulp/main.c index 323e6030bc..22b3ee383a 100644 --- a/examples/system/ulp_riscv/ds18b20_onewire/main/ulp/main.c +++ b/examples/system/ulp_riscv/ds18b20_onewire/main/ulp/main.c @@ -148,7 +148,7 @@ int main (void) break; } - /* ulp_riscv_shutdown() is called automatically when main exits, + /* ulp_riscv_halt() is called automatically when main exits, main will be executed again at the next timeout period, according to ulp_set_wakeup_period() */ diff --git a/examples/system/ulp_riscv/gpio/main/ulp/main.c b/examples/system/ulp_riscv/gpio/main/ulp/main.c index 2f24ba377a..daa70af8a8 100644 --- a/examples/system/ulp_riscv/gpio/main/ulp/main.c +++ b/examples/system/ulp_riscv/gpio/main/ulp/main.c @@ -36,6 +36,6 @@ int main (void) break; } } - /* ulp_riscv_shutdown() is called automatically when main exits */ + /* ulp_riscv_halt() is called automatically when main exits */ return 0; } diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index 6df4e9d5ff..85ee4dd037 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -2069,7 +2069,6 @@ components/ulp/ulp_macro.c components/ulp/ulp_private.h components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv.h components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h -components/ulp/ulp_riscv/ulp_riscv_utils.c components/unity/include/priv/setjmp.h components/unity/include/unity_config.h components/unity/include/unity_fixture_extras.h