mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
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:
commit
935e4b4d62
11
Kconfig
11
Kconfig
@ -13,6 +13,14 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
bool
|
||||
option env="IDF_ENV_FPGA"
|
||||
|
||||
config IDF_TARGET_ARCH_RISCV
|
||||
bool
|
||||
default "n"
|
||||
|
||||
config IDF_TARGET_ARCH_XTENSA
|
||||
bool
|
||||
default "n"
|
||||
|
||||
config IDF_TARGET
|
||||
# This option records the IDF target when sdkconfig is generated the first time.
|
||||
# It is not updated if environment variable $IDF_TARGET changes later, and
|
||||
@ -24,15 +32,18 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
config IDF_TARGET_ESP32
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32"
|
||||
select IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
config IDF_TARGET_ESP32S2
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s2"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
config IDF_TARGET_ESP32S3
|
||||
bool
|
||||
default "y" if IDF_TARGET="esp32s3"
|
||||
select IDF_TARGET_ARCH_XTENSA
|
||||
|
||||
choice IDF_TARGET_ESP32S3_BETA_VERSION
|
||||
prompt "ESP32-S3 beta version"
|
||||
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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) {
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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");
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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) */
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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")
|
||||
|
@ -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));
|
||||
|
@ -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));
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -11,15 +11,19 @@
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef __SOC_SPINLOCK_H
|
||||
#define __SOC_SPINLOCK_H
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/cpu.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/compare_set.h"
|
||||
|
||||
#if __XTENSA__
|
||||
#include "xtensa/xtruntime.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
@ -62,7 +66,7 @@ static inline void __attribute__((always_inline)) spinlock_initialize(spinlock_t
|
||||
*/
|
||||
static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *lock, int32_t timeout)
|
||||
{
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD
|
||||
uint32_t result;
|
||||
uint32_t irq_status;
|
||||
uint32_t ccount_start;
|
||||
@ -106,7 +110,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
|
||||
|
||||
if (timeout != SPINLOCK_WAIT_FOREVER) {
|
||||
uint32_t ccount_now;
|
||||
RSR(CCOUNT, ccount_now);
|
||||
ccount_now = cpu_hal_get_cycle_count();
|
||||
if (ccount_now - ccount_start > (unsigned)timeout) {
|
||||
XTOS_RESTORE_INTLEVEL(irq_status);
|
||||
return false;
|
||||
@ -123,10 +127,9 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
|
||||
XTOS_RESTORE_INTLEVEL(irq_status);
|
||||
return true;
|
||||
|
||||
#else
|
||||
#else // !CONFIG_FREERTOS_UNICORE
|
||||
return true;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,8 +138,7 @@ static inline bool __attribute__((always_inline)) spinlock_acquire(spinlock_t *l
|
||||
*/
|
||||
static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *lock)
|
||||
{
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
#if !CONFIG_FREERTOS_UNICORE && !BOOTLOADER_BUILD
|
||||
uint32_t irq_status;
|
||||
uint32_t core_id;
|
||||
|
||||
@ -160,5 +162,3 @@ static inline void __attribute__((always_inline)) spinlock_release(spinlock_t *l
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
19
components/esp_pm/pm_impl_riscv_temp.c
Normal file
19
components/esp_pm/pm_impl_riscv_temp.c
Normal 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)
|
||||
{
|
||||
|
||||
}
|
@ -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
|
||||
|
@ -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))
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -1,9 +1,9 @@
|
||||
target_include_directories(${COMPONENT_LIB} PRIVATE include)
|
||||
|
||||
set(srcs "panic_handler.c" "panic_handler_asm.S" "cpu_start.c")
|
||||
set(srcs "cpu_start.c" "panic_handler.c")
|
||||
add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs})
|
||||
|
||||
target_sources(${COMPONENT_LIB} PRIVATE ${srcs})
|
||||
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
add_subdirectory(${target})
|
||||
add_subdirectory(soc/${target})
|
||||
|
127
components/esp_system/port/arch/riscv/panic_arch.c
Normal file
127
components/esp_system/port/arch/riscv/panic_arch.c
Normal 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 = ®s;
|
||||
}
|
||||
|
||||
void panic_print_backtrace(const void *frame, int core)
|
||||
{
|
||||
// Basic backtrace
|
||||
panic_print_str("\r\nStack memory:\n");
|
||||
uint32_t sp = (uint32_t)((RvExcFrame *)frame)->sp;
|
||||
const int per_line = 8;
|
||||
for (int x = 0; x < 1024; x += per_line * sizeof(uint32_t)) {
|
||||
uint32_t *spp = (uint32_t *)(sp + x);
|
||||
panic_print_hex(sp + x);
|
||||
panic_print_str(": ");
|
||||
for (int y = 0; y < per_line; y++) {
|
||||
panic_print_str("0x");
|
||||
panic_print_hex(spp[y]);
|
||||
panic_print_char(y == per_line - 1 ? '\n' : ' ');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t panic_get_address(const void *f)
|
||||
{
|
||||
return ((RvExcFrame *)f)->mepc;
|
||||
}
|
||||
|
||||
uint32_t panic_get_cause(const void *f)
|
||||
{
|
||||
return ((RvExcFrame *)f)->mcause;
|
||||
}
|
||||
|
||||
void panic_set_address(void *f, uint32_t addr)
|
||||
{
|
||||
((RvExcFrame *)f)->mepc = addr;
|
||||
}
|
497
components/esp_system/port/arch/xtensa/panic_arch.c
Normal file
497
components/esp_system/port/arch/xtensa/panic_arch.c
Normal 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");
|
||||
}
|
||||
}
|
@ -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));
|
||||
|
@ -1,2 +0,0 @@
|
||||
COMPONENT_SRCDIRS += port port/esp32
|
||||
COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o
|
@ -13,15 +13,9 @@
|
||||
// limitations under the License.
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "freertos/xtensa_context.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
|
||||
#include "esp_spi_flash.h"
|
||||
|
||||
#include "esp_private/panic_reason.h"
|
||||
#include "esp_private/system_internal.h"
|
||||
#include "esp_debug_helpers.h"
|
||||
|
||||
#include "soc/soc_memory_layout.h"
|
||||
#include "soc/cpu.h"
|
||||
@ -30,30 +24,26 @@
|
||||
|
||||
#include "hal/soc_hal.h"
|
||||
#include "hal/cpu_hal.h"
|
||||
#include "hal/wdt_types.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_sys.h"
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/cache_err_int.h"
|
||||
#include "esp32/dport_access.h"
|
||||
#include "esp32/cache_err_int.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/cache_err_int.h"
|
||||
#include "esp32s2/memprot.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "esp32s2/cache_err_int.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
#include "esp32s3/cache_err_int.h"
|
||||
#include "esp32s3/memprot.h"
|
||||
#include "soc/extmem_reg.h"
|
||||
#include "soc/cache_memory.h"
|
||||
#include "soc/rtc_cntl_reg.h"
|
||||
#include "esp32s3/cache_err_int.h"
|
||||
#endif
|
||||
|
||||
#include "esp_private/panic_internal.h"
|
||||
#include "esp_private/panic_reason.h"
|
||||
|
||||
#include "hal/wdt_types.h"
|
||||
#include "hal/wdt_hal.h"
|
||||
|
||||
extern int _invalid_pc_placeholder;
|
||||
|
||||
@ -61,7 +51,7 @@ extern void esp_panic_handler(panic_info_t*);
|
||||
|
||||
static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0};
|
||||
|
||||
static XtExcFrame *xt_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
|
||||
void *g_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
|
||||
|
||||
/*
|
||||
Panic handlers; these get called when an unhandled exception occurs or the assembly-level
|
||||
@ -72,193 +62,19 @@ static XtExcFrame *xt_exc_frames[SOC_CPU_CORES_NUM] = {NULL};
|
||||
/*
|
||||
Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled.
|
||||
*/
|
||||
static void print_illegal_instruction_details(const void *f)
|
||||
{
|
||||
XtExcFrame *frame = (XtExcFrame *) f;
|
||||
/* Print out memory around the instruction word */
|
||||
uint32_t epc = frame->pc;
|
||||
epc = (epc & ~0x3) - 4;
|
||||
|
||||
/* check that the address was sane */
|
||||
if (epc < SOC_IROM_MASK_LOW || epc >= SOC_IROM_HIGH) {
|
||||
return;
|
||||
}
|
||||
volatile uint32_t *pepc = (uint32_t *)epc;
|
||||
|
||||
panic_print_str("Memory dump at 0x");
|
||||
panic_print_hex(epc);
|
||||
panic_print_str(": ");
|
||||
|
||||
panic_print_hex(*pepc);
|
||||
panic_print_str(" ");
|
||||
panic_print_hex(*(pepc + 1));
|
||||
panic_print_str(" ");
|
||||
panic_print_hex(*(pepc + 2));
|
||||
}
|
||||
|
||||
static void print_debug_exception_details(const void *f)
|
||||
{
|
||||
int debug_rsn;
|
||||
asm("rsr.debugcause %0":"=r"(debug_rsn));
|
||||
panic_print_str("Debug exception reason: ");
|
||||
if (debug_rsn & XCHAL_DEBUGCAUSE_ICOUNT_MASK) {
|
||||
panic_print_str("SingleStep ");
|
||||
}
|
||||
if (debug_rsn & XCHAL_DEBUGCAUSE_IBREAK_MASK) {
|
||||
panic_print_str("HwBreakpoint ");
|
||||
}
|
||||
if (debug_rsn & XCHAL_DEBUGCAUSE_DBREAK_MASK) {
|
||||
//Unlike what the ISA manual says, this core seemingly distinguishes from a DBREAK
|
||||
//reason caused by watchdog 0 and one caused by watchdog 1 by setting bit 8 of the
|
||||
//debugcause if the cause is watchpoint 1 and clearing it if it's watchpoint 0.
|
||||
if (debug_rsn & (1 << 8)) {
|
||||
#if CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK
|
||||
int core = 0;
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
if (f == xt_exc_frames[1]) {
|
||||
core = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *name = pcTaskGetTaskName(xTaskGetCurrentTaskHandleForCPU(core));
|
||||
panic_print_str("Stack canary watchpoint triggered (");
|
||||
panic_print_str(name);
|
||||
panic_print_str(") ");
|
||||
#else
|
||||
panic_print_str("Watchpoint 1 triggered ");
|
||||
#endif
|
||||
} else {
|
||||
panic_print_str("Watchpoint 0 triggered ");
|
||||
}
|
||||
}
|
||||
if (debug_rsn & XCHAL_DEBUGCAUSE_BREAK_MASK) {
|
||||
panic_print_str("BREAK instr ");
|
||||
}
|
||||
if (debug_rsn & XCHAL_DEBUGCAUSE_BREAKN_MASK) {
|
||||
panic_print_str("BREAKN instr ");
|
||||
}
|
||||
if (debug_rsn & XCHAL_DEBUGCAUSE_DEBUGINT_MASK) {
|
||||
panic_print_str("DebugIntr ");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_backtrace_entry(uint32_t pc, uint32_t sp)
|
||||
{
|
||||
panic_print_str("0x");
|
||||
panic_print_hex(pc);
|
||||
panic_print_str(":0x");
|
||||
panic_print_hex(sp);
|
||||
}
|
||||
|
||||
static void print_backtrace(const void *f, int core)
|
||||
{
|
||||
XtExcFrame *frame = (XtExcFrame *) f;
|
||||
int depth = 100;
|
||||
//Initialize stk_frame with first frame of stack
|
||||
esp_backtrace_frame_t stk_frame = {.pc = frame->pc, .sp = frame->a1, .next_pc = frame->a0};
|
||||
panic_print_str("\r\nBacktrace:");
|
||||
print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
|
||||
|
||||
//Check if first frame is valid
|
||||
bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
|
||||
(esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
|
||||
/* Ignore the first corrupted PC in case of InstrFetchProhibited */
|
||||
frame->exccause == EXCCAUSE_INSTR_PROHIBITED));
|
||||
|
||||
uint32_t i = ((depth <= 0) ? INT32_MAX : depth) - 1; //Account for stack frame that's already printed
|
||||
while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
|
||||
if (!esp_backtrace_get_next_frame(&stk_frame)) { //Get next stack frame
|
||||
corrupted = true;
|
||||
}
|
||||
panic_print_str(" ");
|
||||
print_backtrace_entry(esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
|
||||
}
|
||||
|
||||
//Print backtrace termination marker
|
||||
if (corrupted) {
|
||||
panic_print_str(" |<-CORRUPTED");
|
||||
} else if (stk_frame.next_pc != 0) { //Backtrace continues
|
||||
panic_print_str(" |<-CONTINUES");
|
||||
}
|
||||
}
|
||||
|
||||
static void print_registers(const void *f, int core)
|
||||
{
|
||||
XtExcFrame *frame = (XtExcFrame *) f;
|
||||
int *regs = (int *)frame;
|
||||
int x, y;
|
||||
const char *sdesc[] = {
|
||||
"PC ", "PS ", "A0 ", "A1 ", "A2 ", "A3 ", "A4 ", "A5 ",
|
||||
"A6 ", "A7 ", "A8 ", "A9 ", "A10 ", "A11 ", "A12 ", "A13 ",
|
||||
"A14 ", "A15 ", "SAR ", "EXCCAUSE", "EXCVADDR", "LBEG ", "LEND ", "LCOUNT "
|
||||
};
|
||||
|
||||
/* only dump registers for 'real' crashes, if crashing via abort()
|
||||
the register window is no longer useful.
|
||||
*/
|
||||
panic_print_str("Core ");
|
||||
panic_print_dec(core);
|
||||
panic_print_str(" register dump:");
|
||||
|
||||
for (x = 0; x < 24; x += 4) {
|
||||
panic_print_str("\r\n");
|
||||
for (y = 0; y < 4; y++) {
|
||||
if (sdesc[x + y][0] != 0) {
|
||||
panic_print_str(sdesc[x + y]);
|
||||
panic_print_str(": 0x");
|
||||
panic_print_hex(regs[x + y + 1]);
|
||||
panic_print_str(" ");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If the core which triggers the interrupt watchpoint was in ISR context, dump the epc registers.
|
||||
if (xPortInterruptedFromISRContext()
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
&& ((core == 0 && frame->exccause == PANIC_RSN_INTWDT_CPU0) ||
|
||||
(core == 1 && frame->exccause == PANIC_RSN_INTWDT_CPU1))
|
||||
#endif //!CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
) {
|
||||
|
||||
panic_print_str("\r\n");
|
||||
|
||||
uint32_t __value;
|
||||
panic_print_str("Core ");
|
||||
panic_print_dec(core);
|
||||
panic_print_str(" was running in ISR context:\r\n");
|
||||
|
||||
__asm__("rsr.epc1 %0" : "=a"(__value));
|
||||
panic_print_str("EPC1 : 0x");
|
||||
panic_print_hex(__value);
|
||||
|
||||
__asm__("rsr.epc2 %0" : "=a"(__value));
|
||||
panic_print_str(" EPC2 : 0x");
|
||||
panic_print_hex(__value);
|
||||
|
||||
__asm__("rsr.epc3 %0" : "=a"(__value));
|
||||
panic_print_str(" EPC3 : 0x");
|
||||
panic_print_hex(__value);
|
||||
|
||||
__asm__("rsr.epc4 %0" : "=a"(__value));
|
||||
panic_print_str(" EPC4 : 0x");
|
||||
panic_print_hex(__value);
|
||||
}
|
||||
}
|
||||
|
||||
static void print_state_for_core(const void *f, int core)
|
||||
{
|
||||
if (!g_panic_abort) {
|
||||
print_registers(f, core);
|
||||
panic_print_registers(f, core);
|
||||
panic_print_str("\r\n");
|
||||
}
|
||||
print_backtrace(f, core);
|
||||
panic_print_backtrace(f, core);
|
||||
}
|
||||
|
||||
static void print_state(const void *f)
|
||||
{
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
int err_core = f == xt_exc_frames[0] ? 0 : 1;
|
||||
int err_core = f == g_exc_frames[0] ? 0 : 1;
|
||||
#else
|
||||
int err_core = 0;
|
||||
#endif
|
||||
@ -271,282 +87,33 @@ static void print_state(const void *f)
|
||||
// If there are other frame info, print them as well
|
||||
for (int i = 0; i < SOC_CPU_CORES_NUM; i++) {
|
||||
// `f` is the frame for the offending core, see note above.
|
||||
if (err_core != i && xt_exc_frames[i] != NULL) {
|
||||
print_state_for_core(xt_exc_frames[i], i);
|
||||
if (err_core != i && g_exc_frames[i] != NULL) {
|
||||
print_state_for_core(g_exc_frames[i], i);
|
||||
panic_print_str("\r\n");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
static inline void print_cache_err_details(const void *f)
|
||||
{
|
||||
uint32_t vaddr = 0, size = 0;
|
||||
uint32_t status[2];
|
||||
status[0] = REG_READ(EXTMEM_CACHE_DBG_STATUS0_REG);
|
||||
status[1] = REG_READ(EXTMEM_CACHE_DBG_STATUS1_REG);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
switch (status[0] & BIT(i)) {
|
||||
case EXTMEM_IC_SYNC_SIZE_FAULT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC0_REG);
|
||||
size = REG_READ(EXTMEM_PRO_ICACHE_MEM_SYNC1_REG);
|
||||
panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_IC_PRELOAD_SIZE_FAULT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_ADDR_REG);
|
||||
size = REG_READ(EXTMEM_PRO_ICACHE_PRELOAD_SIZE_REG);
|
||||
panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_ICACHE_REJECT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_ICACHE_REJECT_VADDR_REG);
|
||||
panic_print_str("Icache reject error occurred while accessing the address 0x");
|
||||
panic_print_hex(vaddr);
|
||||
|
||||
if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
|
||||
panic_print_str(" (invalid mmu entry)");
|
||||
}
|
||||
panic_print_str("\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
switch (status[1] & BIT(i)) {
|
||||
case EXTMEM_DC_SYNC_SIZE_FAULT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC0_REG);
|
||||
size = REG_READ(EXTMEM_PRO_DCACHE_MEM_SYNC1_REG);
|
||||
panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_DC_PRELOAD_SIZE_FAULT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_ADDR_REG);
|
||||
size = REG_READ(EXTMEM_PRO_DCACHE_PRELOAD_SIZE_REG);
|
||||
panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_DCACHE_WRITE_FLASH_ST:
|
||||
panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
|
||||
break;
|
||||
case EXTMEM_DCACHE_REJECT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_DCACHE_REJECT_VADDR_REG);
|
||||
panic_print_str("Dcache reject error occurred while accessing the address 0x");
|
||||
panic_print_hex(vaddr);
|
||||
|
||||
if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
|
||||
panic_print_str(" (invalid mmu entry)");
|
||||
}
|
||||
panic_print_str("\r\n");
|
||||
break;
|
||||
case EXTMEM_MMU_ENTRY_FAULT_ST:
|
||||
vaddr = REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_VADDR_REG);
|
||||
panic_print_str("MMU entry fault error occurred while accessing the address 0x");
|
||||
panic_print_hex(vaddr);
|
||||
|
||||
if (REG_READ(EXTMEM_PRO_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
|
||||
panic_print_str(" (invalid mmu entry)");
|
||||
}
|
||||
panic_print_str("\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void print_memprot_err_details(const void *f)
|
||||
{
|
||||
uint32_t *fault_addr;
|
||||
uint32_t op_type, op_subtype;
|
||||
mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();
|
||||
esp_memprot_get_fault_status( mem_type, &fault_addr, &op_type, &op_subtype );
|
||||
|
||||
char *operation_type = "Write";
|
||||
if ( op_type == 0 ) {
|
||||
operation_type = (mem_type == MEMPROT_IRAM0_SRAM && op_subtype == 0) ? "Instruction fetch" : "Read";
|
||||
}
|
||||
|
||||
panic_print_str( operation_type );
|
||||
panic_print_str( " operation at address 0x" );
|
||||
panic_print_hex( (uint32_t)fault_addr );
|
||||
panic_print_str(" not permitted.\r\n");
|
||||
}
|
||||
|
||||
#elif CONFIG_IDF_TARGET_ESP32S3
|
||||
static inline void print_cache_err_details(const void* f)
|
||||
{
|
||||
uint32_t vaddr = 0, size = 0;
|
||||
uint32_t status;
|
||||
status = REG_READ(EXTMEM_CACHE_ILG_INT_ST_REG);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
switch (status & BIT(i)) {
|
||||
case EXTMEM_ICACHE_SYNC_OP_FAULT_ST:
|
||||
//TODO, which size should fetch
|
||||
//vaddr = REG_READ(EXTMEM_ICACHE_MEM_SYNC0_REG);
|
||||
//size = REG_READ(EXTMEM_ICACHE_MEM_SYNC1_REG);
|
||||
panic_print_str("Icache sync parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_ICACHE_PRELOAD_OP_FAULT_ST:
|
||||
//TODO, which size should fetch
|
||||
vaddr = REG_READ(EXTMEM_ICACHE_PRELOAD_ADDR_REG);
|
||||
size = REG_READ(EXTMEM_ICACHE_PRELOAD_SIZE_REG);
|
||||
panic_print_str("Icache preload parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_DCACHE_SYNC_OP_FAULT_ST:
|
||||
//TODO, which size should fetch
|
||||
//vaddr = REG_READ(EXTMEM_DCACHE_MEM_SYNC0_REG);
|
||||
//size = REG_READ(EXTMEM_DCACHE_MEM_SYNC1_REG);
|
||||
panic_print_str("Dcache sync parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_DCACHE_PRELOAD_OP_FAULT_ST:
|
||||
//TODO, which size should fetch
|
||||
vaddr = REG_READ(EXTMEM_DCACHE_PRELOAD_ADDR_REG);
|
||||
size = REG_READ(EXTMEM_DCACHE_PRELOAD_SIZE_REG);
|
||||
panic_print_str("Dcache preload parameter configuration error, the error address and size is 0x");
|
||||
panic_print_hex(vaddr);
|
||||
panic_print_str("(0x");
|
||||
panic_print_hex(size);
|
||||
panic_print_str(")\r\n");
|
||||
break;
|
||||
case EXTMEM_DCACHE_WRITE_FLASH_ST:
|
||||
panic_print_str("Write back error occurred while dcache tries to write back to flash\r\n");
|
||||
break;
|
||||
case EXTMEM_MMU_ENTRY_FAULT_ST:
|
||||
vaddr = REG_READ(EXTMEM_CACHE_MMU_FAULT_VADDR_REG);
|
||||
panic_print_str("MMU entry fault error occurred while accessing the address 0x");
|
||||
panic_print_hex(vaddr);
|
||||
|
||||
if (REG_READ(EXTMEM_CACHE_MMU_FAULT_CONTENT_REG) & MMU_INVALID) {
|
||||
panic_print_str(" (invalid mmu entry)");
|
||||
}
|
||||
panic_print_str("\r\n");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
panic_print_str("\r\n");
|
||||
}
|
||||
|
||||
static inline void print_memprot_err_details(const void *f)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
static void frame_to_panic_info(XtExcFrame *frame, panic_info_t *info, bool pseudo_excause)
|
||||
static void frame_to_panic_info(void *frame, panic_info_t *info, bool pseudo_excause)
|
||||
{
|
||||
info->core = cpu_hal_get_core_id();
|
||||
info->exception = PANIC_EXCEPTION_FAULT;
|
||||
info->details = NULL;
|
||||
|
||||
info->reason = "Unknown";
|
||||
info->pseudo_excause = pseudo_excause;
|
||||
|
||||
if (pseudo_excause) {
|
||||
if (frame->exccause == PANIC_RSN_INTWDT_CPU0) {
|
||||
info->core = 0;
|
||||
info->exception = PANIC_EXCEPTION_IWDT;
|
||||
} else if (frame->exccause == PANIC_RSN_INTWDT_CPU1) {
|
||||
info->core = 1;
|
||||
info->exception = PANIC_EXCEPTION_IWDT;
|
||||
} else if (frame->exccause == PANIC_RSN_CACHEERR) {
|
||||
info->core = esp_cache_err_get_cpuid();
|
||||
} else {}
|
||||
|
||||
//Please keep in sync with PANIC_RSN_* defines
|
||||
static const char *pseudo_reason[] = {
|
||||
"Unknown reason",
|
||||
"Unhandled debug exception",
|
||||
"Double exception",
|
||||
"Unhandled kernel exception",
|
||||
"Coprocessor exception",
|
||||
"Interrupt wdt timeout on CPU0",
|
||||
"Interrupt wdt timeout on CPU1",
|
||||
#if CONFIG_IDF_TARGET_ESP32
|
||||
"Cache disabled but cached memory region accessed",
|
||||
#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
"Cache exception",
|
||||
#endif
|
||||
};
|
||||
|
||||
info->reason = pseudo_reason[0];
|
||||
info->description = NULL;
|
||||
|
||||
if (frame->exccause <= PANIC_RSN_MAX) {
|
||||
info->reason = pseudo_reason[frame->exccause];
|
||||
}
|
||||
|
||||
if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) {
|
||||
info->details = print_debug_exception_details;
|
||||
info->exception = PANIC_EXCEPTION_DEBUG;
|
||||
}
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
|
||||
if (frame->exccause == PANIC_RSN_CACHEERR) {
|
||||
if ( esp_memprot_get_active_intr_memtype() != MEMPROT_NONE ) {
|
||||
info->details = print_memprot_err_details;
|
||||
info->reason = "Memory protection fault";
|
||||
} else {
|
||||
info->details = print_cache_err_details;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
panic_soc_fill_info(frame, info);
|
||||
} else {
|
||||
static const char *reason[] = {
|
||||
"IllegalInstruction", "Syscall", "InstructionFetchError", "LoadStoreError",
|
||||
"Level1Interrupt", "Alloca", "IntegerDivideByZero", "PCValue",
|
||||
"Privileged", "LoadStoreAlignment", "res", "res",
|
||||
"InstrPDAddrError", "LoadStorePIFDataError", "InstrPIFAddrError", "LoadStorePIFAddrError",
|
||||
"InstTLBMiss", "InstTLBMultiHit", "InstFetchPrivilege", "res",
|
||||
"InstrFetchProhibited", "res", "res", "res",
|
||||
"LoadStoreTLBMiss", "LoadStoreTLBMultihit", "LoadStorePrivilege", "res",
|
||||
"LoadProhibited", "StoreProhibited", "res", "res",
|
||||
"Cp0Dis", "Cp1Dis", "Cp2Dis", "Cp3Dis",
|
||||
"Cp4Dis", "Cp5Dis", "Cp6Dis", "Cp7Dis"
|
||||
};
|
||||
|
||||
if (frame->exccause < (sizeof(reason) / sizeof(char *))) {
|
||||
info->reason = (reason[frame->exccause]);
|
||||
} else {
|
||||
info->reason = "Unknown";
|
||||
}
|
||||
|
||||
info->description = "Exception was unhandled.";
|
||||
|
||||
if (frame->exccause == EXCCAUSE_ILLEGAL) {
|
||||
info->details = print_illegal_instruction_details;
|
||||
}
|
||||
panic_arch_fill_info(frame, info);
|
||||
}
|
||||
|
||||
info->state = print_state;
|
||||
info->addr = ((void *) ((XtExcFrame *) frame)->pc);
|
||||
info->frame = frame;
|
||||
}
|
||||
|
||||
static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
|
||||
static void panic_handler(void *frame, bool pseudo_excause)
|
||||
{
|
||||
/*
|
||||
* Setup environment and perform necessary architecture/chip specific
|
||||
@ -555,7 +122,7 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
|
||||
int core_id = cpu_hal_get_core_id();
|
||||
|
||||
// If multiple cores arrive at panic handler, save frames for all of them
|
||||
xt_exc_frames[core_id] = frame;
|
||||
g_exc_frames[core_id] = frame;
|
||||
|
||||
#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE
|
||||
// These are cases where both CPUs both go into panic handler. The following code ensures
|
||||
@ -563,13 +130,13 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
|
||||
if (pseudo_excause) {
|
||||
#define BUSY_WAIT_IF_TRUE(b) { if (b) while(1); }
|
||||
// For WDT expiry, pause the non-offending core - offending core handles panic
|
||||
BUSY_WAIT_IF_TRUE(frame->exccause == PANIC_RSN_INTWDT_CPU0 && core_id == 1);
|
||||
BUSY_WAIT_IF_TRUE(frame->exccause == PANIC_RSN_INTWDT_CPU1 && core_id == 0);
|
||||
BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 && core_id == 1);
|
||||
BUSY_WAIT_IF_TRUE(panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1 && core_id == 0);
|
||||
|
||||
// For cache error, pause the non-offending core - offending core handles panic
|
||||
if (frame->exccause == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
|
||||
if (panic_get_cause(frame) == PANIC_RSN_CACHEERR && core_id != esp_cache_err_get_cpuid()) {
|
||||
// Only print the backtrace for the offending core in case of the cache error
|
||||
xt_exc_frames[core_id] = NULL;
|
||||
g_exc_frames[core_id] = NULL;
|
||||
while (1) {
|
||||
;
|
||||
}
|
||||
@ -593,15 +160,17 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
|
||||
#endif
|
||||
|
||||
if (esp_cpu_in_ocd_debug_mode()) {
|
||||
if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(frame->pc)) && (frame->pc & 0xC0000000U))) {
|
||||
#if __XTENSA__
|
||||
if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(panic_get_address(frame))) && (panic_get_address(frame) & 0xC0000000U))) {
|
||||
/* Xtensa ABI sets the 2 MSBs of the PC according to the windowed call size
|
||||
* Incase the PC is invalid, GDB will fail to translate addresses to function names
|
||||
* Hence replacing the PC to a placeholder address in case of invalid PC
|
||||
*/
|
||||
frame->pc = (uint32_t)&_invalid_pc_placeholder;
|
||||
panic_set_address(frame, (uint32_t)&_invalid_pc_placeholder);
|
||||
}
|
||||
if (frame->exccause == PANIC_RSN_INTWDT_CPU0 ||
|
||||
frame->exccause == PANIC_RSN_INTWDT_CPU1) {
|
||||
#endif
|
||||
if (panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU0 ||
|
||||
panic_get_cause(frame) == PANIC_RSN_INTWDT_CPU1) {
|
||||
wdt_hal_write_protect_disable(&wdt0_context);
|
||||
wdt_hal_handle_intr(&wdt0_context);
|
||||
wdt_hal_write_protect_enable(&wdt0_context);
|
||||
@ -616,7 +185,7 @@ static void panic_handler(XtExcFrame *frame, bool pseudo_excause)
|
||||
esp_panic_handler(&info);
|
||||
}
|
||||
|
||||
void panicHandler(XtExcFrame *frame)
|
||||
void panicHandler(void *frame)
|
||||
{
|
||||
// This panic handler gets called for when the double exception vector,
|
||||
// kernel exception vector gets used; as well as handling interrupt-based
|
||||
@ -625,7 +194,7 @@ void panicHandler(XtExcFrame *frame)
|
||||
panic_handler(frame, true);
|
||||
}
|
||||
|
||||
void xt_unhandled_exception(XtExcFrame *frame)
|
||||
void xt_unhandled_exception(void *frame)
|
||||
{
|
||||
panic_handler(frame, false);
|
||||
}
|
||||
|
@ -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})
|
@ -177,7 +177,8 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
wdt_hal_write_protect_enable(&rtc_wdt_ctx);
|
||||
#endif
|
||||
|
||||
rtc_cpu_freq_config_t old_config, new_config;
|
||||
rtc_cpu_freq_config_t old_config;
|
||||
rtc_cpu_freq_config_t new_config;
|
||||
rtc_clk_cpu_freq_get_config(&old_config);
|
||||
const uint32_t old_freq_mhz = old_config.freq_mhz;
|
||||
const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ;
|
||||
@ -205,7 +206,9 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk)
|
||||
*/
|
||||
__attribute__((weak)) void esp_perip_clk_init(void)
|
||||
{
|
||||
uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0;
|
||||
uint32_t common_perip_clk;
|
||||
uint32_t hwcrypto_perip_clk;
|
||||
uint32_t wifi_bt_sdio_clk;
|
||||
|
||||
#if CONFIG_FREERTOS_UNICORE
|
||||
RESET_REASON rst_reas[1];
|
2
components/esp_system/port/soc/esp32/component.mk
Normal file
2
components/esp_system/port/soc/esp32/component.mk
Normal file
@ -0,0 +1,2 @@
|
||||
COMPONENT_SRCDIRS += port port/soc/esp32 port/arch/xtensa
|
||||
COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o
|
@ -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})
|
@ -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})
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -16,7 +16,6 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include "esp_err.h"
|
||||
#include "freertos/xtensa_context.h"
|
||||
#include "esp_private/panic_internal.h"
|
||||
|
||||
/**************************************************************************************/
|
||||
|
@ -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";
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -112,6 +112,6 @@ entries:
|
||||
queue: xQueueAddToSet (default)
|
||||
queue: xQueueRemoveFromSet (default)
|
||||
queue: xQueueSelectFromSet (default)
|
||||
port:main_task (default)
|
||||
port_common:main_task (default)
|
||||
port:esp_startup_start_app (default)
|
||||
port:esp_startup_start_app_other_cores (default)
|
||||
|
135
components/freertos/port/port_common.c
Normal file
135
components/freertos/port/port_common.c
Normal 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);
|
||||
}
|
277
components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h
Normal file
277
components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h
Normal 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 */
|
310
components/freertos/port/riscv/include/freertos/portmacro.h
Normal file
310
components/freertos/port/riscv/include/freertos/portmacro.h
Normal 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 */
|
369
components/freertos/port/riscv/port.c
Normal file
369
components/freertos/port/riscv/port.c
Normal 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();
|
||||
}
|
87
components/freertos/port/riscv/portasm.S
Normal file
87
components/freertos/port/riscv/portasm.S
Normal 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
|
@ -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 */
|
@ -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.
|
@ -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();
|
||||
}
|
@ -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"
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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]")
|
||||
|
@ -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;
|
||||
|
@ -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); \
|
||||
|
@ -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"
|
||||
|
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user