Răsfoiți Sursa

Merge branch 'feature/riscv_arch' into 'master'

Add RISC-V support

Closes IDF-2359

See merge request espressif/esp-idf!11140
Angus Gratton 5 ani în urmă
părinte
comite
935e4b4d62
100 a modificat fișierele cu 2254 adăugiri și 772 ștergeri
  1. 11 0
      Kconfig
  2. 2 0
      components/app_trace/app_trace.c
  3. 1 1
      components/bootloader/subproject/CMakeLists.txt
  4. 2 20
      components/bootloader_support/src/bootloader_mem.c
  5. 3 3
      components/bootloader_support/src/bootloader_panic.c
  6. 4 3
      components/bootloader_support/src/bootloader_random.c
  7. 1 1
      components/esp-tls/esp_tls.c
  8. 2 2
      components/esp32/CMakeLists.txt
  9. 2 2
      components/esp32s2/CMakeLists.txt
  10. 2 2
      components/esp32s3/CMakeLists.txt
  11. 4 1
      components/esp_common/CMakeLists.txt
  12. 1 1
      components/esp_common/include/esp_err.h
  13. 4 6
      components/esp_common/include/esp_private/gdbstub.h
  14. 3 4
      components/esp_common/test/test_atomic.c
  15. 1 1
      components/esp_eth/include/esp_eth.h
  16. 2 1
      components/esp_eth/src/esp_eth.c
  17. 2 2
      components/esp_gdbstub/CMakeLists.txt
  18. 1 1
      components/esp_gdbstub/esp32/gdbstub_esp32.c
  19. 1 1
      components/esp_gdbstub/esp32s2/gdbstub_esp32s2.c
  20. 10 0
      components/esp_hw_support/compare_set.c
  21. 19 0
      components/esp_hw_support/cpu_util.c
  22. 16 5
      components/esp_hw_support/include/soc/compare_set.h
  23. 13 4
      components/esp_hw_support/include/soc/cpu.h
  24. 10 10
      components/esp_hw_support/include/soc/spinlock.h
  25. 19 0
      components/esp_pm/pm_impl_riscv_temp.c
  26. 3 2
      components/esp_ringbuf/ringbuf.c
  27. 1 1
      components/esp_system/component.mk
  28. 20 0
      components/esp_system/include/esp_private/panic_internal.h
  29. 3 3
      components/esp_system/intr_alloc.c
  30. 1 0
      components/esp_system/linker.lf
  31. 20 2
      components/esp_system/panic.c
  32. 2 2
      components/esp_system/port/CMakeLists.txt
  33. 127 0
      components/esp_system/port/arch/riscv/panic_arch.c
  34. 497 0
      components/esp_system/port/arch/xtensa/panic_arch.c
  35. 0 0
      components/esp_system/port/arch/xtensa/panic_handler_asm.S
  36. 15 3
      components/esp_system/port/cpu_start.c
  37. 0 2
      components/esp_system/port/esp32/component.mk
  38. 33 464
      components/esp_system/port/panic_handler.c
  39. 6 1
      components/esp_system/port/soc/esp32/CMakeLists.txt
  40. 5 2
      components/esp_system/port/soc/esp32/clk.c
  41. 2 0
      components/esp_system/port/soc/esp32/component.mk
  42. 0 0
      components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S
  43. 0 0
      components/esp_system/port/soc/esp32/intr.c
  44. 0 0
      components/esp_system/port/soc/esp32/reset_reason.c
  45. 7 1
      components/esp_system/port/soc/esp32s2/CMakeLists.txt
  46. 0 0
      components/esp_system/port/soc/esp32s2/async_memcpy_impl_cp_dma.c
  47. 0 0
      components/esp_system/port/soc/esp32s2/clk.c
  48. 0 0
      components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S
  49. 0 0
      components/esp_system/port/soc/esp32s2/reset_reason.c
  50. 0 0
      components/esp_system/port/soc/esp32s2/usb_console.c
  51. 7 1
      components/esp_system/port/soc/esp32s3/CMakeLists.txt
  52. 0 0
      components/esp_system/port/soc/esp32s3/clk.c
  53. 0 0
      components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S
  54. 0 0
      components/esp_system/port/soc/esp32s3/reset_reason.c
  55. 1 1
      components/esp_timer/src/esp_timer.c
  56. 0 1
      components/esp_timer/src/ets_timer_legacy.c
  57. 0 1
      components/espcoredump/include/esp_core_dump.h
  58. 7 1
      components/espcoredump/src/core_dump_port.c
  59. 44 21
      components/freertos/CMakeLists.txt
  60. 3 3
      components/freertos/component.mk
  61. 1 1
      components/freertos/linker.lf
  62. 135 0
      components/freertos/port/port_common.c
  63. 277 0
      components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h
  64. 0 0
      components/freertos/port/riscv/include/freertos/portbenchmark.h
  65. 310 0
      components/freertos/port/riscv/include/freertos/portmacro.h
  66. 369 0
      components/freertos/port/riscv/port.c
  67. 87 0
      components/freertos/port/riscv/portasm.S
  68. 0 0
      components/freertos/port/xtensa/include/freertos/FreeRTOSConfig.h
  69. 46 0
      components/freertos/port/xtensa/include/freertos/portbenchmark.h
  70. 30 65
      components/freertos/port/xtensa/include/freertos/portmacro.h
  71. 0 0
      components/freertos/port/xtensa/include/freertos/portmacro_priv.h
  72. 0 0
      components/freertos/port/xtensa/include/freertos/xtensa_api.h
  73. 0 0
      components/freertos/port/xtensa/include/freertos/xtensa_config.h
  74. 0 0
      components/freertos/port/xtensa/include/freertos/xtensa_context.h
  75. 0 0
      components/freertos/port/xtensa/include/freertos/xtensa_rtos.h
  76. 0 0
      components/freertos/port/xtensa/include/freertos/xtensa_timer.h
  77. 7 82
      components/freertos/port/xtensa/port.c
  78. 0 0
      components/freertos/port/xtensa/portasm.S
  79. 0 0
      components/freertos/port/xtensa/readme_xtensa.txt
  80. 0 0
      components/freertos/port/xtensa/xt_asm_utils.h
  81. 0 0
      components/freertos/port/xtensa/xtensa_context.S
  82. 0 0
      components/freertos/port/xtensa/xtensa_init.c
  83. 0 0
      components/freertos/port/xtensa/xtensa_loadstore_handler.S
  84. 0 0
      components/freertos/port/xtensa/xtensa_overlay_os_hook.c
  85. 0 0
      components/freertos/port/xtensa/xtensa_vector_defaults.S
  86. 0 0
      components/freertos/port/xtensa/xtensa_vectors.S
  87. 0 2
      components/freertos/test/test_float_in_isr.c
  88. 2 0
      components/freertos/test/test_freertos_backported_functions.c
  89. 15 15
      components/freertos/test/test_freertos_isinisrcontext.c
  90. 0 2
      components/freertos/test/test_freertos_scheduling_time.c
  91. 1 1
      components/freertos/test/test_freertos_task_notify.c
  92. 18 7
      components/freertos/test/test_isr_latency.c
  93. 0 1
      components/freertos/test/test_newlib_reent.c
  94. 0 1
      components/freertos/test/test_panic.c
  95. 5 5
      components/freertos/test/test_preemption.c
  96. 3 3
      components/freertos/test/test_spinlocks.c
  97. 0 1
      components/freertos/test/test_suspend_scheduler.c
  98. 0 1
      components/freertos/test/test_task_suspend_resume.c
  99. 2 0
      components/freertos/test/test_thread_local.c
  100. 6 2
      components/freertos/test/test_xtensa_loadstore_handler.c

+ 11 - 0
Kconfig

@@ -13,6 +13,14 @@ mainmenu "Espressif IoT Development Framework Configuration"
         bool
         option env="IDF_ENV_FPGA"
 
+    config IDF_TARGET_ARCH_RISCV
+        bool
+        default "n"
+
+    config IDF_TARGET_ARCH_XTENSA
+        bool
+        default "n"
+
     config IDF_TARGET
         # This option records the IDF target when sdkconfig is generated the first time.
         # It is not updated if environment variable $IDF_TARGET changes later, and
@@ -24,15 +32,18 @@ mainmenu "Espressif IoT Development Framework Configuration"
     config IDF_TARGET_ESP32
         bool
         default "y" if IDF_TARGET="esp32"
+        select IDF_TARGET_ARCH_XTENSA
 
     config IDF_TARGET_ESP32S2
         bool
         default "y" if IDF_TARGET="esp32s2"
         select FREERTOS_UNICORE
+        select IDF_TARGET_ARCH_XTENSA
 
     config IDF_TARGET_ESP32S3
         bool
         default "y" if IDF_TARGET="esp32s3"
+        select IDF_TARGET_ARCH_XTENSA
 
     choice IDF_TARGET_ESP32S3_BETA_VERSION
         prompt "ESP32-S3 beta version"

+ 2 - 0
components/app_trace/app_trace.c

@@ -161,8 +161,10 @@
 #if CONFIG_IDF_TARGET_ESP32S2
 #include "soc/sensitive_reg.h"
 #endif
+#if __XTENSA__
 #include "eri.h"
 #include "trax.h"
+#endif
 #include "soc/timer_periph.h"
 #include "freertos/FreeRTOS.h"
 #include "esp_app_trace.h"

+ 1 - 1
components/bootloader/subproject/CMakeLists.txt

@@ -30,7 +30,7 @@ set(COMPONENTS
     efuse)
 set(BOOTLOADER_BUILD 1)
 include("${IDF_PATH}/tools/cmake/project.cmake")
-set(common_req log esp_rom esp_common esp_hw_support hal xtensa)
+set(common_req log esp_rom esp_common esp_hw_support hal)
 if(LEGACY_INCLUDE_COMMON_HEADERS)
     list(APPEND common_req soc hal)
 endif()

+ 2 - 20
components/bootloader_support/src/bootloader_mem.c

@@ -14,35 +14,17 @@
 
 #include <stdbool.h>
 
-#include "xtensa/config/core.h"
 #include "hal/cpu_hal.h"
 #include "hal/mpu_hal.h"
 #include "hal/mpu_types.h"
 #include "soc/soc_caps.h"
 #include "bootloader_mem.h"
-#include "xt_instr_macros.h"
-#include "xtensa/config/specreg.h"
-
-static inline void cpu_configure_region_protection(void)
-{
-    /* Currently, the only supported chips esp32 and esp32s2
-     * have the same configuration. Move this to the port layer once
-     * more chips with different configurations are supported.
-     *
-     * Both chips have the address space divided into 8 regions, 512MB each.
-     */
-    const int illegal_regions[] = {0, 4, 5, 6, 7}; // 0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000
-    for (int i = 0; i < sizeof(illegal_regions) / sizeof(illegal_regions[0]); ++i) {
-        mpu_hal_set_region_access(illegal_regions[i], MPU_REGION_ILLEGAL);
-    }
-
-    mpu_hal_set_region_access(1, MPU_REGION_RW); // 0x20000000
-}
+#include "soc/cpu.h"
 
 void bootloader_init_mem(void)
 {
     cpu_hal_init_hwloop();
 
     // protect memory region
-    cpu_configure_region_protection();
+    esp_cpu_configure_region_protection();
 }

+ 3 - 3
components/bootloader_support/src/bootloader_panic.c

@@ -14,7 +14,7 @@
 
 #include "esp_log.h"
 #include "bootloader_common.h"
-#include "soc/cpu.h"
+#include "hal/cpu_hal.h"
 #include "esp_rom_sys.h"
 
 
@@ -30,8 +30,8 @@ void abort(void)
 #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT
     esp_rom_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3);
 #endif
-    if (esp_cpu_in_ocd_debug_mode()) {
-        __asm__("break 0,0");
+    if (cpu_hal_is_debugger_attached()) {
+        cpu_hal_break();
     }
     while (1) {
     }

+ 4 - 3
components/bootloader_support/src/bootloader_random.c

@@ -13,7 +13,7 @@
 // limitations under the License.
 #include "sdkconfig.h"
 #include "bootloader_random.h"
-#include "soc/cpu.h"
+#include "hal/cpu_hal.h"
 #include "soc/wdev_reg.h"
 
 #ifndef BOOTLOADER_BUILD
@@ -44,13 +44,14 @@
                values.
             */
             random = REG_READ(WDEV_RND_REG);
-            RSR(CCOUNT, start);
+            start = cpu_hal_get_cycle_count();
             do {
                 random ^= REG_READ(WDEV_RND_REG);
-                RSR(CCOUNT, now);
+                now = cpu_hal_get_cycle_count();
             } while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */
         }
         buffer_bytes[i] = random >> ((i % 4) * 8);
     }
 }
+
 #endif // BOOTLOADER_BUILD

+ 1 - 1
components/esp-tls/esp_tls.c

@@ -280,7 +280,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c
             }
             if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) {
                 int error;
-                unsigned int len = sizeof(error);
+                socklen_t len = sizeof(error);
                 /* pending error check */
                 if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {
                     ESP_LOGD(TAG, "Non blocking connect failed");

+ 2 - 2
components/esp32/CMakeLists.txt

@@ -7,7 +7,7 @@ idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER)
 
 if(BOOTLOADER_BUILD)
     # For bootloader, all we need from esp32 is headers
-    idf_component_register(INCLUDE_DIRS include)
+    idf_component_register(INCLUDE_DIRS include REQUIRES xtensa)
     target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.peripherals.ld")
 else()
     # Regular app build
@@ -25,7 +25,7 @@ else()
 
     set(include_dirs "include")
 
-    set(requires driver efuse soc) #unfortunately rom/uart uses SOC registers directly
+    set(requires driver efuse soc xtensa) #unfortunately rom/uart uses SOC registers directly
 
     # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
     # esp_timer is added here because cpu_start.c uses esp_timer

+ 2 - 2
components/esp32s2/CMakeLists.txt

@@ -6,7 +6,7 @@ endif()
 
 if(BOOTLOADER_BUILD)
     # For bootloader, all we need from esp32s2 is headers
-    idf_component_register(INCLUDE_DIRS include)
+    idf_component_register(INCLUDE_DIRS include REQUIRES xtensa)
     target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32s2.peripherals.ld")
 else()
     # Regular app build
@@ -26,7 +26,7 @@ else()
 
     set(include_dirs "include")
 
-    set(requires driver efuse)
+    set(requires driver efuse xtensa)
 
     # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.
     # esp_timer is added here because cpu_start.c uses esp_timer

+ 2 - 2
components/esp32s3/CMakeLists.txt

@@ -7,7 +7,7 @@ endif()
 
 if(BOOTLOADER_BUILD)
     # For bootloader, all we need from esp32s3 is headers
-    idf_component_register(INCLUDE_DIRS include)
+    idf_component_register(INCLUDE_DIRS include REQUIRES xtensa)
     target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32s3.peripherals.ld")
 else()
     # Regular app build
@@ -25,7 +25,7 @@ else()
              "system_api_esp32s3.c")
     set(include_dirs "include")
 
-    set(requires driver efuse soc) #unfortunately rom/uart uses SOC registers directly
+    set(requires driver efuse soc xtensa) #unfortunately rom/uart uses SOC registers directly
 
     # driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t
     # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function.

+ 4 - 1
components/esp_common/CMakeLists.txt

@@ -14,7 +14,6 @@ else()
     # Regular app build
     list(APPEND srcs "src/brownout.c"
              "src/esp_err.c"
-             "src/dbg_stubs.c"
              "src/esp_err_to_name.c"
              "src/freertos_hooks.c"
              "src/mac_addr.c"
@@ -22,6 +21,10 @@ else()
              "src/task_wdt.c"
              "src/int_wdt.c")
 
+    if(NOT CONFIG_IDF_TARGET_ESP32C3)
+        list(APPEND srcs "src/dbg_stubs.c")
+    endif()
+
     # Note: esp_ipc, esp_pm added as a public requirement to keep compatibility as to be located here.
     idf_component_register(SRCS "${srcs}"
                            INCLUDE_DIRS include

+ 1 - 1
components/esp_common/include/esp_err.h

@@ -21,7 +21,7 @@
 extern "C" {
 #endif
 
-typedef int32_t esp_err_t;
+typedef int esp_err_t;
 
 /* Definitions for error constants. */
 #define ESP_OK          0       /*!< esp_err_t value indicating success (no error) */

+ 4 - 6
components/esp_common/include/esp_private/gdbstub.h

@@ -11,12 +11,10 @@
 // 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.
-#ifndef GDBSTUB_H
-#define GDBSTUB_H
+#pragma once
 
-#include <xtensa/config/core.h>
-#include "freertos/xtensa_api.h"
+/* This header exists to avoid making esp_common depend on gdbstub component for panic handler support */
 
-void esp_gdbstub_panic_handler(XtExcFrame *frame) __attribute__((noreturn));
+typedef void esp_gdbstub_frame_t;
 
-#endif
+void esp_gdbstub_panic_handler(esp_gdbstub_frame_t *frame) __attribute__((noreturn));

+ 3 - 4
components/esp_common/test/test_atomic.c

@@ -2,13 +2,12 @@
 #include <stdatomic.h>
 #include "esp_log.h"
 #include "esp_attr.h"
-#include "freertos/xtensa_api.h"
-
+#include "hal/cpu_hal.h"
 #include "../cache_utils.h"
 
 #define RECORD_TIME_PREPARE() uint32_t __t1, __t2
-#define RECORD_TIME_START()   do {__t1 = xthal_get_ccount();}while(0)
-#define RECORD_TIME_END(p_time) do{__t2 = xthal_get_ccount(); *p_time = (__t2-__t1);}while(0)
+#define RECORD_TIME_START()   do {__t1 = cpu_hal_get_cycle_count();}while(0)
+#define RECORD_TIME_END(p_time) do{__t2 = cpu_hal_get_cycle_count(); *p_time = (__t2-__t1);}while(0)
 
 
 #define TEST_TIMES  11

+ 1 - 1
components/esp_eth/include/esp_eth.h

@@ -192,7 +192,7 @@ esp_err_t esp_eth_update_input_path(
 *       - ESP_ERR_INVALID_ARG: transmit frame buffer failed because of some invalid argument
 *       - ESP_FAIL: transmit frame buffer failed because some other error occurred
 */
-esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, uint32_t length);
+esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length);
 
 /**
 * @brief General Receive

+ 2 - 1
components/esp_eth/src/esp_eth.c

@@ -19,6 +19,7 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/timers.h"
+#include "esp_heap_caps.h"
 
 static const char *TAG = "esp_eth";
 #define ETH_CHECK(a, str, goto_tag, ret_value, ...)                               \
@@ -317,7 +318,7 @@ err:
     return ret;
 }
 
-esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, uint32_t length)
+esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length)
 {
     esp_err_t ret = ESP_OK;
     esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl;

+ 2 - 2
components/esp_gdbstub/CMakeLists.txt

@@ -6,8 +6,8 @@ set(esp_gdbstub_srcs "src/gdbstub.c"
                      "xtensa/gdbstub_xtensa.c")
 
 idf_component_register(SRCS "${esp_gdbstub_srcs}"
-                       INCLUDE_DIRS "include"
-                       PRIV_INCLUDE_DIRS "private_include" "${target}" "xtensa"
+                       INCLUDE_DIRS "include" "xtensa" "${target}"
+                       PRIV_INCLUDE_DIRS "private_include"
                        LDFRAGMENTS "linker.lf"
                        REQUIRES "freertos"
                        PRIV_REQUIRES "soc" "xtensa" "esp_rom")

+ 1 - 1
components/esp_gdbstub/esp32/gdbstub_esp32.c

@@ -42,7 +42,7 @@ void esp_gdbstub_putchar(int c)
 int esp_gdbstub_readmem(intptr_t addr)
 {
     if (addr < 0x20000000 || addr >= 0x80000000) {
-        /* see cpu_configure_region_protection */
+        /* see esp_cpu_configure_region_protection */
         return -1;
     }
     uint32_t val_aligned = *(uint32_t *)(addr & (~3));

