mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-19 13:01:57 -04:00
Add git attributes (#245)
* Add .gitattributes configured to normailze line endings to LF * replace crlf with lf, per .gitattributes
This commit is contained in:
parent
23f641850d
commit
578d040659
105
.gitattributes
vendored
Normal file
105
.gitattributes
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
# Line ending normalization
|
||||
* text=auto
|
||||
|
||||
# Documents
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
*.md text
|
||||
*.adoc text
|
||||
*.textile text
|
||||
*.mustache text
|
||||
*.csv text
|
||||
*.tab text
|
||||
*.tsv text
|
||||
*.sql text
|
||||
*.html text
|
||||
*.css text
|
||||
|
||||
# Graphics
|
||||
*.png binary
|
||||
*.jpg binary
|
||||
*.jpeg binary
|
||||
*.gif binary
|
||||
*.tif binary
|
||||
*.tiff binary
|
||||
*.ico binary
|
||||
*.svg binary
|
||||
*.eps binary
|
||||
|
||||
#sources
|
||||
*.c text
|
||||
*.cc text
|
||||
*.cxx text
|
||||
*.cpp text
|
||||
*.c++ text
|
||||
*.hpp text
|
||||
*.h text
|
||||
*.h++ text
|
||||
*.hh text
|
||||
*.s text
|
||||
*.S text
|
||||
*.asm text
|
||||
|
||||
# Compiled Object files
|
||||
*.slo binary
|
||||
*.lo binary
|
||||
*.o binary
|
||||
*.obj binary
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch binary
|
||||
*.pch binary
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so binary
|
||||
*.dylib binary
|
||||
*.dll binary
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai binary
|
||||
*.la binary
|
||||
*.a binary
|
||||
*.lib binary
|
||||
|
||||
# Executables
|
||||
*.exe binary
|
||||
*.out binary
|
||||
*.app binary
|
||||
|
||||
|
||||
# Basic .gitattributes for a python repo.
|
||||
|
||||
# Source files
|
||||
# ============
|
||||
*.pxd text
|
||||
*.py text
|
||||
*.py3 text
|
||||
*.pyw text
|
||||
*.pyx text
|
||||
|
||||
# Binary files
|
||||
# ============
|
||||
*.db binary
|
||||
*.p binary
|
||||
*.pkl binary
|
||||
*.pyc binary
|
||||
*.pyd binary
|
||||
*.pyo binary
|
||||
|
||||
# Note: .db, .p, and .pkl files are associated
|
||||
# with the python modules ``pickle``, ``dbm.*``,
|
||||
# ``shelve``, ``marshal``, ``anydbm``, & ``bsddb``
|
||||
# (among others).
|
||||
|
||||
*.sh text
|
||||
make text
|
||||
makefile text
|
||||
*.mk text
|
1120
portable/ThirdParty/GCC/Xtensa_ESP32/include/portmacro.h
vendored
1120
portable/ThirdParty/GCC/Xtensa_ESP32/include/portmacro.h
vendored
File diff suppressed because it is too large
Load diff
|
@ -1,390 +1,390 @@
|
|||
/*******************************************************************************
|
||||
Copyright (c) 2006-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.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
|
||||
|
||||
This header contains definitions and macros for use primarily by Xtensa
|
||||
RTOS assembly coded source files. It includes and uses the Xtensa hardware
|
||||
abstraction layer (HAL) to deal with config specifics. It may also be
|
||||
included in C source files.
|
||||
|
||||
!! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !!
|
||||
|
||||
NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XTENSA_CONTEXT_H
|
||||
#define XTENSA_CONTEXT_H
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#include <xtensa/coreasm.h>
|
||||
#endif
|
||||
|
||||
#include <xtensa/config/tie.h>
|
||||
#include <xtensa/corebits.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include <xtensa/xtruntime-frames.h>
|
||||
#include <esp_idf_version.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))
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Macros that help define structures for both C and assembler.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 //_ASMLANGUAGE || __ASSEMBLER__
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
|
||||
|
||||
A stack frame of this structure is allocated for any interrupt or exception.
|
||||
It goes on the current stack. If the RTOS has a system stack for handling
|
||||
interrupts, every thread stack must allow space for just one interrupt stack
|
||||
frame, then nested interrupt stack frames go on the system stack.
|
||||
|
||||
The frame includes basic registers (explicit) and "extra" registers introduced
|
||||
by user TIE or the use of the MAC16 option in the user's Xtensa config.
|
||||
The frame size is minimized by omitting regs not applicable to user's config.
|
||||
|
||||
For Windowed ABI, this stack frame includes the interruptee's base save area,
|
||||
another base save area to manage gcc nested functions, and a little temporary
|
||||
space to help manage the spilling of the register windows.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */
|
||||
STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */
|
||||
STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */
|
||||
STRUCT_FIELD (long, 4, XT_STK_A0, a0)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
|
||||
STRUCT_FIELD (long, 4, XT_STK_A2, a2)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A3, a3)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A4, a4)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A5, a5)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A6, a6)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A7, a7)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A8, a8)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A9, a9)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A10, a10)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A11, a11)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A12, a12)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A13, a13)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A14, a14)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A15, a15)
|
||||
STRUCT_FIELD (long, 4, XT_STK_SAR, sar)
|
||||
STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
|
||||
STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
|
||||
STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
|
||||
STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
|
||||
#endif
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
/* Temporary space for saving stuff during window spill */
|
||||
STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
|
||||
STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
|
||||
STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
|
||||
#endif
|
||||
#ifdef XT_USE_SWPRI
|
||||
/* Storage for virtual priority mask */
|
||||
STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
|
||||
#endif
|
||||
#ifdef XT_USE_OVLY
|
||||
/* Storage for overlay state */
|
||||
STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
|
||||
#endif
|
||||
STRUCT_END(XtExcFrame)
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
#define XT_STK_NEXT1 XtExcFrameSize
|
||||
#else
|
||||
#define XT_STK_NEXT1 sizeof(XtExcFrame)
|
||||
#endif
|
||||
|
||||
/* Allocate extra storage if needed */
|
||||
#if XCHAL_EXTRA_SA_SIZE != 0
|
||||
|
||||
#if XCHAL_EXTRA_SA_ALIGN <= 16
|
||||
#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
|
||||
#else
|
||||
/* If need more alignment than stack, add space for dynamic alignment */
|
||||
#define XT_STK_EXTRA (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN)
|
||||
#endif
|
||||
#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
|
||||
|
||||
#else
|
||||
|
||||
#define XT_STK_NEXT2 XT_STK_NEXT1
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
This is the frame size. Add space for 4 registers (interruptee's base save
|
||||
area) and some space for gcc nested functions if any.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20)
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
SOLICITED STACK FRAME FOR A THREAD
|
||||
|
||||
A stack frame of this structure is allocated whenever a thread enters the
|
||||
RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
|
||||
It goes on the current thread's stack.
|
||||
|
||||
The solicited frame only includes registers that are required to be preserved
|
||||
by the callee according to the compiler's ABI conventions, some space to save
|
||||
the return address for returning to the caller, and the caller's PS register.
|
||||
|
||||
For Windowed ABI, this stack frame includes the caller's base save area.
|
||||
|
||||
Note on XT_SOL_EXIT field:
|
||||
It is necessary to distinguish a solicited from an interrupt stack frame.
|
||||
This field corresponds to XT_STK_EXIT in the interrupt stack frame and is
|
||||
always at the same offset (0). It can be written with a code (usually 0)
|
||||
to distinguish a solicted frame from an interrupt frame. An RTOS port may
|
||||
opt to ignore this field if it has another way of distinguishing frames.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
STRUCT_BEGIN
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A13, a13)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A14, a14)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A15, a15)
|
||||
#else
|
||||
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A1, a1)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
|
||||
#endif
|
||||
STRUCT_END(XtSolFrame)
|
||||
|
||||
/* Size of solicited stack frame */
|
||||
#define XT_SOL_FRMSZ ALIGNUP(0x10, XtSolFrameSize)
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
CO-PROCESSOR STATE SAVE AREA FOR A THREAD
|
||||
|
||||
The RTOS must provide an area per thread to save the state of co-processors
|
||||
when that thread does not have control. Co-processors are context-switched
|
||||
lazily (on demand) only when a new thread uses a co-processor instruction,
|
||||
otherwise a thread retains ownership of the co-processor even when it loses
|
||||
control of the processor. An Xtensa co-processor exception is triggered when
|
||||
any co-processor instruction is executed by a thread that is not the owner,
|
||||
and the context switch of that co-processor is then peformed by the handler.
|
||||
Ownership represents which thread's state is currently in the co-processor.
|
||||
|
||||
Co-processors may not be used by interrupt or exception handlers. If an
|
||||
co-processor instruction is executed by an interrupt or exception handler,
|
||||
the co-processor exception handler will trigger a kernel panic and freeze.
|
||||
This restriction is introduced to reduce the overhead of saving and restoring
|
||||
co-processor state (which can be quite large) and in particular remove that
|
||||
overhead from interrupt handlers.
|
||||
|
||||
The co-processor state save area may be in any convenient per-thread location
|
||||
such as in the thread control block or above the thread stack area. It need
|
||||
not be in the interrupt stack frame since interrupts don't use co-processors.
|
||||
|
||||
Along with the save area for each co-processor, two bitmasks with flags per
|
||||
co-processor (laid out as in the CPENABLE reg) help manage context-switching
|
||||
co-processors as efficiently as possible:
|
||||
|
||||
XT_CPENABLE
|
||||
The contents of a non-running thread's CPENABLE register.
|
||||
It represents the co-processors owned (and whose state is still needed)
|
||||
by the thread. When a thread is preempted, its CPENABLE is saved here.
|
||||
When a thread solicits a context-swtich, its CPENABLE is cleared - the
|
||||
compiler has saved the (caller-saved) co-proc state if it needs to.
|
||||
When a non-running thread loses ownership of a CP, its bit is cleared.
|
||||
When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg.
|
||||
Avoids co-processor exceptions when no change of ownership is needed.
|
||||
|
||||
XT_CPSTORED
|
||||
A bitmask with the same layout as CPENABLE, a bit per co-processor.
|
||||
Indicates whether the state of each co-processor is saved in the state
|
||||
save area. When a thread enters the kernel, only the state of co-procs
|
||||
still enabled in CPENABLE is saved. When the co-processor exception
|
||||
handler assigns ownership of a co-processor to a thread, it restores
|
||||
the saved state only if this bit is set, and clears this bit.
|
||||
|
||||
XT_CP_CS_ST
|
||||
A bitmask with the same layout as CPENABLE, a bit per co-processor.
|
||||
Indicates whether callee-saved state is saved in the state save area.
|
||||
Callee-saved state is saved by itself on a solicited context switch,
|
||||
and restored when needed by the coprocessor exception handler.
|
||||
Unsolicited switches will cause the entire coprocessor to be saved
|
||||
when necessary.
|
||||
|
||||
XT_CP_ASA
|
||||
Pointer to the aligned save area. Allows it to be aligned more than
|
||||
the overall save area (which might only be stack-aligned or TCB-aligned).
|
||||
Especially relevant for Xtensa cores configured with a very large data
|
||||
path that requires alignment greater than 16 bytes (ABI stack alignment).
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
|
||||
/* Offsets of each coprocessor save area within the 'aligned save area': */
|
||||
#define XT_CP0_SA 0
|
||||
#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE)
|
||||
#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE)
|
||||
#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE)
|
||||
#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE)
|
||||
#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE)
|
||||
#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE)
|
||||
#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE)
|
||||
#define XT_CP_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE)
|
||||
|
||||
/* Offsets within the overall save area: */
|
||||
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */
|
||||
#define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */
|
||||
#define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */
|
||||
#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */
|
||||
/* Overall size allows for dynamic alignment: */
|
||||
#define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)
|
||||
#else
|
||||
#define XT_CP_SIZE 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Macro to get the current core ID. Only uses the reg given as an argument.
|
||||
Reading PRID on the ESP32 gives us 0xCDCD on the PRO processor (0)
|
||||
and 0xABAB on the APP CPU (1). We can distinguish between the two by checking
|
||||
bit 13: it's 1 on the APP and 0 on the PRO processor.
|
||||
*/
|
||||
#ifdef __ASSEMBLER__
|
||||
.macro getcoreid reg
|
||||
rsr.prid \reg
|
||||
extui \reg,\reg,13,1
|
||||
.endm
|
||||
#endif
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#define CORE_ID_PRO 0xCDCD
|
||||
#define CORE_ID_APP 0xABAB
|
||||
#else
|
||||
#define CORE_ID_REGVAL_PRO 0xCDCD
|
||||
#define CORE_ID_REGVAL_APP 0xABAB
|
||||
|
||||
/* Included for compatibility, recommend using CORE_ID_REGVAL_PRO instead */
|
||||
#define CORE_ID_PRO CORE_ID_REGVAL_PRO
|
||||
|
||||
/* Included for compatibility, recommend using CORE_ID_REGVAL_APP instead */
|
||||
#define CORE_ID_APP CORE_ID_REGVAL_APP
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
|
||||
|
||||
Convenient where the frame size requirements are the same for both ABIs.
|
||||
ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
|
||||
ENTRY0, RET0 are for frameless functions (no locals, no calls).
|
||||
|
||||
where size = size of stack frame in bytes (must be >0 and aligned to 16).
|
||||
For framed functions the frame is created and the return address saved at
|
||||
base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
|
||||
For frameless functions, there is no frame and return address remains in a0.
|
||||
Note: Because CPP macros expand to a single line, macros requiring multi-line
|
||||
expansions are implemented as assembler macros.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/* Call0 */
|
||||
#define ENTRY(sz) entry1 sz
|
||||
.macro entry1 size=0x10
|
||||
addi sp, sp, -\size
|
||||
s32i a0, sp, 0
|
||||
.endm
|
||||
#define ENTRY0
|
||||
#define RET(sz) ret1 sz
|
||||
.macro ret1 size=0x10
|
||||
l32i a0, sp, 0
|
||||
addi sp, sp, \size
|
||||
ret
|
||||
.endm
|
||||
#define RET0 ret
|
||||
#else
|
||||
/* Windowed */
|
||||
#define ENTRY(sz) entry sp, sz
|
||||
#define ENTRY0 entry sp, 0x10
|
||||
#define RET(sz) retw
|
||||
#define RET0 retw
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* XTENSA_CONTEXT_H */
|
||||
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2006-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.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
XTENSA CONTEXT FRAMES AND MACROS FOR RTOS ASSEMBLER SOURCES
|
||||
|
||||
This header contains definitions and macros for use primarily by Xtensa
|
||||
RTOS assembly coded source files. It includes and uses the Xtensa hardware
|
||||
abstraction layer (HAL) to deal with config specifics. It may also be
|
||||
included in C source files.
|
||||
|
||||
!! Supports only Xtensa Exception Architecture 2 (XEA2). XEA1 not supported. !!
|
||||
|
||||
NOTE: The Xtensa architecture requires stack pointer alignment to 16 bytes.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef XTENSA_CONTEXT_H
|
||||
#define XTENSA_CONTEXT_H
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#include <xtensa/coreasm.h>
|
||||
#endif
|
||||
|
||||
#include <xtensa/config/tie.h>
|
||||
#include <xtensa/corebits.h>
|
||||
#include <xtensa/config/system.h>
|
||||
#include <xtensa/xtruntime-frames.h>
|
||||
#include <esp_idf_version.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))
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
Macros that help define structures for both C and assembler.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#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 //_ASMLANGUAGE || __ASSEMBLER__
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
INTERRUPT/EXCEPTION STACK FRAME FOR A THREAD OR NESTED INTERRUPT
|
||||
|
||||
A stack frame of this structure is allocated for any interrupt or exception.
|
||||
It goes on the current stack. If the RTOS has a system stack for handling
|
||||
interrupts, every thread stack must allow space for just one interrupt stack
|
||||
frame, then nested interrupt stack frames go on the system stack.
|
||||
|
||||
The frame includes basic registers (explicit) and "extra" registers introduced
|
||||
by user TIE or the use of the MAC16 option in the user's Xtensa config.
|
||||
The frame size is minimized by omitting regs not applicable to user's config.
|
||||
|
||||
For Windowed ABI, this stack frame includes the interruptee's base save area,
|
||||
another base save area to manage gcc nested functions, and a little temporary
|
||||
space to help manage the spilling of the register windows.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
STRUCT_BEGIN
|
||||
STRUCT_FIELD (long, 4, XT_STK_EXIT, exit) /* exit point for dispatch */
|
||||
STRUCT_FIELD (long, 4, XT_STK_PC, pc) /* return PC */
|
||||
STRUCT_FIELD (long, 4, XT_STK_PS, ps) /* return PS */
|
||||
STRUCT_FIELD (long, 4, XT_STK_A0, a0)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A1, a1) /* stack pointer before interrupt */
|
||||
STRUCT_FIELD (long, 4, XT_STK_A2, a2)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A3, a3)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A4, a4)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A5, a5)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A6, a6)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A7, a7)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A8, a8)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A9, a9)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A10, a10)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A11, a11)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A12, a12)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A13, a13)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A14, a14)
|
||||
STRUCT_FIELD (long, 4, XT_STK_A15, a15)
|
||||
STRUCT_FIELD (long, 4, XT_STK_SAR, sar)
|
||||
STRUCT_FIELD (long, 4, XT_STK_EXCCAUSE, exccause)
|
||||
STRUCT_FIELD (long, 4, XT_STK_EXCVADDR, excvaddr)
|
||||
#if XCHAL_HAVE_LOOPS
|
||||
STRUCT_FIELD (long, 4, XT_STK_LBEG, lbeg)
|
||||
STRUCT_FIELD (long, 4, XT_STK_LEND, lend)
|
||||
STRUCT_FIELD (long, 4, XT_STK_LCOUNT, lcount)
|
||||
#endif
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
/* Temporary space for saving stuff during window spill */
|
||||
STRUCT_FIELD (long, 4, XT_STK_TMP0, tmp0)
|
||||
STRUCT_FIELD (long, 4, XT_STK_TMP1, tmp1)
|
||||
STRUCT_FIELD (long, 4, XT_STK_TMP2, tmp2)
|
||||
#endif
|
||||
#ifdef XT_USE_SWPRI
|
||||
/* Storage for virtual priority mask */
|
||||
STRUCT_FIELD (long, 4, XT_STK_VPRI, vpri)
|
||||
#endif
|
||||
#ifdef XT_USE_OVLY
|
||||
/* Storage for overlay state */
|
||||
STRUCT_FIELD (long, 4, XT_STK_OVLY, ovly)
|
||||
#endif
|
||||
STRUCT_END(XtExcFrame)
|
||||
|
||||
#if defined(_ASMLANGUAGE) || defined(__ASSEMBLER__)
|
||||
#define XT_STK_NEXT1 XtExcFrameSize
|
||||
#else
|
||||
#define XT_STK_NEXT1 sizeof(XtExcFrame)
|
||||
#endif
|
||||
|
||||
/* Allocate extra storage if needed */
|
||||
#if XCHAL_EXTRA_SA_SIZE != 0
|
||||
|
||||
#if XCHAL_EXTRA_SA_ALIGN <= 16
|
||||
#define XT_STK_EXTRA ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1)
|
||||
#else
|
||||
/* If need more alignment than stack, add space for dynamic alignment */
|
||||
#define XT_STK_EXTRA (ALIGNUP(XCHAL_EXTRA_SA_ALIGN, XT_STK_NEXT1) + XCHAL_EXTRA_SA_ALIGN)
|
||||
#endif
|
||||
#define XT_STK_NEXT2 (XT_STK_EXTRA + XCHAL_EXTRA_SA_SIZE)
|
||||
|
||||
#else
|
||||
|
||||
#define XT_STK_NEXT2 XT_STK_NEXT1
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
This is the frame size. Add space for 4 registers (interruptee's base save
|
||||
area) and some space for gcc nested functions if any.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#define XT_STK_FRMSZ (ALIGNUP(0x10, XT_STK_NEXT2) + 0x20)
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
SOLICITED STACK FRAME FOR A THREAD
|
||||
|
||||
A stack frame of this structure is allocated whenever a thread enters the
|
||||
RTOS kernel intentionally (and synchronously) to submit to thread scheduling.
|
||||
It goes on the current thread's stack.
|
||||
|
||||
The solicited frame only includes registers that are required to be preserved
|
||||
by the callee according to the compiler's ABI conventions, some space to save
|
||||
the return address for returning to the caller, and the caller's PS register.
|
||||
|
||||
For Windowed ABI, this stack frame includes the caller's base save area.
|
||||
|
||||
Note on XT_SOL_EXIT field:
|
||||
It is necessary to distinguish a solicited from an interrupt stack frame.
|
||||
This field corresponds to XT_STK_EXIT in the interrupt stack frame and is
|
||||
always at the same offset (0). It can be written with a code (usually 0)
|
||||
to distinguish a solicted frame from an interrupt frame. An RTOS port may
|
||||
opt to ignore this field if it has another way of distinguishing frames.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
STRUCT_BEGIN
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A12, a12) /* should be on 16-byte alignment */
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A13, a13)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A14, a14)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A15, a15)
|
||||
#else
|
||||
STRUCT_FIELD (long, 4, XT_SOL_EXIT, exit)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PC, pc)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_PS, ps)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_NEXT, next)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A0, a0) /* should be on 16-byte alignment */
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A1, a1)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A2, a2)
|
||||
STRUCT_FIELD (long, 4, XT_SOL_A3, a3)
|
||||
#endif
|
||||
STRUCT_END(XtSolFrame)
|
||||
|
||||
/* Size of solicited stack frame */
|
||||
#define XT_SOL_FRMSZ ALIGNUP(0x10, XtSolFrameSize)
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
CO-PROCESSOR STATE SAVE AREA FOR A THREAD
|
||||
|
||||
The RTOS must provide an area per thread to save the state of co-processors
|
||||
when that thread does not have control. Co-processors are context-switched
|
||||
lazily (on demand) only when a new thread uses a co-processor instruction,
|
||||
otherwise a thread retains ownership of the co-processor even when it loses
|
||||
control of the processor. An Xtensa co-processor exception is triggered when
|
||||
any co-processor instruction is executed by a thread that is not the owner,
|
||||
and the context switch of that co-processor is then peformed by the handler.
|
||||
Ownership represents which thread's state is currently in the co-processor.
|
||||
|
||||
Co-processors may not be used by interrupt or exception handlers. If an
|
||||
co-processor instruction is executed by an interrupt or exception handler,
|
||||
the co-processor exception handler will trigger a kernel panic and freeze.
|
||||
This restriction is introduced to reduce the overhead of saving and restoring
|
||||
co-processor state (which can be quite large) and in particular remove that
|
||||
overhead from interrupt handlers.
|
||||
|
||||
The co-processor state save area may be in any convenient per-thread location
|
||||
such as in the thread control block or above the thread stack area. It need
|
||||
not be in the interrupt stack frame since interrupts don't use co-processors.
|
||||
|
||||
Along with the save area for each co-processor, two bitmasks with flags per
|
||||
co-processor (laid out as in the CPENABLE reg) help manage context-switching
|
||||
co-processors as efficiently as possible:
|
||||
|
||||
XT_CPENABLE
|
||||
The contents of a non-running thread's CPENABLE register.
|
||||
It represents the co-processors owned (and whose state is still needed)
|
||||
by the thread. When a thread is preempted, its CPENABLE is saved here.
|
||||
When a thread solicits a context-swtich, its CPENABLE is cleared - the
|
||||
compiler has saved the (caller-saved) co-proc state if it needs to.
|
||||
When a non-running thread loses ownership of a CP, its bit is cleared.
|
||||
When a thread runs, it's XT_CPENABLE is loaded into the CPENABLE reg.
|
||||
Avoids co-processor exceptions when no change of ownership is needed.
|
||||
|
||||
XT_CPSTORED
|
||||
A bitmask with the same layout as CPENABLE, a bit per co-processor.
|
||||
Indicates whether the state of each co-processor is saved in the state
|
||||
save area. When a thread enters the kernel, only the state of co-procs
|
||||
still enabled in CPENABLE is saved. When the co-processor exception
|
||||
handler assigns ownership of a co-processor to a thread, it restores
|
||||
the saved state only if this bit is set, and clears this bit.
|
||||
|
||||
XT_CP_CS_ST
|
||||
A bitmask with the same layout as CPENABLE, a bit per co-processor.
|
||||
Indicates whether callee-saved state is saved in the state save area.
|
||||
Callee-saved state is saved by itself on a solicited context switch,
|
||||
and restored when needed by the coprocessor exception handler.
|
||||
Unsolicited switches will cause the entire coprocessor to be saved
|
||||
when necessary.
|
||||
|
||||
XT_CP_ASA
|
||||
Pointer to the aligned save area. Allows it to be aligned more than
|
||||
the overall save area (which might only be stack-aligned or TCB-aligned).
|
||||
Especially relevant for Xtensa cores configured with a very large data
|
||||
path that requires alignment greater than 16 bytes (ABI stack alignment).
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if XCHAL_CP_NUM > 0
|
||||
|
||||
/* Offsets of each coprocessor save area within the 'aligned save area': */
|
||||
#define XT_CP0_SA 0
|
||||
#define XT_CP1_SA ALIGNUP(XCHAL_CP1_SA_ALIGN, XT_CP0_SA + XCHAL_CP0_SA_SIZE)
|
||||
#define XT_CP2_SA ALIGNUP(XCHAL_CP2_SA_ALIGN, XT_CP1_SA + XCHAL_CP1_SA_SIZE)
|
||||
#define XT_CP3_SA ALIGNUP(XCHAL_CP3_SA_ALIGN, XT_CP2_SA + XCHAL_CP2_SA_SIZE)
|
||||
#define XT_CP4_SA ALIGNUP(XCHAL_CP4_SA_ALIGN, XT_CP3_SA + XCHAL_CP3_SA_SIZE)
|
||||
#define XT_CP5_SA ALIGNUP(XCHAL_CP5_SA_ALIGN, XT_CP4_SA + XCHAL_CP4_SA_SIZE)
|
||||
#define XT_CP6_SA ALIGNUP(XCHAL_CP6_SA_ALIGN, XT_CP5_SA + XCHAL_CP5_SA_SIZE)
|
||||
#define XT_CP7_SA ALIGNUP(XCHAL_CP7_SA_ALIGN, XT_CP6_SA + XCHAL_CP6_SA_SIZE)
|
||||
#define XT_CP_SA_SIZE ALIGNUP(16, XT_CP7_SA + XCHAL_CP7_SA_SIZE)
|
||||
|
||||
/* Offsets within the overall save area: */
|
||||
#define XT_CPENABLE 0 /* (2 bytes) coprocessors active for this thread */
|
||||
#define XT_CPSTORED 2 /* (2 bytes) coprocessors saved for this thread */
|
||||
#define XT_CP_CS_ST 4 /* (2 bytes) coprocessor callee-saved regs stored for this thread */
|
||||
#define XT_CP_ASA 8 /* (4 bytes) ptr to aligned save area */
|
||||
/* Overall size allows for dynamic alignment: */
|
||||
#define XT_CP_SIZE (12 + XT_CP_SA_SIZE + XCHAL_TOTAL_SA_ALIGN)
|
||||
#else
|
||||
#define XT_CP_SIZE 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
Macro to get the current core ID. Only uses the reg given as an argument.
|
||||
Reading PRID on the ESP32 gives us 0xCDCD on the PRO processor (0)
|
||||
and 0xABAB on the APP CPU (1). We can distinguish between the two by checking
|
||||
bit 13: it's 1 on the APP and 0 on the PRO processor.
|
||||
*/
|
||||
#ifdef __ASSEMBLER__
|
||||
.macro getcoreid reg
|
||||
rsr.prid \reg
|
||||
extui \reg,\reg,13,1
|
||||
.endm
|
||||
#endif
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#define CORE_ID_PRO 0xCDCD
|
||||
#define CORE_ID_APP 0xABAB
|
||||
#else
|
||||
#define CORE_ID_REGVAL_PRO 0xCDCD
|
||||
#define CORE_ID_REGVAL_APP 0xABAB
|
||||
|
||||
/* Included for compatibility, recommend using CORE_ID_REGVAL_PRO instead */
|
||||
#define CORE_ID_PRO CORE_ID_REGVAL_PRO
|
||||
|
||||
/* Included for compatibility, recommend using CORE_ID_REGVAL_APP instead */
|
||||
#define CORE_ID_APP CORE_ID_REGVAL_APP
|
||||
#endif
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
MACROS TO HANDLE ABI SPECIFICS OF FUNCTION ENTRY AND RETURN
|
||||
|
||||
Convenient where the frame size requirements are the same for both ABIs.
|
||||
ENTRY(sz), RET(sz) are for framed functions (have locals or make calls).
|
||||
ENTRY0, RET0 are for frameless functions (no locals, no calls).
|
||||
|
||||
where size = size of stack frame in bytes (must be >0 and aligned to 16).
|
||||
For framed functions the frame is created and the return address saved at
|
||||
base of frame (Call0 ABI) or as determined by hardware (Windowed ABI).
|
||||
For frameless functions, there is no frame and return address remains in a0.
|
||||
Note: Because CPP macros expand to a single line, macros requiring multi-line
|
||||
expansions are implemented as assembler macros.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifdef __ASSEMBLER__
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/* Call0 */
|
||||
#define ENTRY(sz) entry1 sz
|
||||
.macro entry1 size=0x10
|
||||
addi sp, sp, -\size
|
||||
s32i a0, sp, 0
|
||||
.endm
|
||||
#define ENTRY0
|
||||
#define RET(sz) ret1 sz
|
||||
.macro ret1 size=0x10
|
||||
l32i a0, sp, 0
|
||||
addi sp, sp, \size
|
||||
ret
|
||||
.endm
|
||||
#define RET0 ret
|
||||
#else
|
||||
/* Windowed */
|
||||
#define ENTRY(sz) entry sp, sz
|
||||
#define ENTRY0 entry sp, 0x10
|
||||
#define RET(sz) retw
|
||||
#define RET0 retw
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* XTENSA_CONTEXT_H */
|
||||
|
||||
|
|
1056
portable/ThirdParty/GCC/Xtensa_ESP32/port.c
vendored
1056
portable/ThirdParty/GCC/Xtensa_ESP32/port.c
vendored
File diff suppressed because it is too large
Load diff
1368
portable/ThirdParty/GCC/Xtensa_ESP32/portasm.S
vendored
1368
portable/ThirdParty/GCC/Xtensa_ESP32/portasm.S
vendored
File diff suppressed because it is too large
Load diff
234
portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
vendored
234
portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
vendored
|
@ -1,117 +1,117 @@
|
|||
/*
|
||||
* Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
|
||||
* Copyright (C) 2015 Real Time Engineers Ltd.
|
||||
*
|
||||
* All rights reserved
|
||||
*
|
||||
* 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: https://www.FreeRTOS.org/a00114.html
|
||||
*/
|
||||
|
||||
/* This header exists for performance reasons, in order to inline the
|
||||
* implementation of vPortCPUAcquireMutexIntsDisabled and
|
||||
* vPortCPUReleaseMutexIntsDisabled into the
|
||||
* vTaskEnterCritical/vTaskExitCritical functions in task.c as well as the
|
||||
* vPortCPUAcquireMutex/vPortCPUReleaseMutex implementations.
|
||||
*
|
||||
* Normally this kind of performance hack is over the top, but
|
||||
* vTaskEnterCritical/vTaskExitCritical is called a great
|
||||
* deal by FreeRTOS internals.
|
||||
*
|
||||
* It should be #included by freertos port.c or tasks.c, in esp-idf.
|
||||
*
|
||||
* The way it works is that it essentially uses portmux_impl.inc.h as a
|
||||
* generator template of sorts. When no external memory is used, this
|
||||
* template is only used to generate the vPortCPUAcquireMutexIntsDisabledInternal
|
||||
* and vPortCPUReleaseMutexIntsDisabledInternal functions, which use S32C1 to
|
||||
* do an atomic compare & swap. When external memory is used the functions
|
||||
* vPortCPUAcquireMutexIntsDisabledExtram and vPortCPUReleaseMutexIntsDisabledExtram
|
||||
* are also generated, which use uxPortCompareSetExtram to fake the S32C1 instruction.
|
||||
* The wrapper functions vPortCPUAcquireMutexIntsDisabled and
|
||||
* vPortCPUReleaseMutexIntsDisabled will then use the appropriate function to do the
|
||||
* actual lock/unlock.
|
||||
*/
|
||||
#include "soc/cpu.h"
|
||||
#include "portable.h"
|
||||
|
||||
/* XOR one core ID with this value to get the other core ID */
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#define CORE_ID_XOR_SWAP ( CORE_ID_PRO ^ CORE_ID_APP )
|
||||
#else
|
||||
#define CORE_ID_REGVAL_XOR_SWAP (CORE_ID_REGVAL_PRO ^ CORE_ID_REGVAL_APP)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*Define the mux routines for use with muxes in internal RAM */
|
||||
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledInternal
|
||||
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledInternal
|
||||
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSet
|
||||
#include "portmux_impl.inc.h"
|
||||
#undef PORTMUX_AQUIRE_MUX_FN_NAME
|
||||
#undef PORTMUX_RELEASE_MUX_FN_NAME
|
||||
#undef PORTMUX_COMPARE_SET_FN_NAME
|
||||
|
||||
|
||||
#if defined( CONFIG_SPIRAM_SUPPORT )
|
||||
|
||||
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledExtram
|
||||
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledExtram
|
||||
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSetExtram
|
||||
#include "portmux_impl.inc.h"
|
||||
#undef PORTMUX_AQUIRE_MUX_FN_NAME
|
||||
#undef PORTMUX_RELEASE_MUX_FN_NAME
|
||||
#undef PORTMUX_COMPARE_SET_FN_NAME
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE * mux, int timeout_cycles, const char * fnName, int line
|
||||
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE * mux, const char * fnName, int line
|
||||
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( x ) x, timeout_cycles, fnName, line
|
||||
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS( x ) x, fnName, line
|
||||
#else
|
||||
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE * mux, int timeout_cycles
|
||||
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE * mux
|
||||
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( x ) x, timeout_cycles
|
||||
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS( x ) x
|
||||
#endif
|
||||
|
||||
|
||||
static inline bool __attribute__( ( always_inline ) ) vPortCPUAcquireMutexIntsDisabled( PORTMUX_AQUIRE_MUX_FN_ARGS )
|
||||
{
|
||||
#if defined( CONFIG_SPIRAM_SUPPORT )
|
||||
if( esp_ptr_external_ram( mux ) )
|
||||
{
|
||||
return vPortCPUAcquireMutexIntsDisabledExtram( PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( mux ) );
|
||||
}
|
||||
#endif
|
||||
return vPortCPUAcquireMutexIntsDisabledInternal( PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( mux ) );
|
||||
}
|
||||
|
||||
|
||||
static inline void vPortCPUReleaseMutexIntsDisabled( PORTMUX_RELEASE_MUX_FN_ARGS )
|
||||
{
|
||||
#if defined( CONFIG_SPIRAM_SUPPORT )
|
||||
if( esp_ptr_external_ram( mux ) )
|
||||
{
|
||||
vPortCPUReleaseMutexIntsDisabledExtram( PORTMUX_RELEASE_MUX_FN_CALL_ARGS( mux ) );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
vPortCPUReleaseMutexIntsDisabledInternal( PORTMUX_RELEASE_MUX_FN_CALL_ARGS( mux ) );
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
|
||||
* Copyright (C) 2015 Real Time Engineers Ltd.
|
||||
*
|
||||
* All rights reserved
|
||||
*
|
||||
* 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: https://www.FreeRTOS.org/a00114.html
|
||||
*/
|
||||
|
||||
/* This header exists for performance reasons, in order to inline the
|
||||
* implementation of vPortCPUAcquireMutexIntsDisabled and
|
||||
* vPortCPUReleaseMutexIntsDisabled into the
|
||||
* vTaskEnterCritical/vTaskExitCritical functions in task.c as well as the
|
||||
* vPortCPUAcquireMutex/vPortCPUReleaseMutex implementations.
|
||||
*
|
||||
* Normally this kind of performance hack is over the top, but
|
||||
* vTaskEnterCritical/vTaskExitCritical is called a great
|
||||
* deal by FreeRTOS internals.
|
||||
*
|
||||
* It should be #included by freertos port.c or tasks.c, in esp-idf.
|
||||
*
|
||||
* The way it works is that it essentially uses portmux_impl.inc.h as a
|
||||
* generator template of sorts. When no external memory is used, this
|
||||
* template is only used to generate the vPortCPUAcquireMutexIntsDisabledInternal
|
||||
* and vPortCPUReleaseMutexIntsDisabledInternal functions, which use S32C1 to
|
||||
* do an atomic compare & swap. When external memory is used the functions
|
||||
* vPortCPUAcquireMutexIntsDisabledExtram and vPortCPUReleaseMutexIntsDisabledExtram
|
||||
* are also generated, which use uxPortCompareSetExtram to fake the S32C1 instruction.
|
||||
* The wrapper functions vPortCPUAcquireMutexIntsDisabled and
|
||||
* vPortCPUReleaseMutexIntsDisabled will then use the appropriate function to do the
|
||||
* actual lock/unlock.
|
||||
*/
|
||||
#include "soc/cpu.h"
|
||||
#include "portable.h"
|
||||
|
||||
/* XOR one core ID with this value to get the other core ID */
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#define CORE_ID_XOR_SWAP ( CORE_ID_PRO ^ CORE_ID_APP )
|
||||
#else
|
||||
#define CORE_ID_REGVAL_XOR_SWAP (CORE_ID_REGVAL_PRO ^ CORE_ID_REGVAL_APP)
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*Define the mux routines for use with muxes in internal RAM */
|
||||
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledInternal
|
||||
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledInternal
|
||||
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSet
|
||||
#include "portmux_impl.inc.h"
|
||||
#undef PORTMUX_AQUIRE_MUX_FN_NAME
|
||||
#undef PORTMUX_RELEASE_MUX_FN_NAME
|
||||
#undef PORTMUX_COMPARE_SET_FN_NAME
|
||||
|
||||
|
||||
#if defined( CONFIG_SPIRAM_SUPPORT )
|
||||
|
||||
#define PORTMUX_AQUIRE_MUX_FN_NAME vPortCPUAcquireMutexIntsDisabledExtram
|
||||
#define PORTMUX_RELEASE_MUX_FN_NAME vPortCPUReleaseMutexIntsDisabledExtram
|
||||
#define PORTMUX_COMPARE_SET_FN_NAME uxPortCompareSetExtram
|
||||
#include "portmux_impl.inc.h"
|
||||
#undef PORTMUX_AQUIRE_MUX_FN_NAME
|
||||
#undef PORTMUX_RELEASE_MUX_FN_NAME
|
||||
#undef PORTMUX_COMPARE_SET_FN_NAME
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE * mux, int timeout_cycles, const char * fnName, int line
|
||||
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE * mux, const char * fnName, int line
|
||||
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( x ) x, timeout_cycles, fnName, line
|
||||
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS( x ) x, fnName, line
|
||||
#else
|
||||
#define PORTMUX_AQUIRE_MUX_FN_ARGS portMUX_TYPE * mux, int timeout_cycles
|
||||
#define PORTMUX_RELEASE_MUX_FN_ARGS portMUX_TYPE * mux
|
||||
#define PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( x ) x, timeout_cycles
|
||||
#define PORTMUX_RELEASE_MUX_FN_CALL_ARGS( x ) x
|
||||
#endif
|
||||
|
||||
|
||||
static inline bool __attribute__( ( always_inline ) ) vPortCPUAcquireMutexIntsDisabled( PORTMUX_AQUIRE_MUX_FN_ARGS )
|
||||
{
|
||||
#if defined( CONFIG_SPIRAM_SUPPORT )
|
||||
if( esp_ptr_external_ram( mux ) )
|
||||
{
|
||||
return vPortCPUAcquireMutexIntsDisabledExtram( PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( mux ) );
|
||||
}
|
||||
#endif
|
||||
return vPortCPUAcquireMutexIntsDisabledInternal( PORTMUX_AQUIRE_MUX_FN_CALL_ARGS( mux ) );
|
||||
}
|
||||
|
||||
|
||||
static inline void vPortCPUReleaseMutexIntsDisabled( PORTMUX_RELEASE_MUX_FN_ARGS )
|
||||
{
|
||||
#if defined( CONFIG_SPIRAM_SUPPORT )
|
||||
if( esp_ptr_external_ram( mux ) )
|
||||
{
|
||||
vPortCPUReleaseMutexIntsDisabledExtram( PORTMUX_RELEASE_MUX_FN_CALL_ARGS( mux ) );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
vPortCPUReleaseMutexIntsDisabledInternal( PORTMUX_RELEASE_MUX_FN_CALL_ARGS( mux ) );
|
||||
}
|
||||
|
|
|
@ -1,212 +1,212 @@
|
|||
/*
|
||||
* Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
|
||||
* Copyright (C) 2015 Real Time Engineers Ltd.
|
||||
*
|
||||
* All rights reserved
|
||||
*
|
||||
* 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: https://www.FreeRTOS.org/a00114.html
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Warning: funky preprocessor hackery ahead. Including these headers will generate two
|
||||
* functions, which names are defined by the preprocessor macros
|
||||
* PORTMUX_AQUIRE_MUX_FN_NAME and PORTMUX_RELEASE_MUX_FN_NAME. In order to do the compare
|
||||
* and exchange function, they will use whatever PORTMUX_COMPARE_SET_FN_NAME resolves to.
|
||||
*
|
||||
* In some scenarios, this header is included *twice* in portmux_impl.h: one time
|
||||
* for the 'normal' mux code which uses a compare&exchange routine, another time
|
||||
* to generate code for a second set of these routines that use a second mux
|
||||
* (in internal ram) to fake a compare&exchange on a variable in external memory.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static inline bool __attribute__( ( always_inline ) )
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
PORTMUX_AQUIRE_MUX_FN_NAME( portMUX_TYPE * mux,
|
||||
int timeout_cycles,
|
||||
const char * fnName,
|
||||
int line )
|
||||
{
|
||||
#else
|
||||
PORTMUX_AQUIRE_MUX_FN_NAME( portMUX_TYPE * mux, int timeout_cycles )
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
uint32_t res;
|
||||
portBASE_TYPE coreID, otherCoreID;
|
||||
uint32_t ccount_start;
|
||||
bool set_timeout = timeout_cycles > portMUX_NO_TIMEOUT;
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
if( !set_timeout )
|
||||
{
|
||||
timeout_cycles = 10000; /* Always set a timeout in debug mode */
|
||||
set_timeout = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( set_timeout ) /* Timeout */
|
||||
{
|
||||
RSR( CCOUNT, ccount_start );
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
uint32_t owner = mux->owner;
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
if( ( owner != portMUX_FREE_VAL ) && ( owner != CORE_ID_PRO ) && ( owner != CORE_ID_APP ) )
|
||||
#else
|
||||
if (owner != portMUX_FREE_VAL && owner != CORE_ID_REGVAL_PRO && owner != CORE_ID_REGVAL_APP)
|
||||
#endif
|
||||
{
|
||||
ets_printf( "ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line );
|
||||
mux->owner = portMUX_FREE_VAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Spin until we own the core */
|
||||
|
||||
RSR( PRID, coreID );
|
||||
|
||||
/* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP),
|
||||
* not the 0/1 value returned by xPortGetCoreID()
|
||||
*/
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
otherCoreID = CORE_ID_XOR_SWAP ^ coreID;
|
||||
#else
|
||||
otherCoreID = CORE_ID_REGVAL_XOR_SWAP ^ coreID;
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
/* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO,
|
||||
* CORE_ID_APP:
|
||||
*
|
||||
* - If portMUX_FREE_VAL, we want to atomically set to 'coreID'.
|
||||
* - If "our" coreID, we can drop through immediately.
|
||||
* - If "otherCoreID", we spin here.
|
||||
*/
|
||||
res = coreID;
|
||||
PORTMUX_COMPARE_SET_FN_NAME( &mux->owner, portMUX_FREE_VAL, &res );
|
||||
|
||||
if( res != otherCoreID )
|
||||
{
|
||||
break; /* mux->owner is "our" coreID */
|
||||
}
|
||||
|
||||
if( set_timeout )
|
||||
{
|
||||
uint32_t ccount_now;
|
||||
RSR( CCOUNT, ccount_now );
|
||||
|
||||
if( ccount_now - ccount_start > ( unsigned ) timeout_cycles )
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
ets_printf( "Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line );
|
||||
ets_printf( "Owner 0x%x count %d\n", mux->owner, mux->count );
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while( 1 );
|
||||
|
||||
assert( res == coreID || res == portMUX_FREE_VAL ); /* any other value implies memory corruption or uninitialized mux */
|
||||
assert( ( res == portMUX_FREE_VAL ) == ( mux->count == 0 ) ); /* we're first to lock iff count is zero */
|
||||
assert( mux->count < 0xFF ); /* Bad count value implies memory corruption */
|
||||
|
||||
/* now we own it, we can increment the refcount */
|
||||
mux->count++;
|
||||
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
if( res == portMUX_FREE_VAL ) /*initial lock */
|
||||
{
|
||||
mux->lastLockedFn = fnName;
|
||||
mux->lastLockedLine = line;
|
||||
}
|
||||
else
|
||||
{
|
||||
ets_printf( "Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count - 1,
|
||||
mux->lastLockedFn, mux->lastLockedLine, fnName, line );
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_PORTMUX_DEBUG */
|
||||
#endif /* CONFIG_FREERTOS_UNICORE */
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
static inline void PORTMUX_RELEASE_MUX_FN_NAME( portMUX_TYPE * mux,
|
||||
const char * fnName,
|
||||
int line )
|
||||
{
|
||||
#else
|
||||
static inline void PORTMUX_RELEASE_MUX_FN_NAME( portMUX_TYPE * mux )
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
portBASE_TYPE coreID;
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
const char * lastLockedFn = mux->lastLockedFn;
|
||||
int lastLockedLine = mux->lastLockedLine;
|
||||
mux->lastLockedFn = fnName;
|
||||
mux->lastLockedLine = line;
|
||||
uint32_t owner = mux->owner;
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
if( ( owner != portMUX_FREE_VAL ) && ( owner != CORE_ID_PRO ) && ( owner != CORE_ID_APP ) )
|
||||
#else
|
||||
if (owner != portMUX_FREE_VAL && owner != CORE_ID_REGVAL_PRO && owner != CORE_ID_REGVAL_APP)
|
||||
#endif
|
||||
{
|
||||
ets_printf( "ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner );
|
||||
}
|
||||
#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
|
||||
|
||||
#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined( NDEBUG )
|
||||
RSR( PRID, coreID );
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
if( coreID != mux->owner )
|
||||
{
|
||||
ets_printf( "ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux );
|
||||
ets_printf( "Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line );
|
||||
}
|
||||
#endif
|
||||
|
||||
assert( coreID == mux->owner ); /* This is a mutex we didn't lock, or it's corrupt */
|
||||
|
||||
mux->count--;
|
||||
|
||||
if( mux->count == 0 )
|
||||
{
|
||||
mux->owner = portMUX_FREE_VAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( mux->count < 0x100 ); /* Indicates memory corruption */
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
|
||||
ets_printf( "Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line );
|
||||
#endif
|
||||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
/*
|
||||
* Copyright (C) 2016-2017 Espressif Shanghai PTE LTD
|
||||
* Copyright (C) 2015 Real Time Engineers Ltd.
|
||||
*
|
||||
* All rights reserved
|
||||
*
|
||||
* 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: https://www.FreeRTOS.org/a00114.html
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Warning: funky preprocessor hackery ahead. Including these headers will generate two
|
||||
* functions, which names are defined by the preprocessor macros
|
||||
* PORTMUX_AQUIRE_MUX_FN_NAME and PORTMUX_RELEASE_MUX_FN_NAME. In order to do the compare
|
||||
* and exchange function, they will use whatever PORTMUX_COMPARE_SET_FN_NAME resolves to.
|
||||
*
|
||||
* In some scenarios, this header is included *twice* in portmux_impl.h: one time
|
||||
* for the 'normal' mux code which uses a compare&exchange routine, another time
|
||||
* to generate code for a second set of these routines that use a second mux
|
||||
* (in internal ram) to fake a compare&exchange on a variable in external memory.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
static inline bool __attribute__( ( always_inline ) )
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
PORTMUX_AQUIRE_MUX_FN_NAME( portMUX_TYPE * mux,
|
||||
int timeout_cycles,
|
||||
const char * fnName,
|
||||
int line )
|
||||
{
|
||||
#else
|
||||
PORTMUX_AQUIRE_MUX_FN_NAME( portMUX_TYPE * mux, int timeout_cycles )
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
uint32_t res;
|
||||
portBASE_TYPE coreID, otherCoreID;
|
||||
uint32_t ccount_start;
|
||||
bool set_timeout = timeout_cycles > portMUX_NO_TIMEOUT;
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
if( !set_timeout )
|
||||
{
|
||||
timeout_cycles = 10000; /* Always set a timeout in debug mode */
|
||||
set_timeout = true;
|
||||
}
|
||||
#endif
|
||||
|
||||
if( set_timeout ) /* Timeout */
|
||||
{
|
||||
RSR( CCOUNT, ccount_start );
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
uint32_t owner = mux->owner;
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
if( ( owner != portMUX_FREE_VAL ) && ( owner != CORE_ID_PRO ) && ( owner != CORE_ID_APP ) )
|
||||
#else
|
||||
if (owner != portMUX_FREE_VAL && owner != CORE_ID_REGVAL_PRO && owner != CORE_ID_REGVAL_APP)
|
||||
#endif
|
||||
{
|
||||
ets_printf( "ERROR: vPortCPUAcquireMutex: mux %p is uninitialized (0x%X)! Called from %s line %d.\n", mux, owner, fnName, line );
|
||||
mux->owner = portMUX_FREE_VAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Spin until we own the core */
|
||||
|
||||
RSR( PRID, coreID );
|
||||
|
||||
/* Note: coreID is the full 32 bit core ID (CORE_ID_PRO/CORE_ID_APP),
|
||||
* not the 0/1 value returned by xPortGetCoreID()
|
||||
*/
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
otherCoreID = CORE_ID_XOR_SWAP ^ coreID;
|
||||
#else
|
||||
otherCoreID = CORE_ID_REGVAL_XOR_SWAP ^ coreID;
|
||||
#endif
|
||||
|
||||
do
|
||||
{
|
||||
/* mux->owner should be one of portMUX_FREE_VAL, CORE_ID_PRO,
|
||||
* CORE_ID_APP:
|
||||
*
|
||||
* - If portMUX_FREE_VAL, we want to atomically set to 'coreID'.
|
||||
* - If "our" coreID, we can drop through immediately.
|
||||
* - If "otherCoreID", we spin here.
|
||||
*/
|
||||
res = coreID;
|
||||
PORTMUX_COMPARE_SET_FN_NAME( &mux->owner, portMUX_FREE_VAL, &res );
|
||||
|
||||
if( res != otherCoreID )
|
||||
{
|
||||
break; /* mux->owner is "our" coreID */
|
||||
}
|
||||
|
||||
if( set_timeout )
|
||||
{
|
||||
uint32_t ccount_now;
|
||||
RSR( CCOUNT, ccount_now );
|
||||
|
||||
if( ccount_now - ccount_start > ( unsigned ) timeout_cycles )
|
||||
{
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
ets_printf( "Timeout on mux! last non-recursive lock %s line %d, curr %s line %d\n", mux->lastLockedFn, mux->lastLockedLine, fnName, line );
|
||||
ets_printf( "Owner 0x%x count %d\n", mux->owner, mux->count );
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while( 1 );
|
||||
|
||||
assert( res == coreID || res == portMUX_FREE_VAL ); /* any other value implies memory corruption or uninitialized mux */
|
||||
assert( ( res == portMUX_FREE_VAL ) == ( mux->count == 0 ) ); /* we're first to lock iff count is zero */
|
||||
assert( mux->count < 0xFF ); /* Bad count value implies memory corruption */
|
||||
|
||||
/* now we own it, we can increment the refcount */
|
||||
mux->count++;
|
||||
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
if( res == portMUX_FREE_VAL ) /*initial lock */
|
||||
{
|
||||
mux->lastLockedFn = fnName;
|
||||
mux->lastLockedLine = line;
|
||||
}
|
||||
else
|
||||
{
|
||||
ets_printf( "Recursive lock: count=%d last non-recursive lock %s line %d, curr %s line %d\n", mux->count - 1,
|
||||
mux->lastLockedFn, mux->lastLockedLine, fnName, line );
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_PORTMUX_DEBUG */
|
||||
#endif /* CONFIG_FREERTOS_UNICORE */
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
static inline void PORTMUX_RELEASE_MUX_FN_NAME( portMUX_TYPE * mux,
|
||||
const char * fnName,
|
||||
int line )
|
||||
{
|
||||
#else
|
||||
static inline void PORTMUX_RELEASE_MUX_FN_NAME( portMUX_TYPE * mux )
|
||||
{
|
||||
#endif
|
||||
|
||||
|
||||
#if !CONFIG_FREERTOS_UNICORE
|
||||
portBASE_TYPE coreID;
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
const char * lastLockedFn = mux->lastLockedFn;
|
||||
int lastLockedLine = mux->lastLockedLine;
|
||||
mux->lastLockedFn = fnName;
|
||||
mux->lastLockedLine = line;
|
||||
uint32_t owner = mux->owner;
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
if( ( owner != portMUX_FREE_VAL ) && ( owner != CORE_ID_PRO ) && ( owner != CORE_ID_APP ) )
|
||||
#else
|
||||
if (owner != portMUX_FREE_VAL && owner != CORE_ID_REGVAL_PRO && owner != CORE_ID_REGVAL_APP)
|
||||
#endif
|
||||
{
|
||||
ets_printf( "ERROR: vPortCPUReleaseMutex: mux %p is invalid (0x%x)!\n", mux, mux->owner );
|
||||
}
|
||||
#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
|
||||
|
||||
#if CONFIG_FREERTOS_PORTMUX_DEBUG || !defined( NDEBUG )
|
||||
RSR( PRID, coreID );
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
|
||||
if( coreID != mux->owner )
|
||||
{
|
||||
ets_printf( "ERROR: vPortCPUReleaseMutex: mux %p was already unlocked!\n", mux );
|
||||
ets_printf( "Last non-recursive unlock %s line %d, curr unlock %s line %d\n", lastLockedFn, lastLockedLine, fnName, line );
|
||||
}
|
||||
#endif
|
||||
|
||||
assert( coreID == mux->owner ); /* This is a mutex we didn't lock, or it's corrupt */
|
||||
|
||||
mux->count--;
|
||||
|
||||
if( mux->count == 0 )
|
||||
{
|
||||
mux->owner = portMUX_FREE_VAL;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( mux->count < 0x100 ); /* Indicates memory corruption */
|
||||
#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG_RECURSIVE
|
||||
ets_printf( "Recursive unlock: count=%d last locked %s line %d, curr %s line %d\n", mux->count, lastLockedFn, lastLockedLine, fnName, line );
|
||||
#endif
|
||||
}
|
||||
#endif //!CONFIG_FREERTOS_UNICORE
|
||||
}
|
||||
|
|
1406
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_context.S
vendored
1406
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_context.S
vendored
File diff suppressed because it is too large
Load diff
126
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c
vendored
126
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c
vendored
|
@ -1,63 +1,63 @@
|
|||
/*******************************************************************************
|
||||
* // 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.
|
||||
* --------------------------------------------------------------------------------
|
||||
*
|
||||
* XTENSA INITIALIZATION ROUTINES CODED IN C
|
||||
*
|
||||
* This file contains miscellaneous Xtensa RTOS-generic initialization functions
|
||||
* that are implemented in C.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifdef XT_BOARD
|
||||
#include <xtensa/xtbsp.h>
|
||||
#endif
|
||||
|
||||
#include "xtensa_rtos.h"
|
||||
#include "esp_idf_version.h"
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#include "esp_clk.h"
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/clk.h"
|
||||
#endif
|
||||
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
|
||||
|
||||
#ifdef XT_RTOS_TIMER_INT
|
||||
|
||||
unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */
|
||||
|
||||
void _xt_tick_divisor_init( void )
|
||||
{
|
||||
_xt_tick_divisor = esp_clk_cpu_freq() / XT_TICK_PER_SEC;
|
||||
}
|
||||
|
||||
/* Deprecated, to be removed */
|
||||
int xt_clock_freq( void )
|
||||
{
|
||||
return esp_clk_cpu_freq();
|
||||
}
|
||||
|
||||
#endif /* XT_RTOS_TIMER_INT */
|
||||
/*******************************************************************************
|
||||
* // 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.
|
||||
* --------------------------------------------------------------------------------
|
||||
*
|
||||
* XTENSA INITIALIZATION ROUTINES CODED IN C
|
||||
*
|
||||
* This file contains miscellaneous Xtensa RTOS-generic initialization functions
|
||||
* that are implemented in C.
|
||||
*
|
||||
*******************************************************************************/
|
||||
|
||||
|
||||
#ifdef XT_BOARD
|
||||
#include <xtensa/xtbsp.h>
|
||||
#endif
|
||||
|
||||
#include "xtensa_rtos.h"
|
||||
#include "esp_idf_version.h"
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#include "esp_clk.h"
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/clk.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/clk.h"
|
||||
#endif
|
||||
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
|
||||
|
||||
#ifdef XT_RTOS_TIMER_INT
|
||||
|
||||
unsigned _xt_tick_divisor = 0; /* cached number of cycles per tick */
|
||||
|
||||
void _xt_tick_divisor_init( void )
|
||||
{
|
||||
_xt_tick_divisor = esp_clk_cpu_freq() / XT_TICK_PER_SEC;
|
||||
}
|
||||
|
||||
/* Deprecated, to be removed */
|
||||
int xt_clock_freq( void )
|
||||
{
|
||||
return esp_clk_cpu_freq();
|
||||
}
|
||||
|
||||
#endif /* XT_RTOS_TIMER_INT */
|
||||
|
|
366
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
vendored
366
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
vendored
|
@ -1,183 +1,183 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2006-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.
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Xtensa-specific interrupt and exception functions for RTOS ports.
|
||||
* Also see xtensa_intr_asm.S.
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <xtensa/config/core.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/portable.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#include "rom/ets_sys.h"
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#endif
|
||||
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
|
||||
|
||||
#if XCHAL_HAVE_EXCEPTIONS
|
||||
|
||||
/* Handler table is in xtensa_intr_asm.S */
|
||||
|
||||
extern xt_exc_handler _xt_exception_table[ XCHAL_EXCCAUSE_NUM * portNUM_PROCESSORS ];
|
||||
|
||||
|
||||
/*
|
||||
* Default handler for unhandled exceptions.
|
||||
* CHANGED: We do this in panic.c now
|
||||
*/
|
||||
|
||||
/*void xt_unhandled_exception(XtExcFrame *frame) */
|
||||
/*{ */
|
||||
/*exit(-1); */
|
||||
/*} */
|
||||
extern void xt_unhandled_exception( XtExcFrame * frame );
|
||||
|
||||
|
||||
/*
|
||||
* This function registers a handler for the specified exception.
|
||||
* The function returns the address of the previous handler.
|
||||
* On error, it returns 0.
|
||||
*/
|
||||
xt_exc_handler xt_set_exception_handler( int n,
|
||||
xt_exc_handler f )
|
||||
{
|
||||
xt_exc_handler old;
|
||||
|
||||
if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) )
|
||||
{
|
||||
return 0; /* invalid exception number */
|
||||
}
|
||||
|
||||
/* Convert exception number to _xt_exception_table name */
|
||||
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||
old = _xt_exception_table[ n ];
|
||||
|
||||
if( f )
|
||||
{
|
||||
_xt_exception_table[ n ] = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
_xt_exception_table[ n ] = &xt_unhandled_exception;
|
||||
}
|
||||
|
||||
return( ( old == &xt_unhandled_exception ) ? 0 : old );
|
||||
}
|
||||
|
||||
#endif /* if XCHAL_HAVE_EXCEPTIONS */
|
||||
|
||||
#if XCHAL_HAVE_INTERRUPTS
|
||||
|
||||
/* Handler table is in xtensa_intr_asm.S */
|
||||
|
||||
typedef struct xt_handler_table_entry
|
||||
{
|
||||
void * handler;
|
||||
void * arg;
|
||||
} xt_handler_table_entry;
|
||||
|
||||
extern xt_handler_table_entry _xt_interrupt_table[ XCHAL_NUM_INTERRUPTS * portNUM_PROCESSORS ];
|
||||
|
||||
|
||||
/*
|
||||
* Default handler for unhandled interrupts.
|
||||
*/
|
||||
void xt_unhandled_interrupt( void * arg )
|
||||
{
|
||||
ets_printf( "Unhandled interrupt %d on cpu %d!\n", ( int ) arg, xPortGetCoreID() );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function registers a handler for the specified interrupt. The "arg"
|
||||
* parameter specifies the argument to be passed to the handler when it is
|
||||
* invoked. The function returns the address of the previous handler.
|
||||
* On error, it returns 0.
|
||||
*/
|
||||
xt_handler xt_set_interrupt_handler( int n,
|
||||
xt_handler f,
|
||||
void * arg )
|
||||
{
|
||||
xt_handler_table_entry * entry;
|
||||
xt_handler old;
|
||||
|
||||
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
|
||||
{
|
||||
return 0; /* invalid interrupt number */
|
||||
}
|
||||
|
||||
if( Xthal_intlevel[ n ] > XCHAL_EXCM_LEVEL )
|
||||
{
|
||||
return 0; /* priority level too high to safely handle in C */
|
||||
}
|
||||
|
||||
/* Convert exception number to _xt_exception_table name */
|
||||
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||
|
||||
entry = _xt_interrupt_table + n;
|
||||
old = entry->handler;
|
||||
|
||||
if( f )
|
||||
{
|
||||
entry->handler = f;
|
||||
entry->arg = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->handler = &xt_unhandled_interrupt;
|
||||
entry->arg = ( void * ) n;
|
||||
}
|
||||
|
||||
return( ( old == &xt_unhandled_interrupt ) ? 0 : old );
|
||||
}
|
||||
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
void * xt_get_interrupt_handler_arg( int n )
|
||||
{
|
||||
xt_handler_table_entry * entry;
|
||||
|
||||
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
|
||||
{
|
||||
return 0; /* invalid interrupt number */
|
||||
}
|
||||
|
||||
/* Convert exception number to _xt_exception_table name */
|
||||
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||
|
||||
entry = _xt_interrupt_table + n;
|
||||
return entry->arg;
|
||||
}
|
||||
#endif /* if CONFIG_SYSVIEW_ENABLE */
|
||||
|
||||
#endif /* XCHAL_HAVE_INTERRUPTS */
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2006-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.
|
||||
******************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Xtensa-specific interrupt and exception functions for RTOS ports.
|
||||
* Also see xtensa_intr_asm.S.
|
||||
******************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <xtensa/config/core.h>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/xtensa_api.h"
|
||||
#include "freertos/portable.h"
|
||||
#include "esp_idf_version.h"
|
||||
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#include "rom/ets_sys.h"
|
||||
#else
|
||||
#if CONFIG_IDF_TARGET_ESP32S2
|
||||
#include "esp32s2/rom/ets_sys.h"
|
||||
#elif CONFIG_IDF_TARGET_ESP32
|
||||
#include "esp32/rom/ets_sys.h"
|
||||
#endif
|
||||
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
|
||||
|
||||
#if XCHAL_HAVE_EXCEPTIONS
|
||||
|
||||
/* Handler table is in xtensa_intr_asm.S */
|
||||
|
||||
extern xt_exc_handler _xt_exception_table[ XCHAL_EXCCAUSE_NUM * portNUM_PROCESSORS ];
|
||||
|
||||
|
||||
/*
|
||||
* Default handler for unhandled exceptions.
|
||||
* CHANGED: We do this in panic.c now
|
||||
*/
|
||||
|
||||
/*void xt_unhandled_exception(XtExcFrame *frame) */
|
||||
/*{ */
|
||||
/*exit(-1); */
|
||||
/*} */
|
||||
extern void xt_unhandled_exception( XtExcFrame * frame );
|
||||
|
||||
|
||||
/*
|
||||
* This function registers a handler for the specified exception.
|
||||
* The function returns the address of the previous handler.
|
||||
* On error, it returns 0.
|
||||
*/
|
||||
xt_exc_handler xt_set_exception_handler( int n,
|
||||
xt_exc_handler f )
|
||||
{
|
||||
xt_exc_handler old;
|
||||
|
||||
if( ( n < 0 ) || ( n >= XCHAL_EXCCAUSE_NUM ) )
|
||||
{
|
||||
return 0; /* invalid exception number */
|
||||
}
|
||||
|
||||
/* Convert exception number to _xt_exception_table name */
|
||||
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||
old = _xt_exception_table[ n ];
|
||||
|
||||
if( f )
|
||||
{
|
||||
_xt_exception_table[ n ] = f;
|
||||
}
|
||||
else
|
||||
{
|
||||
_xt_exception_table[ n ] = &xt_unhandled_exception;
|
||||
}
|
||||
|
||||
return( ( old == &xt_unhandled_exception ) ? 0 : old );
|
||||
}
|
||||
|
||||
#endif /* if XCHAL_HAVE_EXCEPTIONS */
|
||||
|
||||
#if XCHAL_HAVE_INTERRUPTS
|
||||
|
||||
/* Handler table is in xtensa_intr_asm.S */
|
||||
|
||||
typedef struct xt_handler_table_entry
|
||||
{
|
||||
void * handler;
|
||||
void * arg;
|
||||
} xt_handler_table_entry;
|
||||
|
||||
extern xt_handler_table_entry _xt_interrupt_table[ XCHAL_NUM_INTERRUPTS * portNUM_PROCESSORS ];
|
||||
|
||||
|
||||
/*
|
||||
* Default handler for unhandled interrupts.
|
||||
*/
|
||||
void xt_unhandled_interrupt( void * arg )
|
||||
{
|
||||
ets_printf( "Unhandled interrupt %d on cpu %d!\n", ( int ) arg, xPortGetCoreID() );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function registers a handler for the specified interrupt. The "arg"
|
||||
* parameter specifies the argument to be passed to the handler when it is
|
||||
* invoked. The function returns the address of the previous handler.
|
||||
* On error, it returns 0.
|
||||
*/
|
||||
xt_handler xt_set_interrupt_handler( int n,
|
||||
xt_handler f,
|
||||
void * arg )
|
||||
{
|
||||
xt_handler_table_entry * entry;
|
||||
xt_handler old;
|
||||
|
||||
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
|
||||
{
|
||||
return 0; /* invalid interrupt number */
|
||||
}
|
||||
|
||||
if( Xthal_intlevel[ n ] > XCHAL_EXCM_LEVEL )
|
||||
{
|
||||
return 0; /* priority level too high to safely handle in C */
|
||||
}
|
||||
|
||||
/* Convert exception number to _xt_exception_table name */
|
||||
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||
|
||||
entry = _xt_interrupt_table + n;
|
||||
old = entry->handler;
|
||||
|
||||
if( f )
|
||||
{
|
||||
entry->handler = f;
|
||||
entry->arg = arg;
|
||||
}
|
||||
else
|
||||
{
|
||||
entry->handler = &xt_unhandled_interrupt;
|
||||
entry->arg = ( void * ) n;
|
||||
}
|
||||
|
||||
return( ( old == &xt_unhandled_interrupt ) ? 0 : old );
|
||||
}
|
||||
|
||||
#if CONFIG_SYSVIEW_ENABLE
|
||||
void * xt_get_interrupt_handler_arg( int n )
|
||||
{
|
||||
xt_handler_table_entry * entry;
|
||||
|
||||
if( ( n < 0 ) || ( n >= XCHAL_NUM_INTERRUPTS ) )
|
||||
{
|
||||
return 0; /* invalid interrupt number */
|
||||
}
|
||||
|
||||
/* Convert exception number to _xt_exception_table name */
|
||||
n = n * portNUM_PROCESSORS + xPortGetCoreID();
|
||||
|
||||
entry = _xt_interrupt_table + n;
|
||||
return entry->arg;
|
||||
}
|
||||
#endif /* if CONFIG_SYSVIEW_ENABLE */
|
||||
|
||||
#endif /* XCHAL_HAVE_INTERRUPTS */
|
||||
|
|
|
@ -1,169 +1,169 @@
|
|||
// Copyright 2015-2017 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 "xtensa_rtos.h"
|
||||
#include "esp_idf_version.h"
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#include "esp_panic.h"
|
||||
#else
|
||||
#include "esp_private/panic_reason.h"
|
||||
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
/*
|
||||
This file contains the default handlers for the high interrupt levels as well as some specialized exceptions.
|
||||
The default behaviour is to just exit the interrupt or call the panic handler on the exceptions
|
||||
*/
|
||||
|
||||
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
.global xt_debugexception
|
||||
.weak xt_debugexception
|
||||
.set xt_debugexception, _xt_debugexception
|
||||
.section .iram1,"ax"
|
||||
.type _xt_debugexception,@function
|
||||
.align 4
|
||||
|
||||
_xt_debugexception:
|
||||
movi a0,PANIC_RSN_DEBUGEXCEPTION
|
||||
wsr a0,EXCCAUSE
|
||||
/* _xt_panic assumes a level 1 exception. As we're
|
||||
crashing anyhow, copy EPC & EXCSAVE from DEBUGLEVEL
|
||||
to level 1. */
|
||||
rsr a0,(EPC + XCHAL_DEBUGLEVEL)
|
||||
wsr a0,EPC_1
|
||||
rsr a0,(EXCSAVE + XCHAL_DEBUGLEVEL)
|
||||
wsr a0,EXCSAVE_1
|
||||
call0 _xt_panic /* does not return */
|
||||
rfi XCHAL_DEBUGLEVEL
|
||||
|
||||
#endif /* Debug exception */
|
||||
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
|
||||
.global xt_highint2
|
||||
.weak xt_highint2
|
||||
.set xt_highint2, _xt_highint2
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint2,@function
|
||||
.align 4
|
||||
_xt_highint2:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
.align 4
|
||||
.L_xt_highint2_exit:
|
||||
rsr a0, EXCSAVE_2 /* restore a0 */
|
||||
rfi 2
|
||||
|
||||
#endif /* Level 2 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
|
||||
|
||||
.global xt_highint3
|
||||
.weak xt_highint3
|
||||
.set xt_highint3, _xt_highint3
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint3,@function
|
||||
.align 4
|
||||
_xt_highint3:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint3_exit:
|
||||
rsr a0, EXCSAVE_3 /* restore a0 */
|
||||
rfi 3
|
||||
|
||||
#endif /* Level 3 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
|
||||
|
||||
.global xt_highint4
|
||||
.weak xt_highint4
|
||||
.set xt_highint4, _xt_highint4
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint4,@function
|
||||
.align 4
|
||||
_xt_highint4:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint4_exit:
|
||||
rsr a0, EXCSAVE_4 /* restore a0 */
|
||||
rfi 4
|
||||
|
||||
#endif /* Level 4 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
|
||||
|
||||
.global xt_highint5
|
||||
.weak xt_highint5
|
||||
.set xt_highint5, _xt_highint5
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint5,@function
|
||||
.align 4
|
||||
_xt_highint5:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint5_exit:
|
||||
rsr a0, EXCSAVE_5 /* restore a0 */
|
||||
rfi 5
|
||||
|
||||
|
||||
#endif /* Level 5 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
|
||||
|
||||
.global _xt_highint6
|
||||
.global xt_highint6
|
||||
.weak xt_highint6
|
||||
.set xt_highint6, _xt_highint6
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint6,@function
|
||||
.align 4
|
||||
_xt_highint6:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint6_exit:
|
||||
rsr a0, EXCSAVE_6 /* restore a0 */
|
||||
rfi 6
|
||||
|
||||
#endif /* Level 6 */
|
||||
|
||||
#if XCHAL_HAVE_NMI
|
||||
|
||||
.global _xt_nmi
|
||||
.global xt_nmi
|
||||
.weak xt_nmi
|
||||
.set xt_nmi, _xt_nmi
|
||||
.section .iram1,"ax"
|
||||
.type _xt_nmi,@function
|
||||
.align 4
|
||||
_xt_nmi:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_nmi_exit:
|
||||
rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
|
||||
rfi XCHAL_NMILEVEL
|
||||
|
||||
#endif /* NMI */
|
||||
|
||||
// Copyright 2015-2017 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 "xtensa_rtos.h"
|
||||
#include "esp_idf_version.h"
|
||||
#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
|
||||
#include "esp_panic.h"
|
||||
#else
|
||||
#include "esp_private/panic_reason.h"
|
||||
#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
|
||||
#include "sdkconfig.h"
|
||||
#include "soc/soc.h"
|
||||
|
||||
/*
|
||||
This file contains the default handlers for the high interrupt levels as well as some specialized exceptions.
|
||||
The default behaviour is to just exit the interrupt or call the panic handler on the exceptions
|
||||
*/
|
||||
|
||||
|
||||
#if XCHAL_HAVE_DEBUG
|
||||
.global xt_debugexception
|
||||
.weak xt_debugexception
|
||||
.set xt_debugexception, _xt_debugexception
|
||||
.section .iram1,"ax"
|
||||
.type _xt_debugexception,@function
|
||||
.align 4
|
||||
|
||||
_xt_debugexception:
|
||||
movi a0,PANIC_RSN_DEBUGEXCEPTION
|
||||
wsr a0,EXCCAUSE
|
||||
/* _xt_panic assumes a level 1 exception. As we're
|
||||
crashing anyhow, copy EPC & EXCSAVE from DEBUGLEVEL
|
||||
to level 1. */
|
||||
rsr a0,(EPC + XCHAL_DEBUGLEVEL)
|
||||
wsr a0,EPC_1
|
||||
rsr a0,(EXCSAVE + XCHAL_DEBUGLEVEL)
|
||||
wsr a0,EXCSAVE_1
|
||||
call0 _xt_panic /* does not return */
|
||||
rfi XCHAL_DEBUGLEVEL
|
||||
|
||||
#endif /* Debug exception */
|
||||
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
|
||||
.global xt_highint2
|
||||
.weak xt_highint2
|
||||
.set xt_highint2, _xt_highint2
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint2,@function
|
||||
.align 4
|
||||
_xt_highint2:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
.align 4
|
||||
.L_xt_highint2_exit:
|
||||
rsr a0, EXCSAVE_2 /* restore a0 */
|
||||
rfi 2
|
||||
|
||||
#endif /* Level 2 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
|
||||
|
||||
.global xt_highint3
|
||||
.weak xt_highint3
|
||||
.set xt_highint3, _xt_highint3
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint3,@function
|
||||
.align 4
|
||||
_xt_highint3:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint3_exit:
|
||||
rsr a0, EXCSAVE_3 /* restore a0 */
|
||||
rfi 3
|
||||
|
||||
#endif /* Level 3 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
|
||||
|
||||
.global xt_highint4
|
||||
.weak xt_highint4
|
||||
.set xt_highint4, _xt_highint4
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint4,@function
|
||||
.align 4
|
||||
_xt_highint4:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint4_exit:
|
||||
rsr a0, EXCSAVE_4 /* restore a0 */
|
||||
rfi 4
|
||||
|
||||
#endif /* Level 4 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
|
||||
|
||||
.global xt_highint5
|
||||
.weak xt_highint5
|
||||
.set xt_highint5, _xt_highint5
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint5,@function
|
||||
.align 4
|
||||
_xt_highint5:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint5_exit:
|
||||
rsr a0, EXCSAVE_5 /* restore a0 */
|
||||
rfi 5
|
||||
|
||||
|
||||
#endif /* Level 5 */
|
||||
|
||||
#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
|
||||
|
||||
.global _xt_highint6
|
||||
.global xt_highint6
|
||||
.weak xt_highint6
|
||||
.set xt_highint6, _xt_highint6
|
||||
.section .iram1,"ax"
|
||||
.type _xt_highint6,@function
|
||||
.align 4
|
||||
_xt_highint6:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_highint6_exit:
|
||||
rsr a0, EXCSAVE_6 /* restore a0 */
|
||||
rfi 6
|
||||
|
||||
#endif /* Level 6 */
|
||||
|
||||
#if XCHAL_HAVE_NMI
|
||||
|
||||
.global _xt_nmi
|
||||
.global xt_nmi
|
||||
.weak xt_nmi
|
||||
.set xt_nmi, _xt_nmi
|
||||
.section .iram1,"ax"
|
||||
.type _xt_nmi,@function
|
||||
.align 4
|
||||
_xt_nmi:
|
||||
|
||||
/* Default handler does nothing; just returns */
|
||||
|
||||
.align 4
|
||||
.L_xt_nmi_exit:
|
||||
rsr a0, EXCSAVE + XCHAL_NMILEVEL /* restore a0 */
|
||||
rfi XCHAL_NMILEVEL
|
||||
|
||||
#endif /* NMI */
|
||||
|
||||
|
|
4114
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S
vendored
4114
portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S
vendored
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue