diff --git a/components/esp32s3/Kconfig b/components/esp32s3/Kconfig index 38a2909a15..2fe7561e0c 100644 --- a/components/esp32s3/Kconfig +++ b/components/esp32s3/Kconfig @@ -327,6 +327,13 @@ menu "ESP32S3-Specific" Data is reserved at the beginning of RTC slow memory. + config ESP32S3_ULP_COPROC_RISCV + bool "Enable RISC-V as ULP coprocessor" + depends on ESP32S3_ULP_COPROC_ENABLED + default n + help + Set this to y to use the RISC-V coprocessor instead of the FSM-ULP. + config ESP32S3_DEBUG_OCDAWARE bool "Make exception and panic handlers JTAG/OCD aware" default y diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index def006f30c..6aa72ab71c 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -765,7 +765,7 @@ esp_err_t esp_sleep_disable_wakeup_source(esp_sleep_source_t source) } else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_UART, (RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN))) { s_config.wakeup_triggers &= ~(RTC_UART0_TRIG_EN | RTC_UART1_TRIG_EN); } -#if defined(CONFIG_ESP32_ULP_COPROC_ENABLED) || defined(CONFIG_ESP32S2_ULP_COPROC_ENABLED) +#if defined(CONFIG_ESP32_ULP_COPROC_ENABLED) || defined(CONFIG_ESP32S2_ULP_COPROC_ENABLED) || defined(CONFIG_ESP32S3_ULP_COPROC_ENABLED) else if (CHECK_SOURCE(source, ESP_SLEEP_WAKEUP_ULP, RTC_ULP_TRIG_EN)) { s_config.wakeup_triggers &= ~RTC_ULP_TRIG_EN; } @@ -1135,7 +1135,7 @@ esp_sleep_wakeup_cause_t esp_sleep_get_wakeup_cause(void) } else if (wakeup_cause & RTC_BT_TRIG_EN) { return ESP_SLEEP_WAKEUP_BT; #endif -#if CONFIG_IDF_TARGET_ESP32S2 +#if SOC_RISCV_COPROC_SUPPORTED } else if (wakeup_cause & RTC_COCPU_TRIG_EN) { return ESP_SLEEP_WAKEUP_ULP; } else if (wakeup_cause & RTC_COCPU_TRAP_TRIG_EN) { diff --git a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in index 3cd05c3311..2eb054b0fc 100644 --- a/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in +++ b/components/soc/esp32s3/include/soc/Kconfig.soc_caps.in @@ -171,6 +171,10 @@ config SOC_ULP_SUPPORTED bool default y +config SOC_RISCV_COPROC_SUPPORTED + bool + default y + config SOC_BT_SUPPORTED bool default y diff --git a/components/soc/esp32s3/include/soc/soc.h b/components/soc/esp32s3/include/soc/soc.h index 69b524a1a0..b5df8e1201 100644 --- a/components/soc/esp32s3/include/soc/soc.h +++ b/components/soc/esp32s3/include/soc/soc.h @@ -37,6 +37,10 @@ #define REG_SPI_MEM_BASE(i) (DR_REG_SPI0_BASE - (i) * 0x1000) #define REG_I2C_BASE(i) (DR_REG_I2C_EXT_BASE + (i) * 0x14000 ) +//Convenient way to replace the register ops when ulp riscv projects +//consume this file +#ifndef ULP_RISCV_REGISTER_OPS + //Registers Operation {{ #define ETS_UNCACHED_ADDR(addr) (addr) #define ETS_CACHED_ADDR(addr) (addr) @@ -143,6 +147,7 @@ #endif /* !__ASSEMBLER__ */ //}} +#endif /* !ULP_RISCV_REGISTER_OPS */ //Periheral Clock {{ #define APB_CLK_FREQ_ROM (40*1000000) diff --git a/components/soc/esp32s3/include/soc/soc_caps.h b/components/soc/esp32s3/include/soc/soc_caps.h index 527f0759a4..b3be1edabf 100644 --- a/components/soc/esp32s3/include/soc/soc_caps.h +++ b/components/soc/esp32s3/include/soc/soc_caps.h @@ -36,6 +36,7 @@ #define SOC_CPU_CORES_NUM 2 #define SOC_CACHE_SUPPORT_WRAP 1 #define SOC_ULP_SUPPORTED 1 +#define SOC_RISCV_COPROC_SUPPORTED 1 #define SOC_BT_SUPPORTED 1 #define SOC_USB_OTG_SUPPORTED 1 #define SOC_USB_SERIAL_JTAG_SUPPORTED 1 diff --git a/components/ulp/CMakeLists.txt b/components/ulp/CMakeLists.txt index e73f7004ed..eb84f60856 100644 --- a/components/ulp/CMakeLists.txt +++ b/components/ulp/CMakeLists.txt @@ -1,13 +1,18 @@ idf_build_get_property(target IDF_TARGET) -if(NOT (IDF_TARGET STREQUAL "esp32c3") AND NOT (IDF_TARGET STREQUAL "esp32h2") AND NOT (IDF_TARGET STREQUAL "esp8684")) - set(srcs "ulp.c" - "ulp_macro.c") +set(srcs "") +set(includes include) - if(CONFIG_ESP32S2_ULP_COPROC_RISCV) - list(APPEND srcs "ulp_riscv.c") +if(CONFIG_SOC_ULP_SUPPORTED) + list(APPEND srcs + "ulp.c" + "ulp_macro.c") + + if(CONFIG_SOC_RISCV_COPROC_SUPPORTED) + list(APPEND srcs + "ulp_riscv.c") endif() - - idf_component_register(SRCS ${srcs} - INCLUDE_DIRS include) endif() + +idf_component_register(SRCS ${srcs} + INCLUDE_DIRS ${includes}) diff --git a/components/ulp/cmake/CMakeLists.txt b/components/ulp/cmake/CMakeLists.txt index 4164f113e4..674a20c039 100644 --- a/components/ulp/cmake/CMakeLists.txt +++ b/components/ulp/cmake/CMakeLists.txt @@ -17,10 +17,10 @@ string(REGEX MATCH "\\(GNU Binutils\\) (${version_pattern})" as_version ${as_out set(as_version ${CMAKE_MATCH_1}) -message(STATUS "Building ULP app ${ULP_APP_NAME}") +message(STATUS "Building ULP app ${ULP_APP_NAME} for ${IDF_TARGET}") if(ULP_COCPU_IS_RISCV) - set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/esp32s2.ulp.riscv.ld) + set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/${IDF_TARGET}.ulp.riscv.ld) else() message(STATUS "ULP assembler version: ${as_version}") @@ -38,7 +38,7 @@ else() the toolchain, or proceed at your own risk.") endif() - set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/esp32.ulp.ld) + set(ULP_LD_TEMPLATE ${IDF_PATH}/components/ulp/ld/ulp_fsm.ld) endif() diff --git a/components/ulp/cmake/toolchain-esp32s2-ulp-riscv.cmake b/components/ulp/cmake/toolchain-ulp-riscv.cmake similarity index 100% rename from components/ulp/cmake/toolchain-esp32s2-ulp-riscv.cmake rename to components/ulp/cmake/toolchain-ulp-riscv.cmake diff --git a/components/ulp/include/esp32s3/ulp_riscv.h b/components/ulp/include/esp32s3/ulp_riscv.h new file mode 100644 index 0000000000..7bfbb812c4 --- /dev/null +++ b/components/ulp/include/esp32s3/ulp_riscv.h @@ -0,0 +1,43 @@ +/* + * SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once +#include +#include +#include +#include "esp_err.h" +#include "ulp_common.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Run the program loaded into RTC memory + * @return ESP_OK on success + */ +esp_err_t ulp_riscv_run(void); + +/** + * @brief Load ULP-RISC-V program binary into RTC memory + * + * Different than ULP FSM, the binary program has no special format, it is the ELF + * file generated by RISC-V toolchain converted to binary format using objcopy. + * + * Linker script in components/ulp/ld/esp32s3.ulp.riscv.ld produces ELF files which + * correspond to this format. This linker script produces binaries with load_addr == 0. + * + * @param program_binary pointer to program binary + * @param program_size_bytes size of the program binary + * @return + * - ESP_OK on success + * - 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); + +#ifdef __cplusplus +} +#endif diff --git a/components/ulp/include/ulp_common.h b/components/ulp/include/ulp_common.h index 7ca7b85943..92135fc0f5 100644 --- a/components/ulp/include/ulp_common.h +++ b/components/ulp/include/ulp_common.h @@ -1,20 +1,12 @@ -// Copyright 2016-2018 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: 2016-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once -/* This file contains definitions that are common between esp32/ulp.h - and esp32s2/ulp.h +/* This file contains definitions that are common between esp32/ulp.h, + esp32s2/ulp.h and esp32s3/ulp.h */ #ifdef __cplusplus diff --git a/components/ulp/ld/esp32s3.ulp.riscv.ld b/components/ulp/ld/esp32s3.ulp.riscv.ld new file mode 100644 index 0000000000..e6ffe91949 --- /dev/null +++ b/components/ulp/ld/esp32s3.ulp.riscv.ld @@ -0,0 +1,48 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ +#include "sdkconfig.h" + +ENTRY(reset_vector) + +MEMORY +{ + ram(RW) : ORIGIN = 0, LENGTH = CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM +} + +SECTIONS +{ + . = ORIGIN(ram); + .text : + { + *start.S.obj(.text.vectors) /* Default reset vector must link to offset 0x0 */ + *(.text) + *(.text*) + } >ram + + .rodata ALIGN(4): + { + *(.rodata) + *(.rodata*) + } > ram + + .data ALIGN(4): + { + *(.data) + *(.data*) + *(.sdata) + *(.sdata*) + } > ram + + .bss ALIGN(4) : + { + *(.bss) + *(.bss*) + *(.sbss) + *(.sbss*) + } >ram + + __stack_top = ORIGIN(ram) + LENGTH(ram); +} diff --git a/components/ulp/ld/esp32.ulp.ld b/components/ulp/ld/ulp_fsm.ld similarity index 76% rename from components/ulp/ld/esp32.ulp.ld rename to components/ulp/ld/ulp_fsm.ld index 4fd7499b62..d0f51d6b5a 100644 --- a/components/ulp/ld/esp32.ulp.ld +++ b/components/ulp/ld/ulp_fsm.ld @@ -1,7 +1,14 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include "sdkconfig.h" #if CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM #define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32S2_ULP_COPROC_RESERVE_MEM +#elif CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM +#define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM #else #define LOCAL_ULP_COPROC_RESERVE_MEM CONFIG_ESP32_ULP_COPROC_RESERVE_MEM #endif diff --git a/components/ulp/project_include.cmake b/components/ulp/project_include.cmake index 27341b93ef..cac5a950d8 100644 --- a/components/ulp/project_include.cmake +++ b/components/ulp/project_include.cmake @@ -31,20 +31,19 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs) idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER) idf_build_get_property(idf_path IDF_PATH) + idf_build_get_property(idf_target IDF_TARGET) idf_build_get_property(python PYTHON) idf_build_get_property(extra_cmake_args EXTRA_CMAKE_ARGS) if(IDF_TARGET STREQUAL "esp32") - set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-esp32-ulp.cmake) + set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake) set(ULP_IS_RISCV OFF) - endif() - - if(IDF_TARGET STREQUAL "esp32s2") - if(CONFIG_ESP32S2_ULP_COPROC_RISCV STREQUAL "y") - set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-esp32s2-ulp-riscv.cmake) + elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") + if(CONFIG_ESP32S2_ULP_COPROC_RISCV STREQUAL "y" OR CONFIG_ESP32S3_ULP_COPROC_RISCV STREQUAL "y") + set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-ulp-riscv.cmake) set(ULP_IS_RISCV ON) else() - set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-esp32s2-ulp.cmake) + set(TOOLCHAIN_FLAG ${idf_path}/components/ulp/cmake/toolchain-${idf_target}-ulp.cmake) set(ULP_IS_RISCV OFF) endif() endif() @@ -60,6 +59,7 @@ function(ulp_embed_binary app_name s_sources exp_dep_srcs) -DCOMPONENT_DIR=${COMPONENT_DIR} -DCOMPONENT_INCLUDES=$ -DIDF_PATH=${idf_path} + -DIDF_TARGET=${idf_target} -DSDKCONFIG_HEADER=${SDKCONFIG_HEADER} -DPYTHON=${python} -DULP_COCPU_IS_RISCV=${ULP_IS_RISCV} diff --git a/components/ulp/test/CMakeLists.txt b/components/ulp/test/CMakeLists.txt index d4a231f314..5fde084440 100644 --- a/components/ulp/test/CMakeLists.txt +++ b/components/ulp/test/CMakeLists.txt @@ -1,16 +1,18 @@ -if(IDF_TARGET STREQUAL "esp32s3") - return() +if(IDF_TARGET STREQUAL "esp32") + set(src_dirs ${IDF_TARGET}) + set(ulp_sources "ulp/test_jumps_esp32.S") +elseif(IDF_TARGET STREQUAL "esp32s2" OR IDF_TARGET STREQUAL "esp32s3") + if(CONFIG_ESP32S2_ULP_COPROC_RISCV STREQUAL "y" OR CONFIG_ESP32S3_ULP_COPROC_RISCV STREQUAL "y") + set(src_dirs "ulp_riscv") + set(ulp_sources "ulp_riscv/ulp/test_main.c") + endif() + #TODO: Add ULP-FSM Test case for esp32s2 and esp32s3 endif() -idf_component_register(SRC_DIRS ${IDF_TARGET} + +idf_component_register(SRC_DIRS ${src_dirs} PRIV_INCLUDE_DIRS . PRIV_REQUIRES cmock ulp soc esp_common driver) -if(IDF_TARGET STREQUAL "esp32") - set(ulp_sources "ulp/test_jumps_esp32.S") -elseif(IDF_TARGET STREQUAL "esp32s2") - set(ulp_sources "ulp_riscv/test_main.c") -endif() - set(ulp_app_name ulp_test_app) -set(ulp_exp_dep_srcs ${IDF_TARGET}) +set(ulp_exp_dep_srcs ${src_dirs}) ulp_embed_binary(${ulp_app_name} "${ulp_sources}" "${ulp_exp_dep_srcs}") diff --git a/components/ulp/test/ulp_riscv/test_main.c b/components/ulp/test/ulp_riscv/test_main.c deleted file mode 100644 index 1ee4d6b22b..0000000000 --- a/components/ulp/test/ulp_riscv/test_main.c +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2010-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. - -#include -#include -#include -#include "ulp_riscv/ulp_riscv.h" -#include "ulp_riscv/ulp_riscv_utils.h" - -typedef enum{ - RISCV_READ_WRITE_TEST = 1, - RISCV_DEEP_SLEEP_WAKEUP_TEST, - RISCV_LIGHT_SLEEP_WAKEUP_TEST, - RISCV_NO_COMMAND, -} riscv_test_commands_t; - -typedef enum { - RISCV_COMMAND_OK = 1, - RISCV_COMMAND_NOK, - RISCV_COMMAND_INVALID, -} riscv_test_command_reply_t; - -#define XOR_MASK 0xDEADBEEF - -volatile riscv_test_commands_t main_cpu_command = RISCV_NO_COMMAND; -volatile riscv_test_command_reply_t main_cpu_reply = RISCV_COMMAND_INVALID; -volatile uint32_t riscv_test_data_in = 0; -volatile uint32_t riscv_test_data_out = 0; - -void handle_commands(riscv_test_commands_t cmd) -{ - switch (cmd) { - case RISCV_READ_WRITE_TEST: - riscv_test_data_out =riscv_test_data_in ^ XOR_MASK; - main_cpu_reply = RISCV_COMMAND_OK; - break; - - case RISCV_DEEP_SLEEP_WAKEUP_TEST: - case RISCV_LIGHT_SLEEP_WAKEUP_TEST: - main_cpu_reply = RISCV_COMMAND_OK; - break; - - default: - main_cpu_reply = RISCV_COMMAND_NOK; - break; - } - ulp_riscv_wakeup_main_processor(); -} - -int main (void) -{ - while (1) { - handle_commands(main_cpu_command); - break; - } - - /* ulp_riscv_shutdown() is called automatically when main exits */ - return 0; -} diff --git a/components/ulp/test/esp32s2/test_ulp_riscv.c b/components/ulp/test/ulp_riscv/test_ulp_riscv_main.c similarity index 55% rename from components/ulp/test/esp32s2/test_ulp_riscv.c rename to components/ulp/test/ulp_riscv/test_ulp_riscv_main.c index 07c4e48c97..6d8b51b4ce 100644 --- a/components/ulp/test/esp32s2/test_ulp_riscv.c +++ b/components/ulp/test/ulp_riscv/test_ulp_riscv_main.c @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #include #include @@ -18,10 +10,16 @@ #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" #include "soc/rtc_periph.h" +#if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/ulp.h" #include "esp32s2/ulp_riscv.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/ulp.h" +#include "esp32s3/ulp_riscv.h" +#endif #include "ulp_test_app.h" #include "unity.h" +#include typedef enum{ RISCV_READ_WRITE_TEST = 1, @@ -33,9 +31,11 @@ typedef enum{ typedef enum { RISCV_COMMAND_OK = 1, RISCV_COMMAND_NOK, + RISCV_COMMAND_INVALID, } riscv_test_command_reply_t; #define XOR_MASK 0xDEADBEEF +#define ULP_WAKEUP_PERIOD 1000000 // 1 second 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"); @@ -47,7 +47,7 @@ static void load_and_start_ulp_firmware(void) TEST_ASSERT(ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start)) == ESP_OK); - TEST_ASSERT(ulp_set_wakeup_period(0, 1000000) == ESP_OK); + TEST_ASSERT(ulp_set_wakeup_period(0, ULP_WAKEUP_PERIOD) == ESP_OK); TEST_ASSERT(ulp_riscv_run() == ESP_OK); firmware_loaded = true; @@ -57,37 +57,87 @@ static void load_and_start_ulp_firmware(void) TEST_CASE("ULP-RISC-V and main CPU are able to exchange data", "[ulp][ignore]") { const uint32_t test_data = 0x12345678; + struct timeval start, end; + /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */ load_and_start_ulp_firmware(); + + /* Setup wakeup triggers */ TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK); + /* Setup test data */ ulp_riscv_test_data_in = test_data ^ XOR_MASK; ulp_main_cpu_command = RISCV_READ_WRITE_TEST; + /* Enter Light Sleep */ TEST_ASSERT(esp_light_sleep_start() == ESP_OK); - TEST_ASSERT(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_ULP); - TEST_ASSERT(ulp_main_cpu_reply == RISCV_COMMAND_OK); + /* Wait for wakeup from ULP RISC-V Coprocessor */ + TEST_ASSERT(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_ULP); + + /* Wait till we receive the correct command response */ + gettimeofday(&start, NULL); + while (ulp_command_resp != RISCV_READ_WRITE_TEST) + ; + gettimeofday(&end, NULL); + printf("Response time %ld ms\n", (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000); + + /* Verify test data */ + TEST_ASSERT(ulp_command_resp == RISCV_READ_WRITE_TEST); + TEST_ASSERT(ulp_main_cpu_reply == RISCV_COMMAND_OK); printf("data out: 0x%X, expected: 0x%X \n", ulp_riscv_test_data_out, test_data); TEST_ASSERT(test_data == ulp_riscv_test_data_out); + /* Clear test data */ + ulp_main_cpu_command = RISCV_NO_COMMAND; } TEST_CASE("ULP-RISC-V is able to wakeup main CPU from light sleep", "[ulp][ignore]") { + struct timeval start, end; + + /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */ load_and_start_ulp_firmware(); + + /* Setup wakeup triggers */ TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK); + + /* Setup test data */ ulp_main_cpu_command = RISCV_LIGHT_SLEEP_WAKEUP_TEST; + + /* Enter Light Sleep */ TEST_ASSERT(esp_light_sleep_start() == ESP_OK); + + /* Wait for wakeup from ULP RISC-V Coprocessor */ TEST_ASSERT(esp_sleep_get_wakeup_cause() == ESP_SLEEP_WAKEUP_ULP); + + /* Wait till we receive the correct command response */ + gettimeofday(&start, NULL); + while (ulp_command_resp != RISCV_LIGHT_SLEEP_WAKEUP_TEST) + ; + gettimeofday(&end, NULL); + printf("Response time %ld ms\n", (end.tv_sec - start.tv_sec) * 1000 + (end.tv_usec - start.tv_usec) / 1000); + + /* Verify test data */ + TEST_ASSERT(ulp_command_resp == RISCV_LIGHT_SLEEP_WAKEUP_TEST); TEST_ASSERT(ulp_main_cpu_reply == RISCV_COMMAND_OK); + + /* Clear test data */ + ulp_main_cpu_command = RISCV_NO_COMMAND; } TEST_CASE("ULP-RISC-V is able to wakeup main CPU from deep sleep", "[ulp][reset=SW_CPU_RESET][ignore]") { + /* Load ULP RISC-V firmware and start the ULP RISC-V Coprocessor */ load_and_start_ulp_firmware(); + + /* Setup wakeup triggers */ TEST_ASSERT(esp_sleep_enable_ulp_wakeup() == ESP_OK); + + /* Setup test data */ ulp_main_cpu_command = RISCV_DEEP_SLEEP_WAKEUP_TEST; + + /* Enter Deep Sleep */ esp_deep_sleep_start(); UNITY_TEST_FAIL(__LINE__, "Should not get here!"); } diff --git a/components/ulp/test/ulp_riscv/ulp/test_main.c b/components/ulp/test/ulp_riscv/ulp/test_main.c new file mode 100644 index 0000000000..245a4c5b35 --- /dev/null +++ b/components/ulp/test/ulp_riscv/ulp/test_main.c @@ -0,0 +1,92 @@ +/* + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include "ulp_riscv/ulp_riscv.h" +#include "ulp_riscv/ulp_riscv_utils.h" + +typedef enum{ + RISCV_READ_WRITE_TEST = 1, + RISCV_DEEP_SLEEP_WAKEUP_TEST, + RISCV_LIGHT_SLEEP_WAKEUP_TEST, + RISCV_NO_COMMAND, +} riscv_test_commands_t; + +typedef enum { + RISCV_COMMAND_OK = 1, + RISCV_COMMAND_NOK, + RISCV_COMMAND_INVALID, +} riscv_test_command_reply_t; + +#define XOR_MASK 0xDEADBEEF + +volatile riscv_test_commands_t main_cpu_command = RISCV_NO_COMMAND; +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; + +void handle_commands(riscv_test_commands_t cmd) +{ + switch (cmd) { + case RISCV_READ_WRITE_TEST: + /* Echo the command ID back to the main CPU */ + command_resp = RISCV_READ_WRITE_TEST; + + /* Process test data */ + riscv_test_data_out = riscv_test_data_in ^ XOR_MASK; + + /* Set the command reply status */ + main_cpu_reply = RISCV_COMMAND_OK; + + /* Wakeup the main CPU */ + ulp_riscv_wakeup_main_processor(); + break; + + case RISCV_DEEP_SLEEP_WAKEUP_TEST: + /* Echo the command ID back to the main CPU */ + command_resp = RISCV_DEEP_SLEEP_WAKEUP_TEST; + + /* Set the command reply status */ + main_cpu_reply = RISCV_COMMAND_OK; + + /* Wakeup the main CPU */ + ulp_riscv_wakeup_main_processor(); + break; + + case RISCV_LIGHT_SLEEP_WAKEUP_TEST: + /* Echo the command ID back to the main CPU */ + command_resp = RISCV_LIGHT_SLEEP_WAKEUP_TEST; + + /* Set the command reply status */ + main_cpu_reply = RISCV_COMMAND_OK; + + /* Wakeup the main CPU */ + ulp_riscv_wakeup_main_processor(); + break; + + case RISCV_NO_COMMAND: + main_cpu_reply = RISCV_COMMAND_OK; + break; + + default: + main_cpu_reply = RISCV_COMMAND_NOK; + break; + } +} + +int main (void) +{ + while (1) { + handle_commands(main_cpu_command); + break; + } + + /* ulp_riscv_shutdown() is called automatically when main exits */ + return 0; +} diff --git a/components/ulp/ulp.c b/components/ulp/ulp.c index e0c70a6f83..1dc193bc22 100644 --- a/components/ulp/ulp.c +++ b/components/ulp/ulp.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -59,7 +59,7 @@ esp_err_t ulp_run(uint32_t entry_point) SET_PERI_REG_MASK(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_BIAS_SLEEP_FOLW_8M); // enable ULP timer SET_PERI_REG_MASK(RTC_CNTL_STATE0_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); -#elif defined CONFIG_IDF_TARGET_ESP32S2 +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) // disable ULP timer CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); // wait for at least 1 RTC_SLOW_CLK cycle @@ -144,7 +144,7 @@ esp_err_t ulp_set_wakeup_period(size_t period_index, uint32_t period_us) } REG_SET_FIELD(SENS_ULP_CP_SLEEP_CYC0_REG + period_index * sizeof(uint32_t), SENS_SLEEP_CYCLES_S0, (uint32_t) period_cycles); -#elif defined CONFIG_IDF_TARGET_ESP32S2 +#elif defined(CONFIG_IDF_TARGET_ESP32S2) || defined(CONFIG_IDF_TARGET_ESP32S3) if (period_index > 4) { return ESP_ERR_INVALID_ARG; } diff --git a/components/ulp/ulp_riscv.c b/components/ulp/ulp_riscv.c index 1afbcc0a9f..3591b66c80 100644 --- a/components/ulp/ulp_riscv.c +++ b/components/ulp/ulp_riscv.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -12,8 +12,13 @@ #include "esp_err.h" #include "esp_log.h" #include "esp_private/esp_clk.h" +#if CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/ulp.h" #include "esp32s2/ulp_riscv.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/ulp.h" +#include "esp32s3/ulp_riscv.h" +#endif #include "soc/soc.h" #include "soc/rtc.h" #include "soc/rtc_cntl_reg.h" @@ -23,6 +28,7 @@ esp_err_t ulp_riscv_run(void) { +#if CONFIG_IDF_TARGET_ESP32S2 /* Reset COCPU when power on. */ SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); esp_rom_delay_us(20); @@ -47,6 +53,48 @@ esp_err_t ulp_riscv_run(void) SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); return ESP_OK; +#elif CONFIG_IDF_TARGET_ESP32S3 + /* Reset COCPU when power on. */ + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO); + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); + esp_rom_delay_us(20); + CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLK_FO); + CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SHUT_RESET_EN); + + /* Disable ULP timer */ + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); + /* wait for at least 1 RTC_SLOW_CLK cycle */ + esp_rom_delay_us(20); + + /* We do not select RISC-V as the Coprocessor here as this could lead to a hang + * in the main CPU. Instead, we reset RTC_CNTL_COCPU_SEL after we have enabled the ULP timer. + * + * IDF-4510 + */ + //CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SEL); + + /* Select ULP-RISC-V to send the DONE signal */ + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_DONE_FORCE); + + /* Set the CLKGATE_EN signal */ + SET_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_CLKGATE_EN); + + /* start ULP_TIMER */ + CLEAR_PERI_REG_MASK(RTC_CNTL_ULP_CP_CTRL_REG, RTC_CNTL_ULP_CP_FORCE_START_TOP); + SET_PERI_REG_MASK(RTC_CNTL_ULP_CP_TIMER_REG, RTC_CNTL_ULP_CP_SLP_TIMER_EN); + + /* Select RISC-V as the ULP_TIMER trigger target + * Selecting the RISC-V as the Coprocessor at the end is a workaround + * for the hang issue recorded in IDF-4510. + */ + CLEAR_PERI_REG_MASK(RTC_CNTL_COCPU_CTRL_REG, RTC_CNTL_COCPU_SEL); + + /* Clear any spurious wakeup trigger interrupts upon ULP startup */ + esp_rom_delay_us(20); + REG_WRITE(RTC_CNTL_INT_CLR_REG, RTC_CNTL_COCPU_INT_CLR | RTC_CNTL_COCPU_TRAP_INT_CLR | RTC_CNTL_ULP_CP_INT_CLR); + + return ESP_OK; +#endif } esp_err_t ulp_riscv_load_binary(const uint8_t* program_binary, size_t program_size_bytes) diff --git a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h index a129930326..3249764978 100644 --- a/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h +++ b/components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_gpio.h @@ -1,16 +1,8 @@ -// Copyright 2010-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: 2010-2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Apache-2.0 + */ #pragma once @@ -55,7 +47,11 @@ typedef enum { static inline void ulp_riscv_gpio_init(gpio_num_t gpio_num) { +#if CONFIG_IDF_TARGET_ESP32S2 SET_PERI_REG_MASK(SENS_SAR_IO_MUX_CONF_REG, SENS_IOMUX_CLK_GATE_EN_M); +#elif CONFIG_IDF_TARGET_ESP32S3 + SET_PERI_REG_MASK(SENS_SAR_PERI_CLK_GATE_CONF_REG, SENS_IOMUX_CLK_EN_M); +#endif SET_PERI_REG_MASK(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_MUX_SEL); REG_SET_FIELD(RTC_IO_TOUCH_PAD0_REG + gpio_num*4, RTC_IO_TOUCH_PAD0_FUN_SEL, 0); } 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 58d1fff6b3..3d9077d274 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 @@ -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 + */ #pragma once @@ -63,10 +55,14 @@ void __attribute__((noreturn)) ulp_riscv_shutdown(void); __ccount; }) +#if CONFIG_IDF_TARGET_ESP32S2 /* These are only approximate default numbers, the default frequency of the 8M oscillator is 8.5MHz +/- 5%, at the default DCAP setting */ #define ULP_RISCV_CYCLES_PER_US 8.5 +#elif CONFIG_IDF_TARGET_ESP32S3 +#define ULP_RISCV_CYCLES_PER_US 17.5 +#endif #define ULP_RISCV_CYCLES_PER_MS ULP_RISCV_CYCLES_PER_US*1000 /** diff --git a/docs/doxygen/Doxyfile_esp32s3 b/docs/doxygen/Doxyfile_esp32s3 index f3bd42dc1b..9ff2842ef7 100644 --- a/docs/doxygen/Doxyfile_esp32s3 +++ b/docs/doxygen/Doxyfile_esp32s3 @@ -8,6 +8,8 @@ INPUT += \ $(PROJECT_PATH)/components/driver/include/driver/pcnt.h \ $(PROJECT_PATH)/components/soc/$(IDF_TARGET)/include/soc/touch_sensor_channel.h \ $(PROJECT_PATH)/components/driver/$(IDF_TARGET)/include/driver/touch_sensor.h \ + $(PROJECT_PATH)/components/ulp/include/esp32s3/ulp_riscv.h \ + $(PROJECT_PATH)/components/ulp/include/$(IDF_TARGET)/ulp.h \ $(PROJECT_PATH)/components/usb/include/usb/usb_helpers.h \ $(PROJECT_PATH)/components/usb/include/usb/usb_host.h \ $(PROJECT_PATH)/components/usb/include/usb/usb_types_ch9.h \ diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index 09defeaa6f..a5e28665ae 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -37,7 +37,7 @@ API 指南 线程本地存储 工具 :SOC_ULP_SUPPORTED: ULP 协处理器 - :esp32s2: ULP-RISC-V 协处理器 + :SOC_RISCV_COPROC_SUPPORTED: ULP-RISC-V 协处理器 单元测试 (Target) 单元测试 (Linux Host) :SOC_USB_OTG_SUPPORTED: USB 控制台 diff --git a/examples/system/ulp_riscv/ds18b20_onewire/CMakeLists.txt b/examples/system/ulp_riscv/ds18b20_onewire/CMakeLists.txt index 937f77ace8..3e1310e924 100644 --- a/examples/system/ulp_riscv/ds18b20_onewire/CMakeLists.txt +++ b/examples/system/ulp_riscv/ds18b20_onewire/CMakeLists.txt @@ -2,5 +2,11 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +if(NOT IDF_TARGET STREQUAL "esp32s2") + #IDF-4514 + message(FATAL_ERROR "DO NOT BUILD THIS APP FOR ANY TARGET OTHER THAN ESP32-S2 OTHERWISE YOU MAY BRICK YOUR DEVICE") + return() +endif() + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(ulp_riscv_ds18b20_example) diff --git a/examples/system/ulp_riscv/gpio/CMakeLists.txt b/examples/system/ulp_riscv/gpio/CMakeLists.txt index d49885b79d..6207a44ed8 100644 --- a/examples/system/ulp_riscv/gpio/CMakeLists.txt +++ b/examples/system/ulp_riscv/gpio/CMakeLists.txt @@ -2,5 +2,11 @@ # in this exact order for cmake to work correctly cmake_minimum_required(VERSION 3.5) +if(NOT IDF_TARGET STREQUAL "esp32s2") + #IDF-4514 + message(FATAL_ERROR "DO NOT BUILD THIS APP FOR ANY TARGET OTHER THAN ESP32-S2 OTHERWISE YOU MAY BRICK YOUR DEVICE") + return() +endif() + include($ENV{IDF_PATH}/tools/cmake/project.cmake) project(ulp_riscv_example) diff --git a/tools/ci/check_copyright_ignore.txt b/tools/ci/check_copyright_ignore.txt index c75f99458e..ee5abf21c2 100644 --- a/tools/ci/check_copyright_ignore.txt +++ b/tools/ci/check_copyright_ignore.txt @@ -2062,19 +2062,14 @@ components/touch_element/touch_element.c components/touch_element/touch_matrix.c components/touch_element/touch_slider.c components/ulp/esp32ulp_mapgen.py -components/ulp/include/ulp_common.h components/ulp/ld/esp32.ulp.ld components/ulp/ld/esp32s2.ulp.riscv.ld components/ulp/test/esp32/test_ulp.c components/ulp/test/esp32/test_ulp_as.c -components/ulp/test/esp32s2/test_ulp_riscv.c -components/ulp/test/ulp_riscv/test_main.c 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_gpio.h components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_register_ops.h -components/ulp/ulp_riscv/include/ulp_riscv/ulp_riscv_utils.h components/ulp/ulp_riscv/ulp_riscv_utils.c components/unity/include/priv/setjmp.h components/unity/include/unity_config.h diff --git a/tools/unit-test-app/sdkconfig.defaults.esp32s3 b/tools/unit-test-app/sdkconfig.defaults.esp32s3 index 117349c012..57f3096558 100644 --- a/tools/unit-test-app/sdkconfig.defaults.esp32s3 +++ b/tools/unit-test-app/sdkconfig.defaults.esp32s3 @@ -1 +1,6 @@ CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP_SYSTEM_MEMPROT_FEATURE=n + +CONFIG_ESP32S3_ULP_COPROC_ENABLED=y +CONFIG_ESP32S3_ULP_COPROC_RISCV=y +CONFIG_ESP32S3_ULP_COPROC_RESERVE_MEM=4096