+ 1 - 1
components/esp_gdbstub/esp32s2/gdbstub_esp32s2.c

@@ -42,7 +42,7 @@ void esp_gdbstub_putchar(int c)
 int esp_gdbstub_readmem(intptr_t addr)
 {
     if (addr < 0x20000000 || addr >= 0x80000000) {
-        /* see cpu_configure_region_protection */
+        /* see esp_cpu_configure_region_protection */
         return -1;
     }
     uint32_t val_aligned = *(uint32_t *)(addr & (~3));

+ 10 - 0
components/esp_hw_support/compare_set.c

@@ -13,6 +13,9 @@
 // limitations under the License.
 #include "soc/compare_set.h"
 #include "soc/spinlock.h"
+#include "soc/soc_caps.h"
+
+#if __XTENSA__ && SOC_SPIRAM_SUPPORTED
 
 static spinlock_t global_extram_lock = SPINLOCK_INITIALIZER;
 
@@ -37,3 +40,10 @@ void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t
 
     *set = old_value;
 }
+#else // __XTENSA__ && SOC_SPIRAM_SUPPORTED
+
+void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
+{
+    compare_and_set_native(addr, compare, set);
+}
+#endif // endif

+ 19 - 0
components/esp_hw_support/cpu_util.c

@@ -21,6 +21,7 @@
 #include "hal/cpu_hal.h"
 #include "esp_debug_helpers.h"
 #include "hal/cpu_types.h"
+#include "hal/mpu_hal.h"
 
 #include "hal/soc_hal.h"
 #include "soc/soc_caps.h"
@@ -90,3 +91,21 @@ void IRAM_ATTR esp_set_breakpoint_if_jtag(void *fn)
         cpu_hal_set_breakpoint(0, fn);
     }
 }
+
+#if __XTENSA__
+
+void esp_cpu_configure_region_protection(void)
+{
+    /* Note: currently this is configured the same on all Xtensa targets
+     *
+     * Both chips have the address space divided into 8 regions, 512MB each.
+     */
+    const int illegal_regions[] = {0, 4, 5, 6, 7}; // 0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000
+    for (int i = 0; i < sizeof(illegal_regions) / sizeof(illegal_regions[0]); ++i) {
+        mpu_hal_set_region_access(illegal_regions[i], MPU_REGION_ILLEGAL);
+    }
+
+    mpu_hal_set_region_access(1, MPU_REGION_RW); // 0x20000000
+}
+
+#endif

+ 16 - 5
components/esp_hw_support/include/soc/compare_set.h

@@ -12,14 +12,16 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#ifndef __COMPARE_SET_H
-#define __COMPARE_SET_H
+#pragma once
 
 #include <stdint.h>
 #include <stdbool.h>
 #include "soc/cpu.h"
 #include "soc/soc_memory_layout.h"
+
+#if __XTENSA__
 #include "xtensa/xtruntime.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -35,20 +37,31 @@ static inline void __attribute__((always_inline)) compare_and_set_native(volatil
         :"r"(addr), "r"(compare), "0"(*set)
     );
 #else
+    uint32_t old_value;
+
+#ifdef __XTENSA__
     // No S32C1I, so do this by disabling and re-enabling interrupts (slower)
-    uint32_t intlevel, old_value;
+    uint32_t intlevel;
     __asm__ __volatile__ ("rsil %0, " XTSTR(XCHAL_EXCM_LEVEL) "\n"
                           : "=r"(intlevel));
+#else
+    unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
+#endif
 
     old_value = *addr;
     if (old_value == compare) {
         *addr = *set;
     }
 
+#ifdef __XTENSA__
     __asm__ __volatile__ ("memw \n"
                           "wsr %0, ps\n"
                           :: "r"(intlevel));
 
+#else
+    RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
+#endif
+
     *set = old_value;
 #endif
 }
@@ -59,5 +72,3 @@ void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t
 #ifdef __cplusplus
 }
 #endif
-
-#endif

+ 13 - 4
components/esp_hw_support/include/soc/cpu.h

@@ -18,11 +18,16 @@
 #include <stdint.h>
 #include <stdbool.h>
 #include <stddef.h>
+
+#if __XTENSA__
+#include "xt_instr_macros.h"
+// [refactor-todo] not actually needed in this header now,
+// but kept for compatibility
 #include "xtensa/corebits.h"
 #include "xtensa/config/core.h"
 
 #include "xtensa/config/specreg.h"
-#include "xt_instr_macros.h"
+#endif
 
 #include "hal/cpu_hal.h"
 
@@ -91,11 +96,15 @@ typedef uint32_t esp_cpu_ccount_t;
 
 static inline esp_cpu_ccount_t esp_cpu_get_ccount(void)
 {
-    uint32_t result;
-    RSR(CCOUNT, result);
-    return result;
+    return cpu_hal_get_cycle_count();
 }
 
+/**
+ * @brief Configure CPU to disable access to invalid memory regions
+ *
+ */
+void esp_cpu_configure_region_protection(void);
+
 #ifdef __cplusplus
 }
 #endif

+ 10 - 10
components/esp_hw_support/include/soc/spinlock.h

@@ -11,15 +11,19 @@
 // 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.
-#ifndef __SOC_SPINLOCK_H
-#define __SOC_SPINLOCK_H
+#pragma once
 
 #include <stdint.h>
 #include <stdbool.h>
+#include "sdkconfig.h"
 #include "soc/cpu.h"
+#include "hal/cpu_hal.h"
 #include "soc/soc_memory_layout.h"
 #include "soc/compare_set.h"
+
+#if __XTENSA__
 #include "xtensa/xtruntime.h"
+#endif
 
 #ifdef __cplusplus
 extern "C" {
@@ -62,7 +66,7 @@ static inline void __attribute__((always_inline)) spinlock_initialize(spinlock_t
  */
 static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *lock, int32_t timeout)
 {
-#if !CONFIG_FREERTOS_UNICORE
+#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD
     uint32_t result;
     uint32_t irq_status;
     uint32_t ccount_start;
@@ -106,7 +110,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
 
         if (timeout != SPINLOCK_WAIT_FOREVER) {
             uint32_t ccount_now;
-            RSR(CCOUNT, ccount_now);
+            ccount_now = cpu_hal_get_cycle_count();
             if (ccount_now - ccount_start > (unsigned)timeout) {
                 XTOS_RESTORE_INTLEVEL(irq_status);
                 return false;
@@ -123,10 +127,9 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
     XTOS_RESTORE_INTLEVEL(irq_status);
     return true;
 
-#else
+#else  // !CONFIG_FREERTOS_UNICORE
     return true;
 #endif
-
 }
 
 /**
@@ -135,8 +138,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
  */
 static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *lock)
 {
-
-#if !CONFIG_FREERTOS_UNICORE
+#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD
     uint32_t irq_status;
     uint32_t core_id;
 
@@ -160,5 +162,3 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l
 #ifdef __cplusplus
 }
 #endif
-
-#endif

+ 19 - 0
components/esp_pm/pm_impl_riscv_temp.c

@@ -0,0 +1,19 @@
+// Copyright 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.
+
+/* TODO ESP32-C3 Placeholder until IDF-2107 when this file can be dropped */
+void esp_pm_impl_waiti(void)
+{
+
+}

+ 3 - 2
components/esp_ringbuf/ringbuf.c

@@ -20,8 +20,9 @@
 #include "freertos/ringbuf.h"
 
 //32-bit alignment macros
-#define rbALIGN_SIZE( xSize )       ( ( xSize + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK )
-#define rbCHECK_ALIGNED( pvPtr )    ( ( ( UBaseType_t ) ( pvPtr ) & portBYTE_ALIGNMENT_MASK ) == 0 )
+#define rbALIGN_MASK (0x03)
+#define rbALIGN_SIZE( xSize )       ( ( xSize + rbALIGN_MASK ) & ~rbALIGN_MASK )
+#define rbCHECK_ALIGNED( pvPtr )    ( ( ( UBaseType_t ) ( pvPtr ) & rbALIGN_MASK ) == 0 )
 
 //Ring buffer flags
 #define rbALLOW_SPLIT_FLAG          ( ( UBaseType_t ) 1 )   //The ring buffer allows items to be split

+ 1 - 1
components/esp_system/component.mk

@@ -5,7 +5,7 @@ COMPONENT_ADD_INCLUDEDIRS := include
 COMPONENT_PRIV_INCLUDEDIRS := private_include port/include
 COMPONENT_ADD_LDFRAGMENTS += linker.lf
 
--include $(COMPONENT_PATH)/port/$(SOC_NAME)/component.mk
+include $(COMPONENT_PATH)/port/soc/$(SOC_NAME)/component.mk
 
 # disable stack protection in files which are involved in initialization of that feature
 startup.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS))

+ 20 - 0
components/esp_system/include/esp_private/panic_internal.h

@@ -16,14 +16,20 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+
+#include "soc/soc_caps.h"
+
 #include "sdkconfig.h"
 
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 extern bool g_panic_abort;
 
+extern void *g_exc_frames[SOC_CPU_CORES_NUM];
+
 // Function to print longer amounts of information such as the details
 // and backtrace field of panic_info_t. These functions should limit themselves
 // to printing to the console and should do other more involved processing,
@@ -72,6 +78,20 @@ void panic_print_hex(int h);
 
 void __attribute__((noreturn)) panic_abort(const char *details);
 
+void panic_arch_fill_info(void *frame, panic_info_t *info);
+
+void panic_soc_fill_info(void *frame, panic_info_t *info);
+
+void panic_print_registers(const void *frame, int core);
+
+void panic_print_backtrace(const void *frame, int core);
+
+uint32_t panic_get_address(const void* frame);
+
+void panic_set_address(void *frame, uint32_t addr);
+
+uint32_t panic_get_cause(const void* frame);
+
 #ifdef __cplusplus
 }
 #endif

+ 3 - 3
components/esp_system/intr_alloc.c

@@ -531,7 +531,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre
         vd->shared_vec_info=sh_vec;
         vd->flags|=VECDESC_FL_SHARED;
         //(Re-)set shared isr handler to new value.
