Merge branch 'feature/riscv_arch' into 'master'

Add RISC-V support

Closes IDF-2359

See merge request espressif/esp-idf!11140
This commit is contained in:
Angus Gratton 2020-11-13 07:50:31 +08:00
commit 935e4b4d62
159 changed files with 4055 additions and 890 deletions

11
Kconfig
View File

@ -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"

View File

@ -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"

View File

@ -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()

View File

@ -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();
}

View File

@ -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) {
}

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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) */

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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")

View File

@ -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));

View File

@ -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));

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)
{
}

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -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);
}

View File

@ -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)

View File

@ -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;

View File

@ -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})

View File

@ -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;
}

View File

@ -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");
}
}

View File

@ -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));

View File

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

View File

@ -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->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
} 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->pseudo_excause = pseudo_excause;
info->description = "Exception was unhandled.";
if (frame->exccause == EXCCAUSE_ILLEGAL) {
info->details = print_illegal_instruction_details;
}
if (pseudo_excause) {
panic_soc_fill_info(frame, info);
} else {
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);
}

View File

@ -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})

View File

@ -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];

View File

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

View File

@ -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})

View File

@ -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})

View File

@ -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"

View File

@ -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

View File

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

View File

@ -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";

View File

@ -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)

View File

@ -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

View File

@ -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)

View File

@ -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);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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();
}

View File

@ -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

View File

@ -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 */

View File

@ -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.

View File

@ -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();
}

View File

@ -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"

View File

@ -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()

View File

@ -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
}

View File

@ -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"

View File

@ -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

View File

@ -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)

View File

@ -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;

View File

@ -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]")

View File

@ -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;

View File

@ -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); \

View File

@ -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"

View File

@ -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"

View File

@ -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)

View File

@ -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

Some files were not shown because too many files have changed in this diff Show More