From fccab8f4efc48791ff6fa1d982036b9b238a1c09 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 6 Nov 2020 15:03:03 +1100 Subject: [PATCH 1/5] riscv: Add new arch-level component Changes come from internal branch commit a6723fc --- components/mqtt/esp-mqtt | 2 +- components/riscv/CMakeLists.txt | 18 + components/riscv/include/esp_attr.h | 131 ++++++++ components/riscv/include/esp_debug_helpers.h | 133 ++++++++ components/riscv/include/riscv/csr.h | 135 ++++++++ components/riscv/include/riscv/encoding.h | 227 +++++++++++++ components/riscv/include/riscv/interrupt.h | 115 +++++++ .../riscv/include/riscv/riscv_interrupts.h | 45 +++ .../riscv/include/riscv/rvruntime-frames.h | 95 ++++++ components/riscv/interrupt.c | 111 +++++++ components/riscv/linker.lf | 5 + components/riscv/stdatomic.c | 129 ++++++++ components/riscv/vectors.S | 307 ++++++++++++++++++ 13 files changed, 1452 insertions(+), 1 deletion(-) create mode 100644 components/riscv/CMakeLists.txt create mode 100644 components/riscv/include/esp_attr.h create mode 100644 components/riscv/include/esp_debug_helpers.h create mode 100644 components/riscv/include/riscv/csr.h create mode 100644 components/riscv/include/riscv/encoding.h create mode 100644 components/riscv/include/riscv/interrupt.h create mode 100644 components/riscv/include/riscv/riscv_interrupts.h create mode 100644 components/riscv/include/riscv/rvruntime-frames.h create mode 100644 components/riscv/interrupt.c create mode 100644 components/riscv/linker.lf create mode 100644 components/riscv/stdatomic.c create mode 100644 components/riscv/vectors.S diff --git a/components/mqtt/esp-mqtt b/components/mqtt/esp-mqtt index 01594bf118..b9db8d9020 160000 --- a/components/mqtt/esp-mqtt +++ b/components/mqtt/esp-mqtt @@ -1 +1 @@ -Subproject commit 01594bf118ae502b5a0ead040446f2be75d26223 +Subproject commit b9db8d90204c7f9a23165630fd74ad621516c0c7 diff --git a/components/riscv/CMakeLists.txt b/components/riscv/CMakeLists.txt new file mode 100644 index 0000000000..6d3744d6a7 --- /dev/null +++ b/components/riscv/CMakeLists.txt @@ -0,0 +1,18 @@ +idf_build_get_property(target IDF_TARGET) +if(NOT "${target}" STREQUAL "esp32c3") + return() +endif() +if(BOOTLOADER_BUILD) + set(priv_requires soc) +else() + set(priv_requires soc freertos) + set(srcs + "interrupt.c" + "stdatomic.c" + "vectors.S") +endif() + +idf_component_register(SRCS "${srcs}" + LDFRAGMENTS linker.lf + INCLUDE_DIRS "include" + PRIV_REQUIRES ${priv_requires}) diff --git a/components/riscv/include/esp_attr.h b/components/riscv/include/esp_attr.h new file mode 100644 index 0000000000..38a8fbe4ee --- /dev/null +++ b/components/riscv/include/esp_attr.h @@ -0,0 +1,131 @@ +// 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. +#ifndef __ESP_ATTR_H__ +#define __ESP_ATTR_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "sdkconfig.h" + +#define ROMFN_ATTR + +//Normally, the linker script will put all code and rodata in flash, +//and all variables in shared RAM. These macros can be used to redirect +//particular functions/variables to other memory regions. + +// Forces code into IRAM instead of flash +#define IRAM_ATTR _SECTION_ATTR_IMPL(".iram1", __COUNTER__) + +// Forces data into DRAM instead of flash +#define DRAM_ATTR _SECTION_ATTR_IMPL(".dram1", __COUNTER__) + +// Forces data to be 4 bytes aligned +#define WORD_ALIGNED_ATTR __attribute__((aligned(4))) + +// Forces data to be placed to DMA-capable places +#define DMA_ATTR WORD_ALIGNED_ATTR DRAM_ATTR + +// Forces a function to be inlined +#define FORCE_INLINE_ATTR static inline __attribute__((always_inline)) + +// Forces a string into DRAM instead of flash +// Use as ets_printf(DRAM_STR("Hello world!\n")); +#define DRAM_STR(str) (__extension__({static const DRAM_ATTR char __c[] = (str); (const char *)&__c;})) + +// Forces code into RTC fast memory. See "docs/deep-sleep-stub.rst" +#define RTC_IRAM_ATTR _SECTION_ATTR_IMPL(".rtc.text", __COUNTER__) + +#if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY +// Forces bss variable into external memory. " +#define EXT_RAM_ATTR _SECTION_ATTR_IMPL(".ext_ram.bss", __COUNTER__) +#else +#define EXT_RAM_ATTR +#endif + +// Forces data into RTC slow memory. See "docs/deep-sleep-stub.rst" +// Any variable marked with this attribute will keep its value +// during a deep sleep / wake cycle. +#define RTC_DATA_ATTR _SECTION_ATTR_IMPL(".rtc.data", __COUNTER__) + +// Forces read-only data into RTC memory. See "docs/deep-sleep-stub.rst" +#define RTC_RODATA_ATTR _SECTION_ATTR_IMPL(".rtc.rodata", __COUNTER__) + +// Allows to place data into RTC_SLOW memory. +#define RTC_SLOW_ATTR _SECTION_ATTR_IMPL(".rtc.force_slow", __COUNTER__) + +// Allows to place data into RTC_FAST memory. +#define RTC_FAST_ATTR _SECTION_ATTR_IMPL(".rtc.force_fast", __COUNTER__) + +// Forces data into noinit section to avoid initialization after restart. +#define __NOINIT_ATTR _SECTION_ATTR_IMPL(".noinit", __COUNTER__) + +// Forces data into RTC slow memory of .noinit section. +// Any variable marked with this attribute will keep its value +// after restart or during a deep sleep / wake cycle. +#define RTC_NOINIT_ATTR _SECTION_ATTR_IMPL(".rtc_noinit", __COUNTER__) + +// Forces to not inline function +#define NOINLINE_ATTR __attribute__((noinline)) + +// This allows using enum as flags in C++ +// Format: FLAG_ATTR(flag_enum_t) +#ifdef __cplusplus + +// Inline is required here to avoid multiple definition error in linker +#define FLAG_ATTR_IMPL(TYPE, INT_TYPE) \ +FORCE_INLINE_ATTR constexpr TYPE operator~ (TYPE a) { return (TYPE)~(INT_TYPE)a; } \ +FORCE_INLINE_ATTR constexpr TYPE operator| (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a | (INT_TYPE)b); } \ +FORCE_INLINE_ATTR constexpr TYPE operator& (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a & (INT_TYPE)b); } \ +FORCE_INLINE_ATTR constexpr TYPE operator^ (TYPE a, TYPE b) { return (TYPE)((INT_TYPE)a ^ (INT_TYPE)b); } \ +FORCE_INLINE_ATTR constexpr TYPE operator>> (TYPE a, int b) { return (TYPE)((INT_TYPE)a >> b); } \ +FORCE_INLINE_ATTR constexpr TYPE operator<< (TYPE a, int b) { return (TYPE)((INT_TYPE)a << b); } \ +FORCE_INLINE_ATTR TYPE& operator|=(TYPE& a, TYPE b) { a = a | b; return a; } \ +FORCE_INLINE_ATTR TYPE& operator&=(TYPE& a, TYPE b) { a = a & b; return a; } \ +FORCE_INLINE_ATTR TYPE& operator^=(TYPE& a, TYPE b) { a = a ^ b; return a; } \ +FORCE_INLINE_ATTR TYPE& operator>>=(TYPE& a, int b) { a >>= b; return a; } \ +FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a <<= b; return a; } + +#define FLAG_ATTR_U32(TYPE) FLAG_ATTR_IMPL(TYPE, uint32_t) +#define FLAG_ATTR FLAG_ATTR_U32 + +#else +#define FLAG_ATTR(TYPE) +#endif + +// Implementation for a unique custom section +// +// This prevents gcc producing "x causes a section type conflict with y" +// errors if two variables in the same source file have different linkage (maybe const & non-const) but are placed in the same custom section +// +// Using unique sections also means --gc-sections can remove unused +// data with a custom section type set +#define _SECTION_ATTR_IMPL(SECTION, COUNTER) __attribute__((section(SECTION "." _COUNTER_STRINGIFY(COUNTER)))) + +#define _COUNTER_STRINGIFY(COUNTER) #COUNTER + +/* Use IDF_DEPRECATED attribute to mark anything deprecated from use in + ESP-IDF's own source code, but not deprecated for external users. +*/ +#ifdef IDF_CI_BUILD +#define IDF_DEPRECATED(REASON) __attribute__((deprecated(REASON))) +#else +#define IDF_DEPRECATED(REASON) +#endif + +#ifdef __cplusplus +} +#endif +#endif /* __ESP_ATTR_H__ */ diff --git a/components/riscv/include/esp_debug_helpers.h b/components/riscv/include/esp_debug_helpers.h new file mode 100644 index 0000000000..d088ddeef1 --- /dev/null +++ b/components/riscv/include/esp_debug_helpers.h @@ -0,0 +1,133 @@ +// Copyright 2015-2019 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __ASSEMBLER__ + +#include +#include "esp_err.h" +#include "soc/soc.h" + +#define ESP_WATCHPOINT_LOAD 0x40000000 +#define ESP_WATCHPOINT_STORE 0x80000000 +#define ESP_WATCHPOINT_ACCESS 0xC0000000 + +/* + * @brief Structure used for backtracing + * + * This structure stores the backtrace information of a particular stack frame + * (i.e. the PC and SP). This structure is used iteratively with the + * esp_cpu_get_next_backtrace_frame() function to traverse each frame within a + * single stack. The next_pc represents the PC of the current frame's caller, thus + * a next_pc of 0 indicates that the current frame is the last frame on the stack. + * + * @note Call esp_backtrace_get_start() to obtain initialization values for + * this structure + */ +typedef struct { + uint32_t pc; /* PC of the current frame */ + uint32_t sp; /* SP of the current frame */ + uint32_t next_pc; /* PC of the current frame's caller */ +} esp_backtrace_frame_t; + +/** + * @brief If an OCD is connected over JTAG. set breakpoint 0 to the given function + * address. Do nothing otherwise. + * @param fn Pointer to the target breakpoint position + */ +void esp_set_breakpoint_if_jtag(void *fn); + +/** + * @brief Set a watchpoint to break/panic when a certain memory range is accessed. + * + * @param no Watchpoint number. On the ESP32, this can be 0 or 1. + * @param adr Base address to watch + * @param size Size of the region, starting at the base address, to watch. Must + * be one of 2^n, with n in [0..6]. + * @param flags One of ESP_WATCHPOINT_* flags + * + * @return ESP_ERR_INVALID_ARG on invalid arg, ESP_OK otherwise + * + * @warning The ESP32 watchpoint hardware watches a region of bytes by effectively + * masking away the lower n bits for a region with size 2^n. If adr does + * not have zero for these lower n bits, you may not be watching the + * region you intended. + */ +esp_err_t esp_set_watchpoint(int no, void *adr, int size, int flags); + +/** + * @brief Clear a watchpoint + * + * @param no Watchpoint to clear + * + */ +void esp_clear_watchpoint(int no); + +/** + * Get the first frame of the current stack's backtrace + * + * Given the following function call flow (B -> A -> X -> esp_backtrace_get_start), + * this function will do the following. + * - Flush CPU registers and window frames onto the current stack + * - Return PC and SP of function A (i.e. start of the stack's backtrace) + * - Return PC of function B (i.e. next_pc) + * + * @note This function is implemented in assembly + * + * @param[out] pc PC of the first frame in the backtrace + * @param[out] sp SP of the first frame in the backtrace + * @param[out] next_pc PC of the first frame's caller + */ +extern void esp_backtrace_get_start(uint32_t *pc, uint32_t *sp, uint32_t *next_pc); + +/** + * Get the next frame on a stack for backtracing + * + * Given a stack frame(i), this function will obtain the next stack frame(i-1) + * on the same call stack (i.e. the caller of frame(i)). This function is meant to be + * called iteratively when doing a backtrace. + * + * Entry Conditions: Frame structure containing valid SP and next_pc + * Exit Conditions: + * - Frame structure updated with SP and PC of frame(i-1). next_pc now points to frame(i-2). + * - If a next_pc of 0 is returned, it indicates that frame(i-1) is last frame on the stack + * + * @param[inout] frame Pointer to frame structure + * + * @return + * - True if the SP and PC of the next frame(i-1) are sane + * - False otherwise + */ +bool esp_backtrace_get_next_frame(esp_backtrace_frame_t *frame); + +/** + * @brief Print the backtrace of the current stack + * + * @param depth The maximum number of stack frames to print (should be > 0) + * + * @return + * - ESP_OK Backtrace successfully printed to completion or to depth limit + * - ESP_FAIL Backtrace is corrupted + */ +esp_err_t esp_backtrace_print(int depth); + +#endif +#ifdef __cplusplus +} +#endif diff --git a/components/riscv/include/riscv/csr.h b/components/riscv/include/riscv/csr.h new file mode 100644 index 0000000000..030eb53a93 --- /dev/null +++ b/components/riscv/include/riscv/csr.h @@ -0,0 +1,135 @@ +// Copyright (c) 2013, The Regents of the University of California (Regents). +// Copyright (c) 2018-2019, The libfemto authors +// Copyright (c) 2020 Espressif Systems (Shanghai) PTE LTD +// All Rights Reserved. + +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// 1. Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// 3. Neither the name of the Regents nor the +// names of its contributors may be used to endorse or promote products +// derived from this software without specific prior written permission. + +// IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, +// SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING +// OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS +// BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, +// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +// PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED +// HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE +// MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include +#include +#include +#include +#include "encoding.h" + +/******************************************************** + Physical Memory Protection (PMP) register fields + (privileged spec) + ********************************************************/ + +/* Value of pmpcfg0 CSR. Note this macro is only needed for calculations like (CSR_PMPCFG0 + 1), which must + still be constant at compile time. Use the assembler name pmpcfg0, pmpcfg1, pmpcfg2, etc. in other cases */ +#define CSR_PMPCFG0 0x3A0 + +/* Value of pmpaddr0 CSR. Note, as above, this macro is only needed for calculations and the assembler names + pmpaddr0, pmpaddr1, pmpaddr2, etc should be used otherwise. */ +#define CSR_PMPADDR0 0x3B0 + +/* Generate the PMP address field value when PMPCFG.A == NAPOT + + START & END should be calculated at compile time. The size of the region + (END-START) must be a power of 2 size, and START must be aligned to this + size. + + Note: this value must be right-shifted PMP_SHIFT when written to the PMPADDR + register. The PMP_ENTRY_SET macro will do this. + */ +#define PMPADDR_NAPOT(START, END) ({ \ + _Static_assert(__builtin_popcount((END)-(START)) == 1, "Size must be a power of 2"); \ + _Static_assert((START) % ((END)-(START)) == 0, "Start must be aligned to size"); \ + (((START)) | (((END)-(START)-1)>>1)); \ + }) + +#define PMPADDR_ALL 0xFFFFFFFF + + +/* Set a PMP entry. + + - ENTRY is number of the PMP entry to set. This must be a compile-time constant because it's used to + generate specific assembly instructions. + - ADDR is the address to write to the PMPADDRx register. Note this is the unshifted address. + - CFG is the configuration value to write to the correct CFG entry register. Note that + the macro only sets bits in the CFG register, so it sould be zeroed already. +*/ +#define PMP_ENTRY_SET(ENTRY, ADDR, CFG) do { \ + RV_WRITE_CSR((CSR_PMPADDR0) + (ENTRY), (ADDR) >> (PMP_SHIFT)); \ + RV_SET_CSR((CSR_PMPCFG0) + (ENTRY)/4, ((CFG)&0xFF) << (ENTRY%4)*8); \ + } while(0) + +/******************************************************** + Trigger Module register fields (Debug specification) + ********************************************************/ + +/* tcontrol CSRs not recognized by toolchain currently */ +#define CSR_TCONTROL 0x7a5 +#define CSR_TDATA1 0x7a1 + +#define TCONTROL_MTE (1<<3) /*R/W, Current M mode trigger enable bit*/ + +#define TDATA1_LOAD (1<<0) /*R/W,Fire trigger on load address match*/ +#define TDATA1_STORE (1<<1) /*R/W,Fire trigger on store address mat*/ +#define TDATA1_EXECUTE (1<<2) /*R/W,Fire trigger on instruction fetch address match*/ +#define TDATA1_USER (1<<3) /*R/W,allow trigger to be fired in user mode*/ +#define TDATA1_MACHINE (1<<6) /*R/W,Allow trigger to be fired while hart is executing in machine mode*/ +#define TDATA1_MATCH +#define TDATA1_MATCH_V (0xF) /*R/W,Address match type :0 : Exact byte match 1 : NAPOT range match */ +#define TDATA1_MATCH_S (7) + + +/* RISC-V CSR macros + * Adapted from https://github.com/michaeljclark/riscv-probe/blob/master/libfemto/include/arch/riscv/machine.h + */ + +#define RV_READ_CONST_CSR(reg) ({ unsigned long __tmp; \ + asm ("csrr %0, " _CSR_STRINGIFY(reg) : "=r"(__tmp)); __tmp; }) + +#define RV_READ_CSR(reg) ({ unsigned long __tmp; \ + asm volatile ("csrr %0, " _CSR_STRINGIFY(reg) : "=r"(__tmp)); __tmp; }) + +#define RV_WRITE_CSR(reg, val) ({ \ + asm volatile ("csrw " _CSR_STRINGIFY(reg) ", %0" :: "rK"(val)); }) + +#define RV_SWAP_CSR(reg, val) ({ unsigned long __tmp; \ + asm volatile ("csrrw %0, " _CSR_STRINGIFY(reg) ", %1" : "=r"(__tmp) : "rK"(val)); __tmp; }) + +/* Note: this uses the atomic read-and-set instruction so possible to read the old CSR value as a result */ +#define RV_SET_CSR(reg, bit) ({ unsigned long __tmp; \ + asm volatile ("csrrs %0, " _CSR_STRINGIFY(reg) ", %1" : "=r"(__tmp) : "rK"(bit)); __tmp; }) + +/* Note: this uses the atomic read-and-clear instruction so possible to read the old CSR value as a result */ +#define RV_CLEAR_CSR(reg, bit) ({ unsigned long __tmp; \ + asm volatile ("csrrc %0, " _CSR_STRINGIFY(reg) ", %1" : "=r"(__tmp) : "rK"(bit)); __tmp; }) + +#define RV_SET_CSR_FIELD(_r, _f, _v) ({ (RV_WRITE_CSR((_r),((RV_READ_CSR(_r) & ~((_f##_V) << (_f##_S)))|(((_v) & (_f##_V))<<(_f##_S)))));}) +#define RV_CLEAR_CSR_FIELD(_r, _f) ({ (RV_WRITE_CSR((_r),(RV_READ_CSR(_r) & ~((_f##_V) << (_f##_S)))));}) + +#define _CSR_STRINGIFY(REG) #REG /* needed so the 'reg' argument can be a macro or a register name */ + +#ifdef __cplusplus +} +#endif diff --git a/components/riscv/include/riscv/encoding.h b/components/riscv/include/riscv/encoding.h new file mode 100644 index 0000000000..91c92a696f --- /dev/null +++ b/components/riscv/include/riscv/encoding.h @@ -0,0 +1,227 @@ +/* Copyright (c) 2010-2017, The Regents of the University of California + (Regents). All Rights Reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the Regents nor the + names of its contributors may be used to endorse or promote products + derived from this software without specific prior written permission. + + IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, + SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING + OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS + BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED + HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE + MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. +*/ + +/* Adapted from https://github.com/riscv/riscv-opcodes/blob/master/encoding.h */ + +#pragma once + + +#define MSTATUS_UIE 0x00000001 +#define MSTATUS_SIE 0x00000002 +#define MSTATUS_HIE 0x00000004 +#define MSTATUS_MIE 0x00000008 +#define MSTATUS_UPIE 0x00000010 +#define MSTATUS_SPIE 0x00000020 +#define MSTATUS_HPIE 0x00000040 +#define MSTATUS_MPIE 0x00000080 +#define MSTATUS_SPP 0x00000100 +#define MSTATUS_VS 0x00000600 +#define MSTATUS_MPP 0x00001800 +#define MSTATUS_FS 0x00006000 +#define MSTATUS_XS 0x00018000 +#define MSTATUS_MPRV 0x00020000 +#define MSTATUS_SUM 0x00040000 +#define MSTATUS_MXR 0x00080000 +#define MSTATUS_TVM 0x00100000 +#define MSTATUS_TW 0x00200000 +#define MSTATUS_TSR 0x00400000 +#define MSTATUS32_SD 0x80000000 +#define MSTATUS_UXL 0x0000000300000000 +#define MSTATUS_SXL 0x0000000C00000000 +#define MSTATUS64_SD 0x8000000000000000 + +#define SSTATUS_UIE 0x00000001 +#define SSTATUS_SIE 0x00000002 +#define SSTATUS_UPIE 0x00000010 +#define SSTATUS_SPIE 0x00000020 +#define SSTATUS_SPP 0x00000100 +#define SSTATUS_VS 0x00000600 +#define SSTATUS_FS 0x00006000 +#define SSTATUS_XS 0x00018000 +#define SSTATUS_SUM 0x00040000 +#define SSTATUS_MXR 0x00080000 +#define SSTATUS32_SD 0x80000000 +#define SSTATUS_UXL 0x0000000300000000 +#define SSTATUS64_SD 0x8000000000000000 + +#define USTATUS_UIE 0x00000001 +#define USTATUS_UPIE 0x00000010 + +#define DCSR_XDEBUGVER (3U<<30) +#define DCSR_NDRESET (1<<29) +#define DCSR_FULLRESET (1<<28) +#define DCSR_EBREAKM (1<<15) +#define DCSR_EBREAKH (1<<14) +#define DCSR_EBREAKS (1<<13) +#define DCSR_EBREAKU (1<<12) +#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STOPTIME (1<<9) +#define DCSR_CAUSE (7<<6) +#define DCSR_DEBUGINT (1<<5) +#define DCSR_HALT (1<<3) +#define DCSR_STEP (1<<2) +#define DCSR_PRV (3<<0) + +#define DCSR_CAUSE_NONE 0 +#define DCSR_CAUSE_SWBP 1 +#define DCSR_CAUSE_HWBP 2 +#define DCSR_CAUSE_DEBUGINT 3 +#define DCSR_CAUSE_STEP 4 +#define DCSR_CAUSE_HALT 5 +#define DCSR_CAUSE_GROUP 6 + +#define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) +#define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) +#define MCONTROL_MASKMAX(xlen) (0x3fULL<<((xlen)-11)) + +#define MCONTROL_SELECT (1<<19) +#define MCONTROL_TIMING (1<<18) +#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_CHAIN (1<<11) +#define MCONTROL_MATCH (0xf<<7) +#define MCONTROL_M (1<<6) +#define MCONTROL_H (1<<5) +#define MCONTROL_S (1<<4) +#define MCONTROL_U (1<<3) +#define MCONTROL_EXECUTE (1<<2) +#define MCONTROL_STORE (1<<1) +#define MCONTROL_LOAD (1<<0) + +#define MCONTROL_TYPE_NONE 0 +#define MCONTROL_TYPE_MATCH 2 + +#define MCONTROL_ACTION_DEBUG_EXCEPTION 0 +#define MCONTROL_ACTION_DEBUG_MODE 1 +#define MCONTROL_ACTION_TRACE_START 2 +#define MCONTROL_ACTION_TRACE_STOP 3 +#define MCONTROL_ACTION_TRACE_EMIT 4 + +#define MCONTROL_MATCH_EQUAL 0 +#define MCONTROL_MATCH_NAPOT 1 +#define MCONTROL_MATCH_GE 2 +#define MCONTROL_MATCH_LT 3 +#define MCONTROL_MATCH_MASK_LOW 4 +#define MCONTROL_MATCH_MASK_HIGH 5 + +#define MIP_USIP (1 << IRQ_U_SOFT) +#define MIP_SSIP (1 << IRQ_S_SOFT) +#define MIP_HSIP (1 << IRQ_H_SOFT) +#define MIP_MSIP (1 << IRQ_M_SOFT) +#define MIP_UTIP (1 << IRQ_U_TIMER) +#define MIP_STIP (1 << IRQ_S_TIMER) +#define MIP_HTIP (1 << IRQ_H_TIMER) +#define MIP_MTIP (1 << IRQ_M_TIMER) +#define MIP_UEIP (1 << IRQ_U_EXT) +#define MIP_SEIP (1 << IRQ_S_EXT) +#define MIP_HEIP (1 << IRQ_H_EXT) +#define MIP_MEIP (1 << IRQ_M_EXT) + +#define SIP_SSIP MIP_SSIP +#define SIP_STIP MIP_STIP + +#define PRV_U 0 +#define PRV_S 1 +#define PRV_H 2 +#define PRV_M 3 + +#define SATP32_MODE 0x80000000 +#define SATP32_ASID 0x7FC00000 +#define SATP32_PPN 0x003FFFFF +#define SATP64_MODE 0xF000000000000000 +#define SATP64_ASID 0x0FFFF00000000000 +#define SATP64_PPN 0x00000FFFFFFFFFFF + +#define SATP_MODE_OFF 0 +#define SATP_MODE_SV32 1 +#define SATP_MODE_SV39 8 +#define SATP_MODE_SV48 9 +#define SATP_MODE_SV57 10 +#define SATP_MODE_SV64 11 + +#define PMP_R 0x01 +#define PMP_W 0x02 +#define PMP_X 0x04 +#define PMP_A 0x18 +#define PMP_L 0x80 +#define PMP_SHIFT 2 + +#define PMP_TOR 0x08 +#define PMP_NA4 0x10 +#define PMP_NAPOT 0x18 + +#define IRQ_U_SOFT 0 +#define IRQ_S_SOFT 1 +#define IRQ_H_SOFT 2 +#define IRQ_M_SOFT 3 +#define IRQ_U_TIMER 4 +#define IRQ_S_TIMER 5 +#define IRQ_H_TIMER 6 +#define IRQ_M_TIMER 7 +#define IRQ_U_EXT 8 +#define IRQ_S_EXT 9 +#define IRQ_H_EXT 10 +#define IRQ_M_EXT 11 +#define IRQ_COP 12 +#define IRQ_HOST 13 + +#define DEFAULT_RSTVEC 0x00001000 +#define CLINT_BASE 0x02000000 +#define CLINT_SIZE 0x000c0000 +#define EXT_IO_BASE 0x40000000 +#define DRAM_BASE 0x80000000 + +/* page table entry (PTE) fields */ +#define PTE_V 0x001 /* Valid */ +#define PTE_R 0x002 /* Read */ +#define PTE_W 0x004 /* Write */ +#define PTE_X 0x008 /* Execute */ +#define PTE_U 0x010 /* User */ +#define PTE_G 0x020 /* Global */ +#define PTE_A 0x040 /* Accessed */ +#define PTE_D 0x080 /* Dirty */ +#define PTE_SOFT 0x300 /* Reserved for Software */ + +#define PTE_PPN_SHIFT 10 + +#define PTE_TABLE(PTE) (((PTE) & (PTE_V | PTE_R | PTE_W | PTE_X)) == PTE_V) + +#ifdef __riscv + +#if __riscv_xlen == 64 +# define MSTATUS_SD MSTATUS64_SD +# define SSTATUS_SD SSTATUS64_SD +# define RISCV_PGLEVEL_BITS 9 +# define SATP_MODE SATP64_MODE +#else +# define MSTATUS_SD MSTATUS32_SD +# define SSTATUS_SD SSTATUS32_SD +# define RISCV_PGLEVEL_BITS 10 +# define SATP_MODE SATP32_MODE +#endif +#define RISCV_PGSHIFT 12 +#define RISCV_PGSIZE (1 << RISCV_PGSHIFT) + +#endif // __riscv diff --git a/components/riscv/include/riscv/interrupt.h b/components/riscv/include/riscv/interrupt.h new file mode 100644 index 0000000000..6498d57f2f --- /dev/null +++ b/components/riscv/include/riscv/interrupt.h @@ -0,0 +1,115 @@ +// 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +enum intr_type { + INTR_TYPE_LEVEL = 0, + INTR_TYPE_EDGE +}; +/*************************** Software interrupt dispatcher ***************************/ + +/** Callback type of the interrupt handler */ +typedef void (*intr_handler_t)(void*); + +/** Set the interrupt handler function for the given CPU interrupt + * @param rv_int_num CPU interrupt number + * @param fn Handler function + * @param arg Handler argument + */ +void intr_handler_set(int rv_int_num, intr_handler_t fn, void* arg); + +/** Get the interrupt handler function for the given CPU interrupt + * + *@return interrupt handler registered for a particular interrupt number, or NULL otherwise + */ +intr_handler_t intr_handler_get(int rv_int_num); + +/** Get the interrupt handler argument associated with the given CPU interrupt + * + *@return interrupt handler argument for a particular interrupt number, or NULL otherwise + */ +void *intr_handler_get_arg(int rv_int_num); + +/*************************** Interrupt matrix ***************************/ + +/** + * this function will be removed in later, please use `intr_matrix_set` instead + * Route the peripheral interrupt signal to the CPU + * @param periph_intr_source Peripheral interrupt number, one of ETS_XXX_SOURCE + * @param rv_int_num CPU interrupt number + */ +void intr_matrix_route(int periph_intr_source, int rv_int_num); + +/*************************** ESP-RV Interrupt Controller ***************************/ + +/** + * @brief Enable interrupts from interrupt controller. + * + * @param uint32_t unmask, unmask bits for interrupts, each bit for an interrupt + * + * return none + */ +void esprv_intc_int_enable(uint32_t unmask); + +/** + * @brief Disable interrupts from interrupt controller. + * + * @param uint32_t mask, mask bits for interrupts, each bit for an interrupt + * + * return none + */ +void esprv_intc_int_disable(uint32_t mask); + +/** + * @brief Set interrupt type, level or edge + * + * @param int intr_num, interrupt number + * + * @param enum intr_type type, interrupt type, the level interrupt + can be cleared automatically once the interrupt source cleared, the edge interrupt should be clear by software after handled + * + * return none + */ +void esprv_intc_int_set_type(int intr_num, enum intr_type type); + +/** + * Set interrupt priority in the interrupt controller + * @param rv_int_num CPU interrupt number + * @param priority Interrupt priority level, 1 to 7 + */ +void esprv_intc_int_set_priority(int rv_int_num, int priority); + +/** + * Set interrupt priority threshold. + * Interrupts with priority levels lower than the threshold are masked. + * + * @param priority_threshold Interrupt priority threshold, 0 to 7 + */ +void esprv_intc_set_threshold(int priority_threshold); + +/** + * @brief Get interrupt unmask + * @param none + * @return uint32_t interrupt unmask + */ +uint32_t esprv_intc_get_interrupt_unmask(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/riscv/include/riscv/riscv_interrupts.h b/components/riscv/include/riscv/riscv_interrupts.h new file mode 100644 index 0000000000..b3d225d58c --- /dev/null +++ b/components/riscv/include/riscv/riscv_interrupts.h @@ -0,0 +1,45 @@ +// 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. + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Enable CPU interrupt + * @param rv_int_num CPU interrupt number + */ +void riscv_interrupt_enable(int rv_int_num); + +/** + * Disable CPU interrupt + * @param rv_int_num CPU interrupt number + */ +void riscv_interrupt_disable(int rv_int_num); + +/** + * Globally enable CPU interrupts + */ +void riscv_global_interrupts_enable(void); + +/** + * Globally disable CPU interrupts + */ +void riscv_global_interrupts_disable(void); + +#ifdef __cplusplus +} +#endif diff --git a/components/riscv/include/riscv/rvruntime-frames.h b/components/riscv/include/riscv/rvruntime-frames.h new file mode 100644 index 0000000000..b4e4c141b5 --- /dev/null +++ b/components/riscv/include/riscv/rvruntime-frames.h @@ -0,0 +1,95 @@ +#ifndef __RVRUNTIME_FRAMES_H__ +#define __RVRUNTIME_FRAMES_H__ + +/* Align a value up to nearest n-byte boundary, where n is a power of 2. */ +#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) + +#ifdef STRUCT_BEGIN +#undef STRUCT_BEGIN +#undef STRUCT_FIELD +#undef STRUCT_AFIELD +#undef STRUCT_END +#endif + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) + +#define STRUCT_BEGIN .pushsection .text; .struct 0 +#define STRUCT_FIELD(ctype,size,asname,name) asname: .space size +#define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) +#define STRUCT_END(sname) sname##Size:; .popsection + +#else + +#define STRUCT_BEGIN typedef struct { +#define STRUCT_FIELD(ctype,size,asname,name) ctype name; +#define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; +#define STRUCT_END(sname) } sname; + +#endif + +/* +------------------------------------------------------------------------------- + INTERRUPT/EXCEPTION STACK FRAME FOR A EXCEPTION OR NESTED INTERRUPT +------------------------------------------------------------------------------- +*/ +STRUCT_BEGIN +STRUCT_FIELD (long, 4, RV_STK_MEPC, mepc) /* Machine Exception Program Counter */ +STRUCT_FIELD (long, 4, RV_STK_RA, ra) /* Return address */ +STRUCT_FIELD (long, 4, RV_STK_SP, sp) /* Stack pointer */ +STRUCT_FIELD (long, 4, RV_STK_GP, gp) /* Global pointer */ +STRUCT_FIELD (long, 4, RV_STK_TP, tp) /* Thread pointer */ +STRUCT_FIELD (long, 4, RV_STK_T0, t0) /* Temporary/alternate link register */ +STRUCT_FIELD (long, 4, RV_STK_T1, t1) /* t1-2: Temporaries */ +STRUCT_FIELD (long, 4, RV_STK_T2, t2) +STRUCT_FIELD (long, 4, RV_STK_S0, s0) /* Saved register/frame pointer */ +STRUCT_FIELD (long, 4, RV_STK_S1, s1) /* Saved register */ +STRUCT_FIELD (long, 4, RV_STK_A0, a0) /* a0-1: Function arguments/return address */ +STRUCT_FIELD (long, 4, RV_STK_A1, a1) +STRUCT_FIELD (long, 4, RV_STK_A2, a2) /* a2-7: Function arguments */ +STRUCT_FIELD (long, 4, RV_STK_A3, a3) +STRUCT_FIELD (long, 4, RV_STK_A4, a4) +STRUCT_FIELD (long, 4, RV_STK_A5, a5) +STRUCT_FIELD (long, 4, RV_STK_A6, a6) +STRUCT_FIELD (long, 4, RV_STK_A7, a7) +STRUCT_FIELD (long, 4, RV_STK_S2, s2) /* s2-11: Saved registers */ +STRUCT_FIELD (long, 4, RV_STK_S3, s3) +STRUCT_FIELD (long, 4, RV_STK_S4, s4) +STRUCT_FIELD (long, 4, RV_STK_S5, s5) +STRUCT_FIELD (long, 4, RV_STK_S6, s6) +STRUCT_FIELD (long, 4, RV_STK_S7, s7) +STRUCT_FIELD (long, 4, RV_STK_S8, s8) +STRUCT_FIELD (long, 4, RV_STK_S9, s9) +STRUCT_FIELD (long, 4, RV_STK_S10, s10) +STRUCT_FIELD (long, 4, RV_STK_S11, s11) +STRUCT_FIELD (long, 4, RV_STK_T3, t3) /* t3-6: Temporaries */ +STRUCT_FIELD (long, 4, RV_STK_T4, t4) +STRUCT_FIELD (long, 4, RV_STK_T5, t5) +STRUCT_FIELD (long, 4, RV_STK_T6, t6) +STRUCT_FIELD (long, 4, RV_STK_MSTATUS, mstatus) /* Machine Status */ +STRUCT_FIELD (long, 4, RV_STK_MTVEC, mtvec) /* Machine Trap-Vector Base Address */ +STRUCT_FIELD (long, 4, RV_STK_MCAUSE, mcause) /* Machine Trap Cause */ +STRUCT_FIELD (long, 4, RV_STK_PCCRS, pccrs) /* Performance Counter Counter Registers */ +STRUCT_FIELD (long, 4, RV_STK_PCER, pcer) /* Performance Counter Enable */ +STRUCT_FIELD (long, 4, RV_STK_PCMR, pcmr) /* Performance Counter Mode */ +STRUCT_FIELD (long, 4, RV_STK_HWLP, hwlp) /* Hardware Loop Registers */ +STRUCT_FIELD (long, 4, RV_STK_PRIVLV, privlv) /* Privilege Level */ +STRUCT_FIELD (long, 4, RV_STK_UHARTID, uhartid) /* Hardware Thread ID */ +STRUCT_FIELD (long, 4, RV_STK_MHARTID, mhartid) /* Hardware Thread ID */ +STRUCT_FIELD (long, 4, RV_STK_DCSR, dcsr) /* Debug Control and Status */ +STRUCT_FIELD (long, 4, RV_STK_DPC, dpc) /* Debug PC */ +STRUCT_FIELD (long, 4, RV_STK_INTC_THRESH, intc_thresh) +STRUCT_FIELD (long, 4, RV_STK_RESERVED0, reserved0) +STRUCT_END(RvExcFrame) + +#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) +# define RV_STK_SZ1 RvExcFrameSize +#else +# define RV_STK_SZ1 sizeof(RvExcFrame) +#endif + +/* + * This is the frame size. + */ +#define RV_STK_FRMSZ (ALIGNUP(0x10, RV_STK_SZ1)) + +#endif /* #ifndef __RVRUNTIME_FRAMES_H__ */ diff --git a/components/riscv/interrupt.c b/components/riscv/interrupt.c new file mode 100644 index 0000000000..1b48bfdf89 --- /dev/null +++ b/components/riscv/interrupt.c @@ -0,0 +1,111 @@ +// 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 +#include +#include +#include "riscv/interrupt.h" +#include "soc/interrupt_reg.h" +#include "riscv/csr.h" +#include "esp_attr.h" + +#define RV_INT_COUNT 32 + +static inline void assert_valid_rv_int_num(int rv_int_num) +{ + assert(rv_int_num != 0 && rv_int_num < RV_INT_COUNT && "Invalid CPU interrupt number"); +} + +/*************************** Software interrupt dispatcher ***************************/ + + +typedef struct { + intr_handler_t handler; + void *arg; +} intr_handler_item_t; + +static intr_handler_item_t s_intr_handlers[32]; + +void intr_handler_set(int int_no, intr_handler_t fn, void *arg) +{ + assert_valid_rv_int_num(int_no); + + s_intr_handlers[int_no] = (intr_handler_item_t) { + .handler = fn, + .arg = arg + }; +} + +intr_handler_t intr_handler_get(int rv_int_num) +{ + return s_intr_handlers[rv_int_num].handler; +} + +void *intr_handler_get_arg(int rv_int_num) +{ + return s_intr_handlers[rv_int_num].arg; +} + +/* called from vectors.S */ +void _global_interrupt_handler(intptr_t sp, int mcause) +{ + intr_handler_item_t it = s_intr_handlers[mcause]; + if (it.handler) { + (*it.handler)(it.arg); + } +} + +/*************************** RISC-V interrupt enable/disable ***************************/ + +void intr_matrix_route(int intr_src, int intr_num) +{ + assert(intr_num != 0); + + REG_WRITE(DR_REG_INTERRUPT_BASE + 4 * intr_src, intr_num); +} + +void riscv_global_interrupts_enable(void) +{ + RV_SET_CSR(mstatus, MSTATUS_MIE); +} + +void riscv_global_interrupts_disable(void) +{ + RV_CLEAR_CSR(mstatus, MSTATUS_MIE); +} + +uint32_t esprv_intc_get_interrupt_unmask(void) +{ + return REG_READ(INTERRUPT_CORE0_CPU_INT_ENABLE_REG); +} + +/*************************** Exception names. Used in .gdbinit file. ***************************/ + +const char *riscv_excp_names[16] __attribute__((used)) = { + "misaligned_fetch", + "fault_fetch", + "illegal_instruction", + "breakpoint", + "misaligned_load", + "fault_load", + "misaligned_store", + "fault_store", + "user_ecall", + "supervisor_ecall", + "hypervisor_ecall", + "machine_ecall", + "exec_page_fault", + "load_page_fault", + "reserved", + "store_page_fault" +}; diff --git a/components/riscv/linker.lf b/components/riscv/linker.lf new file mode 100644 index 0000000000..cfcb303cf0 --- /dev/null +++ b/components/riscv/linker.lf @@ -0,0 +1,5 @@ +[mapping:riscv] +archive: libriscv.a +entries: + interrupt (noflash_text) + vectors (noflash_text) diff --git a/components/riscv/stdatomic.c b/components/riscv/stdatomic.c new file mode 100644 index 0000000000..7c0c395db5 --- /dev/null +++ b/components/riscv/stdatomic.c @@ -0,0 +1,129 @@ +// Copyright 2015-2019 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. + +//replacement for gcc built-in functions + +#include "sdkconfig.h" +#include +#include +#include "freertos/portmacro.h" + +//reserved to measure atomic operation time +#define atomic_benchmark_intr_disable() +#define atomic_benchmark_intr_restore(STATE) + +// This allows nested interrupts disabling and restoring via local registers or stack. +// They can be called from interrupts too. +// WARNING: Only applies to current CPU. +#define _ATOMIC_ENTER_CRITICAL(void) ({ \ + unsigned state = portENTER_CRITICAL_NESTED(); \ + atomic_benchmark_intr_disable(); \ + state; \ +}) + +#define _ATOMIC_EXIT_CRITICAL(state) do { \ + atomic_benchmark_intr_restore(state); \ + portEXIT_CRITICAL_NESTED(state); \ + } while (0) + +#define CMP_EXCHANGE(n, type) bool __atomic_compare_exchange_ ## n (type* mem, type* expect, type desired, int success, int failure) \ +{ \ + bool ret = false; \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + if (*mem == *expect) { \ + ret = true; \ + *mem = desired; \ + } else { \ + *expect = *mem; \ + } \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#define FETCH_ADD(n, type) type __atomic_fetch_add_ ## n (type* ptr, type value, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + type ret = *ptr; \ + *ptr = *ptr + value; \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#define FETCH_SUB(n, type) type __atomic_fetch_sub_ ## n (type* ptr, type value, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + type ret = *ptr; \ + *ptr = *ptr - value; \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#define FETCH_AND(n, type) type __atomic_fetch_and_ ## n (type* ptr, type value, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + type ret = *ptr; \ + *ptr = *ptr & value; \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#define FETCH_OR(n, type) type __atomic_fetch_or_ ## n (type* ptr, type value, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + type ret = *ptr; \ + *ptr = *ptr | value; \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#define FETCH_XOR(n, type) type __atomic_fetch_xor_ ## n (type* ptr, type value, int memorder) \ +{ \ + unsigned state = _ATOMIC_ENTER_CRITICAL(); \ + type ret = *ptr; \ + *ptr = *ptr ^ value; \ + _ATOMIC_EXIT_CRITICAL(state); \ + return ret; \ +} + +#pragma GCC diagnostic ignored "-Wbuiltin-declaration-mismatch" + +CMP_EXCHANGE(1, uint8_t) +CMP_EXCHANGE(2, uint16_t) +CMP_EXCHANGE(4, uint32_t) +CMP_EXCHANGE(8, uint64_t) + +FETCH_ADD(1, uint8_t) +FETCH_ADD(2, uint16_t) +FETCH_ADD(4, uint32_t) +FETCH_ADD(8, uint64_t) + +FETCH_SUB(1, uint8_t) +FETCH_SUB(2, uint16_t) +FETCH_SUB(4, uint32_t) +FETCH_SUB(8, uint64_t) + +FETCH_AND(1, uint8_t) +FETCH_AND(2, uint16_t) +FETCH_AND(4, uint32_t) +FETCH_AND(8, uint64_t) + +FETCH_OR(1, uint8_t) +FETCH_OR(2, uint16_t) +FETCH_OR(4, uint32_t) +FETCH_OR(8, uint64_t) + +FETCH_XOR(1, uint8_t) +FETCH_XOR(2, uint16_t) +FETCH_XOR(4, uint32_t) +FETCH_XOR(8, uint64_t) diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S new file mode 100644 index 0000000000..4348cb1047 --- /dev/null +++ b/components/riscv/vectors.S @@ -0,0 +1,307 @@ +// 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 "soc/soc.h" +#include "soc/interrupt_reg.h" + + + .equ SAVE_REGS, 32 + .equ CONTEXT_SIZE, (SAVE_REGS * 4) + .equ PANIC_REGS, 38 + .equ PANIC_REGS_SIZE, (PANIC_REGS * 4) + +.altmacro + +.macro lwsp a, b + lw \a, ((\b)*4)(sp) +.endm + +.macro swsp a, b + sw \a, ((\b)*4)(sp) +.endm + + +.macro save_regs + addi sp, sp, -CONTEXT_SIZE + swsp ra, 1 + swsp a0, 2 + swsp a1, 3 + swsp a2, 4 + swsp a3, 5 + swsp a4, 6 + swsp a5, 7 + swsp a6, 8 + swsp a7, 9 + swsp t0, 10 + swsp t1, 11 + swsp t2, 12 + swsp t3, 13 + swsp t4, 14 + swsp t5, 15 + swsp t6, 16 + //swsp sp, 17 + //swsp gp, 18 + swsp tp, 19 + swsp s0, 20 + swsp s1, 21 + swsp s2, 22 + swsp s3, 23 + swsp s4, 24 + swsp s5, 25 + swsp s6, 26 + swsp s7, 27 + swsp s8, 28 + swsp s9, 29 + swsp s10, 30 + swsp s11, 31 +.endm + +.macro save_mepc + csrr t0, mepc + swsp t0, 0 +.endm + +.macro restore_regs + lwsp ra, 1 + lwsp a0, 2 + lwsp a1, 3 + lwsp a2, 4 + lwsp a3, 5 + lwsp a4, 6 + lwsp a5, 7 + lwsp a6, 8 + lwsp a7, 9 + lwsp t0, 10 + lwsp t1, 11 + lwsp t2, 12 + lwsp t3, 13 + lwsp t4, 14 + lwsp t5, 15 + lwsp t6, 16 + //lwsp sp, 17 + //lwsp gp, 18 + lwsp tp, 19 + lwsp s0, 20 + lwsp s1, 21 + lwsp s2, 22 + lwsp s3, 23 + lwsp s4, 24 + lwsp s5, 25 + lwsp s6, 26 + lwsp s7, 27 + lwsp s8, 28 + lwsp s9, 29 + lwsp s10, 30 + lwsp s11, 31 + addi sp, sp, CONTEXT_SIZE +.endm + +.macro restore_mepc + lwsp t0, 0 + csrw mepc, t0 +.endm + + .global vPortYieldFromISR + .global uxInterruptNesting + .global uxSchedulerRunning + .global xIsrStackTop + .global pxCurrentTCB + .global _global_interrupt_handler + + .section .exception_vectors.text + /* This is the vector table. MTVEC points here. + * + * Use 4-byte intructions here. 1 instruction = 1 entry of the table. + * The CPU jumps to MTVEC (i.e. the first entry) in case of an exception, + * and (MTVEC & 0xfffffffc) + (mcause & 0x7fffffff) * 4, in case of an interrupt. + * + * Note: for our CPU, we need to place this on a 256-byte boundary, as CPU + * only uses the 24 MSBs of the MTVEC, i.e. (MTVEC & 0xffffff00). + */ + + .balign 0x100 + .global _vector_table + .type _vector_table, @function +_vector_table: + .option push + .option norvc + j _panic_handler /* exception handler, entry 0 */ + .rept 31 + j _interrupt_handler /* 31 identical entries, all pointing to the interrupt handler */ + .endr + .option pop + .size _vector_table, .-_vector_table + + /* Exception handler.*/ + .global panicHandler + .type _panic_handler, @function +_panic_handler: + addi sp, sp, -PANIC_REGS_SIZE + swsp x0, 0 + swsp x1, 1 + /* x2 is sp - it will be placed on stack later (after we can use the other registers for computation) */ + swsp x3, 3 + swsp x4, 4 + swsp x5, 5 + swsp x6, 6 + swsp x7, 7 + swsp x8, 8 + swsp x9, 9 + swsp x10, 10 + swsp x11, 11 + swsp x12, 12 + swsp x13, 13 + swsp x14, 14 + swsp x15, 15 + swsp x16, 16 + swsp x17, 17 + swsp x18, 18 + swsp x19, 19 + swsp x20, 20 + swsp x21, 21 + swsp x22, 22 + swsp x23, 23 + swsp x24, 24 + swsp x25, 25 + swsp x26, 26 + swsp x27, 27 + swsp x28, 28 + swsp x29, 29 + swsp x30, 30 + swsp x31, 31 + /* "Undo" the modification already done to the sp (x2) by the panic handler */ + addi a1, x2, PANIC_REGS_SIZE + swsp a1, 2 + csrr a1, mcause + swsp a1, 32 + csrr a1, mepc + swsp a1, 33 + csrr a1, mhartid + swsp a1, 34 + csrr a1, mstatus + swsp a1, 35 + csrr a1, mtval + swsp a1, 36 + csrr a1, mtvec + swsp a1, 37 + mv a0, sp + csrr a1, mcause + jal zero, panicHandler + /* panicHandler never returns */ + .size _panic_handler, .-_panic_handler + + /* This is the interrupt handler. + * It saves the registers on the stack, + * prepares for interrupt nesting, + * re-enables the interrupts, + * then jumps to the C dispatcher in interrupt.c. + */ + .global _interrupt_handler + .type _interrupt_handler, @function +_interrupt_handler: + /* entry */ + save_regs + save_mepc + + /* scheduler not enabled, jump directly to ISR handler */ + lw t0, uxSchedulerRunning + beq t0,zero,already_on_handler + + /* increments the ISR nesting count */ + /* This will work properly when we have nested interrupts */ + la t0, uxInterruptNesting + lw t1, 0x0(t0) + addi t2,t1,1 + sw t2, 0x0(t0) + + /* If reached here from another low-prio ISR, skip stack pushing to TCB */ + bne t1,zero, already_on_handler + + /* Otherwise, save current sp, and use the isr stack from here */ + lw t0, pxCurrentTCB + sw sp, 0x0(t0) + lw sp, xIsrStackTop + +already_on_handler: + /* Before dispatch c handler, restore interrupt to enable nested intr */ + csrr s1, mcause + csrr s2, mstatus + + /* Save the interrupt threshold level */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG + lw s3, 0(t0) + + /* Increase interrupt threshold level */ + la t2, 0x7fffffff + and t1, s1, t2 /* t1 = mcause & mask */ + slli t1, t1, 2 /* t1 = mcause * 4 */ + la t2, INTC_INT_PRIO_REG(0) + add t1, t2, t1 /* t1 = INTC_INT_PRIO_REG + 4 * mcause */ + lw t2, 0(t1) /* t2 = INTC_INT_PRIO_REG[mcause] */ + addi t2, t2, 1 /* t2 = t2 +1 */ + sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ + fence + + la t0, 0x8 + csrrs t0, mstatus, t0 + + /* call the C dispatcher */ + mv a0, sp /* argument 1, stack pointer */ + csrr a1, mcause /* argument 2, interrupt number */ + /* mask off the interrupt flag of mcause */ + la t0, 0x7fffffff + and a1, a1, t0 + jal _global_interrupt_handler + + /* After dispatch c handler, disable interrupt to make freertos make context switch */ + + la t0, 0x8 + csrrc t0, mstatus, t0 + + /* restore the interrupt threshold level */ + la t0, INTERRUPT_CORE0_CPU_INT_THRESH_REG + sw s3, 0(t0) + fence + + /* may skip RTOS aware interrupt since scheduler was not started */ + lw t1, uxSchedulerRunning + beq t1,zero, isr_exit + + /* update nesting interrupts counter */ + la t0, uxInterruptNesting + lw t1, 0x0(t0) + + /* Already zero, protect againts underflow */ + beq t1, zero, isr_skip_decrement + addi t1,t1, -1 + sw t1, 0x0(t0) + +isr_skip_decrement: + /* may still have interrupts pending, skip section below and exit */ + bne t1,zero,isr_exit + + /* handlered all the ISRs and scheduled the next task, take its stack */ + /* load on sp, then exit. */ + lw sp, pxCurrentTCB + lw sp, 0x0(sp) + +isr_exit: + /* restore the rest of the registers */ + csrw mcause, s1 + csrw mstatus, s2 + restore_mepc + restore_regs + + /* exit, this will also re-enable the interrupts */ + mret + .size _interrupt_handler, .-_interrupt_handler From 87e13baaf12fe6deae715d95e912a310fea4ba88 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 6 Nov 2020 15:03:21 +1100 Subject: [PATCH 2/5] freertos: Add RISC-V port Changes come from internal branch commit a6723fc --- components/freertos/CMakeLists.txt | 65 ++- components/freertos/component.mk | 6 +- components/freertos/linker.lf | 2 +- components/freertos/port/port_common.c | 135 +++++++ .../riscv/include/freertos/FreeRTOSConfig.h | 277 +++++++++++++ .../riscv}/include/freertos/portbenchmark.h | 0 .../port/riscv/include/freertos/portmacro.h | 310 +++++++++++++++ components/freertos/port/riscv/port.c | 369 ++++++++++++++++++ components/freertos/port/riscv/portasm.S | 87 +++++ .../xtensa/include/freertos/FreeRTOSConfig.h | 0 .../xtensa/include/freertos/portbenchmark.h | 46 +++ .../xtensa/include/freertos/portmacro.h | 95 ++--- .../xtensa/include/freertos}/portmacro_priv.h | 0 .../xtensa/include/freertos/xtensa_api.h | 0 .../xtensa/include/freertos/xtensa_config.h | 0 .../xtensa/include/freertos/xtensa_context.h | 0 .../xtensa/include/freertos/xtensa_rtos.h | 0 .../xtensa/include/freertos/xtensa_timer.h | 0 components/freertos/{ => port}/xtensa/port.c | 89 +---- .../freertos/{ => port}/xtensa/portasm.S | 0 .../{ => port}/xtensa/readme_xtensa.txt | 0 .../freertos/{ => port}/xtensa/xt_asm_utils.h | 0 .../{ => port}/xtensa/xtensa_context.S | 0 .../freertos/{ => port}/xtensa/xtensa_init.c | 0 .../xtensa/xtensa_loadstore_handler.S | 0 .../xtensa/xtensa_overlay_os_hook.c | 0 .../xtensa/xtensa_vector_defaults.S | 0 .../{ => port}/xtensa/xtensa_vectors.S | 0 components/freertos/test/test_float_in_isr.c | 2 - .../test/test_freertos_backported_functions.c | 2 + .../test/test_freertos_isinisrcontext.c | 30 +- .../test/test_freertos_scheduling_time.c | 2 - .../freertos/test/test_freertos_task_notify.c | 2 +- components/freertos/test/test_isr_latency.c | 25 +- components/freertos/test/test_newlib_reent.c | 1 - components/freertos/test/test_panic.c | 1 - components/freertos/test/test_preemption.c | 10 +- components/freertos/test/test_spinlocks.c | 6 +- .../freertos/test/test_suspend_scheduler.c | 1 - .../freertos/test/test_task_suspend_resume.c | 1 - components/freertos/test/test_thread_local.c | 2 + .../test/test_xtensa_loadstore_handler.c | 8 +- components/lwip/test_afl_host/Makefile | 2 +- components/mdns/test_afl_fuzz_host/Makefile | 2 +- tools/ci/check_public_headers_exceptions.txt | 2 +- tools/ci/test_build_system.sh | 4 +- tools/ci/test_build_system_cmake.sh | 4 +- 47 files changed, 1368 insertions(+), 220 deletions(-) create mode 100644 components/freertos/port/port_common.c create mode 100644 components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h rename components/freertos/{xtensa => port/riscv}/include/freertos/portbenchmark.h (100%) create mode 100644 components/freertos/port/riscv/include/freertos/portmacro.h create mode 100644 components/freertos/port/riscv/port.c create mode 100644 components/freertos/port/riscv/portasm.S rename components/freertos/{ => port}/xtensa/include/freertos/FreeRTOSConfig.h (100%) create mode 100644 components/freertos/port/xtensa/include/freertos/portbenchmark.h rename components/freertos/{ => port}/xtensa/include/freertos/portmacro.h (82%) rename components/freertos/{xtensa => port/xtensa/include/freertos}/portmacro_priv.h (100%) rename components/freertos/{ => port}/xtensa/include/freertos/xtensa_api.h (100%) rename components/freertos/{ => port}/xtensa/include/freertos/xtensa_config.h (100%) rename components/freertos/{ => port}/xtensa/include/freertos/xtensa_context.h (100%) rename components/freertos/{ => port}/xtensa/include/freertos/xtensa_rtos.h (100%) rename components/freertos/{ => port}/xtensa/include/freertos/xtensa_timer.h (100%) rename components/freertos/{ => port}/xtensa/port.c (88%) rename components/freertos/{ => port}/xtensa/portasm.S (100%) rename components/freertos/{ => port}/xtensa/readme_xtensa.txt (100%) rename components/freertos/{ => port}/xtensa/xt_asm_utils.h (100%) rename components/freertos/{ => port}/xtensa/xtensa_context.S (100%) rename components/freertos/{ => port}/xtensa/xtensa_init.c (100%) rename components/freertos/{ => port}/xtensa/xtensa_loadstore_handler.S (100%) rename components/freertos/{ => port}/xtensa/xtensa_overlay_os_hook.c (100%) rename components/freertos/{ => port}/xtensa/xtensa_vector_defaults.S (100%) rename components/freertos/{ => port}/xtensa/xtensa_vectors.S (100%) diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 4c702bd2a1..732d643573 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -4,16 +4,49 @@ if(BOOTLOADER_BUILD) return() endif() -set(srcs - "xtensa/port.c" - "xtensa/portasm.S" - "xtensa/xtensa_context.S" - "xtensa/xtensa_init.c" - "xtensa/xtensa_overlay_os_hook.c" - "xtensa/xtensa_vector_defaults.S" - "xtensa/xtensa_vectors.S") +idf_build_get_property(target IDF_TARGET) + +if(NOT "${target}" STREQUAL "esp32c3") # should test arch here not target, TODO ESP32-C3 IDF-1754 + set(srcs + "port/xtensa/port.c" + "port/xtensa/portasm.S" + "port/xtensa/xtensa_context.S" + "port/xtensa/xtensa_init.c" + "port/xtensa/xtensa_overlay_os_hook.c" + "port/xtensa/xtensa_vector_defaults.S" + "port/xtensa/xtensa_vectors.S") + + set(include_dirs + include + port/xtensa/include) + + set(private_include_dirs + include/freertos + port/xtensa/include/freertos + port/xtensa + .) + + set(required_components app_trace esp_timer) +else() # RISC-V + set(srcs + "port/riscv/port.c" + "port/riscv/portasm.S") + + set(include_dirs + include + port/riscv/include) + + set(private_include_dirs + include/freertos + port/riscv/include/freertos + port/riscv + .) + + set(required_components esp_timer) +endif() list(APPEND srcs + "port/port_common.c" "croutine.c" "event_groups.c" "list.c" @@ -23,19 +56,9 @@ list(APPEND srcs "stream_buffer.c" "FreeRTOS-openocd.c") -set(include_dirs - include - xtensa/include) - -set(private_include_dirs - include/freertos - xtensa/include/freertos - xtensa - .) - if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY) - list(APPEND srcs "xtensa/xtensa_loadstore_handler.S") - endif() + list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S") +endif() # app_trace is required by FreeRTOS headers only when CONFIG_SYSVIEW_ENABLE=y, # but requirements can't depend on config options, so always require it. @@ -43,7 +66,7 @@ idf_component_register(SRCS "${srcs}" INCLUDE_DIRS ${include_dirs} PRIV_INCLUDE_DIRS ${private_include_dirs} LDFRAGMENTS linker.lf - REQUIRES app_trace esp_timer + REQUIRES ${required_components} PRIV_REQUIRES soc) idf_component_get_property(COMPONENT_DIR freertos COMPONENT_DIR) diff --git a/components/freertos/component.mk b/components/freertos/component.mk index fcf27d80ac..e72576cbcd 100644 --- a/components/freertos/component.mk +++ b/components/freertos/component.mk @@ -6,9 +6,9 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority endif -COMPONENT_ADD_INCLUDEDIRS := include xtensa/include -COMPONENT_PRIV_INCLUDEDIRS := include/freertos xtensa/include/freertos xtensa . -COMPONENT_SRCDIRS += xtensa +COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include +COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa . +COMPONENT_SRCDIRS += port port/xtensa ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 966527e7de..b1653f27c8 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -112,6 +112,6 @@ entries: queue: xQueueAddToSet (default) queue: xQueueRemoveFromSet (default) queue: xQueueSelectFromSet (default) - port:main_task (default) + port_common:main_task (default) port:esp_startup_start_app (default) port:esp_startup_start_app_other_cores (default) diff --git a/components/freertos/port/port_common.c b/components/freertos/port/port_common.c new file mode 100644 index 0000000000..b80c82a1b0 --- /dev/null +++ b/components/freertos/port/port_common.c @@ -0,0 +1,135 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#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 /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); +} diff --git a/components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h b/components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h new file mode 100644 index 0000000000..8ad33ae71d --- /dev/null +++ b/components/freertos/port/riscv/include/freertos/FreeRTOSConfig.h @@ -0,0 +1,277 @@ +/* + FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include "sdkconfig.h" + +/* enable use of optimized task selection by the scheduler */ +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + +#define portNUM_PROCESSORS 1 +#define configASSERT_2 0 +#define portUSING_MPU_WRAPPERS 0 +#define configUSE_MUTEX 1 + +#define configMAX_SYSCALL_INTERRUPT_PRIORITY 0 +#define configUSE_NEWLIB_REENTRANT 1 + +#define configNUM_THREAD_LOCAL_STORAGE_POINTERS CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS +#define configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS 1 + +/* configASSERT behaviour */ +#ifndef __ASSEMBLER__ +#include /* 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 */ diff --git a/components/freertos/xtensa/include/freertos/portbenchmark.h b/components/freertos/port/riscv/include/freertos/portbenchmark.h similarity index 100% rename from components/freertos/xtensa/include/freertos/portbenchmark.h rename to components/freertos/port/riscv/include/freertos/portbenchmark.h diff --git a/components/freertos/port/riscv/include/freertos/portmacro.h b/components/freertos/port/riscv/include/freertos/portmacro.h new file mode 100644 index 0000000000..9ba2d57761 --- /dev/null +++ b/components/freertos/port/riscv/include/freertos/portmacro.h @@ -0,0 +1,310 @@ +/* + * FreeRTOS Kernel V10.2.1 + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ +#ifndef PORTMACRO_H +#define PORTMACRO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include +#include + +#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 +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 */ diff --git a/components/freertos/port/riscv/port.c b/components/freertos/port/riscv/port.c new file mode 100644 index 0000000000..a30d225263 --- /dev/null +++ b/components/freertos/port/riscv/port.c @@ -0,0 +1,369 @@ +/* + FreeRTOS V8.2.3 - Copyright (C) 2015 Real Time Engineers Ltd. + All rights reserved + + VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. + + This file is part of the FreeRTOS distribution and was contributed + to the project by Technolution B.V. (www.technolution.nl, + freertos-riscv@technolution.eu) under the terms of the FreeRTOS + contributors license. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation >>>> AND MODIFIED BY <<<< the FreeRTOS exception. + + *************************************************************************** + >>! NOTE: The modification to the GPL is included to allow you to !<< + >>! distribute a combined work that includes FreeRTOS without being !<< + >>! obliged to provide the source code for proprietary components !<< + >>! outside of the FreeRTOS kernel. !<< + *************************************************************************** + + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + FOR A PARTICULAR PURPOSE. Full license text is available on the following + link: http://www.freertos.org/a00114.html + + *************************************************************************** + * * + * FreeRTOS provides completely free yet professionally developed, * + * robust, strictly quality controlled, supported, and cross * + * platform software that is more than just the market leader, it * + * is the industry's de facto standard. * + * * + * Help yourself get started quickly while simultaneously helping * + * to support the FreeRTOS project by purchasing a FreeRTOS * + * tutorial book, reference manual, or both: * + * http://www.FreeRTOS.org/Documentation * + * * + *************************************************************************** + + http://www.FreeRTOS.org/FAQHelp.html - Having a problem? Start by reading + the FAQ page "My application does not run, what could be wrong?". Have you + defined configASSERT()? + + http://www.FreeRTOS.org/support - In return for receiving this top quality + embedded software for free we request you assist our global community by + participating in the support forum. + + http://www.FreeRTOS.org/training - Investing in training allows your team to + be as productive as possible as early as possible. Now you can receive + FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers + Ltd, and the world's leading authority on the world's leading RTOS. + + http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, + including FreeRTOS+Trace - an indispensable productivity tool, a DOS + compatible FAT file system, and our tiny thread aware UDP/IP stack. + + http://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate. + Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS. + + http://www.OpenRTOS.com - Real Time Engineers ltd. license FreeRTOS to High + Integrity Systems ltd. to sell under the OpenRTOS brand. Low cost OpenRTOS + licenses offer ticketed support, indemnification and commercial middleware. + + http://www.SafeRTOS.com - High Integrity Systems also provide a safety + engineered and independently SIL3 certified version for use in safety and + mission critical applications that require provable dependability. + + 1 tab == 4 spaces! +*/ + +/*----------------------------------------------------------------------- + * Implementation of functions defined in portable.h for the RISC-V port. + *----------------------------------------------------------------------*/ + +#include +#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(); +} diff --git a/components/freertos/port/riscv/portasm.S b/components/freertos/port/riscv/portasm.S new file mode 100644 index 0000000000..e4e05e3d68 --- /dev/null +++ b/components/freertos/port/riscv/portasm.S @@ -0,0 +1,87 @@ +// Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + + .global uxInterruptNesting + .global uxSchedulerRunning + .global xIsrStackTop + .global pxCurrentTCB + .global vTaskSwitchContext + .global xPortSwitchFlag + + .section .text + +/** + * This function makes the RTOS aware about a ISR entering, it takes the + * current task stack saved, places into the TCB, loads the ISR stack + * the interrupted stack must be passed in a0. It needs to receive the + * ISR nesting code improvements + */ + + .global rtos_int_enter + .type rtos_int_enter, @function +rtos_int_enter: + /* preserve the return address */ + mv t1, ra + mv t2, a0 + + /* scheduler not enabled, jump directly to ISR handler */ + lw t0, uxSchedulerRunning + beq t0,zero, not_rtos_enter + + /* Sabe current TCB and load the ISR stack */ + lw t0, pxCurrentTCB + sw t2, 0x0(t0) + lw sp, xIsrStackTop + +not_rtos_enter: + mv ra, t1 + ret + +/** + * Recovers the next task to run stack pointer and place it into + * a0, then the interrupt handler can restore the context of + * the next task + */ + .global rtos_int_exit + .type rtos_int_exit, @function +rtos_int_exit: + + /* may skip RTOS aware interrupt since scheduler was not started */ + lw t0, uxSchedulerRunning + beq t0,zero, not_rtos_exit + + /* Schedule the next task if a yield is pending */ + la t0, xPortSwitchFlag + lw t2, 0x0(t0) + beq t2, zero, no_switch + + /* preserve return address and schedule next task */ + addi sp,sp,-4 + sw ra, 0x04(sp) + call vTaskSwitchContext + lw ra, 0x04(sp) + addi sp, sp, 4 + + /* Clears the switch pending flag */ + la t0, xPortSwitchFlag + mv t2, zero + sw t2, 0x0(t0) + +no_switch: + /* Recover the stack of next task and prepare to exit : */ + lw a0, pxCurrentTCB + lw a0, 0x0(a0) + +not_rtos_exit: + ret diff --git a/components/freertos/xtensa/include/freertos/FreeRTOSConfig.h b/components/freertos/port/xtensa/include/freertos/FreeRTOSConfig.h similarity index 100% rename from components/freertos/xtensa/include/freertos/FreeRTOSConfig.h rename to components/freertos/port/xtensa/include/freertos/FreeRTOSConfig.h diff --git a/components/freertos/port/xtensa/include/freertos/portbenchmark.h b/components/freertos/port/xtensa/include/freertos/portbenchmark.h new file mode 100644 index 0000000000..4ce41d3dad --- /dev/null +++ b/components/freertos/port/xtensa/include/freertos/portbenchmark.h @@ -0,0 +1,46 @@ +/******************************************************************************* +// Copyright (c) 2003-2015 Cadence Design Systems, Inc. +// +// Permission is hereby granted, free of charge, to any person obtaining +// a copy of this software and associated documentation files (the +// "Software"), to deal in the Software without restriction, including +// without limitation the rights to use, copy, modify, merge, publish, +// distribute, sublicense, and/or sell copies of the Software, and to +// permit persons to whom the Software is furnished to do so, subject to +// the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +// SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +-------------------------------------------------------------------------------- +*/ + +/* + * This utility helps benchmarking interrupt latency and context switches. + * In order to enable it, set configBENCHMARK to 1 in FreeRTOSConfig.h. + * You will also need to download the FreeRTOS_trace patch that contains + * portbenchmark.c and the complete version of portbenchmark.h + */ + +#ifndef PORTBENCHMARK_H +#define PORTBENCHMARK_H + +#if configBENCHMARK + #error "You need to download the FreeRTOS_trace patch that overwrites this file" +#endif + +#define portbenchmarkINTERRUPT_DISABLE() +#define portbenchmarkINTERRUPT_RESTORE(newstate) +#define portbenchmarkIntLatency() +#define portbenchmarkIntWait() +#define portbenchmarkReset() +#define portbenchmarkPrint() + +#endif /* PORTBENCHMARK */ diff --git a/components/freertos/xtensa/include/freertos/portmacro.h b/components/freertos/port/xtensa/include/freertos/portmacro.h similarity index 82% rename from components/freertos/xtensa/include/freertos/portmacro.h rename to components/freertos/port/xtensa/include/freertos/portmacro.h index 42427dda83..563b4188f4 100644 --- a/components/freertos/xtensa/include/freertos/portmacro.h +++ b/components/freertos/port/xtensa/include/freertos/portmacro.h @@ -1,68 +1,29 @@ /* - FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd. - All rights reserved - - VISIT http://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION. - - *************************************************************************** - * * - * FreeRTOS provides completely free yet professionally developed, * - * robust, strictly quality controlled, supported, and cross * - * platform software that has become a de facto standard. * - * * - * Help yourself get started quickly and support the FreeRTOS * - * project by purchasing a FreeRTOS tutorial book, reference * - * manual, or both from: http://www.FreeRTOS.org/Documentation * - * * - * Thank you! * - * * - *************************************************************************** - - This file is part of the FreeRTOS distribution. - - FreeRTOS is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License (version 2) as published by the - Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception. - - >>! NOTE: The modification to the GPL is included to allow you to !<< - >>! distribute a combined work that includes FreeRTOS without being !<< - >>! obliged to provide the source code for proprietary components !<< - >>! outside of the FreeRTOS kernel. !<< - - FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS - FOR A PARTICULAR PURPOSE. Full license text is available from the following - link: http://www.freertos.org/a00114.html - - 1 tab == 4 spaces! - - *************************************************************************** - * * - * Having a problem? Start by reading the FAQ "My application does * - * not run, what could be wrong?" * - * * - * http://www.FreeRTOS.org/FAQHelp.html * - * * - *************************************************************************** - - http://www.FreeRTOS.org - Documentation, books, training, latest versions, - license and Real Time Engineers Ltd. contact details. - - http://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products, - including FreeRTOS+Trace - an indispensable productivity tool, a DOS - compatible FAT file system, and our tiny thread aware UDP/IP stack. - - http://www.OpenRTOS.com - Real Time Engineers ltd license FreeRTOS to High - Integrity Systems to sell under the OpenRTOS brand. Low cost OpenRTOS - licenses offer ticketed support, indemnification and middleware. - - http://www.SafeRTOS.com - High Integrity Systems also provide a safety - engineered and independently SIL3 certified version for use in safety and - mission critical applications that require provable dependability. - - 1 tab == 4 spaces! -*/ - + * FreeRTOS Kernel V10.2.1 + * Copyright (C) 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * http://www.FreeRTOS.org + * http://aws.amazon.com/freertos + * + * 1 tab == 4 spaces! + */ #ifndef PORTMACRO_H #define PORTMACRO_H @@ -108,8 +69,11 @@ extern "C" { *----------------------------------------------------------- */ -/* Type definitions. */ +#include "esp_system.h" +#include "hal/cpu_hal.h" +#include "xt_instr_macros.h" +/* Type definitions. */ #define portCHAR int8_t #define portFLOAT float #define portDOUBLE double @@ -136,6 +100,7 @@ typedef unsigned portBASE_TYPE UBaseType_t; #include "sdkconfig.h" #include "esp_attr.h" +#include "portmacro_priv.h" // Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. // They can be called from interrupts too. diff --git a/components/freertos/xtensa/portmacro_priv.h b/components/freertos/port/xtensa/include/freertos/portmacro_priv.h similarity index 100% rename from components/freertos/xtensa/portmacro_priv.h rename to components/freertos/port/xtensa/include/freertos/portmacro_priv.h diff --git a/components/freertos/xtensa/include/freertos/xtensa_api.h b/components/freertos/port/xtensa/include/freertos/xtensa_api.h similarity index 100% rename from components/freertos/xtensa/include/freertos/xtensa_api.h rename to components/freertos/port/xtensa/include/freertos/xtensa_api.h diff --git a/components/freertos/xtensa/include/freertos/xtensa_config.h b/components/freertos/port/xtensa/include/freertos/xtensa_config.h similarity index 100% rename from components/freertos/xtensa/include/freertos/xtensa_config.h rename to components/freertos/port/xtensa/include/freertos/xtensa_config.h diff --git a/components/freertos/xtensa/include/freertos/xtensa_context.h b/components/freertos/port/xtensa/include/freertos/xtensa_context.h similarity index 100% rename from components/freertos/xtensa/include/freertos/xtensa_context.h rename to components/freertos/port/xtensa/include/freertos/xtensa_context.h diff --git a/components/freertos/xtensa/include/freertos/xtensa_rtos.h b/components/freertos/port/xtensa/include/freertos/xtensa_rtos.h similarity index 100% rename from components/freertos/xtensa/include/freertos/xtensa_rtos.h rename to components/freertos/port/xtensa/include/freertos/xtensa_rtos.h diff --git a/components/freertos/xtensa/include/freertos/xtensa_timer.h b/components/freertos/port/xtensa/include/freertos/xtensa_timer.h similarity index 100% rename from components/freertos/xtensa/include/freertos/xtensa_timer.h rename to components/freertos/port/xtensa/include/freertos/xtensa_timer.h diff --git a/components/freertos/xtensa/port.c b/components/freertos/port/xtensa/port.c similarity index 88% rename from components/freertos/xtensa/port.c rename to components/freertos/port/xtensa/port.c index b642663bac..1a07ef74a9 100644 --- a/components/freertos/xtensa/port.c +++ b/components/freertos/port/xtensa/port.c @@ -139,8 +139,6 @@ extern void _frxt_tick_timer_init(void); /* Defined in xtensa_context.S */ extern void _xt_coproc_init(void); -extern void app_main(void); - static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate to change in the future, but // for now maintain the same log output @@ -154,7 +152,7 @@ static const char* TAG = "cpu_start"; // [refactor-todo]: might be appropriate t _Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "incorrect tskNO_AFFINITY value"); /*-----------------------------------------------------------*/ -volatile unsigned port_xSchedulerRunning[portNUM_PROCESSORS] = {0}; // Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting +extern volatile int port_xSchedulerRunning[portNUM_PROCESSORS]; unsigned port_interruptNesting[portNUM_PROCESSORS] = {0}; // Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit BaseType_t port_uxCriticalNesting[portNUM_PROCESSORS] = {0}; BaseType_t port_uxOldInterruptState[portNUM_PROCESSORS] = {0}; @@ -488,66 +486,6 @@ void __attribute__((weak)) vApplicationStackOverflowHook( TaskHandle_t xTask, c esp_system_abort(buf); } - -static void main_task(void* args) -{ -#if !CONFIG_FREERTOS_UNICORE - // Wait for FreeRTOS initialization to finish on APP CPU, before replacing its startup stack - while (port_xSchedulerRunning[1] == 0) { - ; - } -#endif - - // [refactor-todo] check if there is a way to move the following block to esp_system startup - heap_caps_enable_nonos_stack_heaps(); - - // Now we have startup stack RAM available for heap, enable any DMA pool memory -#if CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL - if (g_spiram_ok) { - esp_err_t r = esp_spiram_reserve_dma_pool(CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL); - if (r != ESP_OK) { - ESP_EARLY_LOGE(TAG, "Could not reserve internal/DMA pool (error 0x%x)", r); - abort(); - } - } -#endif - - //Initialize task wdt if configured to do so -#ifdef CONFIG_ESP_TASK_WDT_PANIC - ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, true)); -#elif CONFIG_ESP_TASK_WDT - ESP_ERROR_CHECK(esp_task_wdt_init(CONFIG_ESP_TASK_WDT_TIMEOUT_S, false)); -#endif - - //Add IDLE 0 to task wdt -#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU0 - TaskHandle_t idle_0 = xTaskGetIdleTaskHandleForCPU(0); - if(idle_0 != NULL){ - ESP_ERROR_CHECK(esp_task_wdt_add(idle_0)); - } -#endif - //Add IDLE 1 to task wdt -#ifdef CONFIG_ESP_TASK_WDT_CHECK_IDLE_TASK_CPU1 - TaskHandle_t idle_1 = xTaskGetIdleTaskHandleForCPU(1); - if(idle_1 != NULL){ - ESP_ERROR_CHECK(esp_task_wdt_add(idle_1)); - } -#endif - - app_main(); - vTaskDelete(NULL); -} - -// For now, running FreeRTOS on one core and a bare metal on the other (or other OSes) -// is not supported. For now CONFIG_FREERTOS_UNICORE and CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE -// should mirror each other's values. -// -// And since this should be true, we can just check for CONFIG_FREERTOS_UNICORE. -#if CONFIG_FREERTOS_UNICORE != CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - #error "FreeRTOS and system configuration mismatch regarding the use of multiple cores." -#endif - - #if !CONFIG_FREERTOS_UNICORE void esp_startup_start_app_other_cores(void) { @@ -581,33 +519,18 @@ void esp_startup_start_app_other_cores(void) xPortStartScheduler(); abort(); /* Only get to here if FreeRTOS somehow very broken */ } -#endif +#endif // !CONFIG_FREERTOS_UNICORE + +extern void esp_startup_start_app_common(void); void esp_startup_start_app(void) { -#if CONFIG_ESP_INT_WDT - esp_int_wdt_init(); - //Initialize the interrupt watch dog for CPU0. - esp_int_wdt_cpu_init(); -#else +#if !CONFIG_ESP_INT_WDT #if CONFIG_ESP32_ECO3_CACHE_LOCK_FIX assert(!soc_has_cache_lock_bug() && "ESP32 Rev 3 + Dual Core + PSRAM requires INT WDT enabled in project config!"); #endif #endif - esp_crosscore_int_init(); - -#ifndef CONFIG_FREERTOS_UNICORE -#if CONFIG_IDF_TARGET_ESP32 - esp_dport_access_int_init(); -#endif -#endif - - portBASE_TYPE res = xTaskCreatePinnedToCore(&main_task, "main", - ESP_TASK_MAIN_STACK, NULL, - ESP_TASK_MAIN_PRIO, NULL, 0); - assert(res == pdTRUE); - // ESP32 has single core variants. Check that FreeRTOS has been configured properly. #if CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE if (REG_GET_BIT(EFUSE_BLK0_RDATA3_REG, EFUSE_RD_CHIP_VER_DIS_APP_CPU)) { @@ -617,6 +540,8 @@ void esp_startup_start_app(void) } #endif // CONFIG_IDF_TARGET_ESP32 && !CONFIG_FREERTOS_UNICORE + esp_startup_start_app_common(); + ESP_LOGI(TAG, "Starting scheduler on PRO CPU."); vTaskStartScheduler(); } diff --git a/components/freertos/xtensa/portasm.S b/components/freertos/port/xtensa/portasm.S similarity index 100% rename from components/freertos/xtensa/portasm.S rename to components/freertos/port/xtensa/portasm.S diff --git a/components/freertos/xtensa/readme_xtensa.txt b/components/freertos/port/xtensa/readme_xtensa.txt similarity index 100% rename from components/freertos/xtensa/readme_xtensa.txt rename to components/freertos/port/xtensa/readme_xtensa.txt diff --git a/components/freertos/xtensa/xt_asm_utils.h b/components/freertos/port/xtensa/xt_asm_utils.h similarity index 100% rename from components/freertos/xtensa/xt_asm_utils.h rename to components/freertos/port/xtensa/xt_asm_utils.h diff --git a/components/freertos/xtensa/xtensa_context.S b/components/freertos/port/xtensa/xtensa_context.S similarity index 100% rename from components/freertos/xtensa/xtensa_context.S rename to components/freertos/port/xtensa/xtensa_context.S diff --git a/components/freertos/xtensa/xtensa_init.c b/components/freertos/port/xtensa/xtensa_init.c similarity index 100% rename from components/freertos/xtensa/xtensa_init.c rename to components/freertos/port/xtensa/xtensa_init.c diff --git a/components/freertos/xtensa/xtensa_loadstore_handler.S b/components/freertos/port/xtensa/xtensa_loadstore_handler.S similarity index 100% rename from components/freertos/xtensa/xtensa_loadstore_handler.S rename to components/freertos/port/xtensa/xtensa_loadstore_handler.S diff --git a/components/freertos/xtensa/xtensa_overlay_os_hook.c b/components/freertos/port/xtensa/xtensa_overlay_os_hook.c similarity index 100% rename from components/freertos/xtensa/xtensa_overlay_os_hook.c rename to components/freertos/port/xtensa/xtensa_overlay_os_hook.c diff --git a/components/freertos/xtensa/xtensa_vector_defaults.S b/components/freertos/port/xtensa/xtensa_vector_defaults.S similarity index 100% rename from components/freertos/xtensa/xtensa_vector_defaults.S rename to components/freertos/port/xtensa/xtensa_vector_defaults.S diff --git a/components/freertos/xtensa/xtensa_vectors.S b/components/freertos/port/xtensa/xtensa_vectors.S similarity index 100% rename from components/freertos/xtensa/xtensa_vectors.S rename to components/freertos/port/xtensa/xtensa_vectors.S diff --git a/components/freertos/test/test_float_in_isr.c b/components/freertos/test/test_float_in_isr.c index ff0dc675c4..3c2285dcf3 100644 --- a/components/freertos/test/test_float_in_isr.c +++ b/components/freertos/test/test_float_in_isr.c @@ -5,9 +5,7 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "esp_intr_alloc.h" -#include "xtensa/hal.h" #include "unity.h" #include "soc/cpu.h" #include "test_utils.h" diff --git a/components/freertos/test/test_freertos_backported_functions.c b/components/freertos/test/test_freertos_backported_functions.c index e56083ac09..ddaa359f2f 100644 --- a/components/freertos/test/test_freertos_backported_functions.c +++ b/components/freertos/test/test_freertos_backported_functions.c @@ -29,6 +29,7 @@ #include "unity.h" #include "test_utils.h" +#ifdef CONFIG_FREERTOS_SUPPORT_STATIC_ALLOCATION /* ---------------------Test 1: Backported Timer functions----------------------- * Test xTimerCreateStatic(), vTimerSetTimerId(), xTimerGetPeriod(), xTimerGetExpiryTime() * @@ -200,6 +201,7 @@ TEST_CASE("Test FreeRTOS backported eventgroup functions", "[freertos]") //Cleanup static event vEventGroupDelete(eg_handle); } +#endif /* --------Test backported thread local storage pointer and deletion cb feature---------- * vTaskSetThreadLocalStoragePointerAndDelCallback() diff --git a/components/freertos/test/test_freertos_isinisrcontext.c b/components/freertos/test/test_freertos_isinisrcontext.c index 14d317b0ef..8911733f8c 100644 --- a/components/freertos/test/test_freertos_isinisrcontext.c +++ b/components/freertos/test/test_freertos_isinisrcontext.c @@ -4,52 +4,52 @@ #include #include - +#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 } diff --git a/components/freertos/test/test_freertos_scheduling_time.c b/components/freertos/test/test_freertos_scheduling_time.c index f2e45f4be2..bee1e7ff11 100644 --- a/components/freertos/test/test_freertos_scheduling_time.c +++ b/components/freertos/test/test_freertos_scheduling_time.c @@ -4,9 +4,7 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "esp_intr_alloc.h" -#include "xtensa/hal.h" #include "unity.h" #include "soc/cpu.h" #include "test_utils.h" diff --git a/components/freertos/test/test_freertos_task_notify.c b/components/freertos/test/test_freertos_task_notify.c index 65af19d8de..812fdbd746 100644 --- a/components/freertos/test/test_freertos_task_notify.c +++ b/components/freertos/test/test_freertos_task_notify.c @@ -189,7 +189,7 @@ TEST_CASE("Test Task_Notify", "[freertos]") xSemaphoreGive(trigger_send_semphr); //Trigger sender task for(int k = 0; k < NO_OF_TASKS; k++){ //Wait for sender and receiver task deletion - xSemaphoreTake(task_delete_semphr, portMAX_DELAY); + TEST_ASSERT( xSemaphoreTake(task_delete_semphr, 1000 / portTICK_PERIOD_MS) ); } vTaskDelay(5); //Give time tasks to delete diff --git a/components/freertos/test/test_isr_latency.c b/components/freertos/test/test_isr_latency.c index 9c79519091..907dcbcf01 100644 --- a/components/freertos/test/test_isr_latency.c +++ b/components/freertos/test/test_isr_latency.c @@ -1,16 +1,26 @@ #include #include - +#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) diff --git a/components/freertos/test/test_newlib_reent.c b/components/freertos/test/test_newlib_reent.c index 17773cce55..ddc87e2c44 100644 --- a/components/freertos/test/test_newlib_reent.c +++ b/components/freertos/test/test_newlib_reent.c @@ -10,7 +10,6 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" volatile static int done; diff --git a/components/freertos/test/test_panic.c b/components/freertos/test/test_panic.c index 5f53ca305a..80cf7da4f7 100644 --- a/components/freertos/test/test_panic.c +++ b/components/freertos/test/test_panic.c @@ -9,7 +9,6 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" TEST_CASE("Panic handler", "[freertos][ignore]") diff --git a/components/freertos/test/test_preemption.c b/components/freertos/test/test_preemption.c index 9eeafa990c..62c44fd6cc 100644 --- a/components/freertos/test/test_preemption.c +++ b/components/freertos/test/test_preemption.c @@ -9,9 +9,9 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" #include "soc/cpu.h" +#include "hal/cpu_hal.h" #include "test_utils.h" #include "sdkconfig.h" @@ -31,7 +31,7 @@ static void task_send_to_queue(void *param) while(!trigger) {} - RSR(CCOUNT, ccount); + ccount = cpu_hal_get_cycle_count(); flag = true; xQueueSendToBack(queue, &ccount, 0); /* This is to ensure that higher priority task @@ -60,7 +60,7 @@ TEST_CASE("Yield from lower priority task, same CPU", "[freertos]") uint32_t yield_ccount, now_ccount, delta; TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) ); - RSR(CCOUNT, now_ccount); + now_ccount = cpu_hal_get_cycle_count(); TEST_ASSERT( flag ); delta = now_ccount - yield_ccount; @@ -92,12 +92,12 @@ TEST_CASE("Yield from lower priority task, other CPU", "[freertos]") vTaskDelay(2); /* make sure everything is set up */ trigger = true; - RSR(CCOUNT, trigger_ccount); + trigger_ccount = cpu_hal_get_cycle_count(); // yield_ccount is not useful in this test as it's the other core's CCOUNT // so we use trigger_ccount instead TEST_ASSERT( xQueueReceive(queue, &yield_ccount, 100 / portTICK_PERIOD_MS) ); - RSR(CCOUNT, now_ccount); + now_ccount = cpu_hal_get_cycle_count(); TEST_ASSERT( flag ); delta = now_ccount - trigger_ccount; diff --git a/components/freertos/test/test_spinlocks.c b/components/freertos/test/test_spinlocks.c index f41e7b37e7..ad89139315 100644 --- a/components/freertos/test/test_spinlocks.c +++ b/components/freertos/test/test_spinlocks.c @@ -9,9 +9,9 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" #include "soc/cpu.h" +#include "hal/cpu_hal.h" #include "test_utils.h" @@ -20,11 +20,11 @@ static uint32_t start, end; #define BENCHMARK_START() do { \ - RSR(CCOUNT, start); \ + start = cpu_hal_get_cycle_count(); \ } while(0) #define BENCHMARK_END(OPERATION) do { \ - RSR(CCOUNT, end); \ + end = cpu_hal_get_cycle_count(); \ printf("%s took %d cycles/op (%d cycles for %d ops)\n", \ OPERATION, (end - start)/REPEAT_OPS, \ (end - start), REPEAT_OPS); \ diff --git a/components/freertos/test/test_suspend_scheduler.c b/components/freertos/test/test_suspend_scheduler.c index 8817421273..63fecfce30 100644 --- a/components/freertos/test/test_suspend_scheduler.c +++ b/components/freertos/test/test_suspend_scheduler.c @@ -5,7 +5,6 @@ #include "freertos/task.h" #include "freertos/semphr.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" #include "soc/cpu.h" #include "test_utils.h" diff --git a/components/freertos/test/test_task_suspend_resume.c b/components/freertos/test/test_task_suspend_resume.c index 788ebd9b80..31ff29dba7 100644 --- a/components/freertos/test/test_task_suspend_resume.c +++ b/components/freertos/test/test_task_suspend_resume.c @@ -7,7 +7,6 @@ #include "freertos/semphr.h" #include "freertos/timers.h" #include "freertos/queue.h" -#include "freertos/xtensa_api.h" #include "unity.h" #include "soc/cpu.h" #include "test_utils.h" diff --git a/components/freertos/test/test_thread_local.c b/components/freertos/test/test_thread_local.c index 44ecc08168..96b6645d8b 100644 --- a/components/freertos/test/test_thread_local.c +++ b/components/freertos/test/test_thread_local.c @@ -11,6 +11,7 @@ #include "test_utils.h" #include "sdkconfig.h" +#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3) static __thread int tl_test_var1; static __thread uint8_t tl_test_var2 = 55; @@ -108,3 +109,4 @@ TEST_CASE("TLS test", "[freertos]") } vTaskDelay(10); /* Make sure idle task can clean up s_task, before it goes out of scope */ } +#endif // #if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32C3) diff --git a/components/freertos/test/test_xtensa_loadstore_handler.c b/components/freertos/test/test_xtensa_loadstore_handler.c index 6c386e16cb..4e436be63f 100644 --- a/components/freertos/test/test_xtensa_loadstore_handler.c +++ b/components/freertos/test/test_xtensa_loadstore_handler.c @@ -5,10 +5,13 @@ #include #include #include +#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 diff --git a/components/lwip/test_afl_host/Makefile b/components/lwip/test_afl_host/Makefile index 0d00a8e7f7..4d5e2e5d23 100644 --- a/components/lwip/test_afl_host/Makefile +++ b/components/lwip/test_afl_host/Makefile @@ -2,7 +2,7 @@ COMPONENTS_DIR=../.. COMPILER_ICLUDE_DIR=$(shell echo `which xtensa-esp32-elf-gcc | xargs dirname | xargs dirname`/xtensa-esp32-elf) CFLAGS=-std=gnu99 -Og -ggdb -ffunction-sections -fdata-sections -nostdlib -Wall -Werror=all -Wno-int-to-pointer-cast -Wno-error=unused-function -Wno-error=unused-variable -Wno-error=deprecated-declarations -Wno-macro-redefined -Wno-constant-conversion -Wno-incompatible-pointer-types-discards-qualifiers -Wno-typedef-redefinition -Wno-incompatible-pointer-types -Wextra \ -Wno-unused-parameter -Wno-sign-compare -Wno-address -Wno-unused-variable -DESP_PLATFORM -D IDF_VER=\"v3.1\" -MMD -MP -DWITH_POSIX -DLWIP_NO_CTYPE_H=1 -INC_DIRS=-I . -I ./build/config -I $(COMPONENTS_DIR)/newlib/platform_include -I $(COMPONENTS_DIR)/newlib/include -I $(COMPONENTS_DIR)/driver/include -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/ethernet/include -I $(COMPONENTS_DIR)/freertos/include -I $(COMPONENTS_DIR)/heap/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include -I $(COMPONENTS_DIR)/lwip/include/apps -I $(COMPONENTS_DIR)/lwip/lwip/src/include/netif -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/port/esp32/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/include/apps/ping -I $(COMPONENTS_DIR)/lwip/include/apps/sntp -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/tcpip_adapter/include -I $(COMPONENTS_DIR)/esp_rom/include -I $(COMPONENTS_DIR)/esp_common/include -I $(COMPONENTS_DIR)/esp_hw_support/include -I $(COMPONENTS_DIR)/xtensa/include -I $(COMPONENTS_DIR)/xtensa/esp32/include -I $(COMPONENTS_DIR)/esp_wifi/include -I $(COMPONENTS_DIR)/esp_event/include -I $(COMPONENTS_DIR)/freertos/xtensa/include -I $(COMPONENTS_DIR)/esp_system/include -I $(COMPONENTS_DIR)/esp_timer/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/src/esp32/include -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/esp_netif/include -I $(COMPONENTS_DIR)/esp_eth/include -I $(COMPONENTS_DIR)/esp_netif/lwip -I $(COMPONENTS_DIR)/hal/include -I $(COMPONENTS_DIR)/hal/esp32/include -I $(COMPILER_ICLUDE_DIR)/include +INC_DIRS=-I . -I ./build/config -I $(COMPONENTS_DIR)/newlib/platform_include -I $(COMPONENTS_DIR)/newlib/include -I $(COMPONENTS_DIR)/driver/include -I $(COMPONENTS_DIR)/esp32/include -I $(COMPONENTS_DIR)/ethernet/include -I $(COMPONENTS_DIR)/freertos/include -I $(COMPONENTS_DIR)/heap/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include -I $(COMPONENTS_DIR)/lwip/include/apps -I $(COMPONENTS_DIR)/lwip/lwip/src/include/netif -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/port/esp32/include -I $(COMPONENTS_DIR)/lwip/lwip/src/include/posix -I $(COMPONENTS_DIR)/lwip/include/apps/ping -I $(COMPONENTS_DIR)/lwip/include/apps/sntp -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/tcpip_adapter/include -I $(COMPONENTS_DIR)/esp_rom/include -I $(COMPONENTS_DIR)/esp_common/include -I $(COMPONENTS_DIR)/esp_hw_support/include -I $(COMPONENTS_DIR)/xtensa/include -I $(COMPONENTS_DIR)/xtensa/esp32/include -I $(COMPONENTS_DIR)/esp_wifi/include -I $(COMPONENTS_DIR)/esp_event/include -I $(COMPONENTS_DIR)/freertos/port/xtensa/include -I $(COMPONENTS_DIR)/esp_system/include -I $(COMPONENTS_DIR)/esp_timer/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/include -I $(COMPONENTS_DIR)/soc/src/esp32/include -I $(COMPONENTS_DIR)/soc/esp32/include -I $(COMPONENTS_DIR)/esp_netif/include -I $(COMPONENTS_DIR)/esp_eth/include -I $(COMPONENTS_DIR)/esp_netif/lwip -I $(COMPONENTS_DIR)/hal/include -I $(COMPONENTS_DIR)/hal/esp32/include -I $(COMPILER_ICLUDE_DIR)/include TEST_NAME=test FUZZ=afl-fuzz GEN_CFG=generate_config diff --git a/components/mdns/test_afl_fuzz_host/Makefile b/components/mdns/test_afl_fuzz_host/Makefile index 147bd1c054..4d2afd6143 100644 --- a/components/mdns/test_afl_fuzz_host/Makefile +++ b/components/mdns/test_afl_fuzz_host/Makefile @@ -18,7 +18,7 @@ CFLAGS=-g -Wno-unused-value -Wno-missing-declarations -Wno-pointer-bool-conversi -I$(COMPONENTS_DIR)/esp_system/include \ -I$(COMPONENTS_DIR)/esp_timer/include \ -I$(COMPONENTS_DIR)/esp_wifi/include \ - -I$(COMPONENTS_DIR)/freertos/xtensa/include \ + -I$(COMPONENTS_DIR)/freertos/port/xtensa/include \ -I$(COMPONENTS_DIR)/freertos \ -I$(COMPONENTS_DIR)/freertos/include \ -I$(COMPONENTS_DIR)/hal/include \ diff --git a/tools/ci/check_public_headers_exceptions.txt b/tools/ci/check_public_headers_exceptions.txt index 403f6953dd..70c084c922 100644 --- a/tools/ci/check_public_headers_exceptions.txt +++ b/tools/ci/check_public_headers_exceptions.txt @@ -7,7 +7,7 @@ components/xtensa/esp32/include/xtensa/config/ components/newlib/platform_include/ components/freertos/include/freertos/ -components/freertos/xtensa/include/freertos/ +components/freertos/port/xtensa/include/freertos/ components/log/include/esp_log_internal.h diff --git a/tools/ci/test_build_system.sh b/tools/ci/test_build_system.sh index 5c09a05e1b..780bda49f6 100755 --- a/tools/ci/test_build_system.sh +++ b/tools/ci/test_build_system.sh @@ -183,7 +183,7 @@ function run_tests() # and therefore should rebuild assert_rebuilt newlib/syscall_table.o assert_rebuilt nvs_flash/src/nvs_api.o - assert_rebuilt freertos/xtensa/xtensa_vectors.o + assert_rebuilt freertos/port/xtensa/xtensa_vectors.o print_status "Updating project Makefile triggers full recompile" make @@ -193,7 +193,7 @@ function run_tests() # similar to previous test assert_rebuilt newlib/syscall_table.o assert_rebuilt nvs_flash/src/nvs_api.o - assert_rebuilt freertos/xtensa/xtensa_vectors.o + assert_rebuilt freertos/port/xtensa/xtensa_vectors.o print_status "print_flash_cmd target should produce one line of output" make diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index daf7528678..d5d918ff9c 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -220,7 +220,7 @@ function run_tests() # and therefore should rebuild assert_rebuilt esp-idf/newlib/CMakeFiles/${IDF_COMPONENT_PREFIX}_newlib.dir/syscall_table.c.obj assert_rebuilt esp-idf/nvs_flash/CMakeFiles/${IDF_COMPONENT_PREFIX}_nvs_flash.dir/src/nvs_api.cpp.obj - assert_rebuilt esp-idf/freertos/CMakeFiles/${IDF_COMPONENT_PREFIX}_freertos.dir/xtensa/xtensa_vectors.S.obj + assert_rebuilt esp-idf/freertos/CMakeFiles/${IDF_COMPONENT_PREFIX}_freertos.dir/port/xtensa/xtensa_vectors.S.obj mv sdkconfig.bak sdkconfig print_status "Updating project CMakeLists.txt triggers full recompile" @@ -235,7 +235,7 @@ function run_tests() # similar to previous test assert_rebuilt esp-idf/newlib/CMakeFiles/${IDF_COMPONENT_PREFIX}_newlib.dir/syscall_table.c.obj assert_rebuilt esp-idf/nvs_flash/CMakeFiles/${IDF_COMPONENT_PREFIX}_nvs_flash.dir/src/nvs_api.cpp.obj - assert_rebuilt esp-idf/freertos/CMakeFiles/${IDF_COMPONENT_PREFIX}_freertos.dir/xtensa/xtensa_vectors.S.obj + assert_rebuilt esp-idf/freertos/CMakeFiles/${IDF_COMPONENT_PREFIX}_freertos.dir/port/xtensa/xtensa_vectors.S.obj mv sdkconfig.bak sdkconfig print_status "Can build with Ninja (no idf.py)" From 420aef1ffe3939dd553bd3e10a9d75201d6f925f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Fri, 6 Nov 2020 15:00:07 +1100 Subject: [PATCH 3/5] Updates for riscv support * Target components pull in xtensa component directly * Use CPU HAL where applicable * Remove unnecessary xtensa headers * Compilation changes necessary to support non-xtensa gcc types (ie int32_t/uint32_t is no longer signed/unsigned int). Changes come from internal branch commit a6723fc --- Kconfig | 11 ++ components/app_trace/app_trace.c | 2 + .../bootloader/subproject/CMakeLists.txt | 2 +- .../bootloader_support/src/bootloader_mem.c | 22 +--- .../bootloader_support/src/bootloader_panic.c | 6 +- .../src/bootloader_random.c | 7 +- components/esp-tls/esp_tls.c | 2 +- components/esp32/CMakeLists.txt | 4 +- components/esp32s2/CMakeLists.txt | 4 +- components/esp32s3/CMakeLists.txt | 4 +- components/esp_common/CMakeLists.txt | 5 +- components/esp_common/include/esp_err.h | 2 +- .../esp_common/include/esp_private/gdbstub.h | 10 +- components/esp_common/test/test_atomic.c | 7 +- components/esp_eth/include/esp_eth.h | 2 +- components/esp_eth/src/esp_eth.c | 3 +- components/esp_gdbstub/CMakeLists.txt | 4 +- components/esp_gdbstub/esp32/gdbstub_esp32.c | 2 +- .../esp_gdbstub/esp32s2/gdbstub_esp32s2.c | 2 +- components/esp_hw_support/compare_set.c | 10 ++ components/esp_hw_support/cpu_util.c | 19 +++ .../esp_hw_support/include/soc/compare_set.h | 21 ++- components/esp_hw_support/include/soc/cpu.h | 17 ++- .../esp_hw_support/include/soc/spinlock.h | 20 +-- components/esp_pm/pm_impl_riscv_temp.c | 19 +++ components/esp_ringbuf/ringbuf.c | 5 +- components/esp_system/intr_alloc.c | 6 +- components/esp_system/panic.c | 7 +- components/esp_system/port/CMakeLists.txt | 3 +- .../port/{ => arch/xtensa}/panic_handler.c | 10 +- .../{ => arch/xtensa}/panic_handler_asm.S | 0 components/esp_system/port/cpu_start.c | 18 ++- .../esp_system/port/esp32/CMakeLists.txt | 7 +- components/esp_system/port/esp32/component.mk | 2 +- .../esp_system/port/esp32s2/CMakeLists.txt | 8 +- .../esp_system/port/esp32s3/CMakeLists.txt | 8 +- components/esp_timer/src/esp_timer.c | 2 +- components/esp_timer/src/ets_timer_legacy.c | 1 - .../espcoredump/include/esp_core_dump.h | 1 - components/espcoredump/src/core_dump_port.c | 8 +- components/heap/multi_heap_platform.h | 3 +- components/log/log_freertos.c | 7 +- components/log/log_noos.c | 6 +- components/newlib/locks.c | 24 ++-- .../newlib/platform_include/sys/reent.h | 23 ++++ components/newlib/platform_include/time.h | 4 + components/newlib/reent_init.c | 6 - components/newlib/syscalls.c | 3 + components/newlib/test/test_time.c | 1 + components/newlib/time.c | 1 + components/soc/esp32/include/soc/soc.h | 5 +- components/soc/esp32/include/soc/soc_caps.h | 10 +- components/soc/esp32s2/include/soc/soc.h | 5 +- components/soc/esp32s2/include/soc/soc_caps.h | 12 +- components/spiffs/esp_spiffs.c | 2 +- components/spiffs/include/spiffs_config.h | 12 +- components/tinyusb/additions/src/tinyusb.c | 1 + components/unity/unity_port_esp32.c | 5 +- components/vfs/vfs.c | 1 + components/wear_levelling/CMakeLists.txt | 4 + components/wear_levelling/test/test_wl.c | 4 +- .../src/esp_supplicant/esp_wpa3.c | 8 +- components/wpa_supplicant/src/rsn_supp/wpa.c | 6 +- components/wpa_supplicant/src/rsn_supp/wpa.h | 4 +- components/wpa_supplicant/src/utils/common.h | 22 ++-- tools/cmake/build.cmake | 2 +- tools/find_build_apps/common.py | 1 + .../components/test_utils/CMakeLists.txt | 24 +++- .../components/test_utils/ccomp_timer.c | 9 -- .../test_utils/ccomp_timer_impl_riscv.c | 121 ++++++++++++++++++ ...timer_impl.c => ccomp_timer_impl_xtensa.c} | 0 ...{ref_clock.c => ref_clock_impl_rmt_pcnt.c} | 0 .../test_utils/ref_clock_impl_timergroup.c | 50 ++++++++ .../test_utils/test/ccomp_timer_test_api.c | 1 - .../test_utils/test/ccomp_timer_test_data.c | 1 - 75 files changed, 498 insertions(+), 183 deletions(-) create mode 100644 components/esp_pm/pm_impl_riscv_temp.c rename components/esp_system/port/{ => arch/xtensa}/panic_handler.c (99%) rename components/esp_system/port/{ => arch/xtensa}/panic_handler_asm.S (100%) create mode 100644 components/newlib/platform_include/sys/reent.h create mode 100644 tools/unit-test-app/components/test_utils/ccomp_timer_impl_riscv.c rename tools/unit-test-app/components/test_utils/{ccomp_timer_impl.c => ccomp_timer_impl_xtensa.c} (100%) rename tools/unit-test-app/components/test_utils/{ref_clock.c => ref_clock_impl_rmt_pcnt.c} (100%) create mode 100644 tools/unit-test-app/components/test_utils/ref_clock_impl_timergroup.c diff --git a/Kconfig b/Kconfig index 0e5d247d7d..9b230774b6 100644 --- a/Kconfig +++ b/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" diff --git a/components/app_trace/app_trace.c b/components/app_trace/app_trace.c index 6e67ea53a6..2895972b79 100644 --- a/components/app_trace/app_trace.c +++ b/components/app_trace/app_trace.c @@ -161,8 +161,10 @@ #if CONFIG_IDF_TARGET_ESP32S2 #include "soc/sensitive_reg.h" #endif +#if __XTENSA__ #include "eri.h" #include "trax.h" +#endif #include "soc/timer_periph.h" #include "freertos/FreeRTOS.h" #include "esp_app_trace.h" diff --git a/components/bootloader/subproject/CMakeLists.txt b/components/bootloader/subproject/CMakeLists.txt index f2151cb62d..383f3e80b7 100644 --- a/components/bootloader/subproject/CMakeLists.txt +++ b/components/bootloader/subproject/CMakeLists.txt @@ -30,7 +30,7 @@ set(COMPONENTS efuse) set(BOOTLOADER_BUILD 1) include("${IDF_PATH}/tools/cmake/project.cmake") -set(common_req log esp_rom esp_common esp_hw_support hal xtensa) +set(common_req log esp_rom esp_common esp_hw_support hal) if(LEGACY_INCLUDE_COMMON_HEADERS) list(APPEND common_req soc hal) endif() diff --git a/components/bootloader_support/src/bootloader_mem.c b/components/bootloader_support/src/bootloader_mem.c index 26840e6640..98990b74cd 100644 --- a/components/bootloader_support/src/bootloader_mem.c +++ b/components/bootloader_support/src/bootloader_mem.c @@ -14,35 +14,17 @@ #include -#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(); } diff --git a/components/bootloader_support/src/bootloader_panic.c b/components/bootloader_support/src/bootloader_panic.c index 637f2c968c..5136d7a02b 100644 --- a/components/bootloader_support/src/bootloader_panic.c +++ b/components/bootloader_support/src/bootloader_panic.c @@ -14,7 +14,7 @@ #include "esp_log.h" #include "bootloader_common.h" -#include "soc/cpu.h" +#include "hal/cpu_hal.h" #include "esp_rom_sys.h" @@ -30,8 +30,8 @@ void abort(void) #if !CONFIG_ESP_SYSTEM_PANIC_SILENT_REBOOT esp_rom_printf("abort() was called at PC 0x%08x\r\n", (intptr_t)__builtin_return_address(0) - 3); #endif - if (esp_cpu_in_ocd_debug_mode()) { - __asm__("break 0,0"); + if (cpu_hal_is_debugger_attached()) { + cpu_hal_break(); } while (1) { } diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index b7376bf15c..0d6873ef3d 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -13,7 +13,7 @@ // limitations under the License. #include "sdkconfig.h" #include "bootloader_random.h" -#include "soc/cpu.h" +#include "hal/cpu_hal.h" #include "soc/wdev_reg.h" #ifndef BOOTLOADER_BUILD @@ -44,13 +44,14 @@ values. */ random = REG_READ(WDEV_RND_REG); - RSR(CCOUNT, start); + start = cpu_hal_get_cycle_count(); do { random ^= REG_READ(WDEV_RND_REG); - RSR(CCOUNT, now); + now = cpu_hal_get_cycle_count(); } while (now - start < 80 * 32 * 2); /* extra factor of 2 is precautionary */ } buffer_bytes[i] = random >> ((i % 4) * 8); } } + #endif // BOOTLOADER_BUILD diff --git a/components/esp-tls/esp_tls.c b/components/esp-tls/esp_tls.c index d28a06c872..c8e94114a9 100644 --- a/components/esp-tls/esp_tls.c +++ b/components/esp-tls/esp_tls.c @@ -280,7 +280,7 @@ static int esp_tls_low_level_conn(const char *hostname, int hostlen, int port, c } if (FD_ISSET(tls->sockfd, &tls->rset) || FD_ISSET(tls->sockfd, &tls->wset)) { int error; - unsigned int len = sizeof(error); + socklen_t len = sizeof(error); /* pending error check */ if (getsockopt(tls->sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) { ESP_LOGD(TAG, "Non blocking connect failed"); diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt index d73d8a2cf2..fb8dad87df 100644 --- a/components/esp32/CMakeLists.txt +++ b/components/esp32/CMakeLists.txt @@ -7,7 +7,7 @@ idf_build_get_property(sdkconfig_header SDKCONFIG_HEADER) if(BOOTLOADER_BUILD) # For bootloader, all we need from esp32 is headers - idf_component_register(INCLUDE_DIRS include) + idf_component_register(INCLUDE_DIRS include REQUIRES xtensa) target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32.peripherals.ld") else() # Regular app build @@ -25,7 +25,7 @@ else() set(include_dirs "include") - set(requires driver efuse soc) #unfortunately rom/uart uses SOC registers directly + set(requires driver efuse soc xtensa) #unfortunately rom/uart uses SOC registers directly # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function. # esp_timer is added here because cpu_start.c uses esp_timer diff --git a/components/esp32s2/CMakeLists.txt b/components/esp32s2/CMakeLists.txt index ddbeb6bdce..7faf0e2d23 100644 --- a/components/esp32s2/CMakeLists.txt +++ b/components/esp32s2/CMakeLists.txt @@ -6,7 +6,7 @@ endif() if(BOOTLOADER_BUILD) # For bootloader, all we need from esp32s2 is headers - idf_component_register(INCLUDE_DIRS include) + idf_component_register(INCLUDE_DIRS include REQUIRES xtensa) target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32s2.peripherals.ld") else() # Regular app build @@ -26,7 +26,7 @@ else() set(include_dirs "include") - set(requires driver efuse) + set(requires driver efuse xtensa) # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function. # esp_timer is added here because cpu_start.c uses esp_timer diff --git a/components/esp32s3/CMakeLists.txt b/components/esp32s3/CMakeLists.txt index e1e0d31de0..ce87b35ed0 100644 --- a/components/esp32s3/CMakeLists.txt +++ b/components/esp32s3/CMakeLists.txt @@ -7,7 +7,7 @@ endif() if(BOOTLOADER_BUILD) # For bootloader, all we need from esp32s3 is headers - idf_component_register(INCLUDE_DIRS include) + idf_component_register(INCLUDE_DIRS include REQUIRES xtensa) target_linker_script(${COMPONENT_LIB} INTERFACE "ld/esp32s3.peripherals.ld") else() # Regular app build @@ -25,7 +25,7 @@ else() "system_api_esp32s3.c") set(include_dirs "include") - set(requires driver efuse soc) #unfortunately rom/uart uses SOC registers directly + set(requires driver efuse soc xtensa) #unfortunately rom/uart uses SOC registers directly # driver is a public requirement because esp_sleep.h uses gpio_num_t & touch_pad_t # app_update is added here because cpu_start.c uses esp_ota_get_app_description() function. diff --git a/components/esp_common/CMakeLists.txt b/components/esp_common/CMakeLists.txt index 991dc10579..27b1e9b01a 100644 --- a/components/esp_common/CMakeLists.txt +++ b/components/esp_common/CMakeLists.txt @@ -14,7 +14,6 @@ else() # Regular app build list(APPEND srcs "src/brownout.c" "src/esp_err.c" - "src/dbg_stubs.c" "src/esp_err_to_name.c" "src/freertos_hooks.c" "src/mac_addr.c" @@ -22,6 +21,10 @@ else() "src/task_wdt.c" "src/int_wdt.c") + if(NOT CONFIG_IDF_TARGET_ESP32C3) + list(APPEND srcs "src/dbg_stubs.c") + endif() + # Note: esp_ipc, esp_pm added as a public requirement to keep compatibility as to be located here. idf_component_register(SRCS "${srcs}" INCLUDE_DIRS include diff --git a/components/esp_common/include/esp_err.h b/components/esp_common/include/esp_err.h index 105723976d..49c3beb47a 100644 --- a/components/esp_common/include/esp_err.h +++ b/components/esp_common/include/esp_err.h @@ -21,7 +21,7 @@ extern "C" { #endif -typedef int32_t esp_err_t; +typedef int esp_err_t; /* Definitions for error constants. */ #define ESP_OK 0 /*!< esp_err_t value indicating success (no error) */ diff --git a/components/esp_common/include/esp_private/gdbstub.h b/components/esp_common/include/esp_private/gdbstub.h index 9e7243aad0..61c6cc8623 100644 --- a/components/esp_common/include/esp_private/gdbstub.h +++ b/components/esp_common/include/esp_private/gdbstub.h @@ -11,12 +11,10 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#ifndef GDBSTUB_H -#define GDBSTUB_H +#pragma once -#include -#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)); diff --git a/components/esp_common/test/test_atomic.c b/components/esp_common/test/test_atomic.c index 890c42dee0..743ad34e3b 100644 --- a/components/esp_common/test/test_atomic.c +++ b/components/esp_common/test/test_atomic.c @@ -2,13 +2,12 @@ #include #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 diff --git a/components/esp_eth/include/esp_eth.h b/components/esp_eth/include/esp_eth.h index deb6a4126a..76eff00b56 100644 --- a/components/esp_eth/include/esp_eth.h +++ b/components/esp_eth/include/esp_eth.h @@ -192,7 +192,7 @@ esp_err_t esp_eth_update_input_path( * - ESP_ERR_INVALID_ARG: transmit frame buffer failed because of some invalid argument * - ESP_FAIL: transmit frame buffer failed because some other error occurred */ -esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, uint32_t length); +esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length); /** * @brief General Receive diff --git a/components/esp_eth/src/esp_eth.c b/components/esp_eth/src/esp_eth.c index 4af0827299..d7b0a1671e 100644 --- a/components/esp_eth/src/esp_eth.c +++ b/components/esp_eth/src/esp_eth.c @@ -19,6 +19,7 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/timers.h" +#include "esp_heap_caps.h" static const char *TAG = "esp_eth"; #define ETH_CHECK(a, str, goto_tag, ret_value, ...) \ @@ -317,7 +318,7 @@ err: return ret; } -esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, uint32_t length) +esp_err_t esp_eth_transmit(esp_eth_handle_t hdl, void *buf, size_t length) { esp_err_t ret = ESP_OK; esp_eth_driver_t *eth_driver = (esp_eth_driver_t *)hdl; diff --git a/components/esp_gdbstub/CMakeLists.txt b/components/esp_gdbstub/CMakeLists.txt index 14528a4b52..74213d20a0 100644 --- a/components/esp_gdbstub/CMakeLists.txt +++ b/components/esp_gdbstub/CMakeLists.txt @@ -6,8 +6,8 @@ set(esp_gdbstub_srcs "src/gdbstub.c" "xtensa/gdbstub_xtensa.c") idf_component_register(SRCS "${esp_gdbstub_srcs}" - INCLUDE_DIRS "include" - PRIV_INCLUDE_DIRS "private_include" "${target}" "xtensa" + INCLUDE_DIRS "include" "xtensa" "${target}" + PRIV_INCLUDE_DIRS "private_include" LDFRAGMENTS "linker.lf" REQUIRES "freertos" PRIV_REQUIRES "soc" "xtensa" "esp_rom") diff --git a/components/esp_gdbstub/esp32/gdbstub_esp32.c b/components/esp_gdbstub/esp32/gdbstub_esp32.c index a3f87ca7bb..8981550e95 100644 --- a/components/esp_gdbstub/esp32/gdbstub_esp32.c +++ b/components/esp_gdbstub/esp32/gdbstub_esp32.c @@ -42,7 +42,7 @@ void esp_gdbstub_putchar(int c) int esp_gdbstub_readmem(intptr_t addr) { if (addr < 0x20000000 || addr >= 0x80000000) { - /* see cpu_configure_region_protection */ + /* see esp_cpu_configure_region_protection */ return -1; } uint32_t val_aligned = *(uint32_t *)(addr & (~3)); diff --git a/components/esp_gdbstub/esp32s2/gdbstub_esp32s2.c b/components/esp_gdbstub/esp32s2/gdbstub_esp32s2.c index 7bf60cf702..6c0ac46ffc 100644 --- a/components/esp_gdbstub/esp32s2/gdbstub_esp32s2.c +++ b/components/esp_gdbstub/esp32s2/gdbstub_esp32s2.c @@ -42,7 +42,7 @@ void esp_gdbstub_putchar(int c) int esp_gdbstub_readmem(intptr_t addr) { if (addr < 0x20000000 || addr >= 0x80000000) { - /* see cpu_configure_region_protection */ + /* see esp_cpu_configure_region_protection */ return -1; } uint32_t val_aligned = *(uint32_t *)(addr & (~3)); diff --git a/components/esp_hw_support/compare_set.c b/components/esp_hw_support/compare_set.c index 03871ca4ea..09487eb63f 100644 --- a/components/esp_hw_support/compare_set.c +++ b/components/esp_hw_support/compare_set.c @@ -13,6 +13,9 @@ // limitations under the License. #include "soc/compare_set.h" #include "soc/spinlock.h" +#include "soc/soc_caps.h" + +#if __XTENSA__ && SOC_SPIRAM_SUPPORTED static spinlock_t global_extram_lock = SPINLOCK_INITIALIZER; @@ -37,3 +40,10 @@ void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t *set = old_value; } +#else // __XTENSA__ && SOC_SPIRAM_SUPPORTED + +void compare_and_set_extram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) +{ + compare_and_set_native(addr, compare, set); +} +#endif // endif diff --git a/components/esp_hw_support/cpu_util.c b/components/esp_hw_support/cpu_util.c index a251c25b29..09b7c2a0c0 100644 --- a/components/esp_hw_support/cpu_util.c +++ b/components/esp_hw_support/cpu_util.c @@ -21,6 +21,7 @@ #include "hal/cpu_hal.h" #include "esp_debug_helpers.h" #include "hal/cpu_types.h" +#include "hal/mpu_hal.h" #include "hal/soc_hal.h" #include "soc/soc_caps.h" @@ -90,3 +91,21 @@ void IRAM_ATTR esp_set_breakpoint_if_jtag(void *fn) cpu_hal_set_breakpoint(0, fn); } } + +#if __XTENSA__ + +void esp_cpu_configure_region_protection(void) +{ + /* Note: currently this is configured the same on all Xtensa targets + * + * Both chips have the address space divided into 8 regions, 512MB each. + */ + const int illegal_regions[] = {0, 4, 5, 6, 7}; // 0x00000000, 0x80000000, 0xa0000000, 0xc0000000, 0xe0000000 + for (int i = 0; i < sizeof(illegal_regions) / sizeof(illegal_regions[0]); ++i) { + mpu_hal_set_region_access(illegal_regions[i], MPU_REGION_ILLEGAL); + } + + mpu_hal_set_region_access(1, MPU_REGION_RW); // 0x20000000 +} + +#endif diff --git a/components/esp_hw_support/include/soc/compare_set.h b/components/esp_hw_support/include/soc/compare_set.h index ddda35cc22..5a11ab166f 100644 --- a/components/esp_hw_support/include/soc/compare_set.h +++ b/components/esp_hw_support/include/soc/compare_set.h @@ -12,14 +12,16 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef __COMPARE_SET_H -#define __COMPARE_SET_H +#pragma once #include #include #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 diff --git a/components/esp_hw_support/include/soc/cpu.h b/components/esp_hw_support/include/soc/cpu.h index 77b4fcedda..441ced6b7f 100644 --- a/components/esp_hw_support/include/soc/cpu.h +++ b/components/esp_hw_support/include/soc/cpu.h @@ -18,11 +18,16 @@ #include #include #include + +#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 diff --git a/components/esp_hw_support/include/soc/spinlock.h b/components/esp_hw_support/include/soc/spinlock.h index 0135a2a6de..5370642a0b 100644 --- a/components/esp_hw_support/include/soc/spinlock.h +++ b/components/esp_hw_support/include/soc/spinlock.h @@ -11,15 +11,19 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#ifndef __SOC_SPINLOCK_H -#define __SOC_SPINLOCK_H +#pragma once #include #include +#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 diff --git a/components/esp_pm/pm_impl_riscv_temp.c b/components/esp_pm/pm_impl_riscv_temp.c new file mode 100644 index 0000000000..59c94b50d8 --- /dev/null +++ b/components/esp_pm/pm_impl_riscv_temp.c @@ -0,0 +1,19 @@ +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/* TODO ESP32-C3 Placeholder until IDF-2107 when this file can be dropped */ +void esp_pm_impl_waiti(void) +{ + +} diff --git a/components/esp_ringbuf/ringbuf.c b/components/esp_ringbuf/ringbuf.c index 92e15e562c..f8c62d03c7 100644 --- a/components/esp_ringbuf/ringbuf.c +++ b/components/esp_ringbuf/ringbuf.c @@ -20,8 +20,9 @@ #include "freertos/ringbuf.h" //32-bit alignment macros -#define rbALIGN_SIZE( xSize ) ( ( xSize + portBYTE_ALIGNMENT_MASK ) & ~portBYTE_ALIGNMENT_MASK ) -#define rbCHECK_ALIGNED( pvPtr ) ( ( ( UBaseType_t ) ( pvPtr ) & portBYTE_ALIGNMENT_MASK ) == 0 ) +#define rbALIGN_MASK (0x03) +#define rbALIGN_SIZE( xSize ) ( ( xSize + rbALIGN_MASK ) & ~rbALIGN_MASK ) +#define rbCHECK_ALIGNED( pvPtr ) ( ( ( UBaseType_t ) ( pvPtr ) & rbALIGN_MASK ) == 0 ) //Ring buffer flags #define rbALLOW_SPLIT_FLAG ( ( UBaseType_t ) 1 ) //The ring buffer allows items to be split diff --git a/components/esp_system/intr_alloc.c b/components/esp_system/intr_alloc.c index 232a1f1100..603138b23b 100644 --- a/components/esp_system/intr_alloc.c +++ b/components/esp_system/intr_alloc.c @@ -531,7 +531,7 @@ esp_err_t esp_intr_alloc_intrstatus(int source, int flags, uint32_t intrstatusre vd->shared_vec_info=sh_vec; vd->flags|=VECDESC_FL_SHARED; //(Re-)set shared isr handler to new value. - xt_set_interrupt_handler(intr, shared_intr_isr, vd); + interrupt_controller_hal_set_int_handler(intr, shared_intr_isr, vd); } else { //Mark as unusable for other interrupt sources. This is ours now! vd->flags=VECDESC_FL_NONSHARED; @@ -801,11 +801,11 @@ void IRAM_ATTR esp_intr_noniram_enable(void) //equivalents here. -void IRAM_ATTR ets_isr_unmask(unsigned int mask) { +void IRAM_ATTR ets_isr_unmask(uint32_t mask) { interrupt_controller_hal_enable_interrupts(mask); } -void IRAM_ATTR ets_isr_mask(unsigned int mask) { +void IRAM_ATTR ets_isr_mask(uint32_t mask) { interrupt_controller_hal_disable_interrupts(mask); } diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 2c3781d66f..4085be6bcb 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -17,7 +17,6 @@ #include "esp_attr.h" #include "esp_private/system_internal.h" -#include "esp_private/gdbstub.h" #include "esp_private/usb_console.h" #include "esp_ota_ops.h" @@ -53,6 +52,10 @@ #define APPTRACE_ONPANIC_HOST_FLUSH_TMO (1000*CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) #endif +#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 +294,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; diff --git a/components/esp_system/port/CMakeLists.txt b/components/esp_system/port/CMakeLists.txt index 976b568b2f..c53c2aeaa8 100644 --- a/components/esp_system/port/CMakeLists.txt +++ b/components/esp_system/port/CMakeLists.txt @@ -1,6 +1,7 @@ target_include_directories(${COMPONENT_LIB} PRIVATE include) -set(srcs "panic_handler.c" "panic_handler_asm.S" "cpu_start.c") +set(srcs "cpu_start.c") + add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/arch/xtensa/panic_handler.c similarity index 99% rename from components/esp_system/port/panic_handler.c rename to components/esp_system/port/arch/xtensa/panic_handler.c index 314ab2d206..76975d8c55 100644 --- a/components/esp_system/port/panic_handler.c +++ b/components/esp_system/port/arch/xtensa/panic_handler.c @@ -35,18 +35,21 @@ #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/rom/uart.h" #elif CONFIG_IDF_TARGET_ESP32S2 #include "esp32s2/cache_err_int.h" +#include "esp32s2/rom/uart.h" #include "esp32s2/memprot.h" #include "soc/extmem_reg.h" #include "soc/cache_memory.h" #include "soc/rtc_cntl_reg.h" #elif CONFIG_IDF_TARGET_ESP32S3 #include "esp32s3/cache_err_int.h" +#include "esp32s3/rom/uart.h" #include "esp32s3/memprot.h" #include "soc/extmem_reg.h" #include "soc/cache_memory.h" @@ -187,7 +190,6 @@ 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 ", @@ -201,9 +203,9 @@ static void print_registers(const void *f, int core) panic_print_dec(core); panic_print_str(" register dump:"); - for (x = 0; x < 24; x += 4) { + for (int x = 0; x < 24; x += 4) { panic_print_str("\r\n"); - for (y = 0; y < 4; y++) { + for (int y = 0; y < 4; y++) { if (sdesc[x + y][0] != 0) { panic_print_str(sdesc[x + y]); panic_print_str(": 0x"); diff --git a/components/esp_system/port/panic_handler_asm.S b/components/esp_system/port/arch/xtensa/panic_handler_asm.S similarity index 100% rename from components/esp_system/port/panic_handler_asm.S rename to components/esp_system/port/arch/xtensa/panic_handler_asm.S diff --git a/components/esp_system/port/cpu_start.c b/components/esp_system/port/cpu_start.c index f3c9091012..43209c267b 100644 --- a/components/esp_system/port/cpu_start.c +++ b/components/esp_system/port/cpu_start.c @@ -71,7 +71,9 @@ #include "soc/rtc.h" #include "soc/spinlock.h" +#if CONFIG_ESP32_TRAX || CONFIG_ESP32S2_TRAX #include "trax.h" +#endif #include "bootloader_mem.h" @@ -219,7 +221,7 @@ static void start_other_core(void) static void intr_matrix_clear(void) { - for (int i = ETS_WIFI_MAC_INTR_SOURCE; i < ETS_MAX_INTR_SOURCE; i++) { + for (int i = 0; i < ETS_MAX_INTR_SOURCE; i++) { intr_matrix_set(0, i, ETS_INVALID_INUM); #if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE intr_matrix_set(1, i, ETS_INVALID_INUM); @@ -239,6 +241,18 @@ void IRAM_ATTR call_start_cpu0(void) RESET_REASON rst_reas[1]; #endif +#ifdef __riscv + // Configure the global pointer register + // (This should be the first thing IDF app does, as any other piece of code could be + // relaxed by the linker to access something relative to __global_pointer$) + __asm__ __volatile__ ( + ".option push\n" + ".option norelax\n" + "la gp, __global_pointer$\n" + ".option pop" + ); +#endif + // Move exception vectors to IRAM cpu_hal_set_vecbase(&_init_start); @@ -361,7 +375,6 @@ void IRAM_ATTR call_start_cpu0(void) } #endif -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #if CONFIG_SPIRAM_FETCH_INSTRUCTIONS extern void instruction_flash_page_info_init(void); instruction_flash_page_info_init(); @@ -391,7 +404,6 @@ void IRAM_ATTR call_start_cpu0(void) extern void esp_enable_cache_wrap(uint32_t icache_wrap_enable, uint32_t dcache_wrap_enable); esp_enable_cache_wrap(icache_wrap_enable, dcache_wrap_enable); #endif -#endif // CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 #if CONFIG_SPIRAM_ALLOW_BSS_SEG_EXTERNAL_MEMORY memset(&_ext_ram_bss_start, 0, (&_ext_ram_bss_end - &_ext_ram_bss_start) * sizeof(_ext_ram_bss_start)); diff --git a/components/esp_system/port/esp32/CMakeLists.txt b/components/esp_system/port/esp32/CMakeLists.txt index 76d7ca5130..f1ddfe3d05 100644 --- a/components/esp_system/port/esp32/CMakeLists.txt +++ b/components/esp_system/port/esp32/CMakeLists.txt @@ -1,4 +1,9 @@ -set(srcs "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c") +set(srcs "dport_panic_highint_hdl.S" + "clk.c" + "reset_reason.c" + "../arch/xtensa/panic_handler.c" + "../arch/xtensa/panic_handler_asm.S" + ) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_system/port/esp32/component.mk b/components/esp_system/port/esp32/component.mk index 3508f48a9e..88dd942940 100644 --- a/components/esp_system/port/esp32/component.mk +++ b/components/esp_system/port/esp32/component.mk @@ -1,2 +1,2 @@ -COMPONENT_SRCDIRS += port port/esp32 +COMPONENT_SRCDIRS += port port/esp32 port/arch/xtensa COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o diff --git a/components/esp_system/port/esp32s2/CMakeLists.txt b/components/esp_system/port/esp32s2/CMakeLists.txt index 0d93b7b0a3..ee8643a087 100644 --- a/components/esp_system/port/esp32s2/CMakeLists.txt +++ b/components/esp_system/port/esp32s2/CMakeLists.txt @@ -1,4 +1,10 @@ -set(srcs "async_memcpy_impl_cp_dma.c" "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c") +set(srcs "async_memcpy_impl_cp_dma.c" + "dport_panic_highint_hdl.S" + "clk.c" + "reset_reason.c" + "../arch/xtensa/panic_handler.c" + "../arch/xtensa/panic_handler_asm.S" + ) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_system/port/esp32s3/CMakeLists.txt b/components/esp_system/port/esp32s3/CMakeLists.txt index 3726d76e29..6bfc1d5a86 100644 --- a/components/esp_system/port/esp32s3/CMakeLists.txt +++ b/components/esp_system/port/esp32s3/CMakeLists.txt @@ -1,4 +1,10 @@ -set(srcs "../async_memcpy_impl_gdma.c" "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c") +set(srcs "dport_panic_highint_hdl.S" + "clk.c" + "reset_reason.c" + "../async_memcpy_impl_gdma.c" + "../arch/xtensa/panic_handler.c" + "../arch/xtensa/panic_handler_asm.S" + ) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) target_sources(${COMPONENT_LIB} PRIVATE ${srcs}) diff --git a/components/esp_timer/src/esp_timer.c b/components/esp_timer/src/esp_timer.c index 18802197ea..d3ccb4f59a 100644 --- a/components/esp_timer/src/esp_timer.c +++ b/components/esp_timer/src/esp_timer.c @@ -22,7 +22,7 @@ #include "esp_log.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/xtensa_api.h" +#include "freertos/semphr.h" #include "soc/spinlock.h" #include "esp_timer.h" #include "esp_timer_impl.h" diff --git a/components/esp_timer/src/ets_timer_legacy.c b/components/esp_timer/src/ets_timer_legacy.c index 15e6617f81..fc7f624280 100644 --- a/components/esp_timer/src/ets_timer_legacy.c +++ b/components/esp_timer/src/ets_timer_legacy.c @@ -27,7 +27,6 @@ #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" -#include "freertos/xtensa_api.h" #include "sdkconfig.h" #include "esp_timer.h" #if CONFIG_IDF_TARGET_ESP32 diff --git a/components/espcoredump/include/esp_core_dump.h b/components/espcoredump/include/esp_core_dump.h index 2a6c109324..24a13e5d86 100644 --- a/components/espcoredump/include/esp_core_dump.h +++ b/components/espcoredump/include/esp_core_dump.h @@ -16,7 +16,6 @@ #include #include "esp_err.h" -#include "freertos/xtensa_context.h" #include "esp_private/panic_internal.h" /**************************************************************************************/ diff --git a/components/espcoredump/src/core_dump_port.c b/components/espcoredump/src/core_dump_port.c index 5033ba8d5e..7be3f5beec 100644 --- a/components/espcoredump/src/core_dump_port.c +++ b/components/espcoredump/src/core_dump_port.c @@ -16,8 +16,14 @@ #include "soc/soc_memory_layout.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" -#include "freertos/xtensa_context.h" // for exception register stack structure #include "esp_core_dump_priv.h" + +#if __XTENSA__ +#include "freertos/xtensa_context.h" +#else // __XTENSA__ +#define XCHAL_NUM_AREGS 64 // TODO-ESP32C3 coredump support IDF-1758 +#endif // __XTENSA__ + #include "esp_rom_sys.h" const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port"; diff --git a/components/heap/multi_heap_platform.h b/components/heap/multi_heap_platform.h index 2d3ed00314..24a1719af7 100644 --- a/components/heap/multi_heap_platform.h +++ b/components/heap/multi_heap_platform.h @@ -15,7 +15,8 @@ #ifdef MULTI_HEAP_FREERTOS -#include +#include "freertos/FreeRTOS.h" + #include "sdkconfig.h" #include "esp_rom_sys.h" #if CONFIG_IDF_TARGET_ESP32 diff --git a/components/log/log_freertos.c b/components/log/log_freertos.c index e619944df2..2a14dcb4f5 100644 --- a/components/log/log_freertos.c +++ b/components/log/log_freertos.c @@ -103,9 +103,14 @@ uint32_t esp_log_timestamp(void) return base + tick_count * (1000 / configTICK_RATE_HZ); } -/* FIXME: define an API for getting the timestamp in soc/hal */ +/* FIXME: define an API for getting the timestamp in soc/hal IDF-2351 */ uint32_t esp_log_early_timestamp(void) { +#if CONFIG_IDF_TARGET_ESP32 + /* ESP32 ROM stores separate clock rate values for each CPU, but we want the PRO CPU value always */ extern uint32_t g_ticks_per_us_pro; return esp_cpu_get_ccount() / (g_ticks_per_us_pro * 1000); +#else + return esp_cpu_get_ccount() / (ets_get_cpu_frequency() * 1000); +#endif } diff --git a/components/log/log_noos.c b/components/log/log_noos.c index cf755839bf..f1fbdb8f3a 100644 --- a/components/log/log_noos.c +++ b/components/log/log_noos.c @@ -36,11 +36,11 @@ void esp_log_impl_unlock(void) s_lock = 0; } -/* FIXME: define an API for getting the timestamp in soc/hal */ +/* FIXME: define an API for getting the timestamp in soc/hal IDF-2351 */ uint32_t esp_log_early_timestamp(void) { - extern uint32_t g_ticks_per_us_pro; - return esp_cpu_get_ccount() / (g_ticks_per_us_pro * 1000); + extern uint32_t ets_get_cpu_frequency(void); + return esp_cpu_get_ccount() / (ets_get_cpu_frequency() * 1000); } uint32_t esp_log_timestamp(void) __attribute__((alias("esp_log_early_timestamp"))); diff --git a/components/newlib/locks.c b/components/newlib/locks.c index f50c650526..e3e9915fe3 100644 --- a/components/newlib/locks.c +++ b/components/newlib/locks.c @@ -21,6 +21,7 @@ #include "freertos/semphr.h" #include "freertos/task.h" #include "freertos/portable.h" +#include "esp_heap_caps.h" /* Notes on our newlib lock implementation: * @@ -48,12 +49,6 @@ static portMUX_TYPE lock_init_spinlock = portMUX_INITIALIZER_UNLOCKED; */ static void IRAM_ATTR lock_init_generic(_lock_t *lock, uint8_t mutex_type) { portENTER_CRITICAL(&lock_init_spinlock); - if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { - /* nothing to do until the scheduler is running */ - portEXIT_CRITICAL(&lock_init_spinlock); - return; - } - if (*lock) { /* Lock already initialised (either we didn't check earlier, or it got initialised while we were waiting for the @@ -124,17 +119,20 @@ void _lock_close_recursive(_lock_t *lock) __attribute__((alias("_lock_close"))); */ static int IRAM_ATTR lock_acquire_generic(_lock_t *lock, uint32_t delay, uint8_t mutex_type) { xSemaphoreHandle h = (xSemaphoreHandle)(*lock); + if (!h) { if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { return 0; /* locking is a no-op before scheduler is up, so this "succeeds" */ } - /* lazy initialise lock - might have had a static initializer in newlib (that we don't use), - or _lock_init might have been called before the scheduler was running... */ + /* lazy initialise lock - might have had a static initializer (that we don't use) */ lock_init_generic(lock, mutex_type); h = (xSemaphoreHandle)(*lock); configASSERT(h != NULL); } + if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { + return 0; /* locking is a no-op before scheduler is up, so this "succeeds" */ + } BaseType_t success; if (!xPortCanYield()) { /* In ISR Context */ @@ -182,13 +180,11 @@ int IRAM_ATTR _lock_try_acquire_recursive(_lock_t *lock) { mutex_type is queueQUEUE_TYPE_RECURSIVE_MUTEX or queueQUEUE_TYPE_MUTEX */ static void IRAM_ATTR lock_release_generic(_lock_t *lock, uint8_t mutex_type) { - xSemaphoreHandle h = (xSemaphoreHandle)(*lock); - if (h == NULL) { - /* This is probably because the scheduler isn't running yet, - or the scheduler just started running and some code was - "holding" a not-yet-initialised lock... */ - return; + if (xTaskGetSchedulerState() == taskSCHEDULER_NOT_STARTED) { + return; /* locking is a no-op before scheduler is up */ } + xSemaphoreHandle h = (xSemaphoreHandle)(*lock); + assert(h); if (!xPortCanYield()) { if (mutex_type == queueQUEUE_TYPE_RECURSIVE_MUTEX) { diff --git a/components/newlib/platform_include/sys/reent.h b/components/newlib/platform_include/sys/reent.h new file mode 100644 index 0000000000..f58eb0ed6d --- /dev/null +++ b/components/newlib/platform_include/sys/reent.h @@ -0,0 +1,23 @@ +// 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. + +#pragma once + +#include_next + +/* This function is not part of the newlib API, it is defined in libc/stdio/local.h + * There is no nice way to get __cleanup member populated while avoiding __sinit, + * so extern declaration is used here. + */ +extern void _cleanup_r(struct _reent* r); diff --git a/components/newlib/platform_include/time.h b/components/newlib/platform_include/time.h index e633bd4ec0..bbffaad8b9 100644 --- a/components/newlib/platform_include/time.h +++ b/components/newlib/platform_include/time.h @@ -22,8 +22,12 @@ extern "C" { #include_next #define _POSIX_TIMERS 1 +#ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (clockid_t)4 +#endif +#ifndef CLOCK_BOOTTIME #define CLOCK_BOOTTIME (clockid_t)4 +#endif int clock_settime(clockid_t clock_id, const struct timespec *tp); int clock_gettime(clockid_t clock_id, struct timespec *tp); diff --git a/components/newlib/reent_init.c b/components/newlib/reent_init.c index 11e4c58a7b..1e74e548f0 100644 --- a/components/newlib/reent_init.c +++ b/components/newlib/reent_init.c @@ -19,12 +19,6 @@ #include #include "esp_attr.h" -/* This function is not part on newlib API, it is defined in libc/stdio/local.h - * There is no nice way to get __cleanup member populated while avoiding __sinit, - * so extern declaration is used here. - */ -extern void _cleanup_r(struct _reent* r); - /** * This is the replacement for newlib's _REENT_INIT_PTR and __sinit. * The problem with __sinit is that it allocates three FILE structures diff --git a/components/newlib/syscalls.c b/components/newlib/syscalls.c index faa5828b6e..d6c3098592 100644 --- a/components/newlib/syscalls.c +++ b/components/newlib/syscalls.c @@ -100,6 +100,9 @@ int _unlink_r(struct _reent *r, const char *path) __attribute__((weak,alias("syscall_not_implemented"))); int _rename_r(struct _reent *r, const char *src, const char *dst) __attribute__((weak,alias("syscall_not_implemented"))); +int _isatty_r(struct _reent *r, int fd) + __attribute__((weak,alias("syscall_not_implemented"))); + /* These functions are not expected to be overridden */ int system(const char* str) diff --git a/components/newlib/test/test_time.c b/components/newlib/test/test_time.c index 5887337e66..361cba9b33 100644 --- a/components/newlib/test/test_time.c +++ b/components/newlib/test/test_time.c @@ -15,6 +15,7 @@ #include "esp_log.h" #include "esp_rom_sys.h" #include "esp_system.h" +#include "esp_timer.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/clk.h" diff --git a/components/newlib/time.c b/components/newlib/time.c index 4073d02af0..a021d15eee 100644 --- a/components/newlib/time.c +++ b/components/newlib/time.c @@ -25,6 +25,7 @@ #include "esp_system.h" #include "esp_attr.h" +#include "esp_rom_sys.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" diff --git a/components/soc/esp32/include/soc/soc.h b/components/soc/esp32/include/soc/soc.h index a707c8afd8..17d06eb701 100644 --- a/components/soc/esp32/include/soc/soc.h +++ b/components/soc/esp32/include/soc/soc.h @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef _ESP32_SOC_H_ -#define _ESP32_SOC_H_ +#pragma once #ifndef __ASSEMBLER__ #include @@ -414,5 +413,3 @@ //Invalid interrupt for number interrupt matrix #define ETS_INVALID_INUM 6 - -#endif /* _ESP32_SOC_H_ */ diff --git a/components/soc/esp32/include/soc/soc_caps.h b/components/soc/esp32/include/soc/soc_caps.h index b882876526..59e36c5485 100644 --- a/components/soc/esp32/include/soc/soc_caps.h +++ b/components/soc/esp32/include/soc/soc_caps.h @@ -135,6 +135,9 @@ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_HS_MODE (1) +#define SOC_LEDC_SUPPORT_HS_MODE (1) +#define SOC_LEDC_CHANNEL_NUM (8) +#define SOC_LEDC_TIMER_BIT_WIDE_NUM (20) /*-------------------------- MCPWM CAPS --------------------------------------*/ #define SOC_MCPWM_PERIPH_NUM 2 ///< MCPWM peripheral number @@ -170,7 +173,7 @@ #define SOC_RTCIO_PIN_COUNT 18 /*-------------------------- SIGMA DELTA CAPS --------------------------------*/ -#define SOC_SIGMADELTA_NUM (1) // 1 sigma-delta peripheral +#define SOC_SIGMADELTA_NUM 1 #define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels /*-------------------------- SPI CAPS ----------------------------------------*/ @@ -192,9 +195,10 @@ /*-------------------------- TIMER GROUP CAPS --------------------------------*/ #define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (64) #define SOC_TIMER_GROUP_PRESCALE_BIT_WIDTH (16) -#define SOC_TIMER_GROUPS (2) -#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2) +#define SOC_TIMER_GROUPS (2) +#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2) #define SOC_TIMER_GROUP_TOTAL_TIMERS (SOC_TIMER_GROUPS * SOC_TIMER_GROUP_TIMERS_PER_GROUP) +#define SOC_TIMER_GROUP_LAYOUT {2,2} /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_NUM (10) diff --git a/components/soc/esp32s2/include/soc/soc.h b/components/soc/esp32s2/include/soc/soc.h index a1ff1edade..6325f311d7 100644 --- a/components/soc/esp32s2/include/soc/soc.h +++ b/components/soc/esp32s2/include/soc/soc.h @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#ifndef _ESP32_SOC_H_ -#define _ESP32_SOC_H_ +#pragma once #ifndef __ASSEMBLER__ #include @@ -359,5 +358,3 @@ //Invalid interrupt for number interrupt matrix #define ETS_INVALID_INUM 6 - -#endif /* _ESP32_SOC_H_ */ diff --git a/components/soc/esp32s2/include/soc/soc_caps.h b/components/soc/esp32s2/include/soc/soc_caps.h index f8a9b5205b..6adc7587e0 100644 --- a/components/soc/esp32s2/include/soc/soc_caps.h +++ b/components/soc/esp32s2/include/soc/soc_caps.h @@ -127,6 +127,8 @@ /*-------------------------- LEDC CAPS ---------------------------------------*/ #define SOC_LEDC_SUPPORT_XTAL_CLOCK (1) +#define SOC_LEDC_CHANNEL_NUM (8) +#define SOC_LEDC_TIMER_BIT_WIDE_NUM (14) /*-------------------------- MPU CAPS ----------------------------------------*/ //TODO: correct the caller and remove unsupported lines @@ -158,7 +160,7 @@ #define SOC_RTCIO_PIN_COUNT 22 /*-------------------------- SIGMA DELTA CAPS --------------------------------*/ -#define SOC_SIGMADELTA_NUM (1) // 1 sigma-delta peripheral +#define SOC_SIGMADELTA_NUM 1 #define SOC_SIGMADELTA_CHANNEL_NUM (8) // 8 channels /*-------------------------- SPI CAPS ----------------------------------------*/ @@ -194,12 +196,14 @@ #define SOC_SYSTIMER_BIT_WIDTH_HI (32) // Bit width of systimer high part /*-------------------------- TIMER GROUP CAPS --------------------------------*/ -#define SOC_TIMER_GROUP_SUPPORT_XTAL (1) +#define SOC_TIMER_GROUP_SUPPORT_XTAL (1) +#define SOC_TIMER_GROUP_XTAL_MHZ (40) #define SOC_TIMER_GROUP_COUNTER_BIT_WIDTH (64) #define SOC_TIMER_GROUP_PRESCALE_BIT_WIDTH (16) -#define SOC_TIMER_GROUPS (2) -#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2) +#define SOC_TIMER_GROUPS (2) +#define SOC_TIMER_GROUP_TIMERS_PER_GROUP (2) #define SOC_TIMER_GROUP_TOTAL_TIMERS (SOC_TIMER_GROUPS * SOC_TIMER_GROUP_TIMERS_PER_GROUP) +#define SOC_TIMER_GROUP_LAYOUT {2,2} /*-------------------------- TOUCH SENSOR CAPS -------------------------------*/ #define SOC_TOUCH_SENSOR_NUM (15) /*! 15 Touch channels */ diff --git a/components/spiffs/esp_spiffs.c b/components/spiffs/esp_spiffs.c index c0205ba8ef..92ef3aa18d 100644 --- a/components/spiffs/esp_spiffs.c +++ b/components/spiffs/esp_spiffs.c @@ -275,7 +275,7 @@ esp_err_t esp_spiffs_info(const char* partition_label, size_t *total_bytes, size if (esp_spiffs_by_label(partition_label, &index) != ESP_OK) { return ESP_ERR_INVALID_STATE; } - SPIFFS_info(_efs[index]->fs, total_bytes, used_bytes); + SPIFFS_info(_efs[index]->fs, (uint32_t *)total_bytes, (uint32_t *)used_bytes); return ESP_OK; } diff --git a/components/spiffs/include/spiffs_config.h b/components/spiffs/include/spiffs_config.h index a382ba6f95..ca7f0cc6fb 100644 --- a/components/spiffs/include/spiffs_config.h +++ b/components/spiffs/include/spiffs_config.h @@ -51,12 +51,12 @@ #endif // needed types -typedef signed int s32_t; -typedef unsigned int u32_t; -typedef signed short s16_t; -typedef unsigned short u16_t; -typedef signed char s8_t; -typedef unsigned char u8_t; +typedef int32_t s32_t; +typedef uint32_t u32_t; +typedef int16_t s16_t; +typedef uint16_t u16_t; +typedef int8_t s8_t; +typedef uint8_t u8_t; struct spiffs_t; extern void spiffs_api_lock(struct spiffs_t *fs); diff --git a/components/tinyusb/additions/src/tinyusb.c b/components/tinyusb/additions/src/tinyusb.c index e2fd061fc7..967058d372 100644 --- a/components/tinyusb/additions/src/tinyusb.c +++ b/components/tinyusb/additions/src/tinyusb.c @@ -28,6 +28,7 @@ #include "tusb.h" #include "tusb_tasks.h" #include "sdkconfig.h" +#include "esp_rom_gpio.h" const static char *TAG = "TinyUSB"; diff --git a/components/unity/unity_port_esp32.c b/components/unity/unity_port_esp32.c index f85aa503ab..ce2112f1de 100644 --- a/components/unity/unity_port_esp32.c +++ b/components/unity/unity_port_esp32.c @@ -15,6 +15,7 @@ #include "unity.h" #include "sdkconfig.h" #include "soc/cpu.h" +#include "hal/cpu_hal.h" #include "esp_rom_uart.h" #if CONFIG_IDF_TARGET_ESP32 #include "esp32/clk.h" @@ -75,12 +76,12 @@ void unity_gets(char *dst, size_t len) void unity_exec_time_start(void) { - RSR(CCOUNT, s_test_start); + s_test_start = cpu_hal_get_cycle_count(); } void unity_exec_time_stop(void) { - RSR(CCOUNT, s_test_stop); + s_test_stop = cpu_hal_get_cycle_count(); } uint32_t unity_exec_time_get_ms(void) diff --git a/components/vfs/vfs.c b/components/vfs/vfs.c index fc8c70b939..fbf4d90566 100644 --- a/components/vfs/vfs.c +++ b/components/vfs/vfs.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include diff --git a/components/wear_levelling/CMakeLists.txt b/components/wear_levelling/CMakeLists.txt index e5d39463be..e7e2022b8b 100644 --- a/components/wear_levelling/CMakeLists.txt +++ b/components/wear_levelling/CMakeLists.txt @@ -1,3 +1,7 @@ +idf_build_get_property(target IDF_TARGET) +if(${target} STREQUAL "esp32c3") + return() # TODO ESP32-C3 IDF-2180 +endif() idf_component_register(SRCS "Partition.cpp" "SPI_Flash.cpp" "WL_Ext_Perf.cpp" diff --git a/components/wear_levelling/test/test_wl.c b/components/wear_levelling/test/test_wl.c index f46e28c404..77cf31f50c 100644 --- a/components/wear_levelling/test/test_wl.c +++ b/components/wear_levelling/test/test_wl.c @@ -236,7 +236,7 @@ TEST_CASE("multiple write is correct", "[wear_levelling]") check_mem_data(handle, init_val, buff); uint32_t start; - RSR(CCOUNT, start); + start = cpu_hal_get_cycle_count(); for (int m=0 ; m< 100000 ; m++) { @@ -249,7 +249,7 @@ TEST_CASE("multiple write is correct", "[wear_levelling]") check_mem_data(handle, init_val, buff); uint32_t end; - RSR(CCOUNT, end); + end = cpu_hal_get_cycle_count(); uint32_t ms = (end - start) / (esp_clk_cpu_freq() / 1000); printf("loop %4i pass, time= %ims\n", m, ms); if (ms > 10000) { diff --git a/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c b/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c index 3a106b5cad..3be8bef2f6 100644 --- a/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c +++ b/components/wpa_supplicant/src/esp_supplicant/esp_wpa3.c @@ -130,7 +130,7 @@ void esp_wpa3_free_sae_data(void) sae_clear_data(&g_sae_data); } -static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, u32 *sae_msg_len) +static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, size_t *sae_msg_len) { u8 *buf = NULL; @@ -138,13 +138,13 @@ static u8 *wpa3_build_sae_msg(u8 *bssid, u32 sae_msg_type, u32 *sae_msg_len) case SAE_MSG_COMMIT: if (ESP_OK != wpa3_build_sae_commit(bssid)) return NULL; - *sae_msg_len = (u32)wpabuf_len(g_sae_commit); + *sae_msg_len = wpabuf_len(g_sae_commit); buf = wpabuf_mhead_u8(g_sae_commit); break; case SAE_MSG_CONFIRM: if (ESP_OK != wpa3_build_sae_confirm()) return NULL; - *sae_msg_len = (u32)wpabuf_len(g_sae_confirm); + *sae_msg_len = wpabuf_len(g_sae_confirm); buf = wpabuf_mhead_u8(g_sae_confirm); break; default: @@ -205,7 +205,7 @@ static int wpa3_parse_sae_confirm(u8 *buf, u32 len) return ESP_OK; } -static int wpa3_parse_sae_msg(u8 *buf, u32 len, u32 sae_msg_type, u16 status) +static int wpa3_parse_sae_msg(u8 *buf, size_t len, u32 sae_msg_type, u16 status) { int ret = ESP_OK; diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index a301b6073e..77c0f403c6 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -80,7 +80,7 @@ void eapol_sm_notify_eap_success(Boolean success) } -wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher) +wifi_cipher_type_t cipher_type_map_supp_to_public(unsigned wpa_cipher) { switch (wpa_cipher) { case WPA_CIPHER_NONE: @@ -109,7 +109,7 @@ wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher) } } -uint32_t cipher_type_map_public_to_supp(wifi_cipher_type_t cipher) +unsigned cipher_type_map_public_to_supp(wifi_cipher_type_t cipher) { switch (cipher) { case WIFI_CIPHER_TYPE_NONE: @@ -2298,7 +2298,7 @@ void wpa_supplicant_stop_countermeasures(u16 *pisunicast) int wpa_michael_mic_failure(u16 isunicast) { struct wpa_sm *sm = &gWpaSm; - int32_t *pmic_errors_seen=(isunicast)? &((sm->install_ptk).mic_errors_seen) : &((sm->install_gtk).mic_errors_seen); + int *pmic_errors_seen=(isunicast)? &((sm->install_ptk).mic_errors_seen) : &((sm->install_gtk).mic_errors_seen); wpa_printf(MSG_DEBUG, "\nTKIP MIC failure occur\n"); diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.h b/components/wpa_supplicant/src/rsn_supp/wpa.h index 491c12c813..bd64af2bc7 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.h +++ b/components/wpa_supplicant/src/rsn_supp/wpa.h @@ -130,9 +130,9 @@ char * dup_binstr(const void *src, size_t len); int wpa_michael_mic_failure(u16 isunicast); -wifi_cipher_type_t cipher_type_map_supp_to_public(uint32_t wpa_cipher); +wifi_cipher_type_t cipher_type_map_supp_to_public(unsigned cipher); -uint32_t cipher_type_map_supp_to_public(wifi_cipher_type_t cipher); +unsigned cipher_type_map_public_to_supp(wifi_cipher_type_t cipher); void wpa_sta_clear_curr_pmksa(void); diff --git a/components/wpa_supplicant/src/utils/common.h b/components/wpa_supplicant/src/utils/common.h index fb4865652f..70119d0b56 100644 --- a/components/wpa_supplicant/src/utils/common.h +++ b/components/wpa_supplicant/src/utils/common.h @@ -27,16 +27,14 @@ typedef int16_t s16; typedef int8_t s8; #endif /*ESP_PLATFORM*/ -#if defined(__XTENSA__) +#if defined(__linux__) || defined(__GLIBC__) +#include +#include +#else #include #define __BYTE_ORDER BYTE_ORDER #define __LITTLE_ENDIAN LITTLE_ENDIAN #define __BIG_ENDIAN BIG_ENDIAN -#endif /*__XTENSA__*/ - -#if defined(__linux__) || defined(__GLIBC__) || defined(__ets__) -#include -#include #endif /* __linux__ */ /* Define platform specific byte swapping macros */ @@ -85,16 +83,16 @@ static inline unsigned int wpa_swap_32(unsigned int v) #if __BYTE_ORDER == __LITTLE_ENDIAN #define le_to_host16(n) ((__force u16) (le16) (n)) #define host_to_le16(n) ((__force le16) (u16) (n)) -#define be_to_host16(n) __bswap_16((__force u16) (be16) (n)) -#define host_to_be16(n) ((__force be16) __bswap_16((n))) +#define be_to_host16(n) __builtin_bswap16((__force u16) (be16) (n)) +#define host_to_be16(n) ((__force be16) __builtin_bswap16((n))) #define le_to_host32(n) ((__force u32) (le32) (n)) #define host_to_le32(n) ((__force le32) (u32) (n)) -#define be_to_host32(n) __bswap_32((__force u32) (be32) (n)) -#define host_to_be32(n) ((__force be32) __bswap_32((n))) +#define be_to_host32(n) __builtin_bswap32((__force u32) (be32) (n)) +#define host_to_be32(n) ((__force be32) __builtin_bswap32((n))) #define le_to_host64(n) ((__force u64) (le64) (n)) #define host_to_le64(n) ((__force le64) (u64) (n)) -#define be_to_host64(n) __bswap_64((__force u64) (be64) (n)) -#define host_to_be64(n) ((__force be64) bswap_64((n))) +#define be_to_host64(n) __builtin_bswap64((__force u64) (be64) (n)) +#define host_to_be64(n) ((__force be64) __builtin_bswap64((n))) #elif __BYTE_ORDER == __BIG_ENDIAN #define le_to_host16(n) __bswap_16(n) #define host_to_le16(n) __bswap_16(n) diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index 7560b0267b..d9fd06258d 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -155,7 +155,7 @@ function(__build_init idf_path) # # - lwip is here so that #include works without any special provisions # - esp_hw_support is here for backward compatibility - set(requires_common cxx newlib freertos esp_hw_support heap log lwip soc hal esp_rom esp_common esp_system xtensa) + set(requires_common cxx newlib freertos esp_hw_support heap log lwip soc hal esp_rom esp_common esp_system) idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${requires_common}") __build_get_idf_git_revision() diff --git a/tools/find_build_apps/common.py b/tools/find_build_apps/common.py index 51368c5ce8..6f3feea0bd 100644 --- a/tools/find_build_apps/common.py +++ b/tools/find_build_apps/common.py @@ -264,6 +264,7 @@ class BuildItem(object): sys.executable, IDF_SIZE_PY, '--json', + '--target', self.target, '-o', size_json_fp, map_file ] diff --git a/tools/unit-test-app/components/test_utils/CMakeLists.txt b/tools/unit-test-app/components/test_utils/CMakeLists.txt index b327cd4915..a950bfa82d 100644 --- a/tools/unit-test-app/components/test_utils/CMakeLists.txt +++ b/tools/unit-test-app/components/test_utils/CMakeLists.txt @@ -1,8 +1,22 @@ -idf_component_register(SRCS "ccomp_timer.c" - "ref_clock.c" - "test_runner.c" - "test_utils.c" - "ccomp_timer_impl.c" +set(srcs "ccomp_timer.c" + "test_runner.c" + "test_utils.c") + +if(CONFIG_IDF_TARGET_ESP32) + list(APPEND srcs "ref_clock_impl_rmt_pcnt.c") +else() + list(APPEND srcs "ref_clock_impl_timergroup.c") +endif() + +if(CONFIG_IDF_TARGET_ARCH_RISCV) + list(APPEND srcs "ccomp_timer_impl_riscv.c") +endif() + +if(CONFIG_IDF_TARGET_ARCH_XTENSA) + list(APPEND srcs "ccomp_timer_impl_xtensa.c") +endif() + +idf_component_register(SRCS ${srcs} INCLUDE_DIRS include PRIV_INCLUDE_DIRS private_include REQUIRES spi_flash idf_test cmock diff --git a/tools/unit-test-app/components/test_utils/ccomp_timer.c b/tools/unit-test-app/components/test_utils/ccomp_timer.c index 104d8f8a50..01ee71e6e8 100644 --- a/tools/unit-test-app/components/test_utils/ccomp_timer.c +++ b/tools/unit-test-app/components/test_utils/ccomp_timer.c @@ -23,15 +23,6 @@ #include "esp_log.h" #include "esp_intr_alloc.h" -#if CONFIG_IDF_TARGET_ESP32 -#include "esp32/clk.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/clk.h" -#elif CONFIG_IDF_TARGET_ESP32S3 -#include "esp32s3/clk.h" -#endif - - static const char TAG[] = "ccomp_timer"; esp_err_t ccomp_timer_start(void) diff --git a/tools/unit-test-app/components/test_utils/ccomp_timer_impl_riscv.c b/tools/unit-test-app/components/test_utils/ccomp_timer_impl_riscv.c new file mode 100644 index 0000000000..477170f4da --- /dev/null +++ b/tools/unit-test-app/components/test_utils/ccomp_timer_impl_riscv.c @@ -0,0 +1,121 @@ +// Copyright 2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include "freertos/portmacro.h" +#include "esp_freertos_hooks.h" +#include "soc/soc_caps.h" +#include "hal/cpu_hal.h" +#include "esp_rom_sys.h" + +#if CONFIG_IDF_TARGET_ESP32C3 +#include "esp32c3/clk.h" +#endif + +typedef enum { + PERF_TIMER_UNINIT = 0, // timer has not been initialized yet + PERF_TIMER_IDLE, // timer has been initialized but is not tracking elapsed time + PERF_TIMER_ACTIVE // timer is tracking elapsed time +} ccomp_timer_state_t; + +typedef struct { + uint32_t last_ccount; // last CCOUNT value, updated every os tick + ccomp_timer_state_t state; // state of the timer + int64_t ccount; // accumulated processors cycles during the time when timer is active +} ccomp_timer_status_t; + +// Each core has its independent timer +ccomp_timer_status_t s_status[SOC_CPU_CORES_NUM]; + +static portMUX_TYPE s_lock = portMUX_INITIALIZER_UNLOCKED; + +static void IRAM_ATTR update_ccount(void) +{ + if (s_status[cpu_hal_get_core_id()].state == PERF_TIMER_ACTIVE) { + int64_t new_ccount = cpu_hal_get_cycle_count(); + if (new_ccount > s_status[cpu_hal_get_core_id()].last_ccount) { + s_status[cpu_hal_get_core_id()].ccount += new_ccount - s_status[cpu_hal_get_core_id()].last_ccount; + } else { + // CCOUNT has wrapped around + s_status[cpu_hal_get_core_id()].ccount += new_ccount + (UINT32_MAX - s_status[cpu_hal_get_core_id()].last_ccount); + } + s_status[cpu_hal_get_core_id()].last_ccount = new_ccount; + } +} + +esp_err_t ccomp_timer_impl_init(void) +{ + s_status[cpu_hal_get_core_id()].state = PERF_TIMER_IDLE; + return ESP_OK; +} + +esp_err_t ccomp_timer_impl_deinit(void) +{ + s_status[cpu_hal_get_core_id()].state = PERF_TIMER_UNINIT; + return ESP_OK; +} + +esp_err_t ccomp_timer_impl_start(void) +{ + s_status[cpu_hal_get_core_id()].state = PERF_TIMER_ACTIVE; + s_status[cpu_hal_get_core_id()].last_ccount = cpu_hal_get_cycle_count(); + // Update elapsed cycles every OS tick + esp_register_freertos_tick_hook_for_cpu(update_ccount, cpu_hal_get_core_id()); + return ESP_OK; +} + +esp_err_t IRAM_ATTR ccomp_timer_impl_stop(void) +{ + esp_deregister_freertos_tick_hook_for_cpu(update_ccount, cpu_hal_get_core_id()); + update_ccount(); + s_status[cpu_hal_get_core_id()].state = PERF_TIMER_IDLE; + return ESP_OK; +} + +int64_t IRAM_ATTR ccomp_timer_impl_get_time(void) +{ + update_ccount(); + int64_t cycles = s_status[cpu_hal_get_core_id()].ccount; + esp_rom_printf("cycles=%lld\n", cycles); + esp_rom_printf("cpu freq=%d\r\n", esp_clk_cpu_freq()); + esp_rom_printf("duration=%lld\n", cycles * 1000000 / esp_clk_cpu_freq()); + return (cycles * 1000000) / esp_clk_cpu_freq(); +} + +esp_err_t ccomp_timer_impl_reset(void) +{ + s_status[cpu_hal_get_core_id()].ccount = 0; + s_status[cpu_hal_get_core_id()].last_ccount = 0; + return ESP_OK; +} + +bool ccomp_timer_impl_is_init(void) +{ + return s_status[cpu_hal_get_core_id()].state != PERF_TIMER_UNINIT; +} + +bool IRAM_ATTR ccomp_timer_impl_is_active(void) +{ + return s_status[cpu_hal_get_core_id()].state == PERF_TIMER_ACTIVE; +} + +void IRAM_ATTR ccomp_timer_impl_lock(void) +{ + portENTER_CRITICAL(&s_lock); +} + +void IRAM_ATTR ccomp_timer_impl_unlock(void) +{ + portEXIT_CRITICAL(&s_lock); +} diff --git a/tools/unit-test-app/components/test_utils/ccomp_timer_impl.c b/tools/unit-test-app/components/test_utils/ccomp_timer_impl_xtensa.c similarity index 100% rename from tools/unit-test-app/components/test_utils/ccomp_timer_impl.c rename to tools/unit-test-app/components/test_utils/ccomp_timer_impl_xtensa.c diff --git a/tools/unit-test-app/components/test_utils/ref_clock.c b/tools/unit-test-app/components/test_utils/ref_clock_impl_rmt_pcnt.c similarity index 100% rename from tools/unit-test-app/components/test_utils/ref_clock.c rename to tools/unit-test-app/components/test_utils/ref_clock_impl_rmt_pcnt.c diff --git a/tools/unit-test-app/components/test_utils/ref_clock_impl_timergroup.c b/tools/unit-test-app/components/test_utils/ref_clock_impl_timergroup.c new file mode 100644 index 0000000000..bdacc2baa9 --- /dev/null +++ b/tools/unit-test-app/components/test_utils/ref_clock_impl_timergroup.c @@ -0,0 +1,50 @@ +// 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 "test_utils.h" +#include "driver/periph_ctrl.h" +#include "soc/periph_defs.h" +#include "hal/timer_hal.h" + +#define TIMER_GROUP_ID (1) +#define TIMER_ID (0) +static timer_hal_context_t timer_hal; + +void ref_clock_init(void) +{ + periph_module_enable(PERIPH_TIMG1_MODULE); + timer_hal_init(&timer_hal, TIMER_GROUP_ID, TIMER_ID); + timer_hal_set_use_xtal(&timer_hal, true); // Select XTAL, so ref_clock is independent of the APL clock + timer_hal_set_divider(&timer_hal, 40); // Resolution is configured to 1MHz + timer_hal_set_counter_increase(&timer_hal, true); // increase mode + timer_hal_set_counter_enable(&timer_hal, false); // stop timer from running + timer_hal_set_counter_value(&timer_hal, 0); // initial count value to zero + timer_hal_intr_disable(&timer_hal); // disable interrupt + timer_hal_set_alarm_enable(&timer_hal, false); // we don't need to generate any interrupt + timer_hal_set_auto_reload(&timer_hal, false); + timer_hal_set_counter_enable(&timer_hal, true); // start counter +} + +void ref_clock_deinit(void) +{ + timer_hal_set_counter_enable(&timer_hal, false); // stop timer from running + periph_module_disable(PERIPH_TIMG1_MODULE); +} + +uint64_t ref_clock_get(void) +{ + uint64_t count_value = 0; + timer_hal_get_counter_value(&timer_hal, &count_value); + return count_value; +} diff --git a/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_api.c b/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_api.c index a71dddea85..75b24d2588 100644 --- a/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_api.c +++ b/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_api.c @@ -5,7 +5,6 @@ #include "esp_log.h" #include "esp_attr.h" #include "ccomp_timer.h" -#include "eri.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" diff --git a/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_data.c b/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_data.c index 7039c82dba..6fc92090bd 100644 --- a/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_data.c +++ b/tools/unit-test-app/components/test_utils/test/ccomp_timer_test_data.c @@ -5,7 +5,6 @@ #include "esp_log.h" #include "esp_attr.h" #include "ccomp_timer.h" -#include "eri.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" From 4cc6b5571b8372d0e1b21b32a4490d1400504afd Mon Sep 17 00:00:00 2001 From: Renz Bagaporo Date: Thu, 8 Oct 2020 13:18:16 +0800 Subject: [PATCH 4/5] esp_system: support riscv panic --- components/esp_system/component.mk | 2 +- .../include/esp_private/panic_internal.h | 20 + components/esp_system/linker.lf | 1 + components/esp_system/panic.c | 15 + components/esp_system/port/CMakeLists.txt | 5 +- .../esp_system/port/arch/riscv/panic_arch.c | 127 ++++ .../xtensa/{panic_handler.c => panic_arch.c} | 540 +++++++----------- components/esp_system/port/esp32/component.mk | 2 - components/esp_system/port/panic_handler.c | 220 +++++++ .../port/{ => soc}/esp32/CMakeLists.txt | 4 +- .../esp_system/port/{ => soc}/esp32/clk.c | 7 +- .../esp_system/port/soc/esp32/component.mk | 2 + .../{ => soc}/esp32/dport_panic_highint_hdl.S | 0 .../esp_system/port/{ => soc}/esp32/intr.c | 0 .../port/{ => soc}/esp32/reset_reason.c | 0 .../port/{ => soc}/esp32s2/CMakeLists.txt | 4 +- .../esp32s2/async_memcpy_impl_cp_dma.c | 0 .../esp_system/port/{ => soc}/esp32s2/clk.c | 0 .../esp32s2/dport_panic_highint_hdl.S | 0 .../port/{ => soc}/esp32s2/reset_reason.c | 0 .../port/{ => soc}/esp32s2/usb_console.c | 0 .../port/{ => soc}/esp32s3/CMakeLists.txt | 6 +- .../esp_system/port/{ => soc}/esp32s3/clk.c | 0 .../esp32s3/dport_panic_highint_hdl.S | 0 .../port/{ => soc}/esp32s3/reset_reason.c | 0 .../riscv/include/esp_private/panic_reason.h | 20 + .../riscv/include/riscv/rvruntime-frames.h | 111 ++-- components/riscv/vectors.S | 259 ++++----- docs/en/api-guides/hlinterrupts.rst | 2 +- tools/test_idf_size/app.map | 6 +- tools/test_idf_size/app2.map | 10 +- tools/test_idf_size/app_esp32s2.map | 10 +- 32 files changed, 803 insertions(+), 570 deletions(-) create mode 100644 components/esp_system/port/arch/riscv/panic_arch.c rename components/esp_system/port/arch/xtensa/{panic_handler.c => panic_arch.c} (62%) delete mode 100644 components/esp_system/port/esp32/component.mk create mode 100644 components/esp_system/port/panic_handler.c rename components/esp_system/port/{ => soc}/esp32/CMakeLists.txt (84%) rename components/esp_system/port/{ => soc}/esp32/clk.c (98%) create mode 100644 components/esp_system/port/soc/esp32/component.mk rename components/esp_system/port/{ => soc}/esp32/dport_panic_highint_hdl.S (100%) rename components/esp_system/port/{ => soc}/esp32/intr.c (100%) rename components/esp_system/port/{ => soc}/esp32/reset_reason.c (100%) rename components/esp_system/port/{ => soc}/esp32s2/CMakeLists.txt (87%) rename components/esp_system/port/{ => soc}/esp32s2/async_memcpy_impl_cp_dma.c (100%) rename components/esp_system/port/{ => soc}/esp32s2/clk.c (100%) rename components/esp_system/port/{ => soc}/esp32s2/dport_panic_highint_hdl.S (100%) rename components/esp_system/port/{ => soc}/esp32s2/reset_reason.c (100%) rename components/esp_system/port/{ => soc}/esp32s2/usb_console.c (100%) rename components/esp_system/port/{ => soc}/esp32s3/CMakeLists.txt (78%) rename components/esp_system/port/{ => soc}/esp32s3/clk.c (100%) rename components/esp_system/port/{ => soc}/esp32s3/dport_panic_highint_hdl.S (100%) rename components/esp_system/port/{ => soc}/esp32s3/reset_reason.c (100%) create mode 100644 components/riscv/include/esp_private/panic_reason.h diff --git a/components/esp_system/component.mk b/components/esp_system/component.mk index caa3400967..d78bcef737 100644 --- a/components/esp_system/component.mk +++ b/components/esp_system/component.mk @@ -5,7 +5,7 @@ COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := private_include port/include COMPONENT_ADD_LDFRAGMENTS += linker.lf --include $(COMPONENT_PATH)/port/$(SOC_NAME)/component.mk +include $(COMPONENT_PATH)/port/soc/$(SOC_NAME)/component.mk # disable stack protection in files which are involved in initialization of that feature startup.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS)) diff --git a/components/esp_system/include/esp_private/panic_internal.h b/components/esp_system/include/esp_private/panic_internal.h index 583d3eba74..d43a705aba 100644 --- a/components/esp_system/include/esp_private/panic_internal.h +++ b/components/esp_system/include/esp_private/panic_internal.h @@ -16,14 +16,20 @@ #include #include + +#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 diff --git a/components/esp_system/linker.lf b/components/esp_system/linker.lf index 412b10d192..17ab599c35 100644 --- a/components/esp_system/linker.lf +++ b/components/esp_system/linker.lf @@ -3,6 +3,7 @@ archive: libesp_system.a entries: panic (noflash) panic_handler (noflash) + panic_arch (noflash) reset_reason (noflash) system_api:esp_system_abort (noflash) startup:do_core_init (default) diff --git a/components/esp_system/panic.c b/components/esp_system/panic.c index 4085be6bcb..518a75e4c7 100644 --- a/components/esp_system/panic.c +++ b/components/esp_system/panic.c @@ -46,11 +46,26 @@ #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" diff --git a/components/esp_system/port/CMakeLists.txt b/components/esp_system/port/CMakeLists.txt index c53c2aeaa8..628c79f007 100644 --- a/components/esp_system/port/CMakeLists.txt +++ b/components/esp_system/port/CMakeLists.txt @@ -1,10 +1,9 @@ target_include_directories(${COMPONENT_LIB} PRIVATE include) -set(srcs "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}) diff --git a/components/esp_system/port/arch/riscv/panic_arch.c b/components/esp_system/port/arch/riscv/panic_arch.c new file mode 100644 index 0000000000..ded4a7ee6f --- /dev/null +++ b/components/esp_system/port/arch/riscv/panic_arch.c @@ -0,0 +1,127 @@ + +// Copyright 2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include + +#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; +} diff --git a/components/esp_system/port/arch/xtensa/panic_handler.c b/components/esp_system/port/arch/xtensa/panic_arch.c similarity index 62% rename from components/esp_system/port/arch/xtensa/panic_handler.c rename to components/esp_system/port/arch/xtensa/panic_arch.c index 76975d8c55..752b46fa9e 100644 --- a/components/esp_system/port/arch/xtensa/panic_handler.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -11,185 +11,38 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. -#include - #include "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" -#include "soc/soc_caps.h" -#include "soc/rtc.h" - -#include "hal/soc_hal.h" -#include "hal/cpu_hal.h" -#include "hal/wdt_types.h" -#include "hal/wdt_hal.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" -#include "esp32/dport_access.h" -#include "esp32/rom/uart.h" -#elif CONFIG_IDF_TARGET_ESP32S2 -#include "esp32s2/cache_err_int.h" -#include "esp32s2/rom/uart.h" -#include "esp32s2/memprot.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/rom/uart.h" #include "esp32s3/memprot.h" -#include "soc/extmem_reg.h" -#include "soc/cache_memory.h" -#include "soc/rtc_cntl_reg.h" #endif +#endif // CONFIG_IDF_TARGET_ESP32 -#include "esp_private/panic_internal.h" - -extern int _invalid_pc_placeholder; - -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}; - -/* - Panic handlers; these get called when an unhandled exception occurs or the assembly-level - task switching / interrupt code runs into an unrecoverable error. The default task stack - overflow handler and abort handler are also in here. -*/ - -/* - 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) +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 ", @@ -248,37 +101,76 @@ static void print_registers(const void *f, int core) } } -static void print_state_for_core(const void *f, int core) +static void print_illegal_instruction_details(const void *f) { - if (!g_panic_abort) { - print_registers(f, core); - panic_print_str("\r\n"); + 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; } - print_backtrace(f, core); + 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_state(const void *f) + +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 - int err_core = f == xt_exc_frames[0] ? 0 : 1; -#else - int err_core = 0; + if (f == g_exc_frames[1]) { + core = 1; + } #endif - print_state_for_core(f, err_core); - - panic_print_str("\r\n"); - -#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - // 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); - panic_print_str("\r\n"); + 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 "); } } -#endif + 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 @@ -460,194 +352,146 @@ 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) + +void panic_arch_fill_info(void *f, panic_info_t *info) { - info->core = cpu_hal_get_core_id(); - info->exception = PANIC_EXCEPTION_FAULT; - info->details = NULL; + 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" + }; - info->pseudo_excause = pseudo_excause; - if (pseudo_excause) { - if (frame->exccause == PANIC_RSN_INTWDT_CPU0) { - info->core = 0; - info->exception = PANIC_EXCEPTION_IWDT; - } else if (frame->exccause == PANIC_RSN_INTWDT_CPU1) { - info->core = 1; - info->exception = PANIC_EXCEPTION_IWDT; - } else if (frame->exccause == PANIC_RSN_CACHEERR) { - info->core = esp_cache_err_get_cpuid(); - } else {} - - //Please keep in sync with PANIC_RSN_* defines - static const char *pseudo_reason[] = { - "Unknown reason", - "Unhandled debug exception", - "Double exception", - "Unhandled kernel exception", - "Coprocessor exception", - "Interrupt wdt timeout on CPU0", - "Interrupt wdt timeout on CPU1", -#if CONFIG_IDF_TARGET_ESP32 - "Cache disabled but cached memory region accessed", -#elif CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - "Cache exception", -#endif - }; - - info->reason = pseudo_reason[0]; - info->description = NULL; - - if (frame->exccause <= PANIC_RSN_MAX) { - info->reason = pseudo_reason[frame->exccause]; - } - - if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) { - info->details = print_debug_exception_details; - info->exception = PANIC_EXCEPTION_DEBUG; - } - -#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3 - if (frame->exccause == PANIC_RSN_CACHEERR) { - if ( esp_memprot_get_active_intr_memtype() != MEMPROT_NONE ) { - info->details = print_memprot_err_details; - info->reason = "Memory protection fault"; - } else { - info->details = print_cache_err_details; - } - } -#endif + if (frame->exccause < (sizeof(reason) / sizeof(char *))) { + info->reason = (reason[frame->exccause]); } 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; - } + info->reason = "Unknown"; + } + + info->description = "Exception was unhandled."; + + if (frame->exccause == EXCCAUSE_ILLEGAL) { + info->details = print_illegal_instruction_details; } - info->state = print_state; info->addr = ((void *) ((XtExcFrame *) frame)->pc); - info->frame = frame; } -static void panic_handler(XtExcFrame *frame, bool pseudo_excause) +void panic_soc_fill_info(void *f, panic_info_t *info) { - /* - * Setup environment and perform necessary architecture/chip specific - * steps here prior to the system panic handler. - * */ - 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; - -#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE - // These are cases where both CPUs both go into panic handler. The following code ensures - // only one core proceeds to the system panic handler. - 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); - - // 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()) { - // Only print the backtrace for the offending core in case of the cache error - xt_exc_frames[core_id] = NULL; - while (1) { - ; - } - } - } - - esp_rom_delay_us(1); - SOC_HAL_STALL_OTHER_CORES(); -#endif + // [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 - esp_dport_access_int_abort(); + "Cache disabled but cached memory region accessed", +#elif CONFIG_IDF_TARGET_ESP32S2 + "Cache exception", #endif + }; -#if !CONFIG_ESP_PANIC_HANDLER_IRAM - // Re-enable CPU cache for current CPU if it was disabled - if (!spi_flash_cache_enabled()) { - spi_flash_enable_cache(core_id); - panic_print_str("Re-enable cpu cache.\r\n"); - } -#endif + info->reason = pseudo_reason[0]; + info->description = NULL; - if (esp_cpu_in_ocd_debug_mode()) { - if (!(esp_ptr_executable(cpu_ll_pc_to_ptr(frame->pc)) && (frame->pc & 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; - } - if (frame->exccause == PANIC_RSN_INTWDT_CPU0 || - frame->exccause == PANIC_RSN_INTWDT_CPU1) { - wdt_hal_write_protect_disable(&wdt0_context); - wdt_hal_handle_intr(&wdt0_context); - wdt_hal_write_protect_enable(&wdt0_context); - } + if (frame->exccause <= PANIC_RSN_MAX) { + info->reason = pseudo_reason[frame->exccause]; } - // Convert architecture exception frame into abstracted panic info - panic_info_t info; - frame_to_panic_info(frame, &info, pseudo_excause); - - // Call the system panic handler - esp_panic_handler(&info); -} - -void panicHandler(XtExcFrame *frame) -{ - // This panic handler gets called for when the double exception vector, - // kernel exception vector gets used; as well as handling interrupt-based - // faults cache error, wdt expiry. EXCAUSE register gets written with - // one of PANIC_RSN_* values. - panic_handler(frame, true); -} - -void xt_unhandled_exception(XtExcFrame *frame) -{ - panic_handler(frame, false); -} - -void __attribute__((noreturn)) panic_restart(void) -{ - bool digital_reset_needed = false; -#ifdef CONFIG_IDF_TARGET_ESP32 - // On the ESP32, cache error status can only be cleared by system reset - if (esp_cache_err_get_cpuid() != -1) { - digital_reset_needed = true; + if (frame->exccause == PANIC_RSN_DEBUGEXCEPTION) { + info->details = print_debug_exception_details; + info->exception = PANIC_EXCEPTION_DEBUG; } -#endif + #if CONFIG_IDF_TARGET_ESP32S2 - if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) { - digital_reset_needed = true; + 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 - if (digital_reset_needed) { - esp_restart_noos_dig(); - } - esp_restart_noos(); +} + +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"); + } } diff --git a/components/esp_system/port/esp32/component.mk b/components/esp_system/port/esp32/component.mk deleted file mode 100644 index 88dd942940..0000000000 --- a/components/esp_system/port/esp32/component.mk +++ /dev/null @@ -1,2 +0,0 @@ -COMPONENT_SRCDIRS += port port/esp32 port/arch/xtensa -COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o diff --git a/components/esp_system/port/panic_handler.c b/components/esp_system/port/panic_handler.c new file mode 100644 index 0000000000..aff036f489 --- /dev/null +++ b/components/esp_system/port/panic_handler.c @@ -0,0 +1,220 @@ +// 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 + +#include "esp_spi_flash.h" + +#include "esp_private/system_internal.h" + +#include "soc/soc_memory_layout.h" +#include "soc/cpu.h" +#include "soc/soc_caps.h" +#include "soc/rtc.h" + +#include "hal/soc_hal.h" +#include "hal/cpu_hal.h" + +#include "sdkconfig.h" +#include "esp_rom_sys.h" + +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/dport_access.h" +#include "esp32/cache_err_int.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/memprot.h" +#include "esp32s2/cache_err_int.h" +#elif CONFIG_IDF_TARGET_ESP32S3 +#include "esp32s3/memprot.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; + +extern void esp_panic_handler(panic_info_t*); + +static wdt_hal_context_t wdt0_context = {.inst = WDT_MWDT0, .mwdt_dev = &TIMERG0}; + +void *g_exc_frames[SOC_CPU_CORES_NUM] = {NULL}; + +/* + Panic handlers; these get called when an unhandled exception occurs or the assembly-level + task switching / interrupt code runs into an unrecoverable error. The default task stack + overflow handler and abort handler are also in here. +*/ + +/* + Note: The linker script will put everything in this file in IRAM/DRAM, so it also works with flash cache disabled. +*/ +static void print_state_for_core(const void *f, int core) +{ + if (!g_panic_abort) { + panic_print_registers(f, core); + panic_print_str("\r\n"); + } + panic_print_backtrace(f, core); +} + +static void print_state(const void *f) +{ +#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE + int err_core = f == g_exc_frames[0] ? 0 : 1; +#else + int err_core = 0; +#endif + + print_state_for_core(f, err_core); + + panic_print_str("\r\n"); + +#if !CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE + // 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 && g_exc_frames[i] != NULL) { + print_state_for_core(g_exc_frames[i], i); + panic_print_str("\r\n"); + } + } +#endif +} + +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) { + panic_soc_fill_info(frame, info); + } else { + panic_arch_fill_info(frame, info); + } + + info->state = print_state; + info->frame = frame; +} + +static void panic_handler(void *frame, bool pseudo_excause) +{ + /* + * Setup environment and perform necessary architecture/chip specific + * steps here prior to the system panic handler. + * */ + int core_id = cpu_hal_get_core_id(); + + // If multiple cores arrive at panic handler, save frames for all of them + 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 + // only one core proceeds to the system panic handler. + 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(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 (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 + g_exc_frames[core_id] = NULL; + while (1) { + ; + } + } + } + + esp_rom_delay_us(1); + SOC_HAL_STALL_OTHER_CORES(); +#endif + +#if CONFIG_IDF_TARGET_ESP32 + esp_dport_access_int_abort(); +#endif + +#if !CONFIG_ESP_PANIC_HANDLER_IRAM + // Re-enable CPU cache for current CPU if it was disabled + if (!spi_flash_cache_enabled()) { + spi_flash_enable_cache(core_id); + panic_print_str("Re-enable cpu cache.\r\n"); + } +#endif + + if (esp_cpu_in_ocd_debug_mode()) { +#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 + */ + panic_set_address(frame, (uint32_t)&_invalid_pc_placeholder); + } +#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); + } + } + + // Convert architecture exception frame into abstracted panic info + panic_info_t info; + frame_to_panic_info(frame, &info, pseudo_excause); + + // Call the system panic handler + esp_panic_handler(&info); +} + +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 + // faults cache error, wdt expiry. EXCAUSE register gets written with + // one of PANIC_RSN_* values. + panic_handler(frame, true); +} + +void xt_unhandled_exception(void *frame) +{ + panic_handler(frame, false); +} + +void __attribute__((noreturn)) panic_restart(void) +{ + bool digital_reset_needed = false; +#ifdef CONFIG_IDF_TARGET_ESP32 + // On the ESP32, cache error status can only be cleared by system reset + if (esp_cache_err_get_cpuid() != -1) { + digital_reset_needed = true; + } +#endif +#if CONFIG_IDF_TARGET_ESP32S2 + if (esp_memprot_is_intr_ena_any() || esp_memprot_is_locked_any()) { + digital_reset_needed = true; + } +#endif + if (digital_reset_needed) { + esp_restart_noos_dig(); + } + esp_restart_noos(); +} diff --git a/components/esp_system/port/esp32/CMakeLists.txt b/components/esp_system/port/soc/esp32/CMakeLists.txt similarity index 84% rename from components/esp_system/port/esp32/CMakeLists.txt rename to components/esp_system/port/soc/esp32/CMakeLists.txt index f1ddfe3d05..388edd5a6e 100644 --- a/components/esp_system/port/esp32/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32/CMakeLists.txt @@ -1,8 +1,8 @@ set(srcs "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c" - "../arch/xtensa/panic_handler.c" - "../arch/xtensa/panic_handler_asm.S" + "../../arch/xtensa/panic_arch.c" + "../../arch/xtensa/panic_handler_asm.S" ) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) diff --git a/components/esp_system/port/esp32/clk.c b/components/esp_system/port/soc/esp32/clk.c similarity index 98% rename from components/esp_system/port/esp32/clk.c rename to components/esp_system/port/soc/esp32/clk.c index 853fa41493..e47453bfb0 100644 --- a/components/esp_system/port/esp32/clk.c +++ b/components/esp_system/port/soc/esp32/clk.c @@ -177,7 +177,8 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk) wdt_hal_write_protect_enable(&rtc_wdt_ctx); #endif - rtc_cpu_freq_config_t old_config, new_config; + rtc_cpu_freq_config_t old_config; + rtc_cpu_freq_config_t new_config; rtc_clk_cpu_freq_get_config(&old_config); const uint32_t old_freq_mhz = old_config.freq_mhz; const uint32_t new_freq_mhz = CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ; @@ -205,7 +206,9 @@ static void select_rtc_slow_clk(slow_clk_sel_t slow_clk) */ __attribute__((weak)) void esp_perip_clk_init(void) { - uint32_t common_perip_clk, hwcrypto_perip_clk, wifi_bt_sdio_clk = 0; + uint32_t common_perip_clk; + uint32_t hwcrypto_perip_clk; + uint32_t wifi_bt_sdio_clk; #if CONFIG_FREERTOS_UNICORE RESET_REASON rst_reas[1]; diff --git a/components/esp_system/port/soc/esp32/component.mk b/components/esp_system/port/soc/esp32/component.mk new file mode 100644 index 0000000000..02c670c81a --- /dev/null +++ b/components/esp_system/port/soc/esp32/component.mk @@ -0,0 +1,2 @@ +COMPONENT_SRCDIRS += port port/soc/esp32 port/arch/xtensa +COMPONENT_OBJEXCLUDE += port/async_memcpy_impl_gdma.o diff --git a/components/esp_system/port/esp32/dport_panic_highint_hdl.S b/components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S similarity index 100% rename from components/esp_system/port/esp32/dport_panic_highint_hdl.S rename to components/esp_system/port/soc/esp32/dport_panic_highint_hdl.S diff --git a/components/esp_system/port/esp32/intr.c b/components/esp_system/port/soc/esp32/intr.c similarity index 100% rename from components/esp_system/port/esp32/intr.c rename to components/esp_system/port/soc/esp32/intr.c diff --git a/components/esp_system/port/esp32/reset_reason.c b/components/esp_system/port/soc/esp32/reset_reason.c similarity index 100% rename from components/esp_system/port/esp32/reset_reason.c rename to components/esp_system/port/soc/esp32/reset_reason.c diff --git a/components/esp_system/port/esp32s2/CMakeLists.txt b/components/esp_system/port/soc/esp32s2/CMakeLists.txt similarity index 87% rename from components/esp_system/port/esp32s2/CMakeLists.txt rename to components/esp_system/port/soc/esp32s2/CMakeLists.txt index ee8643a087..443c34c8c0 100644 --- a/components/esp_system/port/esp32s2/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32s2/CMakeLists.txt @@ -2,8 +2,8 @@ set(srcs "async_memcpy_impl_cp_dma.c" "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c" - "../arch/xtensa/panic_handler.c" - "../arch/xtensa/panic_handler_asm.S" + "../../arch/xtensa/panic_arch.c" + "../../arch/xtensa/panic_handler_asm.S" ) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) diff --git a/components/esp_system/port/esp32s2/async_memcpy_impl_cp_dma.c b/components/esp_system/port/soc/esp32s2/async_memcpy_impl_cp_dma.c similarity index 100% rename from components/esp_system/port/esp32s2/async_memcpy_impl_cp_dma.c rename to components/esp_system/port/soc/esp32s2/async_memcpy_impl_cp_dma.c diff --git a/components/esp_system/port/esp32s2/clk.c b/components/esp_system/port/soc/esp32s2/clk.c similarity index 100% rename from components/esp_system/port/esp32s2/clk.c rename to components/esp_system/port/soc/esp32s2/clk.c diff --git a/components/esp_system/port/esp32s2/dport_panic_highint_hdl.S b/components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S similarity index 100% rename from components/esp_system/port/esp32s2/dport_panic_highint_hdl.S rename to components/esp_system/port/soc/esp32s2/dport_panic_highint_hdl.S diff --git a/components/esp_system/port/esp32s2/reset_reason.c b/components/esp_system/port/soc/esp32s2/reset_reason.c similarity index 100% rename from components/esp_system/port/esp32s2/reset_reason.c rename to components/esp_system/port/soc/esp32s2/reset_reason.c diff --git a/components/esp_system/port/esp32s2/usb_console.c b/components/esp_system/port/soc/esp32s2/usb_console.c similarity index 100% rename from components/esp_system/port/esp32s2/usb_console.c rename to components/esp_system/port/soc/esp32s2/usb_console.c diff --git a/components/esp_system/port/esp32s3/CMakeLists.txt b/components/esp_system/port/soc/esp32s3/CMakeLists.txt similarity index 78% rename from components/esp_system/port/esp32s3/CMakeLists.txt rename to components/esp_system/port/soc/esp32s3/CMakeLists.txt index 6bfc1d5a86..d35152b1d3 100644 --- a/components/esp_system/port/esp32s3/CMakeLists.txt +++ b/components/esp_system/port/soc/esp32s3/CMakeLists.txt @@ -1,9 +1,9 @@ set(srcs "dport_panic_highint_hdl.S" "clk.c" "reset_reason.c" - "../async_memcpy_impl_gdma.c" - "../arch/xtensa/panic_handler.c" - "../arch/xtensa/panic_handler_asm.S" + "../../async_memcpy_impl_gdma.c" + "../../arch/xtensa/panic_arch.c" + "../../arch/xtensa/panic_handler_asm.S" ) add_prefix(srcs "${CMAKE_CURRENT_LIST_DIR}/" ${srcs}) diff --git a/components/esp_system/port/esp32s3/clk.c b/components/esp_system/port/soc/esp32s3/clk.c similarity index 100% rename from components/esp_system/port/esp32s3/clk.c rename to components/esp_system/port/soc/esp32s3/clk.c diff --git a/components/esp_system/port/esp32s3/dport_panic_highint_hdl.S b/components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S similarity index 100% rename from components/esp_system/port/esp32s3/dport_panic_highint_hdl.S rename to components/esp_system/port/soc/esp32s3/dport_panic_highint_hdl.S diff --git a/components/esp_system/port/esp32s3/reset_reason.c b/components/esp_system/port/soc/esp32s3/reset_reason.c similarity index 100% rename from components/esp_system/port/esp32s3/reset_reason.c rename to components/esp_system/port/soc/esp32s3/reset_reason.c diff --git a/components/riscv/include/esp_private/panic_reason.h b/components/riscv/include/esp_private/panic_reason.h new file mode 100644 index 0000000000..a91e6b3396 --- /dev/null +++ b/components/riscv/include/esp_private/panic_reason.h @@ -0,0 +1,20 @@ +// 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. +#pragma once + +#define PANIC_RSN_NONE 0 +#define PANIC_RSN_INTWDT_CPU0 1 +#define PANIC_RSN_INTWDT_CPU1 2 +#define PANIC_RSN_CACHEERR 3 +#define PANIC_RSN_MAX 3 diff --git a/components/riscv/include/riscv/rvruntime-frames.h b/components/riscv/include/riscv/rvruntime-frames.h index b4e4c141b5..1ef8934f14 100644 --- a/components/riscv/include/riscv/rvruntime-frames.h +++ b/components/riscv/include/riscv/rvruntime-frames.h @@ -1,8 +1,22 @@ +// 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. + #ifndef __RVRUNTIME_FRAMES_H__ #define __RVRUNTIME_FRAMES_H__ /* Align a value up to nearest n-byte boundary, where n is a power of 2. */ -#define ALIGNUP(n, val) (((val) + (n)-1) & -(n)) +#define ALIGNUP(n, val) (((val) + (n) - 1) & -(n)) #ifdef STRUCT_BEGIN #undef STRUCT_BEGIN @@ -12,19 +26,15 @@ #endif #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) - #define STRUCT_BEGIN .pushsection .text; .struct 0 #define STRUCT_FIELD(ctype,size,asname,name) asname: .space size #define STRUCT_AFIELD(ctype,size,asname,name,n) asname: .space (size)*(n) #define STRUCT_END(sname) sname##Size:; .popsection - #else - #define STRUCT_BEGIN typedef struct { #define STRUCT_FIELD(ctype,size,asname,name) ctype name; #define STRUCT_AFIELD(ctype,size,asname,name,n) ctype name[n]; #define STRUCT_END(sname) } sname; - #endif /* @@ -33,63 +43,54 @@ ------------------------------------------------------------------------------- */ STRUCT_BEGIN -STRUCT_FIELD (long, 4, RV_STK_MEPC, mepc) /* Machine Exception Program Counter */ -STRUCT_FIELD (long, 4, RV_STK_RA, ra) /* Return address */ -STRUCT_FIELD (long, 4, RV_STK_SP, sp) /* Stack pointer */ -STRUCT_FIELD (long, 4, RV_STK_GP, gp) /* Global pointer */ -STRUCT_FIELD (long, 4, RV_STK_TP, tp) /* Thread pointer */ -STRUCT_FIELD (long, 4, RV_STK_T0, t0) /* Temporary/alternate link register */ -STRUCT_FIELD (long, 4, RV_STK_T1, t1) /* t1-2: Temporaries */ -STRUCT_FIELD (long, 4, RV_STK_T2, t2) -STRUCT_FIELD (long, 4, RV_STK_S0, s0) /* Saved register/frame pointer */ -STRUCT_FIELD (long, 4, RV_STK_S1, s1) /* Saved register */ -STRUCT_FIELD (long, 4, RV_STK_A0, a0) /* a0-1: Function arguments/return address */ -STRUCT_FIELD (long, 4, RV_STK_A1, a1) -STRUCT_FIELD (long, 4, RV_STK_A2, a2) /* a2-7: Function arguments */ -STRUCT_FIELD (long, 4, RV_STK_A3, a3) -STRUCT_FIELD (long, 4, RV_STK_A4, a4) -STRUCT_FIELD (long, 4, RV_STK_A5, a5) -STRUCT_FIELD (long, 4, RV_STK_A6, a6) -STRUCT_FIELD (long, 4, RV_STK_A7, a7) -STRUCT_FIELD (long, 4, RV_STK_S2, s2) /* s2-11: Saved registers */ -STRUCT_FIELD (long, 4, RV_STK_S3, s3) -STRUCT_FIELD (long, 4, RV_STK_S4, s4) -STRUCT_FIELD (long, 4, RV_STK_S5, s5) -STRUCT_FIELD (long, 4, RV_STK_S6, s6) -STRUCT_FIELD (long, 4, RV_STK_S7, s7) -STRUCT_FIELD (long, 4, RV_STK_S8, s8) -STRUCT_FIELD (long, 4, RV_STK_S9, s9) -STRUCT_FIELD (long, 4, RV_STK_S10, s10) -STRUCT_FIELD (long, 4, RV_STK_S11, s11) -STRUCT_FIELD (long, 4, RV_STK_T3, t3) /* t3-6: Temporaries */ -STRUCT_FIELD (long, 4, RV_STK_T4, t4) -STRUCT_FIELD (long, 4, RV_STK_T5, t5) -STRUCT_FIELD (long, 4, RV_STK_T6, t6) -STRUCT_FIELD (long, 4, RV_STK_MSTATUS, mstatus) /* Machine Status */ -STRUCT_FIELD (long, 4, RV_STK_MTVEC, mtvec) /* Machine Trap-Vector Base Address */ -STRUCT_FIELD (long, 4, RV_STK_MCAUSE, mcause) /* Machine Trap Cause */ -STRUCT_FIELD (long, 4, RV_STK_PCCRS, pccrs) /* Performance Counter Counter Registers */ -STRUCT_FIELD (long, 4, RV_STK_PCER, pcer) /* Performance Counter Enable */ -STRUCT_FIELD (long, 4, RV_STK_PCMR, pcmr) /* Performance Counter Mode */ -STRUCT_FIELD (long, 4, RV_STK_HWLP, hwlp) /* Hardware Loop Registers */ -STRUCT_FIELD (long, 4, RV_STK_PRIVLV, privlv) /* Privilege Level */ -STRUCT_FIELD (long, 4, RV_STK_UHARTID, uhartid) /* Hardware Thread ID */ -STRUCT_FIELD (long, 4, RV_STK_MHARTID, mhartid) /* Hardware Thread ID */ -STRUCT_FIELD (long, 4, RV_STK_DCSR, dcsr) /* Debug Control and Status */ -STRUCT_FIELD (long, 4, RV_STK_DPC, dpc) /* Debug PC */ -STRUCT_FIELD (long, 4, RV_STK_INTC_THRESH, intc_thresh) -STRUCT_FIELD (long, 4, RV_STK_RESERVED0, reserved0) +STRUCT_FIELD (long, 4, RV_STK_MEPC, mepc) /* Machine Exception Program Counter */ +STRUCT_FIELD (long, 4, RV_STK_RA, ra) /* Return address */ +STRUCT_FIELD (long, 4, RV_STK_SP, sp) /* Stack pointer */ +STRUCT_FIELD (long, 4, RV_STK_GP, gp) /* Global pointer */ +STRUCT_FIELD (long, 4, RV_STK_TP, tp) /* Thread pointer */ +STRUCT_FIELD (long, 4, RV_STK_T0, t0) /* Temporary/alternate link register */ +STRUCT_FIELD (long, 4, RV_STK_T1, t1) /* t1-2: Temporaries */ +STRUCT_FIELD (long, 4, RV_STK_T2, t2) +STRUCT_FIELD (long, 4, RV_STK_S0, s0) /* Saved register/frame pointer */ +STRUCT_FIELD (long, 4, RV_STK_S1, s1) /* Saved register */ +STRUCT_FIELD (long, 4, RV_STK_A0, a0) /* a0-1: Function arguments/return address */ +STRUCT_FIELD (long, 4, RV_STK_A1, a1) +STRUCT_FIELD (long, 4, RV_STK_A2, a2) /* a2-7: Function arguments */ +STRUCT_FIELD (long, 4, RV_STK_A3, a3) +STRUCT_FIELD (long, 4, RV_STK_A4, a4) +STRUCT_FIELD (long, 4, RV_STK_A5, a5) +STRUCT_FIELD (long, 4, RV_STK_A6, a6) +STRUCT_FIELD (long, 4, RV_STK_A7, a7) +STRUCT_FIELD (long, 4, RV_STK_S2, s2) /* s2-11: Saved registers */ +STRUCT_FIELD (long, 4, RV_STK_S3, s3) +STRUCT_FIELD (long, 4, RV_STK_S4, s4) +STRUCT_FIELD (long, 4, RV_STK_S5, s5) +STRUCT_FIELD (long, 4, RV_STK_S6, s6) +STRUCT_FIELD (long, 4, RV_STK_S7, s7) +STRUCT_FIELD (long, 4, RV_STK_S8, s8) +STRUCT_FIELD (long, 4, RV_STK_S9, s9) +STRUCT_FIELD (long, 4, RV_STK_S10, s10) +STRUCT_FIELD (long, 4, RV_STK_S11, s11) +STRUCT_FIELD (long, 4, RV_STK_T3, t3) /* t3-6: Temporaries */ +STRUCT_FIELD (long, 4, RV_STK_T4, t4) +STRUCT_FIELD (long, 4, RV_STK_T5, t5) +STRUCT_FIELD (long, 4, RV_STK_T6, t6) +STRUCT_FIELD (long, 4, RV_STK_MSTATUS, mstatus) /* Machine Status */ +STRUCT_FIELD (long, 4, RV_STK_MTVEC, mtvec) /* Machine Trap-Vector Base Address */ +STRUCT_FIELD (long, 4, RV_STK_MCAUSE, mcause) /* Machine Trap Cause */ +STRUCT_FIELD (long, 4, RV_STK_MTVAL, mtval) /* Machine Trap Value */ +STRUCT_FIELD (long, 4, RV_STK_MHARTID, mhartid) /* Hardware Thread ID in machine mode */ STRUCT_END(RvExcFrame) #if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__) -# define RV_STK_SZ1 RvExcFrameSize +#define RV_STK_SZ1 RvExcFrameSize #else -# define RV_STK_SZ1 sizeof(RvExcFrame) +#define RV_STK_SZ1 sizeof(RvExcFrame) #endif /* - * This is the frame size. + * Exception stack frame size, after align up to 16 bytes boundary */ -#define RV_STK_FRMSZ (ALIGNUP(0x10, RV_STK_SZ1)) +#define RV_STK_FRMSZ (ALIGNUP(0x10, RV_STK_SZ1)) #endif /* #ifndef __RVRUNTIME_FRAMES_H__ */ diff --git a/components/riscv/vectors.S b/components/riscv/vectors.S index 4348cb1047..203c5adabe 100644 --- a/components/riscv/vectors.S +++ b/components/riscv/vectors.S @@ -13,101 +13,85 @@ // limitations under the License. #include "soc/soc.h" #include "soc/interrupt_reg.h" +#include "riscv/rvruntime-frames.h" .equ SAVE_REGS, 32 .equ CONTEXT_SIZE, (SAVE_REGS * 4) - .equ PANIC_REGS, 38 - .equ PANIC_REGS_SIZE, (PANIC_REGS * 4) - -.altmacro - -.macro lwsp a, b - lw \a, ((\b)*4)(sp) -.endm - -.macro swsp a, b - sw \a, ((\b)*4)(sp) -.endm - .macro save_regs - addi sp, sp, -CONTEXT_SIZE - swsp ra, 1 - swsp a0, 2 - swsp a1, 3 - swsp a2, 4 - swsp a3, 5 - swsp a4, 6 - swsp a5, 7 - swsp a6, 8 - swsp a7, 9 - swsp t0, 10 - swsp t1, 11 - swsp t2, 12 - swsp t3, 13 - swsp t4, 14 - swsp t5, 15 - swsp t6, 16 - //swsp sp, 17 - //swsp gp, 18 - swsp tp, 19 - swsp s0, 20 - swsp s1, 21 - swsp s2, 22 - swsp s3, 23 - swsp s4, 24 - swsp s5, 25 - swsp s6, 26 - swsp s7, 27 - swsp s8, 28 - swsp s9, 29 - swsp s10, 30 - swsp s11, 31 + addi sp, sp, -CONTEXT_SIZE + sw ra, RV_STK_RA(sp) + sw tp, RV_STK_TP(sp) + sw t0, RV_STK_T0(sp) + sw t1, RV_STK_T1(sp) + sw t2, RV_STK_T2(sp) + sw s0, RV_STK_S0(sp) + sw s1, RV_STK_S1(sp) + sw a0, RV_STK_A0(sp) + sw a1, RV_STK_A1(sp) + sw a2, RV_STK_A2(sp) + sw a3, RV_STK_A3(sp) + sw a4, RV_STK_A4(sp) + sw a5, RV_STK_A5(sp) + sw a6, RV_STK_A6(sp) + sw a7, RV_STK_A7(sp) + sw s2, RV_STK_S2(sp) + sw s3, RV_STK_S3(sp) + sw s4, RV_STK_S4(sp) + sw s5, RV_STK_S5(sp) + sw s6, RV_STK_S6(sp) + sw s7, RV_STK_S7(sp) + sw s8, RV_STK_S8(sp) + sw s9, RV_STK_S9(sp) + sw s10, RV_STK_S10(sp) + sw s11, RV_STK_S11(sp) + sw t3, RV_STK_T3(sp) + sw t4, RV_STK_T4(sp) + sw t5, RV_STK_T5(sp) + sw t6, RV_STK_T6(sp) .endm .macro save_mepc - csrr t0, mepc - swsp t0, 0 + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) .endm .macro restore_regs - lwsp ra, 1 - lwsp a0, 2 - lwsp a1, 3 - lwsp a2, 4 - lwsp a3, 5 - lwsp a4, 6 - lwsp a5, 7 - lwsp a6, 8 - lwsp a7, 9 - lwsp t0, 10 - lwsp t1, 11 - lwsp t2, 12 - lwsp t3, 13 - lwsp t4, 14 - lwsp t5, 15 - lwsp t6, 16 - //lwsp sp, 17 - //lwsp gp, 18 - lwsp tp, 19 - lwsp s0, 20 - lwsp s1, 21 - lwsp s2, 22 - lwsp s3, 23 - lwsp s4, 24 - lwsp s5, 25 - lwsp s6, 26 - lwsp s7, 27 - lwsp s8, 28 - lwsp s9, 29 - lwsp s10, 30 - lwsp s11, 31 + lw ra, RV_STK_RA(sp) + lw tp, RV_STK_TP(sp) + lw t0, RV_STK_T0(sp) + lw t1, RV_STK_T1(sp) + lw t2, RV_STK_T2(sp) + lw s0, RV_STK_S0(sp) + lw s1, RV_STK_S1(sp) + lw a0, RV_STK_A0(sp) + lw a1, RV_STK_A1(sp) + lw a2, RV_STK_A2(sp) + lw a3, RV_STK_A3(sp) + lw a4, RV_STK_A4(sp) + lw a5, RV_STK_A5(sp) + lw a6, RV_STK_A6(sp) + lw a7, RV_STK_A7(sp) + lw s2, RV_STK_S2(sp) + lw s3, RV_STK_S3(sp) + lw s4, RV_STK_S4(sp) + lw s5, RV_STK_S5(sp) + lw s6, RV_STK_S6(sp) + lw s7, RV_STK_S7(sp) + lw s8, RV_STK_S8(sp) + lw s9, RV_STK_S9(sp) + lw s10, RV_STK_S10(sp) + lw s11, RV_STK_S11(sp) + lw t3, RV_STK_T3(sp) + lw t4, RV_STK_T4(sp) + lw t5, RV_STK_T5(sp) + lw t6, RV_STK_T6(sp) addi sp, sp, CONTEXT_SIZE .endm .macro restore_mepc - lwsp t0, 0 + lw t0, RV_STK_MEPC(sp) csrw mepc, t0 .endm @@ -143,61 +127,61 @@ _vector_table: .size _vector_table, .-_vector_table /* Exception handler.*/ - .global panicHandler + .global xt_unhandled_exception .type _panic_handler, @function _panic_handler: - addi sp, sp, -PANIC_REGS_SIZE - swsp x0, 0 - swsp x1, 1 - /* x2 is sp - it will be placed on stack later (after we can use the other registers for computation) */ - swsp x3, 3 - swsp x4, 4 - swsp x5, 5 - swsp x6, 6 - swsp x7, 7 - swsp x8, 8 - swsp x9, 9 - swsp x10, 10 - swsp x11, 11 - swsp x12, 12 - swsp x13, 13 - swsp x14, 14 - swsp x15, 15 - swsp x16, 16 - swsp x17, 17 - swsp x18, 18 - swsp x19, 19 - swsp x20, 20 - swsp x21, 21 - swsp x22, 22 - swsp x23, 23 - swsp x24, 24 - swsp x25, 25 - swsp x26, 26 - swsp x27, 27 - swsp x28, 28 - swsp x29, 29 - swsp x30, 30 - swsp x31, 31 - /* "Undo" the modification already done to the sp (x2) by the panic handler */ - addi a1, x2, PANIC_REGS_SIZE - swsp a1, 2 - csrr a1, mcause - swsp a1, 32 - csrr a1, mepc - swsp a1, 33 - csrr a1, mhartid - swsp a1, 34 - csrr a1, mstatus - swsp a1, 35 - csrr a1, mtval - swsp a1, 36 - csrr a1, mtvec - swsp a1, 37 + addi sp, sp, -RV_STK_FRMSZ /* allocate space on stack to store necessary registers */ + /* save general registers */ + sw ra, RV_STK_RA(sp) + sw gp, RV_STK_GP(sp) + sw tp, RV_STK_TP(sp) + sw t0, RV_STK_T0(sp) + sw t1, RV_STK_T1(sp) + sw t2, RV_STK_T2(sp) + sw s0, RV_STK_S0(sp) + sw s1, RV_STK_S1(sp) + sw a0, RV_STK_A0(sp) + sw a1, RV_STK_A1(sp) + sw a2, RV_STK_A2(sp) + sw a3, RV_STK_A3(sp) + sw a4, RV_STK_A4(sp) + sw a5, RV_STK_A5(sp) + sw a6, RV_STK_A6(sp) + sw a7, RV_STK_A7(sp) + sw s2, RV_STK_S2(sp) + sw s3, RV_STK_S3(sp) + sw s4, RV_STK_S4(sp) + sw s5, RV_STK_S5(sp) + sw s6, RV_STK_S6(sp) + sw s7, RV_STK_S7(sp) + sw s8, RV_STK_S8(sp) + sw s9, RV_STK_S9(sp) + sw s10, RV_STK_S10(sp) + sw s11, RV_STK_S11(sp) + sw t3, RV_STK_T3(sp) + sw t4, RV_STK_T4(sp) + sw t5, RV_STK_T5(sp) + sw t6, RV_STK_T6(sp) + addi t0, sp, RV_STK_FRMSZ /* restore sp with the value when trap happened */ + sw t0, RV_STK_SP(sp) + csrr t0, mepc + sw t0, RV_STK_MEPC(sp) + csrr t0, mstatus + sw t0, RV_STK_MSTATUS(sp) + csrr t0, mtvec + sw t0, RV_STK_MTVEC(sp) + csrr t0, mcause + sw t0, RV_STK_MCAUSE(sp) + csrr t0, mtval + sw t0, RV_STK_MTVAL(sp) + csrr t0, mhartid + sw t0, RV_STK_MHARTID(sp) + + /* call xt_unhandled_exception(sp,cause) */ mv a0, sp csrr a1, mcause - jal zero, panicHandler - /* panicHandler never returns */ + jal zero, xt_unhandled_exception + /* panicHandler never returns */ .size _panic_handler, .-_panic_handler /* This is the interrupt handler. @@ -215,16 +199,15 @@ _interrupt_handler: /* scheduler not enabled, jump directly to ISR handler */ lw t0, uxSchedulerRunning - beq t0,zero,already_on_handler + beq t0, zero, already_on_handler /* increments the ISR nesting count */ - /* This will work properly when we have nested interrupts */ la t0, uxInterruptNesting lw t1, 0x0(t0) addi t2,t1,1 sw t2, 0x0(t0) - /* If reached here from another low-prio ISR, skip stack pushing to TCB */ + /* If reached here from another low priority ISR, skip stack pushing to TCB */ bne t1,zero, already_on_handler /* Otherwise, save current sp, and use the isr stack from here */ @@ -242,7 +225,7 @@ already_on_handler: lw s3, 0(t0) /* Increase interrupt threshold level */ - la t2, 0x7fffffff + li t2, 0x7fffffff and t1, s1, t2 /* t1 = mcause & mask */ slli t1, t1, 2 /* t1 = mcause * 4 */ la t2, INTC_INT_PRIO_REG(0) @@ -252,14 +235,14 @@ already_on_handler: sw t2, 0(t0) /* INTERRUPT_CORE0_CPU_INT_THRESH_REG = t2 */ fence - la t0, 0x8 + li t0, 0x8 csrrs t0, mstatus, t0 /* call the C dispatcher */ mv a0, sp /* argument 1, stack pointer */ csrr a1, mcause /* argument 2, interrupt number */ /* mask off the interrupt flag of mcause */ - la t0, 0x7fffffff + li t0, 0x7fffffff and a1, a1, t0 jal _global_interrupt_handler @@ -281,7 +264,7 @@ already_on_handler: la t0, uxInterruptNesting lw t1, 0x0(t0) - /* Already zero, protect againts underflow */ + /* Already zero, protect against underflow */ beq t1, zero, isr_skip_decrement addi t1,t1, -1 sw t1, 0x0(t0) @@ -290,7 +273,7 @@ isr_skip_decrement: /* may still have interrupts pending, skip section below and exit */ bne t1,zero,isr_exit - /* handlered all the ISRs and scheduled the next task, take its stack */ + /* handled all the ISRs and scheduled the next task, take its stack */ /* load on sp, then exit. */ lw sp, pxCurrentTCB lw sp, 0x0(sp) diff --git a/docs/en/api-guides/hlinterrupts.rst b/docs/en/api-guides/hlinterrupts.rst index 4d6b4a9d60..c5e28cb119 100644 --- a/docs/en/api-guides/hlinterrupts.rst +++ b/docs/en/api-guides/hlinterrupts.rst @@ -31,7 +31,7 @@ Using these symbols is done by creating an assembly file (suffix .S) and definin rsr a0, EXCSAVE_5 rfi 5 -For a real-life example, see the :component_file:`esp_system/port/{IDF_TARGET_PATH_NAME}/dport_panic_highint_hdl.S` file; the panic handler interrupt is implemented there. +For a real-life example, see the :component_file:`esp_system/port/soc/{IDF_TARGET_PATH_NAME}/dport_panic_highint_hdl.S` file; the panic handler interrupt is implemented there. Notes diff --git a/tools/test_idf_size/app.map b/tools/test_idf_size/app.map index a8bdc4d976..0dae32b208 100644 --- a/tools/test_idf_size/app.map +++ b/tools/test_idf_size/app.map @@ -17299,7 +17299,7 @@ END GROUP .literal.commonErrorHandler 0x0000000040080b80 0x4 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x28 (size before relaxing) - .literal.panicHandler + .literal.panic_handle_pseudo_exception 0x0000000040080b84 0x38 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0xc0 (size before relaxing) .literal.xt_unhandled_exception @@ -18250,10 +18250,10 @@ END GROUP 0x0000000040087c34 0x44 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x56 (size before relaxing) *fill* 0x0000000040087c78 0x0 - .text.panicHandler + .text.panic_handle_pseudo_exception 0x0000000040087c78 0x1a0 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0x1cc (size before relaxing) - 0x0000000040087c78 panicHandler + 0x0000000040087c78 panic_handle_pseudo_exception .text.xt_unhandled_exception 0x0000000040087e18 0x77 /home/user/esp/esp-idf/tools/unit-test-app/build/esp32/libesp32.a(panic.o) 0xa1 (size before relaxing) diff --git a/tools/test_idf_size/app2.map b/tools/test_idf_size/app2.map index ca6114cefe..51dd2ad2a8 100644 --- a/tools/test_idf_size/app2.map +++ b/tools/test_idf_size/app2.map @@ -8909,7 +8909,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-el .literal.vApplicationStackOverflowHook 0x0000000040080bb8 0x8 esp-idf/esp32/libesp32.a(panic.c.obj) 0x18 (size before relaxing) - .literal.panicHandler + .literal.panic_handle_pseudo_exception 0x0000000040080bc0 0x34 esp-idf/esp32/libesp32.a(panic.c.obj) 0xa8 (size before relaxing) .literal.xt_unhandled_exception @@ -10153,10 +10153,10 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-el 0x23 (size before relaxing) 0x0000000040086bd0 vApplicationStackOverflowHook *fill* 0x0000000040086be7 0x1 - .text.panicHandler + .text.panic_handle_pseudo_exception 0x0000000040086be8 0x165 esp-idf/esp32/libesp32.a(panic.c.obj) 0x19c (size before relaxing) - 0x0000000040086be8 panicHandler + 0x0000000040086be8 panic_handle_pseudo_exception *fill* 0x0000000040086d4d 0x3 .text.xt_unhandled_exception 0x0000000040086d50 0x88 esp-idf/esp32/libesp32.a(panic.c.obj) @@ -10939,7 +10939,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32-elf/esp-2019r2-8.2.0/xtensa-esp32-el .rodata.vApplicationStackOverflowHook.str1.4 0x000000003ffb1cbc 0x3e esp-idf/esp32/libesp32.a(panic.c.obj) *fill* 0x000000003ffb1cfa 0x2 - .rodata.panicHandler.str1.4 + .rodata.panic_handle_pseudo_exception.str1.4 0x000000003ffb1cfc 0x1a9 esp-idf/esp32/libesp32.a(panic.c.obj) *fill* 0x000000003ffb1ea5 0x3 .rodata.xt_unhandled_exception.str1.4 @@ -17060,7 +17060,7 @@ newlib_include_locks_impl esp-idf/newlib/libnewlib.a(loc newlib_include_pthread_impl esp-idf/newlib/libnewlib.a(pthread.c.obj) newlib_include_syscalls_impl esp-idf/newlib/libnewlib.a(syscalls.c.obj) opendir esp-idf/vfs/libvfs.a(vfs.c.obj) -panicHandler esp-idf/esp32/libesp32.a(panic.c.obj) +panic_handle_pseudo_exception esp-idf/esp32/libesp32.a(panic.c.obj) esp-idf/freertos/libfreertos.a(xtensa_vectors.S.obj) esp-idf/esp32/libesp32.a(dport_panic_highint_hdl.S.obj) pcTaskGetTaskName esp-idf/freertos/libfreertos.a(tasks.c.obj) diff --git a/tools/test_idf_size/app_esp32s2.map b/tools/test_idf_size/app_esp32s2.map index c805a8f1e0..e459ef3e6c 100644 --- a/tools/test_idf_size/app_esp32s2.map +++ b/tools/test_idf_size/app_esp32s2.map @@ -7678,7 +7678,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32s2-elf/esp-2019r2-8.2.0/xtensa-esp32s .literal.vApplicationStackOverflowHook 0x0000000040024a4c 0x8 esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x18 (size before relaxing) - .literal.panicHandler + .literal.panic_handle_pseudo_exception 0x0000000040024a54 0x9c esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x1a8 (size before relaxing) .literal.xt_unhandled_exception @@ -8819,10 +8819,10 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32s2-elf/esp-2019r2-8.2.0/xtensa-esp32s 0x23 (size before relaxing) 0x0000000040029b88 vApplicationStackOverflowHook *fill* 0x0000000040029b9f 0x1 - .text.panicHandler + .text.panic_handle_pseudo_exception 0x0000000040029ba0 0x31d esp-idf/esp32s2/libesp32s2.a(panic.c.obj) 0x3a0 (size before relaxing) - 0x0000000040029ba0 panicHandler + 0x0000000040029ba0 panic_handle_pseudo_exception *fill* 0x0000000040029ebd 0x3 .text.xt_unhandled_exception 0x0000000040029ec0 0x7d esp-idf/esp32s2/libesp32s2.a(panic.c.obj) @@ -9570,7 +9570,7 @@ LOAD /home/xy/.espressif/tools/xtensa-esp32s2-elf/esp-2019r2-8.2.0/xtensa-esp32s .rodata.vApplicationStackOverflowHook.str1.4 0x000000003ffbd8f4 0x3e esp-idf/esp32s2/libesp32s2.a(panic.c.obj) *fill* 0x000000003ffbd932 0x2 - .rodata.panicHandler.str1.4 + .rodata.panic_handle_pseudo_exception.str1.4 0x000000003ffbd934 0x418 esp-idf/esp32s2/libesp32s2.a(panic.c.obj) .rodata.xt_unhandled_exception.str1.4 0x000000003ffbdd4c 0x4d esp-idf/esp32s2/libesp32s2.a(panic.c.obj) @@ -15047,7 +15047,7 @@ newlib_include_locks_impl esp-idf/newlib/libnewlib.a(loc newlib_include_pthread_impl esp-idf/newlib/libnewlib.a(pthread.c.obj) newlib_include_syscalls_impl esp-idf/newlib/libnewlib.a(syscalls.c.obj) opendir esp-idf/vfs/libvfs.a(vfs.c.obj) -panicHandler esp-idf/esp32s2/libesp32s2.a(panic.c.obj) +panic_handle_pseudo_exception esp-idf/esp32s2/libesp32s2.a(panic.c.obj) esp-idf/freertos/libfreertos.a(xtensa_vectors.S.obj) esp-idf/esp32s2/libesp32s2.a(dport_panic_highint_hdl.S.obj) pcTaskGetTaskName esp-idf/freertos/libfreertos.a(tasks.c.obj) From b52c764bf39174c6c89baaeb34bec488ee7804f0 Mon Sep 17 00:00:00 2001 From: "Michael (XIAO Xufeng)" Date: Fri, 30 Oct 2020 13:44:24 +0800 Subject: [PATCH 5/5] idf_size.py: add support for esp32c3 and risc-v --- tools/cmake/project.cmake | 8 ++++---- tools/find_build_apps/common.py | 1 - tools/idf_size.py | 25 ++++++++++++++++++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index c7342be51b..8b47268f54 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -430,9 +430,9 @@ macro(project project_name) set(project_elf ${CMAKE_PROJECT_NAME}.elf) - # Create a dummy file to work around CMake requirement of having a source - # file while adding an executable - set(project_elf_src ${CMAKE_BINARY_DIR}/project_elf_src.c) + # Create a dummy file to work around CMake requirement of having a source file while adding an + # executable. This is also used by idf_size.py to detect the target + set(project_elf_src ${CMAKE_BINARY_DIR}/project_elf_src_${IDF_TARGET}.c) add_custom_command(OUTPUT ${project_elf_src} COMMAND ${CMAKE_COMMAND} -E touch ${project_elf_src} VERBATIM) @@ -470,7 +470,7 @@ macro(project project_name) idf_build_get_property(idf_path IDF_PATH) idf_build_get_property(python PYTHON) - set(idf_size ${python} ${idf_path}/tools/idf_size.py --target ${IDF_TARGET}) + set(idf_size ${python} ${idf_path}/tools/idf_size.py) if(DEFINED OUTPUT_JSON AND OUTPUT_JSON) list(APPEND idf_size "--json") endif() diff --git a/tools/find_build_apps/common.py b/tools/find_build_apps/common.py index 6f3feea0bd..51368c5ce8 100644 --- a/tools/find_build_apps/common.py +++ b/tools/find_build_apps/common.py @@ -264,7 +264,6 @@ class BuildItem(object): sys.executable, IDF_SIZE_PY, '--json', - '--target', self.target, '-o', size_json_fp, map_file ] diff --git a/tools/idf_size.py b/tools/idf_size.py index a4fc173a60..76625780e4 100755 --- a/tools/idf_size.py +++ b/tools/idf_size.py @@ -128,6 +128,17 @@ class MemRegions(object): return sorted([ MemRegDef(0x3FC88000, 0x8000 + 6 * 0x10000, MemRegions.DIRAM_ID, 0x40378000), ]) + elif target == 'esp32c3': + return sorted([ + MemRegDef(0x3FC80000, 0x60000, MemRegions.DIRAM_ID, 0x40380000), + + # MemRegDef(0x3FC80000, 0x20000, MemRegions.DIRAM_ID, 0x40380000), + # MemRegDef(0x3FCA0000, 0x20000, MemRegions.DIRAM_ID, 0x403A0000), + # MemRegDef(0x3FCC0000, 0x20000, MemRegions.DIRAM_ID, 0x403C0000), + + # Used by cache + MemRegDef(0x4037C000, 0x4000, MemRegions.IRAM_ID, 0), + ]) else: return None @@ -212,22 +223,30 @@ def load_memory_config(map_file): def detect_target_chip(map_file): - ''' Detect target chip based on the xtensa toolchain name in in the linker script part of the MAP file ''' + ''' Detect target chip based on the target archive name in the linker script part of the MAP file ''' scan_to_header(map_file, 'Linker script and memory map') - RE_TARGET = re.compile(r'^LOAD .*?/xtensa-([^-]+)-elf/') + RE_TARGET = re.compile(r'project_elf_src_(.*)\.c.obj') + # For back-compatible with make + RE_TARGET_MAKE = re.compile(r'^LOAD .*?/xtensa-([^-]+)-elf/') for line in map_file: m = RE_TARGET.search(line) if m: return m.group(1) + + m = RE_TARGET_MAKE.search(line) + if m: + return m.group(1) + line = line.strip() # There could be empty line(s) between the "Linker script and memory map" header and "LOAD lines". Therefore, # line stripping and length is checked as well. The "LOAD lines" are between START GROUP and END GROUP for # older MAP files. - if not line.startswith(('LOAD', 'START GROUP')) and len(line) > 0: + if not line.startswith(('LOAD', 'START GROUP', 'END GROUP')) and len(line) > 0: # This break is a failsafe to not process anything load_sections() might want to analyze. break + return None