-        xt_set_interrupt_handler(intr, shared_intr_isr, vd);
+        interrupt_controller_hal_set_int_handler(intr, shared_intr_isr, vd);
     } else {
         //Mark as unusable for other interrupt sources. This is ours now!
         vd->flags=VECDESC_FL_NONSHARED;
@@ -801,11 +801,11 @@ void IRAM_ATTR esp_intr_noniram_enable(void)
 //equivalents here.
 
 
-void IRAM_ATTR ets_isr_unmask(unsigned int mask) {
+void IRAM_ATTR ets_isr_unmask(uint32_t mask) {
     interrupt_controller_hal_enable_interrupts(mask);
 }
 
-void IRAM_ATTR ets_isr_mask(unsigned int mask) {
+void IRAM_ATTR ets_isr_mask(uint32_t mask) {
     interrupt_controller_hal_disable_interrupts(mask);
 }
 

+ 1 - 0
components/esp_system/linker.lf

@@ -3,6 +3,7 @@ archive: libesp_system.a
 entries:
     panic (noflash)
     panic_handler (noflash)
+    panic_arch (noflash)
     reset_reason (noflash)
     system_api:esp_system_abort (noflash)
     startup:do_core_init (default)

+ 20 - 2
components/esp_system/panic.c

@@ -17,7 +17,6 @@
 #include "esp_attr.h"
 
 #include "esp_private/system_internal.h"
-#include "esp_private/gdbstub.h"
 #include "esp_private/usb_console.h"
 #include "esp_ota_ops.h"
 
@@ -47,11 +46,30 @@
 
 #include "sdkconfig.h"
 
+#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
+#include "esp_private/gdbstub.h"
+#endif
+
+#if CONFIG_ESP32_ENABLE_COREDUMP
+#include "esp_core_dump.h"
+#endif
+
+#if CONFIG_APPTRACE_ENABLE
+#include "esp_app_trace.h"
+#if CONFIG_SYSVIEW_ENABLE
+#include "SEGGER_RTT.h"
+#endif
+
 #if CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO == -1
 #define APPTRACE_ONPANIC_HOST_FLUSH_TMO   ESP_APPTRACE_TMO_INFINITE
 #else
 #define APPTRACE_ONPANIC_HOST_FLUSH_TMO   (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO)
 #endif
+#endif // CONFIG_APPTRACE_ENABLE
+
+#if CONFIG_ESP_SYSTEM_PANIC_GDBSTUB
+#include "esp_private/gdbstub.h"
+#endif
 
 bool g_panic_abort = false;
 static char *s_panic_abort_details = NULL;
@@ -291,7 +309,7 @@ void esp_panic_handler(panic_info_t *info)
     wdt_hal_disable(&rtc_wdt_ctx);
     wdt_hal_write_protect_enable(&rtc_wdt_ctx);
     panic_print_str("Entering gdb stub now.\r\n");
-    esp_gdbstub_panic_handler((XtExcFrame*) info->frame);
+    esp_gdbstub_panic_handler((esp_gdbstub_frame_t*)info->frame);
 #else
 #if CONFIG_ESP_COREDUMP_ENABLE
     static bool s_dumping_core;

+ 2 - 2
components/esp_system/port/CMakeLists.txt

@@ -1,9 +1,9 @@
 target_include_directories(${COMPONENT_LIB} PRIVATE include)
 
-set(srcs "panic_handler.c" "panic_handler_asm.S" "cpu_start.c")
+set(srcs "cpu_start.c" "panic_handler.c")
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
 
 target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
 
 idf_build_get_property(target IDF_TARGET)
-add_subdirectory(${target})
+add_subdirectory(soc/${target})

+ 127 - 0
components/esp_system/port/arch/riscv/panic_arch.c

@@ -0,0 +1,127 @@
+
+// Copyright 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 <stdio.h>
+
+#include "esp_private/panic_internal.h"
+#include "riscv/rvruntime-frames.h"
+
+extern void esp_panic_handler(panic_info_t *);
+
+void panic_print_registers(const void *f, int core)
+{
+    uint32_t *regs = (uint32_t *)f;
+
+    // only print ABI name
+    const char *desc[] = {
+        "MEPC    ", "RA      ", "SP      ", "GP      ", "TP      ", "T0      ", "T1      ", "T2      ",
+        "S0/FP   ", "S1      ", "A0      ", "A1      ", "A2      ", "A3      ", "A4      ", "A5      ",
+        "A6      ", "A7      ", "S2      ", "S3      ", "S4      ", "S5      ", "S6      ", "S7      ",
+        "S8      ", "S9      ", "S10     ", "S11     ", "T3      ", "T4      ", "T5      ", "T6      ",
+        "MSTATUS ", "MTVEC   ", "MCAUSE  ", "MTVAL   ", "MHARTID "
+    };
+
+    panic_print_str("Core ");
+    panic_print_dec(((RvExcFrame *)f)->mhartid);
+    panic_print_str(" register dump:");
+
+    for (int x = 0; x < sizeof(desc) / sizeof(desc[0]); x += 4) {
+        panic_print_str("\r\n");
+        for (int y = 0; y < 4 && x + y < sizeof(desc) / sizeof(desc[0]); y++) {
+            if (desc[x + y][0] != 0) {
+                panic_print_str(desc[x + y]);
+                panic_print_str(": 0x");
+                panic_print_hex(regs[x + y]);
+                panic_print_str("  ");
+            }
+        }
+    }
+}
+
+void panic_soc_fill_info(void *f, panic_info_t *info)
+{
+    // TODO ESP32-C3 IDF-2386 / support soc panic
+    return;
+}
+
+void panic_arch_fill_info(void *frame, panic_info_t *info)
+{
+    RvExcFrame *regs = (RvExcFrame *) frame;
+    info->core = 0;
+    info->exception = PANIC_EXCEPTION_FAULT;
+
+    //Please keep in sync with PANIC_RSN_* defines
+    static const char *reason[] = {
+        "Instruction address misaligned",
+        "Instruction access fault",
+        "Illegal instruction",
+        "Breakpoint",
+        "Load address misaligned",
+        "Load access fault",
+        "Store address misaligned",
+        "Store access fault",
+        "Environment call from U-mode",
+        "Environment call from S-mode",
+        NULL,
+        "Environment call from M-mode",
+        "Instruction page fault",
+        "Load page fault",
+        NULL,
+        "Store page fault",
+    };
+
+    if (regs->mcause < (sizeof(reason) / sizeof(reason[0]))) {
+        if (reason[regs->mcause] != NULL) {
+            info->reason = (reason[regs->mcause]);
+        }
+    }
+
+    info->description = "Exception was unhandled.";
+
+    info->addr = (void *) regs->mepc;
+    info->frame = &regs;
+}
+
+void panic_print_backtrace(const void *frame, int core)
+{
+    // Basic backtrace
+    panic_print_str("\r\nStack memory:\n");
+    uint32_t sp = (uint32_t)((RvExcFrame *)frame)->sp;
+    const int per_line = 8;
+    for (int x = 0; x < 1024; x += per_line * sizeof(uint32_t)) {
+        uint32_t *spp = (uint32_t *)(sp + x);
+        panic_print_hex(sp + x);
+        panic_print_str(": ");
+        for (int y = 0; y < per_line; y++) {
+            panic_print_str("0x");
+            panic_print_hex(spp[y]);
+            panic_print_char(y == per_line - 1 ? '\n' : ' ');
+        }
+    }
+}
+
+uint32_t panic_get_address(const void *f)
+{
+    return ((RvExcFrame *)f)->mepc;
+}
+
+uint32_t panic_get_cause(const void *f)
+{
+    return ((RvExcFrame *)f)->mcause;
+}
+
+void panic_set_address(void *f, uint32_t addr)
+{
+    ((RvExcFrame *)f)->mepc = addr;
+}

+ 497 - 0
components/esp_system/port/arch/xtensa/panic_arch.c

@@ -0,0 +1,497 @@
+// Copyright 2015-2016 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 "freertos/xtensa_context.h"
+#include "freertos/FreeRTOS.h"
+#include "freertos/task.h"
+
+#include "esp_debug_helpers.h"
+
+#include "esp_private/panic_internal.h"
+#include "esp_private/panic_reason.h"
+#include "soc/soc.h"
+
+#include "sdkconfig.h"
+
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/cache_err_int.h"
+#else
+#include "soc/extmem_reg.h"
+#include "soc/cache_memory.h"
+#include "soc/rtc_cntl_reg.h"
+#if CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/cache_err_int.h"
+#include "esp32s2/memprot.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/cache_err_int.h"
+#include "esp32s3/memprot.h"
+#endif
+#endif // CONFIG_IDF_TARGET_ESP32
+
+void panic_print_registers(const void *f, int core)
+{
+    XtExcFrame *frame = (XtExcFrame *) f;
+    int *regs = (int *)frame;
+
+    const char *sdesc[] = {
+        "PC      ", "PS      ", "A0      ", "A1      ", "A2      ", "A3      ", "A4      ", "A5      ",
+        "A6      ", "A7      ", "A8      ", "A9      ", "A10     ", "A11     ", "A12     ", "A13     ",
+        "A14     ", "A15     ", "SAR     ", "EXCCAUSE", "EXCVADDR", "LBEG    ", "LEND    ", "LCOUNT  "
+    };
+
+    /* only dump registers for 'real' crashes, if crashing via abort()
+       the register window is no longer useful.
+    */
+    panic_print_str("Core ");
+    panic_print_dec(core);
+    panic_print_str(" register dump:");
+
+    for (int x = 0; x < 24; x += 4) {
+        panic_print_str("\r\n");
+        for (int y = 0; y < 4; y++) {
+            if (sdesc[x + y][0] != 0) {
+                panic_print_str(sdesc[x + y]);
+                panic_print_str(": 0x");
+                panic_print_hex(regs[x + y + 1]);
+                panic_print_str("  ");
+            }
+        }
+    }
+
+    // If the core which triggers the interrupt watchpoint was in ISR context, dump the epc registers.
+    if (xPortInterruptedFromISRContext()
+#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
+            && ((core == 0 && frame->exccause == PANIC_RSN_INTWDT_CPU0) ||
+                (core == 1 && frame->exccause == PANIC_RSN_INTWDT_CPU1))
+#endif //!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
+        ) {
+
+        panic_print_str("\r\n");
+
+        uint32_t __value;
+        panic_print_str("Core ");
+        panic_print_dec(core);
+        panic_print_str(" was running in ISR context:\r\n");
+
+        __asm__("rsr.epc1 %0" : "=a"(__value));
+        panic_print_str("EPC1    : 0x");
+        panic_print_hex(__value);
+
+        __asm__("rsr.epc2 %0" : "=a"(__value));
+        panic_print_str("  EPC2    : 0x");
+        panic_print_hex(__value);
+
+        __asm__("rsr.epc3 %0" : "=a"(__value));
+        panic_print_str("  EPC3    : 0x");
+        panic_print_hex(__value);
+
+        __asm__("rsr.epc4 %0" : "=a"(__value));
+        panic_print_str("  EPC4    : 0x");
+        panic_print_hex(__value);
+    }
+}
+
+static void print_illegal_instruction_details(const void *f)
+{
+    XtExcFrame *frame  = (XtExcFrame *) f;
+    /* Print out memory around the instruction word */
+    uint32_t epc = frame->pc;
+    epc = (epc & ~0x3) - 4;
+
+    /* check that the address was sane */
+    if (epc < SOC_IROM_MASK_LOW || epc >= SOC_IROM_HIGH) {
+        return;
+    }
+    volatile uint32_t *pepc = (uint32_t *)epc;
+
+    panic_print_str("Memory dump at 0x");
+    panic_print_hex(epc);
+    panic_print_str(": ");
+
+    panic_print_hex(*pepc);
+    panic_print_str(" ");
+    panic_print_hex(*(pepc + 1));
+    panic_print_str(" ");
+    panic_print_hex(*(pepc + 2));
+}
+
+
+static void print_debug_exception_details(const void *f)
+{
+    int debug_rsn;
+    asm("rsr.debugcause %0":"=r"(debug_rsn));
+    panic_print_str("Debug exception reason: ");
+    if (debug_rsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) {
+        panic_print_str("SingleStep ");
+    }
+    if (debug_rsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) {
+        panic_print_str("HwBreakpoint ");
+    }
+    if (debug_rsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
+        //Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
+        //reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
+        //debugcause if the cause is watchpoint 1 and clearing it if it's watchpoint 0.
+        if (debug_rsn & (1 << 8)) {
+#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
+            int core = 0;
+
+#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
+            if (f == g_exc_frames[1]) {
+                core = 1;
+            }
+#endif
+
+            const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core));
+            panic_print_str("Stack canary watchpoint triggered (");
+            panic_print_str(name);
+            panic_print_str(") ");
+#else
+            panic_print_str("Watchpoint 1 triggered ");
+#endif
+        } else {
+            panic_print_str("Watchpoint 0 triggered ");
+        }
+    }
+    if (debug_rsn & XCHAL_DEBUGCAUSE_BREAK_MASK) {
+        panic_print_str("BREAK instr ");
+    }
+    if (debug_rsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) {
+        panic_print_str("BREAKN instr ");
+    }
+    if (debug_rsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) {
+        panic_print_str("DebugIntr ");
+    }
+}
+
+#if CONFIG_IDF_TARGET_ESP32S2
+static inline void print_cache_err_details(const void *f)
+{
+    uint32_t vaddr = 0, size = 0;
+    uint32_t status[2];
+    status[0] = REG_READ(EXTMEM_CACHE_DBG_STATUS0_REG);
+    status[1] = REG_READ(EXTMEM_CACHE_DBG_STATUS1_REG);
+    for (int i = 0; i < 32; i++) {
+        switch (status[0] & BIT(i)) {
+        case EXTMEM_IC_SYNC_SIZE_FAULT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC0_REG);
+            size = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC1_REG);
+            panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_IC_PRELOAD_SIZE_FAULT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_ADDR_REG);
+            size = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_SIZE_REG);
+            panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_ICACHE_REJECT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_ICACHE_REJECT_VADDR_REG);
+            panic_print_str("Icache reject error occurred while accessing the address 0x");
+            panic_print_hex(vaddr);
+
+            if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
+                panic_print_str(" (invalid mmu entry)");
+            }
+            panic_print_str("\r\n");
+            break;
+        default:
+            break;
+        }
+        switch (status[1] & BIT(i)) {
+        case EXTMEM_DC_SYNC_SIZE_FAULT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC0_REG);
+            size = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC1_REG);
+            panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_DC_PRELOAD_SIZE_FAULT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_ADDR_REG);
+            size = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_SIZE_REG);
+            panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_DCACHE_WRITE_FLASH_ST:
+            panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
+            break;
+        case EXTMEM_DCACHE_REJECT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_DCACHE_REJECT_VADDR_REG);
+            panic_print_str("Dcache reject error occurred while accessing the address 0x");
+            panic_print_hex(vaddr);
+
+            if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
+                panic_print_str(" (invalid mmu entry)");
+            }
+            panic_print_str("\r\n");
+            break;
+        case EXTMEM_MMU_ENTRY_FAULT_ST:
+            vaddr = REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_VADDR_REG);
+            panic_print_str("MMU entry fault error occurred while accessing the address 0x");
+            panic_print_hex(vaddr);
+
+            if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
+                panic_print_str(" (invalid mmu entry)");
+            }
+            panic_print_str("\r\n");
+            break;
+        default:
+            break;
+        }
+    }
+}
+
+static inline void print_memprot_err_details(const void *f)
+{
+    uint32_t *fault_addr;
+    uint32_t op_type, op_subtype;
+    mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
+    esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype );
+
+    char *operation_type = "Write";
+    if ( op_type == 0 ) {
+        operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read";
+    }
+
+    panic_print_str( operation_type );
+    panic_print_str( " operation at address 0x" );
+    panic_print_hex( (uint32_t)fault_addr );
+    panic_print_str(" not permitted.\r\n");
+}
+
+#elif CONFIG_IDF_TARGET_ESP32S3
+static inline void print_cache_err_details(const void* f)
+{
+    uint32_t vaddr = 0, size = 0;
+    uint32_t status;
+    status = REG_READ(EXTMEM_CACHE_ILG_INT_ST_REG);
+    for (int i = 0; i < 32; i++) {
+        switch (status & BIT(i)) {
+        case EXTMEM_ICACHE_SYNC_OP_FAULT_ST:
+            //TODO, which size should fetch
+            //vaddr = REG_READ(EXTMEM_ICACHE_MEM_SYNC0_REG);
+            //size = REG_READ(EXTMEM_ICACHE_MEM_SYNC1_REG);
+            panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST:
+            //TODO, which size should fetch
+            vaddr = REG_READ(EXTMEM_ICACHE_PRELOAD_ADDR_REG);
+            size = REG_READ(EXTMEM_ICACHE_PRELOAD_SIZE_REG);
+            panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_DCACHE_SYNC_OP_FAULT_ST:
+            //TODO, which size should fetch
+            //vaddr = REG_READ(EXTMEM_DCACHE_MEM_SYNC0_REG);
+            //size = REG_READ(EXTMEM_DCACHE_MEM_SYNC1_REG);
+            panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_DCACHE_PRELOAD_OP_FAULT_ST:
+            //TODO, which size should fetch
+            vaddr = REG_READ(EXTMEM_DCACHE_PRELOAD_ADDR_REG);
+            size = REG_READ(EXTMEM_DCACHE_PRELOAD_SIZE_REG);
+            panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
+            panic_print_hex(vaddr);
+            panic_print_str("(0x");
+            panic_print_hex(size);
+            panic_print_str(")\r\n");
+            break;
+        case EXTMEM_DCACHE_WRITE_FLASH_ST:
+            panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
+            break;
+        case EXTMEM_MMU_ENTRY_FAULT_ST:
+            vaddr = REG_READ(EXTMEM_CACHE_MMU_FAULT_VADDR_REG);
+            panic_print_str("MMU entry fault error occurred while accessing the address 0x");
+            panic_print_hex(vaddr);
+
+            if (REG_READ(EXTMEM_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
+                panic_print_str(" (invalid mmu entry)");
+            }
+            panic_print_str("\r\n");
+            break;
+        default:
+            break;
+        }
+    }
+    panic_print_str("\r\n");
+}
+
+static inline void print_memprot_err_details(const void *f)
+{
+}
+#endif
+
+
+void panic_arch_fill_info(void *f, panic_info_t *info)
+{
+    XtExcFrame *frame = (XtExcFrame*) f;
+    static const char *reason[] = {
+        "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
+        "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
+        "Privileged", "LoadStoreAlignment", "res", "res",
+        "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
+        "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
+        "InstrFetchProhibited", "res", "res", "res",
+        "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
+        "LoadProhibited", "StoreProhibited", "res", "res",
+        "Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
+        "Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
+    };
+
+    if (frame->exccause < (sizeof(reason) / sizeof(char *))) {
+        info->reason = (reason[frame->exccause]);
+    } else {
+        info->reason = "Unknown";
+    }
+
+    info->description = "Exception was unhandled.";
+
+    if (frame->exccause == EXCCAUSE_ILLEGAL) {
+        info->details = print_illegal_instruction_details;
+    }
+
+    info->addr = ((void *) ((XtExcFrame *) frame)->pc);
+}
+
+void panic_soc_fill_info(void *f, panic_info_t *info)
+{
+    // [refactor-todo] this should be in the common port panic_handler.c, once
+    // these special exceptions are supported in there.
+    XtExcFrame *frame = (XtExcFrame*) f;
+    if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
+        info->core = 0;
+        info->exception = PANIC_EXCEPTION_IWDT;
+    } else if (frame->exccause == PANIC_RSN_INTWDT_CPU1) {
+        info->core = 1;
+        info->exception = PANIC_EXCEPTION_IWDT;
+    } else if (frame->exccause == PANIC_RSN_CACHEERR) {
+        info->core =  esp_cache_err_get_cpuid();
+    } else {}
+
+    //Please keep in sync with PANIC_RSN_* defines
+    static const char *pseudo_reason[] = {
+        "Unknown reason",
+        "Unhandled debug exception",
+        "Double exception",
+        "Unhandled kernel exception",
+        "Coprocessor exception",
+        "Interrupt wdt timeout on CPU0",
+        "Interrupt wdt timeout on CPU1",
+#if CONFIG_IDF_TARGET_ESP32
+        "Cache disabled but cached memory region accessed",
+#elif CONFIG_IDF_TARGET_ESP32S2
+        "Cache exception",
+#endif
+    };
+
+    info->reason = pseudo_reason[0];
+    info->description = NULL;
+
+    if (frame->exccause <= PANIC_RSN_MAX) {
+        info->reason = pseudo_reason[frame->exccause];
+    }
+
+    if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
+        info->details = print_debug_exception_details;
+        info->exception = PANIC_EXCEPTION_DEBUG;
+    }
+
+#if CONFIG_IDF_TARGET_ESP32S2
+    if (frame->exccause == PANIC_RSN_CACHEERR) {
+        if ( esp_memprot_is_intr_ena_any() ) {
+            info->details = print_memprot_err_details;
+            info->reason = "Memory protection fault";
+        } else {
+            info->details = print_cache_err_details;
+        }
+    }
+#endif
+}
+
+static void print_backtrace_entry(uint32_t pc, uint32_t sp)
+{
+    panic_print_str("0x");
+    panic_print_hex(pc);
+    panic_print_str(":0x");
+    panic_print_hex(sp);
+}
+
+uint32_t panic_get_address(const void* f)
+{
+    return ((XtExcFrame*)f)->pc;
+}
+
+uint32_t panic_get_cause(const void* f)
+{
+    return ((XtExcFrame*)f)->exccause;
+}
+
+void panic_set_address(void *f, uint32_t addr)
+{
+    ((XtExcFrame*)f)->pc = addr;
+}
+
+void panic_print_backtrace(const void *f, int core)
+{
+    // [refactor-todo] once debug helpers have support for both xtensa and riscv, move to
+    // common panic_handler.c
+    XtExcFrame *frame = (XtExcFrame *) f;
+    int depth = 100;
+    //Initialize stk_frame with first frame of stack
+    esp_backtrace_frame_t stk_frame = {.pc = frame->pc, .sp = frame->a1, .next_pc = frame->a0};
+    panic_print_str("\r\nBacktrace:");
+    print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
+
+    //Check if first frame is valid
+    bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
+                       (esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
+                        /* Ignore the first corrupted PC in case of InstrFetchProhibited */
+                        frame->exccause == EXCCAUSE_INSTR_PROHIBITED));
+
+    uint32_t i = ((depth <= 0) ? INT32_MAX : depth) - 1;    //Account for stack frame that's already printed
+    while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
+        if (!esp_backtrace_get_next_frame(&stk_frame)) {    //Get next stack frame
+            corrupted = true;
+        }
+        panic_print_str(" ");
+        print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
+    }
+
+    //Print backtrace termination marker
+    if (corrupted) {
+        panic_print_str(" |<-CORRUPTED");
+    } else if (stk_frame.next_pc != 0) {    //Backtrace continues
+        panic_print_str(" |<-CONTINUES");
+    }
+}

+ 0 - 0
components/esp_system/port/panic_handler_asm.S → components/esp_system/port/arch/xtensa/panic_handler_asm.S


+ 15 - 3
components/esp_system/port/cpu_start.c

@@ -71,7 +71,9 @@
 #include "soc/rtc.h"
 #include "soc/spinlock.h"
 
+#if CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX
 #include "trax.h"
+#endif
 
 #include "bootloader_mem.h"
 
@@ -219,7 +221,7 @@ static void start_other_core(void)
 
 static void intr_matrix_clear(void)
 {
-    for (int i = ETS_WIFI_MAC_INTR_SOURCE; i < ETS_MAX_INTR_SOURCE; i++) {
+    for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) {
         intr_matrix_set(0, i, ETS_INVALID_INUM);
 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
         intr_matrix_set(1, i, ETS_INVALID_INUM);
@@ -239,6 +241,18 @@ void IRAM_ATTR call_start_cpu0(void)
     RESET_REASON rst_reas[1];
 #endif
 
+#ifdef __riscv
+    // Configure the global pointer register
+    // (This should be the first thing IDF app does, as any other piece of code could be
+    // relaxed by the linker to access something relative to __global_pointer$)
+    __asm__ __volatile__ (
+    	".option push\n"
+        ".option norelax\n"
+        "la gp, __global_pointer$\n"
+        ".option pop"
+                          );
+#endif
+
     // Move exception vectors to IRAM
     cpu_hal_set_vecbase(&_init_start);
 
@@ -361,7 +375,6 @@ void IRAM_ATTR call_start_cpu0(void)
     }
 #endif
 
-#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS
     extern void instruction_flash_page_info_init(void);
     instruction_flash_page_info_init();
@@ -391,7 +404,6 @@ void IRAM_ATTR call_start_cpu0(void)
     extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable, uint32_t dcache_wrap_enable);
     esp_enable_cache_wrap(icache_wrap_enable, dcache_wrap_enable);
 #endif
-#endif // CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
 
 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY
     memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start));

+ 0 - 2
components/esp_system/port/esp32/component.mk

@@ -1,2 +0,0 @@
-COMPONENT_SRCDIRS += port port/esp32
-COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o

+ 33 - 464
components/esp_system/port/panic_handler.c

@@ -13,15 +13,9 @@
 // limitations under the License.
 #include <stdlib.h>
 
-#include "freertos/xtensa_context.h"
-#include "freertos/FreeRTOS.h"
-#include "freertos/task.h"
-
 #include "esp_spi_flash.h"
 
-#include "esp_private/panic_reason.h"
 #include "esp_private/system_internal.h"
-#include "esp_debug_helpers.h"
 
 #include "soc/soc_memory_layout.h"
 #include "soc/cpu.h"
@@ -30,30 +24,26 @@
 
 #include "hal/soc_hal.h"
 #include "hal/cpu_hal.h"
-#include "hal/wdt_types.h"
-#include "hal/wdt_hal.h"
-
 
 #include "sdkconfig.h"
 #include "esp_rom_sys.h"
+
 #if CONFIG_IDF_TARGET_ESP32
-#include "esp32/cache_err_int.h"
 #include "esp32/dport_access.h"
+#include "esp32/cache_err_int.h"
 #elif CONFIG_IDF_TARGET_ESP32S2
-#include "esp32s2/cache_err_int.h"
 #include "esp32s2/memprot.h"
-#include "soc/extmem_reg.h"
-#include "soc/cache_memory.h"
-#include "soc/rtc_cntl_reg.h"
+#include "esp32s2/cache_err_int.h"
 #elif CONFIG_IDF_TARGET_ESP32S3
-#include "esp32s3/cache_err_int.h"
 #include "esp32s3/memprot.h"
-#include "soc/extmem_reg.h"
-#include "soc/cache_memory.h"
-#include "soc/rtc_cntl_reg.h"
+#include "esp32s3/cache_err_int.h"
 #endif
 
 #include "esp_private/panic_internal.h"
+#include "esp_private/panic_reason.h"
+
+#include "hal/wdt_types.h"
+#include "hal/wdt_hal.h"
 
 extern int _invalid_pc_placeholder;
 
@@ -61,7 +51,7 @@ extern void esp_panic_handler(panic_info_t*);
 
 static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
 
-static XtExcFrame *xt_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
+void *g_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
 
 /*
   Panic handlers; these get called when an unhandled exception occurs or the assembly-level
@@ -72,193 +62,19 @@ static XtExcFrame *xt_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
 /*
   Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
 */
-static void print_illegal_instruction_details(const void *f)
-{
-    XtExcFrame *frame  = (XtExcFrame *) f;
-    /* Print out memory around the instruction word */
-    uint32_t epc = frame->pc;
-    epc = (epc & ~0x3) - 4;
-
-    /* check that the address was sane */
-    if (epc < SOC_IROM_MASK_LOW || epc >= SOC_IROM_HIGH) {
-        return;
-    }
-    volatile uint32_t *pepc = (uint32_t *)epc;
-
-    panic_print_str("Memory dump at 0x");
-    panic_print_hex(epc);
-    panic_print_str(": ");
-
-    panic_print_hex(*pepc);
-    panic_print_str(" ");
-    panic_print_hex(*(pepc + 1));
-    panic_print_str(" ");
-    panic_print_hex(*(pepc + 2));
-}
-
-static void print_debug_exception_details(const void *f)
-{
-    int debug_rsn;
-    asm("rsr.debugcause %0":"=r"(debug_rsn));
-    panic_print_str("Debug exception reason: ");
-    if (debug_rsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) {
-        panic_print_str("SingleStep ");
-    }
-    if (debug_rsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) {
-        panic_print_str("HwBreakpoint ");
-    }
-    if (debug_rsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
-        //Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
-        //reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
-        //debugcause if the cause is watchpoint 1 and clearing it if it's watchpoint 0.
-        if (debug_rsn & (1 << 8)) {
-#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
-            int core = 0;
-
-#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
-            if (f == xt_exc_frames[1]) {
-                core = 1;
-            }
-#endif
-
-            const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core));
-            panic_print_str("Stack canary watchpoint triggered (");
-            panic_print_str(name);
-            panic_print_str(") ");
-#else
-            panic_print_str("Watchpoint 1 triggered ");
-#endif
-        } else {
-            panic_print_str("Watchpoint 0 triggered ");
-        }
-    }
-    if (debug_rsn & XCHAL_DEBUGCAUSE_BREAK_MASK) {
-        panic_print_str("BREAK instr ");
-    }
-    if (debug_rsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) {
-        panic_print_str("BREAKN instr ");
-    }
-    if (debug_rsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) {
-        panic_print_str("DebugIntr ");
-    }
-}
-
-static void print_backtrace_entry(uint32_t pc, uint32_t sp)
-{
-    panic_print_str("0x");
-    panic_print_hex(pc);
-    panic_print_str(":0x");
-    panic_print_hex(sp);
-}
-
-static void print_backtrace(const void *f, int core)
-{
-    XtExcFrame *frame = (XtExcFrame *) f;
-    int depth = 100;
-    //Initialize stk_frame with first frame of stack
-    esp_backtrace_frame_t stk_frame = {.pc = frame->pc, .sp = frame->a1, .next_pc = frame->a0};
-    panic_print_str("\r\nBacktrace:");
-    print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
-
-    //Check if first frame is valid
-    bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
-                       (esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
-                        /* Ignore the first corrupted PC in case of InstrFetchProhibited */
-                        frame->exccause == EXCCAUSE_INSTR_PROHIBITED));
-
-    uint32_t i = ((depth <= 0) ? INT32_MAX : depth) - 1;    //Account for stack frame that's already printed
-    while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
-        if (!esp_backtrace_get_next_frame(&stk_frame)) {    //Get next stack frame
-            corrupted = true;
-        }
-        panic_print_str(" ");
-        print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
-    }
-
-    //Print backtrace termination marker
-    if (corrupted) {
-        panic_print_str(" |<-CORRUPTED");
-    } else if (stk_frame.next_pc != 0) {    //Backtrace continues
-        panic_print_str(" |<-CONTINUES");
-    }
-}
-
-static void print_registers(const void *f, int core)
-{
-    XtExcFrame *frame = (XtExcFrame *) f;
-    int *regs = (int *)frame;
-    int x, y;
-    const char *sdesc[] = {
-        "PC      ", "PS      ", "A0      ", "A1      ", "A2      ", "A3      ", "A4      ", "A5      ",
-        "A6      ", "A7      ", "A8      ", "A9      ", "A10     ", "A11     ", "A12     ", "A13     ",
-        "A14     ", "A15     ", "SAR     ", "EXCCAUSE", "EXCVADDR", "LBEG    ", "LEND    ", "LCOUNT  "
-    };
-
-    /* only dump registers for 'real' crashes, if crashing via abort()
-       the register window is no longer useful.
-    */
-    panic_print_str("Core ");
-    panic_print_dec(core);
-    panic_print_str(" register dump:");
-
-    for (x = 0; x < 24; x += 4) {
-        panic_print_str("\r\n");
-        for (y = 0; y < 4; y++) {
-            if (sdesc[x + y][0] != 0) {
-                panic_print_str(sdesc[x + y]);
-                panic_print_str(": 0x");
-                panic_print_hex(regs[x + y + 1]);
-                panic_print_str("  ");
-            }
-        }
-    }
-
-    // If the core which triggers the interrupt watchpoint was in ISR context, dump the epc registers.
-    if (xPortInterruptedFromISRContext()
-#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
-            && ((core == 0 && frame->exccause == PANIC_RSN_INTWDT_CPU0) ||
-                (core == 1 && frame->exccause == PANIC_RSN_INTWDT_CPU1))
-#endif //!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
-        ) {
-
-        panic_print_str("\r\n");
-
-        uint32_t __value;
-        panic_print_str("Core ");
-        panic_print_dec(core);
-        panic_print_str(" was running in ISR context:\r\n");
-
-        __asm__("rsr.epc1 %0" : "=a"(__value));
-        panic_print_str("EPC1    : 0x");
-        panic_print_hex(__value);
-
-        __asm__("rsr.epc2 %0" : "=a"(__value));
-        panic_print_str("  EPC2    : 0x");
-        panic_print_hex(__value);
-
-        __asm__("rsr.epc3 %0" : "=a"(__value));
-        panic_print_str("  EPC3    : 0x");
-        panic_print_hex(__value);
-
-        __asm__("rsr.epc4 %0" : "=a"(__value));
-        panic_print_str("  EPC4    : 0x");
-        panic_print_hex(__value);
-    }
-}
-
 static void print_state_for_core(const void *f, int core)
 {
     if (!g_panic_abort) {
-        print_registers(f, core);
+        panic_print_registers(f, core);
         panic_print_str("\r\n");
     }
-    print_backtrace(f, core);
+    panic_print_backtrace(f, core);
 }
 
 static void print_state(const void *f)
 {
 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
-    int err_core = f == xt_exc_frames[0] ? 0 : 1;
+    int err_core = f == g_exc_frames[0] ? 0 : 1;
 #else
     int err_core = 0;
 #endif
@@ -271,282 +87,33 @@ static void print_state(const void *f)
     // If there are other frame info, print them as well
     for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
         // `f` is the frame for the offending core, see note above.
-        if (err_core != i && xt_exc_frames[i] != NULL) {
-            print_state_for_core(xt_exc_frames[i], i);
+        if (err_core != i && g_exc_frames[i] != NULL) {
+            print_state_for_core(g_exc_frames[i], i);
             panic_print_str("\r\n");
         }
     }
 #endif
 }
 
-#if CONFIG_IDF_TARGET_ESP32S2
-static inline void print_cache_err_details(const void *f)
-{
-    uint32_t vaddr = 0, size = 0;
-    uint32_t status[2];
-    status[0] = REG_READ(EXTMEM_CACHE_DBG_STATUS0_REG);
-    status[1] = REG_READ(EXTMEM_CACHE_DBG_STATUS1_REG);
-    for (int i = 0; i < 32; i++) {
-        switch (status[0] & BIT(i)) {
-        case EXTMEM_IC_SYNC_SIZE_FAULT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC0_REG);
-            size = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC1_REG);
-            panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_IC_PRELOAD_SIZE_FAULT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_ADDR_REG);
-            size = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_SIZE_REG);
-            panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_ICACHE_REJECT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_ICACHE_REJECT_VADDR_REG);
-            panic_print_str("Icache reject error occurred while accessing the address 0x");
-            panic_print_hex(vaddr);
-
-            if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
-                panic_print_str(" (invalid mmu entry)");
-            }
-            panic_print_str("\r\n");
-            break;
-        default:
-            break;
-        }
-        switch (status[1] & BIT(i)) {
-        case EXTMEM_DC_SYNC_SIZE_FAULT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC0_REG);
-            size = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC1_REG);
-            panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_DC_PRELOAD_SIZE_FAULT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_ADDR_REG);
-            size = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_SIZE_REG);
-            panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_DCACHE_WRITE_FLASH_ST:
-            panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
-            break;
-        case EXTMEM_DCACHE_REJECT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_DCACHE_REJECT_VADDR_REG);
-            panic_print_str("Dcache reject error occurred while accessing the address 0x");
-            panic_print_hex(vaddr);
-
-            if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
-                panic_print_str(" (invalid mmu entry)");
-            }
-            panic_print_str("\r\n");
-            break;
-        case EXTMEM_MMU_ENTRY_FAULT_ST:
-            vaddr = REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_VADDR_REG);
-            panic_print_str("MMU entry fault error occurred while accessing the address 0x");
-            panic_print_hex(vaddr);
-
-            if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
-                panic_print_str(" (invalid mmu entry)");
-            }
-            panic_print_str("\r\n");
-            break;
-        default:
-            break;
-        }
-    }
-}
-
-static inline void print_memprot_err_details(const void *f)
-{
-    uint32_t *fault_addr;
-    uint32_t op_type, op_subtype;
-    mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
-    esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype );
-
-    char *operation_type = "Write";
-    if ( op_type == 0 ) {
-        operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read";
-    }
-
-    panic_print_str( operation_type );
-    panic_print_str( " operation at address 0x" );
-    panic_print_hex( (uint32_t)fault_addr );
-    panic_print_str(" not permitted.\r\n");
-}
-
-#elif CONFIG_IDF_TARGET_ESP32S3
-static inline void print_cache_err_details(const void* f)
-{
-    uint32_t vaddr = 0, size = 0;
-    uint32_t status;
-    status = REG_READ(EXTMEM_CACHE_ILG_INT_ST_REG);
-    for (int i = 0; i < 32; i++) {
-        switch (status & BIT(i)) {
-        case EXTMEM_ICACHE_SYNC_OP_FAULT_ST:
-            //TODO, which size should fetch
-            //vaddr = REG_READ(EXTMEM_ICACHE_MEM_SYNC0_REG);
-            //size = REG_READ(EXTMEM_ICACHE_MEM_SYNC1_REG);
-            panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST:
-            //TODO, which size should fetch
-            vaddr = REG_READ(EXTMEM_ICACHE_PRELOAD_ADDR_REG);
-            size = REG_READ(EXTMEM_ICACHE_PRELOAD_SIZE_REG);
-            panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_DCACHE_SYNC_OP_FAULT_ST:
-            //TODO, which size should fetch
-            //vaddr = REG_READ(EXTMEM_DCACHE_MEM_SYNC0_REG);
-            //size = REG_READ(EXTMEM_DCACHE_MEM_SYNC1_REG);
-            panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_DCACHE_PRELOAD_OP_FAULT_ST:
-            //TODO, which size should fetch
-            vaddr = REG_READ(EXTMEM_DCACHE_PRELOAD_ADDR_REG);
-            size = REG_READ(EXTMEM_DCACHE_PRELOAD_SIZE_REG);
-            panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
-            panic_print_hex(vaddr);
-            panic_print_str("(0x");
-            panic_print_hex(size);
-            panic_print_str(")\r\n");
-            break;
-        case EXTMEM_DCACHE_WRITE_FLASH_ST:
-            panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
-            break;
-        case EXTMEM_MMU_ENTRY_FAULT_ST:
-            vaddr = REG_READ(EXTMEM_CACHE_MMU_FAULT_VADDR_REG);
-            panic_print_str("MMU entry fault error occurred while accessing the address 0x");
-            panic_print_hex(vaddr);
-
-            if (REG_READ(EXTMEM_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
-                panic_print_str(" (invalid mmu entry)");
-            }
-            panic_print_str("\r\n");
-            break;
-        default:
-            break;
-        }
-    }
-    panic_print_str("\r\n");
-}
-
-static inline void print_memprot_err_details(const void *f)
-{
-}
-#endif
-
-static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseudo_excause)
+static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_excause)
 {
     info->core = cpu_hal_get_core_id();
     info->exception = PANIC_EXCEPTION_FAULT;
     info->details = NULL;
-
+    info->reason = "Unknown";
     info->pseudo_excause = pseudo_excause;
-    if (pseudo_excause) {
-        if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
-            info->core = 0;
-            info->exception = PANIC_EXCEPTION_IWDT;
-        } else if (frame->exccause == PANIC_RSN_INTWDT_CPU1) {
-            info->core = 1;
-            info->exception = PANIC_EXCEPTION_IWDT;
-        } else if (frame->exccause == PANIC_RSN_CACHEERR) {
-            info->core =  esp_cache_err_get_cpuid();
-        } else {}
-
-        //Please keep in sync with PANIC_RSN_* defines
-        static const char *pseudo_reason[] = {
-            "Unknown reason",
-            "Unhandled debug exception",
-            "Double exception",
-            "Unhandled kernel exception",
-            "Coprocessor exception",
-            "Interrupt wdt timeout on CPU0",
-            "Interrupt wdt timeout on CPU1",
-#if CONFIG_IDF_TARGET_ESP32
-            "Cache disabled but cached memory region accessed",
-#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-            "Cache exception",
-#endif
-        };
 
-        info->reason = pseudo_reason[0];
-        info->description = NULL;
-
-        if (frame->exccause <= PANIC_RSN_MAX) {
-            info->reason = pseudo_reason[frame->exccause];
-        }
-
-        if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
-            info->details = print_debug_exception_details;
-            info->exception = PANIC_EXCEPTION_DEBUG;
-        }
-
-#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
-        if (frame->exccause == PANIC_RSN_CACHEERR) {
-            if ( esp_memprot_get_active_intr_memtype() != MEMPROT_NONE ) {
-                info->details = print_memprot_err_details;
-                info->reason = "Memory protection fault";
-            } else {
-                info->details = print_cache_err_details;
-            }
-        }
-#endif
+    if (pseudo_excause) {
+        panic_soc_fill_info(frame, info);
     } else {
-        static const char *reason[] = {
-            "IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
-            "Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
-            "Privileged", "LoadStoreAlignment", "res", "res",
-            "InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
-            "InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
-            "InstrFetchProhibited", "res", "res", "res",
-            "LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
-            "LoadProhibited", "StoreProhibited", "res", "res",
-            "Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
-            "Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
-        };
-
-        if (frame->exccause < (sizeof(reason) / sizeof(char *))) {
-            info->reason = (reason[frame->exccause]);
-        } else {
-            info->reason = "Unknown";
-        }
-
-        info->description = "Exception was unhandled.";
-
-        if (frame->exccause == EXCCAUSE_ILLEGAL) {
-            info->details = print_illegal_instruction_details;
-        }
+        panic_arch_fill_info(frame, info);
     }
 
     info->state = print_state;
-    info->addr = ((void *) ((XtExcFrame *) frame)->pc);
     info->frame = frame;
 }
 
-static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
+static void panic_handler(void *frame, bool pseudo_excause)
 {
     /*
      * Setup environment and perform necessary architecture/chip specific
@@ -555,7 +122,7 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
     int core_id = cpu_hal_get_core_id();
 
     // If multiple cores arrive at panic handler, save frames for all of them
-    xt_exc_frames[core_id] = frame;
+    g_exc_frames[core_id] = frame;
 
 #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
     // These are cases where both CPUs both go into panic handler. The following code ensures
@@ -563,13 +130,13 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
     if (pseudo_excause) {
 #define BUSY_WAIT_IF_TRUE(b)                { if (b) while(1); }
         // For WDT expiry, pause the non-offending core - offending core handles panic
-        BUSY_WAIT_IF_TRUE(frame->exccause == PANIC_RSN_INTWDT_CPU0 && core_id == 1);
-        BUSY_WAIT_IF_TRUE(frame->exccause == PANIC_RSN_INTWDT_CPU1 && core_id == 0);
+        BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1);
+        BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0);
 
         // For cache error, pause the non-offending core - offending core handles panic
-        if (frame->exccause == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
+        if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
             // Only print the backtrace for the offending core in case of the cache error
-            xt_exc_frames[core_id] = NULL;
+            g_exc_frames[core_id] = NULL;
             while (1) {
                 ;
             }
@@ -593,15 +160,17 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
 #endif
 
     if (esp_cpu_in_ocd_debug_mode()) {
-        if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(frame->pc)) && (frame->pc & 0xC0000000U))) {
+#if __XTENSA__
+        if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(panic_get_address(frame))) && (panic_get_address(frame) & 0xC0000000U))) {
             /* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
              * Incase the PC is invalid, GDB will fail to translate addresses to function names
              * Hence replacing the PC to a placeholder address in case of invalid PC
              */
-            frame->pc = (uint32_t)&_invalid_pc_placeholder;
+            panic_set_address(frame, (uint32_t)&_invalid_pc_placeholder);
         }
-        if (frame->exccause == PANIC_RSN_INTWDT_CPU0 ||
-                frame->exccause == PANIC_RSN_INTWDT_CPU1) {
+#endif
+        if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 ||
+            panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1) {
             wdt_hal_write_protect_disable(&wdt0_context);
             wdt_hal_handle_intr(&wdt0_context);
             wdt_hal_write_protect_enable(&wdt0_context);
@@ -616,7 +185,7 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
     esp_panic_handler(&info);
 }
 
-void panicHandler(XtExcFrame *frame)
+void panicHandler(void *frame)
 {
     // This panic handler gets called for when the double exception vector,
     // kernel exception vector gets used; as well as handling interrupt-based
@@ -625,7 +194,7 @@ void panicHandler(XtExcFrame *frame)
     panic_handler(frame, true);
 }
 
-void xt_unhandled_exception(XtExcFrame *frame)
+void xt_unhandled_exception(void *frame)
 {
     panic_handler(frame, false);
 }

+ 6 - 1
components/esp_system/port/esp32/CMakeLists.txt → components/esp_system/port/soc/esp32/CMakeLists.txt

@@ -1,4 +1,9 @@
-set(srcs "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c")
+set(srcs "dport_panic_highint_hdl.S"
+         "clk.c"
+         "reset_reason.c"
+         "../../arch/xtensa/panic_arch.c"
+         "../../arch/xtensa/panic_handler_asm.S"
+         )
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
 
 target_sources(${COMPONENT_LIB} PRIVATE ${srcs})

+ 5 - 2
components/esp_system/port/esp32/clk.c → components/esp_system/port/soc/esp32/clk.c

@@ -177,7 +177,8 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
     wdt_hal_write_protect_enable(&rtc_wdt_ctx);
 #endif
 
-    rtc_cpu_freq_config_t old_config, new_config;
+    rtc_cpu_freq_config_t old_config;
+    rtc_cpu_freq_config_t new_config;
     rtc_clk_cpu_freq_get_config(&old_config);
     const uint32_t old_freq_mhz = old_config.freq_mhz;
     const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
@@ -205,7 +206,9 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
  */
 __attribute__((weak)) void esp_perip_clk_init(void)
 {
-    uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
+    uint32_t common_perip_clk;
+    uint32_t hwcrypto_perip_clk;
+    uint32_t wifi_bt_sdio_clk;
 
 #if CONFIG_FREERTOS_UNICORE
     RESET_REASON rst_reas[1];

+ 2 - 0
components/esp_system/port/soc/esp32/component.mk

@@ -0,0 +1,2 @@
+COMPONENT_SRCDIRS += port port/soc/esp32 port/arch/xtensa
+COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o

+ 0 - 0
components/esp_system/port/esp32/dport_panic_highint_hdl.S → components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S


+ 0 - 0
components/esp_system/port/esp32/intr.c → components/esp_system/port/soc/esp32/intr.c


+ 0 - 0
components/esp_system/port/esp32/reset_reason.c → components/esp_system/port/soc/esp32/reset_reason.c


+ 7 - 1
components/esp_system/port/esp32s2/CMakeLists.txt → components/esp_system/port/soc/esp32s2/CMakeLists.txt

@@ -1,4 +1,10 @@
-set(srcs "async_memcpy_impl_cp_dma.c" "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c")
+set(srcs "async_memcpy_impl_cp_dma.c"
+         "dport_panic_highint_hdl.S"
+         "clk.c"
+         "reset_reason.c"
+         "../../arch/xtensa/panic_arch.c"
+         "../../arch/xtensa/panic_handler_asm.S"
+         )
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
 
 target_sources(${COMPONENT_LIB} PRIVATE ${srcs})

+ 0 - 0
components/esp_system/port/esp32s2/async_memcpy_impl_cp_dma.c → components/esp_system/port/soc/esp32s2/async_memcpy_impl_cp_dma.c


+ 0 - 0
components/esp_system/port/esp32s2/clk.c → components/esp_system/port/soc/esp32s2/clk.c


+ 0 - 0
components/esp_system/port/esp32s2/dport_panic_highint_hdl.S → components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S


+ 0 - 0
components/esp_system/port/esp32s2/reset_reason.c → components/esp_system/port/soc/esp32s2/reset_reason.c


+ 0 - 0
components/esp_system/port/esp32s2/usb_console.c → components/esp_system/port/soc/esp32s2/usb_console.c


+ 7 - 1
components/esp_system/port/esp32s3/CMakeLists.txt → components/esp_system/port/soc/esp32s3/CMakeLists.txt

@@ -1,4 +1,10 @@
-set(srcs "../async_memcpy_impl_gdma.c" "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c")
+set(srcs "dport_panic_highint_hdl.S"
+         "clk.c"
+         "reset_reason.c"
+         "../../async_memcpy_impl_gdma.c"
+         "../../arch/xtensa/panic_arch.c"
+         "../../arch/xtensa/panic_handler_asm.S"
+         )
 add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
 
 target_sources(${COMPONENT_LIB} PRIVATE ${srcs})

+ 0 - 0
components/esp_system/port/esp32s3/clk.c → components/esp_system/port/soc/esp32s3/clk.c


+ 0 - 0
components/esp_system/port/esp32s3/dport_panic_highint_hdl.S → components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S


+ 0 - 0
components/esp_system/port/esp32s3/reset_reason.c → components/esp_system/port/soc/esp32s3/reset_reason.c


+ 1 - 1
components/esp_timer/src/esp_timer.c

@@ -22,7 +22,7 @@
 #include "esp_log.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "freertos/xtensa_api.h"
+#include "freertos/semphr.h"
 #include "soc/spinlock.h"
 #include "esp_timer.h"
 #include "esp_timer_impl.h"

+ 0 - 1
components/esp_timer/src/ets_timer_legacy.c

@@ -27,7 +27,6 @@
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/semphr.h"
-#include "freertos/xtensa_api.h"
 #include "sdkconfig.h"
 #include "esp_timer.h"
 #if CONFIG_IDF_TARGET_ESP32

+ 0 - 1
components/espcoredump/include/esp_core_dump.h

@@ -16,7 +16,6 @@
 
 #include <stddef.h>
 #include "esp_err.h"
-#include "freertos/xtensa_context.h"
 #include "esp_private/panic_internal.h"
 
 /**************************************************************************************/

+ 7 - 1
components/espcoredump/src/core_dump_port.c

@@ -16,8 +16,14 @@
 #include "soc/soc_memory_layout.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
-#include "freertos/xtensa_context.h" // for exception register stack structure
 #include "esp_core_dump_priv.h"
+
+#if __XTENSA__
+#include "freertos/xtensa_context.h"
+#else // __XTENSA__
+#define XCHAL_NUM_AREGS 64 // TODO-ESP32C3 coredump support IDF-1758
+#endif // __XTENSA__
+
 #include "esp_rom_sys.h"
 
 const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port";

+ 44 - 21
components/freertos/CMakeLists.txt

@@ -4,16 +4,49 @@ if(BOOTLOADER_BUILD)
     return()
 endif()
 
-set(srcs
-    "xtensa/port.c"
-    "xtensa/portasm.S"
-    "xtensa/xtensa_context.S"
-    "xtensa/xtensa_init.c"
-    "xtensa/xtensa_overlay_os_hook.c"
-    "xtensa/xtensa_vector_defaults.S"
-    "xtensa/xtensa_vectors.S")
+idf_build_get_property(target IDF_TARGET)
+
+if(NOT "${target}" STREQUAL "esp32c3")  # should test arch here not target, TODO ESP32-C3 IDF-1754
+    set(srcs
+        "port/xtensa/port.c"
+        "port/xtensa/portasm.S"
+        "port/xtensa/xtensa_context.S"
+        "port/xtensa/xtensa_init.c"
+        "port/xtensa/xtensa_overlay_os_hook.c"
+        "port/xtensa/xtensa_vector_defaults.S"
+        "port/xtensa/xtensa_vectors.S")
+
+    set(include_dirs
+        include
+        port/xtensa/include)
+
+    set(private_include_dirs
+        include/freertos
+        port/xtensa/include/freertos
+        port/xtensa
+        .)
+
+    set(required_components app_trace esp_timer)
+else()  # RISC-V
+    set(srcs
+        "port/riscv/port.c"
+        "port/riscv/portasm.S")
+
+    set(include_dirs
+        include
+        port/riscv/include)
+
+    set(private_include_dirs
+        include/freertos
+        port/riscv/include/freertos
+        port/riscv
+        .)
+
+    set(required_components esp_timer)
+endif()
 
 list(APPEND srcs
+    "port/port_common.c"
     "croutine.c"
     "event_groups.c"
     "list.c"
@@ -23,19 +56,9 @@ list(APPEND srcs
     "stream_buffer.c"
     "FreeRTOS-openocd.c")
 
-set(include_dirs
-    include
-    xtensa/include)
-
-set(private_include_dirs
-    include/freertos
-    xtensa/include/freertos
-    xtensa
-    .)
-
 if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY)
-     list(APPEND srcs "xtensa/xtensa_loadstore_handler.S")
- endif()
+    list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S")
+endif()
 
 # app_trace is required by FreeRTOS headers only when CONFIG_SYSVIEW_ENABLE=y,
 # but requirements can't depend on config options, so always require it.
@@ -43,7 +66,7 @@ idf_component_register(SRCS "${srcs}"
                     INCLUDE_DIRS ${include_dirs}
                     PRIV_INCLUDE_DIRS  ${private_include_dirs}
                     LDFRAGMENTS linker.lf
-                    REQUIRES app_trace esp_timer
+                    REQUIRES ${required_components}
                     PRIV_REQUIRES soc)
 
 idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR)

+ 3 - 3
components/freertos/component.mk

@@ -6,9 +6,9 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
 	COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority
 endif
 
-COMPONENT_ADD_INCLUDEDIRS := include xtensa/include
-COMPONENT_PRIV_INCLUDEDIRS := include/freertos xtensa/include/freertos xtensa .
-COMPONENT_SRCDIRS += xtensa
+COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include
+COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa .
+COMPONENT_SRCDIRS += port port/xtensa
 
 ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
 	COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o

+ 1 - 1
components/freertos/linker.lf

@@ -112,6 +112,6 @@ entries:
         queue: xQueueAddToSet (default)
         queue: xQueueRemoveFromSet (default)
         queue: xQueueSelectFromSet (default)
-    port:main_task (default)
+    port_common:main_task (default)
     port:esp_startup_start_app (default)
     port:esp_startup_start_app_other_cores (default)

+ 135 - 0
components/freertos/port/port_common.c

@@ -0,0 +1,135 @@
+// 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.
+
+#include <string.h>
+#include "FreeRTOS.h"
+#include "task.h"
+#include "portmacro.h"
+#include "esp_system.h"
+#include "esp_heap_caps_init.h"
+#include "esp_int_wdt.h"
+#include "esp_task_wdt.h"
+#include "esp_task.h"
+#include "esp_private/crosscore_int.h"
+#include "esp_private/startup_internal.h"
+#include "esp_log.h"
+#include "soc/dport_access.h"
+#include "sdkconfig.h"
+
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/spiram.h"
+#elif CONFIG_IDF_TARGET_ESP32S2
+#include "esp32s2/spiram.h"
+#elif CONFIG_IDF_TARGET_ESP32S3
+#include "esp32s3/spiram.h"
+#elif CONFIG_IDF_TARGET_ESP32C3
+// SPIRAM is not supported on ESP32-C3
+#endif
+
+#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
+static const char* TAG = "cpu_start";
+#endif
+
+/* Architecture-agnostic parts of the FreeRTOS ESP-IDF port layer can go here.
+ *
+ * The actual call flow will be to call esp_startup_start_app() in <ARCH>/port.c,
+ * which will then call esp_startup_start_app_common()
+ */
+
+// Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
+volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0};
+
+// For now, running FreeRTOS on one core and a bare metal on the other (or other OSes)
+// is not supported. For now CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
+// should mirror each other's values.
+//
+// And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE.
+#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
+	#error "FreeRTOS and system configuration mismatch regarding the use of multiple cores."
+#endif
+
+static void main_task(void* args);
+
+extern void app_main(void);
+
+void esp_startup_start_app_common(void)
+{
+#if CONFIG_ESP_INT_WDT
+	esp_int_wdt_init();
+	//Initialize the interrupt watch dog for CPU0.
+	esp_int_wdt_cpu_init();
+#endif
+
+	esp_crosscore_int_init();
+
+#ifndef CONFIG_FREERTOS_UNICORE
+#if CONFIG_IDF_TARGET_ESP32
+	esp_dport_access_int_init();
+#endif
+#endif
+
+	portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
+												ESP_TASK_MAIN_STACK, NULL,
+												ESP_TASK_MAIN_PRIO, NULL, 0);
+	assert(res == pdTRUE);
+}
+
+static void main_task(void* args)
+{
+#if !CONFIG_FREERTOS_UNICORE
+	// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
+	while (port_xSchedulerRunning[1] == 0) {
+		;
+	}
+#endif
+
+	// [refactor-todo] check if there is a way to move the following block to esp_system startup
+	heap_caps_enable_nonos_stack_heaps();
+
+	// Now we have startup stack RAM available for heap, enable any DMA pool memory
+#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
+	if (g_spiram_ok) {
+		esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
+		if (r != ESP_OK) {
+			ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
+			abort();
+		}
+	}
+#endif
+
+	//Initialize task wdt if configured to do so
+#ifdef CONFIG_ESP_TASK_WDT_PANIC
+	ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true));
+#elif CONFIG_ESP_TASK_WDT
+	ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false));
+#endif
+
+	//Add IDLE 0 to task wdt
+#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
+	TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
+	if(idle_0 != NULL){
+		ESP_ERROR_CHECK(esp_task_wdt_add(idle_0));
+	}
+#endif
+	//Add IDLE 1 to task wdt
+#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
+	TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
+	if(idle_1 != NULL){
+		ESP_ERROR_CHECK(esp_task_wdt_add(idle_1));
+	}
+#endif
+
+	app_main();
+	vTaskDelete(NULL);
+}

+ 277 - 0
components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h

@@ -0,0 +1,277 @@
+/*
+    FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+
+	***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+	***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+	the FAQ page "My application does not run, what could be wrong?".  Have you
+	defined configASSERT()?
+
+	http://www.FreeRTOS.org/support - In return for receiving this top quality
+	embedded software for free we request you assist our global community by
+	participating in the support forum.
+
+	http://www.FreeRTOS.org/training - Investing in training allows your team to
+	be as productive as possible as early as possible.  Now you can receive
+	FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+	Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+#ifndef FREERTOS_CONFIG_H
+#define FREERTOS_CONFIG_H
+
+#include "sdkconfig.h"
+
+/* enable use of optimized task selection by the scheduler */
+#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0
+
+#define portNUM_PROCESSORS 1
+#define configASSERT_2	0
+#define portUSING_MPU_WRAPPERS 0
+#define configUSE_MUTEX 1
+
+#define configMAX_SYSCALL_INTERRUPT_PRIORITY	0
+#define configUSE_NEWLIB_REENTRANT		1
+
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
+#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1
+
+/* configASSERT behaviour */
+#ifndef __ASSEMBLER__
+#include <stdlib.h> /* for abort() */
+#include "esp32c3/rom/ets_sys.h"
+
+#if defined(CONFIG_FREERTOS_ASSERT_DISABLE)
+#define configASSERT(a) /* assertions disabled */
+#elif defined(CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE)
+#define configASSERT(a) if (unlikely(!(a))) {                               \
+        esp_rom_printf("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__,  \
+                   __FUNCTION__);                                           \
+    }
+#else /* CONFIG_FREERTOS_ASSERT_FAIL_ABORT */
+#define configASSERT(a) if (unlikely(!(a))) {                               \
+        esp_rom_printf("%s:%d (%s)- assert failed!\n", __FILE__, __LINE__,  \
+                   __FUNCTION__);                                           \
+        abort();                                                            \
+        }
+#endif
+
+#if CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION
+#define UNTESTED_FUNCTION() { esp_rom_printf("Untested FreeRTOS function %s\r\n", __FUNCTION__); configASSERT(false); } while(0)
+#else
+#define UNTESTED_FUNCTION()
+#endif
+
+
+#endif /* def __ASSEMBLER__ */
+
+
+/*-----------------------------------------------------------
+ * Application specific definitions.
+ *
+ * These definitions should be adjusted for your particular hardware and
+ * application requirements.
+ *
+ * Note that the default heap size is deliberately kept small so that
+ * the build is more likely to succeed for configurations with limited
+ * memory.
+ *
+ * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
+ * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
+ *----------------------------------------------------------*/
+
+#define configUSE_PREEMPTION			1
+#define configUSE_IDLE_HOOK				1
+#define configUSE_TICK_HOOK				1
+#define configRECORD_STACK_HIGH_ADDRESS 1
+#define configTICK_RATE_HZ				( CONFIG_FREERTOS_HZ )
+
+/* Default clock rate for simulator */
+//#define configCPU_CLOCK_HZ				80000000
+
+/* This has impact on speed of search for highest priority */
+#ifdef SMALL_TEST
+#define configMAX_PRIORITIES			( 7 )
+#else
+#define configMAX_PRIORITIES			( 25 )
+#endif
+
+#if defined(CONFIG_APPTRACE_ENABLE)
+/* apptrace module requires at least 2KB of stack per task */
+#define configMINIMAL_STACK_SIZE		2048
+#elif defined(CONFIG_COMPILER_OPTIMIZATION_NONE)
+/* with optimizations disabled, scheduler uses additional stack */
+#define configMINIMAL_STACK_SIZE		1024
+#else
+#define configMINIMAL_STACK_SIZE		768
+#endif
+
+#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS
+#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1
+
+#ifndef configIDLE_TASK_STACK_SIZE
+#define configIDLE_TASK_STACK_SIZE CONFIG_FREERTOS_IDLE_TASK_STACKSIZE
+#endif
+
+/* The port layer uses a separate interrupt stack. Adjust the stack size */
+/* to suit the needs of your specific application.                        */
+#ifndef configISR_STACK_SIZE
+#define configISR_STACK_SIZE			CONFIG_FREERTOS_ISR_STACKSIZE
+#endif
+
+/* Minimal heap size to make sure examples can run on memory limited
+   configs. Adjust this to suit your system. */
+
+
+//We define the heap to span all of the non-statically-allocated shared RAM. ToDo: Make sure there
+//is some space left for the app and main cpu when running outside of a thread.
+#define configAPPLICATION_ALLOCATED_HEAP 1
+#define configTOTAL_HEAP_SIZE			(&_heap_end - &_heap_start)//( ( size_t ) (64 * 1024) )
+
+#define configMAX_TASK_NAME_LEN			( CONFIG_FREERTOS_MAX_TASK_NAME_LEN )
+
+#ifdef CONFIG_FREERTOS_USE_TRACE_FACILITY
+#define configUSE_TRACE_FACILITY        1       /* Used by uxTaskGetSystemState(), and other trace facility functions */
+#endif
+
+#ifdef CONFIG_FREERTOS_USE_STATS_FORMATTING_FUNCTIONS
+#define configUSE_STATS_FORMATTING_FUNCTIONS    1   /* Used by vTaskList() */
+#endif
+
+#ifdef CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
+#define configTASKLIST_INCLUDE_COREID   1
+#endif
+
+#ifdef CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
+#define configGENERATE_RUN_TIME_STATS   1       /* Used by vTaskGetRunTimeStats() */
+#endif
+
+#define configUSE_TRACE_FACILITY_2      0
+#define configBENCHMARK					0
+#define configUSE_16_BIT_TICKS			0
+#define configIDLE_SHOULD_YIELD			0
+#define configQUEUE_REGISTRY_SIZE		CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE
+
+#define configUSE_MUTEXES				1
+#define configUSE_RECURSIVE_MUTEXES		1
+#define configUSE_COUNTING_SEMAPHORES	1
+
+#if CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE
+#define configCHECK_FOR_STACK_OVERFLOW	0
+#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL
+#define configCHECK_FOR_STACK_OVERFLOW	1
+#elif CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY
+#define configCHECK_FOR_STACK_OVERFLOW	2
+#endif
+
+/* Co-routine definitions. */
+#define configUSE_CO_ROUTINES 			0
+#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
+
+/* Set the following definitions to 1 to include the API function, or zero
+   to exclude the API function. */
+
+#define INCLUDE_vTaskPrioritySet			1
+#define INCLUDE_uxTaskPriorityGet			1
+#define INCLUDE_vTaskDelete					1
+#define INCLUDE_vTaskCleanUpResources		0
+#define INCLUDE_vTaskSuspend				1
+#define INCLUDE_vTaskDelayUntil				1
+#define INCLUDE_vTaskDelay					1
+#define INCLUDE_uxTaskGetStackHighWaterMark	1
+#define INCLUDE_pcTaskGetTaskName			1
+#define INCLUDE_xTaskGetIdleTaskHandle      1
+#define INCLUDE_pxTaskGetStackStart			1
+
+#define INCLUDE_xSemaphoreGetMutexHolder    1
+
+/* The priority at which the tick interrupt runs.  This should probably be
+   kept at 1. */
+#define configKERNEL_INTERRUPT_PRIORITY		1
+#define configSUPPORT_DYNAMIC_ALLOCATION    1
+#define configSUPPORT_STATIC_ALLOCATION CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
+
+#ifndef __ASSEMBLER__
+#if CONFIG_FREERTOS_ENABLE_STATIC_TASK_CLEAN_UP
+extern void vPortCleanUpTCB ( void *pxTCB );
+#define portCLEAN_UP_TCB( pxTCB )           vPortCleanUpTCB( pxTCB )
+#endif
+#endif
+
+/* Test FreeRTOS timers (with timer task) and more. */
+/* Some files don't compile if this flag is disabled */
+#define configUSE_TIMERS                    1
+#define configTIMER_TASK_PRIORITY           CONFIG_FREERTOS_TIMER_TASK_PRIORITY
+#define configTIMER_QUEUE_LENGTH            CONFIG_FREERTOS_TIMER_QUEUE_LENGTH
+#define configTIMER_TASK_STACK_DEPTH        CONFIG_FREERTOS_TIMER_TASK_STACK_DEPTH
+
+#define INCLUDE_xTimerPendFunctionCall      1
+#define INCLUDE_eTaskGetState               1
+#define configUSE_QUEUE_SETS                1
+
+#define configUSE_TICKLESS_IDLE             CONFIG_FREERTOS_USE_TICKLESS_IDLE
+#if configUSE_TICKLESS_IDLE
+#define configEXPECTED_IDLE_TIME_BEFORE_SLEEP   CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP
+#endif //configUSE_TICKLESS_IDLE
+
+#ifndef configENABLE_TASK_SNAPSHOT
+#define configENABLE_TASK_SNAPSHOT          1
+#endif
+
+#if CONFIG_FREERTOS_CHECK_MUTEX_GIVEN_BY_OWNER
+#define configCHECK_MUTEX_GIVEN_BY_OWNER    1
+#else
+#define configCHECK_MUTEX_GIVEN_BY_OWNER    0
+#endif
+
+#endif /* FREERTOS_CONFIG_H */

+ 0 - 0
components/freertos/xtensa/include/freertos/portbenchmark.h → components/freertos/port/riscv/include/freertos/portbenchmark.h


+ 310 - 0
components/freertos/port/riscv/include/freertos/portmacro.h

@@ -0,0 +1,310 @@
+/*
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __ASSEMBLER__
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "sdkconfig.h"
+#include "esp_attr.h"
+#include "esp_heap_caps.h"
+#ifdef CONFIG_LEGACY_INCLUDE_COMMON_HEADERS
+#include "soc/soc_memory_layout.h"
+#endif
+#include "soc/spinlock.h"
+#include "soc/interrupt_core0_reg.h"
+#include "esp_rom_sys.h"
+#include "soc/cpu.h"
+#include "esp_system.h"
+#include "esp_newlib.h"
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+#define portCHAR		uint8_t
+#define portFLOAT		float
+#define portDOUBLE		double
+#define portLONG		int32_t
+#define portSHORT		int16_t
+#define portSTACK_TYPE	uint8_t
+#define portBASE_TYPE	int
+// interrupt module will mask interrupt with priority less than threshold
+#define RVHAL_EXCM_LEVEL    4
+
+typedef portSTACK_TYPE			StackType_t;
+typedef portBASE_TYPE			BaseType_t;
+typedef unsigned portBASE_TYPE	UBaseType_t;
+
+#if( configUSE_16_BIT_TICKS == 1 )
+	typedef uint16_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffff
+#else
+	typedef uint32_t TickType_t;
+	#define portMAX_DELAY ( TickType_t ) 0xffffffffUL
+#endif
+/*------------------------------------------------------*/
+
+/* Architecture specifics. */
+#define portSTACK_GROWTH			( -1 )
+#define portTICK_PERIOD_MS			( ( TickType_t ) (1000 / configTICK_RATE_HZ) )
+#define portBYTE_ALIGNMENT			16
+/*-----------------------------------------------------------*/
+#include "portbenchmark.h"
+
+static inline uint32_t IRAM_ATTR xPortGetCoreID(void) {
+    return cpu_hal_get_core_id();
+}
+
+
+static inline bool IRAM_ATTR xPortCanYield(void)
+{
+    uint32_t threshold = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
+    /* when enter critical code, freertos will mask threshold to RVHAL_EXCM_LEVEL
+     * and exit critical code, will recover threshold value (1). so threshold <= 1
+     * means not in critical code
+     */
+    return (threshold <= 1);
+}
+
+static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set)
+{
+#if defined(CONFIG_SPIRAM)
+    compare_and_set_extram(addr, compare, set);
+#endif
+}
+
+static inline void __attribute__((always_inline)) uxPortCompareSet(volatile uint32_t *addr, uint32_t compare, uint32_t *set) {
+    compare_and_set_native(addr, compare, set);
+}
+
+#define portCRITICAL_NESTING_IN_TCB 0
+
+/*
+ * Send an interrupt to another core in order to make the task running
+ * on it yield for a higher-priority task.
+ */
+void vPortYieldOtherCore( BaseType_t coreid);
+
+/*
+ Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
+ watchpoint around.
+ */
+void vPortSetStackWatchpoint( void* pxStackStart );
+
+/*
+ * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
+ * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
+ */
+BaseType_t xPortInIsrContext(void);
+
+/*
+ * This function will be called in High prio ISRs. Returns true if the current core was in ISR context
+ * before calling into high prio ISR context.
+ */
+BaseType_t xPortInterruptedFromISRContext(void);
+
+/* "mux" data structure (spinlock) */
+typedef struct {
+	/* owner field values:
+	 * 0				- Uninitialized (invalid)
+	 * portMUX_FREE_VAL - Mux is free, can be locked by either CPU
+	 * CORE_ID_REGVAL_PRO / CORE_ID_REGVAL_APP - Mux is locked to the particular core
+	 *
+	 *
+	 * Any value other than portMUX_FREE_VAL, CORE_ID_REGVAL_PRO, CORE_ID_REGVAL_APP indicates corruption
+	 */
+	uint32_t owner;
+	/* count field:
+	 * If mux is unlocked, count should be zero.
+	 * If mux is locked, count is non-zero & represents the number of recursive locks on the mux.
+	 */
+	uint32_t count;
+#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+	const char *lastLockedFn;
+	int lastLockedLine;
+#endif
+} portMUX_TYPE;
+
+#define portMUX_FREE_VAL		SPINLOCK_FREE
+
+/* Special constants for vPortCPUAcquireMutexTimeout() */
+#define portMUX_NO_TIMEOUT      SPINLOCK_WAIT_FOREVER  /* When passed for 'timeout_cycles', spin forever if necessary */
+#define portMUX_TRY_LOCK        SPINLOCK_NO_WAIT     /* Try to acquire the spinlock a single time only */
+
+// Keep this in sync with the portMUX_TYPE struct definition please.
+#ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
+#define portMUX_INITIALIZER_UNLOCKED {					\
+		.owner = portMUX_FREE_VAL,						\
+		.count = 0,										\
+	}
+#else
+#define portMUX_INITIALIZER_UNLOCKED {					\
+		.owner = portMUX_FREE_VAL,						\
+		.count = 0,										\
+		.lastLockedFn = "(never locked)",				\
+		.lastLockedLine = -1							\
+	}
+#endif
+
+/* Scheduler utilities. */
+extern void vPortYield( void );
+extern void vPortYieldFromISR( void );
+
+#define portYIELD()			    vPortYield()
+#define portYIELD_FROM_ISR()    vPortYieldFromISR()
+
+/* Yielding within an API call (when interrupts are off), means the yield should be delayed
+   until interrupts are re-enabled.
+   To do this, we use the "cross-core" interrupt as a trigger to yield on this core when interrupts are re-enabled.This
+   is the same interrupt & code path which is used to trigger a yield between CPUs, although in this case the yield is
+   happening on the same CPU.
+*/
+#define portYIELD_WITHIN_API() portYIELD()
+/*-----------------------------------------------------------*/
+
+/* Critical section management. */
+extern int vPortSetInterruptMask(void);
+extern void vPortClearInterruptMask( int );
+
+void vPortCPUInitializeMutex(portMUX_TYPE *mux);
+void vPortCPUAcquireMutex(portMUX_TYPE *mux);
+bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles);
+void vPortCPUReleaseMutex(portMUX_TYPE *mux);
+
+extern void vPortEnterCritical( void );
+extern void vPortExitCritical( void );
+
+#define portDISABLE_INTERRUPTS()				portSET_INTERRUPT_MASK_FROM_ISR()
+#define portENABLE_INTERRUPTS()					portCLEAR_INTERRUPT_MASK_FROM_ISR(1)
+
+#define portENTER_CRITICAL(mux)		{(void)mux;  vPortEnterCritical();}
+#define portEXIT_CRITICAL(mux)		{(void)mux;  vPortExitCritical();}
+
+#define portENTER_CRITICAL_ISR(mux)    portENTER_CRITICAL(mux)
+#define portEXIT_CRITICAL_ISR(mux)     portEXIT_CRITICAL(mux)
+
+#define portENTER_CRITICAL_SAFE(mux)  do {                                             \
+                                         if (xPortInIsrContext()) {                    \
+                                             portENTER_CRITICAL_ISR(mux);              \
+                                         } else {                                      \
+                                             portENTER_CRITICAL(mux);                  \
+                                         }                                             \
+                                      } while(0)
+
+#define portEXIT_CRITICAL_SAFE(mux)  do {                                              \
+                                         if (xPortInIsrContext()) {                    \
+                                             portEXIT_CRITICAL_ISR(mux);               \
+                                         } else {                                      \
+                                             portEXIT_CRITICAL(mux);                   \
+                                         }                                             \
+                                      } while(0)
+
+/*------------------------------------------------------------*/
+#define portSET_INTERRUPT_MASK_FROM_ISR()       vPortSetInterruptMask()
+#define portCLEAR_INTERRUPT_MASK_FROM_ISR( uxSavedStatusValue )       vPortClearInterruptMask( uxSavedStatusValue )
+#define portEND_SWITCHING_ISR( xSwitchRequired ) if( xSwitchRequired ) vPortYield()
+
+// Cleaner solution allows nested interrupts disabling and restoring via local registers or stack.
+// They can be called from interrupts too.
+static inline unsigned portENTER_CRITICAL_NESTED(void) {
+    unsigned state = portSET_INTERRUPT_MASK_FROM_ISR();
+	return state;
+}
+
+#define portEXIT_CRITICAL_NESTED(state)   do { portCLEAR_INTERRUPT_MASK_FROM_ISR( state );} while(0);
+/*-----------------------------------------------------------*/
+
+//Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force
+//the stack memory to always be internal.
+#define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
+#define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
+
+#define pvPortMallocTcbMem(size) pvPortMalloc(size)
+#define pvPortMallocStackMem(size)  pvPortMalloc(size)
+
+/* Fine resolution time */
+#define portGET_RUN_TIME_COUNTER_VALUE() 0
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+
+#ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
+/* Coarse resolution time (us) */
+#define portALT_GET_RUN_TIME_COUNTER_VALUE(x)    do{(void)x; }while(0)
+#endif
+
+extern void esp_vApplicationIdleHook( void );
+extern void esp_vApplicationTickHook( void );
+
+#ifndef CONFIG_FREERTOS_LEGACY_HOOKS
+#define vApplicationIdleHook    esp_vApplicationIdleHook
+#define vApplicationTickHook    esp_vApplicationTickHook
+#endif /* !CONFIG_FREERTOS_LEGACY_HOOKS */
+
+/* Task function macros as described on the FreeRTOS.org WEB site. */
+#define portTASK_FUNCTION_PROTO( vFunction, pvParameters ) void vFunction( void *pvParameters )
+#define portTASK_FUNCTION( vFunction, pvParameters ) void vFunction( void *pvParameters )
+
+void vApplicationSleep( TickType_t xExpectedIdleTime );
+#define portSUPPRESS_TICKS_AND_SLEEP( idleTime ) vApplicationSleep( idleTime )
+
+#define portNOP() __asm volatile 	( " nop " )
+
+#define portVALID_TCB_MEM(ptr) esp_ptr_byte_accessible(ptr)
+#define portVALID_STACK_MEM(ptr) esp_ptr_byte_accessible(ptr)
+
+// configASSERT_2 if requested
+#if configASSERT_2
+#include <stdio.h>
+void exit(int);
+#define configASSERT( x )   if (!(x)) { porttracePrint(-1); printf("\nAssertion failed in %s:%d\n", __FILE__, __LINE__); exit(-1); }
+#endif
+
+
+#endif //__ASSEMBLER__
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* PORTMACRO_H */

+ 369 - 0
components/freertos/port/riscv/port.c

@@ -0,0 +1,369 @@
+/*
+    FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd.
+    All rights reserved
+
+    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+
+    This file is part of the FreeRTOS distribution and was contributed
+    to the project by Technolution B.V. (www.technolution.nl,
+    freertos-riscv@technolution.eu) under the terms of the FreeRTOS
+    contributors license.
+
+    FreeRTOS is free software; you can redistribute it and/or modify it under
+    the terms of the GNU General Public License (version 2) as published by the
+    Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception.
+
+    ***************************************************************************
+    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+    >>!   distribute a combined work that includes FreeRTOS without being   !<<
+    >>!   obliged to provide the source code for proprietary components     !<<
+    >>!   outside of the FreeRTOS kernel.                                   !<<
+    ***************************************************************************
+
+    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+    FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+    link: http://www.freertos.org/a00114.html
+
+    ***************************************************************************
+     *                                                                       *
+     *    FreeRTOS provides completely free yet professionally developed,    *
+     *    robust, strictly quality controlled, supported, and cross          *
+     *    platform software that is more than just the market leader, it     *
+     *    is the industry's de facto standard.                               *
+     *                                                                       *
+     *    Help yourself get started quickly while simultaneously helping     *
+     *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+     *    tutorial book, reference manual, or both:                          *
+     *    http://www.FreeRTOS.org/Documentation                              *
+     *                                                                       *
+    ***************************************************************************
+
+    http://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+    the FAQ page "My application does not run, what could be wrong?".  Have you
+    defined configASSERT()?
+
+    http://www.FreeRTOS.org/support - In return for receiving this top quality
+    embedded software for free we request you assist our global community by
+    participating in the support forum.
+
+    http://www.FreeRTOS.org/training - Investing in training allows your team to
+    be as productive as possible as early as possible.  Now you can receive
+    FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+    Ltd, and the world's leading authority on the world's leading RTOS.
+
+    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+    compatible FAT file system, and our tiny thread aware UDP/IP stack.
+
+    http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+    Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+
+    http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High
+    Integrity Systems ltd. to sell under the OpenRTOS brand.  Low cost OpenRTOS
+    licenses offer ticketed support, indemnification and commercial middleware.
+
+    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
+    engineered and independently SIL3 certified version for use in safety and
+    mission critical applications that require provable dependability.
+
+    1 tab == 4 spaces!
+*/
+
+/*-----------------------------------------------------------------------
+ * Implementation of functions defined in portable.h for the RISC-V port.
+ *----------------------------------------------------------------------*/
+
+#include <string.h>
+#include "FreeRTOS.h"
+#include "task.h"
+#include "sdkconfig.h"
+#include "portmacro.h"
+#include "riscv/interrupt.h"
+#include "soc/periph_defs.h"
+#include "soc/system_reg.h"
+#include "soc/interrupt_reg.h"
+#include "hal/systimer_hal.h"
+#include "hal/systimer_ll.h"
+#include "riscv/riscv_interrupts.h"
+#include "riscv/interrupt.h"
+#include "esp_system.h"
+#include "esp_intr_alloc.h"
+#include "esp_log.h"
+
+/**
+ * @brief A variable is used to keep track of the critical section nesting.
+ * @note This variable has to be stored as part of the task context and must be initialized to a non zero value
+ *       to ensure interrupts don't inadvertently become unmasked before the scheduler starts.
+ *       As it is stored as part of the task context it will automatically be set to 0 when the first task is started.
+ */
+static UBaseType_t uxCriticalNesting = 0;
+static UBaseType_t uxSavedInterruptState = 0;
+BaseType_t uxSchedulerRunning = 0;
+UBaseType_t uxInterruptNesting = 0;
+__attribute__((aligned(16))) static StackType_t xIsrStack[configISR_STACK_SIZE];
+StackType_t *xIsrStackTop = &xIsrStack[0] + (configISR_STACK_SIZE & (~((portPOINTER_SIZE_TYPE)portBYTE_ALIGNMENT_MASK)));
+
+static const char *TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
+
+static void vPortSysTickHandler(void);
+static void vPortSetupTimer(void);
+static void vPortSetupSoftwareInterrupt(void);
+static void vPortSoftwareInterrupt(void);
+static void prvTaskExitError(void);
+
+extern void esprv_intc_int_set_threshold(int); // FIXME, this function is in ROM only
+
+void vPortEnterCritical(void)
+{
+    BaseType_t state = portENTER_CRITICAL_NESTED();
+    uxCriticalNesting++;
+
+    if (uxCriticalNesting == 1) {
+        //portDISABLE_INTERRUPTS();
+        uxSavedInterruptState = state;
+    }
+}
+
+void vPortExitCritical(void)
+{
+    if (uxCriticalNesting > 0) {
+        uxCriticalNesting--;
+        if (uxCriticalNesting == 0) {
+            portEXIT_CRITICAL_NESTED(uxSavedInterruptState);
+            //portENABLE_INTERRUPTS();
+        }
+    }
+}
+
+/**
+ * @brief Set up the systimer peripheral to generate the tick interrupt
+ *
+ */
+void vPortSetupTimer(void)
+{
+    /* register the interrupt handler */
+    intr_handler_set(ETS_SYSTICK_INUM, (intr_handler_t)&vPortSysTickHandler, NULL);
+
+    /* pass the timer interrupt through the interrupt matrix */
+    intr_matrix_route(ETS_SYSTIMER_TARGET0_EDGE_INTR_SOURCE, ETS_SYSTICK_INUM);
+
+    /* enable the interrupt in the INTC */
+    esprv_intc_int_enable(BIT(ETS_SYSTICK_INUM));
+    esprv_intc_int_set_type(BIT(ETS_SYSTICK_INUM), INTR_TYPE_LEVEL);
+    esprv_intc_int_set_priority(ETS_SYSTICK_INUM, 1);
+
+    /* configure the timer */
+    systimer_hal_init();
+    systimer_hal_enable_counter(SYSTIMER_COUNTER_1);
+    systimer_hal_set_alarm_period(SYSTIMER_ALARM_0, 1000000UL / CONFIG_FREERTOS_HZ);
+    systimer_hal_select_alarm_mode(SYSTIMER_ALARM_0, SYSTIMER_ALARM_MODE_PERIOD);
+    systimer_hal_enable_alarm_int(SYSTIMER_ALARM_0);
+    systimer_hal_connect_alarm_counter(SYSTIMER_ALARM_0, SYSTIMER_COUNTER_1);
+}
+
+/* setup software interrupt */
+void vPortSetupSoftwareInterrupt(void)
+{
+    /* register the interrupt handler, see interrupt.h */
+    intr_handler_set(ETS_CPU_INTR0_INUM, (intr_handler_t)&vPortSoftwareInterrupt, NULL);
+
+    /* pass the "FROM_CPU_0", a.k.a. cross-core interrupt, through the interrupt matrix */
+    intr_matrix_route(ETS_FROM_CPU_INTR0_SOURCE, ETS_CPU_INTR0_INUM);
+
+    /* enable the interrupt in the INTC */
+    esprv_intc_int_enable(BIT(ETS_CPU_INTR0_INUM));
+    esprv_intc_int_set_type(BIT(ETS_CPU_INTR0_INUM), INTR_TYPE_LEVEL);
+    esprv_intc_int_set_priority(ETS_CPU_INTR0_INUM, 1);
+
+    // TODO ESP32-C3 IDF-2126, maybe can use interrupt allocation API for all of the above? unsure...
+    esp_intr_reserve(ETS_CPU_INTR0_INUM, xPortGetCoreID());
+}
+
+void prvTaskExitError(void)
+{
+    /* A function that implements a task must not exit or attempt to return to
+    its caller as there is nothing to return to.  If a task wants to exit it
+    should instead call vTaskDelete( NULL ).
+
+    Artificially force an assert() to be triggered if configASSERT() is
+    defined, then stop here so application writers can catch the error. */
+    configASSERT(uxCriticalNesting == ~0UL);
+    portDISABLE_INTERRUPTS();
+    for (;;)
+        ;
+}
+
+/* Clear current interrupt mask and set given mask */
+void vPortClearInterruptMask(int mask)
+{
+    REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, mask);
+}
+
+/* Set interrupt mask and return current interrupt enable register */
+int vPortSetInterruptMask(void)
+{
+    int ret;
+    unsigned old_mstatus = RV_CLEAR_CSR(mstatus, MSTATUS_MIE);
+    ret = REG_READ(INTERRUPT_CORE0_CPU_INT_THRESH_REG);
+    REG_WRITE(INTERRUPT_CORE0_CPU_INT_THRESH_REG, RVHAL_EXCM_LEVEL);
+    RV_SET_CSR(mstatus, old_mstatus & MSTATUS_MIE);
+    return ret;
+}
+
+/*
+ * See header file for description.
+ */
+StackType_t *pxPortInitialiseStack(StackType_t *pxTopOfStack, TaskFunction_t pxCode, void *pvParameters)
+{
+    extern uint32_t __global_pointer$;
+
+    /* Simulate the stack frame as it would be created by a context switch
+    interrupt. */
+    RvExcFrame *frame = (RvExcFrame *)pxTopOfStack;
+    frame--;
+    frame->ra = (UBaseType_t)prvTaskExitError;
+    frame->mepc = (UBaseType_t)pxCode;
+    frame->a0 = (UBaseType_t)pvParameters;
+    frame->gp = (UBaseType_t)&__global_pointer$;
+    frame->a1 = 0x11111111;
+    frame->a2 = 0x22222222;
+    frame->a3 = 0x33333333;
+    return (StackType_t *)frame;
+}
+
+void vPortSysTickHandler(void)
+{
+    systimer_ll_clear_alarm_int(SYSTIMER_ALARM_0);
+
+    if (!uxSchedulerRunning) {
+        return;
+    }
+
+    if (xTaskIncrementTick() != pdFALSE) {
+        vTaskSwitchContext();
+    }
+}
+
+BaseType_t xPortStartScheduler(void)
+{
+    vPortSetupTimer();
+    vPortSetupSoftwareInterrupt();
+    uxCriticalNesting = 0;
+    uxSchedulerRunning = 0;          /* this means first yield */
+    esprv_intc_int_set_threshold(1); /* set global INTC masking level */
+    riscv_global_interrupts_enable();
+    vPortYield();
+    /*Should not get here*/
+    return pdFALSE;
+}
+
+void vPortEndScheduler(void)
+{
+    /* very unlikely this function will be called, so just trap here */
+    while (1)
+        ;
+}
+
+void vPortSoftwareInterrupt(void)
+{
+    uxSchedulerRunning = 1;
+    vTaskSwitchContext();
+    REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 0);
+}
+
+void vPortYieldOtherCore(BaseType_t coreid)
+{
+    (void)coreid;
+    vPortYield();
+}
+
+void vPortYield(void)
+{
+    if (uxInterruptNesting) {
+        vPortYieldFromISR();
+    } else {
+        REG_WRITE(SYSTEM_CPU_INTR_FROM_CPU_0_REG, 1);
+
+        /* There are 3-4 instructions of latency between triggering the software
+           interrupt and the CPU interrupt happening. Make sure it happened before
+           we return, otherwise vTaskDelay() may return and execute 1-2
+           instructions before the delay actually happens.
+
+           (We could use the WFI instruction here, but there is a chance that
+           the interrupt will happen while evaluating the other two conditions
+           for an instant yield, and if that happens then the WFI would be
+           waiting for the next interrupt to occur...)
+        */
+        while(uxSchedulerRunning && uxCriticalNesting == 0 && REG_READ(SYSTEM_CPU_INTR_FROM_CPU_0_REG) != 0) { }
+    }
+}
+
+void vPortYieldFromISR(void)
+{
+    vTaskSwitchContext();
+}
+
+void vPortSetStackWatchpoint(void *pxStackStart)
+{
+    (void)pxStackStart; // TODO ESP32-C3 IDF-2207
+}
+
+BaseType_t xPortInIsrContext(void)
+{
+    return uxInterruptNesting;
+}
+
+BaseType_t IRAM_ATTR xPortInterruptedFromISRContext(void)
+{
+    /* For single core, this can be the same as xPortInIsrContext() because reading it is atomic */
+	return uxInterruptNesting;
+}
+
+
+void vPortCPUInitializeMutex(portMUX_TYPE *mux)
+{
+    (void)mux;
+}
+
+void vPortCPUAcquireMutex(portMUX_TYPE *mux)
+{
+    (void)mux;
+}
+
+bool vPortCPUAcquireMutexTimeout(portMUX_TYPE *mux, int timeout_cycles)
+{
+    (void)mux;
+    (void)timeout_cycles;
+    return true;
+}
+
+void vPortCPUReleaseMutex(portMUX_TYPE *mux)
+{
+    (void)mux;
+}
+
+void __attribute__((weak)) vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName)
+{
+#define ERR_STR1 "***ERROR*** A stack overflow in task "
+#define ERR_STR2 " has been detected."
+    const char *str[] = {ERR_STR1, pcTaskName, ERR_STR2};
+
+    char buf[sizeof(ERR_STR1) + CONFIG_FREERTOS_MAX_TASK_NAME_LEN + sizeof(ERR_STR2) + 1 /* null char */] = {0};
+
+    char *dest = buf;
+    for (int i = 0; i < sizeof(str) / sizeof(str[0]); i++) {
+        dest = strcat(dest, str[i]);
+    }
+    esp_system_abort(buf);
+}
+
+extern void esp_startup_start_app_common(void);
+
+void esp_startup_start_app(void)
+{
+    esp_startup_start_app_common();
+
+    ESP_LOGI(TAG, "Starting scheduler.");
+    vTaskStartScheduler();
+}

+ 87 - 0
components/freertos/port/riscv/portasm.S

@@ -0,0 +1,87 @@
+// 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.
+
+    .global uxInterruptNesting
+    .global uxSchedulerRunning
+    .global xIsrStackTop
+    .global pxCurrentTCB
+    .global vTaskSwitchContext
+    .global xPortSwitchFlag
+
+    .section .text
+
+/**
+ * This function makes the RTOS aware about a ISR entering, it takes the
+ * current task stack saved, places into the TCB, loads the ISR stack
+ * the interrupted stack must be passed in a0. It needs to receive the
+ * ISR nesting code improvements
+ */
+
+    .global rtos_int_enter
+    .type rtos_int_enter, @function
+rtos_int_enter:
+    /* preserve the return address */
+    mv t1, ra
+    mv t2, a0
+
+    /* scheduler not enabled, jump directly to ISR handler */
+    lw t0, uxSchedulerRunning
+    beq t0,zero, not_rtos_enter
+
+    /* Sabe current TCB and load the ISR stack */
+    lw  t0, pxCurrentTCB
+    sw 	t2, 0x0(t0)
+    lw  sp, xIsrStackTop
+
+not_rtos_enter:
+    mv  ra, t1
+    ret
+
+/**
+ * Recovers the next task to run stack pointer and place it into
+ * a0, then the interrupt handler can restore the context of
+ * the next task
+ */
+    .global rtos_int_exit
+    .type rtos_int_exit, @function
+rtos_int_exit:
+
+    /* may skip RTOS aware interrupt since scheduler was not started */
+    lw t0, uxSchedulerRunning
+    beq t0,zero, not_rtos_exit
+
+    /* Schedule the next task if a yield is pending */
+    la t0, xPortSwitchFlag
+    lw t2, 0x0(t0)
+    beq t2, zero, no_switch
+
+    /* preserve return address and schedule next task */
+    addi sp,sp,-4
+    sw  ra, 0x04(sp)
+    call vTaskSwitchContext
+    lw  ra, 0x04(sp)
+    addi sp, sp, 4
+
+    /* Clears the switch pending flag */
+    la t0, xPortSwitchFlag
+    mv t2, zero
+    sw  t2, 0x0(t0)
+
+no_switch:
+    /* Recover the stack of next task and prepare to exit : */
+    lw a0, pxCurrentTCB
+    lw a0, 0x0(a0)
+
+not_rtos_exit:
+    ret

+ 0 - 0
components/freertos/xtensa/include/freertos/FreeRTOSConfig.h → components/freertos/port/xtensa/include/freertos/FreeRTOSConfig.h


+ 46 - 0
components/freertos/port/xtensa/include/freertos/portbenchmark.h

@@ -0,0 +1,46 @@
+/*******************************************************************************
+// Copyright (c) 2003-2015 Cadence Design Systems, Inc.
+//
+// Permission is hereby granted, free of charge, to any person obtaining
+// a copy of this software and associated documentation files (the
+// "Software"), to deal in the Software without restriction, including
+// without limitation the rights to use, copy, modify, merge, publish,
+// distribute, sublicense, and/or sell copies of the Software, and to
+// permit persons to whom the Software is furnished to do so, subject to
+// the following conditions:
+//
+// The above copyright notice and this permission notice shall be included
+// in all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+--------------------------------------------------------------------------------
+*/
+
+/*
+ * This utility helps benchmarking interrupt latency and context switches.
+ * In order to enable it, set configBENCHMARK to 1 in FreeRTOSConfig.h.
+ * You will also need to download the FreeRTOS_trace patch that contains
+ * portbenchmark.c and the complete version of portbenchmark.h
+ */
+
+#ifndef PORTBENCHMARK_H
+#define PORTBENCHMARK_H
+
+#if configBENCHMARK
+    #error "You need to download the FreeRTOS_trace patch that overwrites this file"
+#endif
+
+#define portbenchmarkINTERRUPT_DISABLE()
+#define portbenchmarkINTERRUPT_RESTORE(newstate)
+#define portbenchmarkIntLatency()
+#define portbenchmarkIntWait()
+#define portbenchmarkReset()
+#define portbenchmarkPrint()
+
+#endif /* PORTBENCHMARK */

+ 30 - 65
components/freertos/xtensa/include/freertos/portmacro.h → components/freertos/port/xtensa/include/freertos/portmacro.h

@@ -1,68 +1,29 @@
 /*
-    FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
-    All rights reserved
-
-    VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
-
-    ***************************************************************************
-     *                                                                       *
-     *    FreeRTOS provides completely free yet professionally developed,    *
-     *    robust, strictly quality controlled, supported, and cross          *
-     *    platform software that has become a de facto standard.             *
-     *                                                                       *
-     *    Help yourself get started quickly and support the FreeRTOS         *
-     *    project by purchasing a FreeRTOS tutorial book, reference          *
-     *    manual, or both from: http://www.FreeRTOS.org/Documentation        *
-     *                                                                       *
-     *    Thank you!                                                         *
-     *                                                                       *
-    ***************************************************************************
-
-    This file is part of the FreeRTOS distribution.
-
-    FreeRTOS is free software; you can redistribute it and/or modify it under
-    the terms of the GNU General Public License (version 2) as published by the
-    Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
-
-    >>!   NOTE: The modification to the GPL is included to allow you to     !<<
-    >>!   distribute a combined work that includes FreeRTOS without being   !<<
-    >>!   obliged to provide the source code for proprietary components     !<<
-    >>!   outside of the FreeRTOS kernel.                                   !<<
-
-    FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
-    WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
-    FOR A PARTICULAR PURPOSE.  Full license text is available from the following
-    link: http://www.freertos.org/a00114.html
-
-    1 tab == 4 spaces!
-
-    ***************************************************************************
-     *                                                                       *
-     *    Having a problem?  Start by reading the FAQ "My application does   *
-     *    not run, what could be wrong?"                                     *
-     *                                                                       *
-     *    http://www.FreeRTOS.org/FAQHelp.html                               *
-     *                                                                       *
-    ***************************************************************************
-
-    http://www.FreeRTOS.org - Documentation, books, training, latest versions,
-    license and Real Time Engineers Ltd. contact details.
-
-    http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
-    including FreeRTOS+Trace - an indispensable productivity tool, a DOS
-    compatible FAT file system, and our tiny thread aware UDP/IP stack.
-
-    http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High
-    Integrity Systems to sell under the OpenRTOS brand.  Low cost OpenRTOS
-    licenses offer ticketed support, indemnification and middleware.
-
-    http://www.SafeRTOS.com - High Integrity Systems also provide a safety
-    engineered and independently SIL3 certified version for use in safety and
-    mission critical applications that require provable dependability.
-
-    1 tab == 4 spaces!
-*/
-
+ * FreeRTOS Kernel V10.2.1
+ * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * this software and associated documentation files (the "Software"), to deal in
+ * the Software without restriction, including without limitation the rights to
+ * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+ * the Software, and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+ * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+ * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+ * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * http://www.FreeRTOS.org
+ * http://aws.amazon.com/freertos
+ *
+ * 1 tab == 4 spaces!
+ */
 #ifndef PORTMACRO_H
 #define PORTMACRO_H
 
@@ -108,8 +69,11 @@ extern "C" {
  *-----------------------------------------------------------
  */
 
-/* Type definitions. */
+#include "esp_system.h"
+#include "hal/cpu_hal.h"
+#include "xt_instr_macros.h"
 
+/* Type definitions. */
 #define portCHAR		int8_t
 #define portFLOAT		float
 #define portDOUBLE		double
@@ -136,6 +100,7 @@ typedef unsigned portBASE_TYPE	UBaseType_t;
 
 #include "sdkconfig.h"
 #include "esp_attr.h"
+#include "portmacro_priv.h"
 
 // Cleaner solution allows nested interrupts disabling and restoring via local registers or stack.
 // They can be called from interrupts too.

+ 0 - 0
components/freertos/xtensa/portmacro_priv.h → components/freertos/port/xtensa/include/freertos/portmacro_priv.h


+ 0 - 0
components/freertos/xtensa/include/freertos/xtensa_api.h → components/freertos/port/xtensa/include/freertos/xtensa_api.h


+ 0 - 0
components/freertos/xtensa/include/freertos/xtensa_config.h → components/freertos/port/xtensa/include/freertos/xtensa_config.h


+ 0 - 0
components/freertos/xtensa/include/freertos/xtensa_context.h → components/freertos/port/xtensa/include/freertos/xtensa_context.h


+ 0 - 0
components/freertos/xtensa/include/freertos/xtensa_rtos.h → components/freertos/port/xtensa/include/freertos/xtensa_rtos.h


+ 0 - 0
components/freertos/xtensa/include/freertos/xtensa_timer.h → components/freertos/port/xtensa/include/freertos/xtensa_timer.h


+ 7 - 82
components/freertos/xtensa/port.c → components/freertos/port/xtensa/port.c

@@ -139,8 +139,6 @@ extern void _frxt_tick_timer_init(void);
 /* Defined in xtensa_context.S */
 extern void _xt_coproc_init(void);
 
-extern void app_main(void);
-
 static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but
 								// for now maintain the same log output
 
@@ -154,7 +152,7 @@ static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate t
 _Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value");
 
 /*-----------------------------------------------------------*/
-volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting
+extern volatile int port_xSchedulerRunning[portNUM_PROCESSORS];
 unsigned port_interruptNesting[portNUM_PROCESSORS] = {0};  // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit
 BaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0};
 BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0};
@@ -488,66 +486,6 @@ void  __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c
 	esp_system_abort(buf);
 }
 
-
-static void main_task(void* args)
-{
-#if !CONFIG_FREERTOS_UNICORE
-	// Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack
-	while (port_xSchedulerRunning[1] == 0) {
-		;
-	}
-#endif
-
-	// [refactor-todo] check if there is a way to move the following block to esp_system startup
-	heap_caps_enable_nonos_stack_heaps();
-
-	// Now we have startup stack RAM available for heap, enable any DMA pool memory
-#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL
-	if (g_spiram_ok) {
-		esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL);
-		if (r != ESP_OK) {
-			ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r);
-			abort();
-		}
-	}
-#endif
-
-	//Initialize task wdt if configured to do so
-#ifdef CONFIG_ESP_TASK_WDT_PANIC
-	ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true));
-#elif CONFIG_ESP_TASK_WDT
-	ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false));
-#endif
-
-	//Add IDLE 0 to task wdt
-#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0
-	TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0);
-	if(idle_0 != NULL){
-		ESP_ERROR_CHECK(esp_task_wdt_add(idle_0));
-	}
-#endif
-	//Add IDLE 1 to task wdt
-#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1
-	TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1);
-	if(idle_1 != NULL){
-		ESP_ERROR_CHECK(esp_task_wdt_add(idle_1));
-	}
-#endif
-
-	app_main();
-	vTaskDelete(NULL);
-}
-
-// For now, running FreeRTOS on one core and a bare metal on the other (or other OSes)
-// is not supported. For now CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
-// should mirror each other's values.
-//
-// And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE.
-#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
-	#error "FreeRTOS and system configuration mismatch regarding the use of multiple cores."
-#endif
-
-
 #if !CONFIG_FREERTOS_UNICORE
 void esp_startup_start_app_other_cores(void)
 {
@@ -581,33 +519,18 @@ void esp_startup_start_app_other_cores(void)
 	xPortStartScheduler();
 	abort(); /* Only get to here if FreeRTOS somehow very broken */
 }
-#endif
+#endif // !CONFIG_FREERTOS_UNICORE
+
+extern void esp_startup_start_app_common(void);
 
 void esp_startup_start_app(void)
 {
-#if CONFIG_ESP_INT_WDT
-	esp_int_wdt_init();
-	//Initialize the interrupt watch dog for CPU0.
-	esp_int_wdt_cpu_init();
-#else
+#if !CONFIG_ESP_INT_WDT
 #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX
 	assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!");
 #endif
 #endif
 
-	esp_crosscore_int_init();
-
-#ifndef CONFIG_FREERTOS_UNICORE
-#if CONFIG_IDF_TARGET_ESP32
-	esp_dport_access_int_init();
-#endif
-#endif
-
-	portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main",
-												ESP_TASK_MAIN_STACK, NULL,
-												ESP_TASK_MAIN_PRIO, NULL, 0);
-	assert(res == pdTRUE);
-
 	// ESP32 has single core variants. Check that FreeRTOS has been configured properly.
 #if CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
 	if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) {
@@ -617,6 +540,8 @@ void esp_startup_start_app(void)
 	}
 #endif // CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE
 
+	esp_startup_start_app_common();
+
 	ESP_LOGI(TAG, "Starting scheduler on PRO CPU.");
 	vTaskStartScheduler();
 }

+ 0 - 0
components/freertos/xtensa/portasm.S → components/freertos/port/xtensa/portasm.S


+ 0 - 0
components/freertos/xtensa/readme_xtensa.txt → components/freertos/port/xtensa/readme_xtensa.txt


+ 0 - 0
components/freertos/xtensa/xt_asm_utils.h → components/freertos/port/xtensa/xt_asm_utils.h


+ 0 - 0
components/freertos/xtensa/xtensa_context.S → components/freertos/port/xtensa/xtensa_context.S


+ 0 - 0
components/freertos/xtensa/xtensa_init.c → components/freertos/port/xtensa/xtensa_init.c


+ 0 - 0
components/freertos/xtensa/xtensa_loadstore_handler.S → components/freertos/port/xtensa/xtensa_loadstore_handler.S


+ 0 - 0
components/freertos/xtensa/xtensa_overlay_os_hook.c → components/freertos/port/xtensa/xtensa_overlay_os_hook.c


+ 0 - 0
components/freertos/xtensa/xtensa_vector_defaults.S → components/freertos/port/xtensa/xtensa_vector_defaults.S


+ 0 - 0
components/freertos/xtensa/xtensa_vectors.S → components/freertos/port/xtensa/xtensa_vectors.S


+ 0 - 2
components/freertos/test/test_float_in_isr.c

@@ -5,9 +5,7 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "esp_intr_alloc.h"
-#include "xtensa/hal.h"
 #include "unity.h"
 #include "soc/cpu.h"
 #include "test_utils.h"

+ 2 - 0
components/freertos/test/test_freertos_backported_functions.c

@@ -29,6 +29,7 @@
 #include "unity.h"
 #include "test_utils.h"
 
+#ifdef CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION
 /* ---------------------Test 1: Backported Timer functions-----------------------
  * Test xTimerCreateStatic(), vTimerSetTimerId(), xTimerGetPeriod(), xTimerGetExpiryTime()
  *
@@ -200,6 +201,7 @@ TEST_CASE("Test FreeRTOS backported eventgroup functions", "[freertos]")
     //Cleanup static event
     vEventGroupDelete(eg_handle);
 }
+#endif
 
 /* --------Test backported thread local storage pointer and deletion cb feature----------
  * vTaskSetThreadLocalStoragePointerAndDelCallback()

+ 15 - 15
components/freertos/test/test_freertos_isinisrcontext.c

@@ -4,52 +4,52 @@
 
 #include <esp_types.h>
 #include <stdio.h>
-
+#include "sdkconfig.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 #include "esp_intr_alloc.h"
-#include "xtensa/hal.h"
 #include "esp_rom_sys.h"
+#include "esp_freertos_hooks.h"
 
 #if CONFIG_FREERTOS_CORETIMER_0
 
 static volatile int in_int_context, int_handled;
 
 
-static void testint(void *arg) {
-    xthal_set_ccompare(1, xthal_get_ccount()+8000000000);
+static void testint(void)
+{
     esp_rom_printf("INT!\n");
-    if (xPortInIsrContext()) in_int_context++;
+    if (xPortInIsrContext()) {
+        in_int_context++;
+    }
     int_handled++;
 }
 
 
-static void testthread(void *arg) {
-    intr_handle_t handle;
-    in_int_context=0;
-    int_handled=0;
+static void testthread(void *arg)
+{
+    in_int_context = 0;
+    int_handled = 0;
     TEST_ASSERT(!xPortInIsrContext());
-    xthal_set_ccompare(1, xthal_get_ccount()+8000000);
-    esp_err_t err = esp_intr_alloc(ETS_INTERNAL_TIMER1_INTR_SOURCE, 0, &testint, NULL, &handle);
+    esp_err_t err = esp_register_freertos_tick_hook_for_cpu(testint, xPortGetCoreID());
     TEST_ASSERT_EQUAL_HEX32(ESP_OK, err);
     vTaskDelay(100 / portTICK_PERIOD_MS);
     TEST_ASSERT(int_handled);
     TEST_ASSERT(in_int_context);
-    TEST_ASSERT_EQUAL_HEX32( ESP_OK, esp_intr_free(handle) );
+    esp_deregister_freertos_tick_hook_for_cpu(testint, xPortGetCoreID());
     vTaskDelete(NULL);
 }
 
 
 TEST_CASE("xPortInIsrContext test", "[freertos]")
 {
-    xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 0);
+    xTaskCreatePinnedToCore(testthread, "tst", 4096, NULL, 3, NULL, 0);
     vTaskDelay(150 / portTICK_PERIOD_MS);
 #if portNUM_PROCESSORS == 2
-    xTaskCreatePinnedToCore(testthread, "tst" , 4096, NULL, 3, NULL, 1);
+    xTaskCreatePinnedToCore(testthread, "tst", 4096, NULL, 3, NULL, 1);
     vTaskDelay(150 / portTICK_PERIOD_MS);
 #endif
 }

+ 0 - 2
components/freertos/test/test_freertos_scheduling_time.c

@@ -4,9 +4,7 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "esp_intr_alloc.h"
-#include "xtensa/hal.h"
 #include "unity.h"
 #include "soc/cpu.h"
 #include "test_utils.h"

+ 1 - 1
components/freertos/test/test_freertos_task_notify.c

@@ -189,7 +189,7 @@ TEST_CASE("Test Task_Notify", "[freertos]")
 
             xSemaphoreGive(trigger_send_semphr);    //Trigger sender task
             for(int k = 0; k < NO_OF_TASKS; k++){             //Wait for sender and receiver task deletion
-                xSemaphoreTake(task_delete_semphr, portMAX_DELAY);
+                TEST_ASSERT( xSemaphoreTake(task_delete_semphr, 1000 / portTICK_PERIOD_MS) );
             }
             vTaskDelay(5);      //Give time tasks to delete
 

+ 18 - 7
components/freertos/test/test_isr_latency.c

@@ -1,16 +1,26 @@
 #include <esp_types.h>
 #include <stdio.h>
-
+#include "sdkconfig.h"
 #include "freertos/FreeRTOS.h"
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "esp_intr_alloc.h"
-#include "xtensa/hal.h"
 #include "unity.h"
 #include "soc/cpu.h"
 #include "test_utils.h"
+#if CONFIG_IDF_TARGET_ARCH_XTENSA
+#include "xtensa/hal.h"
+#include "freertos/xtensa_api.h"
+#define TEST_SET_INT_MASK(mask) xt_set_intset(mask)
+#define TEST_CLR_INT_MASK(mask) xt_set_intclear(mask)
+#elif CONFIG_IDF_TARGET_ARCH_RISCV
+#include "riscv/interrupt.h"
+#define TEST_SET_INT_MASK(mask) esprv_intc_int_enable(mask)
+#define TEST_CLR_INT_MASK(mask) esprv_intc_int_disable(mask)
+#endif
+
+#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
 
 #define SW_ISR_LEVEL_1  7
 
@@ -25,8 +35,7 @@ static void software_isr_using_parameter_vportyield(void *arg) {
     (void)arg;
     BaseType_t yield;
     delta_enter_cycles += portGET_RUN_TIME_COUNTER_VALUE() - cycle_before_trigger;
-
-    xt_set_intclear(1 << SW_ISR_LEVEL_1);
+    TEST_CLR_INT_MASK(1 << SW_ISR_LEVEL_1);
 
     xSemaphoreGiveFromISR(sync, &yield);
     portYIELD_FROM_ISR(yield);
@@ -39,7 +48,7 @@ static void software_isr_using_no_argument_vportyield(void *arg) {
     BaseType_t yield;
     delta_enter_cycles += portGET_RUN_TIME_COUNTER_VALUE() - cycle_before_trigger;
 
-    xt_set_intclear(1 << SW_ISR_LEVEL_1);
+    TEST_CLR_INT_MASK(1 << SW_ISR_LEVEL_1);
 
     xSemaphoreGiveFromISR(sync, &yield);
     if(yield) {
@@ -53,7 +62,7 @@ static void test_task(void *arg) {
 
     for(int i = 0;i < 10000; i++) {
         cycle_before_trigger = portGET_RUN_TIME_COUNTER_VALUE();
-        xt_set_intset(1 << SW_ISR_LEVEL_1);
+        TEST_SET_INT_MASK(1 << SW_ISR_LEVEL_1);
         xSemaphoreTake(sync, portMAX_DELAY);
         delta_exit_cycles += portGET_RUN_TIME_COUNTER_VALUE() - cycle_before_exit;
     }
@@ -103,3 +112,5 @@ TEST_CASE("isr latency test vport-yield-from-isr with parameter", "[freertos][ig
 
     esp_intr_free(handle);
 }
+
+#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)

+ 0 - 1
components/freertos/test/test_newlib_reent.c

@@ -10,7 +10,6 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 
 volatile static int done;

+ 0 - 1
components/freertos/test/test_panic.c

@@ -9,7 +9,6 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 
 TEST_CASE("Panic handler", "[freertos][ignore]")

+ 5 - 5
components/freertos/test/test_preemption.c

@@ -9,9 +9,9 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 #include "soc/cpu.h"
+#include "hal/cpu_hal.h"
 #include "test_utils.h"
 #include "sdkconfig.h"
 
@@ -31,7 +31,7 @@ static void task_send_to_queue(void *param)
 
     while(!trigger) {}
 
-    RSR(CCOUNT, ccount);
+    ccount = cpu_hal_get_cycle_count();
     flag = true;
     xQueueSendToBack(queue, &ccount, 0);
     /* This is to ensure that higher priority task
@@ -60,7 +60,7 @@ TEST_CASE("Yield from lower priority task, same CPU", "[freertos]")
 
         uint32_t yield_ccount, now_ccount, delta;
         TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) );
-        RSR(CCOUNT, now_ccount);
+        now_ccount = cpu_hal_get_cycle_count();
         TEST_ASSERT( flag );
 
         delta = now_ccount - yield_ccount;
@@ -92,12 +92,12 @@ TEST_CASE("Yield from lower priority task, other CPU", "[freertos]")
 
         vTaskDelay(2); /* make sure everything is set up */
         trigger = true;
-        RSR(CCOUNT, trigger_ccount);
+        trigger_ccount = cpu_hal_get_cycle_count();
 
         // yield_ccount is not useful in this test as it's the other core's CCOUNT
         // so we use trigger_ccount instead
         TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) );
-        RSR(CCOUNT, now_ccount);
+        now_ccount = cpu_hal_get_cycle_count();
         TEST_ASSERT( flag );
 
         delta = now_ccount - trigger_ccount;

+ 3 - 3
components/freertos/test/test_spinlocks.c

@@ -9,9 +9,9 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 #include "soc/cpu.h"
+#include "hal/cpu_hal.h"
 
 #include "test_utils.h"
 
@@ -20,11 +20,11 @@
 static uint32_t start, end;
 
 #define BENCHMARK_START() do {                  \
-        RSR(CCOUNT, start);                     \
+        start = cpu_hal_get_cycle_count();                     \
     } while(0)
 
 #define BENCHMARK_END(OPERATION) do {                       \
-        RSR(CCOUNT, end);                                           \
+        end = cpu_hal_get_cycle_count();                                          \
         printf("%s took %d cycles/op (%d cycles for %d ops)\n",     \
                OPERATION, (end - start)/REPEAT_OPS,                 \
                (end - start), REPEAT_OPS);                          \

+ 0 - 1
components/freertos/test/test_suspend_scheduler.c

@@ -5,7 +5,6 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 #include "soc/cpu.h"
 #include "test_utils.h"

+ 0 - 1
components/freertos/test/test_task_suspend_resume.c

@@ -7,7 +7,6 @@
 #include "freertos/semphr.h"
 #include "freertos/timers.h"
 #include "freertos/queue.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 #include "soc/cpu.h"
 #include "test_utils.h"

+ 2 - 0
components/freertos/test/test_thread_local.c

@@ -11,6 +11,7 @@
 #include "test_utils.h"
 #include "sdkconfig.h"
 
+#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)
 
 static __thread int tl_test_var1;
 static __thread uint8_t tl_test_var2 = 55;
@@ -108,3 +109,4 @@ TEST_CASE("TLS test", "[freertos]")
     }
     vTaskDelay(10); /* Make sure idle task can clean up s_task, before it goes out of scope */
 }
+#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3)

+ 6 - 2
components/freertos/test/test_xtensa_loadstore_handler.c

@@ -5,10 +5,13 @@
 #include <esp_types.h>
 #include <stdio.h>
 #include <esp_heap_caps.h>
+#include "sdkconfig.h"
 #include "esp_system.h"
-#include "freertos/xtensa_api.h"
 #include "unity.h"
 
+#if CONFIG_IDF_TARGET_ARCH_XTENSA
+#include "freertos/xtensa_api.h"
+
 #ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
 TEST_CASE("LoadStore Exception handler", "[freertos]")
 {
@@ -119,4 +122,5 @@ TEST_CASE("LoadStore Exception handler", "[freertos]")
     TEST_ASSERT_TRUE(heap_caps_check_integrity_all(true));
     heap_caps_free(arr);
 }
-#endif
+#endif // CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
+#endif // CONFIG_IDF_TARGET_ARCH_XTENSA

Unele fișiere nu au fost afișate deoarece prea multe fișiere au fost modificate în acest diff