Add git attributes (#245)

* Add .gitattributes configured to normailze line endings to LF

* replace crlf with lf, per .gitattributes
diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 0000000..81170d5
--- /dev/null
+++ b/.gitattributes
@@ -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
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/include/portmacro.h b/portable/ThirdParty/GCC/Xtensa_ESP32/include/portmacro.h
index eba402d..10a00c6 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/include/portmacro.h
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/include/portmacro.h
@@ -1,560 +1,560 @@
-/*

- *  FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.

- *  All rights reserved

- *

- *  VISIT https://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

- *

- ***************************************************************************

- *                                                                       *

- *    FreeRTOS provides completely free yet professionally developed,    *

- *    robust, strictly quality controlled, supported, and cross          *

- *    platform software that has become a de facto standard.             *

- *                                                                       *

- *    Help yourself get started quickly and support the FreeRTOS         *

- *    project by purchasing a FreeRTOS tutorial book, reference          *

- *    manual, or both from: https://www.FreeRTOS.org/Documentation       *

- *                                                                       *

- *    Thank you!                                                         *

- *                                                                       *

- ***************************************************************************

- *

- *  This file is part of the FreeRTOS distribution.

- *

- *  FreeRTOS is free software; you can redistribute it and/or modify it under

- *  the terms of the GNU General Public License (version 2) as published by the

- *  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.

- *

- *  >>!   NOTE: The modification to the GPL is included to allow you to     !<<

- *  >>!   distribute a combined work that includes FreeRTOS without being   !<<

- *  >>!   obliged to provide the source code for proprietary components     !<<

- *  >>!   outside of the FreeRTOS kernel.                                   !<<

- *

- *  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY

- *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

- *  FOR A PARTICULAR PURPOSE.  Full license text is available from the following

- *  link: https://www.FreeRTOS.org/a00114.html

- *

- *

- ***************************************************************************

- *                                                                       *

- *    Having a problem?  Start by reading the FAQ "My application does   *

- *    not run, what could be wrong?"                                     *

- *                                                                       *

- *    https://www.FreeRTOS.org/FAQHelp.html                              *

- *                                                                       *

- ***************************************************************************

- *

- *  https://www.FreeRTOS.org - Documentation, books, training, latest versions,

- *  license and Real Time Engineers Ltd. contact details.

- *

- *  https://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,

- *  including FreeRTOS+Trace - an indispensable productivity tool, a DOS

- *  compatible FAT file system, and our tiny thread aware UDP/IP stack.

- *

- *  https://www.highintegritysystems.com/openrtos/ - Real Time Engineers ltd

- *  license FreeRTOS to High Integrity Systems to sell under the OpenRTOS brand.

- *  Low cost OpenRTOS licenses offer ticketed support, indemnification

- *  and middleware.

- *

- *  https://www.highintegritysystems.com/safertos/ - High Integrity Systems

- *  also provide a safety engineered and independently SIL3 certified version

- *  for use in safety and mission critical applications that require

- *  provable dependability.

- *

- */

-

-#ifndef PORTMACRO_H

-#define PORTMACRO_H

-

-/* *INDENT-OFF* */

-#ifdef __cplusplus

-    extern "C" {

-#endif

-/* *INDENT-ON* */

-

-#ifndef __ASSEMBLER__

-

-    #include <stdint.h>

-

-    #include <xtensa/hal.h>

-    #include <xtensa/config/core.h>

-    #include <xtensa/config/system.h> /* required for XSHAL_CLIB */

-    #include <xtensa/xtruntime.h>

-    #include "esp_timer.h"            /* required for FreeRTOS run time stats */

-    #include "esp_system.h"

-    #include "esp_idf_version.h"

-

-

-    #include <esp_heap_caps.h>

-    #include "soc/soc_memory_layout.h"

-

-/*#include "xtensa_context.h" */

-

-/*-----------------------------------------------------------

- * Port specific definitions.

- *

- * The settings in this file configure FreeRTOS correctly for the

- * given hardware and compiler.

- *

- * These settings should not be altered.

- *-----------------------------------------------------------

- */

-

-/* Type definitions. */

-

-    #define portCHAR          int8_t

-    #define portFLOAT         float

-    #define portDOUBLE        double

-    #define portLONG          int32_t

-    #define portSHORT         int16_t

-    #define portSTACK_TYPE    uint8_t

-    #define portBASE_TYPE     int

-

-    typedef portSTACK_TYPE           StackType_t;

-    typedef portBASE_TYPE            BaseType_t;

-    typedef unsigned portBASE_TYPE   UBaseType_t;

-

-    #if ( configUSE_16_BIT_TICKS == 1 )

-        typedef uint16_t             TickType_t;

-        #define portMAX_DELAY    ( TickType_t ) 0xffff

-    #else

-        typedef uint32_t             TickType_t;

-        #define portMAX_DELAY    ( TickType_t ) 0xffffffffUL

-    #endif

-/*-----------------------------------------------------------*/

-

-/* portbenchmark */

-    #include "portbenchmark.h"

-

-    #include "sdkconfig.h"

-    #include "esp_attr.h"

-

-/* "mux" data structure (spinlock) */

-    typedef struct

-    {

-        /* owner field values:

-         * 0                - Uninitialized (invalid)

-         * portMUX_FREE_VAL - Mux is free, can be locked by either CPU

-         * CORE_ID_REGVAL_PRO / CORE_ID_REGVAL_APP - Mux is locked to the particular core

-         *

-         * Any value other than portMUX_FREE_VAL, CORE_ID_REGVAL_PRO, CORE_ID_REGVAL_APP indicates corruption

-         */

-        uint32_t owner;

-

-        /* count field:

-         * If mux is unlocked, count should be zero.

-         * If mux is locked, count is non-zero & represents the number of recursive locks on the mux.

-         */

-        uint32_t count;

-        #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-            const char * lastLockedFn;

-            int lastLockedLine;

-        #endif

-    } portMUX_TYPE;

-

-    #define portMUX_FREE_VAL      0xB33FFFFF

-

-/* Special constants for vPortCPUAcquireMutexTimeout() */

-    #define portMUX_NO_TIMEOUT    ( -1 ) /* When passed for 'timeout_cycles', spin forever if necessary */

-    #define portMUX_TRY_LOCK      0      /* Try to acquire the spinlock a single time only */

-

-/* Keep this in sync with the portMUX_TYPE struct definition please. */

-    #ifndef CONFIG_FREERTOS_PORTMUX_DEBUG

-        #define portMUX_INITIALIZER_UNLOCKED \

-    {                                        \

-        .owner = portMUX_FREE_VAL,           \

-        .count = 0,                          \

-    }

-    #else

-        #define portMUX_INITIALIZER_UNLOCKED \

-    {                                        \

-        .owner = portMUX_FREE_VAL,           \

-        .count = 0,                          \

-        .lastLockedFn = "(never locked)",    \

-        .lastLockedLine = -1                 \

-    }

-    #endif /* ifndef CONFIG_FREERTOS_PORTMUX_DEBUG */

-

-

-    #define portASSERT_IF_IN_ISR()    vPortAssertIfInISR()

-    void vPortAssertIfInISR();

-

-    #define portCRITICAL_NESTING_IN_TCB    1

-

-/*

- * Modifications to portENTER_CRITICAL.

- *

- * For an introduction, see "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst

- *

- * The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by

- * disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because

- * interrupts are disabled, ISRs can't corrupt data structures either.

- *

- * For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop

- * the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding

- * a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will

- * spinlock in the portENTER_CRITICAL code until the first CPU is done.

- *

- * For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same

- * CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the

- * data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks

- * do not disable the interrupts (because they already are).

- *

- * This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels

- * will break this scheme.

- *

- * Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning

- * that either function can be called both from ISR as well as task context. This is not standard FreeRTOS

- * behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.

- */

-    void vPortCPUInitializeMutex( portMUX_TYPE * mux );

-    #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-        #error CONFIG_FREERTOS_PORTMUX_DEBUG not supported in Amazon FreeRTOS

-    #endif

-

-    void vTaskExitCritical();

-    void vTaskEnterCritical();

-    static inline void vPortConsumeSpinlockArg( int unused,

-                                                ... )

-    {

-    }

-

-/** @brief Acquire a portmux spinlock with a timeout

- *

- * @param mux Pointer to portmux to acquire.

- * @param timeout_cycles Timeout to spin, in CPU cycles. Pass portMUX_NO_TIMEOUT to wait forever,

- * portMUX_TRY_LOCK to try a single time to acquire the lock.

- *

- * @return true if mutex is successfully acquired, false on timeout.

- */

-    bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,

-                                      int timeout_cycles );

-    void vPortCPUReleaseMutex( portMUX_TYPE * mux );

-

-    #define portENTER_CRITICAL( ... )        do { vTaskEnterCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 )

-    #define portEXIT_CRITICAL( ... )         do { vTaskExitCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 )

-

-

-    #define portENTER_CRITICAL_ISR( mux )    vPortCPUAcquireMutexTimeout( mux, portMUX_NO_TIMEOUT )

-    #define portEXIT_CRITICAL_ISR( mux )     vPortCPUReleaseMutex( mux )

-

-    #define portENTER_CRITICAL_SAFE( mux ) \

-    do {                                   \

-        if( xPortInIsrContext() ) {        \

-            portENTER_CRITICAL_ISR( mux ); \

-        }                                  \

-        else {                             \

-            portENTER_CRITICAL( mux );     \

-        }                                  \

-    } while( 0 )

-

-    #define portEXIT_CRITICAL_SAFE( mux ) \

-    do {                                  \

-        if( xPortInIsrContext() ) {       \

-            portEXIT_CRITICAL_ISR( mux ); \

-        }                                 \

-        else {                            \

-            portEXIT_CRITICAL( mux );     \

-        }                                 \

-    } while( 0 )

-

-

-/* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */

-/* These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. */

-/* */

-/* Only applies to one CPU. See notes above & below for reasons not to use these. */

-    #define portDISABLE_INTERRUPTS()    do { XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL ); portbenchmarkINTERRUPT_DISABLE(); } while( 0 )

-    #define portENABLE_INTERRUPTS()     do { portbenchmarkINTERRUPT_RESTORE( 0 ); XTOS_SET_INTLEVEL( 0 ); } while( 0 )

-

-/* Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. */

-/* They can be called from interrupts too. */

-/* WARNING: Only applies to current CPU. See notes above. */

-    static inline unsigned portENTER_CRITICAL_NESTED()

-    {

-        unsigned state = XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL );

-

-        portbenchmarkINTERRUPT_DISABLE();

-        return state;

-    }

-    #define portEXIT_CRITICAL_NESTED( state )             do { portbenchmarkINTERRUPT_RESTORE( state ); XTOS_RESTORE_JUST_INTLEVEL( state ); } while( 0 )

-

-/* These FreeRTOS versions are similar to the nested versions above */

-    #define portSET_INTERRUPT_MASK_FROM_ISR()             portENTER_CRITICAL_NESTED()

-    #define portCLEAR_INTERRUPT_MASK_FROM_ISR( state )    portEXIT_CRITICAL_NESTED( state )

-

-/*Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force */

-/*the stack memory to always be internal. */

-    #define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)

-    #define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)

-

-    #define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps)

-    #define pvPortMallocStackMem(size)  heap_caps_malloc(size, portStackMemoryCaps)

-

-/*xTaskCreateStatic uses these functions to check incoming memory. */

-    #define portVALID_TCB_MEM( ptr )          ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) )

-    #ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY

-        #define portVALID_STACK_MEM( ptr )    esp_ptr_byte_accessible( ptr )

-    #else

-        #define portVALID_STACK_MEM( ptr )    ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) )

-    #endif

-

-/*

- * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare

- * *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is updated with the previous

- * value of *addr (either 'compare' or some other value.)

- *

- * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the

- * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the

- * ESP32 (portMUX assertions would fail).

- */

-        static inline void uxPortCompareSet( volatile uint32_t * addr,

-                                             uint32_t compare,

-                                             uint32_t * set )

-        {

-            #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))

-            __asm__ __volatile__ (

-                "WSR       %2,SCOMPARE1 \n"

-                "S32C1I     %0, %1, 0   \n"

-                : "=r" ( *set )

-                : "r" ( addr ), "r" ( compare ), "0" ( *set )

-                );

-            #else

-            #if ( XCHAL_HAVE_S32C1I > 0 )

-                __asm__ __volatile__ (

-                    "WSR 	    %2,SCOMPARE1 \n"

-                    "S32C1I     %0, %1, 0	 \n"

-                    : "=r" ( *set )

-                    : "r" ( addr ), "r" ( compare ), "0" ( *set )

-                    );

-            #else

-                /* No S32C1I, so do this by disabling and re-enabling interrupts (slower) */

-                uint32_t intlevel, old_value;

-                __asm__ __volatile__ ( "rsil %0, " XTSTR( XCHAL_EXCM_LEVEL ) "\n"

-                                       : "=r" ( intlevel ) );

-

-                old_value = *addr;

-

-                if( old_value == compare )

-                {

-                    *addr = *set;

-                }

-

-                __asm__ __volatile__ ( "memw \n"

-                                       "wsr %0, ps\n"

-                                       : : "r" ( intlevel ) );

-

-                *set = old_value;

-            #endif /* if ( XCHAL_HAVE_S32C1I > 0 ) */

-            #endif /* #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)) */

-        }

-

-        #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))

-        void uxPortCompareSetExtram( volatile uint32_t * addr,

-                                     uint32_t compare,

-                                     uint32_t * set );

-        #else

-        static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) 

-        {

-        #if defined(CONFIG_ESP32_SPIRAM_SUPPORT)    

-            compare_and_set_extram(addr, compare, set);

-        #endif    

-        }

-        #endif

-

-/*-----------------------------------------------------------*/

-

-/* Architecture specifics. */

-    #define portSTACK_GROWTH      ( -1 )

-    #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )

-    #define portBYTE_ALIGNMENT    4

-    #define portNOP()    XT_NOP()

-/*-----------------------------------------------------------*/

-

-/* Fine resolution time */

-    #define portGET_RUN_TIME_COUNTER_VALUE()    xthal_get_ccount()

-/*ccount or esp_timer are initialized elsewhere */

-    #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()

-

-    #ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER

-/* Coarse resolution time (us) */

-        #define portALT_GET_RUN_TIME_COUNTER_VALUE( x )    x = ( uint32_t ) esp_timer_get_time()

-    #endif

-

-

-

-/* Kernel utilities. */

-    void vPortYield( void );

-    void _frxt_setup_switch( void );

-    #define portYIELD()             vPortYield()

-    #define portYIELD_FROM_ISR()    { traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch(); }

-

-    static inline uint32_t xPortGetCoreID();

-

-/*-----------------------------------------------------------*/

-

-/* Task function macros as described on the FreeRTOS.org WEB site. */

-    #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )

-    #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )

-

-/* When coprocessors are defined, we to maintain a pointer to coprocessors area. */

-/* We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: */

-/* MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. */

-/* The field is normally used for memory protection. FreeRTOS should create another general purpose field. */

-    typedef struct

-    {

-        #if XCHAL_CP_NUM > 0

-            volatile StackType_t * coproc_area; /* Pointer to coprocessor save area; MUST BE FIRST */

-        #endif

-

-        #if portUSING_MPU_WRAPPERS

-            /* Define here mpu_settings, which is port dependent */

-            int mpu_setting; /* Just a dummy example here; MPU not ported to Xtensa yet */

-        #endif

-

-        #if configUSE_TRACE_FACILITY_2

-            struct

-            {

-                /* Cf. porttraceStamp() */

-                int taskstamp;      /* Stamp from inside task to see where we are */

-                int taskstampcount; /* A counter usually incremented when we restart the task's loop */

-            } porttrace;

-        #endif

-    } xMPU_SETTINGS;

-

-/* Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) */

-    #if ( XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2 ) && !portUSING_MPU_WRAPPERS /* If MPU wrappers not used, we still need to allocate coproc area */

-        #undef portUSING_MPU_WRAPPERS

-        #define portUSING_MPU_WRAPPERS    1                                           /* Enable it to allocate coproc area */

-        #define MPU_WRAPPERS_H                                                        /* Override mpu_wrapper.h to disable unwanted code */

-        #define PRIVILEGED_FUNCTION

-        #define PRIVILEGED_DATA

-    #endif

-

-    void vApplicationSleep( TickType_t xExpectedIdleTime );

-    void vPortSetStackWatchpoint( void* pxStackStart );

-

-    #define portSUPPRESS_TICKS_AND_SLEEP( idleTime )    vApplicationSleep( idleTime )

-

-    /*-----------------------------------------------------------*/

-

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))    

-    /* Architecture specific optimisations. */

-    

-    #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1

-    

-    /* Check the configuration. */

-    #if( configMAX_PRIORITIES > 32 )

-        #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice.

-    #endif

-    

-    /* Store/clear the ready priorities in a bit map. */

-    #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )

-    #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )

-    

-    /*-----------------------------------------------------------*/

-    

-    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) )

-    

-    #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */

-

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-    

-    /*-----------------------------------------------------------*/

-    

-

-    void _xt_coproc_release( volatile void * coproc_sa_base );

-

-

-/*

- * Map to the memory management routines required for the port.

- *

- * Note that libc standard malloc/free are also available for

- * non-FreeRTOS-specific code, and behave the same as

- * pvPortMalloc()/vPortFree().

- */

-    #define pvPortMalloc                       heap_caps_malloc_default

-    #define vPortFree                          heap_caps_free

-    #define xPortGetFreeHeapSize               esp_get_free_heap_size

-    #define xPortGetMinimumEverFreeHeapSize    esp_get_minimum_free_heap_size

-

-#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))

-/*

- * Send an interrupt to another core in order to make the task running

- * on it yield for a higher-priority task.

- */

-

-        void vPortYieldOtherCore( BaseType_t coreid ) PRIVILEGED_FUNCTION;

-

-#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-/*

- * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack

- * watchpoint around.

- */

-    void vPortSetStackWatchpoint( void * pxStackStart );

-

-/*

- * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs

- * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.

- */

-    BaseType_t xPortInIsrContext();

-

-

-/*

- * This function will be called in High prio ISRs. Returns true if the current core was in ISR context

- * before calling into high prio ISR context.

- */

-    BaseType_t xPortInterruptedFromISRContext();

-

-/*

- * The structures and methods of manipulating the MPU are contained within the

- * port layer.

- *

- * Fills the xMPUSettings structure with the memory region information

- * contained in xRegions.

- */

-    #if ( portUSING_MPU_WRAPPERS == 1 )

-        struct xMEMORY_REGION;

-        void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,

-                                        const struct xMEMORY_REGION * const xRegions,

-                                        StackType_t * pxBottomOfStack,

-                                        uint32_t usStackDepth ) PRIVILEGED_FUNCTION;

-        void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings );

-    #endif

-

-/* Multi-core: get current core ID */

-    static inline uint32_t IRAM_ATTR xPortGetCoreID()

-    {

-        int id;

-

-        asm (

-            "rsr.prid %0\n"

-            " extui %0,%0,13,1"

-            : "=r" ( id ) );

-        return id;

-    }

-

-/* Get tick rate per second */

-    uint32_t xPortGetTickRateHz( void );

-

-/* porttrace */

-    #if configUSE_TRACE_FACILITY_2

-        #include "porttrace.h"

-    #endif

-

-/* configASSERT_2 if requested */

-    #if configASSERT_2

-        #include <stdio.h>

-        void exit( int );

-        #define configASSERT( x )    if( !( x ) ) { porttracePrint( -1 ); printf( "\nAssertion failed in %s:%d\n", __FILE__, __LINE__ ); exit( -1 ); }

-    #endif

-

-#endif // __ASSEMBLER__

-

-/* *INDENT-OFF* */

-#ifdef __cplusplus

-    }

-#endif

-/* *INDENT-ON* */

-

-#endif /* PORTMACRO_H */

+/*
+ *  FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
+ *  All rights reserved
+ *
+ *  VISIT https://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+ *
+ ***************************************************************************
+ *                                                                       *
+ *    FreeRTOS provides completely free yet professionally developed,    *
+ *    robust, strictly quality controlled, supported, and cross          *
+ *    platform software that has become a de facto standard.             *
+ *                                                                       *
+ *    Help yourself get started quickly and support the FreeRTOS         *
+ *    project by purchasing a FreeRTOS tutorial book, reference          *
+ *    manual, or both from: https://www.FreeRTOS.org/Documentation       *
+ *                                                                       *
+ *    Thank you!                                                         *
+ *                                                                       *
+ ***************************************************************************
+ *
+ *  This file is part of the FreeRTOS distribution.
+ *
+ *  FreeRTOS is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License (version 2) as published by the
+ *  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+ *
+ *  >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+ *  >>!   distribute a combined work that includes FreeRTOS without being   !<<
+ *  >>!   obliged to provide the source code for proprietary components     !<<
+ *  >>!   outside of the FreeRTOS kernel.                                   !<<
+ *
+ *  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  Full license text is available from the following
+ *  link: https://www.FreeRTOS.org/a00114.html
+ *
+ *
+ ***************************************************************************
+ *                                                                       *
+ *    Having a problem?  Start by reading the FAQ "My application does   *
+ *    not run, what could be wrong?"                                     *
+ *                                                                       *
+ *    https://www.FreeRTOS.org/FAQHelp.html                              *
+ *                                                                       *
+ ***************************************************************************
+ *
+ *  https://www.FreeRTOS.org - Documentation, books, training, latest versions,
+ *  license and Real Time Engineers Ltd. contact details.
+ *
+ *  https://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ *  including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ *  compatible FAT file system, and our tiny thread aware UDP/IP stack.
+ *
+ *  https://www.highintegritysystems.com/openrtos/ - Real Time Engineers ltd
+ *  license FreeRTOS to High Integrity Systems to sell under the OpenRTOS brand.
+ *  Low cost OpenRTOS licenses offer ticketed support, indemnification
+ *  and middleware.
+ *
+ *  https://www.highintegritysystems.com/safertos/ - High Integrity Systems
+ *  also provide a safety engineered and independently SIL3 certified version
+ *  for use in safety and mission critical applications that require
+ *  provable dependability.
+ *
+ */
+
+#ifndef PORTMACRO_H
+#define PORTMACRO_H
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+    extern "C" {
+#endif
+/* *INDENT-ON* */
+
+#ifndef __ASSEMBLER__
+
+    #include <stdint.h>
+
+    #include <xtensa/hal.h>
+    #include <xtensa/config/core.h>
+    #include <xtensa/config/system.h> /* required for XSHAL_CLIB */
+    #include <xtensa/xtruntime.h>
+    #include "esp_timer.h"            /* required for FreeRTOS run time stats */
+    #include "esp_system.h"
+    #include "esp_idf_version.h"
+
+
+    #include <esp_heap_caps.h>
+    #include "soc/soc_memory_layout.h"
+
+/*#include "xtensa_context.h" */
+
+/*-----------------------------------------------------------
+ * Port specific definitions.
+ *
+ * The settings in this file configure FreeRTOS correctly for the
+ * given hardware and compiler.
+ *
+ * These settings should not be altered.
+ *-----------------------------------------------------------
+ */
+
+/* Type definitions. */
+
+    #define portCHAR          int8_t
+    #define portFLOAT         float
+    #define portDOUBLE        double
+    #define portLONG          int32_t
+    #define portSHORT         int16_t
+    #define portSTACK_TYPE    uint8_t
+    #define portBASE_TYPE     int
+
+    typedef portSTACK_TYPE           StackType_t;
+    typedef portBASE_TYPE            BaseType_t;
+    typedef unsigned portBASE_TYPE   UBaseType_t;
+
+    #if ( configUSE_16_BIT_TICKS == 1 )
+        typedef uint16_t             TickType_t;
+        #define portMAX_DELAY    ( TickType_t ) 0xffff
+    #else
+        typedef uint32_t             TickType_t;
+        #define portMAX_DELAY    ( TickType_t ) 0xffffffffUL
+    #endif
+/*-----------------------------------------------------------*/
+
+/* portbenchmark */
+    #include "portbenchmark.h"
+
+    #include "sdkconfig.h"
+    #include "esp_attr.h"
+
+/* "mux" data structure (spinlock) */
+    typedef struct
+    {
+        /* owner field values:
+         * 0                - Uninitialized (invalid)
+         * portMUX_FREE_VAL - Mux is free, can be locked by either CPU
+         * CORE_ID_REGVAL_PRO / CORE_ID_REGVAL_APP - Mux is locked to the particular core
+         *
+         * Any value other than portMUX_FREE_VAL, CORE_ID_REGVAL_PRO, CORE_ID_REGVAL_APP indicates corruption
+         */
+        uint32_t owner;
+
+        /* count field:
+         * If mux is unlocked, count should be zero.
+         * If mux is locked, count is non-zero & represents the number of recursive locks on the mux.
+         */
+        uint32_t count;
+        #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+            const char * lastLockedFn;
+            int lastLockedLine;
+        #endif
+    } portMUX_TYPE;
+
+    #define portMUX_FREE_VAL      0xB33FFFFF
+
+/* Special constants for vPortCPUAcquireMutexTimeout() */
+    #define portMUX_NO_TIMEOUT    ( -1 ) /* When passed for 'timeout_cycles', spin forever if necessary */
+    #define portMUX_TRY_LOCK      0      /* Try to acquire the spinlock a single time only */
+
+/* Keep this in sync with the portMUX_TYPE struct definition please. */
+    #ifndef CONFIG_FREERTOS_PORTMUX_DEBUG
+        #define portMUX_INITIALIZER_UNLOCKED \
+    {                                        \
+        .owner = portMUX_FREE_VAL,           \
+        .count = 0,                          \
+    }
+    #else
+        #define portMUX_INITIALIZER_UNLOCKED \
+    {                                        \
+        .owner = portMUX_FREE_VAL,           \
+        .count = 0,                          \
+        .lastLockedFn = "(never locked)",    \
+        .lastLockedLine = -1                 \
+    }
+    #endif /* ifndef CONFIG_FREERTOS_PORTMUX_DEBUG */
+
+
+    #define portASSERT_IF_IN_ISR()    vPortAssertIfInISR()
+    void vPortAssertIfInISR();
+
+    #define portCRITICAL_NESTING_IN_TCB    1
+
+/*
+ * Modifications to portENTER_CRITICAL.
+ *
+ * For an introduction, see "Critical Sections & Disabling Interrupts" in docs/api-guides/freertos-smp.rst
+ *
+ * The original portENTER_CRITICAL only disabled the ISRs. This is enough for single-CPU operation: by
+ * disabling the interrupts, there is no task switch so no other tasks can meddle in the data, and because
+ * interrupts are disabled, ISRs can't corrupt data structures either.
+ *
+ * For multiprocessing, things get a bit more hairy. First of all, disabling the interrupts doesn't stop
+ * the tasks or ISRs on the other processors meddling with our CPU. For tasks, this is solved by adding
+ * a spinlock to the portENTER_CRITICAL macro. A task running on the other CPU accessing the same data will
+ * spinlock in the portENTER_CRITICAL code until the first CPU is done.
+ *
+ * For ISRs, we now also need muxes: while portENTER_CRITICAL disabling interrupts will stop ISRs on the same
+ * CPU from meddling with the data, it does not stop interrupts on the other cores from interfering with the
+ * data. For this, we also use a spinlock in the routines called by the ISR, but these spinlocks
+ * do not disable the interrupts (because they already are).
+ *
+ * This all assumes that interrupts are either entirely disabled or enabled. Interrupt priority levels
+ * will break this scheme.
+ *
+ * Remark: For the ESP32, portENTER_CRITICAL and portENTER_CRITICAL_ISR both alias vTaskEnterCritical, meaning
+ * that either function can be called both from ISR as well as task context. This is not standard FreeRTOS
+ * behaviour; please keep this in mind if you need any compatibility with other FreeRTOS implementations.
+ */
+    void vPortCPUInitializeMutex( portMUX_TYPE * mux );
+    #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+        #error CONFIG_FREERTOS_PORTMUX_DEBUG not supported in Amazon FreeRTOS
+    #endif
+
+    void vTaskExitCritical();
+    void vTaskEnterCritical();
+    static inline void vPortConsumeSpinlockArg( int unused,
+                                                ... )
+    {
+    }
+
+/** @brief Acquire a portmux spinlock with a timeout
+ *
+ * @param mux Pointer to portmux to acquire.
+ * @param timeout_cycles Timeout to spin, in CPU cycles. Pass portMUX_NO_TIMEOUT to wait forever,
+ * portMUX_TRY_LOCK to try a single time to acquire the lock.
+ *
+ * @return true if mutex is successfully acquired, false on timeout.
+ */
+    bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,
+                                      int timeout_cycles );
+    void vPortCPUReleaseMutex( portMUX_TYPE * mux );
+
+    #define portENTER_CRITICAL( ... )        do { vTaskEnterCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 )
+    #define portEXIT_CRITICAL( ... )         do { vTaskExitCritical(); vPortConsumeSpinlockArg( 0, ## __VA_ARGS__ ); } while( 0 )
+
+
+    #define portENTER_CRITICAL_ISR( mux )    vPortCPUAcquireMutexTimeout( mux, portMUX_NO_TIMEOUT )
+    #define portEXIT_CRITICAL_ISR( mux )     vPortCPUReleaseMutex( mux )
+
+    #define portENTER_CRITICAL_SAFE( mux ) \
+    do {                                   \
+        if( xPortInIsrContext() ) {        \
+            portENTER_CRITICAL_ISR( mux ); \
+        }                                  \
+        else {                             \
+            portENTER_CRITICAL( mux );     \
+        }                                  \
+    } while( 0 )
+
+    #define portEXIT_CRITICAL_SAFE( mux ) \
+    do {                                  \
+        if( xPortInIsrContext() ) {       \
+            portEXIT_CRITICAL_ISR( mux ); \
+        }                                 \
+        else {                            \
+            portEXIT_CRITICAL( mux );     \
+        }                                 \
+    } while( 0 )
+
+
+/* Critical section management. NW-TODO: replace XTOS_SET_INTLEVEL with more efficient version, if any? */
+/* These cannot be nested. They should be used with a lot of care and cannot be called from interrupt level. */
+/* */
+/* Only applies to one CPU. See notes above & below for reasons not to use these. */
+    #define portDISABLE_INTERRUPTS()    do { XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL ); portbenchmarkINTERRUPT_DISABLE(); } while( 0 )
+    #define portENABLE_INTERRUPTS()     do { portbenchmarkINTERRUPT_RESTORE( 0 ); XTOS_SET_INTLEVEL( 0 ); } while( 0 )
+
+/* Cleaner solution allows nested interrupts disabling and restoring via local registers or stack. */
+/* They can be called from interrupts too. */
+/* WARNING: Only applies to current CPU. See notes above. */
+    static inline unsigned portENTER_CRITICAL_NESTED()
+    {
+        unsigned state = XTOS_SET_INTLEVEL( XCHAL_EXCM_LEVEL );
+
+        portbenchmarkINTERRUPT_DISABLE();
+        return state;
+    }
+    #define portEXIT_CRITICAL_NESTED( state )             do { portbenchmarkINTERRUPT_RESTORE( state ); XTOS_RESTORE_JUST_INTLEVEL( state ); } while( 0 )
+
+/* These FreeRTOS versions are similar to the nested versions above */
+    #define portSET_INTERRUPT_MASK_FROM_ISR()             portENTER_CRITICAL_NESTED()
+    #define portCLEAR_INTERRUPT_MASK_FROM_ISR( state )    portEXIT_CRITICAL_NESTED( state )
+
+/*Because the ROM routines don't necessarily handle a stack in external RAM correctly, we force */
+/*the stack memory to always be internal. */
+    #define portTcbMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
+    #define portStackMemoryCaps (MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT)
+
+    #define pvPortMallocTcbMem(size) heap_caps_malloc(size, portTcbMemoryCaps)
+    #define pvPortMallocStackMem(size)  heap_caps_malloc(size, portStackMemoryCaps)
+
+/*xTaskCreateStatic uses these functions to check incoming memory. */
+    #define portVALID_TCB_MEM( ptr )          ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) )
+    #ifdef CONFIG_SPIRAM_ALLOW_STACK_EXTERNAL_MEMORY
+        #define portVALID_STACK_MEM( ptr )    esp_ptr_byte_accessible( ptr )
+    #else
+        #define portVALID_STACK_MEM( ptr )    ( esp_ptr_internal( ptr ) && esp_ptr_byte_accessible( ptr ) )
+    #endif
+
+/*
+ * Wrapper for the Xtensa compare-and-set instruction. This subroutine will atomically compare
+ * *addr to 'compare'. If *addr == compare, *addr is set to *set. *set is updated with the previous
+ * value of *addr (either 'compare' or some other value.)
+ *
+ * Warning: From the ISA docs: in some (unspecified) cases, the s32c1i instruction may return the
+ * *bitwise inverse* of the old mem if the mem wasn't written. This doesn't seem to happen on the
+ * ESP32 (portMUX assertions would fail).
+ */
+        static inline void uxPortCompareSet( volatile uint32_t * addr,
+                                             uint32_t compare,
+                                             uint32_t * set )
+        {
+            #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
+            __asm__ __volatile__ (
+                "WSR       %2,SCOMPARE1 \n"
+                "S32C1I     %0, %1, 0   \n"
+                : "=r" ( *set )
+                : "r" ( addr ), "r" ( compare ), "0" ( *set )
+                );
+            #else
+            #if ( XCHAL_HAVE_S32C1I > 0 )
+                __asm__ __volatile__ (
+                    "WSR 	    %2,SCOMPARE1 \n"
+                    "S32C1I     %0, %1, 0	 \n"
+                    : "=r" ( *set )
+                    : "r" ( addr ), "r" ( compare ), "0" ( *set )
+                    );
+            #else
+                /* No S32C1I, so do this by disabling and re-enabling interrupts (slower) */
+                uint32_t intlevel, old_value;
+                __asm__ __volatile__ ( "rsil %0, " XTSTR( XCHAL_EXCM_LEVEL ) "\n"
+                                       : "=r" ( intlevel ) );
+
+                old_value = *addr;
+
+                if( old_value == compare )
+                {
+                    *addr = *set;
+                }
+
+                __asm__ __volatile__ ( "memw \n"
+                                       "wsr %0, ps\n"
+                                       : : "r" ( intlevel ) );
+
+                *set = old_value;
+            #endif /* if ( XCHAL_HAVE_S32C1I > 0 ) */
+            #endif /* #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)) */
+        }
+
+        #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
+        void uxPortCompareSetExtram( volatile uint32_t * addr,
+                                     uint32_t compare,
+                                     uint32_t * set );
+        #else
+        static inline void uxPortCompareSetExtram(volatile uint32_t *addr, uint32_t compare, uint32_t *set) 
+        {
+        #if defined(CONFIG_ESP32_SPIRAM_SUPPORT)    
+            compare_and_set_extram(addr, compare, set);
+        #endif    
+        }
+        #endif
+
+/*-----------------------------------------------------------*/
+
+/* Architecture specifics. */
+    #define portSTACK_GROWTH      ( -1 )
+    #define portTICK_PERIOD_MS    ( ( TickType_t ) 1000 / configTICK_RATE_HZ )
+    #define portBYTE_ALIGNMENT    4
+    #define portNOP()    XT_NOP()
+/*-----------------------------------------------------------*/
+
+/* Fine resolution time */
+    #define portGET_RUN_TIME_COUNTER_VALUE()    xthal_get_ccount()
+/*ccount or esp_timer are initialized elsewhere */
+    #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS()
+
+    #ifdef CONFIG_FREERTOS_RUN_TIME_STATS_USING_ESP_TIMER
+/* Coarse resolution time (us) */
+        #define portALT_GET_RUN_TIME_COUNTER_VALUE( x )    x = ( uint32_t ) esp_timer_get_time()
+    #endif
+
+
+
+/* Kernel utilities. */
+    void vPortYield( void );
+    void _frxt_setup_switch( void );
+    #define portYIELD()             vPortYield()
+    #define portYIELD_FROM_ISR()    { traceISR_EXIT_TO_SCHEDULER(); _frxt_setup_switch(); }
+
+    static inline uint32_t xPortGetCoreID();
+
+/*-----------------------------------------------------------*/
+
+/* Task function macros as described on the FreeRTOS.org WEB site. */
+    #define portTASK_FUNCTION_PROTO( vFunction, pvParameters )    void vFunction( void * pvParameters )
+    #define portTASK_FUNCTION( vFunction, pvParameters )          void vFunction( void * pvParameters )
+
+/* When coprocessors are defined, we to maintain a pointer to coprocessors area. */
+/* We currently use a hack: redefine field xMPU_SETTINGS in TCB block as a structure that can hold: */
+/* MPU wrappers, coprocessor area pointer, trace code structure, and more if needed. */
+/* The field is normally used for memory protection. FreeRTOS should create another general purpose field. */
+    typedef struct
+    {
+        #if XCHAL_CP_NUM > 0
+            volatile StackType_t * coproc_area; /* Pointer to coprocessor save area; MUST BE FIRST */
+        #endif
+
+        #if portUSING_MPU_WRAPPERS
+            /* Define here mpu_settings, which is port dependent */
+            int mpu_setting; /* Just a dummy example here; MPU not ported to Xtensa yet */
+        #endif
+
+        #if configUSE_TRACE_FACILITY_2
+            struct
+            {
+                /* Cf. porttraceStamp() */
+                int taskstamp;      /* Stamp from inside task to see where we are */
+                int taskstampcount; /* A counter usually incremented when we restart the task's loop */
+            } porttrace;
+        #endif
+    } xMPU_SETTINGS;
+
+/* Main hack to use MPU_wrappers even when no MPU is defined (warning: mpu_setting should not be accessed; otherwise move this above xMPU_SETTINGS) */
+    #if ( XCHAL_CP_NUM > 0 || configUSE_TRACE_FACILITY_2 ) && !portUSING_MPU_WRAPPERS /* If MPU wrappers not used, we still need to allocate coproc area */
+        #undef portUSING_MPU_WRAPPERS
+        #define portUSING_MPU_WRAPPERS    1                                           /* Enable it to allocate coproc area */
+        #define MPU_WRAPPERS_H                                                        /* Override mpu_wrapper.h to disable unwanted code */
+        #define PRIVILEGED_FUNCTION
+        #define PRIVILEGED_DATA
+    #endif
+
+    void vApplicationSleep( TickType_t xExpectedIdleTime );
+    void vPortSetStackWatchpoint( void* pxStackStart );
+
+    #define portSUPPRESS_TICKS_AND_SLEEP( idleTime )    vApplicationSleep( idleTime )
+
+    /*-----------------------------------------------------------*/
+
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))    
+    /* Architecture specific optimisations. */
+    
+    #if configUSE_PORT_OPTIMISED_TASK_SELECTION == 1
+    
+    /* Check the configuration. */
+    #if( configMAX_PRIORITIES > 32 )
+        #error configUSE_PORT_OPTIMISED_TASK_SELECTION can only be set to 1 when configMAX_PRIORITIES is less than or equal to 32.  It is very rare that a system requires more than 10 to 15 different priorities as tasks that share a priority will time slice.
+    #endif
+    
+    /* Store/clear the ready priorities in a bit map. */
+    #define portRECORD_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) |= ( 1UL << ( uxPriority ) )
+    #define portRESET_READY_PRIORITY( uxPriority, uxReadyPriorities ) ( uxReadyPriorities ) &= ~( 1UL << ( uxPriority ) )
+    
+    /*-----------------------------------------------------------*/
+    
+    #define portGET_HIGHEST_PRIORITY( uxTopPriority, uxReadyPriorities ) uxTopPriority = ( 31 - __builtin_clz( ( uxReadyPriorities ) ) )
+    
+    #endif /* configUSE_PORT_OPTIMISED_TASK_SELECTION */
+
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+    
+    /*-----------------------------------------------------------*/
+    
+
+    void _xt_coproc_release( volatile void * coproc_sa_base );
+
+
+/*
+ * Map to the memory management routines required for the port.
+ *
+ * Note that libc standard malloc/free are also available for
+ * non-FreeRTOS-specific code, and behave the same as
+ * pvPortMalloc()/vPortFree().
+ */
+    #define pvPortMalloc                       heap_caps_malloc_default
+    #define vPortFree                          heap_caps_free
+    #define xPortGetFreeHeapSize               esp_get_free_heap_size
+    #define xPortGetMinimumEverFreeHeapSize    esp_get_minimum_free_heap_size
+
+#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
+/*
+ * Send an interrupt to another core in order to make the task running
+ * on it yield for a higher-priority task.
+ */
+
+        void vPortYieldOtherCore( BaseType_t coreid ) PRIVILEGED_FUNCTION;
+
+#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+/*
+ * Callback to set a watchpoint on the end of the stack. Called every context switch to change the stack
+ * watchpoint around.
+ */
+    void vPortSetStackWatchpoint( void * pxStackStart );
+
+/*
+ * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
+ * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
+ */
+    BaseType_t xPortInIsrContext();
+
+
+/*
+ * This function will be called in High prio ISRs. Returns true if the current core was in ISR context
+ * before calling into high prio ISR context.
+ */
+    BaseType_t xPortInterruptedFromISRContext();
+
+/*
+ * The structures and methods of manipulating the MPU are contained within the
+ * port layer.
+ *
+ * Fills the xMPUSettings structure with the memory region information
+ * contained in xRegions.
+ */
+    #if ( portUSING_MPU_WRAPPERS == 1 )
+        struct xMEMORY_REGION;
+        void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
+                                        const struct xMEMORY_REGION * const xRegions,
+                                        StackType_t * pxBottomOfStack,
+                                        uint32_t usStackDepth ) PRIVILEGED_FUNCTION;
+        void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings );
+    #endif
+
+/* Multi-core: get current core ID */
+    static inline uint32_t IRAM_ATTR xPortGetCoreID()
+    {
+        int id;
+
+        asm (
+            "rsr.prid %0\n"
+            " extui %0,%0,13,1"
+            : "=r" ( id ) );
+        return id;
+    }
+
+/* Get tick rate per second */
+    uint32_t xPortGetTickRateHz( void );
+
+/* porttrace */
+    #if configUSE_TRACE_FACILITY_2
+        #include "porttrace.h"
+    #endif
+
+/* configASSERT_2 if requested */
+    #if configASSERT_2
+        #include <stdio.h>
+        void exit( int );
+        #define configASSERT( x )    if( !( x ) ) { porttracePrint( -1 ); printf( "\nAssertion failed in %s:%d\n", __FILE__, __LINE__ ); exit( -1 ); }
+    #endif
+
+#endif // __ASSEMBLER__
+
+/* *INDENT-OFF* */
+#ifdef __cplusplus
+    }
+#endif
+/* *INDENT-ON* */
+
+#endif /* PORTMACRO_H */
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_context.h b/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_context.h
index 031db65..bb49eb2 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_context.h
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/include/xtensa_context.h
@@ -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 */
+
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/port.c b/portable/ThirdParty/GCC/Xtensa_ESP32/port.c
index 639e9f4..e5b7e1a 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/port.c
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/port.c
@@ -1,528 +1,528 @@
-/*

- *  FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.

- *  All rights reserved

- *

- *  VISIT https://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.

- *

- *  This file is part of the FreeRTOS distribution.

- *

- *  FreeRTOS is free software; you can redistribute it and/or modify it under

- *  the terms of the GNU General Public License (version 2) as published by the

- *  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.

- *

- ***************************************************************************

- *  >>!   NOTE: The modification to the GPL is included to allow you to     !<<

- *  >>!   distribute a combined work that includes FreeRTOS without being   !<<

- *  >>!   obliged to provide the source code for proprietary components     !<<

- *  >>!   outside of the FreeRTOS kernel.                                   !<<

- ***************************************************************************

- *

- *  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY

- *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS

- *  FOR A PARTICULAR PURPOSE.  Full license text is available on the following

- *  link: https://www.FreeRTOS.org/a00114.html

- *

- ***************************************************************************

- *                                                                       *

- *    FreeRTOS provides completely free yet professionally developed,    *

- *    robust, strictly quality controlled, supported, and cross          *

- *    platform software that is more than just the market leader, it     *

- *    is the industry's de facto standard.                               *

- *                                                                       *

- *    Help yourself get started quickly while simultaneously helping     *

- *    to support the FreeRTOS project by purchasing a FreeRTOS           *

- *    tutorial book, reference manual, or both:                          *

- *    https://www.FreeRTOS.org/Documentation                             *

- *                                                                       *

- ***************************************************************************

- *

- *  https://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading

- *  the FAQ page "My application does not run, what could be wrong?".  Have you

- *  defined configASSERT()?

- *

- *  https://www.FreeRTOS.org/support - In return for receiving this top quality

- *  embedded software for free we request you assist our global community by

- *  participating in the support forum.

- *

- *  https://www.FreeRTOS.org/training - Investing in training allows your team

- *  to be as productive as possible as early as possible.  Now you can receive

- *  FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers

- *  Ltd, and the world's leading authority on the world's leading RTOS.

- *

- *  https://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,

- *  including FreeRTOS+Trace - an indispensable productivity tool, a DOS

- *  compatible FAT file system, and our tiny thread aware UDP/IP stack.

- *

- *  https://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.

- *  Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.

- *

- *  https://www.highintegritysystems.com/openrtos/ - Real Time Engineers ltd.

- *  license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS

- *  brand.  Low cost OpenRTOS licenses offer ticketed support, indemnification

- *  and commercial middleware.

- *

- *  https://www.highintegritysystems.com/safertos/ - High Integrity Systems

- *  also provide a safety engineered and independently SIL3 certified version

- *  for use in safety and mission critical applications that require provable

- *  dependability.

- *

- */

-

-/*******************************************************************************

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

- * -----------------------------------------------------------------------------

- */

-

-#include <stdlib.h>

-#include <xtensa/config/core.h>

-

-#include "xtensa_rtos.h"

-#include "esp_idf_version.h"

-

-#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))

-#include "rom/ets_sys.h"

-#include "esp_panic.h"

-#include "esp_crosscore_int.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

-#include "esp_private/panic_reason.h"

-#include "esp_debug_helpers.h"

-#include "esp_private/crosscore_int.h"

-#include "esp_log.h"

-#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */

-#include "soc/cpu.h"

-

-#include "FreeRTOS.h"

-#include "task.h"

-

-#include "esp_heap_caps.h"

-

-#include "esp_intr_alloc.h"

-

-/* Defined in portasm.h */

-extern void _frxt_tick_timer_init( void );

-

-/* Defined in xtensa_context.S */

-extern void _xt_coproc_init( void );

-

-

-#if CONFIG_FREERTOS_CORETIMER_0

-    #define SYSTICK_INTR_ID    ( ETS_INTERNAL_TIMER0_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF )

-#endif

-#if CONFIG_FREERTOS_CORETIMER_1

-    #define SYSTICK_INTR_ID    ( ETS_INTERNAL_TIMER1_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF )

-#endif

-

-/*-----------------------------------------------------------*/

-

-unsigned port_xSchedulerRunning[ portNUM_PROCESSORS ] = { 0 }; /* Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting */

-unsigned port_interruptNesting[ portNUM_PROCESSORS ] = { 0 };  /* Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit */

-

-/*-----------------------------------------------------------*/

-

-/* User exception dispatcher when exiting */

-void _xt_user_exit( void );

-

-#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER

-/* Wrapper to allow task functions to return (increases stack overhead by 16 bytes) */

-    static void vPortTaskWrapper( TaskFunction_t pxCode,

-                                  void * pvParameters )

-    {

-        pxCode( pvParameters );

-        /*FreeRTOS tasks should not return. Log the task name and abort. */

-        char * pcTaskName = pcTaskGetTaskName( NULL );

-        ESP_LOGE( "FreeRTOS", "FreeRTOS Task \"%s\" should not return, Aborting now!", pcTaskName );

-        abort();

-    }

-#endif /* if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER */

-

-/*

- * Stack initialization

- */

-/* *INDENT-OFF* */

-#if portUSING_MPU_WRAPPERS

-    StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,

-                                         TaskFunction_t pxCode,

-                                         void * pvParameters,

-                                         BaseType_t xRunPrivileged )

-#else

-    StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,

-                                         TaskFunction_t pxCode,

-                                         void * pvParameters )

-#endif

-/* *INDENT-ON* */

-{

-    StackType_t * sp, * tp;

-    XtExcFrame * frame;

-

-    #if XCHAL_CP_NUM > 0

-        uint32_t * p;

-    #endif

-

-    /* Create interrupt stack frame aligned to 16 byte boundary */

-    sp = ( StackType_t * ) ( ( ( UBaseType_t ) pxTopOfStack - XT_CP_SIZE - XT_STK_FRMSZ ) & ~0xf );

-

-    /* Clear the entire frame (do not use memset() because we don't depend on C library) */

-    for( tp = sp; tp <= pxTopOfStack; ++tp )

-    {

-        *tp = 0;

-    }

-

-    frame = ( XtExcFrame * ) sp;

-

-    /* Explicitly initialize certain saved registers */

-    #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER

-        frame->pc = ( UBaseType_t ) vPortTaskWrapper; /* task wrapper						*/

-    #else

-        frame->pc = ( UBaseType_t ) pxCode;           /* task entrypoint					*/

-    #endif

-    frame->a0 = 0;                                    /* to terminate GDB backtrace		*/

-    frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ;    /* physical top of stack frame		*/

-    frame->exit = ( UBaseType_t ) _xt_user_exit;      /* user exception exit dispatcher	*/

-

-    /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */

-    /* Also set entry point argument parameter. */

-    #ifdef __XTENSA_CALL0_ABI__

-        #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER

-            frame->a2 = ( UBaseType_t ) pxCode;

-            frame->a3 = ( UBaseType_t ) pvParameters;

-        #else

-            frame->a2 = ( UBaseType_t ) pvParameters;

-        #endif

-        frame->ps = PS_UM | PS_EXCM;

-    #else

-        /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */

-        #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER

-            frame->a6 = ( UBaseType_t ) pxCode;

-            frame->a7 = ( UBaseType_t ) pvParameters;

-        #else

-            frame->a6 = ( UBaseType_t ) pvParameters;

-        #endif

-        frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );

-    #endif /* ifdef __XTENSA_CALL0_ABI__ */

-

-    #ifdef XT_USE_SWPRI

-        /* Set the initial virtual priority mask value to all 1's. */

-        frame->vpri = 0xFFFFFFFF;

-    #endif

-

-    #if XCHAL_CP_NUM > 0

-        /* Init the coprocessor save area (see xtensa_context.h) */

-

-        /* No access to TCB here, so derive indirectly. Stack growth is top to bottom.

-         * //p = (uint32_t *) xMPUSettings->coproc_area;

-         */

-        p = ( uint32_t * ) ( ( ( uint32_t ) pxTopOfStack - XT_CP_SIZE ) & ~0xf );

-        configASSERT( ( uint32_t ) p >= frame->a1 );

-        p[ 0 ] = 0;

-        p[ 1 ] = 0;

-        p[ 2 ] = ( ( ( uint32_t ) p ) + 12 + XCHAL_TOTAL_SA_ALIGN - 1 ) & -XCHAL_TOTAL_SA_ALIGN;

-    #endif

-

-    return sp;

-}

-

-/*-----------------------------------------------------------*/

-

-void vPortEndScheduler( void )

-{

-    /* It is unlikely that the Xtensa port will get stopped.  If required simply

-     * disable the tick interrupt here. */

-}

-

-/*-----------------------------------------------------------*/

-

-BaseType_t xPortStartScheduler( void )

-{

-    /* Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored */

-

-    #if XCHAL_CP_NUM > 0

-        /* Initialize co-processor management for tasks. Leave CPENABLE alone. */

-        _xt_coproc_init();

-    #endif

-

-    /* Init the tick divisor value */

-    _xt_tick_divisor_init();

-

-    /* Setup the hardware to generate the tick. */

-    _frxt_tick_timer_init();

-

-    port_xSchedulerRunning[ xPortGetCoreID() ] = 1;

-

-    /* Cannot be directly called from C; never returns */

-    __asm__ volatile ( "call0    _frxt_dispatch\n" );

-

-    /* Should not get here. */

-    return pdTRUE;

-}

-/*-----------------------------------------------------------*/

-

-BaseType_t xPortSysTickHandler( void )

-{

-    BaseType_t ret;

-    unsigned interruptMask;

-

-    portbenchmarkIntLatency();

-    traceISR_ENTER( SYSTICK_INTR_ID );

-

-    /* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be

-     * disabled before calling xTaskIncrementTick as it access the

-     * kernel lists. */

-    interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();

-    {

-        ret = xTaskIncrementTick();

-    }

-    portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );

-

-    if( ret != pdFALSE )

-    {

-        portYIELD_FROM_ISR();

-    }

-    else

-    {

-        traceISR_EXIT();

-    }

-

-    return ret;

-}

-

-

-void vPortYieldOtherCore( BaseType_t coreid )

-{

-    esp_crosscore_int_send_yield( coreid );

-}

-

-/*-----------------------------------------------------------*/

-

-/*

- * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.

- */

-#if portUSING_MPU_WRAPPERS

-    void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,

-                                    const struct xMEMORY_REGION * const xRegions,

-                                    StackType_t * pxBottomOfStack,

-                                    uint32_t usStackDepth )

-    {

-        #if XCHAL_CP_NUM > 0

-            xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + usStackDepth - 1 ));

-            xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );

-            xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf );

-

-

-            /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to

-             * clear the stack area after we return. This is done in pxPortInitialiseStack().

-             */

-        #endif

-    }

-

-    void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings )

-    {

-        /* If task has live floating point registers somewhere, release them */

-        _xt_coproc_release( xMPUSettings->coproc_area );

-    }

-

-#endif /* if portUSING_MPU_WRAPPERS */

-

-/*

- * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs

- * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.

- */

-BaseType_t xPortInIsrContext()

-{

-    unsigned int irqStatus;

-    BaseType_t ret;

-

-    irqStatus = portENTER_CRITICAL_NESTED();

-    ret = ( port_interruptNesting[ xPortGetCoreID() ] != 0 );

-    portEXIT_CRITICAL_NESTED( irqStatus );

-    return ret;

-}

-

-/*

- * This function will be called in High prio ISRs. Returns true if the current core was in ISR context

- * before calling into high prio ISR context.

- */

-BaseType_t IRAM_ATTR xPortInterruptedFromISRContext()

-{

-    return( port_interruptNesting[ xPortGetCoreID() ] != 0 );

-}

-

-void vPortAssertIfInISR()

-{

-    if( xPortInIsrContext() )

-    {

-        ets_printf( "core=%d port_interruptNesting=%d\n\n", xPortGetCoreID(), port_interruptNesting[ xPortGetCoreID() ] );

-    }

-

-    configASSERT( !xPortInIsrContext() );

-}

-

-/*

- * For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked.

- */

-void vPortCPUInitializeMutex( portMUX_TYPE * mux )

-{

-    #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-        ets_printf( "Initializing mux %p\n", mux );

-        mux->lastLockedFn = "(never locked)";

-        mux->lastLockedLine = -1;

-    #endif

-    mux->owner = portMUX_FREE_VAL;

-    mux->count = 0;

-}

-

-#include "portmux_impl.h"

-

-/*

- * For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long.

- */

-#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-    void vPortCPUAcquireMutex( portMUX_TYPE * mux,

-                               const char * fnName,

-                               int line )

-    {

-        unsigned int irqStatus = portENTER_CRITICAL_NESTED();

-

-        vPortCPUAcquireMutexIntsDisabled( mux, portMUX_NO_TIMEOUT, fnName, line );

-        portEXIT_CRITICAL_NESTED( irqStatus );

-    }

-

-    bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,

-                                      int timeout_cycles,

-                                      const char * fnName,

-                                      int line )

-    {

-        unsigned int irqStatus = portENTER_CRITICAL_NESTED();

-        bool result = vPortCPUAcquireMutexIntsDisabled( mux, timeout_cycles, fnName, line );

-

-        portEXIT_CRITICAL_NESTED( irqStatus );

-        return result;

-    }

-

-#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */

-    void vPortCPUAcquireMutex( portMUX_TYPE * mux )

-    {

-        unsigned int irqStatus = portENTER_CRITICAL_NESTED();

-

-        vPortCPUAcquireMutexIntsDisabled( mux, portMUX_NO_TIMEOUT );

-        portEXIT_CRITICAL_NESTED( irqStatus );

-    }

-

-    bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,

-                                      int timeout_cycles )

-    {

-        unsigned int irqStatus = portENTER_CRITICAL_NESTED();

-        bool result = vPortCPUAcquireMutexIntsDisabled( mux, timeout_cycles );

-

-        portEXIT_CRITICAL_NESTED( irqStatus );

-        return result;

-    }

-#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */

-

-

-/*

- * For kernel use: Release a per-CPU mux

- *

- * Mux must be already locked by this core

- */

-#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-    void vPortCPUReleaseMutex( portMUX_TYPE * mux,

-                               const char * fnName,

-                               int line )

-    {

-        unsigned int irqStatus = portENTER_CRITICAL_NESTED();

-

-        vPortCPUReleaseMutexIntsDisabled( mux, fnName, line );

-        portEXIT_CRITICAL_NESTED( irqStatus );

-    }

-#else

-    void vPortCPUReleaseMutex( portMUX_TYPE * mux )

-    {

-        unsigned int irqStatus = portENTER_CRITICAL_NESTED();

-

-        vPortCPUReleaseMutexIntsDisabled( mux );

-        portEXIT_CRITICAL_NESTED( irqStatus );

-    }

-#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */

-

-void vPortSetStackWatchpoint( void * pxStackStart )

-{

-    /*Set watchpoint 1 to watch the last 32 bytes of the stack. */

-    /*Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because */

-    /*the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32 */

-    /*bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most */

-    /*28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes. */

-    /*This way, we make sure we trigger before/when the stack canary is corrupted, not after. */

-    int addr = ( int ) pxStackStart;

-

-    addr = ( addr + 31 ) & ( ~31 );

-    esp_set_watchpoint( 1, ( char * ) addr, 32, ESP_WATCHPOINT_STORE );

-}

-

-#if defined( CONFIG_SPIRAM_SUPPORT )

-

-/*

- * Compare & set (S32C1) does not work in external RAM. Instead, this routine uses a mux (in internal memory) to fake it.

- */

-    static portMUX_TYPE extram_mux = portMUX_INITIALIZER_UNLOCKED;

-

-    void uxPortCompareSetExtram( volatile uint32_t * addr,

-                                 uint32_t compare,

-                                 uint32_t * set )

-    {

-        uint32_t prev;

-

-        uint32_t oldlevel = portENTER_CRITICAL_NESTED();

-

-        #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-            vPortCPUAcquireMutexIntsDisabled( &extram_mux, portMUX_NO_TIMEOUT, __FUNCTION__, __LINE__ );

-        #else

-            vPortCPUAcquireMutexIntsDisabled( &extram_mux, portMUX_NO_TIMEOUT );

-        #endif

-        prev = *addr;

-

-        if( prev == compare )

-        {

-            *addr = *set;

-        }

-

-        *set = prev;

-        #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG

-            vPortCPUReleaseMutexIntsDisabled( &extram_mux, __FUNCTION__, __LINE__ );

-        #else

-            vPortCPUReleaseMutexIntsDisabled( &extram_mux );

-        #endif

-

-        portEXIT_CRITICAL_NESTED(oldlevel);

-    }

-#endif //defined(CONFIG_SPIRAM_SUPPORT)

-

-

-

-uint32_t xPortGetTickRateHz( void )

-{

-    return ( uint32_t ) configTICK_RATE_HZ;

-}

+/*
+ *  FreeRTOS V8.2.0 - Copyright (C) 2015 Real Time Engineers Ltd.
+ *  All rights reserved
+ *
+ *  VISIT https://www.FreeRTOS.org TO ENSURE YOU ARE USING THE LATEST VERSION.
+ *
+ *  This file is part of the FreeRTOS distribution.
+ *
+ *  FreeRTOS is free software; you can redistribute it and/or modify it under
+ *  the terms of the GNU General Public License (version 2) as published by the
+ *  Free Software Foundation >>!AND MODIFIED BY!<< the FreeRTOS exception.
+ *
+ ***************************************************************************
+ *  >>!   NOTE: The modification to the GPL is included to allow you to     !<<
+ *  >>!   distribute a combined work that includes FreeRTOS without being   !<<
+ *  >>!   obliged to provide the source code for proprietary components     !<<
+ *  >>!   outside of the FreeRTOS kernel.                                   !<<
+ ***************************************************************************
+ *
+ *  FreeRTOS is distributed in the hope that it will be useful, but WITHOUT ANY
+ *  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ *  FOR A PARTICULAR PURPOSE.  Full license text is available on the following
+ *  link: https://www.FreeRTOS.org/a00114.html
+ *
+ ***************************************************************************
+ *                                                                       *
+ *    FreeRTOS provides completely free yet professionally developed,    *
+ *    robust, strictly quality controlled, supported, and cross          *
+ *    platform software that is more than just the market leader, it     *
+ *    is the industry's de facto standard.                               *
+ *                                                                       *
+ *    Help yourself get started quickly while simultaneously helping     *
+ *    to support the FreeRTOS project by purchasing a FreeRTOS           *
+ *    tutorial book, reference manual, or both:                          *
+ *    https://www.FreeRTOS.org/Documentation                             *
+ *                                                                       *
+ ***************************************************************************
+ *
+ *  https://www.FreeRTOS.org/FAQHelp.html - Having a problem?  Start by reading
+ *  the FAQ page "My application does not run, what could be wrong?".  Have you
+ *  defined configASSERT()?
+ *
+ *  https://www.FreeRTOS.org/support - In return for receiving this top quality
+ *  embedded software for free we request you assist our global community by
+ *  participating in the support forum.
+ *
+ *  https://www.FreeRTOS.org/training - Investing in training allows your team
+ *  to be as productive as possible as early as possible.  Now you can receive
+ *  FreeRTOS training directly from Richard Barry, CEO of Real Time Engineers
+ *  Ltd, and the world's leading authority on the world's leading RTOS.
+ *
+ *  https://www.FreeRTOS.org/plus - A selection of FreeRTOS ecosystem products,
+ *  including FreeRTOS+Trace - an indispensable productivity tool, a DOS
+ *  compatible FAT file system, and our tiny thread aware UDP/IP stack.
+ *
+ *  https://www.FreeRTOS.org/labs - Where new FreeRTOS products go to incubate.
+ *  Come and try FreeRTOS+TCP, our new open source TCP/IP stack for FreeRTOS.
+ *
+ *  https://www.highintegritysystems.com/openrtos/ - Real Time Engineers ltd.
+ *  license FreeRTOS to High Integrity Systems ltd. to sell under the OpenRTOS
+ *  brand.  Low cost OpenRTOS licenses offer ticketed support, indemnification
+ *  and commercial middleware.
+ *
+ *  https://www.highintegritysystems.com/safertos/ - High Integrity Systems
+ *  also provide a safety engineered and independently SIL3 certified version
+ *  for use in safety and mission critical applications that require provable
+ *  dependability.
+ *
+ */
+
+/*******************************************************************************
+ * // 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.
+ * -----------------------------------------------------------------------------
+ */
+
+#include <stdlib.h>
+#include <xtensa/config/core.h>
+
+#include "xtensa_rtos.h"
+#include "esp_idf_version.h"
+
+#if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
+#include "rom/ets_sys.h"
+#include "esp_panic.h"
+#include "esp_crosscore_int.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
+#include "esp_private/panic_reason.h"
+#include "esp_debug_helpers.h"
+#include "esp_private/crosscore_int.h"
+#include "esp_log.h"
+#endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
+#include "soc/cpu.h"
+
+#include "FreeRTOS.h"
+#include "task.h"
+
+#include "esp_heap_caps.h"
+
+#include "esp_intr_alloc.h"
+
+/* Defined in portasm.h */
+extern void _frxt_tick_timer_init( void );
+
+/* Defined in xtensa_context.S */
+extern void _xt_coproc_init( void );
+
+
+#if CONFIG_FREERTOS_CORETIMER_0
+    #define SYSTICK_INTR_ID    ( ETS_INTERNAL_TIMER0_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF )
+#endif
+#if CONFIG_FREERTOS_CORETIMER_1
+    #define SYSTICK_INTR_ID    ( ETS_INTERNAL_TIMER1_INTR_SOURCE + ETS_INTERNAL_INTR_SOURCE_OFF )
+#endif
+
+/*-----------------------------------------------------------*/
+
+unsigned port_xSchedulerRunning[ portNUM_PROCESSORS ] = { 0 }; /* Duplicate of inaccessible xSchedulerRunning; needed at startup to avoid counting nesting */
+unsigned port_interruptNesting[ portNUM_PROCESSORS ] = { 0 };  /* Interrupt nesting level. Increased/decreased in portasm.c, _frxt_int_enter/_frxt_int_exit */
+
+/*-----------------------------------------------------------*/
+
+/* User exception dispatcher when exiting */
+void _xt_user_exit( void );
+
+#if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
+/* Wrapper to allow task functions to return (increases stack overhead by 16 bytes) */
+    static void vPortTaskWrapper( TaskFunction_t pxCode,
+                                  void * pvParameters )
+    {
+        pxCode( pvParameters );
+        /*FreeRTOS tasks should not return. Log the task name and abort. */
+        char * pcTaskName = pcTaskGetTaskName( NULL );
+        ESP_LOGE( "FreeRTOS", "FreeRTOS Task \"%s\" should not return, Aborting now!", pcTaskName );
+        abort();
+    }
+#endif /* if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER */
+
+/*
+ * Stack initialization
+ */
+/* *INDENT-OFF* */
+#if portUSING_MPU_WRAPPERS
+    StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+                                         TaskFunction_t pxCode,
+                                         void * pvParameters,
+                                         BaseType_t xRunPrivileged )
+#else
+    StackType_t * pxPortInitialiseStack( StackType_t * pxTopOfStack,
+                                         TaskFunction_t pxCode,
+                                         void * pvParameters )
+#endif
+/* *INDENT-ON* */
+{
+    StackType_t * sp, * tp;
+    XtExcFrame * frame;
+
+    #if XCHAL_CP_NUM > 0
+        uint32_t * p;
+    #endif
+
+    /* Create interrupt stack frame aligned to 16 byte boundary */
+    sp = ( StackType_t * ) ( ( ( UBaseType_t ) pxTopOfStack - XT_CP_SIZE - XT_STK_FRMSZ ) & ~0xf );
+
+    /* Clear the entire frame (do not use memset() because we don't depend on C library) */
+    for( tp = sp; tp <= pxTopOfStack; ++tp )
+    {
+        *tp = 0;
+    }
+
+    frame = ( XtExcFrame * ) sp;
+
+    /* Explicitly initialize certain saved registers */
+    #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
+        frame->pc = ( UBaseType_t ) vPortTaskWrapper; /* task wrapper						*/
+    #else
+        frame->pc = ( UBaseType_t ) pxCode;           /* task entrypoint					*/
+    #endif
+    frame->a0 = 0;                                    /* to terminate GDB backtrace		*/
+    frame->a1 = ( UBaseType_t ) sp + XT_STK_FRMSZ;    /* physical top of stack frame		*/
+    frame->exit = ( UBaseType_t ) _xt_user_exit;      /* user exception exit dispatcher	*/
+
+    /* Set initial PS to int level 0, EXCM disabled ('rfe' will enable), user mode. */
+    /* Also set entry point argument parameter. */
+    #ifdef __XTENSA_CALL0_ABI__
+        #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
+            frame->a2 = ( UBaseType_t ) pxCode;
+            frame->a3 = ( UBaseType_t ) pvParameters;
+        #else
+            frame->a2 = ( UBaseType_t ) pvParameters;
+        #endif
+        frame->ps = PS_UM | PS_EXCM;
+    #else
+        /* + for windowed ABI also set WOE and CALLINC (pretend task was 'call4'd). */
+        #if CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER
+            frame->a6 = ( UBaseType_t ) pxCode;
+            frame->a7 = ( UBaseType_t ) pvParameters;
+        #else
+            frame->a6 = ( UBaseType_t ) pvParameters;
+        #endif
+        frame->ps = PS_UM | PS_EXCM | PS_WOE | PS_CALLINC( 1 );
+    #endif /* ifdef __XTENSA_CALL0_ABI__ */
+
+    #ifdef XT_USE_SWPRI
+        /* Set the initial virtual priority mask value to all 1's. */
+        frame->vpri = 0xFFFFFFFF;
+    #endif
+
+    #if XCHAL_CP_NUM > 0
+        /* Init the coprocessor save area (see xtensa_context.h) */
+
+        /* No access to TCB here, so derive indirectly. Stack growth is top to bottom.
+         * //p = (uint32_t *) xMPUSettings->coproc_area;
+         */
+        p = ( uint32_t * ) ( ( ( uint32_t ) pxTopOfStack - XT_CP_SIZE ) & ~0xf );
+        configASSERT( ( uint32_t ) p >= frame->a1 );
+        p[ 0 ] = 0;
+        p[ 1 ] = 0;
+        p[ 2 ] = ( ( ( uint32_t ) p ) + 12 + XCHAL_TOTAL_SA_ALIGN - 1 ) & -XCHAL_TOTAL_SA_ALIGN;
+    #endif
+
+    return sp;
+}
+
+/*-----------------------------------------------------------*/
+
+void vPortEndScheduler( void )
+{
+    /* It is unlikely that the Xtensa port will get stopped.  If required simply
+     * disable the tick interrupt here. */
+}
+
+/*-----------------------------------------------------------*/
+
+BaseType_t xPortStartScheduler( void )
+{
+    /* Interrupts are disabled at this point and stack contains PS with enabled interrupts when task context is restored */
+
+    #if XCHAL_CP_NUM > 0
+        /* Initialize co-processor management for tasks. Leave CPENABLE alone. */
+        _xt_coproc_init();
+    #endif
+
+    /* Init the tick divisor value */
+    _xt_tick_divisor_init();
+
+    /* Setup the hardware to generate the tick. */
+    _frxt_tick_timer_init();
+
+    port_xSchedulerRunning[ xPortGetCoreID() ] = 1;
+
+    /* Cannot be directly called from C; never returns */
+    __asm__ volatile ( "call0    _frxt_dispatch\n" );
+
+    /* Should not get here. */
+    return pdTRUE;
+}
+/*-----------------------------------------------------------*/
+
+BaseType_t xPortSysTickHandler( void )
+{
+    BaseType_t ret;
+    unsigned interruptMask;
+
+    portbenchmarkIntLatency();
+    traceISR_ENTER( SYSTICK_INTR_ID );
+
+    /* Interrupts upto configMAX_SYSCALL_INTERRUPT_PRIORITY must be
+     * disabled before calling xTaskIncrementTick as it access the
+     * kernel lists. */
+    interruptMask = portSET_INTERRUPT_MASK_FROM_ISR();
+    {
+        ret = xTaskIncrementTick();
+    }
+    portCLEAR_INTERRUPT_MASK_FROM_ISR( interruptMask );
+
+    if( ret != pdFALSE )
+    {
+        portYIELD_FROM_ISR();
+    }
+    else
+    {
+        traceISR_EXIT();
+    }
+
+    return ret;
+}
+
+
+void vPortYieldOtherCore( BaseType_t coreid )
+{
+    esp_crosscore_int_send_yield( coreid );
+}
+
+/*-----------------------------------------------------------*/
+
+/*
+ * Used to set coprocessor area in stack. Current hack is to reuse MPU pointer for coprocessor area.
+ */
+#if portUSING_MPU_WRAPPERS
+    void vPortStoreTaskMPUSettings( xMPU_SETTINGS * xMPUSettings,
+                                    const struct xMEMORY_REGION * const xRegions,
+                                    StackType_t * pxBottomOfStack,
+                                    uint32_t usStackDepth )
+    {
+        #if XCHAL_CP_NUM > 0
+            xMPUSettings->coproc_area = ( StackType_t * ) ( ( uint32_t ) ( pxBottomOfStack + usStackDepth - 1 ));
+            xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( portPOINTER_SIZE_TYPE ) xMPUSettings->coproc_area ) & ( ~( ( portPOINTER_SIZE_TYPE ) portBYTE_ALIGNMENT_MASK ) ) );
+            xMPUSettings->coproc_area = ( StackType_t * ) ( ( ( uint32_t ) xMPUSettings->coproc_area - XT_CP_SIZE ) & ~0xf );
+
+
+            /* NOTE: we cannot initialize the coprocessor save area here because FreeRTOS is going to
+             * clear the stack area after we return. This is done in pxPortInitialiseStack().
+             */
+        #endif
+    }
+
+    void vPortReleaseTaskMPUSettings( xMPU_SETTINGS * xMPUSettings )
+    {
+        /* If task has live floating point registers somewhere, release them */
+        _xt_coproc_release( xMPUSettings->coproc_area );
+    }
+
+#endif /* if portUSING_MPU_WRAPPERS */
+
+/*
+ * Returns true if the current core is in ISR context; low prio ISR, med prio ISR or timer tick ISR. High prio ISRs
+ * aren't detected here, but they normally cannot call C code, so that should not be an issue anyway.
+ */
+BaseType_t xPortInIsrContext()
+{
+    unsigned int irqStatus;
+    BaseType_t ret;
+
+    irqStatus = portENTER_CRITICAL_NESTED();
+    ret = ( port_interruptNesting[ xPortGetCoreID() ] != 0 );
+    portEXIT_CRITICAL_NESTED( irqStatus );
+    return ret;
+}
+
+/*
+ * This function will be called in High prio ISRs. Returns true if the current core was in ISR context
+ * before calling into high prio ISR context.
+ */
+BaseType_t IRAM_ATTR xPortInterruptedFromISRContext()
+{
+    return( port_interruptNesting[ xPortGetCoreID() ] != 0 );
+}
+
+void vPortAssertIfInISR()
+{
+    if( xPortInIsrContext() )
+    {
+        ets_printf( "core=%d port_interruptNesting=%d\n\n", xPortGetCoreID(), port_interruptNesting[ xPortGetCoreID() ] );
+    }
+
+    configASSERT( !xPortInIsrContext() );
+}
+
+/*
+ * For kernel use: Initialize a per-CPU mux. Mux will be initialized unlocked.
+ */
+void vPortCPUInitializeMutex( portMUX_TYPE * mux )
+{
+    #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+        ets_printf( "Initializing mux %p\n", mux );
+        mux->lastLockedFn = "(never locked)";
+        mux->lastLockedLine = -1;
+    #endif
+    mux->owner = portMUX_FREE_VAL;
+    mux->count = 0;
+}
+
+#include "portmux_impl.h"
+
+/*
+ * For kernel use: Acquire a per-CPU mux. Spinlocks, so don't hold on to these muxes for too long.
+ */
+#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+    void vPortCPUAcquireMutex( portMUX_TYPE * mux,
+                               const char * fnName,
+                               int line )
+    {
+        unsigned int irqStatus = portENTER_CRITICAL_NESTED();
+
+        vPortCPUAcquireMutexIntsDisabled( mux, portMUX_NO_TIMEOUT, fnName, line );
+        portEXIT_CRITICAL_NESTED( irqStatus );
+    }
+
+    bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,
+                                      int timeout_cycles,
+                                      const char * fnName,
+                                      int line )
+    {
+        unsigned int irqStatus = portENTER_CRITICAL_NESTED();
+        bool result = vPortCPUAcquireMutexIntsDisabled( mux, timeout_cycles, fnName, line );
+
+        portEXIT_CRITICAL_NESTED( irqStatus );
+        return result;
+    }
+
+#else /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
+    void vPortCPUAcquireMutex( portMUX_TYPE * mux )
+    {
+        unsigned int irqStatus = portENTER_CRITICAL_NESTED();
+
+        vPortCPUAcquireMutexIntsDisabled( mux, portMUX_NO_TIMEOUT );
+        portEXIT_CRITICAL_NESTED( irqStatus );
+    }
+
+    bool vPortCPUAcquireMutexTimeout( portMUX_TYPE * mux,
+                                      int timeout_cycles )
+    {
+        unsigned int irqStatus = portENTER_CRITICAL_NESTED();
+        bool result = vPortCPUAcquireMutexIntsDisabled( mux, timeout_cycles );
+
+        portEXIT_CRITICAL_NESTED( irqStatus );
+        return result;
+    }
+#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
+
+
+/*
+ * For kernel use: Release a per-CPU mux
+ *
+ * Mux must be already locked by this core
+ */
+#ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+    void vPortCPUReleaseMutex( portMUX_TYPE * mux,
+                               const char * fnName,
+                               int line )
+    {
+        unsigned int irqStatus = portENTER_CRITICAL_NESTED();
+
+        vPortCPUReleaseMutexIntsDisabled( mux, fnName, line );
+        portEXIT_CRITICAL_NESTED( irqStatus );
+    }
+#else
+    void vPortCPUReleaseMutex( portMUX_TYPE * mux )
+    {
+        unsigned int irqStatus = portENTER_CRITICAL_NESTED();
+
+        vPortCPUReleaseMutexIntsDisabled( mux );
+        portEXIT_CRITICAL_NESTED( irqStatus );
+    }
+#endif /* ifdef CONFIG_FREERTOS_PORTMUX_DEBUG */
+
+void vPortSetStackWatchpoint( void * pxStackStart )
+{
+    /*Set watchpoint 1 to watch the last 32 bytes of the stack. */
+    /*Unfortunately, the Xtensa watchpoints can't set a watchpoint on a random [base - base+n] region because */
+    /*the size works by masking off the lowest address bits. For that reason, we futz a bit and watch the lowest 32 */
+    /*bytes of the stack we can actually watch. In general, this can cause the watchpoint to be triggered at most */
+    /*28 bytes early. The value 32 is chosen because it's larger than the stack canary, which in FreeRTOS is 20 bytes. */
+    /*This way, we make sure we trigger before/when the stack canary is corrupted, not after. */
+    int addr = ( int ) pxStackStart;
+
+    addr = ( addr + 31 ) & ( ~31 );
+    esp_set_watchpoint( 1, ( char * ) addr, 32, ESP_WATCHPOINT_STORE );
+}
+
+#if defined( CONFIG_SPIRAM_SUPPORT )
+
+/*
+ * Compare & set (S32C1) does not work in external RAM. Instead, this routine uses a mux (in internal memory) to fake it.
+ */
+    static portMUX_TYPE extram_mux = portMUX_INITIALIZER_UNLOCKED;
+
+    void uxPortCompareSetExtram( volatile uint32_t * addr,
+                                 uint32_t compare,
+                                 uint32_t * set )
+    {
+        uint32_t prev;
+
+        uint32_t oldlevel = portENTER_CRITICAL_NESTED();
+
+        #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+            vPortCPUAcquireMutexIntsDisabled( &extram_mux, portMUX_NO_TIMEOUT, __FUNCTION__, __LINE__ );
+        #else
+            vPortCPUAcquireMutexIntsDisabled( &extram_mux, portMUX_NO_TIMEOUT );
+        #endif
+        prev = *addr;
+
+        if( prev == compare )
+        {
+            *addr = *set;
+        }
+
+        *set = prev;
+        #ifdef CONFIG_FREERTOS_PORTMUX_DEBUG
+            vPortCPUReleaseMutexIntsDisabled( &extram_mux, __FUNCTION__, __LINE__ );
+        #else
+            vPortCPUReleaseMutexIntsDisabled( &extram_mux );
+        #endif
+
+        portEXIT_CRITICAL_NESTED(oldlevel);
+    }
+#endif //defined(CONFIG_SPIRAM_SUPPORT)
+
+
+
+uint32_t xPortGetTickRateHz( void )
+{
+    return ( uint32_t ) configTICK_RATE_HZ;
+}
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/portasm.S b/portable/ThirdParty/GCC/Xtensa_ESP32/portasm.S
index 8985bf3..1dd7d5e 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/portasm.S
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/portasm.S
@@ -1,684 +1,684 @@
-/*

-//-----------------------------------------------------------------------------

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

-//-----------------------------------------------------------------------------

-*/

-

-#include "xtensa_rtos.h"

-#include "sdkconfig.h"

-#include "esp_idf_version.h"

-

-#define TOPOFSTACK_OFFS                 0x00    /* StackType_t *pxTopOfStack */

-#define CP_TOPOFSTACK_OFFS              0x04    /* xMPU_SETTINGS.coproc_area */

-

-.extern pxCurrentTCB

-

-/*

-*******************************************************************************

-* Interrupt stack. The size of the interrupt stack is determined by the config

-* parameter "configISR_STACK_SIZE" in FreeRTOSConfig.h

-*******************************************************************************

-*/

-

-    .data

-    .align      16

-    .global     port_IntStack

-    .global     port_IntStackTop

-    .global     port_switch_flag

-port_IntStack:

-    .space      configISR_STACK_SIZE*portNUM_PROCESSORS		/* This allocates stacks for each individual CPU. */

-port_IntStackTop:

-    .word		0

-port_switch_flag:

-    .space      portNUM_PROCESSORS*4 /* One flag for each individual CPU. */

-

-    .text

-

-/*

-*******************************************************************************

-* _frxt_setup_switch

-* void _frxt_setup_switch(void);

-* 

-* Sets an internal flag indicating that a task switch is required on return

-* from interrupt handling.

-* 

-*******************************************************************************

-*/

-    .global     _frxt_setup_switch

-    .type       _frxt_setup_switch,@function

-    .align      4

-_frxt_setup_switch:

-

-    ENTRY(16)

-

-	getcoreid a3

-    movi    a2, port_switch_flag

-	addx4	a2,  a3, a2

-

-    movi    a3, 1

-    s32i    a3, a2, 0

-

-    RET(16)

-

-

-

-

-

-

-/*

-*******************************************************************************

-* _frxt_int_enter

-* void _frxt_int_enter(void)

-*

-* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_ENTER function for

-* freeRTOS. Saves the rest of the interrupt context (not already saved).

-* May only be called from assembly code by the 'call0' instruction, with

-* interrupts disabled.

-* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.

-*

-*******************************************************************************

-*/

-    .globl  _frxt_int_enter

-    .type   _frxt_int_enter,@function

-    .align  4

-_frxt_int_enter:

-

-    /* Save a12-13 in the stack frame as required by _xt_context_save. */

-    s32i    a12, a1, XT_STK_A12

-    s32i    a13, a1, XT_STK_A13

-

-    /* Save return address in a safe place (free a0). */

-    mov     a12, a0

-

-    /* Save the rest of the interrupted context (preserves A12-13). */

-    call0   _xt_context_save

-

-    /*

-    Save interrupted task's SP in TCB only if not nesting.

-    Manage nesting directly rather than call the generic IntEnter()

-    (in windowed ABI we can't call a C function here anyway because PS.EXCM is still set).

-    */

-	getcoreid a4

-    movi    a2,  port_xSchedulerRunning

-	addx4	a2,  a4, a2

-    movi    a3,  port_interruptNesting

-	addx4	a3,  a4, a3

-    l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */

-    beqz    a2,  1f                     /* scheduler not running, no tasks */

-    l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */

-    addi    a2,  a2, 1                  /* increment nesting count         */

-    s32i    a2,  a3, 0                  /* save nesting count              */

-    bnei    a2,  1, .Lnested            /* !=0 before incr, so nested      */

-

-    movi    a2,  pxCurrentTCB

-	addx4	a2,  a4, a2

-    l32i    a2,  a2, 0                  /* a2 = current TCB                */

-    beqz    a2,  1f

-    s32i    a1,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP */

-    movi    a1,  port_IntStack+configISR_STACK_SIZE   /* a1 = top of intr stack for CPU 0  */

-    movi    a2,  configISR_STACK_SIZE   /* add configISR_STACK_SIZE * cpu_num to arrive at top of stack for cpu_num */

-	mull	a2,  a4, a2

-	add     a1,  a1, a2					/* for current proc */

-

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef CONFIG_FREERTOS_FPU_IN_ISR

-    #if XCHAL_CP_NUM > 0

-    rsr     a3, CPENABLE                /* Restore thread scope CPENABLE */

-    addi    sp, sp,-4                   /* ISR will manage FPU coprocessor by forcing */

-    s32i    a3, a1, 0                   /* its trigger */

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-.Lnested:

-1:

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef CONFIG_FREERTOS_FPU_IN_ISR

-    #if XCHAL_CP_NUM > 0

-    movi    a3,  0              /* whilst ISRs pending keep CPENABLE exception active */

-    wsr     a3,  CPENABLE

-    rsync

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    mov     a0,  a12                    /* restore return addr and return  */

-    ret

-

-/*

-*******************************************************************************

-* _frxt_int_exit

-* void _frxt_int_exit(void)

-*

-* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_EXIT function for

-* FreeRTOS. If required, calls vPortYieldFromInt() to perform task context

-* switching, restore the (possibly) new task's context, and return to the

-* exit dispatcher saved in the task's stack frame at XT_STK_EXIT.

-* May only be called from assembly code by the 'call0' instruction. Does not

-* return to caller.

-* See the description of the XT_RTOS_ENTER macro in xtensa_rtos.h.

-*

-*******************************************************************************

-*/

-    .globl  _frxt_int_exit

-    .type   _frxt_int_exit,@function

-    .align  4

-_frxt_int_exit:

-

-	getcoreid a4

-    movi    a2,  port_xSchedulerRunning

-	addx4	a2,  a4, a2

-    movi    a3,  port_interruptNesting

-	addx4	a3,  a4, a3

-    rsil    a0,  XCHAL_EXCM_LEVEL       /* lock out interrupts             */

-    l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */

-    beqz    a2,  .Lnoswitch             /* scheduler not running, no tasks */

-    l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */

-    addi    a2,  a2, -1                 /* decrement nesting count         */

-    s32i    a2,  a3, 0                  /* save nesting count              */

-    bnez    a2,  .Lnesting              /* !=0 after decr so still nested  */

-

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef CONFIG_FREERTOS_FPU_IN_ISR 

-    #if XCHAL_CP_NUM > 0

-    l32i    a3,  sp, 0                  /* Grab last CPENABLE before leave ISR */

-    addi    sp,  sp, 4

-    wsr     a3, CPENABLE

-    rsync                               /* ensure CPENABLE was modified */

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    movi    a2,  pxCurrentTCB

-	addx4	a2,  a4, a2

-    l32i    a2,  a2, 0                  /* a2 = current TCB                */

-    beqz    a2,  1f                     /* no task ? go to dispatcher      */

-    l32i    a1,  a2, TOPOFSTACK_OFFS    /* SP = pxCurrentTCB->pxTopOfStack */

-

-    movi    a2,  port_switch_flag       /* address of switch flag          */

-	addx4	a2,  a4, a2					/* point to flag for this cpu      */

-    l32i    a3,  a2, 0                  /* a3 = port_switch_flag           */

-    beqz    a3,  .Lnoswitch             /* flag = 0 means no switch reqd   */

-    movi    a3,  0

-    s32i    a3,  a2, 0                  /* zero out the flag for next time */

-

-1:

-    /*

-    Call0 ABI callee-saved regs a12-15 need to be saved before possible preemption.

-    However a12-13 were already saved by _frxt_int_enter().

-    */

-    #ifdef __XTENSA_CALL0_ABI__

-    s32i    a14, a1, XT_STK_A14

-    s32i    a15, a1, XT_STK_A15

-    #endif

-

-    #ifdef __XTENSA_CALL0_ABI__

-    call0   vPortYieldFromInt       /* call dispatch inside the function; never returns */

-    #else

-    call4   vPortYieldFromInt       /* this one returns */

-    call0   _frxt_dispatch          /* tail-call dispatcher */

-    /* Never returns here. */

-    #endif

-

-.Lnoswitch:

-    /*

-    If we came here then about to resume the interrupted task.

-    */

-

-.Lnesting:

-    /*

-    We come here only if there was no context switch, that is if this

-    is a nested interrupt, or the interrupted task was not preempted.

-    In either case there's no need to load the SP.

-    */

-

-    /* Restore full context from interrupt stack frame */

-    call0   _xt_context_restore

-

-    /*

-    Must return via the exit dispatcher corresponding to the entrypoint from which

-    this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt

-    stack frame is deallocated in the exit dispatcher.

-    */

-    l32i    a0,  a1, XT_STK_EXIT

-    ret

-

-

-/*

-**********************************************************************************************************

-*                                           _frxt_timer_int

-*                                      void _frxt_timer_int(void)

-*

-* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for FreeRTOS.

-* Called every timer interrupt.

-* Manages the tick timer and calls xPortSysTickHandler() every tick.

-* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.

-*

-* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance.

-*

-**********************************************************************************************************

-*/

-    .globl  _frxt_timer_int

-    .type   _frxt_timer_int,@function

-    .align  4

-_frxt_timer_int:

-

-    /*

-    Xtensa timers work by comparing a cycle counter with a preset value.  Once the match occurs

-    an interrupt is generated, and the handler has to set a new cycle count into the comparator.

-    To avoid clock drift due to interrupt latency, the new cycle count is computed from the old,

-    not the time the interrupt was serviced. However if a timer interrupt is ever serviced more

-    than one tick late, it is necessary to process multiple ticks until the new cycle count is

-    in the future, otherwise the next timer interrupt would not occur until after the cycle

-    counter had wrapped (2^32 cycles later).

-

-    do {

-        ticks++;

-        old_ccompare = read_ccompare_i();

-        write_ccompare_i( old_ccompare + divisor );

-        service one tick;

-        diff = read_ccount() - old_ccompare;

-    } while ( diff > divisor );

-    */

-

-    ENTRY(16)

-

-    #ifdef CONFIG_PM_TRACE

-    movi a6, 1 /* = ESP_PM_TRACE_TICK */

-    getcoreid a7

-    call4 esp_pm_trace_enter

-    #endif // CONFIG_PM_TRACE

-

-.L_xt_timer_int_catchup:

-

-    /* Update the timer comparator for the next tick. */

-    #ifdef XT_CLOCK_FREQ

-    movi    a2, XT_TICK_DIVISOR         /* a2 = comparator increment          */

-    #else

-    movi    a3, _xt_tick_divisor

-    l32i    a2, a3, 0                   /* a2 = comparator increment          */

-    #endif

-    rsr     a3, XT_CCOMPARE             /* a3 = old comparator value          */

-    add     a4, a3, a2                  /* a4 = new comparator value          */

-    wsr     a4, XT_CCOMPARE             /* update comp. and clear interrupt   */

-    esync

-

-    #ifdef __XTENSA_CALL0_ABI__

-    /* Preserve a2 and a3 across C calls. */

-    s32i    a2, sp, 4

-    s32i    a3, sp, 8

-    #endif

-

-    /* Call the FreeRTOS tick handler (see port.c). */

-    #ifdef __XTENSA_CALL0_ABI__

-    call0   xPortSysTickHandler

-    #else

-    call4   xPortSysTickHandler

-    #endif

-

-    #ifdef __XTENSA_CALL0_ABI__

-    /* Restore a2 and a3. */

-    l32i    a2, sp, 4

-    l32i    a3, sp, 8

-    #endif

-

-    /* Check if we need to process more ticks to catch up. */

-    esync                               /* ensure comparator update complete  */

-    rsr     a4, CCOUNT                  /* a4 = cycle count                   */

-    sub     a4, a4, a3                  /* diff = ccount - old comparator     */

-    blt     a2, a4, .L_xt_timer_int_catchup  /* repeat while diff > divisor */

-

-#ifdef CONFIG_PM_TRACE

-    movi a6, 1 /* = ESP_PM_TRACE_TICK */

-    getcoreid a7

-    call4 esp_pm_trace_exit

-#endif // CONFIG_PM_TRACE

-

-    RET(16)

-

-    /*

-**********************************************************************************************************

-*                                           _frxt_tick_timer_init

-*                                      void _frxt_tick_timer_init(void)

-*

-* Initialize timer and timer interrrupt handler (_xt_tick_divisor_init() has already been been called).

-* Callable from C (obeys ABI conventions on entry).

-*

-**********************************************************************************************************

-*/

-    .globl  _frxt_tick_timer_init

-    .type   _frxt_tick_timer_init,@function

-    .align  4

-_frxt_tick_timer_init:

-

-    ENTRY(16)

-

-

-    /* Set up the periodic tick timer (assume enough time to complete init). */

-    #ifdef XT_CLOCK_FREQ

-    movi    a3, XT_TICK_DIVISOR

-    #else

-    movi    a2, _xt_tick_divisor

-    l32i    a3, a2, 0

-    #endif

-    rsr     a2, CCOUNT              /* current cycle count */

-    add     a2, a2, a3              /* time of first timer interrupt */

-    wsr     a2, XT_CCOMPARE         /* set the comparator */

-

-    /*

-    Enable the timer interrupt at the device level. Don't write directly

-    to the INTENABLE register because it may be virtualized.

-    */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a2, XT_TIMER_INTEN

-    call0   xt_ints_on

-    #else

-    movi    a6, XT_TIMER_INTEN

-    call4   xt_ints_on

-    #endif

-

-    RET(16)

-

-/*

-**********************************************************************************************************

-*                                    DISPATCH THE HIGH READY TASK

-*                                     void _frxt_dispatch(void)

-*

-* Switch context to the highest priority ready task, restore its state and dispatch control to it.

-*

-* This is a common dispatcher that acts as a shared exit path for all the context switch functions

-* including vPortYield() and vPortYieldFromInt(), all of which tail-call this dispatcher

-* (for windowed ABI vPortYieldFromInt() calls it indirectly via _frxt_int_exit() ).

-*

-* The Xtensa port uses different stack frames for solicited and unsolicited task suspension (see

-* comments on stack frames in xtensa_context.h). This function restores the state accordingly.

-* If restoring a task that solicited entry, restores the minimal state and leaves CPENABLE clear.

-* If restoring a task that was preempted, restores all state including the task's CPENABLE.

-*

-* Entry:

-*   pxCurrentTCB  points to the TCB of the task to suspend,

-*   Because it is tail-called without a true function entrypoint, it needs no 'entry' instruction.

-*

-* Exit:

-*   If incoming task called vPortYield() (solicited), this function returns as if from vPortYield().

-*   If incoming task was preempted by an interrupt, this function jumps to exit dispatcher.

-*

-**********************************************************************************************************

-*/

-    .globl  _frxt_dispatch

-    .type   _frxt_dispatch,@function

-    .align  4

-_frxt_dispatch:

-

-    #ifdef __XTENSA_CALL0_ABI__

-    call0   vTaskSwitchContext  // Get next TCB to resume

-    movi    a2, pxCurrentTCB

-	getcoreid a3

-	addx4	a2,  a3, a2

-    #else

-    call4   vTaskSwitchContext  // Get next TCB to resume

-    movi    a2, pxCurrentTCB

-	getcoreid a3

-	addx4	a2,  a3, a2

-    #endif

-    l32i    a3,  a2, 0

-    l32i    sp,  a3, TOPOFSTACK_OFFS     /* SP = next_TCB->pxTopOfStack;  */

-    s32i    a3,  a2, 0

-

-    /* Determine the type of stack frame. */

-    l32i    a2,  sp, XT_STK_EXIT        /* exit dispatcher or solicited flag */

-    bnez    a2,  .L_frxt_dispatch_stk

-

-.L_frxt_dispatch_sol:

-

-    /* Solicited stack frame. Restore minimal context and return from vPortYield(). */

-    l32i    a3,  sp, XT_SOL_PS

-    #ifdef __XTENSA_CALL0_ABI__

-    l32i    a12, sp, XT_SOL_A12

-    l32i    a13, sp, XT_SOL_A13

-    l32i    a14, sp, XT_SOL_A14

-    l32i    a15, sp, XT_SOL_A15

-    #endif

-    l32i    a0,  sp, XT_SOL_PC

-    #if XCHAL_CP_NUM > 0

-    /* Ensure wsr.CPENABLE is complete (should be, it was cleared on entry). */

-    rsync

-    #endif

-    /* As soons as PS is restored, interrupts can happen. No need to sync PS. */

-    wsr     a3,  PS

-    #ifdef __XTENSA_CALL0_ABI__

-    addi    sp,  sp, XT_SOL_FRMSZ

-    ret

-    #else

-    retw

-    #endif

-

-.L_frxt_dispatch_stk:

-

-    #if XCHAL_CP_NUM > 0

-    /* Restore CPENABLE from task's co-processor save area. */

-    movi    a3, pxCurrentTCB            /* cp_state =                       */

-	getcoreid a2

-	addx4	a3,  a2, a3

-    l32i    a3, a3, 0

-    l32i    a2, a3, CP_TOPOFSTACK_OFFS     /* StackType_t                       *pxStack; */

-    l16ui   a3, a2, XT_CPENABLE         /* CPENABLE = cp_state->cpenable;   */

-    wsr     a3, CPENABLE

-    #endif

-

-    /* Interrupt stack frame. Restore full context and return to exit dispatcher. */

-    call0   _xt_context_restore

-

-    /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */

-    #ifdef __XTENSA_CALL0_ABI__

-    l32i    a14, sp, XT_STK_A14

-    l32i    a15, sp, XT_STK_A15

-    #endif

-

-    #if XCHAL_CP_NUM > 0

-    /* Ensure wsr.CPENABLE has completed. */

-    rsync

-    #endif

-

-    /*

-    Must return via the exit dispatcher corresponding to the entrypoint from which

-    this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt

-    stack frame is deallocated in the exit dispatcher.

-    */

-    l32i    a0, sp, XT_STK_EXIT

-    ret

-

-

-/*

-**********************************************************************************************************

-*                            PERFORM A SOLICTED CONTEXT SWITCH (from a task)

-*                                        void vPortYield(void)

-*

-* This function saves the minimal state needed for a solicited task suspension, clears CPENABLE,

-* then tail-calls the dispatcher _frxt_dispatch() to perform the actual context switch

-*

-* At Entry:

-*   pxCurrentTCB  points to the TCB of the task to suspend

-*   Callable from C (obeys ABI conventions on entry).

-*

-* Does not return to caller.

-*

-**********************************************************************************************************

-*/

-    .globl  vPortYield

-    .type   vPortYield,@function

-    .align  4

-vPortYield:

-

-    #ifdef __XTENSA_CALL0_ABI__

-    addi    sp,  sp, -XT_SOL_FRMSZ

-    #else

-    entry   sp,  XT_SOL_FRMSZ

-    #endif

-

-    rsr     a2,  PS

-    s32i    a0,  sp, XT_SOL_PC

-    s32i    a2,  sp, XT_SOL_PS

-    #ifdef __XTENSA_CALL0_ABI__

-    s32i    a12, sp, XT_SOL_A12         /* save callee-saved registers      */

-    s32i    a13, sp, XT_SOL_A13

-    s32i    a14, sp, XT_SOL_A14

-    s32i    a15, sp, XT_SOL_A15

-    #else

-    /* Spill register windows. Calling xthal_window_spill() causes extra    */

-    /* spills and reloads, so we will set things up to call the _nw version */

-    /* instead to save cycles.                                              */

-    movi    a6,  ~(PS_WOE_MASK|PS_INTLEVEL_MASK)  /* spills a4-a7 if needed */

-    and     a2,  a2, a6                           /* clear WOE, INTLEVEL    */

-    addi    a2,  a2, XCHAL_EXCM_LEVEL             /* set INTLEVEL           */

-    wsr     a2,  PS

-    rsync

-    call0   xthal_window_spill_nw

-    l32i    a2,  sp, XT_SOL_PS                    /* restore PS             */

-    wsr     a2,  PS

-    #endif

-

-    rsil    a2,  XCHAL_EXCM_LEVEL       /* disable low/med interrupts       */

-

-    #if XCHAL_CP_NUM > 0

-    /* Save coprocessor callee-saved state (if any). At this point CPENABLE */

-    /* should still reflect which CPs were in use (enabled).                */

-    call0   _xt_coproc_savecs

-    #endif

-

-    movi    a2,  pxCurrentTCB

-	getcoreid a3

-	addx4	a2,  a3, a2

-    l32i    a2,  a2, 0                  /* a2 = pxCurrentTCB                */

-    movi    a3,  0

-    s32i    a3,  sp, XT_SOL_EXIT        /* 0 to flag as solicited frame     */

-    s32i    sp,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP  */

-

-    #if XCHAL_CP_NUM > 0

-    /* Clear CPENABLE, also in task's co-processor state save area. */

-    l32i    a2,  a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state      */

-    movi    a3,  0

-    wsr     a3,  CPENABLE

-    beqz    a2,  1f

-    s16i    a3,  a2, XT_CPENABLE        /* clear saved cpenable             */

-1:

-    #endif

-

-    /* Tail-call dispatcher. */

-    call0   _frxt_dispatch

-    /* Never reaches here. */

-

-

-/*

-**********************************************************************************************************

-*                         PERFORM AN UNSOLICITED CONTEXT SWITCH (from an interrupt)

-*                                        void vPortYieldFromInt(void)

-*

-* This calls the context switch hook (removed), saves and clears CPENABLE, then tail-calls the dispatcher

-* _frxt_dispatch() to perform the actual context switch.

-*

-* At Entry:

-*   Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCB->pxTopOfStack.

-*   pxCurrentTCB  points to the TCB of the task to suspend,

-*   Callable from C (obeys ABI conventions on entry).

-*

-* At Exit:

-*   Windowed ABI defers the actual context switch until the stack is unwound to interrupt entry.

-*   Call0 ABI tail-calls the dispatcher directly (no need to unwind) so does not return to caller.

-*

-**********************************************************************************************************

-*/

-    .globl  vPortYieldFromInt

-    .type   vPortYieldFromInt,@function

-    .align  4

-vPortYieldFromInt:

-

-    ENTRY(16)

-

-    #if XCHAL_CP_NUM > 0

-    /* Save CPENABLE in task's co-processor save area, and clear CPENABLE.  */

-    movi    a3, pxCurrentTCB            /* cp_state =                       */

-	getcoreid a2

-	addx4	a3,  a2, a3

-    l32i    a3, a3, 0

-

-    l32i    a2, a3, CP_TOPOFSTACK_OFFS

-

-    rsr     a3, CPENABLE

-    s16i    a3, a2, XT_CPENABLE         /* cp_state->cpenable = CPENABLE;   */

-    movi    a3, 0

-    wsr     a3, CPENABLE                /* disable all co-processors        */

-    #endif

-

-    #ifdef __XTENSA_CALL0_ABI__

-    /* Tail-call dispatcher. */

-    call0   _frxt_dispatch

-    /* Never reaches here. */

-    #else

-    RET(16)

-    #endif

-

-/*

-**********************************************************************************************************

-*                                        _frxt_task_coproc_state

-*                                   void _frxt_task_coproc_state(void)

-*

-* Implements the Xtensa RTOS porting layer's XT_RTOS_CP_STATE function for FreeRTOS.

-*

-* May only be called when a task is running, not within an interrupt handler (returns 0 in that case).

-* May only be called from assembly code by the 'call0' instruction. Does NOT obey ABI conventions.

-* Returns in A15 a pointer to the base of the co-processor state save area for the current task.

-* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.

-*

-**********************************************************************************************************

-*/

-#if XCHAL_CP_NUM > 0

-

-    .globl  _frxt_task_coproc_state

-    .type   _frxt_task_coproc_state,@function

-    .align  4

-_frxt_task_coproc_state:

-

-

-	/* We can use a3 as a scratchpad, the instances of code calling XT_RTOS_CP_STATE don't seem to need it saved. */

-	getcoreid a3

-    movi    a15, port_xSchedulerRunning /* if (port_xSchedulerRunning              */

-	addx4	a15, a3,a15

-    l32i    a15, a15, 0

-    beqz    a15, 1f

-    movi    a15, port_interruptNesting  /* && port_interruptNesting == 0           */

-	addx4	a15, a3, a15

-    l32i    a15, a15, 0

-    bnez    a15, 1f

-

-    movi    a15, pxCurrentTCB

-	addx4	a15, a3, a15

-    l32i    a15, a15, 0                 /* && pxCurrentTCB != 0) {                 */

-

-    beqz    a15, 2f

-    l32i    a15, a15, CP_TOPOFSTACK_OFFS

-    ret

-

-1:  movi    a15, 0

-2:  ret

-

-#endif /* XCHAL_CP_NUM > 0 */

+/*
+//-----------------------------------------------------------------------------
+// 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.
+//-----------------------------------------------------------------------------
+*/
+
+#include "xtensa_rtos.h"
+#include "sdkconfig.h"
+#include "esp_idf_version.h"
+
+#define TOPOFSTACK_OFFS                 0x00    /* StackType_t *pxTopOfStack */
+#define CP_TOPOFSTACK_OFFS              0x04    /* xMPU_SETTINGS.coproc_area */
+
+.extern pxCurrentTCB
+
+/*
+*******************************************************************************
+* Interrupt stack. The size of the interrupt stack is determined by the config
+* parameter "configISR_STACK_SIZE" in FreeRTOSConfig.h
+*******************************************************************************
+*/
+
+    .data
+    .align      16
+    .global     port_IntStack
+    .global     port_IntStackTop
+    .global     port_switch_flag
+port_IntStack:
+    .space      configISR_STACK_SIZE*portNUM_PROCESSORS		/* This allocates stacks for each individual CPU. */
+port_IntStackTop:
+    .word		0
+port_switch_flag:
+    .space      portNUM_PROCESSORS*4 /* One flag for each individual CPU. */
+
+    .text
+
+/*
+*******************************************************************************
+* _frxt_setup_switch
+* void _frxt_setup_switch(void);
+* 
+* Sets an internal flag indicating that a task switch is required on return
+* from interrupt handling.
+* 
+*******************************************************************************
+*/
+    .global     _frxt_setup_switch
+    .type       _frxt_setup_switch,@function
+    .align      4
+_frxt_setup_switch:
+
+    ENTRY(16)
+
+	getcoreid a3
+    movi    a2, port_switch_flag
+	addx4	a2,  a3, a2
+
+    movi    a3, 1
+    s32i    a3, a2, 0
+
+    RET(16)
+
+
+
+
+
+
+/*
+*******************************************************************************
+* _frxt_int_enter
+* void _frxt_int_enter(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_ENTER function for
+* freeRTOS. Saves the rest of the interrupt context (not already saved).
+* May only be called from assembly code by the 'call0' instruction, with
+* interrupts disabled.
+* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+*******************************************************************************
+*/
+    .globl  _frxt_int_enter
+    .type   _frxt_int_enter,@function
+    .align  4
+_frxt_int_enter:
+
+    /* Save a12-13 in the stack frame as required by _xt_context_save. */
+    s32i    a12, a1, XT_STK_A12
+    s32i    a13, a1, XT_STK_A13
+
+    /* Save return address in a safe place (free a0). */
+    mov     a12, a0
+
+    /* Save the rest of the interrupted context (preserves A12-13). */
+    call0   _xt_context_save
+
+    /*
+    Save interrupted task's SP in TCB only if not nesting.
+    Manage nesting directly rather than call the generic IntEnter()
+    (in windowed ABI we can't call a C function here anyway because PS.EXCM is still set).
+    */
+	getcoreid a4
+    movi    a2,  port_xSchedulerRunning
+	addx4	a2,  a4, a2
+    movi    a3,  port_interruptNesting
+	addx4	a3,  a4, a3
+    l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */
+    beqz    a2,  1f                     /* scheduler not running, no tasks */
+    l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */
+    addi    a2,  a2, 1                  /* increment nesting count         */
+    s32i    a2,  a3, 0                  /* save nesting count              */
+    bnei    a2,  1, .Lnested            /* !=0 before incr, so nested      */
+
+    movi    a2,  pxCurrentTCB
+	addx4	a2,  a4, a2
+    l32i    a2,  a2, 0                  /* a2 = current TCB                */
+    beqz    a2,  1f
+    s32i    a1,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP */
+    movi    a1,  port_IntStack+configISR_STACK_SIZE   /* a1 = top of intr stack for CPU 0  */
+    movi    a2,  configISR_STACK_SIZE   /* add configISR_STACK_SIZE * cpu_num to arrive at top of stack for cpu_num */
+	mull	a2,  a4, a2
+	add     a1,  a1, a2					/* for current proc */
+
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef CONFIG_FREERTOS_FPU_IN_ISR
+    #if XCHAL_CP_NUM > 0
+    rsr     a3, CPENABLE                /* Restore thread scope CPENABLE */
+    addi    sp, sp,-4                   /* ISR will manage FPU coprocessor by forcing */
+    s32i    a3, a1, 0                   /* its trigger */
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+.Lnested:
+1:
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef CONFIG_FREERTOS_FPU_IN_ISR
+    #if XCHAL_CP_NUM > 0
+    movi    a3,  0              /* whilst ISRs pending keep CPENABLE exception active */
+    wsr     a3,  CPENABLE
+    rsync
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    mov     a0,  a12                    /* restore return addr and return  */
+    ret
+
+/*
+*******************************************************************************
+* _frxt_int_exit
+* void _frxt_int_exit(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_INT_EXIT function for
+* FreeRTOS. If required, calls vPortYieldFromInt() to perform task context
+* switching, restore the (possibly) new task's context, and return to the
+* exit dispatcher saved in the task's stack frame at XT_STK_EXIT.
+* May only be called from assembly code by the 'call0' instruction. Does not
+* return to caller.
+* See the description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+*******************************************************************************
+*/
+    .globl  _frxt_int_exit
+    .type   _frxt_int_exit,@function
+    .align  4
+_frxt_int_exit:
+
+	getcoreid a4
+    movi    a2,  port_xSchedulerRunning
+	addx4	a2,  a4, a2
+    movi    a3,  port_interruptNesting
+	addx4	a3,  a4, a3
+    rsil    a0,  XCHAL_EXCM_LEVEL       /* lock out interrupts             */
+    l32i    a2,  a2, 0                  /* a2 = port_xSchedulerRunning     */
+    beqz    a2,  .Lnoswitch             /* scheduler not running, no tasks */
+    l32i    a2,  a3, 0                  /* a2 = port_interruptNesting      */
+    addi    a2,  a2, -1                 /* decrement nesting count         */
+    s32i    a2,  a3, 0                  /* save nesting count              */
+    bnez    a2,  .Lnesting              /* !=0 after decr so still nested  */
+
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef CONFIG_FREERTOS_FPU_IN_ISR 
+    #if XCHAL_CP_NUM > 0
+    l32i    a3,  sp, 0                  /* Grab last CPENABLE before leave ISR */
+    addi    sp,  sp, 4
+    wsr     a3, CPENABLE
+    rsync                               /* ensure CPENABLE was modified */
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    movi    a2,  pxCurrentTCB
+	addx4	a2,  a4, a2
+    l32i    a2,  a2, 0                  /* a2 = current TCB                */
+    beqz    a2,  1f                     /* no task ? go to dispatcher      */
+    l32i    a1,  a2, TOPOFSTACK_OFFS    /* SP = pxCurrentTCB->pxTopOfStack */
+
+    movi    a2,  port_switch_flag       /* address of switch flag          */
+	addx4	a2,  a4, a2					/* point to flag for this cpu      */
+    l32i    a3,  a2, 0                  /* a3 = port_switch_flag           */
+    beqz    a3,  .Lnoswitch             /* flag = 0 means no switch reqd   */
+    movi    a3,  0
+    s32i    a3,  a2, 0                  /* zero out the flag for next time */
+
+1:
+    /*
+    Call0 ABI callee-saved regs a12-15 need to be saved before possible preemption.
+    However a12-13 were already saved by _frxt_int_enter().
+    */
+    #ifdef __XTENSA_CALL0_ABI__
+    s32i    a14, a1, XT_STK_A14
+    s32i    a15, a1, XT_STK_A15
+    #endif
+
+    #ifdef __XTENSA_CALL0_ABI__
+    call0   vPortYieldFromInt       /* call dispatch inside the function; never returns */
+    #else
+    call4   vPortYieldFromInt       /* this one returns */
+    call0   _frxt_dispatch          /* tail-call dispatcher */
+    /* Never returns here. */
+    #endif
+
+.Lnoswitch:
+    /*
+    If we came here then about to resume the interrupted task.
+    */
+
+.Lnesting:
+    /*
+    We come here only if there was no context switch, that is if this
+    is a nested interrupt, or the interrupted task was not preempted.
+    In either case there's no need to load the SP.
+    */
+
+    /* Restore full context from interrupt stack frame */
+    call0   _xt_context_restore
+
+    /*
+    Must return via the exit dispatcher corresponding to the entrypoint from which
+    this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt
+    stack frame is deallocated in the exit dispatcher.
+    */
+    l32i    a0,  a1, XT_STK_EXIT
+    ret
+
+
+/*
+**********************************************************************************************************
+*                                           _frxt_timer_int
+*                                      void _frxt_timer_int(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_TIMER_INT function for FreeRTOS.
+* Called every timer interrupt.
+* Manages the tick timer and calls xPortSysTickHandler() every tick.
+* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+* Callable from C (obeys ABI conventions). Implemented in assmebly code for performance.
+*
+**********************************************************************************************************
+*/
+    .globl  _frxt_timer_int
+    .type   _frxt_timer_int,@function
+    .align  4
+_frxt_timer_int:
+
+    /*
+    Xtensa timers work by comparing a cycle counter with a preset value.  Once the match occurs
+    an interrupt is generated, and the handler has to set a new cycle count into the comparator.
+    To avoid clock drift due to interrupt latency, the new cycle count is computed from the old,
+    not the time the interrupt was serviced. However if a timer interrupt is ever serviced more
+    than one tick late, it is necessary to process multiple ticks until the new cycle count is
+    in the future, otherwise the next timer interrupt would not occur until after the cycle
+    counter had wrapped (2^32 cycles later).
+
+    do {
+        ticks++;
+        old_ccompare = read_ccompare_i();
+        write_ccompare_i( old_ccompare + divisor );
+        service one tick;
+        diff = read_ccount() - old_ccompare;
+    } while ( diff > divisor );
+    */
+
+    ENTRY(16)
+
+    #ifdef CONFIG_PM_TRACE
+    movi a6, 1 /* = ESP_PM_TRACE_TICK */
+    getcoreid a7
+    call4 esp_pm_trace_enter
+    #endif // CONFIG_PM_TRACE
+
+.L_xt_timer_int_catchup:
+
+    /* Update the timer comparator for the next tick. */
+    #ifdef XT_CLOCK_FREQ
+    movi    a2, XT_TICK_DIVISOR         /* a2 = comparator increment          */
+    #else
+    movi    a3, _xt_tick_divisor
+    l32i    a2, a3, 0                   /* a2 = comparator increment          */
+    #endif
+    rsr     a3, XT_CCOMPARE             /* a3 = old comparator value          */
+    add     a4, a3, a2                  /* a4 = new comparator value          */
+    wsr     a4, XT_CCOMPARE             /* update comp. and clear interrupt   */
+    esync
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /* Preserve a2 and a3 across C calls. */
+    s32i    a2, sp, 4
+    s32i    a3, sp, 8
+    #endif
+
+    /* Call the FreeRTOS tick handler (see port.c). */
+    #ifdef __XTENSA_CALL0_ABI__
+    call0   xPortSysTickHandler
+    #else
+    call4   xPortSysTickHandler
+    #endif
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /* Restore a2 and a3. */
+    l32i    a2, sp, 4
+    l32i    a3, sp, 8
+    #endif
+
+    /* Check if we need to process more ticks to catch up. */
+    esync                               /* ensure comparator update complete  */
+    rsr     a4, CCOUNT                  /* a4 = cycle count                   */
+    sub     a4, a4, a3                  /* diff = ccount - old comparator     */
+    blt     a2, a4, .L_xt_timer_int_catchup  /* repeat while diff > divisor */
+
+#ifdef CONFIG_PM_TRACE
+    movi a6, 1 /* = ESP_PM_TRACE_TICK */
+    getcoreid a7
+    call4 esp_pm_trace_exit
+#endif // CONFIG_PM_TRACE
+
+    RET(16)
+
+    /*
+**********************************************************************************************************
+*                                           _frxt_tick_timer_init
+*                                      void _frxt_tick_timer_init(void)
+*
+* Initialize timer and timer interrrupt handler (_xt_tick_divisor_init() has already been been called).
+* Callable from C (obeys ABI conventions on entry).
+*
+**********************************************************************************************************
+*/
+    .globl  _frxt_tick_timer_init
+    .type   _frxt_tick_timer_init,@function
+    .align  4
+_frxt_tick_timer_init:
+
+    ENTRY(16)
+
+
+    /* Set up the periodic tick timer (assume enough time to complete init). */
+    #ifdef XT_CLOCK_FREQ
+    movi    a3, XT_TICK_DIVISOR
+    #else
+    movi    a2, _xt_tick_divisor
+    l32i    a3, a2, 0
+    #endif
+    rsr     a2, CCOUNT              /* current cycle count */
+    add     a2, a2, a3              /* time of first timer interrupt */
+    wsr     a2, XT_CCOMPARE         /* set the comparator */
+
+    /*
+    Enable the timer interrupt at the device level. Don't write directly
+    to the INTENABLE register because it may be virtualized.
+    */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a2, XT_TIMER_INTEN
+    call0   xt_ints_on
+    #else
+    movi    a6, XT_TIMER_INTEN
+    call4   xt_ints_on
+    #endif
+
+    RET(16)
+
+/*
+**********************************************************************************************************
+*                                    DISPATCH THE HIGH READY TASK
+*                                     void _frxt_dispatch(void)
+*
+* Switch context to the highest priority ready task, restore its state and dispatch control to it.
+*
+* This is a common dispatcher that acts as a shared exit path for all the context switch functions
+* including vPortYield() and vPortYieldFromInt(), all of which tail-call this dispatcher
+* (for windowed ABI vPortYieldFromInt() calls it indirectly via _frxt_int_exit() ).
+*
+* The Xtensa port uses different stack frames for solicited and unsolicited task suspension (see
+* comments on stack frames in xtensa_context.h). This function restores the state accordingly.
+* If restoring a task that solicited entry, restores the minimal state and leaves CPENABLE clear.
+* If restoring a task that was preempted, restores all state including the task's CPENABLE.
+*
+* Entry:
+*   pxCurrentTCB  points to the TCB of the task to suspend,
+*   Because it is tail-called without a true function entrypoint, it needs no 'entry' instruction.
+*
+* Exit:
+*   If incoming task called vPortYield() (solicited), this function returns as if from vPortYield().
+*   If incoming task was preempted by an interrupt, this function jumps to exit dispatcher.
+*
+**********************************************************************************************************
+*/
+    .globl  _frxt_dispatch
+    .type   _frxt_dispatch,@function
+    .align  4
+_frxt_dispatch:
+
+    #ifdef __XTENSA_CALL0_ABI__
+    call0   vTaskSwitchContext  // Get next TCB to resume
+    movi    a2, pxCurrentTCB
+	getcoreid a3
+	addx4	a2,  a3, a2
+    #else
+    call4   vTaskSwitchContext  // Get next TCB to resume
+    movi    a2, pxCurrentTCB
+	getcoreid a3
+	addx4	a2,  a3, a2
+    #endif
+    l32i    a3,  a2, 0
+    l32i    sp,  a3, TOPOFSTACK_OFFS     /* SP = next_TCB->pxTopOfStack;  */
+    s32i    a3,  a2, 0
+
+    /* Determine the type of stack frame. */
+    l32i    a2,  sp, XT_STK_EXIT        /* exit dispatcher or solicited flag */
+    bnez    a2,  .L_frxt_dispatch_stk
+
+.L_frxt_dispatch_sol:
+
+    /* Solicited stack frame. Restore minimal context and return from vPortYield(). */
+    l32i    a3,  sp, XT_SOL_PS
+    #ifdef __XTENSA_CALL0_ABI__
+    l32i    a12, sp, XT_SOL_A12
+    l32i    a13, sp, XT_SOL_A13
+    l32i    a14, sp, XT_SOL_A14
+    l32i    a15, sp, XT_SOL_A15
+    #endif
+    l32i    a0,  sp, XT_SOL_PC
+    #if XCHAL_CP_NUM > 0
+    /* Ensure wsr.CPENABLE is complete (should be, it was cleared on entry). */
+    rsync
+    #endif
+    /* As soons as PS is restored, interrupts can happen. No need to sync PS. */
+    wsr     a3,  PS
+    #ifdef __XTENSA_CALL0_ABI__
+    addi    sp,  sp, XT_SOL_FRMSZ
+    ret
+    #else
+    retw
+    #endif
+
+.L_frxt_dispatch_stk:
+
+    #if XCHAL_CP_NUM > 0
+    /* Restore CPENABLE from task's co-processor save area. */
+    movi    a3, pxCurrentTCB            /* cp_state =                       */
+	getcoreid a2
+	addx4	a3,  a2, a3
+    l32i    a3, a3, 0
+    l32i    a2, a3, CP_TOPOFSTACK_OFFS     /* StackType_t                       *pxStack; */
+    l16ui   a3, a2, XT_CPENABLE         /* CPENABLE = cp_state->cpenable;   */
+    wsr     a3, CPENABLE
+    #endif
+
+    /* Interrupt stack frame. Restore full context and return to exit dispatcher. */
+    call0   _xt_context_restore
+
+    /* In Call0 ABI, restore callee-saved regs (A12, A13 already restored). */
+    #ifdef __XTENSA_CALL0_ABI__
+    l32i    a14, sp, XT_STK_A14
+    l32i    a15, sp, XT_STK_A15
+    #endif
+
+    #if XCHAL_CP_NUM > 0
+    /* Ensure wsr.CPENABLE has completed. */
+    rsync
+    #endif
+
+    /*
+    Must return via the exit dispatcher corresponding to the entrypoint from which
+    this was called. Interruptee's A0, A1, PS, PC are restored and the interrupt
+    stack frame is deallocated in the exit dispatcher.
+    */
+    l32i    a0, sp, XT_STK_EXIT
+    ret
+
+
+/*
+**********************************************************************************************************
+*                            PERFORM A SOLICTED CONTEXT SWITCH (from a task)
+*                                        void vPortYield(void)
+*
+* This function saves the minimal state needed for a solicited task suspension, clears CPENABLE,
+* then tail-calls the dispatcher _frxt_dispatch() to perform the actual context switch
+*
+* At Entry:
+*   pxCurrentTCB  points to the TCB of the task to suspend
+*   Callable from C (obeys ABI conventions on entry).
+*
+* Does not return to caller.
+*
+**********************************************************************************************************
+*/
+    .globl  vPortYield
+    .type   vPortYield,@function
+    .align  4
+vPortYield:
+
+    #ifdef __XTENSA_CALL0_ABI__
+    addi    sp,  sp, -XT_SOL_FRMSZ
+    #else
+    entry   sp,  XT_SOL_FRMSZ
+    #endif
+
+    rsr     a2,  PS
+    s32i    a0,  sp, XT_SOL_PC
+    s32i    a2,  sp, XT_SOL_PS
+    #ifdef __XTENSA_CALL0_ABI__
+    s32i    a12, sp, XT_SOL_A12         /* save callee-saved registers      */
+    s32i    a13, sp, XT_SOL_A13
+    s32i    a14, sp, XT_SOL_A14
+    s32i    a15, sp, XT_SOL_A15
+    #else
+    /* Spill register windows. Calling xthal_window_spill() causes extra    */
+    /* spills and reloads, so we will set things up to call the _nw version */
+    /* instead to save cycles.                                              */
+    movi    a6,  ~(PS_WOE_MASK|PS_INTLEVEL_MASK)  /* spills a4-a7 if needed */
+    and     a2,  a2, a6                           /* clear WOE, INTLEVEL    */
+    addi    a2,  a2, XCHAL_EXCM_LEVEL             /* set INTLEVEL           */
+    wsr     a2,  PS
+    rsync
+    call0   xthal_window_spill_nw
+    l32i    a2,  sp, XT_SOL_PS                    /* restore PS             */
+    wsr     a2,  PS
+    #endif
+
+    rsil    a2,  XCHAL_EXCM_LEVEL       /* disable low/med interrupts       */
+
+    #if XCHAL_CP_NUM > 0
+    /* Save coprocessor callee-saved state (if any). At this point CPENABLE */
+    /* should still reflect which CPs were in use (enabled).                */
+    call0   _xt_coproc_savecs
+    #endif
+
+    movi    a2,  pxCurrentTCB
+	getcoreid a3
+	addx4	a2,  a3, a2
+    l32i    a2,  a2, 0                  /* a2 = pxCurrentTCB                */
+    movi    a3,  0
+    s32i    a3,  sp, XT_SOL_EXIT        /* 0 to flag as solicited frame     */
+    s32i    sp,  a2, TOPOFSTACK_OFFS    /* pxCurrentTCB->pxTopOfStack = SP  */
+
+    #if XCHAL_CP_NUM > 0
+    /* Clear CPENABLE, also in task's co-processor state save area. */
+    l32i    a2,  a2, CP_TOPOFSTACK_OFFS /* a2 = pxCurrentTCB->cp_state      */
+    movi    a3,  0
+    wsr     a3,  CPENABLE
+    beqz    a2,  1f
+    s16i    a3,  a2, XT_CPENABLE        /* clear saved cpenable             */
+1:
+    #endif
+
+    /* Tail-call dispatcher. */
+    call0   _frxt_dispatch
+    /* Never reaches here. */
+
+
+/*
+**********************************************************************************************************
+*                         PERFORM AN UNSOLICITED CONTEXT SWITCH (from an interrupt)
+*                                        void vPortYieldFromInt(void)
+*
+* This calls the context switch hook (removed), saves and clears CPENABLE, then tail-calls the dispatcher
+* _frxt_dispatch() to perform the actual context switch.
+*
+* At Entry:
+*   Interrupted task context has been saved in an interrupt stack frame at pxCurrentTCB->pxTopOfStack.
+*   pxCurrentTCB  points to the TCB of the task to suspend,
+*   Callable from C (obeys ABI conventions on entry).
+*
+* At Exit:
+*   Windowed ABI defers the actual context switch until the stack is unwound to interrupt entry.
+*   Call0 ABI tail-calls the dispatcher directly (no need to unwind) so does not return to caller.
+*
+**********************************************************************************************************
+*/
+    .globl  vPortYieldFromInt
+    .type   vPortYieldFromInt,@function
+    .align  4
+vPortYieldFromInt:
+
+    ENTRY(16)
+
+    #if XCHAL_CP_NUM > 0
+    /* Save CPENABLE in task's co-processor save area, and clear CPENABLE.  */
+    movi    a3, pxCurrentTCB            /* cp_state =                       */
+	getcoreid a2
+	addx4	a3,  a2, a3
+    l32i    a3, a3, 0
+
+    l32i    a2, a3, CP_TOPOFSTACK_OFFS
+
+    rsr     a3, CPENABLE
+    s16i    a3, a2, XT_CPENABLE         /* cp_state->cpenable = CPENABLE;   */
+    movi    a3, 0
+    wsr     a3, CPENABLE                /* disable all co-processors        */
+    #endif
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /* Tail-call dispatcher. */
+    call0   _frxt_dispatch
+    /* Never reaches here. */
+    #else
+    RET(16)
+    #endif
+
+/*
+**********************************************************************************************************
+*                                        _frxt_task_coproc_state
+*                                   void _frxt_task_coproc_state(void)
+*
+* Implements the Xtensa RTOS porting layer's XT_RTOS_CP_STATE function for FreeRTOS.
+*
+* May only be called when a task is running, not within an interrupt handler (returns 0 in that case).
+* May only be called from assembly code by the 'call0' instruction. Does NOT obey ABI conventions.
+* Returns in A15 a pointer to the base of the co-processor state save area for the current task.
+* See the detailed description of the XT_RTOS_ENTER macro in xtensa_rtos.h.
+*
+**********************************************************************************************************
+*/
+#if XCHAL_CP_NUM > 0
+
+    .globl  _frxt_task_coproc_state
+    .type   _frxt_task_coproc_state,@function
+    .align  4
+_frxt_task_coproc_state:
+
+
+	/* We can use a3 as a scratchpad, the instances of code calling XT_RTOS_CP_STATE don't seem to need it saved. */
+	getcoreid a3
+    movi    a15, port_xSchedulerRunning /* if (port_xSchedulerRunning              */
+	addx4	a15, a3,a15
+    l32i    a15, a15, 0
+    beqz    a15, 1f
+    movi    a15, port_interruptNesting  /* && port_interruptNesting == 0           */
+	addx4	a15, a3, a15
+    l32i    a15, a15, 0
+    bnez    a15, 1f
+
+    movi    a15, pxCurrentTCB
+	addx4	a15, a3, a15
+    l32i    a15, a15, 0                 /* && pxCurrentTCB != 0) {                 */
+
+    beqz    a15, 2f
+    l32i    a15, a15, CP_TOPOFSTACK_OFFS
+    ret
+
+1:  movi    a15, 0
+2:  ret
+
+#endif /* XCHAL_CP_NUM > 0 */
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h b/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
index 791d05e..9d3b38b 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.h
@@ -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 ) );
+}
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.inc.h b/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.inc.h
index b19ce83..e2c637b 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.inc.h
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/portmux_impl.inc.h
@@ -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
+        }
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_context.S b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_context.S
index 9020a76..2a64ec6 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_context.S
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_context.S
@@ -1,703 +1,703 @@
-/*******************************************************************************

-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 SAVE AND RESTORE ROUTINES

-

-Low-level Call0 functions for handling generic context save and restore of

-registers not specifically addressed by the interrupt vectors and handlers.

-Those registers (not handled by these functions) are PC, PS, A0, A1 (SP).

-Except for the calls to RTOS functions, this code is generic to Xtensa.

-

-Note that in Call0 ABI, interrupt handlers are expected to preserve the callee-

-save regs (A12-A15), which is always the case if the handlers are coded in C.

-However A12, A13 are made available as scratch registers for interrupt dispatch

-code, so are presumed saved anyway, and are always restored even in Call0 ABI.

-Only A14, A15 are truly handled as callee-save regs.

-

-Because Xtensa is a configurable architecture, this port supports all user

-generated configurations (except restrictions stated in the release notes).

-This is accomplished by conditional compilation using macros and functions

-defined in the Xtensa HAL (hardware adaptation layer) for your configuration.

-Only the processor state included in your configuration is saved and restored,

-including any processor state added by user configuration options or TIE.

-

-*******************************************************************************/

-

-/*  Warn nicely if this file gets named with a lowercase .s instead of .S:  */

-#define NOERROR #

-NOERROR: .error "C preprocessor needed for this file: make sure its filename\

- ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option."

-

-

-#include "xtensa_rtos.h"

-#include "xtensa_context.h"

-#include "esp_idf_version.h"

-#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-#include "xt_asm_utils.h"

-#endif

-

-#ifdef XT_USE_OVLY

-#include <xtensa/overlay_os_asm.h>

-#endif

-

-    .text

-

-/*******************************************************************************

-

-_xt_context_save

-

-    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!

-

-Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the

-interrupt stack frame defined in xtensa_rtos.h.

-Its counterpart is _xt_context_restore (which also restores A12, A13).

-

-Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame.

-This function preserves A12 & A13 in order to provide the caller with 2 scratch 

-regs that need not be saved over the call to this function. The choice of which

-2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw,

-to avoid moving data more than necessary. Caller can assign regs accordingly.

-

-Entry Conditions:

-    A0  = Return address in caller.

-    A1  = Stack pointer of interrupted thread or handler ("interruptee").

-    Original A12, A13 have already been saved in the interrupt stack frame.

-    Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the 

-    point of interruption.

-    If windowed ABI, PS.EXCM = 1 (exceptions disabled).

-

-Exit conditions:

-    A0  = Return address in caller.

-    A1  = Stack pointer of interrupted thread or handler ("interruptee").

-    A12, A13 as at entry (preserved).

-    If windowed ABI, PS.EXCM = 1 (exceptions disabled).

-

-*******************************************************************************/

-

-    .global _xt_context_save

-    .type   _xt_context_save,@function

-    .align  4

-	.literal_position

-    .align  4

-

-_xt_context_save:

-

-    s32i    a2,  sp, XT_STK_A2

-    s32i    a3,  sp, XT_STK_A3

-    s32i    a4,  sp, XT_STK_A4

-    s32i    a5,  sp, XT_STK_A5

-    s32i    a6,  sp, XT_STK_A6

-    s32i    a7,  sp, XT_STK_A7

-    s32i    a8,  sp, XT_STK_A8

-    s32i    a9,  sp, XT_STK_A9

-    s32i    a10, sp, XT_STK_A10

-    s32i    a11, sp, XT_STK_A11

-

-    /*

-    Call0 ABI callee-saved regs a12-15 do not need to be saved here.

-    a12-13 are the caller's responsibility so it can use them as scratch.

-    So only need to save a14-a15 here for Windowed ABI (not Call0).

-    */

-    #ifndef __XTENSA_CALL0_ABI__

-    s32i    a14, sp, XT_STK_A14

-    s32i    a15, sp, XT_STK_A15

-    #endif

-

-    rsr     a3,  SAR

-    s32i    a3,  sp, XT_STK_SAR

-

-    #if XCHAL_HAVE_LOOPS

-    rsr     a3,  LBEG

-    s32i    a3,  sp, XT_STK_LBEG

-    rsr     a3,  LEND

-    s32i    a3,  sp, XT_STK_LEND

-    rsr     a3,  LCOUNT

-    s32i    a3,  sp, XT_STK_LCOUNT

-    #endif

-

-    #ifdef XT_USE_SWPRI

-    /* Save virtual priority mask */

-    movi    a3,  _xt_vpri_mask

-    l32i    a3,  a3, 0

-    s32i    a3,  sp, XT_STK_VPRI

-    #endif

-

-    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)

-    mov     a9,  a0                     /* preserve ret addr */

-    #endif

-

-    #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifndef __XTENSA_CALL0_ABI__

-    /*

-    To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15.

-    Need to save a9,12,13 temporarily (in frame temps) and recover originals.

-    Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow

-    and underflow exceptions disabled (assured by PS.EXCM == 1).

-    */

-    s32i    a12, sp, XT_STK_TMP0        /* temp. save stuff in stack frame */

-    s32i    a13, sp, XT_STK_TMP1    

-    s32i    a9,  sp, XT_STK_TMP2    

-

-    /*

-    Save the overlay state if we are supporting overlays. Since we just saved

-    three registers, we can conveniently use them here. Note that as of now,

-    overlays only work for windowed calling ABI.

-    */

-    #ifdef XT_USE_OVLY

-    l32i    a9,  sp, XT_STK_PC          /* recover saved PC */

-    _xt_overlay_get_state    a9, a12, a13

-    s32i    a9,  sp, XT_STK_OVLY        /* save overlay state */

-    #endif

-

-    l32i    a12, sp, XT_STK_A12         /* recover original a9,12,13 */

-    l32i    a13, sp, XT_STK_A13

-    l32i    a9,  sp, XT_STK_A9

-    addi    sp,  sp, XT_STK_FRMSZ       /* restore the interruptee's SP */

-    call0   xthal_window_spill_nw       /* preserves only a4,5,8,9,12,13 */

-    addi    sp,  sp, -XT_STK_FRMSZ

-    l32i    a12, sp, XT_STK_TMP0        /* recover stuff from stack frame */

-    l32i    a13, sp, XT_STK_TMP1    

-    l32i    a9,  sp, XT_STK_TMP2    

-    #endif

-    #endif /* (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0)) */

-

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    s32i    a12, sp, XT_STK_TMP0        /* temp. save stuff in stack frame */

-    s32i    a13, sp, XT_STK_TMP1

-    s32i    a9,  sp, XT_STK_TMP2

-

-    l32i    a12, sp, XT_STK_A12         /* recover original a9,12,13 */

-    l32i    a13, sp, XT_STK_A13

-    l32i    a9,  sp, XT_STK_A9

-    #endif

-

-    #if XCHAL_EXTRA_SA_SIZE > 0

-    addi    a2,  sp, XT_STK_EXTRA       /* where to save it */

-    # if XCHAL_EXTRA_SA_ALIGN > 16

-    movi    a3, -XCHAL_EXTRA_SA_ALIGN

-    and     a2, a2, a3                  /* align dynamically >16 bytes */

-    # endif

-    call0   xthal_save_extra_nw         /* destroys a0,2,3 */

-    #endif

-

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifndef __XTENSA_CALL0_ABI__

-    #ifdef XT_USE_OVLY

-    l32i    a9,  sp, XT_STK_PC          /* recover saved PC */

-    _xt_overlay_get_state    a9, a12, a13

-    s32i    a9,  sp, XT_STK_OVLY        /* save overlay state */

-    #endif

-

-    /* SPILL_ALL_WINDOWS macro requires window overflow exceptions to be enabled,

-     * i.e. PS.EXCM cleared and PS.WOE set.

-     * Since we are going to clear PS.EXCM, we also need to increase INTLEVEL

-     * at least to XCHAL_EXCM_LEVEL. This matches that value of effective INTLEVEL

-     * at entry (CINTLEVEL=max(PS.INTLEVEL, XCHAL_EXCM_LEVEL) when PS.EXCM is set.

-     * Since WindowOverflow exceptions will trigger inside SPILL_ALL_WINDOWS,

-     * need to save/restore EPC1 as well.

-     * Note: even though a4-a15 are saved into the exception frame, we should not

-     * clobber them until after SPILL_ALL_WINDOWS. This is because these registers

-     * may contain live windows belonging to previous frames in the call stack.

-     * These frames will be spilled by SPILL_ALL_WINDOWS, and if the register was

-     * used as a temporary by this code, the temporary value would get stored

-     * onto the stack, instead of the real value.

-     */

-    rsr     a2, PS                     /* to be restored after SPILL_ALL_WINDOWS */

-    movi    a0, PS_INTLEVEL_MASK

-    and     a3, a2, a0                 /* get the current INTLEVEL */

-    bgeui   a3, XCHAL_EXCM_LEVEL, 1f   /* calculate max(INTLEVEL, XCHAL_EXCM_LEVEL) */

-    movi    a3, XCHAL_EXCM_LEVEL

-1:

-    movi    a0, PS_UM | PS_WOE         /* clear EXCM, enable window overflow, set new INTLEVEL */

-    or      a3, a3, a0

-    wsr     a3, ps

-    rsr     a0, EPC1                   /* to be restored after SPILL_ALL_WINDOWS */

-

-    addi    sp,  sp, XT_STK_FRMSZ      /* restore the interruptee's SP */

-    SPILL_ALL_WINDOWS

-    addi    sp,  sp, -XT_STK_FRMSZ     /* return the current stack pointer and proceed with context save*/

-

-

-    wsr     a2, PS                     /* restore to the value at entry */

-    rsync

-    wsr     a0, EPC1                   /* likewise */

-

-    #endif /* __XTENSA_CALL0_ABI__ */

-

-    l32i    a12, sp, XT_STK_TMP0        /* restore the temp saved registers */

-    l32i    a13, sp, XT_STK_TMP1        /* our return address is there */

-    l32i    a9,  sp, XT_STK_TMP2

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)

-    mov     a0, a9                      /* retrieve ret addr */

-    #endif

-

-    ret

-

-/*******************************************************************************

-

-_xt_context_restore

-

-    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!

-

-Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0

-ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt 

-stack frame defined in xtensa_rtos.h .

-Its counterpart is _xt_context_save (whose caller saved A12, A13).

-

-Caller is responsible to restore PC, PS, A0, A1 (SP).

-

-Entry Conditions:

-    A0  = Return address in caller.

-    A1  = Stack pointer of interrupted thread or handler ("interruptee").

-

-Exit conditions:

-    A0  = Return address in caller.

-    A1  = Stack pointer of interrupted thread or handler ("interruptee").

-    Other processor state except PC, PS, A0, A1 (SP), is as at the point 

-    of interruption.

-

-*******************************************************************************/

-

-    .global _xt_context_restore

-    .type   _xt_context_restore,@function

-    .align  4

-	.literal_position

-    .align  4

-_xt_context_restore:

-

-    #if XCHAL_EXTRA_SA_SIZE > 0

-    /*  

-    NOTE: Normally the xthal_restore_extra_nw macro only affects address

-    registers a2-a5. It is theoretically possible for Xtensa processor

-    designers to write TIE that causes more address registers to be

-    affected, but it is generally unlikely. If that ever happens,

-    more registers need to be saved/restored around this macro invocation.

-    Here we only assume a13 is preserved.

-    Future Xtensa tools releases might limit the regs that can be affected.

-    */

-    mov     a13, a0                     /* preserve ret addr */

-    addi    a2,  sp, XT_STK_EXTRA       /* where to find it */

-    # if XCHAL_EXTRA_SA_ALIGN > 16

-    movi    a3, -XCHAL_EXTRA_SA_ALIGN

-    and     a2, a2, a3                  /* align dynamically >16 bytes */

-    # endif

-    call0   xthal_restore_extra_nw      /* destroys a0,2,3,4,5 */

-    mov     a0,  a13                    /* retrieve ret addr */

-    #endif

-

-    #if XCHAL_HAVE_LOOPS

-    l32i    a2,  sp, XT_STK_LBEG

-    l32i    a3,  sp, XT_STK_LEND

-    wsr     a2,  LBEG

-    l32i    a2,  sp, XT_STK_LCOUNT

-    wsr     a3,  LEND

-    wsr     a2,  LCOUNT

-    #endif

-

-    #ifdef XT_USE_OVLY

-    /*

-    If we are using overlays, this is a good spot to check if we need

-    to restore an overlay for the incoming task. Here we have a bunch

-    of registers to spare. Note that this step is going to use a few

-    bytes of storage below SP (SP-20 to SP-32) if an overlay is going

-    to be restored.

-    */

-    l32i    a2,  sp, XT_STK_PC          /* retrieve PC */

-    l32i    a3,  sp, XT_STK_PS          /* retrieve PS */

-    l32i    a4,  sp, XT_STK_OVLY        /* retrieve overlay state */

-    l32i    a5,  sp, XT_STK_A1          /* retrieve stack ptr */

-    _xt_overlay_check_map    a2, a3, a4, a5, a6

-    s32i    a2,  sp, XT_STK_PC          /* save updated PC */

-    s32i    a3,  sp, XT_STK_PS          /* save updated PS */

-    #endif

-

-    #ifdef XT_USE_SWPRI

-    /* Restore virtual interrupt priority and interrupt enable */

-    movi    a3,  _xt_intdata

-    l32i    a4,  a3, 0                  /* a4 = _xt_intenable */

-    l32i    a5,  sp, XT_STK_VPRI        /* a5 = saved _xt_vpri_mask */

-    and     a4,  a4, a5

-    wsr     a4,  INTENABLE              /* update INTENABLE */

-    s32i    a5,  a3, 4                  /* restore _xt_vpri_mask */

-    #endif

-

-    l32i    a3,  sp, XT_STK_SAR

-    l32i    a2,  sp, XT_STK_A2

-    wsr     a3,  SAR

-    l32i    a3,  sp, XT_STK_A3

-    l32i    a4,  sp, XT_STK_A4

-    l32i    a5,  sp, XT_STK_A5

-    l32i    a6,  sp, XT_STK_A6

-    l32i    a7,  sp, XT_STK_A7

-    l32i    a8,  sp, XT_STK_A8

-    l32i    a9,  sp, XT_STK_A9

-    l32i    a10, sp, XT_STK_A10

-    l32i    a11, sp, XT_STK_A11

-

-    /*

-    Call0 ABI callee-saved regs a12-15 do not need to be restored here.

-    However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), 

-    so need to be restored anyway, despite being callee-saved in Call0.

-    */

-    l32i    a12, sp, XT_STK_A12

-    l32i    a13, sp, XT_STK_A13

-    #ifndef __XTENSA_CALL0_ABI__

-    l32i    a14, sp, XT_STK_A14

-    l32i    a15, sp, XT_STK_A15

-    #endif

-

-    ret

-

-

-/*******************************************************************************

-

-_xt_coproc_init

-

-Initializes global co-processor management data, setting all co-processors

-to "unowned". Leaves CPENABLE as it found it (does NOT clear it).

-

-Called during initialization of the RTOS, before any threads run.

-

-This may be called from normal Xtensa single-threaded application code which

-might use co-processors. The Xtensa run-time initialization enables all 

-co-processors. They must remain enabled here, else a co-processor exception

-might occur outside of a thread, which the exception handler doesn't expect.

-

-Entry Conditions:

-    Xtensa single-threaded run-time environment is in effect.

-    No thread is yet running.

-

-Exit conditions:

-    None.

-

-Obeys ABI conventions per prototype:

-    void _xt_coproc_init(void)

-

-*******************************************************************************/

-

-#if XCHAL_CP_NUM > 0

-

-    .global _xt_coproc_init

-    .type   _xt_coproc_init,@function

-    .align  4

-	.literal_position

-    .align  4

-_xt_coproc_init:

-    ENTRY0

-

-    /* Initialize thread co-processor ownerships to 0 (unowned). */

-    movi    a2, _xt_coproc_owner_sa         /* a2 = base of owner array */

-    addi    a3, a2, (XCHAL_CP_MAX*portNUM_PROCESSORS) << 2       /* a3 = top+1 of owner array */

-    movi    a4, 0                           /* a4 = 0 (unowned) */

-1:  s32i    a4, a2, 0

-    addi    a2, a2, 4

-    bltu    a2, a3, 1b

-

-    RET0

-

-#endif

-

-

-/*******************************************************************************

-

-_xt_coproc_release

-

-Releases any and all co-processors owned by a given thread. The thread is 

-identified by it's co-processor state save area defined in xtensa_context.h .

-

-Must be called before a thread's co-proc save area is deleted to avoid

-memory corruption when the exception handler tries to save the state.

-May be called when a thread terminates or completes but does not delete

-the co-proc save area, to avoid the exception handler having to save the 

-thread's co-proc state before another thread can use it (optimization).

-

-Needs to be called on the processor the thread was running on. Unpinned threads

-won't have an entry here because they get pinned as soon they use a coprocessor.

-

-Entry Conditions:

-    A2  = Pointer to base of co-processor state save area.

-

-Exit conditions:

-    None.

-

-Obeys ABI conventions per prototype:

-    void _xt_coproc_release(void * coproc_sa_base)

-

-*******************************************************************************/

-

-#if XCHAL_CP_NUM > 0

-

-    .global _xt_coproc_release

-    .type   _xt_coproc_release,@function

-    .align  4

-	.literal_position

-    .align  4

-_xt_coproc_release:

-    ENTRY0                                  /* a2 = base of save area */

-

-	getcoreid a5

-	movi    a3, XCHAL_CP_MAX << 2

-	mull    a5, a5, a3

-    movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */

-	add     a3, a3, a5

-

-    addi    a4, a3, XCHAL_CP_MAX << 2       /* a4 = top+1 of owner array */

-    movi    a5, 0                           /* a5 = 0 (unowned) */

-

-    rsil    a6, XCHAL_EXCM_LEVEL            /* lock interrupts */

-

-1:  l32i    a7, a3, 0                       /* a7 = owner at a3 */

-    bne     a2, a7, 2f                      /* if (coproc_sa_base == owner) */

-    s32i    a5, a3, 0                       /*   owner = unowned */

-2:  addi    a3, a3, 1<<2                    /* a3 = next entry in owner array */

-    bltu    a3, a4, 1b                      /* repeat until end of array */

-

-3:  wsr     a6, PS                          /* restore interrupts */

-

-    RET0

-

-#endif

-

-

-/*******************************************************************************

-_xt_coproc_savecs

-

-If there is a current thread and it has a coprocessor state save area, then

-save all callee-saved state into this area. This function is called from the

-solicited context switch handler. It calls a system-specific function to get

-the coprocessor save area base address.

-

-Entry conditions:

-    - The thread being switched out is still the current thread.

-    - CPENABLE state reflects which coprocessors are active.

-    - Registers have been saved/spilled already.

-

-Exit conditions:

-    - All necessary CP callee-saved state has been saved.

-    - Registers a2-a7, a13-a15 have been trashed.

-

-Must be called from assembly code only, using CALL0.

-*******************************************************************************/

-#if XCHAL_CP_NUM > 0

-

-    .extern     _xt_coproc_sa_offset   /* external reference */

-

-    .global     _xt_coproc_savecs

-    .type       _xt_coproc_savecs,@function

-    .align  4

-	.literal_position

-    .align      4

-_xt_coproc_savecs:

-

-    /* At entry, CPENABLE should be showing which CPs are enabled. */

-

-    rsr     a2, CPENABLE                /* a2 = which CPs are enabled      */

-    beqz    a2, .Ldone                  /* quick exit if none              */

-    mov     a14, a0                     /* save return address             */

-    call0   XT_RTOS_CP_STATE            /* get address of CP save area     */

-    mov     a0, a14                     /* restore return address          */

-    beqz    a15, .Ldone                 /* if none then nothing to do      */

-    s16i    a2, a15, XT_CP_CS_ST        /* save mask of CPs being stored   */

-    movi    a13, _xt_coproc_sa_offset   /* array of CP save offsets        */

-    l32i    a15, a15, XT_CP_ASA         /* a15 = base of aligned save area */

-

-#if XCHAL_CP0_SA_SIZE

-    bbci.l  a2, 0, 2f                   /* CP 0 not enabled                */

-    l32i    a14, a13, 0                 /* a14 = _xt_coproc_sa_offset[0]   */

-    add     a3, a14, a15                /* a3 = save area for CP 0         */

-    xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP1_SA_SIZE

-    bbci.l  a2, 1, 2f                   /* CP 1 not enabled                */

-    l32i    a14, a13, 4                 /* a14 = _xt_coproc_sa_offset[1]   */

-    add     a3, a14, a15                /* a3 = save area for CP 1         */

-    xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP2_SA_SIZE

-    bbci.l  a2, 2, 2f

-    l32i    a14, a13, 8

-    add     a3, a14, a15

-    xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP3_SA_SIZE

-    bbci.l  a2, 3, 2f

-    l32i    a14, a13, 12

-    add     a3, a14, a15

-    xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP4_SA_SIZE

-    bbci.l  a2, 4, 2f

-    l32i    a14, a13, 16

-    add     a3, a14, a15

-    xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP5_SA_SIZE

-    bbci.l  a2, 5, 2f

-    l32i    a14, a13, 20

-    add     a3, a14, a15

-    xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP6_SA_SIZE

-    bbci.l  a2, 6, 2f

-    l32i    a14, a13, 24

-    add     a3, a14, a15

-    xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP7_SA_SIZE

-    bbci.l  a2, 7, 2f

-    l32i    a14, a13, 28

-    add     a3, a14, a15

-    xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-.Ldone:

-    ret

-#endif

-

-

-/*******************************************************************************

-_xt_coproc_restorecs

-

-Restore any callee-saved coprocessor state for the incoming thread.

-This function is called from coprocessor exception handling, when giving

-ownership to a thread that solicited a context switch earlier. It calls a

-system-specific function to get the coprocessor save area base address.

-

-Entry conditions:

-    - The incoming thread is set as the current thread.

-    - CPENABLE is set up correctly for all required coprocessors.

-    - a2 = mask of coprocessors to be restored.

-

-Exit conditions:

-    - All necessary CP callee-saved state has been restored.

-    - CPENABLE - unchanged.

-    - Registers a2-a7, a13-a15 have been trashed.

-

-Must be called from assembly code only, using CALL0.

-*******************************************************************************/

-#if XCHAL_CP_NUM > 0

-

-    .global     _xt_coproc_restorecs

-    .type       _xt_coproc_restorecs,@function

-    .align  4

-	.literal_position

-    .align      4

-_xt_coproc_restorecs:

-

-    mov     a14, a0                     /* save return address             */

-    call0   XT_RTOS_CP_STATE            /* get address of CP save area     */

-    mov     a0, a14                     /* restore return address          */

-    beqz    a15, .Ldone2                /* if none then nothing to do      */

-    l16ui   a3, a15, XT_CP_CS_ST        /* a3 = which CPs have been saved  */

-    xor     a3, a3, a2                  /* clear the ones being restored   */

-    s32i    a3, a15, XT_CP_CS_ST        /* update saved CP mask            */

-    movi    a13, _xt_coproc_sa_offset   /* array of CP save offsets        */

-    l32i    a15, a15, XT_CP_ASA         /* a15 = base of aligned save area */

-    

-#if XCHAL_CP0_SA_SIZE

-    bbci.l  a2, 0, 2f                   /* CP 0 not enabled                */

-    l32i    a14, a13, 0                 /* a14 = _xt_coproc_sa_offset[0]   */

-    add     a3, a14, a15                /* a3 = save area for CP 0         */

-    xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:  

-#endif

-

-#if XCHAL_CP1_SA_SIZE

-    bbci.l  a2, 1, 2f                   /* CP 1 not enabled                */

-    l32i    a14, a13, 4                 /* a14 = _xt_coproc_sa_offset[1]   */

-    add     a3, a14, a15                /* a3 = save area for CP 1         */

-    xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP2_SA_SIZE

-    bbci.l  a2, 2, 2f

-    l32i    a14, a13, 8

-    add     a3, a14, a15

-    xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP3_SA_SIZE

-    bbci.l  a2, 3, 2f

-    l32i    a14, a13, 12

-    add     a3, a14, a15

-    xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP4_SA_SIZE

-    bbci.l  a2, 4, 2f

-    l32i    a14, a13, 16

-    add     a3, a14, a15

-    xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP5_SA_SIZE

-    bbci.l  a2, 5, 2f

-    l32i    a14, a13, 20

-    add     a3, a14, a15

-    xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP6_SA_SIZE

-    bbci.l  a2, 6, 2f

-    l32i    a14, a13, 24

-    add     a3, a14, a15

-    xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-#if XCHAL_CP7_SA_SIZE

-    bbci.l  a2, 7, 2f

-    l32i    a14, a13, 28

-    add     a3, a14, a15

-    xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL

-2:

-#endif

-

-.Ldone2:

-    ret

-

-#endif

-

-

+/*******************************************************************************
+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 SAVE AND RESTORE ROUTINES
+
+Low-level Call0 functions for handling generic context save and restore of
+registers not specifically addressed by the interrupt vectors and handlers.
+Those registers (not handled by these functions) are PC, PS, A0, A1 (SP).
+Except for the calls to RTOS functions, this code is generic to Xtensa.
+
+Note that in Call0 ABI, interrupt handlers are expected to preserve the callee-
+save regs (A12-A15), which is always the case if the handlers are coded in C.
+However A12, A13 are made available as scratch registers for interrupt dispatch
+code, so are presumed saved anyway, and are always restored even in Call0 ABI.
+Only A14, A15 are truly handled as callee-save regs.
+
+Because Xtensa is a configurable architecture, this port supports all user
+generated configurations (except restrictions stated in the release notes).
+This is accomplished by conditional compilation using macros and functions
+defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
+Only the processor state included in your configuration is saved and restored,
+including any processor state added by user configuration options or TIE.
+
+*******************************************************************************/
+
+/*  Warn nicely if this file gets named with a lowercase .s instead of .S:  */
+#define NOERROR #
+NOERROR: .error "C preprocessor needed for this file: make sure its filename\
+ ends in uppercase .S, or use xt-xcc's -x assembler-with-cpp option."
+
+
+#include "xtensa_rtos.h"
+#include "xtensa_context.h"
+#include "esp_idf_version.h"
+#if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+#include "xt_asm_utils.h"
+#endif
+
+#ifdef XT_USE_OVLY
+#include <xtensa/overlay_os_asm.h>
+#endif
+
+    .text
+
+/*******************************************************************************
+
+_xt_context_save
+
+    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
+
+Saves all Xtensa processor state except PC, PS, A0, A1 (SP), A12, A13, in the
+interrupt stack frame defined in xtensa_rtos.h.
+Its counterpart is _xt_context_restore (which also restores A12, A13).
+
+Caller is expected to have saved PC, PS, A0, A1 (SP), A12, A13 in the frame.
+This function preserves A12 & A13 in order to provide the caller with 2 scratch 
+regs that need not be saved over the call to this function. The choice of which
+2 regs to provide is governed by xthal_window_spill_nw and xthal_save_extra_nw,
+to avoid moving data more than necessary. Caller can assign regs accordingly.
+
+Entry Conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+    Original A12, A13 have already been saved in the interrupt stack frame.
+    Other processor state except PC, PS, A0, A1 (SP), A12, A13, is as at the 
+    point of interruption.
+    If windowed ABI, PS.EXCM = 1 (exceptions disabled).
+
+Exit conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+    A12, A13 as at entry (preserved).
+    If windowed ABI, PS.EXCM = 1 (exceptions disabled).
+
+*******************************************************************************/
+
+    .global _xt_context_save
+    .type   _xt_context_save,@function
+    .align  4
+	.literal_position
+    .align  4
+
+_xt_context_save:
+
+    s32i    a2,  sp, XT_STK_A2
+    s32i    a3,  sp, XT_STK_A3
+    s32i    a4,  sp, XT_STK_A4
+    s32i    a5,  sp, XT_STK_A5
+    s32i    a6,  sp, XT_STK_A6
+    s32i    a7,  sp, XT_STK_A7
+    s32i    a8,  sp, XT_STK_A8
+    s32i    a9,  sp, XT_STK_A9
+    s32i    a10, sp, XT_STK_A10
+    s32i    a11, sp, XT_STK_A11
+
+    /*
+    Call0 ABI callee-saved regs a12-15 do not need to be saved here.
+    a12-13 are the caller's responsibility so it can use them as scratch.
+    So only need to save a14-a15 here for Windowed ABI (not Call0).
+    */
+    #ifndef __XTENSA_CALL0_ABI__
+    s32i    a14, sp, XT_STK_A14
+    s32i    a15, sp, XT_STK_A15
+    #endif
+
+    rsr     a3,  SAR
+    s32i    a3,  sp, XT_STK_SAR
+
+    #if XCHAL_HAVE_LOOPS
+    rsr     a3,  LBEG
+    s32i    a3,  sp, XT_STK_LBEG
+    rsr     a3,  LEND
+    s32i    a3,  sp, XT_STK_LEND
+    rsr     a3,  LCOUNT
+    s32i    a3,  sp, XT_STK_LCOUNT
+    #endif
+
+    #ifdef XT_USE_SWPRI
+    /* Save virtual priority mask */
+    movi    a3,  _xt_vpri_mask
+    l32i    a3,  a3, 0
+    s32i    a3,  sp, XT_STK_VPRI
+    #endif
+
+    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
+    mov     a9,  a0                     /* preserve ret addr */
+    #endif
+
+    #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifndef __XTENSA_CALL0_ABI__
+    /*
+    To spill the reg windows, temp. need pre-interrupt stack ptr and a4-15.
+    Need to save a9,12,13 temporarily (in frame temps) and recover originals.
+    Interrupts need to be disabled below XCHAL_EXCM_LEVEL and window overflow
+    and underflow exceptions disabled (assured by PS.EXCM == 1).
+    */
+    s32i    a12, sp, XT_STK_TMP0        /* temp. save stuff in stack frame */
+    s32i    a13, sp, XT_STK_TMP1    
+    s32i    a9,  sp, XT_STK_TMP2    
+
+    /*
+    Save the overlay state if we are supporting overlays. Since we just saved
+    three registers, we can conveniently use them here. Note that as of now,
+    overlays only work for windowed calling ABI.
+    */
+    #ifdef XT_USE_OVLY
+    l32i    a9,  sp, XT_STK_PC          /* recover saved PC */
+    _xt_overlay_get_state    a9, a12, a13
+    s32i    a9,  sp, XT_STK_OVLY        /* save overlay state */
+    #endif
+
+    l32i    a12, sp, XT_STK_A12         /* recover original a9,12,13 */
+    l32i    a13, sp, XT_STK_A13
+    l32i    a9,  sp, XT_STK_A9
+    addi    sp,  sp, XT_STK_FRMSZ       /* restore the interruptee's SP */
+    call0   xthal_window_spill_nw       /* preserves only a4,5,8,9,12,13 */
+    addi    sp,  sp, -XT_STK_FRMSZ
+    l32i    a12, sp, XT_STK_TMP0        /* recover stuff from stack frame */
+    l32i    a13, sp, XT_STK_TMP1    
+    l32i    a9,  sp, XT_STK_TMP2    
+    #endif
+    #endif /* (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0)) */
+
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    s32i    a12, sp, XT_STK_TMP0        /* temp. save stuff in stack frame */
+    s32i    a13, sp, XT_STK_TMP1
+    s32i    a9,  sp, XT_STK_TMP2
+
+    l32i    a12, sp, XT_STK_A12         /* recover original a9,12,13 */
+    l32i    a13, sp, XT_STK_A13
+    l32i    a9,  sp, XT_STK_A9
+    #endif
+
+    #if XCHAL_EXTRA_SA_SIZE > 0
+    addi    a2,  sp, XT_STK_EXTRA       /* where to save it */
+    # if XCHAL_EXTRA_SA_ALIGN > 16
+    movi    a3, -XCHAL_EXTRA_SA_ALIGN
+    and     a2, a2, a3                  /* align dynamically >16 bytes */
+    # endif
+    call0   xthal_save_extra_nw         /* destroys a0,2,3 */
+    #endif
+
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifndef __XTENSA_CALL0_ABI__
+    #ifdef XT_USE_OVLY
+    l32i    a9,  sp, XT_STK_PC          /* recover saved PC */
+    _xt_overlay_get_state    a9, a12, a13
+    s32i    a9,  sp, XT_STK_OVLY        /* save overlay state */
+    #endif
+
+    /* SPILL_ALL_WINDOWS macro requires window overflow exceptions to be enabled,
+     * i.e. PS.EXCM cleared and PS.WOE set.
+     * Since we are going to clear PS.EXCM, we also need to increase INTLEVEL
+     * at least to XCHAL_EXCM_LEVEL. This matches that value of effective INTLEVEL
+     * at entry (CINTLEVEL=max(PS.INTLEVEL, XCHAL_EXCM_LEVEL) when PS.EXCM is set.
+     * Since WindowOverflow exceptions will trigger inside SPILL_ALL_WINDOWS,
+     * need to save/restore EPC1 as well.
+     * Note: even though a4-a15 are saved into the exception frame, we should not
+     * clobber them until after SPILL_ALL_WINDOWS. This is because these registers
+     * may contain live windows belonging to previous frames in the call stack.
+     * These frames will be spilled by SPILL_ALL_WINDOWS, and if the register was
+     * used as a temporary by this code, the temporary value would get stored
+     * onto the stack, instead of the real value.
+     */
+    rsr     a2, PS                     /* to be restored after SPILL_ALL_WINDOWS */
+    movi    a0, PS_INTLEVEL_MASK
+    and     a3, a2, a0                 /* get the current INTLEVEL */
+    bgeui   a3, XCHAL_EXCM_LEVEL, 1f   /* calculate max(INTLEVEL, XCHAL_EXCM_LEVEL) */
+    movi    a3, XCHAL_EXCM_LEVEL
+1:
+    movi    a0, PS_UM | PS_WOE         /* clear EXCM, enable window overflow, set new INTLEVEL */
+    or      a3, a3, a0
+    wsr     a3, ps
+    rsr     a0, EPC1                   /* to be restored after SPILL_ALL_WINDOWS */
+
+    addi    sp,  sp, XT_STK_FRMSZ      /* restore the interruptee's SP */
+    SPILL_ALL_WINDOWS
+    addi    sp,  sp, -XT_STK_FRMSZ     /* return the current stack pointer and proceed with context save*/
+
+
+    wsr     a2, PS                     /* restore to the value at entry */
+    rsync
+    wsr     a0, EPC1                   /* likewise */
+
+    #endif /* __XTENSA_CALL0_ABI__ */
+
+    l32i    a12, sp, XT_STK_TMP0        /* restore the temp saved registers */
+    l32i    a13, sp, XT_STK_TMP1        /* our return address is there */
+    l32i    a9,  sp, XT_STK_TMP2
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    #if XCHAL_EXTRA_SA_SIZE > 0 || !defined(__XTENSA_CALL0_ABI__)
+    mov     a0, a9                      /* retrieve ret addr */
+    #endif
+
+    ret
+
+/*******************************************************************************
+
+_xt_context_restore
+
+    !! MUST BE CALLED ONLY BY 'CALL0' INSTRUCTION !!
+
+Restores all Xtensa processor state except PC, PS, A0, A1 (SP) (and in Call0
+ABI, A14, A15 which are preserved by all interrupt handlers) from an interrupt 
+stack frame defined in xtensa_rtos.h .
+Its counterpart is _xt_context_save (whose caller saved A12, A13).
+
+Caller is responsible to restore PC, PS, A0, A1 (SP).
+
+Entry Conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+
+Exit conditions:
+    A0  = Return address in caller.
+    A1  = Stack pointer of interrupted thread or handler ("interruptee").
+    Other processor state except PC, PS, A0, A1 (SP), is as at the point 
+    of interruption.
+
+*******************************************************************************/
+
+    .global _xt_context_restore
+    .type   _xt_context_restore,@function
+    .align  4
+	.literal_position
+    .align  4
+_xt_context_restore:
+
+    #if XCHAL_EXTRA_SA_SIZE > 0
+    /*  
+    NOTE: Normally the xthal_restore_extra_nw macro only affects address
+    registers a2-a5. It is theoretically possible for Xtensa processor
+    designers to write TIE that causes more address registers to be
+    affected, but it is generally unlikely. If that ever happens,
+    more registers need to be saved/restored around this macro invocation.
+    Here we only assume a13 is preserved.
+    Future Xtensa tools releases might limit the regs that can be affected.
+    */
+    mov     a13, a0                     /* preserve ret addr */
+    addi    a2,  sp, XT_STK_EXTRA       /* where to find it */
+    # if XCHAL_EXTRA_SA_ALIGN > 16
+    movi    a3, -XCHAL_EXTRA_SA_ALIGN
+    and     a2, a2, a3                  /* align dynamically >16 bytes */
+    # endif
+    call0   xthal_restore_extra_nw      /* destroys a0,2,3,4,5 */
+    mov     a0,  a13                    /* retrieve ret addr */
+    #endif
+
+    #if XCHAL_HAVE_LOOPS
+    l32i    a2,  sp, XT_STK_LBEG
+    l32i    a3,  sp, XT_STK_LEND
+    wsr     a2,  LBEG
+    l32i    a2,  sp, XT_STK_LCOUNT
+    wsr     a3,  LEND
+    wsr     a2,  LCOUNT
+    #endif
+
+    #ifdef XT_USE_OVLY
+    /*
+    If we are using overlays, this is a good spot to check if we need
+    to restore an overlay for the incoming task. Here we have a bunch
+    of registers to spare. Note that this step is going to use a few
+    bytes of storage below SP (SP-20 to SP-32) if an overlay is going
+    to be restored.
+    */
+    l32i    a2,  sp, XT_STK_PC          /* retrieve PC */
+    l32i    a3,  sp, XT_STK_PS          /* retrieve PS */
+    l32i    a4,  sp, XT_STK_OVLY        /* retrieve overlay state */
+    l32i    a5,  sp, XT_STK_A1          /* retrieve stack ptr */
+    _xt_overlay_check_map    a2, a3, a4, a5, a6
+    s32i    a2,  sp, XT_STK_PC          /* save updated PC */
+    s32i    a3,  sp, XT_STK_PS          /* save updated PS */
+    #endif
+
+    #ifdef XT_USE_SWPRI
+    /* Restore virtual interrupt priority and interrupt enable */
+    movi    a3,  _xt_intdata
+    l32i    a4,  a3, 0                  /* a4 = _xt_intenable */
+    l32i    a5,  sp, XT_STK_VPRI        /* a5 = saved _xt_vpri_mask */
+    and     a4,  a4, a5
+    wsr     a4,  INTENABLE              /* update INTENABLE */
+    s32i    a5,  a3, 4                  /* restore _xt_vpri_mask */
+    #endif
+
+    l32i    a3,  sp, XT_STK_SAR
+    l32i    a2,  sp, XT_STK_A2
+    wsr     a3,  SAR
+    l32i    a3,  sp, XT_STK_A3
+    l32i    a4,  sp, XT_STK_A4
+    l32i    a5,  sp, XT_STK_A5
+    l32i    a6,  sp, XT_STK_A6
+    l32i    a7,  sp, XT_STK_A7
+    l32i    a8,  sp, XT_STK_A8
+    l32i    a9,  sp, XT_STK_A9
+    l32i    a10, sp, XT_STK_A10
+    l32i    a11, sp, XT_STK_A11
+
+    /*
+    Call0 ABI callee-saved regs a12-15 do not need to be restored here.
+    However a12-13 were saved for scratch before XT_RTOS_INT_ENTER(), 
+    so need to be restored anyway, despite being callee-saved in Call0.
+    */
+    l32i    a12, sp, XT_STK_A12
+    l32i    a13, sp, XT_STK_A13
+    #ifndef __XTENSA_CALL0_ABI__
+    l32i    a14, sp, XT_STK_A14
+    l32i    a15, sp, XT_STK_A15
+    #endif
+
+    ret
+
+
+/*******************************************************************************
+
+_xt_coproc_init
+
+Initializes global co-processor management data, setting all co-processors
+to "unowned". Leaves CPENABLE as it found it (does NOT clear it).
+
+Called during initialization of the RTOS, before any threads run.
+
+This may be called from normal Xtensa single-threaded application code which
+might use co-processors. The Xtensa run-time initialization enables all 
+co-processors. They must remain enabled here, else a co-processor exception
+might occur outside of a thread, which the exception handler doesn't expect.
+
+Entry Conditions:
+    Xtensa single-threaded run-time environment is in effect.
+    No thread is yet running.
+
+Exit conditions:
+    None.
+
+Obeys ABI conventions per prototype:
+    void _xt_coproc_init(void)
+
+*******************************************************************************/
+
+#if XCHAL_CP_NUM > 0
+
+    .global _xt_coproc_init
+    .type   _xt_coproc_init,@function
+    .align  4
+	.literal_position
+    .align  4
+_xt_coproc_init:
+    ENTRY0
+
+    /* Initialize thread co-processor ownerships to 0 (unowned). */
+    movi    a2, _xt_coproc_owner_sa         /* a2 = base of owner array */
+    addi    a3, a2, (XCHAL_CP_MAX*portNUM_PROCESSORS) << 2       /* a3 = top+1 of owner array */
+    movi    a4, 0                           /* a4 = 0 (unowned) */
+1:  s32i    a4, a2, 0
+    addi    a2, a2, 4
+    bltu    a2, a3, 1b
+
+    RET0
+
+#endif
+
+
+/*******************************************************************************
+
+_xt_coproc_release
+
+Releases any and all co-processors owned by a given thread. The thread is 
+identified by it's co-processor state save area defined in xtensa_context.h .
+
+Must be called before a thread's co-proc save area is deleted to avoid
+memory corruption when the exception handler tries to save the state.
+May be called when a thread terminates or completes but does not delete
+the co-proc save area, to avoid the exception handler having to save the 
+thread's co-proc state before another thread can use it (optimization).
+
+Needs to be called on the processor the thread was running on. Unpinned threads
+won't have an entry here because they get pinned as soon they use a coprocessor.
+
+Entry Conditions:
+    A2  = Pointer to base of co-processor state save area.
+
+Exit conditions:
+    None.
+
+Obeys ABI conventions per prototype:
+    void _xt_coproc_release(void * coproc_sa_base)
+
+*******************************************************************************/
+
+#if XCHAL_CP_NUM > 0
+
+    .global _xt_coproc_release
+    .type   _xt_coproc_release,@function
+    .align  4
+	.literal_position
+    .align  4
+_xt_coproc_release:
+    ENTRY0                                  /* a2 = base of save area */
+
+	getcoreid a5
+	movi    a3, XCHAL_CP_MAX << 2
+	mull    a5, a5, a3
+    movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */
+	add     a3, a3, a5
+
+    addi    a4, a3, XCHAL_CP_MAX << 2       /* a4 = top+1 of owner array */
+    movi    a5, 0                           /* a5 = 0 (unowned) */
+
+    rsil    a6, XCHAL_EXCM_LEVEL            /* lock interrupts */
+
+1:  l32i    a7, a3, 0                       /* a7 = owner at a3 */
+    bne     a2, a7, 2f                      /* if (coproc_sa_base == owner) */
+    s32i    a5, a3, 0                       /*   owner = unowned */
+2:  addi    a3, a3, 1<<2                    /* a3 = next entry in owner array */
+    bltu    a3, a4, 1b                      /* repeat until end of array */
+
+3:  wsr     a6, PS                          /* restore interrupts */
+
+    RET0
+
+#endif
+
+
+/*******************************************************************************
+_xt_coproc_savecs
+
+If there is a current thread and it has a coprocessor state save area, then
+save all callee-saved state into this area. This function is called from the
+solicited context switch handler. It calls a system-specific function to get
+the coprocessor save area base address.
+
+Entry conditions:
+    - The thread being switched out is still the current thread.
+    - CPENABLE state reflects which coprocessors are active.
+    - Registers have been saved/spilled already.
+
+Exit conditions:
+    - All necessary CP callee-saved state has been saved.
+    - Registers a2-a7, a13-a15 have been trashed.
+
+Must be called from assembly code only, using CALL0.
+*******************************************************************************/
+#if XCHAL_CP_NUM > 0
+
+    .extern     _xt_coproc_sa_offset   /* external reference */
+
+    .global     _xt_coproc_savecs
+    .type       _xt_coproc_savecs,@function
+    .align  4
+	.literal_position
+    .align      4
+_xt_coproc_savecs:
+
+    /* At entry, CPENABLE should be showing which CPs are enabled. */
+
+    rsr     a2, CPENABLE                /* a2 = which CPs are enabled      */
+    beqz    a2, .Ldone                  /* quick exit if none              */
+    mov     a14, a0                     /* save return address             */
+    call0   XT_RTOS_CP_STATE            /* get address of CP save area     */
+    mov     a0, a14                     /* restore return address          */
+    beqz    a15, .Ldone                 /* if none then nothing to do      */
+    s16i    a2, a15, XT_CP_CS_ST        /* save mask of CPs being stored   */
+    movi    a13, _xt_coproc_sa_offset   /* array of CP save offsets        */
+    l32i    a15, a15, XT_CP_ASA         /* a15 = base of aligned save area */
+
+#if XCHAL_CP0_SA_SIZE
+    bbci.l  a2, 0, 2f                   /* CP 0 not enabled                */
+    l32i    a14, a13, 0                 /* a14 = _xt_coproc_sa_offset[0]   */
+    add     a3, a14, a15                /* a3 = save area for CP 0         */
+    xchal_cp0_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP1_SA_SIZE
+    bbci.l  a2, 1, 2f                   /* CP 1 not enabled                */
+    l32i    a14, a13, 4                 /* a14 = _xt_coproc_sa_offset[1]   */
+    add     a3, a14, a15                /* a3 = save area for CP 1         */
+    xchal_cp1_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP2_SA_SIZE
+    bbci.l  a2, 2, 2f
+    l32i    a14, a13, 8
+    add     a3, a14, a15
+    xchal_cp2_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP3_SA_SIZE
+    bbci.l  a2, 3, 2f
+    l32i    a14, a13, 12
+    add     a3, a14, a15
+    xchal_cp3_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP4_SA_SIZE
+    bbci.l  a2, 4, 2f
+    l32i    a14, a13, 16
+    add     a3, a14, a15
+    xchal_cp4_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP5_SA_SIZE
+    bbci.l  a2, 5, 2f
+    l32i    a14, a13, 20
+    add     a3, a14, a15
+    xchal_cp5_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP6_SA_SIZE
+    bbci.l  a2, 6, 2f
+    l32i    a14, a13, 24
+    add     a3, a14, a15
+    xchal_cp6_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP7_SA_SIZE
+    bbci.l  a2, 7, 2f
+    l32i    a14, a13, 28
+    add     a3, a14, a15
+    xchal_cp7_store a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+.Ldone:
+    ret
+#endif
+
+
+/*******************************************************************************
+_xt_coproc_restorecs
+
+Restore any callee-saved coprocessor state for the incoming thread.
+This function is called from coprocessor exception handling, when giving
+ownership to a thread that solicited a context switch earlier. It calls a
+system-specific function to get the coprocessor save area base address.
+
+Entry conditions:
+    - The incoming thread is set as the current thread.
+    - CPENABLE is set up correctly for all required coprocessors.
+    - a2 = mask of coprocessors to be restored.
+
+Exit conditions:
+    - All necessary CP callee-saved state has been restored.
+    - CPENABLE - unchanged.
+    - Registers a2-a7, a13-a15 have been trashed.
+
+Must be called from assembly code only, using CALL0.
+*******************************************************************************/
+#if XCHAL_CP_NUM > 0
+
+    .global     _xt_coproc_restorecs
+    .type       _xt_coproc_restorecs,@function
+    .align  4
+	.literal_position
+    .align      4
+_xt_coproc_restorecs:
+
+    mov     a14, a0                     /* save return address             */
+    call0   XT_RTOS_CP_STATE            /* get address of CP save area     */
+    mov     a0, a14                     /* restore return address          */
+    beqz    a15, .Ldone2                /* if none then nothing to do      */
+    l16ui   a3, a15, XT_CP_CS_ST        /* a3 = which CPs have been saved  */
+    xor     a3, a3, a2                  /* clear the ones being restored   */
+    s32i    a3, a15, XT_CP_CS_ST        /* update saved CP mask            */
+    movi    a13, _xt_coproc_sa_offset   /* array of CP save offsets        */
+    l32i    a15, a15, XT_CP_ASA         /* a15 = base of aligned save area */
+    
+#if XCHAL_CP0_SA_SIZE
+    bbci.l  a2, 0, 2f                   /* CP 0 not enabled                */
+    l32i    a14, a13, 0                 /* a14 = _xt_coproc_sa_offset[0]   */
+    add     a3, a14, a15                /* a3 = save area for CP 0         */
+    xchal_cp0_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:  
+#endif
+
+#if XCHAL_CP1_SA_SIZE
+    bbci.l  a2, 1, 2f                   /* CP 1 not enabled                */
+    l32i    a14, a13, 4                 /* a14 = _xt_coproc_sa_offset[1]   */
+    add     a3, a14, a15                /* a3 = save area for CP 1         */
+    xchal_cp1_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP2_SA_SIZE
+    bbci.l  a2, 2, 2f
+    l32i    a14, a13, 8
+    add     a3, a14, a15
+    xchal_cp2_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP3_SA_SIZE
+    bbci.l  a2, 3, 2f
+    l32i    a14, a13, 12
+    add     a3, a14, a15
+    xchal_cp3_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP4_SA_SIZE
+    bbci.l  a2, 4, 2f
+    l32i    a14, a13, 16
+    add     a3, a14, a15
+    xchal_cp4_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP5_SA_SIZE
+    bbci.l  a2, 5, 2f
+    l32i    a14, a13, 20
+    add     a3, a14, a15
+    xchal_cp5_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP6_SA_SIZE
+    bbci.l  a2, 6, 2f
+    l32i    a14, a13, 24
+    add     a3, a14, a15
+    xchal_cp6_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+#if XCHAL_CP7_SA_SIZE
+    bbci.l  a2, 7, 2f
+    l32i    a14, a13, 28
+    add     a3, a14, a15
+    xchal_cp7_load a3, a4, a5, a6, a7 continue=0 ofs=-1 select=XTHAL_SAS_TIE|XTHAL_SAS_NOCC|XTHAL_SAS_CALE alloc=XTHAL_SAS_ALL
+2:
+#endif
+
+.Ldone2:
+    ret
+
+#endif
+
+
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c
index 1862ddd..0be384a 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_init.c
@@ -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 */
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
index 3ed8d10..19c14a8 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_intr.c
@@ -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 */
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vector_defaults.S b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vector_defaults.S
index b760e0e..44362a1 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vector_defaults.S
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vector_defaults.S
@@ -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 */
+
diff --git a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S
index a93f655..ad099fa 100644
--- a/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S
+++ b/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S
@@ -1,2057 +1,2057 @@
-/*******************************************************************************

-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 VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS

-

-  Xtensa low level exception and interrupt vectors and handlers for an RTOS.

-

-  Interrupt handlers and user exception handlers support interaction with

-  the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and

-  after user's specific interrupt handlers. These macros are defined in

-  xtensa_<rtos>.h to call suitable functions in a specific RTOS.

-

-  Users can install application-specific interrupt handlers for low and

-  medium level interrupts, by calling xt_set_interrupt_handler(). These

-  handlers can be written in C, and must obey C calling convention. The

-  handler table is indexed by the interrupt number. Each handler may be

-  provided with an argument. 

-

-  Note that the system timer interrupt is handled specially, and is

-  dispatched to the RTOS-specific handler. This timer cannot be hooked

-  by application code.

-

-  Optional hooks are also provided to install a handler per level at 

-  run-time, made available by compiling this source file with 

-  '-DXT_INTEXC_HOOKS' (useful for automated testing).

-

-!!  This file is a template that usually needs to be modified to handle       !!

-!!  application specific interrupts. Search USER_EDIT for helpful comments    !!

-!!  on where to insert handlers and how to write them.                        !!

-

-  Users can also install application-specific exception handlers in the

-  same way, by calling xt_set_exception_handler(). One handler slot is

-  provided for each exception type. Note that some exceptions are handled

-  by the porting layer itself, and cannot be taken over by application

-  code in this manner. These are the alloca, syscall, and coprocessor

-  exceptions.

-

-  The exception handlers can be written in C, and must follow C calling

-  convention. Each handler is passed a pointer to an exception frame as

-  its single argument. The exception frame is created on the stack, and

-  holds the saved context of the thread that took the exception. If the

-  handler returns, the context will be restored and the instruction that

-  caused the exception will be retried. If the handler makes any changes

-  to the saved state in the exception frame, the changes will be applied

-  when restoring the context.

-

-  Because Xtensa is a configurable architecture, this port supports all user

-  generated configurations (except restrictions stated in the release notes).

-  This is accomplished by conditional compilation using macros and functions

-  defined in the Xtensa HAL (hardware adaptation layer) for your configuration.

-  Only the relevant parts of this file will be included in your RTOS build.

-  For example, this file provides interrupt vector templates for all types and

-  all priority levels, but only the ones in your configuration are built.

-

-  NOTES on the use of 'call0' for long jumps instead of 'j':

-   1. This file should be assembled with the -mlongcalls option to xt-xcc.

-   2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to

-      a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the

-      distance from the call to the destination. The linker then relaxes

-      it back to 'call0 dest' if it determines that dest is within range.

-      This allows more flexibility in locating code without the performance

-      overhead of the 'l32r' literal data load in cases where the destination

-      is in range of 'call0'. There is an additional benefit in that 'call0'

-      has a longer range than 'j' due to the target being word-aligned, so 

-      the 'l32r' sequence is less likely needed.

-   3. The use of 'call0' with -mlongcalls requires that register a0 not be 

-      live at the time of the call, which is always the case for a function 

-      call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.

-   4. This use of 'call0' is independent of the C function call ABI.

-

-*******************************************************************************/

-

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

-

-/*

-  Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.

-  Please change this when the tcb structure is changed

-*/

-#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3

-.extern pxCurrentTCB

-

-/*

---------------------------------------------------------------------------------

-    In order for backtracing to be able to trace from the pre-exception stack

-    across to the exception stack (including nested interrupts), we need to create

-    a pseudo base-save area to make it appear like the exception dispatcher was

-    triggered by a CALL4 from the pre-exception code. In reality, the exception

-    dispatcher uses the same window as pre-exception code, and only CALL0s are

-    used within the exception dispatcher.

-

-    To create the pseudo base-save area, we need to store a copy of the pre-exception's

-    base save area (a0 to a4) below the exception dispatcher's SP. EXCSAVE_x will

-    be used to store a copy of the SP that points to the interrupted code's exception

-    frame just in case the exception dispatcher's SP does not point to the exception

-    frame (which is the case when switching from task to interrupt stack).

-

-    Clearing the pseudo base-save area is uncessary as the interrupt dispatcher

-    will restore the current SP to that of the pre-exception SP.

---------------------------------------------------------------------------------

-*/

-#ifdef CONFIG_FREERTOS_INTERRUPT_BACKTRACE

-#define XT_DEBUG_BACKTRACE    1

-#endif

-

-

-/*

---------------------------------------------------------------------------------

-  Defines used to access _xtos_interrupt_table.

---------------------------------------------------------------------------------

-*/

-#define XIE_HANDLER     0

-#define XIE_ARG         4

-#define XIE_SIZE        8

-

-

-/*

-  Macro get_percpu_entry_for - convert a per-core ID into a multicore entry.

-  Basically does reg=reg*portNUM_PROCESSORS+current_core_id

-  Multiple versions here to optimize for specific portNUM_PROCESSORS values.

-*/

-    .macro get_percpu_entry_for reg scratch

-#if (portNUM_PROCESSORS == 1)

-    /* No need to do anything */

-#elif  (portNUM_PROCESSORS == 2)

-    /* Optimized 2-core code. */

-    getcoreid \scratch

-    addx2 \reg,\reg,\scratch

-#else

-    /* Generalized n-core code. Untested! */

-    movi \scratch,portNUM_PROCESSORS

-    mull \scratch,\reg,\scratch

-    getcoreid \reg

-    add \reg,\scratch,\reg

-#endif

-   .endm

-/*

---------------------------------------------------------------------------------

-  Macro extract_msb - return the input with only the highest bit set.

-

-  Input  : "ain"  - Input value, clobbered.

-  Output : "aout" - Output value, has only one bit set, MSB of "ain".

-  The two arguments must be different AR registers.

---------------------------------------------------------------------------------

-*/

-

-    .macro  extract_msb     aout ain

-1:

-    addi    \aout, \ain, -1         /* aout = ain - 1        */

-    and     \ain, \ain, \aout       /* ain  = ain & aout     */

-    bnez    \ain, 1b                /* repeat until ain == 0 */

-    addi    \aout, \aout, 1         /* return aout + 1       */

-    .endm

-

-/*

---------------------------------------------------------------------------------

-  Macro dispatch_c_isr - dispatch interrupts to user ISRs.

-  This will dispatch to user handlers (if any) that are registered in the

-  XTOS dispatch table (_xtos_interrupt_table). These handlers would have

-  been registered by calling _xtos_set_interrupt_handler(). There is one

-  exception - the timer interrupt used by the OS will not be dispatched

-  to a user handler - this must be handled by the caller of this macro.

-

-  Level triggered and software interrupts are automatically deasserted by

-  this code.

-

-  ASSUMPTIONS:

-    -- PS.INTLEVEL is set to "level" at entry

-    -- PS.EXCM = 0, C calling enabled

-

-  NOTE: For CALL0 ABI, a12-a15 have not yet been saved.

-

-  NOTE: This macro will use registers a0 and a2-a7. The arguments are:

-    level -- interrupt level

-    mask  -- interrupt bitmask for this level

---------------------------------------------------------------------------------

-*/

-

-    .macro  dispatch_c_isr    level  mask

-

-    #ifdef CONFIG_PM_TRACE

-    movi a6, 0 /* = ESP_PM_TRACE_IDLE */

-    getcoreid a7

-    call4 esp_pm_trace_exit

-    #endif // CONFIG_PM_TRACE

-

-    /* Get mask of pending, enabled interrupts at this level into a2. */

-

-.L_xt_user_int_&level&:

-    rsr     a2, INTENABLE

-    rsr     a3, INTERRUPT

-    movi    a4, \mask

-    and     a2, a2, a3

-    and     a2, a2, a4

-    beqz    a2, 9f                          /* nothing to do */

-

-    /* This bit of code provides a nice debug backtrace in the debugger.

-       It does take a few more instructions, so undef XT_DEBUG_BACKTRACE

-       if you want to save the cycles.

-       At this point, the exception frame should have been allocated and filled,

-       and current sp points to the interrupt stack (for non-nested interrupt)

-       or below the allocated exception frame (for nested interrupts). Copy the

-       pre-exception's base save area below the current SP.

-    */

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    rsr     a0, EXCSAVE_1 + \level - 1      /* Get exception frame pointer stored in EXCSAVE_x */

-    l32i    a3, a0, XT_STK_A0               /* Copy pre-exception a0 (return address) */

-    s32e    a3, a1, -16

-    l32i    a3, a0, XT_STK_A1               /* Copy pre-exception a1 (stack pointer) */

-    s32e    a3, a1, -12

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-    /* Backtracing only needs a0 and a1, no need to create full base save area.

-       Also need to change current frame's return address to point to pre-exception's

-       last run instruction.

-     */

-    rsr     a0, EPC_1 + \level - 1          /* return address */

-    movi    a4, 0xC0000000                  /* constant with top 2 bits set (call size) */

-    or      a0, a0, a4                      /* set top 2 bits */

-    addx2   a0, a4, a0                      /* clear top bit -- simulating call4 size   */

-    #endif

-    #endif

-

-    #ifdef CONFIG_PM_ENABLE

-    call4 esp_pm_impl_isr_hook

-    #endif

-

-    #ifdef XT_INTEXC_HOOKS

-    /* Call interrupt hook if present to (pre)handle interrupts. */

-    movi    a4, _xt_intexc_hooks

-    l32i    a4, a4, \level << 2

-    beqz    a4, 2f

-    #ifdef __XTENSA_CALL0_ABI__

-    callx0  a4

-    beqz    a2, 9f

-    #else

-    mov     a6, a2

-    callx4  a4

-    beqz    a6, 9f

-    mov     a2, a6

-    #endif

-2:

-    #endif

-

-    /* Now look up in the dispatch table and call user ISR if any. */

-    /* If multiple bits are set then MSB has highest priority.     */

-

-    extract_msb  a4, a2                     /* a4 = MSB of a2, a2 trashed */

-

-    #ifdef XT_USE_SWPRI

-    /* Enable all interrupts at this level that are numerically higher

-       than the one we just selected, since they are treated as higher

-       priority.

-    */

-    movi    a3, \mask                       /* a3 = all interrupts at this level */

-    add     a2, a4, a4                      /* a2 = a4 << 1 */

-    addi    a2, a2, -1                      /* a2 = mask of 1's <= a4 bit */

-    and     a2, a2, a3                      /* a2 = mask of all bits <= a4 at this level */

-    movi    a3, _xt_intdata

-    l32i    a6, a3, 4                       /* a6 = _xt_vpri_mask */

-    neg     a2, a2

-    addi    a2, a2, -1                      /* a2 = mask to apply */

-    and     a5, a6, a2                      /* mask off all bits <= a4 bit */

-    s32i    a5, a3, 4                       /* update _xt_vpri_mask */

-    rsr     a3, INTENABLE

-    and     a3, a3, a2                      /* mask off all bits <= a4 bit */

-    wsr     a3, INTENABLE

-    rsil    a3, \level - 1                  /* lower interrupt level by 1 */

-    #endif

-

-    movi    a3, XT_TIMER_INTEN              /* a3 = timer interrupt bit */

-    wsr     a4, INTCLEAR                    /* clear sw or edge-triggered interrupt */

-    beq     a3, a4, 7f                      /* if timer interrupt then skip table */

-

-    find_ms_setbit a3, a4, a3, 0            /* a3 = interrupt number */

-

-    get_percpu_entry_for a3, a12

-    movi    a4, _xt_interrupt_table

-    addx8   a3, a3, a4                      /* a3 = address of interrupt table entry */

-    l32i    a4, a3, XIE_HANDLER             /* a4 = handler address */

-    #ifdef __XTENSA_CALL0_ABI__

-    mov     a12, a6                         /* save in callee-saved reg */

-    l32i    a2, a3, XIE_ARG                 /* a2 = handler arg */

-    callx0  a4                              /* call handler */

-    mov     a2, a12

-    #else

-    mov     a2, a6                          /* save in windowed reg */

-    l32i    a6, a3, XIE_ARG                 /* a6 = handler arg */

-    callx4  a4                              /* call handler */

-    #endif

-

-    #ifdef XT_USE_SWPRI

-    j       8f

-    #else

-    j       .L_xt_user_int_&level&          /* check for more interrupts */

-    #endif

-

-7:

-

-    .ifeq XT_TIMER_INTPRI - \level

-.L_xt_user_int_timer_&level&:

-    /*

-    Interrupt handler for the RTOS tick timer if at this level.

-    We'll be reading the interrupt state again after this call

-    so no need to preserve any registers except a6 (vpri_mask).

-    */

-

-    #ifdef __XTENSA_CALL0_ABI__

-    mov     a12, a6

-    call0   XT_RTOS_TIMER_INT

-    mov     a2, a12

-    #else

-    mov     a2, a6

-    call4   XT_RTOS_TIMER_INT

-    #endif

-    .endif

-

-    #ifdef XT_USE_SWPRI

-    j       8f

-    #else

-    j       .L_xt_user_int_&level&          /* check for more interrupts */

-    #endif

-

-    #ifdef XT_USE_SWPRI

-8:

-    /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from

-       virtual _xt_intenable which _could_ have changed during interrupt

-       processing. */

-

-    movi    a3, _xt_intdata

-    l32i    a4, a3, 0                       /* a4 = _xt_intenable    */

-    s32i    a2, a3, 4                       /* update _xt_vpri_mask  */

-    and     a4, a4, a2                      /* a4 = masked intenable */

-    wsr     a4, INTENABLE                   /* update INTENABLE      */

-    #endif

-

-9:

-    /* done */

-

-    .endm

-

-

-/*

---------------------------------------------------------------------------------

-  Panic handler.

-  Should be reached by call0 (preferable) or jump only. If call0, a0 says where 

-  from. If on simulator, display panic message and abort, else loop indefinitely.

---------------------------------------------------------------------------------

-*/

-

-    .section .iram1,"ax"

-    .global panicHandler

-

-    .global     _xt_panic

-    .type       _xt_panic,@function

-    .align      4

-    .literal_position

-    .align      4

-

-_xt_panic:

-    /* Allocate exception frame and save minimal context. */

-    mov     a0, sp

-    addi    sp, sp, -XT_STK_FRMSZ

-    s32i    a0, sp, XT_STK_A1

-    #if XCHAL_HAVE_WINDOWED

-    s32e    a0, sp, -12                     /* for debug backtrace */

-    #endif

-    rsr     a0, PS                          /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_1                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    #if XCHAL_HAVE_WINDOWED

-    s32e    a0, sp, -16                     /* for debug backtrace */

-    #endif

-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */

-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */

-    call0   _xt_context_save

-

-    /* Save exc cause and vaddr into exception frame */

-    rsr     a0, EXCCAUSE

-    s32i    a0, sp, XT_STK_EXCCAUSE

-    rsr     a0, EXCVADDR

-    s32i    a0, sp, XT_STK_EXCVADDR

-

-    /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */

-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */

-

-    s32i    a0, sp, XT_STK_A0

-

-    /* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */

-    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE

-    wsr     a0, PS

-

-    //Call panic handler

-    mov     a6,sp

-    call4 panicHandler

-

-

-    .align 4

-//Call using call0. Prints the hex char in a2. Kills a3, a4, a5

-panic_print_hex:

-    movi a3,0x60000000

-    movi a4,8

-panic_print_hex_loop:

-    l32i a5, a3, 0x1c

-    extui a5, a5, 16, 8

-    bgei a5,64,panic_print_hex_loop

-

-    srli a5,a2,28

-    bgei a5,10,panic_print_hex_a

-    addi a5,a5,'0'

-    j panic_print_hex_ok

-panic_print_hex_a:

-    addi a5,a5,'A'-10

-panic_print_hex_ok:

-    s32i a5,a3,0

-    slli a2,a2,4

-    

-    addi a4,a4,-1

-    bnei a4,0,panic_print_hex_loop

-    movi a5,' '

-    s32i a5,a3,0

-

-    ret

-

-

-

-    .section    .rodata, "a"

-    .align      4

-

-

-

-/*

---------------------------------------------------------------------------------

-    Hooks to dynamically install handlers for exceptions and interrupts.

-    Allows automated regression frameworks to install handlers per test.

-    Consists of an array of function pointers indexed by interrupt level, 

-    with index 0 containing the entry for user exceptions.

-    Initialized with all 0s, meaning no handler is installed at each level.

-    See comment in xtensa_rtos.h for more details.

-

-    *WARNING*  This array is for all CPUs, that is, installing a hook for 

-    one CPU will install it for all others as well!

---------------------------------------------------------------------------------

-*/

-

-    #ifdef XT_INTEXC_HOOKS

-    .data

-    .global     _xt_intexc_hooks

-    .type       _xt_intexc_hooks,@object

-    .align      4

-

-_xt_intexc_hooks:

-    .fill       XT_INTEXC_HOOK_NUM, 4, 0

-    #endif

-

-

-/*

---------------------------------------------------------------------------------

-  EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS

-  (except window exception vectors).

-

-  Each vector goes at a predetermined location according to the Xtensa

-  hardware configuration, which is ensured by its placement in a special

-  section known to the Xtensa linker support package (LSP). It performs

-  the minimum necessary before jumping to the handler in the .text section.

-

-  The corresponding handler goes in the normal .text section. It sets up

-  the appropriate stack frame, saves a few vector-specific registers and

-  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context

-  and enter the RTOS, then sets up a C environment. It then calls the

-  user's interrupt handler code (which may be coded in C) and finally 

-  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.

-

-  While XT_RTOS_INT_EXIT does not return directly to the interruptee,

-  eventually the RTOS scheduler will want to dispatch the interrupted

-  task or handler. The scheduler will return to the exit point that was

-  saved in the interrupt stack frame at XT_STK_EXIT.

---------------------------------------------------------------------------------

-*/

-

-

-/*

---------------------------------------------------------------------------------

-Debug Exception.

---------------------------------------------------------------------------------

-*/

-

-#if XCHAL_HAVE_DEBUG

-

-    .begin      literal_prefix .DebugExceptionVector

-    .section    .DebugExceptionVector.text, "ax"

-    .global     _DebugExceptionVector

-    .align      4

-    .global     xt_debugexception

-_DebugExceptionVector:

-    wsr     a0, EXCSAVE+XCHAL_DEBUGLEVEL    /* preserve a0 */

-    call0   xt_debugexception            /* load exception handler */

-

-    .end        literal_prefix

-

-#endif

-

-/*

---------------------------------------------------------------------------------

-Double Exception.

-Double exceptions are not a normal occurrence. They indicate a bug of some kind.

---------------------------------------------------------------------------------

-*/

-

-#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR

-

-    .begin      literal_prefix .DoubleExceptionVector

-    .section    .DoubleExceptionVector.text, "ax"

-    .global     _DoubleExceptionVector

-    .align      4

-

-_DoubleExceptionVector:

-

-    #if XCHAL_HAVE_DEBUG

-    break   1, 4                            /* unhandled double exception */

-    #endif

-    movi    a0,PANIC_RSN_DOUBLEEXCEPTION

-    wsr     a0,EXCCAUSE

-    call0   _xt_panic                       /* does not return */

-    rfde                                    /* make a0 point here not later */

-

-    .end        literal_prefix

-

-#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */

-

-/*

---------------------------------------------------------------------------------

-Kernel Exception (including Level 1 Interrupt from kernel mode).

---------------------------------------------------------------------------------

-*/

-

-    .begin      literal_prefix .KernelExceptionVector

-    .section    .KernelExceptionVector.text, "ax"

-    .global     _KernelExceptionVector

-    .align      4

-

-_KernelExceptionVector:

-

-    wsr     a0, EXCSAVE_1                   /* preserve a0 */

-    call0   _xt_kernel_exc                  /* kernel exception handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-    .section .iram1,"ax"

-    .align      4

-

-_xt_kernel_exc:

-    #if XCHAL_HAVE_DEBUG

-    break   1, 0                            /* unhandled kernel exception */

-    #endif

-    movi    a0,PANIC_RSN_KERNELEXCEPTION

-    wsr     a0,EXCCAUSE

-    call0   _xt_panic                       /* does not return */

-    rfe                                     /* make a0 point here not there */

-

-

-/*

---------------------------------------------------------------------------------

-User Exception (including Level 1 Interrupt from user mode).

---------------------------------------------------------------------------------

-*/

-

-    .begin      literal_prefix .UserExceptionVector

-    .section    .UserExceptionVector.text, "ax"

-    .global     _UserExceptionVector

-    .type       _UserExceptionVector,@function

-    .align      4

-

-_UserExceptionVector:

-

-    wsr     a0, EXCSAVE_1                   /* preserve a0 */

-    call0   _xt_user_exc                    /* user exception handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-/*

---------------------------------------------------------------------------------

-  Insert some waypoints for jumping beyond the signed 8-bit range of

-  conditional branch instructions, so the conditional branchces to specific

-  exception handlers are not taken in the mainline. Saves some cycles in the

-  mainline.

---------------------------------------------------------------------------------

-*/

-

-#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY

-    .global   LoadStoreErrorHandler

-    .global   AlignmentErrorHandler

-#endif

-

-    .section .iram1,"ax"

-

-    #if XCHAL_HAVE_WINDOWED

-    .align      4

-_xt_to_alloca_exc:

-    call0   _xt_alloca_exc                  /* in window vectors section */

-    /* never returns here - call0 is used as a jump (see note at top) */

-    #endif

-

-    .align      4

-_xt_to_syscall_exc:

-    call0   _xt_syscall_exc

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    #if XCHAL_CP_NUM > 0

-    .align      4

-_xt_to_coproc_exc:

-    call0   _xt_coproc_exc

-    /* never returns here - call0 is used as a jump (see note at top) */

-    #endif

-

-#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY

-    .align      4

-_call_loadstore_handler:

-    call0   LoadStoreErrorHandler

-    /* This will return only if wrong opcode or address out of range*/

-    j       .LS_exit

-

-    .align      4

-_call_alignment_handler:

-    call0   AlignmentErrorHandler

-    /* This will return only if wrong opcode or address out of range*/

-    addi    a0, a0, 1

-    j       .LS_exit

-#endif

-

-/*

---------------------------------------------------------------------------------

-  User exception handler.

---------------------------------------------------------------------------------

-*/

-

-    .type       _xt_user_exc,@function

-    .align      4

-

-_xt_user_exc:

-

-    /* If level 1 interrupt then jump to the dispatcher */

-    rsr     a0, EXCCAUSE

-    beqi    a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1

-

-    /* Handle any coprocessor exceptions. Rely on the fact that exception

-       numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.

-    */

-    #if XCHAL_CP_NUM > 0

-    bgeui   a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc

-    #endif

-

-    /* Handle alloca and syscall exceptions */

-    #if XCHAL_HAVE_WINDOWED

-    beqi    a0, EXCCAUSE_ALLOCA,  _xt_to_alloca_exc

-    #endif

-    beqi    a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc

-

-#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY

-    beqi    a0, EXCCAUSE_LOAD_STORE_ERROR, _call_loadstore_handler

-

-    addi    a0, a0, -1

-    beqi    a0, 8, _call_alignment_handler

-    addi    a0, a0, 1

-.LS_exit:

-#endif

-

-    /* Handle all other exceptions. All can have user-defined handlers. */

-    /* NOTE: we'll stay on the user stack for exception handling.       */

-

-    /* Allocate exception frame and save minimal context. */

-    mov     a0, sp

-    addi    sp, sp, -XT_STK_FRMSZ

-    s32i    a0, sp, XT_STK_A1

-    #if XCHAL_HAVE_WINDOWED

-    s32e    a0, sp, -12                     /* for debug backtrace */

-    #endif

-    rsr     a0, PS                          /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_1                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    #if XCHAL_HAVE_WINDOWED

-    s32e    a0, sp, -16                     /* for debug backtrace */

-    #endif

-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */

-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */

-    call0   _xt_context_save

-

-    /* Save exc cause and vaddr into exception frame */

-    rsr     a0, EXCCAUSE

-    s32i    a0, sp, XT_STK_EXCCAUSE

-    rsr     a0, EXCVADDR

-    s32i    a0, sp, XT_STK_EXCVADDR

-

-    /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */

-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-

-    /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM

-    #else

-    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-

-    /*

-        Create pseudo base save area. At this point, sp is still pointing to the

-        allocated and filled exception stack frame.

-    */

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    l32i    a3, sp, XT_STK_A0               /* Copy pre-exception a0 (return address) */

-    s32e    a3, sp, -16

-    l32i    a3, sp, XT_STK_A1               /* Copy pre-exception a1 (stack pointer) */

-    s32e    a3, sp, -12

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-    rsr     a0, EPC_1                       /* return address for debug backtrace */

-    movi    a5, 0xC0000000                  /* constant with top 2 bits set (call size) */

-    rsync                                   /* wait for WSR.PS to complete */

-    or      a0, a0, a5                      /* set top 2 bits */

-    addx2   a0, a5, a0                      /* clear top bit -- thus simulating call4 size */

-    #else

-    rsync                                   /* wait for WSR.PS to complete */

-    #endif

-    #endif

-

-    rsr     a2, EXCCAUSE                    /* recover exc cause */

-

-    #ifdef XT_INTEXC_HOOKS

-    /*

-    Call exception hook to pre-handle exceptions (if installed).

-    Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).

-    */

-    movi    a4, _xt_intexc_hooks

-    l32i    a4, a4, 0                       /* user exception hook index 0 */

-    beqz    a4, 1f

-.Ln_xt_user_exc_call_hook:

-    #ifdef __XTENSA_CALL0_ABI__

-    callx0  a4

-    beqi    a2, -1, .L_xt_user_done

-    #else

-    mov     a6, a2

-    callx4  a4

-    beqi    a6, -1, .L_xt_user_done

-    mov     a2, a6

-    #endif

-1:

-    #endif

-

-    rsr     a2, EXCCAUSE                    /* recover exc cause */

-    movi    a3, _xt_exception_table

-    get_percpu_entry_for a2, a4

-    addx4   a4, a2, a3                      /* a4 = address of exception table entry */

-    l32i    a4, a4, 0                       /* a4 = handler address */

-    #ifdef __XTENSA_CALL0_ABI__

-    mov     a2, sp                          /* a2 = pointer to exc frame */

-    callx0  a4                              /* call handler */

-    #else

-    mov     a6, sp                          /* a6 = pointer to exc frame */

-    callx4  a4                              /* call handler */

-    #endif

-

-.L_xt_user_done:

-

-    /* Restore context and return */

-    call0   _xt_context_restore

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, PS

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_1

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove exception frame */

-    rsync                                   /* ensure PS and EPC written */

-    rfe                                     /* PS.EXCM is cleared */

-

-

-/*

---------------------------------------------------------------------------------

-  Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT

-  on entry and used to return to a thread or interrupted interrupt handler.

---------------------------------------------------------------------------------

-*/

-

-    .global     _xt_user_exit

-    .type       _xt_user_exit,@function

-    .align      4

-_xt_user_exit:

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, PS

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_1

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */

-    rsync                                   /* ensure PS and EPC written */

-    rfe                                     /* PS.EXCM is cleared */

-

-

-/*

-

---------------------------------------------------------------------------------

-Syscall Exception Handler (jumped to from User Exception Handler).

-Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).

-Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.

---------------------------------------------------------------------------------

-*/

-

-    .section .iram1,"ax"

-    .type       _xt_syscall_exc,@function

-    .align      4

-_xt_syscall_exc:

-

-    #ifdef __XTENSA_CALL0_ABI__

-    /*

-    Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.

-    Use a minimal stack frame (16B) to save A2 & A3 for scratch.

-    PS.EXCM could be cleared here, but unlikely to improve worst-case latency.

-    rsr     a0, PS

-    addi    a0, a0, -PS_EXCM_MASK

-    wsr     a0, PS

-    */

-    addi    sp, sp, -16

-    s32i    a2, sp, 8

-    s32i    a3, sp, 12

-    #else   /* Windowed ABI */

-    /*

-    Save necessary context and spill the register windows.

-    PS.EXCM is still set and must remain set until after the spill.

-    Reuse context save function though it saves more than necessary.

-    For this reason, a full interrupt stack frame is allocated.

-    */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */

-    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */

-    call0   _xt_context_save

-    #endif

-

-    /*

-    Grab the interruptee's PC and skip over the 'syscall' instruction.

-    If it's at the end of a zero-overhead loop and it's not on the last

-    iteration, decrement loop counter and skip to beginning of loop.

-    */

-    rsr     a2, EPC_1                       /* a2 = PC of 'syscall' */

-    addi    a3, a2, 3                       /* ++PC                 */

-    #if XCHAL_HAVE_LOOPS

-    rsr     a0, LEND                        /* if (PC == LEND       */

-    bne     a3, a0, 1f

-    rsr     a0, LCOUNT                      /*     && LCOUNT != 0)  */

-    beqz    a0, 1f                          /* {                    */

-    addi    a0, a0, -1                      /*   --LCOUNT           */

-    rsr     a3, LBEG                        /*   PC = LBEG          */

-    wsr     a0, LCOUNT                      /* }                    */

-    #endif

-1:  wsr     a3, EPC_1                       /* update PC            */

-

-    /* Restore interruptee's context and return from exception. */

-    #ifdef __XTENSA_CALL0_ABI__

-    l32i    a2, sp, 8

-    l32i    a3, sp, 12

-    addi    sp, sp, 16

-    #else

-    call0   _xt_context_restore

-    addi    sp, sp, XT_STK_FRMSZ

-    #endif

-    movi    a0, -1

-    movnez  a2, a0, a2                      /* return -1 if not syscall 0 */

-    rsr     a0, EXCSAVE_1

-    rfe

-

-/*

---------------------------------------------------------------------------------

-Co-Processor Exception Handler (jumped to from User Exception Handler).

-These exceptions are generated by co-processor instructions, which are only

-allowed in thread code (not in interrupts or kernel code). This restriction is 

-deliberately imposed to reduce the burden of state-save/restore in interrupts.

---------------------------------------------------------------------------------

-*/

-#if XCHAL_CP_NUM > 0

-

-    .section .rodata, "a"

-

-/* Offset to CP n save area in thread's CP save area. */

-    .global _xt_coproc_sa_offset

-    .type   _xt_coproc_sa_offset,@object

-    .align  16                      /* minimize crossing cache boundaries */

-_xt_coproc_sa_offset:

-    .word   XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA

-    .word   XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA

-

-/* Bitmask for CP n's CPENABLE bit. */

-    .type   _xt_coproc_mask,@object

-    .align  16,,8                   /* try to keep it all in one cache line */

-    .set    i, 0

-_xt_coproc_mask:

-    .rept   XCHAL_CP_MAX

-    .long   (i<<16) | (1<<i)    // upper 16-bits = i, lower = bitmask

-    .set    i, i+1

-    .endr

-

-    .data

-

-/* Owner thread of CP n, identified by thread's CP save area (0 = unowned). */

-    .global _xt_coproc_owner_sa

-    .type   _xt_coproc_owner_sa,@object

-    .align  16,,XCHAL_CP_MAX<<2     /* minimize crossing cache boundaries */

-_xt_coproc_owner_sa:

-    .space  (XCHAL_CP_MAX * portNUM_PROCESSORS) << 2

-

-    .section .iram1,"ax"

-

-

-    .align  4

-.L_goto_invalid:

-    j   .L_xt_coproc_invalid    /* not in a thread (invalid) */

-    .align  4

-.L_goto_done:

-    j   .L_xt_coproc_done

-

-

-/*

---------------------------------------------------------------------------------

-  Coprocessor exception handler.

-  At entry, only a0 has been saved (in EXCSAVE_1).

---------------------------------------------------------------------------------

-*/

-

-    .type   _xt_coproc_exc,@function

-    .align  4

-

-_xt_coproc_exc:

-

-    /* Allocate interrupt stack frame and save minimal context. */

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    #if XCHAL_HAVE_WINDOWED

-    s32e    a0, sp, -12                     /* for debug backtrace */

-    #endif

-    rsr     a0, PS                          /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_1                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    #if XCHAL_HAVE_WINDOWED

-    s32e    a0, sp, -16                     /* for debug backtrace */

-    #endif

-    movi    a0, _xt_user_exit               /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    rsr     a0, EXCCAUSE

-    s32i    a5, sp, XT_STK_A5               /* save a5 */

-    addi    a5, a0, -EXCCAUSE_CP0_DISABLED  /* a5 = CP index */

-

-    /* Save a few more of interruptee's registers (a5 was already saved). */

-    s32i    a2,  sp, XT_STK_A2

-    s32i    a3,  sp, XT_STK_A3

-    s32i    a4,  sp, XT_STK_A4

-    s32i    a15, sp, XT_STK_A15

-

-    /* Get co-processor state save area of new owner thread. */

-    call0   XT_RTOS_CP_STATE                /* a15 = new owner's save area */

-    #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))

-    beqz    a15, .L_goto_invalid            /* not in a thread (invalid) */

-    #else

-    #ifndef CONFIG_FREERTOS_FPU_IN_ISR     

-    beqz    a15, .L_goto_invalid

-    #endif

-    #endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    /*When FPU in ISR is enabled we could deal with zeroed a15 */

-

-    /* Enable the co-processor's bit in CPENABLE. */

-    movi    a0, _xt_coproc_mask

-    rsr     a4, CPENABLE                    /* a4 = CPENABLE */

-    addx4   a0, a5, a0                      /* a0 = &_xt_coproc_mask[n] */

-    l32i    a0, a0, 0                       /* a0 = (n << 16) | (1 << n) */

-

-    /* FPU operations are incompatible with non-pinned tasks. If we have a FPU operation

-       here, to keep the entire thing from crashing, it's better to pin the task to whatever

-       core we're running on now. */

-    movi    a2, pxCurrentTCB

-    getcoreid a3

-    addx4     a2,  a3, a2

-    l32i    a2, a2, 0                       /* a2 = start of pxCurrentTCB[cpuid] */

-    addi    a2, a2, TASKTCB_XCOREID_OFFSET  /* offset to xCoreID in tcb struct */

-    s32i    a3, a2, 0                       /* store current cpuid */

-

-    /* Grab correct xt_coproc_owner_sa for this core */

-    movi    a2, XCHAL_CP_MAX << 2

-    mull    a2, a2, a3                      /* multiply by current processor id */

-    movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */

-    add     a3, a3, a2                      /* a3 = owner area needed for this processor */

-

-    extui   a2, a0, 0, 16                   /* coprocessor bitmask portion */

-    or      a4, a4, a2                      /* a4 = CPENABLE | (1 << n) */

-    wsr     a4, CPENABLE

-

-/* 

-Keep loading _xt_coproc_owner_sa[n] atomic (=load once, then use that value

-everywhere): _xt_coproc_release assumes it works like this in order not to need

-locking.

-*/

-

-

-    /* Get old coprocessor owner thread (save area ptr) and assign new one.  */

-    addx4   a3,  a5, a3                      /* a3 = &_xt_coproc_owner_sa[n] */

-    l32i    a2,  a3, 0                       /* a2 = old owner's save area */

-    s32i    a15, a3, 0                       /* _xt_coproc_owner_sa[n] = new */

-    rsync                                    /* ensure wsr.CPENABLE is complete */

-

-    /* Only need to context switch if new owner != old owner. */

-    /* If float is necessary on ISR, we need to remove this check */

-    /* below, because on restoring from ISR we may have new == old condition used

-     * to force cp restore to next thread

-     */

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifndef CONFIG_FREERTOS_FPU_IN_ISR

-    #endif

-    beq     a15, a2, .L_goto_done           /* new owner == old, we're done */

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #endif

-    #endif

-

-    /* If no old owner then nothing to save. */

-    beqz    a2, .L_check_new

-

-    /* If old owner not actively using CP then nothing to save. */

-    l16ui   a4,  a2,  XT_CPENABLE           /* a4 = old owner's CPENABLE */

-    bnone   a4,  a0,  .L_check_new          /* old owner not using CP    */

-

-.L_save_old:

-    /* Save old owner's coprocessor state. */

-

-    movi    a5, _xt_coproc_sa_offset

-

-    /* Mark old owner state as no longer active (CPENABLE bit n clear). */

-    xor     a4,  a4,  a0                    /* clear CP bit in CPENABLE    */

-    s16i    a4,  a2,  XT_CPENABLE           /* update old owner's CPENABLE */

-

-    extui   a4,  a0,  16,  5                /* a4 = CP index = n */

-    addx4   a5,  a4,  a5                    /* a5 = &_xt_coproc_sa_offset[n] */

-

-    /* Mark old owner state as saved (CPSTORED bit n set). */

-    l16ui   a4,  a2,  XT_CPSTORED           /* a4 = old owner's CPSTORED */

-    l32i    a5,  a5,  0                     /* a5 = XT_CP[n]_SA offset */

-    or      a4,  a4,  a0                    /* set CP in old owner's CPSTORED */

-    s16i    a4,  a2,  XT_CPSTORED           /* update old owner's CPSTORED */

-    l32i    a2, a2, XT_CP_ASA               /* ptr to actual (aligned) save area */

-    extui   a3, a0, 16, 5                   /* a3 = CP index = n */

-    add     a2, a2, a5                      /* a2 = old owner's area for CP n */

-

-    /*

-    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.

-    It is theoretically possible for Xtensa processor designers to write TIE 

-    that causes more address registers to be affected, but it is generally 

-    unlikely. If that ever happens, more registers needs to be saved/restored

-    around this macro invocation, and the value in a15 needs to be recomputed.

-    */

-    xchal_cpi_store_funcbody

-

-.L_check_new:

-    /* Check if any state has to be restored for new owner. */

-    /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    beqz    a15, .L_xt_coproc_done

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    l16ui   a3,  a15, XT_CPSTORED           /* a3 = new owner's CPSTORED */

-    movi    a4, _xt_coproc_sa_offset

-    bnone   a3,  a0,  .L_check_cs           /* full CP not saved, check callee-saved */

-    xor     a3,  a3,  a0                    /* CPSTORED bit is set, clear it */

-    s16i    a3,  a15, XT_CPSTORED           /* update new owner's CPSTORED */

-

-    /* Adjust new owner's save area pointers to area for CP n. */

-    extui   a3,  a0, 16, 5                  /* a3 = CP index = n */

-    addx4   a4,  a3, a4                     /* a4 = &_xt_coproc_sa_offset[n] */

-    l32i    a4,  a4, 0                      /* a4 = XT_CP[n]_SA */

-    l32i    a5, a15, XT_CP_ASA              /* ptr to actual (aligned) save area */

-    add     a2,  a4, a5                     /* a2 = new owner's area for CP */

-

-    /*

-    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.

-    It is theoretically possible for Xtensa processor designers to write TIE 

-    that causes more address registers to be affected, but it is generally 

-    unlikely. If that ever happens, more registers needs to be saved/restored

-    around this macro invocation.

-    */

-    xchal_cpi_load_funcbody

-

-    /* Restore interruptee's saved registers. */

-    /* Can omit rsync for wsr.CPENABLE here because _xt_user_exit does it. */

-.L_xt_coproc_done:

-    l32i    a15, sp, XT_STK_A15

-    l32i    a5,  sp, XT_STK_A5

-    l32i    a4,  sp, XT_STK_A4

-    l32i    a3,  sp, XT_STK_A3

-    l32i    a2,  sp, XT_STK_A2

-    call0   _xt_user_exit                   /* return via exit dispatcher */

-    /* Never returns here - call0 is used as a jump (see note at top) */

-

-.L_check_cs:

-    /* a0 = CP mask in low bits, a15 = new owner's save area */

-    l16ui   a2, a15, XT_CP_CS_ST            /* a2 = mask of CPs saved    */

-    bnone   a2,  a0, .L_xt_coproc_done      /* if no match then done     */

-    and     a2,  a2, a0                     /* a2 = which CPs to restore */

-    extui   a2,  a2, 0, 8                   /* extract low 8 bits        */

-    s32i    a6,  sp, XT_STK_A6              /* save extra needed regs    */

-    s32i    a7,  sp, XT_STK_A7

-    s32i    a13, sp, XT_STK_A13

-    s32i    a14, sp, XT_STK_A14

-    call0   _xt_coproc_restorecs            /* restore CP registers      */

-    l32i    a6,  sp, XT_STK_A6              /* restore saved registers   */

-    l32i    a7,  sp, XT_STK_A7

-    l32i    a13, sp, XT_STK_A13

-    l32i    a14, sp, XT_STK_A14

-    j       .L_xt_coproc_done

-

-    /* Co-processor exception occurred outside a thread (not supported). */

-.L_xt_coproc_invalid:

-    movi    a0,PANIC_RSN_COPROCEXCEPTION

-    wsr     a0,EXCCAUSE

-    call0   _xt_panic                       /* not in a thread (invalid) */

-    /* never returns */

-

-

-#endif /* XCHAL_CP_NUM */

-

-

-/*

--------------------------------------------------------------------------------

-  Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet.

--------------------------------------------------------------------------------

-*/

-

-    .section .iram1,"ax"

-    .type       _xt_lowint1,@function

-    .align      4

-

-_xt_lowint1:

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    rsr     a0, PS                          /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_1                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    movi    a0, _xt_user_exit               /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    /* EXCSAVE_1 should now be free to use. Use it to keep a copy of the

-    current stack pointer that points to the exception frame (XT_STK_FRAME).*/

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    mov     a0, sp

-    wsr     a0, EXCSAVE_1

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-

-    /* Save rest of interrupt context and enter RTOS. */

-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */

-

-    /* !! We are now on the RTOS system stack !! */ 

-

-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(1) | PS_UM

-    #else 

-    movi    a0, PS_INTLEVEL(1) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-    rsync

-

-    /* OK to call C code at this point, dispatch user ISRs */

-

-    dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK

-

-    /* Done handling interrupts, transfer control to OS */

-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */

-

-

-/*

--------------------------------------------------------------------------------

-  MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS.

-

-  Medium priority interrupts are by definition those with priority greater

-  than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by

-  setting PS.EXCM and therefore can easily support a C environment for

-  handlers in C, and interact safely with an RTOS.

-

-  Each vector goes at a predetermined location according to the Xtensa

-  hardware configuration, which is ensured by its placement in a special

-  section known to the Xtensa linker support package (LSP). It performs

-  the minimum necessary before jumping to the handler in the .text section.

-

-  The corresponding handler goes in the normal .text section. It sets up

-  the appropriate stack frame, saves a few vector-specific registers and

-  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context

-  and enter the RTOS, then sets up a C environment. It then calls the

-  user's interrupt handler code (which may be coded in C) and finally 

-  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.

-

-  While XT_RTOS_INT_EXIT does not return directly to the interruptee,

-  eventually the RTOS scheduler will want to dispatch the interrupted

-  task or handler. The scheduler will return to the exit point that was

-  saved in the interrupt stack frame at XT_STK_EXIT.

--------------------------------------------------------------------------------

-*/

-

-#if XCHAL_EXCM_LEVEL >= 2

-

-    .begin      literal_prefix .Level2InterruptVector

-    .section    .Level2InterruptVector.text, "ax"

-    .global     _Level2Vector

-    .type       _Level2Vector,@function

-    .align      4

-_Level2Vector:

-    wsr     a0, EXCSAVE_2                   /* preserve a0 */

-    call0   _xt_medint2                     /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-    .section .iram1,"ax"

-    .type       _xt_medint2,@function

-    .align      4

-_xt_medint2:

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    rsr     a0, EPS_2                       /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_2                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_2                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    movi    a0, _xt_medint2_exit            /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    /* EXCSAVE_2 should now be free to use. Use it to keep a copy of the

-    current stack pointer that points to the exception frame (XT_STK_FRAME).*/

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    mov     a0, sp

-    wsr     a0, EXCSAVE_2

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-

-    /* Save rest of interrupt context and enter RTOS. */

-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */

-

-    /* !! We are now on the RTOS system stack !! */

-

-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(2) | PS_UM

-    #else

-    movi    a0, PS_INTLEVEL(2) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-    rsync

-

-    /* OK to call C code at this point, dispatch user ISRs */

-

-    dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK

-

-    /* Done handling interrupts, transfer control to OS */

-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */

-

-    /*

-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT

-    on entry and used to return to a thread or interrupted interrupt handler.

-    */

-    .global     _xt_medint2_exit

-    .type       _xt_medint2_exit,@function

-    .align      4

-_xt_medint2_exit:

-    /* Restore only level-specific regs (the rest were already restored) */

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, EPS_2

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_2

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */

-    rsync                                   /* ensure EPS and EPC written */

-    rfi     2

-

-#endif  /* Level 2 */

-

-#if XCHAL_EXCM_LEVEL >= 3

-

-    .begin      literal_prefix .Level3InterruptVector

-    .section    .Level3InterruptVector.text, "ax"

-    .global     _Level3Vector

-    .type       _Level3Vector,@function

-    .align      4

-_Level3Vector:

-    wsr     a0, EXCSAVE_3                   /* preserve a0 */

-    call0   _xt_medint3                     /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-    .section .iram1,"ax"

-    .type       _xt_medint3,@function

-    .align      4

-_xt_medint3:

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    rsr     a0, EPS_3                       /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_3                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_3                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    movi    a0, _xt_medint3_exit            /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    /* EXCSAVE_3 should now be free to use. Use it to keep a copy of the

-    current stack pointer that points to the exception frame (XT_STK_FRAME).*/

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    mov     a0, sp

-    wsr     a0, EXCSAVE_3

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-

-    /* Save rest of interrupt context and enter RTOS. */

-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */

-

-    /* !! We are now on the RTOS system stack !! */

-

-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(3) | PS_UM

-    #else

-    movi    a0, PS_INTLEVEL(3) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-    rsync

-

-    /* OK to call C code at this point, dispatch user ISRs */

-

-    dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK

-

-    /* Done handling interrupts, transfer control to OS */

-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */

-

-    /*

-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT

-    on entry and used to return to a thread or interrupted interrupt handler.

-    */

-    .global     _xt_medint3_exit

-    .type       _xt_medint3_exit,@function

-    .align      4

-_xt_medint3_exit:

-    /* Restore only level-specific regs (the rest were already restored) */

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, EPS_3

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_3

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */

-    rsync                                   /* ensure EPS and EPC written */

-    rfi     3

-

-#endif  /* Level 3 */

-

-#if XCHAL_EXCM_LEVEL >= 4

-

-    .begin      literal_prefix .Level4InterruptVector

-    .section    .Level4InterruptVector.text, "ax"

-    .global     _Level4Vector

-    .type       _Level4Vector,@function

-    .align      4

-_Level4Vector:

-    wsr     a0, EXCSAVE_4                   /* preserve a0 */

-    call0   _xt_medint4                     /* load interrupt handler */

-

-    .end        literal_prefix

-

-    .section .iram1,"ax"

-    .type       _xt_medint4,@function

-    .align      4

-_xt_medint4:

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    rsr     a0, EPS_4                       /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_4                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_4                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    movi    a0, _xt_medint4_exit            /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    /* EXCSAVE_4 should now be free to use. Use it to keep a copy of the

-    current stack pointer that points to the exception frame (XT_STK_FRAME).*/

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    mov     a0, sp

-    wsr     a0, EXCSAVE_4

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-

-    /* Save rest of interrupt context and enter RTOS. */

-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */

-

-    /* !! We are now on the RTOS system stack !! */

-

-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(4) | PS_UM

-    #else

-    movi    a0, PS_INTLEVEL(4) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-    rsync

-

-    /* OK to call C code at this point, dispatch user ISRs */

-

-    dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK

-

-    /* Done handling interrupts, transfer control to OS */

-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */

-

-    /*

-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT

-    on entry and used to return to a thread or interrupted interrupt handler.

-    */

-    .global     _xt_medint4_exit

-    .type       _xt_medint4_exit,@function

-    .align      4

-_xt_medint4_exit:

-    /* Restore only level-specific regs (the rest were already restored) */

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, EPS_4

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_4

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */

-    rsync                                   /* ensure EPS and EPC written */

-    rfi     4

-

-#endif  /* Level 4 */

-

-#if XCHAL_EXCM_LEVEL >= 5

-

-    .begin      literal_prefix .Level5InterruptVector

-    .section    .Level5InterruptVector.text, "ax"

-    .global     _Level5Vector

-    .type       _Level5Vector,@function

-    .align      4

-_Level5Vector:

-    wsr     a0, EXCSAVE_5                   /* preserve a0 */

-    call0   _xt_medint5                     /* load interrupt handler */

-

-    .end        literal_prefix

-

-    .section .iram1,"ax"

-    .type       _xt_medint5,@function

-    .align      4

-_xt_medint5:

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    rsr     a0, EPS_5                       /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_5                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_5                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    movi    a0, _xt_medint5_exit            /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    /* EXCSAVE_5 should now be free to use. Use it to keep a copy of the

-    current stack pointer that points to the exception frame (XT_STK_FRAME).*/

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    mov     a0, sp

-    wsr     a0, EXCSAVE_5

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    /* Save rest of interrupt context and enter RTOS. */

-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */

-

-    /* !! We are now on the RTOS system stack !! */

-

-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(5) | PS_UM

-    #else

-    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-    rsync

-

-    /* OK to call C code at this point, dispatch user ISRs */

-

-    dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK

-

-    /* Done handling interrupts, transfer control to OS */

-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */

-

-    /*

-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT

-    on entry and used to return to a thread or interrupted interrupt handler.

-    */

-    .global     _xt_medint5_exit

-    .type       _xt_medint5_exit,@function

-    .align      4

-_xt_medint5_exit:

-    /* Restore only level-specific regs (the rest were already restored) */

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, EPS_5

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_5

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */

-    rsync                                   /* ensure EPS and EPC written */

-    rfi     5

-

-#endif  /* Level 5 */

-

-#if XCHAL_EXCM_LEVEL >= 6

-

-    .begin      literal_prefix .Level6InterruptVector

-    .section    .Level6InterruptVector.text, "ax"

-    .global     _Level6Vector

-    .type       _Level6Vector,@function

-    .align      4

-_Level6Vector:

-    wsr     a0, EXCSAVE_6                   /* preserve a0 */

-    call0   _xt_medint6                     /* load interrupt handler */

-

-    .end        literal_prefix

-

-    .section .iram1,"ax"

-    .type       _xt_medint6,@function

-    .align      4

-_xt_medint6:

-    mov     a0, sp                          /* sp == a1 */

-    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */

-    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */

-    rsr     a0, EPS_6                       /* save interruptee's PS */

-    s32i    a0, sp, XT_STK_PS

-    rsr     a0, EPC_6                       /* save interruptee's PC */

-    s32i    a0, sp, XT_STK_PC

-    rsr     a0, EXCSAVE_6                   /* save interruptee's a0 */

-    s32i    a0, sp, XT_STK_A0

-    movi    a0, _xt_medint6_exit            /* save exit point for dispatch */

-    s32i    a0, sp, XT_STK_EXIT

-

-    /* EXCSAVE_6 should now be free to use. Use it to keep a copy of the

-    current stack pointer that points to the exception frame (XT_STK_FRAME).*/

-    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))

-    #ifdef XT_DEBUG_BACKTRACE

-    #ifndef __XTENSA_CALL0_ABI__

-    mov     a0, sp

-    wsr     a0, EXCSAVE_6

-    #endif

-    #endif

-    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */

-

-    /* Save rest of interrupt context and enter RTOS. */

-    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */

-

-    /* !! We are now on the RTOS system stack !! */

-

-    /* Set up PS for C, enable interrupts above this level and clear EXCM. */

-    #ifdef __XTENSA_CALL0_ABI__

-    movi    a0, PS_INTLEVEL(6) | PS_UM

-    #else

-    movi    a0, PS_INTLEVEL(6) | PS_UM | PS_WOE

-    #endif

-    wsr     a0, PS

-    rsync

-

-    /* OK to call C code at this point, dispatch user ISRs */

-

-    dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK

-

-    /* Done handling interrupts, transfer control to OS */

-    call0   XT_RTOS_INT_EXIT                /* does not return directly here */

-

-    /*

-    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT

-    on entry and used to return to a thread or interrupted interrupt handler.

-    */

-    .global     _xt_medint6_exit

-    .type       _xt_medint6_exit,@function

-    .align      4

-_xt_medint6_exit:

-    /* Restore only level-specific regs (the rest were already restored) */

-    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */

-    wsr     a0, EPS_6

-    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */

-    wsr     a0, EPC_6

-    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */

-    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */

-    rsync                                   /* ensure EPS and EPC written */

-    rfi     6

-

-#endif  /* Level 6 */

-

-

-/*******************************************************************************

-

-HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS

-

-High priority interrupts are by definition those with priorities greater

-than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority

-interrupts cannot interact with the RTOS, that is they must save all regs

-they use and not call any RTOS function.

-

-A further restriction imposed by the Xtensa windowed architecture is that

-high priority interrupts must not modify the stack area even logically

-"above" the top of the interrupted stack (they need to provide their

-own stack or static save area).

-

-Cadence Design Systems recommends high priority interrupt handlers be coded in assembly

-and used for purposes requiring very short service times.

-

-Here are templates for high priority (level 2+) interrupt vectors.

-They assume only one interrupt per level to avoid the burden of identifying

-which interrupts at this level are pending and enabled. This allows for 

-minimum latency and avoids having to save/restore a2 in addition to a0.

-If more than one interrupt per high priority level is configured, this burden

-is on the handler which in any case must provide a way to save and restore

-registers it uses without touching the interrupted stack.

-

-Each vector goes at a predetermined location according to the Xtensa

-hardware configuration, which is ensured by its placement in a special

-section known to the Xtensa linker support package (LSP). It performs

-the minimum necessary before jumping to the handler in the .text section.

-

-*******************************************************************************/

-

-/*

-These stubs just call xt_highintX/xt_nmi to handle the real interrupt. Please define

-these in an external assembly source file. If these symbols are not defined anywhere

-else, the defaults in xtensa_vector_defaults.S are used.

-*/

-

-#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2

-

-    .begin      literal_prefix .Level2InterruptVector

-    .section    .Level2InterruptVector.text, "ax"

-    .global     _Level2Vector

-    .type       _Level2Vector,@function

-    .global     xt_highint2

-    .align      4

-_Level2Vector:

-    wsr     a0, EXCSAVE_2                   /* preserve a0 */

-    call0   xt_highint2                    /* load interrupt handler */

-

-    .end        literal_prefix

-

-#endif  /* Level 2 */

-

-#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3

-

-    .begin      literal_prefix .Level3InterruptVector

-    .section    .Level3InterruptVector.text, "ax"

-    .global     _Level3Vector

-    .type       _Level3Vector,@function

-    .global     xt_highint3

-    .align      4

-_Level3Vector:

-    wsr     a0, EXCSAVE_3                   /* preserve a0 */

-    call0   xt_highint3                    /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-#endif  /* Level 3 */

-

-#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4

-

-    .begin      literal_prefix .Level4InterruptVector

-    .section    .Level4InterruptVector.text, "ax"

-    .global     _Level4Vector

-    .type       _Level4Vector,@function

-    .global     xt_highint4

-    .align      4

-_Level4Vector:

-    wsr     a0, EXCSAVE_4                   /* preserve a0 */

-    call0   xt_highint4                    /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-#endif  /* Level 4 */

-

-#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5

-

-    .begin      literal_prefix .Level5InterruptVector

-    .section    .Level5InterruptVector.text, "ax"

-    .global     _Level5Vector

-    .type       _Level5Vector,@function

-    .global     xt_highint5

-    .align      4

-_Level5Vector:

-    wsr     a0, EXCSAVE_5                   /* preserve a0 */

-    call0   xt_highint5                    /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-#endif  /* Level 5 */

-

-#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6

-

-    .begin      literal_prefix .Level6InterruptVector

-    .section    .Level6InterruptVector.text, "ax"

-    .global     _Level6Vector

-    .type       _Level6Vector,@function

-    .global     xt_highint6

-    .align      4

-_Level6Vector:

-    wsr     a0, EXCSAVE_6                   /* preserve a0 */

-    call0   xt_highint6                    /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-#endif  /* Level 6 */

-

-#if XCHAL_HAVE_NMI

-

-    .begin      literal_prefix .NMIExceptionVector

-    .section    .NMIExceptionVector.text, "ax"

-    .global     _NMIExceptionVector

-    .type       _NMIExceptionVector,@function

-    .global     xt_nmi

-    .align      4

-_NMIExceptionVector:

-    wsr     a0, EXCSAVE + XCHAL_NMILEVEL  _ /* preserve a0 */

-    call0   xt_nmi                         /* load interrupt handler */

-    /* never returns here - call0 is used as a jump (see note at top) */

-

-    .end        literal_prefix

-

-#endif  /* NMI */

-

-

-/*******************************************************************************

-

-WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER

-

-Here is the code for each window overflow/underflow exception vector and 

-(interspersed) efficient code for handling the alloca exception cause.

-Window exceptions are handled entirely in the vector area and are very

-tight for performance. The alloca exception is also handled entirely in 

-the window vector area so comes at essentially no cost in code size.

-Users should never need to modify them and Cadence Design Systems recommends 

-they do not.

-

-Window handlers go at predetermined vector locations according to the

-Xtensa hardware configuration, which is ensured by their placement in a

-special section known to the Xtensa linker support package (LSP). Since

-their offsets in that section are always the same, the LSPs do not define

-a section per vector.

-

-These things are coded for XEA2 only (XEA1 is not supported).

-

-Note on Underflow Handlers:

-The underflow handler for returning from call[i+1] to call[i]

-must preserve all the registers from call[i+1]'s window.

-In particular, a0 and a1 must be preserved because the RETW instruction

-will be reexecuted (and may even underflow if an intervening exception

-has flushed call[i]'s registers).

-Registers a2 and up may contain return values.

-

-*******************************************************************************/

-

-#if XCHAL_HAVE_WINDOWED

-

-    .section .WindowVectors.text, "ax"

-

-/*

---------------------------------------------------------------------------------

-Window Overflow Exception for Call4.

-

-Invoked if a call[i] referenced a register (a4-a15)

-that contains data from ancestor call[j];

-call[j] had done a call4 to call[j+1].

-On entry here:

-    window rotated to call[j] start point;

-        a0-a3 are registers to be saved;

-        a4-a15 must be preserved;

-        a5 is call[j+1]'s stack pointer.

---------------------------------------------------------------------------------

-*/

-

-    .org    0x0

-    .global _WindowOverflow4

-_WindowOverflow4:

-

-    s32e    a0, a5, -16     /* save a0 to call[j+1]'s stack frame */

-    s32e    a1, a5, -12     /* save a1 to call[j+1]'s stack frame */

-    s32e    a2, a5,  -8     /* save a2 to call[j+1]'s stack frame */

-    s32e    a3, a5,  -4     /* save a3 to call[j+1]'s stack frame */

-    rfwo                    /* rotates back to call[i] position */

-

-/*

---------------------------------------------------------------------------------

-Window Underflow Exception for Call4

-

-Invoked by RETW returning from call[i+1] to call[i]

-where call[i]'s registers must be reloaded (not live in ARs);

-where call[i] had done a call4 to call[i+1].

-On entry here:

-        window rotated to call[i] start point;

-        a0-a3 are undefined, must be reloaded with call[i].reg[0..3];

-        a4-a15 must be preserved (they are call[i+1].reg[0..11]);

-        a5 is call[i+1]'s stack pointer.

---------------------------------------------------------------------------------

-*/

-

-    .org    0x40

-    .global _WindowUnderflow4

-_WindowUnderflow4:

-

-    l32e    a0, a5, -16     /* restore a0 from call[i+1]'s stack frame */

-    l32e    a1, a5, -12     /* restore a1 from call[i+1]'s stack frame */

-    l32e    a2, a5,  -8     /* restore a2 from call[i+1]'s stack frame */

-    l32e    a3, a5,  -4     /* restore a3 from call[i+1]'s stack frame */

-    rfwu

-

-/*

---------------------------------------------------------------------------------

-Handle alloca exception generated by interruptee executing 'movsp'.

-This uses space between the window vectors, so is essentially "free".

-All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,

-and PS.EXCM has been set by the exception hardware (can't be interrupted).

-The fact the alloca exception was taken means the registers associated with

-the base-save area have been spilled and will be restored by the underflow

-handler, so those 4 registers are available for scratch.

-The code is optimized to avoid unaligned branches and minimize cache misses.

---------------------------------------------------------------------------------

-*/

-

-    .align  4

-    .global _xt_alloca_exc

-_xt_alloca_exc:

-

-    rsr     a0, WINDOWBASE  /* grab WINDOWBASE before rotw changes it */

-    rotw    -1              /* WINDOWBASE goes to a4, new a0-a3 are scratch */

-    rsr     a2, PS

-    extui   a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS

-    xor     a3, a3, a4      /* bits changed from old to current windowbase */

-    rsr     a4, EXCSAVE_1   /* restore original a0 (now in a4) */

-    slli    a3, a3, XCHAL_PS_OWB_SHIFT

-    xor     a2, a2, a3      /* flip changed bits in old window base */

-    wsr     a2, PS          /* update PS.OWB to new window base */

-    rsync

-

-    _bbci.l a4, 31, _WindowUnderflow4

-    rotw    -1              /* original a0 goes to a8 */

-    _bbci.l a8, 30, _WindowUnderflow8

-    rotw    -1

-    j               _WindowUnderflow12

-

-/*

---------------------------------------------------------------------------------

-Window Overflow Exception for Call8

-

-Invoked if a call[i] referenced a register (a4-a15)

-that contains data from ancestor call[j];

-call[j] had done a call8 to call[j+1].

-On entry here:

-    window rotated to call[j] start point;

-        a0-a7 are registers to be saved;

-        a8-a15 must be preserved;

-        a9 is call[j+1]'s stack pointer.

---------------------------------------------------------------------------------

-*/

-

-    .org    0x80

-    .global _WindowOverflow8

-_WindowOverflow8:

-

-    s32e    a0, a9, -16     /* save a0 to call[j+1]'s stack frame */

-    l32e    a0, a1, -12     /* a0 <- call[j-1]'s sp

-                               (used to find end of call[j]'s frame) */

-    s32e    a1, a9, -12     /* save a1 to call[j+1]'s stack frame */

-    s32e    a2, a9,  -8     /* save a2 to call[j+1]'s stack frame */

-    s32e    a3, a9,  -4     /* save a3 to call[j+1]'s stack frame */

-    s32e    a4, a0, -32     /* save a4 to call[j]'s stack frame */

-    s32e    a5, a0, -28     /* save a5 to call[j]'s stack frame */

-    s32e    a6, a0, -24     /* save a6 to call[j]'s stack frame */

-    s32e    a7, a0, -20     /* save a7 to call[j]'s stack frame */

-    rfwo                    /* rotates back to call[i] position */

-

-/*

---------------------------------------------------------------------------------

-Window Underflow Exception for Call8

-

-Invoked by RETW returning from call[i+1] to call[i]

-where call[i]'s registers must be reloaded (not live in ARs);

-where call[i] had done a call8 to call[i+1].

-On entry here:

-        window rotated to call[i] start point;

-        a0-a7 are undefined, must be reloaded with call[i].reg[0..7];

-        a8-a15 must be preserved (they are call[i+1].reg[0..7]);

-        a9 is call[i+1]'s stack pointer.

---------------------------------------------------------------------------------

-*/

-

-    .org    0xC0

-    .global _WindowUnderflow8

-_WindowUnderflow8:

-

-    l32e    a0, a9, -16     /* restore a0 from call[i+1]'s stack frame */

-    l32e    a1, a9, -12     /* restore a1 from call[i+1]'s stack frame */

-    l32e    a2, a9,  -8     /* restore a2 from call[i+1]'s stack frame */

-    l32e    a7, a1, -12     /* a7 <- call[i-1]'s sp

-                               (used to find end of call[i]'s frame) */

-    l32e    a3, a9,  -4     /* restore a3 from call[i+1]'s stack frame */

-    l32e    a4, a7, -32     /* restore a4 from call[i]'s stack frame */

-    l32e    a5, a7, -28     /* restore a5 from call[i]'s stack frame */

-    l32e    a6, a7, -24     /* restore a6 from call[i]'s stack frame */

-    l32e    a7, a7, -20     /* restore a7 from call[i]'s stack frame */

-    rfwu

-

-/*

---------------------------------------------------------------------------------

-Window Overflow Exception for Call12

-

-Invoked if a call[i] referenced a register (a4-a15)

-that contains data from ancestor call[j];

-call[j] had done a call12 to call[j+1].

-On entry here:

-    window rotated to call[j] start point;

-        a0-a11 are registers to be saved;

-        a12-a15 must be preserved;

-        a13 is call[j+1]'s stack pointer.

---------------------------------------------------------------------------------

-*/

-

-    .org    0x100

-    .global _WindowOverflow12

-_WindowOverflow12:

-

-    s32e    a0,  a13, -16   /* save a0 to call[j+1]'s stack frame */

-    l32e    a0,  a1,  -12   /* a0 <- call[j-1]'s sp

-                               (used to find end of call[j]'s frame) */

-    s32e    a1,  a13, -12   /* save a1 to call[j+1]'s stack frame */

-    s32e    a2,  a13,  -8   /* save a2 to call[j+1]'s stack frame */

-    s32e    a3,  a13,  -4   /* save a3 to call[j+1]'s stack frame */

-    s32e    a4,  a0,  -48   /* save a4 to end of call[j]'s stack frame */

-    s32e    a5,  a0,  -44   /* save a5 to end of call[j]'s stack frame */

-    s32e    a6,  a0,  -40   /* save a6 to end of call[j]'s stack frame */

-    s32e    a7,  a0,  -36   /* save a7 to end of call[j]'s stack frame */

-    s32e    a8,  a0,  -32   /* save a8 to end of call[j]'s stack frame */

-    s32e    a9,  a0,  -28   /* save a9 to end of call[j]'s stack frame */

-    s32e    a10, a0,  -24   /* save a10 to end of call[j]'s stack frame */

-    s32e    a11, a0,  -20   /* save a11 to end of call[j]'s stack frame */

-    rfwo                    /* rotates back to call[i] position */

-

-/*

---------------------------------------------------------------------------------

-Window Underflow Exception for Call12

-

-Invoked by RETW returning from call[i+1] to call[i]

-where call[i]'s registers must be reloaded (not live in ARs);

-where call[i] had done a call12 to call[i+1].

-On entry here:

-        window rotated to call[i] start point;

-        a0-a11 are undefined, must be reloaded with call[i].reg[0..11];

-        a12-a15 must be preserved (they are call[i+1].reg[0..3]);

-        a13 is call[i+1]'s stack pointer.

---------------------------------------------------------------------------------

-*/

-

-    .org 0x140

-    .global _WindowUnderflow12

-_WindowUnderflow12:

-

-    l32e    a0,  a13, -16   /* restore a0 from call[i+1]'s stack frame */

-    l32e    a1,  a13, -12   /* restore a1 from call[i+1]'s stack frame */

-    l32e    a2,  a13,  -8   /* restore a2 from call[i+1]'s stack frame */

-    l32e    a11, a1,  -12   /* a11 <- call[i-1]'s sp

-                               (used to find end of call[i]'s frame) */

-    l32e    a3,  a13,  -4   /* restore a3 from call[i+1]'s stack frame */

-    l32e    a4,  a11, -48   /* restore a4 from end of call[i]'s stack frame */

-    l32e    a5,  a11, -44   /* restore a5 from end of call[i]'s stack frame */

-    l32e    a6,  a11, -40   /* restore a6 from end of call[i]'s stack frame */

-    l32e    a7,  a11, -36   /* restore a7 from end of call[i]'s stack frame */

-    l32e    a8,  a11, -32   /* restore a8 from end of call[i]'s stack frame */

-    l32e    a9,  a11, -28   /* restore a9 from end of call[i]'s stack frame */

-    l32e    a10, a11, -24   /* restore a10 from end of call[i]'s stack frame */

-    l32e    a11, a11, -20   /* restore a11 from end of call[i]'s stack frame */

-    rfwu

-

-#endif /* XCHAL_HAVE_WINDOWED */

-

-    .section    .UserEnter.text, "ax"

-    .global     call_user_start

-    .type       call_user_start,@function

-    .align      4

-    .literal_position

-

-

-

+/*******************************************************************************
+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 VECTORS AND LOW LEVEL HANDLERS FOR AN RTOS
+
+  Xtensa low level exception and interrupt vectors and handlers for an RTOS.
+
+  Interrupt handlers and user exception handlers support interaction with
+  the RTOS by calling XT_RTOS_INT_ENTER and XT_RTOS_INT_EXIT before and
+  after user's specific interrupt handlers. These macros are defined in
+  xtensa_<rtos>.h to call suitable functions in a specific RTOS.
+
+  Users can install application-specific interrupt handlers for low and
+  medium level interrupts, by calling xt_set_interrupt_handler(). These
+  handlers can be written in C, and must obey C calling convention. The
+  handler table is indexed by the interrupt number. Each handler may be
+  provided with an argument. 
+
+  Note that the system timer interrupt is handled specially, and is
+  dispatched to the RTOS-specific handler. This timer cannot be hooked
+  by application code.
+
+  Optional hooks are also provided to install a handler per level at 
+  run-time, made available by compiling this source file with 
+  '-DXT_INTEXC_HOOKS' (useful for automated testing).
+
+!!  This file is a template that usually needs to be modified to handle       !!
+!!  application specific interrupts. Search USER_EDIT for helpful comments    !!
+!!  on where to insert handlers and how to write them.                        !!
+
+  Users can also install application-specific exception handlers in the
+  same way, by calling xt_set_exception_handler(). One handler slot is
+  provided for each exception type. Note that some exceptions are handled
+  by the porting layer itself, and cannot be taken over by application
+  code in this manner. These are the alloca, syscall, and coprocessor
+  exceptions.
+
+  The exception handlers can be written in C, and must follow C calling
+  convention. Each handler is passed a pointer to an exception frame as
+  its single argument. The exception frame is created on the stack, and
+  holds the saved context of the thread that took the exception. If the
+  handler returns, the context will be restored and the instruction that
+  caused the exception will be retried. If the handler makes any changes
+  to the saved state in the exception frame, the changes will be applied
+  when restoring the context.
+
+  Because Xtensa is a configurable architecture, this port supports all user
+  generated configurations (except restrictions stated in the release notes).
+  This is accomplished by conditional compilation using macros and functions
+  defined in the Xtensa HAL (hardware adaptation layer) for your configuration.
+  Only the relevant parts of this file will be included in your RTOS build.
+  For example, this file provides interrupt vector templates for all types and
+  all priority levels, but only the ones in your configuration are built.
+
+  NOTES on the use of 'call0' for long jumps instead of 'j':
+   1. This file should be assembled with the -mlongcalls option to xt-xcc.
+   2. The -mlongcalls compiler option causes 'call0 dest' to be expanded to
+      a sequence 'l32r a0, dest' 'callx0 a0' which works regardless of the
+      distance from the call to the destination. The linker then relaxes
+      it back to 'call0 dest' if it determines that dest is within range.
+      This allows more flexibility in locating code without the performance
+      overhead of the 'l32r' literal data load in cases where the destination
+      is in range of 'call0'. There is an additional benefit in that 'call0'
+      has a longer range than 'j' due to the target being word-aligned, so 
+      the 'l32r' sequence is less likely needed.
+   3. The use of 'call0' with -mlongcalls requires that register a0 not be 
+      live at the time of the call, which is always the case for a function 
+      call but needs to be ensured if 'call0' is used as a jump in lieu of 'j'.
+   4. This use of 'call0' is independent of the C function call ABI.
+
+*******************************************************************************/
+
+#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"
+
+/*
+  Define for workaround: pin no-cpu-affinity tasks to a cpu when fpu is used.
+  Please change this when the tcb structure is changed
+*/
+#define TASKTCB_XCOREID_OFFSET (0x38+configMAX_TASK_NAME_LEN+3)&~3
+.extern pxCurrentTCB
+
+/*
+--------------------------------------------------------------------------------
+    In order for backtracing to be able to trace from the pre-exception stack
+    across to the exception stack (including nested interrupts), we need to create
+    a pseudo base-save area to make it appear like the exception dispatcher was
+    triggered by a CALL4 from the pre-exception code. In reality, the exception
+    dispatcher uses the same window as pre-exception code, and only CALL0s are
+    used within the exception dispatcher.
+
+    To create the pseudo base-save area, we need to store a copy of the pre-exception's
+    base save area (a0 to a4) below the exception dispatcher's SP. EXCSAVE_x will
+    be used to store a copy of the SP that points to the interrupted code's exception
+    frame just in case the exception dispatcher's SP does not point to the exception
+    frame (which is the case when switching from task to interrupt stack).
+
+    Clearing the pseudo base-save area is uncessary as the interrupt dispatcher
+    will restore the current SP to that of the pre-exception SP.
+--------------------------------------------------------------------------------
+*/
+#ifdef CONFIG_FREERTOS_INTERRUPT_BACKTRACE
+#define XT_DEBUG_BACKTRACE    1
+#endif
+
+
+/*
+--------------------------------------------------------------------------------
+  Defines used to access _xtos_interrupt_table.
+--------------------------------------------------------------------------------
+*/
+#define XIE_HANDLER     0
+#define XIE_ARG         4
+#define XIE_SIZE        8
+
+
+/*
+  Macro get_percpu_entry_for - convert a per-core ID into a multicore entry.
+  Basically does reg=reg*portNUM_PROCESSORS+current_core_id
+  Multiple versions here to optimize for specific portNUM_PROCESSORS values.
+*/
+    .macro get_percpu_entry_for reg scratch
+#if (portNUM_PROCESSORS == 1)
+    /* No need to do anything */
+#elif  (portNUM_PROCESSORS == 2)
+    /* Optimized 2-core code. */
+    getcoreid \scratch
+    addx2 \reg,\reg,\scratch
+#else
+    /* Generalized n-core code. Untested! */
+    movi \scratch,portNUM_PROCESSORS
+    mull \scratch,\reg,\scratch
+    getcoreid \reg
+    add \reg,\scratch,\reg
+#endif
+   .endm
+/*
+--------------------------------------------------------------------------------
+  Macro extract_msb - return the input with only the highest bit set.
+
+  Input  : "ain"  - Input value, clobbered.
+  Output : "aout" - Output value, has only one bit set, MSB of "ain".
+  The two arguments must be different AR registers.
+--------------------------------------------------------------------------------
+*/
+
+    .macro  extract_msb     aout ain
+1:
+    addi    \aout, \ain, -1         /* aout = ain - 1        */
+    and     \ain, \ain, \aout       /* ain  = ain & aout     */
+    bnez    \ain, 1b                /* repeat until ain == 0 */
+    addi    \aout, \aout, 1         /* return aout + 1       */
+    .endm
+
+/*
+--------------------------------------------------------------------------------
+  Macro dispatch_c_isr - dispatch interrupts to user ISRs.
+  This will dispatch to user handlers (if any) that are registered in the
+  XTOS dispatch table (_xtos_interrupt_table). These handlers would have
+  been registered by calling _xtos_set_interrupt_handler(). There is one
+  exception - the timer interrupt used by the OS will not be dispatched
+  to a user handler - this must be handled by the caller of this macro.
+
+  Level triggered and software interrupts are automatically deasserted by
+  this code.
+
+  ASSUMPTIONS:
+    -- PS.INTLEVEL is set to "level" at entry
+    -- PS.EXCM = 0, C calling enabled
+
+  NOTE: For CALL0 ABI, a12-a15 have not yet been saved.
+
+  NOTE: This macro will use registers a0 and a2-a7. The arguments are:
+    level -- interrupt level
+    mask  -- interrupt bitmask for this level
+--------------------------------------------------------------------------------
+*/
+
+    .macro  dispatch_c_isr    level  mask
+
+    #ifdef CONFIG_PM_TRACE
+    movi a6, 0 /* = ESP_PM_TRACE_IDLE */
+    getcoreid a7
+    call4 esp_pm_trace_exit
+    #endif // CONFIG_PM_TRACE
+
+    /* Get mask of pending, enabled interrupts at this level into a2. */
+
+.L_xt_user_int_&level&:
+    rsr     a2, INTENABLE
+    rsr     a3, INTERRUPT
+    movi    a4, \mask
+    and     a2, a2, a3
+    and     a2, a2, a4
+    beqz    a2, 9f                          /* nothing to do */
+
+    /* This bit of code provides a nice debug backtrace in the debugger.
+       It does take a few more instructions, so undef XT_DEBUG_BACKTRACE
+       if you want to save the cycles.
+       At this point, the exception frame should have been allocated and filled,
+       and current sp points to the interrupt stack (for non-nested interrupt)
+       or below the allocated exception frame (for nested interrupts). Copy the
+       pre-exception's base save area below the current SP.
+    */
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    rsr     a0, EXCSAVE_1 + \level - 1      /* Get exception frame pointer stored in EXCSAVE_x */
+    l32i    a3, a0, XT_STK_A0               /* Copy pre-exception a0 (return address) */
+    s32e    a3, a1, -16
+    l32i    a3, a0, XT_STK_A1               /* Copy pre-exception a1 (stack pointer) */
+    s32e    a3, a1, -12
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+    /* Backtracing only needs a0 and a1, no need to create full base save area.
+       Also need to change current frame's return address to point to pre-exception's
+       last run instruction.
+     */
+    rsr     a0, EPC_1 + \level - 1          /* return address */
+    movi    a4, 0xC0000000                  /* constant with top 2 bits set (call size) */
+    or      a0, a0, a4                      /* set top 2 bits */
+    addx2   a0, a4, a0                      /* clear top bit -- simulating call4 size   */
+    #endif
+    #endif
+
+    #ifdef CONFIG_PM_ENABLE
+    call4 esp_pm_impl_isr_hook
+    #endif
+
+    #ifdef XT_INTEXC_HOOKS
+    /* Call interrupt hook if present to (pre)handle interrupts. */
+    movi    a4, _xt_intexc_hooks
+    l32i    a4, a4, \level << 2
+    beqz    a4, 2f
+    #ifdef __XTENSA_CALL0_ABI__
+    callx0  a4
+    beqz    a2, 9f
+    #else
+    mov     a6, a2
+    callx4  a4
+    beqz    a6, 9f
+    mov     a2, a6
+    #endif
+2:
+    #endif
+
+    /* Now look up in the dispatch table and call user ISR if any. */
+    /* If multiple bits are set then MSB has highest priority.     */
+
+    extract_msb  a4, a2                     /* a4 = MSB of a2, a2 trashed */
+
+    #ifdef XT_USE_SWPRI
+    /* Enable all interrupts at this level that are numerically higher
+       than the one we just selected, since they are treated as higher
+       priority.
+    */
+    movi    a3, \mask                       /* a3 = all interrupts at this level */
+    add     a2, a4, a4                      /* a2 = a4 << 1 */
+    addi    a2, a2, -1                      /* a2 = mask of 1's <= a4 bit */
+    and     a2, a2, a3                      /* a2 = mask of all bits <= a4 at this level */
+    movi    a3, _xt_intdata
+    l32i    a6, a3, 4                       /* a6 = _xt_vpri_mask */
+    neg     a2, a2
+    addi    a2, a2, -1                      /* a2 = mask to apply */
+    and     a5, a6, a2                      /* mask off all bits <= a4 bit */
+    s32i    a5, a3, 4                       /* update _xt_vpri_mask */
+    rsr     a3, INTENABLE
+    and     a3, a3, a2                      /* mask off all bits <= a4 bit */
+    wsr     a3, INTENABLE
+    rsil    a3, \level - 1                  /* lower interrupt level by 1 */
+    #endif
+
+    movi    a3, XT_TIMER_INTEN              /* a3 = timer interrupt bit */
+    wsr     a4, INTCLEAR                    /* clear sw or edge-triggered interrupt */
+    beq     a3, a4, 7f                      /* if timer interrupt then skip table */
+
+    find_ms_setbit a3, a4, a3, 0            /* a3 = interrupt number */
+
+    get_percpu_entry_for a3, a12
+    movi    a4, _xt_interrupt_table
+    addx8   a3, a3, a4                      /* a3 = address of interrupt table entry */
+    l32i    a4, a3, XIE_HANDLER             /* a4 = handler address */
+    #ifdef __XTENSA_CALL0_ABI__
+    mov     a12, a6                         /* save in callee-saved reg */
+    l32i    a2, a3, XIE_ARG                 /* a2 = handler arg */
+    callx0  a4                              /* call handler */
+    mov     a2, a12
+    #else
+    mov     a2, a6                          /* save in windowed reg */
+    l32i    a6, a3, XIE_ARG                 /* a6 = handler arg */
+    callx4  a4                              /* call handler */
+    #endif
+
+    #ifdef XT_USE_SWPRI
+    j       8f
+    #else
+    j       .L_xt_user_int_&level&          /* check for more interrupts */
+    #endif
+
+7:
+
+    .ifeq XT_TIMER_INTPRI - \level
+.L_xt_user_int_timer_&level&:
+    /*
+    Interrupt handler for the RTOS tick timer if at this level.
+    We'll be reading the interrupt state again after this call
+    so no need to preserve any registers except a6 (vpri_mask).
+    */
+
+    #ifdef __XTENSA_CALL0_ABI__
+    mov     a12, a6
+    call0   XT_RTOS_TIMER_INT
+    mov     a2, a12
+    #else
+    mov     a2, a6
+    call4   XT_RTOS_TIMER_INT
+    #endif
+    .endif
+
+    #ifdef XT_USE_SWPRI
+    j       8f
+    #else
+    j       .L_xt_user_int_&level&          /* check for more interrupts */
+    #endif
+
+    #ifdef XT_USE_SWPRI
+8:
+    /* Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
+       virtual _xt_intenable which _could_ have changed during interrupt
+       processing. */
+
+    movi    a3, _xt_intdata
+    l32i    a4, a3, 0                       /* a4 = _xt_intenable    */
+    s32i    a2, a3, 4                       /* update _xt_vpri_mask  */
+    and     a4, a4, a2                      /* a4 = masked intenable */
+    wsr     a4, INTENABLE                   /* update INTENABLE      */
+    #endif
+
+9:
+    /* done */
+
+    .endm
+
+
+/*
+--------------------------------------------------------------------------------
+  Panic handler.
+  Should be reached by call0 (preferable) or jump only. If call0, a0 says where 
+  from. If on simulator, display panic message and abort, else loop indefinitely.
+--------------------------------------------------------------------------------
+*/
+
+    .section .iram1,"ax"
+    .global panicHandler
+
+    .global     _xt_panic
+    .type       _xt_panic,@function
+    .align      4
+    .literal_position
+    .align      4
+
+_xt_panic:
+    /* Allocate exception frame and save minimal context. */
+    mov     a0, sp
+    addi    sp, sp, -XT_STK_FRMSZ
+    s32i    a0, sp, XT_STK_A1
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -12                     /* for debug backtrace */
+    #endif
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -16                     /* for debug backtrace */
+    #endif
+    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
+    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
+    call0   _xt_context_save
+
+    /* Save exc cause and vaddr into exception frame */
+    rsr     a0, EXCCAUSE
+    s32i    a0, sp, XT_STK_EXCCAUSE
+    rsr     a0, EXCVADDR
+    s32i    a0, sp, XT_STK_EXCVADDR
+
+    /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+
+    s32i    a0, sp, XT_STK_A0
+
+    /* Set up PS for C, disable all interrupts except NMI and debug, and clear EXCM. */
+    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
+    wsr     a0, PS
+
+    //Call panic handler
+    mov     a6,sp
+    call4 panicHandler
+
+
+    .align 4
+//Call using call0. Prints the hex char in a2. Kills a3, a4, a5
+panic_print_hex:
+    movi a3,0x60000000
+    movi a4,8
+panic_print_hex_loop:
+    l32i a5, a3, 0x1c
+    extui a5, a5, 16, 8
+    bgei a5,64,panic_print_hex_loop
+
+    srli a5,a2,28
+    bgei a5,10,panic_print_hex_a
+    addi a5,a5,'0'
+    j panic_print_hex_ok
+panic_print_hex_a:
+    addi a5,a5,'A'-10
+panic_print_hex_ok:
+    s32i a5,a3,0
+    slli a2,a2,4
+    
+    addi a4,a4,-1
+    bnei a4,0,panic_print_hex_loop
+    movi a5,' '
+    s32i a5,a3,0
+
+    ret
+
+
+
+    .section    .rodata, "a"
+    .align      4
+
+
+
+/*
+--------------------------------------------------------------------------------
+    Hooks to dynamically install handlers for exceptions and interrupts.
+    Allows automated regression frameworks to install handlers per test.
+    Consists of an array of function pointers indexed by interrupt level, 
+    with index 0 containing the entry for user exceptions.
+    Initialized with all 0s, meaning no handler is installed at each level.
+    See comment in xtensa_rtos.h for more details.
+
+    *WARNING*  This array is for all CPUs, that is, installing a hook for 
+    one CPU will install it for all others as well!
+--------------------------------------------------------------------------------
+*/
+
+    #ifdef XT_INTEXC_HOOKS
+    .data
+    .global     _xt_intexc_hooks
+    .type       _xt_intexc_hooks,@object
+    .align      4
+
+_xt_intexc_hooks:
+    .fill       XT_INTEXC_HOOK_NUM, 4, 0
+    #endif
+
+
+/*
+--------------------------------------------------------------------------------
+  EXCEPTION AND LEVEL 1 INTERRUPT VECTORS AND LOW LEVEL HANDLERS
+  (except window exception vectors).
+
+  Each vector goes at a predetermined location according to the Xtensa
+  hardware configuration, which is ensured by its placement in a special
+  section known to the Xtensa linker support package (LSP). It performs
+  the minimum necessary before jumping to the handler in the .text section.
+
+  The corresponding handler goes in the normal .text section. It sets up
+  the appropriate stack frame, saves a few vector-specific registers and
+  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
+  and enter the RTOS, then sets up a C environment. It then calls the
+  user's interrupt handler code (which may be coded in C) and finally 
+  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
+
+  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
+  eventually the RTOS scheduler will want to dispatch the interrupted
+  task or handler. The scheduler will return to the exit point that was
+  saved in the interrupt stack frame at XT_STK_EXIT.
+--------------------------------------------------------------------------------
+*/
+
+
+/*
+--------------------------------------------------------------------------------
+Debug Exception.
+--------------------------------------------------------------------------------
+*/
+
+#if XCHAL_HAVE_DEBUG
+
+    .begin      literal_prefix .DebugExceptionVector
+    .section    .DebugExceptionVector.text, "ax"
+    .global     _DebugExceptionVector
+    .align      4
+    .global     xt_debugexception
+_DebugExceptionVector:
+    wsr     a0, EXCSAVE+XCHAL_DEBUGLEVEL    /* preserve a0 */
+    call0   xt_debugexception            /* load exception handler */
+
+    .end        literal_prefix
+
+#endif
+
+/*
+--------------------------------------------------------------------------------
+Double Exception.
+Double exceptions are not a normal occurrence. They indicate a bug of some kind.
+--------------------------------------------------------------------------------
+*/
+
+#ifdef XCHAL_DOUBLEEXC_VECTOR_VADDR
+
+    .begin      literal_prefix .DoubleExceptionVector
+    .section    .DoubleExceptionVector.text, "ax"
+    .global     _DoubleExceptionVector
+    .align      4
+
+_DoubleExceptionVector:
+
+    #if XCHAL_HAVE_DEBUG
+    break   1, 4                            /* unhandled double exception */
+    #endif
+    movi    a0,PANIC_RSN_DOUBLEEXCEPTION
+    wsr     a0,EXCCAUSE
+    call0   _xt_panic                       /* does not return */
+    rfde                                    /* make a0 point here not later */
+
+    .end        literal_prefix
+
+#endif /* XCHAL_DOUBLEEXC_VECTOR_VADDR */
+
+/*
+--------------------------------------------------------------------------------
+Kernel Exception (including Level 1 Interrupt from kernel mode).
+--------------------------------------------------------------------------------
+*/
+
+    .begin      literal_prefix .KernelExceptionVector
+    .section    .KernelExceptionVector.text, "ax"
+    .global     _KernelExceptionVector
+    .align      4
+
+_KernelExceptionVector:
+
+    wsr     a0, EXCSAVE_1                   /* preserve a0 */
+    call0   _xt_kernel_exc                  /* kernel exception handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .section .iram1,"ax"
+    .align      4
+
+_xt_kernel_exc:
+    #if XCHAL_HAVE_DEBUG
+    break   1, 0                            /* unhandled kernel exception */
+    #endif
+    movi    a0,PANIC_RSN_KERNELEXCEPTION
+    wsr     a0,EXCCAUSE
+    call0   _xt_panic                       /* does not return */
+    rfe                                     /* make a0 point here not there */
+
+
+/*
+--------------------------------------------------------------------------------
+User Exception (including Level 1 Interrupt from user mode).
+--------------------------------------------------------------------------------
+*/
+
+    .begin      literal_prefix .UserExceptionVector
+    .section    .UserExceptionVector.text, "ax"
+    .global     _UserExceptionVector
+    .type       _UserExceptionVector,@function
+    .align      4
+
+_UserExceptionVector:
+
+    wsr     a0, EXCSAVE_1                   /* preserve a0 */
+    call0   _xt_user_exc                    /* user exception handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+/*
+--------------------------------------------------------------------------------
+  Insert some waypoints for jumping beyond the signed 8-bit range of
+  conditional branch instructions, so the conditional branchces to specific
+  exception handlers are not taken in the mainline. Saves some cycles in the
+  mainline.
+--------------------------------------------------------------------------------
+*/
+
+#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
+    .global   LoadStoreErrorHandler
+    .global   AlignmentErrorHandler
+#endif
+
+    .section .iram1,"ax"
+
+    #if XCHAL_HAVE_WINDOWED
+    .align      4
+_xt_to_alloca_exc:
+    call0   _xt_alloca_exc                  /* in window vectors section */
+    /* never returns here - call0 is used as a jump (see note at top) */
+    #endif
+
+    .align      4
+_xt_to_syscall_exc:
+    call0   _xt_syscall_exc
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    #if XCHAL_CP_NUM > 0
+    .align      4
+_xt_to_coproc_exc:
+    call0   _xt_coproc_exc
+    /* never returns here - call0 is used as a jump (see note at top) */
+    #endif
+
+#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
+    .align      4
+_call_loadstore_handler:
+    call0   LoadStoreErrorHandler
+    /* This will return only if wrong opcode or address out of range*/
+    j       .LS_exit
+
+    .align      4
+_call_alignment_handler:
+    call0   AlignmentErrorHandler
+    /* This will return only if wrong opcode or address out of range*/
+    addi    a0, a0, 1
+    j       .LS_exit
+#endif
+
+/*
+--------------------------------------------------------------------------------
+  User exception handler.
+--------------------------------------------------------------------------------
+*/
+
+    .type       _xt_user_exc,@function
+    .align      4
+
+_xt_user_exc:
+
+    /* If level 1 interrupt then jump to the dispatcher */
+    rsr     a0, EXCCAUSE
+    beqi    a0, EXCCAUSE_LEVEL1INTERRUPT, _xt_lowint1
+
+    /* Handle any coprocessor exceptions. Rely on the fact that exception
+       numbers above EXCCAUSE_CP0_DISABLED all relate to the coprocessors.
+    */
+    #if XCHAL_CP_NUM > 0
+    bgeui   a0, EXCCAUSE_CP0_DISABLED, _xt_to_coproc_exc
+    #endif
+
+    /* Handle alloca and syscall exceptions */
+    #if XCHAL_HAVE_WINDOWED
+    beqi    a0, EXCCAUSE_ALLOCA,  _xt_to_alloca_exc
+    #endif
+    beqi    a0, EXCCAUSE_SYSCALL, _xt_to_syscall_exc
+
+#ifdef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
+    beqi    a0, EXCCAUSE_LOAD_STORE_ERROR, _call_loadstore_handler
+
+    addi    a0, a0, -1
+    beqi    a0, 8, _call_alignment_handler
+    addi    a0, a0, 1
+.LS_exit:
+#endif
+
+    /* Handle all other exceptions. All can have user-defined handlers. */
+    /* NOTE: we'll stay on the user stack for exception handling.       */
+
+    /* Allocate exception frame and save minimal context. */
+    mov     a0, sp
+    addi    sp, sp, -XT_STK_FRMSZ
+    s32i    a0, sp, XT_STK_A1
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -12                     /* for debug backtrace */
+    #endif
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -16                     /* for debug backtrace */
+    #endif
+    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
+    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
+    call0   _xt_context_save
+
+    /* Save exc cause and vaddr into exception frame */
+    rsr     a0, EXCCAUSE
+    s32i    a0, sp, XT_STK_EXCCAUSE
+    rsr     a0, EXCVADDR
+    s32i    a0, sp, XT_STK_EXCVADDR
+
+    /* _xt_context_save seems to save the current a0, but we need the interuptees a0. Fix this. */
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+
+    /* Set up PS for C, reenable hi-pri interrupts, and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(XCHAL_EXCM_LEVEL) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+
+    /*
+        Create pseudo base save area. At this point, sp is still pointing to the
+        allocated and filled exception stack frame.
+    */
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    l32i    a3, sp, XT_STK_A0               /* Copy pre-exception a0 (return address) */
+    s32e    a3, sp, -16
+    l32i    a3, sp, XT_STK_A1               /* Copy pre-exception a1 (stack pointer) */
+    s32e    a3, sp, -12
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+    rsr     a0, EPC_1                       /* return address for debug backtrace */
+    movi    a5, 0xC0000000                  /* constant with top 2 bits set (call size) */
+    rsync                                   /* wait for WSR.PS to complete */
+    or      a0, a0, a5                      /* set top 2 bits */
+    addx2   a0, a5, a0                      /* clear top bit -- thus simulating call4 size */
+    #else
+    rsync                                   /* wait for WSR.PS to complete */
+    #endif
+    #endif
+
+    rsr     a2, EXCCAUSE                    /* recover exc cause */
+
+    #ifdef XT_INTEXC_HOOKS
+    /*
+    Call exception hook to pre-handle exceptions (if installed).
+    Pass EXCCAUSE in a2, and check result in a2 (if -1, skip default handling).
+    */
+    movi    a4, _xt_intexc_hooks
+    l32i    a4, a4, 0                       /* user exception hook index 0 */
+    beqz    a4, 1f
+.Ln_xt_user_exc_call_hook:
+    #ifdef __XTENSA_CALL0_ABI__
+    callx0  a4
+    beqi    a2, -1, .L_xt_user_done
+    #else
+    mov     a6, a2
+    callx4  a4
+    beqi    a6, -1, .L_xt_user_done
+    mov     a2, a6
+    #endif
+1:
+    #endif
+
+    rsr     a2, EXCCAUSE                    /* recover exc cause */
+    movi    a3, _xt_exception_table
+    get_percpu_entry_for a2, a4
+    addx4   a4, a2, a3                      /* a4 = address of exception table entry */
+    l32i    a4, a4, 0                       /* a4 = handler address */
+    #ifdef __XTENSA_CALL0_ABI__
+    mov     a2, sp                          /* a2 = pointer to exc frame */
+    callx0  a4                              /* call handler */
+    #else
+    mov     a6, sp                          /* a6 = pointer to exc frame */
+    callx4  a4                              /* call handler */
+    #endif
+
+.L_xt_user_done:
+
+    /* Restore context and return */
+    call0   _xt_context_restore
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, PS
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_1
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove exception frame */
+    rsync                                   /* ensure PS and EPC written */
+    rfe                                     /* PS.EXCM is cleared */
+
+
+/*
+--------------------------------------------------------------------------------
+  Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+  on entry and used to return to a thread or interrupted interrupt handler.
+--------------------------------------------------------------------------------
+*/
+
+    .global     _xt_user_exit
+    .type       _xt_user_exit,@function
+    .align      4
+_xt_user_exit:
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, PS
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_1
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure PS and EPC written */
+    rfe                                     /* PS.EXCM is cleared */
+
+
+/*
+
+--------------------------------------------------------------------------------
+Syscall Exception Handler (jumped to from User Exception Handler).
+Syscall 0 is required to spill the register windows (no-op in Call 0 ABI).
+Only syscall 0 is handled here. Other syscalls return -1 to caller in a2.
+--------------------------------------------------------------------------------
+*/
+
+    .section .iram1,"ax"
+    .type       _xt_syscall_exc,@function
+    .align      4
+_xt_syscall_exc:
+
+    #ifdef __XTENSA_CALL0_ABI__
+    /*
+    Save minimal regs for scratch. Syscall 0 does nothing in Call0 ABI.
+    Use a minimal stack frame (16B) to save A2 & A3 for scratch.
+    PS.EXCM could be cleared here, but unlikely to improve worst-case latency.
+    rsr     a0, PS
+    addi    a0, a0, -PS_EXCM_MASK
+    wsr     a0, PS
+    */
+    addi    sp, sp, -16
+    s32i    a2, sp, 8
+    s32i    a3, sp, 12
+    #else   /* Windowed ABI */
+    /*
+    Save necessary context and spill the register windows.
+    PS.EXCM is still set and must remain set until after the spill.
+    Reuse context save function though it saves more than necessary.
+    For this reason, a full interrupt stack frame is allocated.
+    */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a12, sp, XT_STK_A12             /* _xt_context_save requires A12- */
+    s32i    a13, sp, XT_STK_A13             /* A13 to have already been saved */
+    call0   _xt_context_save
+    #endif
+
+    /*
+    Grab the interruptee's PC and skip over the 'syscall' instruction.
+    If it's at the end of a zero-overhead loop and it's not on the last
+    iteration, decrement loop counter and skip to beginning of loop.
+    */
+    rsr     a2, EPC_1                       /* a2 = PC of 'syscall' */
+    addi    a3, a2, 3                       /* ++PC                 */
+    #if XCHAL_HAVE_LOOPS
+    rsr     a0, LEND                        /* if (PC == LEND       */
+    bne     a3, a0, 1f
+    rsr     a0, LCOUNT                      /*     && LCOUNT != 0)  */
+    beqz    a0, 1f                          /* {                    */
+    addi    a0, a0, -1                      /*   --LCOUNT           */
+    rsr     a3, LBEG                        /*   PC = LBEG          */
+    wsr     a0, LCOUNT                      /* }                    */
+    #endif
+1:  wsr     a3, EPC_1                       /* update PC            */
+
+    /* Restore interruptee's context and return from exception. */
+    #ifdef __XTENSA_CALL0_ABI__
+    l32i    a2, sp, 8
+    l32i    a3, sp, 12
+    addi    sp, sp, 16
+    #else
+    call0   _xt_context_restore
+    addi    sp, sp, XT_STK_FRMSZ
+    #endif
+    movi    a0, -1
+    movnez  a2, a0, a2                      /* return -1 if not syscall 0 */
+    rsr     a0, EXCSAVE_1
+    rfe
+
+/*
+--------------------------------------------------------------------------------
+Co-Processor Exception Handler (jumped to from User Exception Handler).
+These exceptions are generated by co-processor instructions, which are only
+allowed in thread code (not in interrupts or kernel code). This restriction is 
+deliberately imposed to reduce the burden of state-save/restore in interrupts.
+--------------------------------------------------------------------------------
+*/
+#if XCHAL_CP_NUM > 0
+
+    .section .rodata, "a"
+
+/* Offset to CP n save area in thread's CP save area. */
+    .global _xt_coproc_sa_offset
+    .type   _xt_coproc_sa_offset,@object
+    .align  16                      /* minimize crossing cache boundaries */
+_xt_coproc_sa_offset:
+    .word   XT_CP0_SA, XT_CP1_SA, XT_CP2_SA, XT_CP3_SA
+    .word   XT_CP4_SA, XT_CP5_SA, XT_CP6_SA, XT_CP7_SA
+
+/* Bitmask for CP n's CPENABLE bit. */
+    .type   _xt_coproc_mask,@object
+    .align  16,,8                   /* try to keep it all in one cache line */
+    .set    i, 0
+_xt_coproc_mask:
+    .rept   XCHAL_CP_MAX
+    .long   (i<<16) | (1<<i)    // upper 16-bits = i, lower = bitmask
+    .set    i, i+1
+    .endr
+
+    .data
+
+/* Owner thread of CP n, identified by thread's CP save area (0 = unowned). */
+    .global _xt_coproc_owner_sa
+    .type   _xt_coproc_owner_sa,@object
+    .align  16,,XCHAL_CP_MAX<<2     /* minimize crossing cache boundaries */
+_xt_coproc_owner_sa:
+    .space  (XCHAL_CP_MAX * portNUM_PROCESSORS) << 2
+
+    .section .iram1,"ax"
+
+
+    .align  4
+.L_goto_invalid:
+    j   .L_xt_coproc_invalid    /* not in a thread (invalid) */
+    .align  4
+.L_goto_done:
+    j   .L_xt_coproc_done
+
+
+/*
+--------------------------------------------------------------------------------
+  Coprocessor exception handler.
+  At entry, only a0 has been saved (in EXCSAVE_1).
+--------------------------------------------------------------------------------
+*/
+
+    .type   _xt_coproc_exc,@function
+    .align  4
+
+_xt_coproc_exc:
+
+    /* Allocate interrupt stack frame and save minimal context. */
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -12                     /* for debug backtrace */
+    #endif
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    #if XCHAL_HAVE_WINDOWED
+    s32e    a0, sp, -16                     /* for debug backtrace */
+    #endif
+    movi    a0, _xt_user_exit               /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    rsr     a0, EXCCAUSE
+    s32i    a5, sp, XT_STK_A5               /* save a5 */
+    addi    a5, a0, -EXCCAUSE_CP0_DISABLED  /* a5 = CP index */
+
+    /* Save a few more of interruptee's registers (a5 was already saved). */
+    s32i    a2,  sp, XT_STK_A2
+    s32i    a3,  sp, XT_STK_A3
+    s32i    a4,  sp, XT_STK_A4
+    s32i    a15, sp, XT_STK_A15
+
+    /* Get co-processor state save area of new owner thread. */
+    call0   XT_RTOS_CP_STATE                /* a15 = new owner's save area */
+    #if (ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0))
+    beqz    a15, .L_goto_invalid            /* not in a thread (invalid) */
+    #else
+    #ifndef CONFIG_FREERTOS_FPU_IN_ISR     
+    beqz    a15, .L_goto_invalid
+    #endif
+    #endif /* ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    /*When FPU in ISR is enabled we could deal with zeroed a15 */
+
+    /* Enable the co-processor's bit in CPENABLE. */
+    movi    a0, _xt_coproc_mask
+    rsr     a4, CPENABLE                    /* a4 = CPENABLE */
+    addx4   a0, a5, a0                      /* a0 = &_xt_coproc_mask[n] */
+    l32i    a0, a0, 0                       /* a0 = (n << 16) | (1 << n) */
+
+    /* FPU operations are incompatible with non-pinned tasks. If we have a FPU operation
+       here, to keep the entire thing from crashing, it's better to pin the task to whatever
+       core we're running on now. */
+    movi    a2, pxCurrentTCB
+    getcoreid a3
+    addx4     a2,  a3, a2
+    l32i    a2, a2, 0                       /* a2 = start of pxCurrentTCB[cpuid] */
+    addi    a2, a2, TASKTCB_XCOREID_OFFSET  /* offset to xCoreID in tcb struct */
+    s32i    a3, a2, 0                       /* store current cpuid */
+
+    /* Grab correct xt_coproc_owner_sa for this core */
+    movi    a2, XCHAL_CP_MAX << 2
+    mull    a2, a2, a3                      /* multiply by current processor id */
+    movi    a3, _xt_coproc_owner_sa         /* a3 = base of owner array */
+    add     a3, a3, a2                      /* a3 = owner area needed for this processor */
+
+    extui   a2, a0, 0, 16                   /* coprocessor bitmask portion */
+    or      a4, a4, a2                      /* a4 = CPENABLE | (1 << n) */
+    wsr     a4, CPENABLE
+
+/* 
+Keep loading _xt_coproc_owner_sa[n] atomic (=load once, then use that value
+everywhere): _xt_coproc_release assumes it works like this in order not to need
+locking.
+*/
+
+
+    /* Get old coprocessor owner thread (save area ptr) and assign new one.  */
+    addx4   a3,  a5, a3                      /* a3 = &_xt_coproc_owner_sa[n] */
+    l32i    a2,  a3, 0                       /* a2 = old owner's save area */
+    s32i    a15, a3, 0                       /* _xt_coproc_owner_sa[n] = new */
+    rsync                                    /* ensure wsr.CPENABLE is complete */
+
+    /* Only need to context switch if new owner != old owner. */
+    /* If float is necessary on ISR, we need to remove this check */
+    /* below, because on restoring from ISR we may have new == old condition used
+     * to force cp restore to next thread
+     */
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifndef CONFIG_FREERTOS_FPU_IN_ISR
+    #endif
+    beq     a15, a2, .L_goto_done           /* new owner == old, we're done */
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #endif
+    #endif
+
+    /* If no old owner then nothing to save. */
+    beqz    a2, .L_check_new
+
+    /* If old owner not actively using CP then nothing to save. */
+    l16ui   a4,  a2,  XT_CPENABLE           /* a4 = old owner's CPENABLE */
+    bnone   a4,  a0,  .L_check_new          /* old owner not using CP    */
+
+.L_save_old:
+    /* Save old owner's coprocessor state. */
+
+    movi    a5, _xt_coproc_sa_offset
+
+    /* Mark old owner state as no longer active (CPENABLE bit n clear). */
+    xor     a4,  a4,  a0                    /* clear CP bit in CPENABLE    */
+    s16i    a4,  a2,  XT_CPENABLE           /* update old owner's CPENABLE */
+
+    extui   a4,  a0,  16,  5                /* a4 = CP index = n */
+    addx4   a5,  a4,  a5                    /* a5 = &_xt_coproc_sa_offset[n] */
+
+    /* Mark old owner state as saved (CPSTORED bit n set). */
+    l16ui   a4,  a2,  XT_CPSTORED           /* a4 = old owner's CPSTORED */
+    l32i    a5,  a5,  0                     /* a5 = XT_CP[n]_SA offset */
+    or      a4,  a4,  a0                    /* set CP in old owner's CPSTORED */
+    s16i    a4,  a2,  XT_CPSTORED           /* update old owner's CPSTORED */
+    l32i    a2, a2, XT_CP_ASA               /* ptr to actual (aligned) save area */
+    extui   a3, a0, 16, 5                   /* a3 = CP index = n */
+    add     a2, a2, a5                      /* a2 = old owner's area for CP n */
+
+    /*
+    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
+    It is theoretically possible for Xtensa processor designers to write TIE 
+    that causes more address registers to be affected, but it is generally 
+    unlikely. If that ever happens, more registers needs to be saved/restored
+    around this macro invocation, and the value in a15 needs to be recomputed.
+    */
+    xchal_cpi_store_funcbody
+
+.L_check_new:
+    /* Check if any state has to be restored for new owner. */
+    /* NOTE: a15 = new owner's save area, cannot be zero when we get here. */
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    beqz    a15, .L_xt_coproc_done
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    l16ui   a3,  a15, XT_CPSTORED           /* a3 = new owner's CPSTORED */
+    movi    a4, _xt_coproc_sa_offset
+    bnone   a3,  a0,  .L_check_cs           /* full CP not saved, check callee-saved */
+    xor     a3,  a3,  a0                    /* CPSTORED bit is set, clear it */
+    s16i    a3,  a15, XT_CPSTORED           /* update new owner's CPSTORED */
+
+    /* Adjust new owner's save area pointers to area for CP n. */
+    extui   a3,  a0, 16, 5                  /* a3 = CP index = n */
+    addx4   a4,  a3, a4                     /* a4 = &_xt_coproc_sa_offset[n] */
+    l32i    a4,  a4, 0                      /* a4 = XT_CP[n]_SA */
+    l32i    a5, a15, XT_CP_ASA              /* ptr to actual (aligned) save area */
+    add     a2,  a4, a5                     /* a2 = new owner's area for CP */
+
+    /*
+    The config-specific HAL macro invoked below destroys a2-5, preserves a0-1.
+    It is theoretically possible for Xtensa processor designers to write TIE 
+    that causes more address registers to be affected, but it is generally 
+    unlikely. If that ever happens, more registers needs to be saved/restored
+    around this macro invocation.
+    */
+    xchal_cpi_load_funcbody
+
+    /* Restore interruptee's saved registers. */
+    /* Can omit rsync for wsr.CPENABLE here because _xt_user_exit does it. */
+.L_xt_coproc_done:
+    l32i    a15, sp, XT_STK_A15
+    l32i    a5,  sp, XT_STK_A5
+    l32i    a4,  sp, XT_STK_A4
+    l32i    a3,  sp, XT_STK_A3
+    l32i    a2,  sp, XT_STK_A2
+    call0   _xt_user_exit                   /* return via exit dispatcher */
+    /* Never returns here - call0 is used as a jump (see note at top) */
+
+.L_check_cs:
+    /* a0 = CP mask in low bits, a15 = new owner's save area */
+    l16ui   a2, a15, XT_CP_CS_ST            /* a2 = mask of CPs saved    */
+    bnone   a2,  a0, .L_xt_coproc_done      /* if no match then done     */
+    and     a2,  a2, a0                     /* a2 = which CPs to restore */
+    extui   a2,  a2, 0, 8                   /* extract low 8 bits        */
+    s32i    a6,  sp, XT_STK_A6              /* save extra needed regs    */
+    s32i    a7,  sp, XT_STK_A7
+    s32i    a13, sp, XT_STK_A13
+    s32i    a14, sp, XT_STK_A14
+    call0   _xt_coproc_restorecs            /* restore CP registers      */
+    l32i    a6,  sp, XT_STK_A6              /* restore saved registers   */
+    l32i    a7,  sp, XT_STK_A7
+    l32i    a13, sp, XT_STK_A13
+    l32i    a14, sp, XT_STK_A14
+    j       .L_xt_coproc_done
+
+    /* Co-processor exception occurred outside a thread (not supported). */
+.L_xt_coproc_invalid:
+    movi    a0,PANIC_RSN_COPROCEXCEPTION
+    wsr     a0,EXCCAUSE
+    call0   _xt_panic                       /* not in a thread (invalid) */
+    /* never returns */
+
+
+#endif /* XCHAL_CP_NUM */
+
+
+/*
+-------------------------------------------------------------------------------
+  Level 1 interrupt dispatch. Assumes stack frame has not been allocated yet.
+-------------------------------------------------------------------------------
+*/
+
+    .section .iram1,"ax"
+    .type       _xt_lowint1,@function
+    .align      4
+
+_xt_lowint1:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, PS                          /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_1                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_1                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_user_exit               /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    /* EXCSAVE_1 should now be free to use. Use it to keep a copy of the
+    current stack pointer that points to the exception frame (XT_STK_FRAME).*/
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    mov     a0, sp
+    wsr     a0, EXCSAVE_1
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */ 
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(1) | PS_UM
+    #else 
+    movi    a0, PS_INTLEVEL(1) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+
+/*
+-------------------------------------------------------------------------------
+  MEDIUM PRIORITY (LEVEL 2+) INTERRUPT VECTORS AND LOW LEVEL HANDLERS.
+
+  Medium priority interrupts are by definition those with priority greater
+  than 1 and not greater than XCHAL_EXCM_LEVEL. These are disabled by
+  setting PS.EXCM and therefore can easily support a C environment for
+  handlers in C, and interact safely with an RTOS.
+
+  Each vector goes at a predetermined location according to the Xtensa
+  hardware configuration, which is ensured by its placement in a special
+  section known to the Xtensa linker support package (LSP). It performs
+  the minimum necessary before jumping to the handler in the .text section.
+
+  The corresponding handler goes in the normal .text section. It sets up
+  the appropriate stack frame, saves a few vector-specific registers and
+  calls XT_RTOS_INT_ENTER to save the rest of the interrupted context
+  and enter the RTOS, then sets up a C environment. It then calls the
+  user's interrupt handler code (which may be coded in C) and finally 
+  calls XT_RTOS_INT_EXIT to transfer control to the RTOS for scheduling.
+
+  While XT_RTOS_INT_EXIT does not return directly to the interruptee,
+  eventually the RTOS scheduler will want to dispatch the interrupted
+  task or handler. The scheduler will return to the exit point that was
+  saved in the interrupt stack frame at XT_STK_EXIT.
+-------------------------------------------------------------------------------
+*/
+
+#if XCHAL_EXCM_LEVEL >= 2
+
+    .begin      literal_prefix .Level2InterruptVector
+    .section    .Level2InterruptVector.text, "ax"
+    .global     _Level2Vector
+    .type       _Level2Vector,@function
+    .align      4
+_Level2Vector:
+    wsr     a0, EXCSAVE_2                   /* preserve a0 */
+    call0   _xt_medint2                     /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .section .iram1,"ax"
+    .type       _xt_medint2,@function
+    .align      4
+_xt_medint2:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_2                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_2                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_2                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint2_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* EXCSAVE_2 should now be free to use. Use it to keep a copy of the
+    current stack pointer that points to the exception frame (XT_STK_FRAME).*/
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    mov     a0, sp
+    wsr     a0, EXCSAVE_2
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(2) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(2) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint2_exit
+    .type       _xt_medint2_exit,@function
+    .align      4
+_xt_medint2_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_2
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_2
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     2
+
+#endif  /* Level 2 */
+
+#if XCHAL_EXCM_LEVEL >= 3
+
+    .begin      literal_prefix .Level3InterruptVector
+    .section    .Level3InterruptVector.text, "ax"
+    .global     _Level3Vector
+    .type       _Level3Vector,@function
+    .align      4
+_Level3Vector:
+    wsr     a0, EXCSAVE_3                   /* preserve a0 */
+    call0   _xt_medint3                     /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+    .section .iram1,"ax"
+    .type       _xt_medint3,@function
+    .align      4
+_xt_medint3:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_3                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_3                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_3                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint3_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* EXCSAVE_3 should now be free to use. Use it to keep a copy of the
+    current stack pointer that points to the exception frame (XT_STK_FRAME).*/
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    mov     a0, sp
+    wsr     a0, EXCSAVE_3
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(3) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(3) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint3_exit
+    .type       _xt_medint3_exit,@function
+    .align      4
+_xt_medint3_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_3
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_3
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     3
+
+#endif  /* Level 3 */
+
+#if XCHAL_EXCM_LEVEL >= 4
+
+    .begin      literal_prefix .Level4InterruptVector
+    .section    .Level4InterruptVector.text, "ax"
+    .global     _Level4Vector
+    .type       _Level4Vector,@function
+    .align      4
+_Level4Vector:
+    wsr     a0, EXCSAVE_4                   /* preserve a0 */
+    call0   _xt_medint4                     /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .section .iram1,"ax"
+    .type       _xt_medint4,@function
+    .align      4
+_xt_medint4:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_4                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_4                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_4                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint4_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* EXCSAVE_4 should now be free to use. Use it to keep a copy of the
+    current stack pointer that points to the exception frame (XT_STK_FRAME).*/
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    mov     a0, sp
+    wsr     a0, EXCSAVE_4
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(4) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(4) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint4_exit
+    .type       _xt_medint4_exit,@function
+    .align      4
+_xt_medint4_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_4
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_4
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     4
+
+#endif  /* Level 4 */
+
+#if XCHAL_EXCM_LEVEL >= 5
+
+    .begin      literal_prefix .Level5InterruptVector
+    .section    .Level5InterruptVector.text, "ax"
+    .global     _Level5Vector
+    .type       _Level5Vector,@function
+    .align      4
+_Level5Vector:
+    wsr     a0, EXCSAVE_5                   /* preserve a0 */
+    call0   _xt_medint5                     /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .section .iram1,"ax"
+    .type       _xt_medint5,@function
+    .align      4
+_xt_medint5:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_5                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_5                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_5                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint5_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* EXCSAVE_5 should now be free to use. Use it to keep a copy of the
+    current stack pointer that points to the exception frame (XT_STK_FRAME).*/
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    mov     a0, sp
+    wsr     a0, EXCSAVE_5
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(5) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(5) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint5_exit
+    .type       _xt_medint5_exit,@function
+    .align      4
+_xt_medint5_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_5
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_5
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     5
+
+#endif  /* Level 5 */
+
+#if XCHAL_EXCM_LEVEL >= 6
+
+    .begin      literal_prefix .Level6InterruptVector
+    .section    .Level6InterruptVector.text, "ax"
+    .global     _Level6Vector
+    .type       _Level6Vector,@function
+    .align      4
+_Level6Vector:
+    wsr     a0, EXCSAVE_6                   /* preserve a0 */
+    call0   _xt_medint6                     /* load interrupt handler */
+
+    .end        literal_prefix
+
+    .section .iram1,"ax"
+    .type       _xt_medint6,@function
+    .align      4
+_xt_medint6:
+    mov     a0, sp                          /* sp == a1 */
+    addi    sp, sp, -XT_STK_FRMSZ           /* allocate interrupt stack frame */
+    s32i    a0, sp, XT_STK_A1               /* save pre-interrupt SP */
+    rsr     a0, EPS_6                       /* save interruptee's PS */
+    s32i    a0, sp, XT_STK_PS
+    rsr     a0, EPC_6                       /* save interruptee's PC */
+    s32i    a0, sp, XT_STK_PC
+    rsr     a0, EXCSAVE_6                   /* save interruptee's a0 */
+    s32i    a0, sp, XT_STK_A0
+    movi    a0, _xt_medint6_exit            /* save exit point for dispatch */
+    s32i    a0, sp, XT_STK_EXIT
+
+    /* EXCSAVE_6 should now be free to use. Use it to keep a copy of the
+    current stack pointer that points to the exception frame (XT_STK_FRAME).*/
+    #if (ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0))
+    #ifdef XT_DEBUG_BACKTRACE
+    #ifndef __XTENSA_CALL0_ABI__
+    mov     a0, sp
+    wsr     a0, EXCSAVE_6
+    #endif
+    #endif
+    #endif /* ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0) */
+
+    /* Save rest of interrupt context and enter RTOS. */
+    call0   XT_RTOS_INT_ENTER               /* common RTOS interrupt entry */
+
+    /* !! We are now on the RTOS system stack !! */
+
+    /* Set up PS for C, enable interrupts above this level and clear EXCM. */
+    #ifdef __XTENSA_CALL0_ABI__
+    movi    a0, PS_INTLEVEL(6) | PS_UM
+    #else
+    movi    a0, PS_INTLEVEL(6) | PS_UM | PS_WOE
+    #endif
+    wsr     a0, PS
+    rsync
+
+    /* OK to call C code at this point, dispatch user ISRs */
+
+    dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
+
+    /* Done handling interrupts, transfer control to OS */
+    call0   XT_RTOS_INT_EXIT                /* does not return directly here */
+
+    /*
+    Exit point for dispatch. Saved in interrupt stack frame at XT_STK_EXIT
+    on entry and used to return to a thread or interrupted interrupt handler.
+    */
+    .global     _xt_medint6_exit
+    .type       _xt_medint6_exit,@function
+    .align      4
+_xt_medint6_exit:
+    /* Restore only level-specific regs (the rest were already restored) */
+    l32i    a0, sp, XT_STK_PS               /* retrieve interruptee's PS */
+    wsr     a0, EPS_6
+    l32i    a0, sp, XT_STK_PC               /* retrieve interruptee's PC */
+    wsr     a0, EPC_6
+    l32i    a0, sp, XT_STK_A0               /* retrieve interruptee's A0 */
+    l32i    sp, sp, XT_STK_A1               /* remove interrupt stack frame */
+    rsync                                   /* ensure EPS and EPC written */
+    rfi     6
+
+#endif  /* Level 6 */
+
+
+/*******************************************************************************
+
+HIGH PRIORITY (LEVEL > XCHAL_EXCM_LEVEL) INTERRUPT VECTORS AND HANDLERS
+
+High priority interrupts are by definition those with priorities greater
+than XCHAL_EXCM_LEVEL. This includes non-maskable (NMI). High priority
+interrupts cannot interact with the RTOS, that is they must save all regs
+they use and not call any RTOS function.
+
+A further restriction imposed by the Xtensa windowed architecture is that
+high priority interrupts must not modify the stack area even logically
+"above" the top of the interrupted stack (they need to provide their
+own stack or static save area).
+
+Cadence Design Systems recommends high priority interrupt handlers be coded in assembly
+and used for purposes requiring very short service times.
+
+Here are templates for high priority (level 2+) interrupt vectors.
+They assume only one interrupt per level to avoid the burden of identifying
+which interrupts at this level are pending and enabled. This allows for 
+minimum latency and avoids having to save/restore a2 in addition to a0.
+If more than one interrupt per high priority level is configured, this burden
+is on the handler which in any case must provide a way to save and restore
+registers it uses without touching the interrupted stack.
+
+Each vector goes at a predetermined location according to the Xtensa
+hardware configuration, which is ensured by its placement in a special
+section known to the Xtensa linker support package (LSP). It performs
+the minimum necessary before jumping to the handler in the .text section.
+
+*******************************************************************************/
+
+/*
+These stubs just call xt_highintX/xt_nmi to handle the real interrupt. Please define
+these in an external assembly source file. If these symbols are not defined anywhere
+else, the defaults in xtensa_vector_defaults.S are used.
+*/
+
+#if XCHAL_NUM_INTLEVELS >=2 && XCHAL_EXCM_LEVEL <2 && XCHAL_DEBUGLEVEL !=2
+
+    .begin      literal_prefix .Level2InterruptVector
+    .section    .Level2InterruptVector.text, "ax"
+    .global     _Level2Vector
+    .type       _Level2Vector,@function
+    .global     xt_highint2
+    .align      4
+_Level2Vector:
+    wsr     a0, EXCSAVE_2                   /* preserve a0 */
+    call0   xt_highint2                    /* load interrupt handler */
+
+    .end        literal_prefix
+
+#endif  /* Level 2 */
+
+#if XCHAL_NUM_INTLEVELS >=3 && XCHAL_EXCM_LEVEL <3 && XCHAL_DEBUGLEVEL !=3
+
+    .begin      literal_prefix .Level3InterruptVector
+    .section    .Level3InterruptVector.text, "ax"
+    .global     _Level3Vector
+    .type       _Level3Vector,@function
+    .global     xt_highint3
+    .align      4
+_Level3Vector:
+    wsr     a0, EXCSAVE_3                   /* preserve a0 */
+    call0   xt_highint3                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+#endif  /* Level 3 */
+
+#if XCHAL_NUM_INTLEVELS >=4 && XCHAL_EXCM_LEVEL <4 && XCHAL_DEBUGLEVEL !=4
+
+    .begin      literal_prefix .Level4InterruptVector
+    .section    .Level4InterruptVector.text, "ax"
+    .global     _Level4Vector
+    .type       _Level4Vector,@function
+    .global     xt_highint4
+    .align      4
+_Level4Vector:
+    wsr     a0, EXCSAVE_4                   /* preserve a0 */
+    call0   xt_highint4                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+#endif  /* Level 4 */
+
+#if XCHAL_NUM_INTLEVELS >=5 && XCHAL_EXCM_LEVEL <5 && XCHAL_DEBUGLEVEL !=5
+
+    .begin      literal_prefix .Level5InterruptVector
+    .section    .Level5InterruptVector.text, "ax"
+    .global     _Level5Vector
+    .type       _Level5Vector,@function
+    .global     xt_highint5
+    .align      4
+_Level5Vector:
+    wsr     a0, EXCSAVE_5                   /* preserve a0 */
+    call0   xt_highint5                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+#endif  /* Level 5 */
+
+#if XCHAL_NUM_INTLEVELS >=6 && XCHAL_EXCM_LEVEL <6 && XCHAL_DEBUGLEVEL !=6
+
+    .begin      literal_prefix .Level6InterruptVector
+    .section    .Level6InterruptVector.text, "ax"
+    .global     _Level6Vector
+    .type       _Level6Vector,@function
+    .global     xt_highint6
+    .align      4
+_Level6Vector:
+    wsr     a0, EXCSAVE_6                   /* preserve a0 */
+    call0   xt_highint6                    /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+#endif  /* Level 6 */
+
+#if XCHAL_HAVE_NMI
+
+    .begin      literal_prefix .NMIExceptionVector
+    .section    .NMIExceptionVector.text, "ax"
+    .global     _NMIExceptionVector
+    .type       _NMIExceptionVector,@function
+    .global     xt_nmi
+    .align      4
+_NMIExceptionVector:
+    wsr     a0, EXCSAVE + XCHAL_NMILEVEL  _ /* preserve a0 */
+    call0   xt_nmi                         /* load interrupt handler */
+    /* never returns here - call0 is used as a jump (see note at top) */
+
+    .end        literal_prefix
+
+#endif  /* NMI */
+
+
+/*******************************************************************************
+
+WINDOW OVERFLOW AND UNDERFLOW EXCEPTION VECTORS AND ALLOCA EXCEPTION HANDLER
+
+Here is the code for each window overflow/underflow exception vector and 
+(interspersed) efficient code for handling the alloca exception cause.
+Window exceptions are handled entirely in the vector area and are very
+tight for performance. The alloca exception is also handled entirely in 
+the window vector area so comes at essentially no cost in code size.
+Users should never need to modify them and Cadence Design Systems recommends 
+they do not.
+
+Window handlers go at predetermined vector locations according to the
+Xtensa hardware configuration, which is ensured by their placement in a
+special section known to the Xtensa linker support package (LSP). Since
+their offsets in that section are always the same, the LSPs do not define
+a section per vector.
+
+These things are coded for XEA2 only (XEA1 is not supported).
+
+Note on Underflow Handlers:
+The underflow handler for returning from call[i+1] to call[i]
+must preserve all the registers from call[i+1]'s window.
+In particular, a0 and a1 must be preserved because the RETW instruction
+will be reexecuted (and may even underflow if an intervening exception
+has flushed call[i]'s registers).
+Registers a2 and up may contain return values.
+
+*******************************************************************************/
+
+#if XCHAL_HAVE_WINDOWED
+
+    .section .WindowVectors.text, "ax"
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call4.
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call4 to call[j+1].
+On entry here:
+    window rotated to call[j] start point;
+        a0-a3 are registers to be saved;
+        a4-a15 must be preserved;
+        a5 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x0
+    .global _WindowOverflow4
+_WindowOverflow4:
+
+    s32e    a0, a5, -16     /* save a0 to call[j+1]'s stack frame */
+    s32e    a1, a5, -12     /* save a1 to call[j+1]'s stack frame */
+    s32e    a2, a5,  -8     /* save a2 to call[j+1]'s stack frame */
+    s32e    a3, a5,  -4     /* save a3 to call[j+1]'s stack frame */
+    rfwo                    /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call4
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call4 to call[i+1].
+On entry here:
+        window rotated to call[i] start point;
+        a0-a3 are undefined, must be reloaded with call[i].reg[0..3];
+        a4-a15 must be preserved (they are call[i+1].reg[0..11]);
+        a5 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x40
+    .global _WindowUnderflow4
+_WindowUnderflow4:
+
+    l32e    a0, a5, -16     /* restore a0 from call[i+1]'s stack frame */
+    l32e    a1, a5, -12     /* restore a1 from call[i+1]'s stack frame */
+    l32e    a2, a5,  -8     /* restore a2 from call[i+1]'s stack frame */
+    l32e    a3, a5,  -4     /* restore a3 from call[i+1]'s stack frame */
+    rfwu
+
+/*
+--------------------------------------------------------------------------------
+Handle alloca exception generated by interruptee executing 'movsp'.
+This uses space between the window vectors, so is essentially "free".
+All interruptee's regs are intact except a0 which is saved in EXCSAVE_1,
+and PS.EXCM has been set by the exception hardware (can't be interrupted).
+The fact the alloca exception was taken means the registers associated with
+the base-save area have been spilled and will be restored by the underflow
+handler, so those 4 registers are available for scratch.
+The code is optimized to avoid unaligned branches and minimize cache misses.
+--------------------------------------------------------------------------------
+*/
+
+    .align  4
+    .global _xt_alloca_exc
+_xt_alloca_exc:
+
+    rsr     a0, WINDOWBASE  /* grab WINDOWBASE before rotw changes it */
+    rotw    -1              /* WINDOWBASE goes to a4, new a0-a3 are scratch */
+    rsr     a2, PS
+    extui   a3, a2, XCHAL_PS_OWB_SHIFT, XCHAL_PS_OWB_BITS
+    xor     a3, a3, a4      /* bits changed from old to current windowbase */
+    rsr     a4, EXCSAVE_1   /* restore original a0 (now in a4) */
+    slli    a3, a3, XCHAL_PS_OWB_SHIFT
+    xor     a2, a2, a3      /* flip changed bits in old window base */
+    wsr     a2, PS          /* update PS.OWB to new window base */
+    rsync
+
+    _bbci.l a4, 31, _WindowUnderflow4
+    rotw    -1              /* original a0 goes to a8 */
+    _bbci.l a8, 30, _WindowUnderflow8
+    rotw    -1
+    j               _WindowUnderflow12
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call8
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call8 to call[j+1].
+On entry here:
+    window rotated to call[j] start point;
+        a0-a7 are registers to be saved;
+        a8-a15 must be preserved;
+        a9 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x80
+    .global _WindowOverflow8
+_WindowOverflow8:
+
+    s32e    a0, a9, -16     /* save a0 to call[j+1]'s stack frame */
+    l32e    a0, a1, -12     /* a0 <- call[j-1]'s sp
+                               (used to find end of call[j]'s frame) */
+    s32e    a1, a9, -12     /* save a1 to call[j+1]'s stack frame */
+    s32e    a2, a9,  -8     /* save a2 to call[j+1]'s stack frame */
+    s32e    a3, a9,  -4     /* save a3 to call[j+1]'s stack frame */
+    s32e    a4, a0, -32     /* save a4 to call[j]'s stack frame */
+    s32e    a5, a0, -28     /* save a5 to call[j]'s stack frame */
+    s32e    a6, a0, -24     /* save a6 to call[j]'s stack frame */
+    s32e    a7, a0, -20     /* save a7 to call[j]'s stack frame */
+    rfwo                    /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call8
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call8 to call[i+1].
+On entry here:
+        window rotated to call[i] start point;
+        a0-a7 are undefined, must be reloaded with call[i].reg[0..7];
+        a8-a15 must be preserved (they are call[i+1].reg[0..7]);
+        a9 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0xC0
+    .global _WindowUnderflow8
+_WindowUnderflow8:
+
+    l32e    a0, a9, -16     /* restore a0 from call[i+1]'s stack frame */
+    l32e    a1, a9, -12     /* restore a1 from call[i+1]'s stack frame */
+    l32e    a2, a9,  -8     /* restore a2 from call[i+1]'s stack frame */
+    l32e    a7, a1, -12     /* a7 <- call[i-1]'s sp
+                               (used to find end of call[i]'s frame) */
+    l32e    a3, a9,  -4     /* restore a3 from call[i+1]'s stack frame */
+    l32e    a4, a7, -32     /* restore a4 from call[i]'s stack frame */
+    l32e    a5, a7, -28     /* restore a5 from call[i]'s stack frame */
+    l32e    a6, a7, -24     /* restore a6 from call[i]'s stack frame */
+    l32e    a7, a7, -20     /* restore a7 from call[i]'s stack frame */
+    rfwu
+
+/*
+--------------------------------------------------------------------------------
+Window Overflow Exception for Call12
+
+Invoked if a call[i] referenced a register (a4-a15)
+that contains data from ancestor call[j];
+call[j] had done a call12 to call[j+1].
+On entry here:
+    window rotated to call[j] start point;
+        a0-a11 are registers to be saved;
+        a12-a15 must be preserved;
+        a13 is call[j+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org    0x100
+    .global _WindowOverflow12
+_WindowOverflow12:
+
+    s32e    a0,  a13, -16   /* save a0 to call[j+1]'s stack frame */
+    l32e    a0,  a1,  -12   /* a0 <- call[j-1]'s sp
+                               (used to find end of call[j]'s frame) */
+    s32e    a1,  a13, -12   /* save a1 to call[j+1]'s stack frame */
+    s32e    a2,  a13,  -8   /* save a2 to call[j+1]'s stack frame */
+    s32e    a3,  a13,  -4   /* save a3 to call[j+1]'s stack frame */
+    s32e    a4,  a0,  -48   /* save a4 to end of call[j]'s stack frame */
+    s32e    a5,  a0,  -44   /* save a5 to end of call[j]'s stack frame */
+    s32e    a6,  a0,  -40   /* save a6 to end of call[j]'s stack frame */
+    s32e    a7,  a0,  -36   /* save a7 to end of call[j]'s stack frame */
+    s32e    a8,  a0,  -32   /* save a8 to end of call[j]'s stack frame */
+    s32e    a9,  a0,  -28   /* save a9 to end of call[j]'s stack frame */
+    s32e    a10, a0,  -24   /* save a10 to end of call[j]'s stack frame */
+    s32e    a11, a0,  -20   /* save a11 to end of call[j]'s stack frame */
+    rfwo                    /* rotates back to call[i] position */
+
+/*
+--------------------------------------------------------------------------------
+Window Underflow Exception for Call12
+
+Invoked by RETW returning from call[i+1] to call[i]
+where call[i]'s registers must be reloaded (not live in ARs);
+where call[i] had done a call12 to call[i+1].
+On entry here:
+        window rotated to call[i] start point;
+        a0-a11 are undefined, must be reloaded with call[i].reg[0..11];
+        a12-a15 must be preserved (they are call[i+1].reg[0..3]);
+        a13 is call[i+1]'s stack pointer.
+--------------------------------------------------------------------------------
+*/
+
+    .org 0x140
+    .global _WindowUnderflow12
+_WindowUnderflow12:
+
+    l32e    a0,  a13, -16   /* restore a0 from call[i+1]'s stack frame */
+    l32e    a1,  a13, -12   /* restore a1 from call[i+1]'s stack frame */
+    l32e    a2,  a13,  -8   /* restore a2 from call[i+1]'s stack frame */
+    l32e    a11, a1,  -12   /* a11 <- call[i-1]'s sp
+                               (used to find end of call[i]'s frame) */
+    l32e    a3,  a13,  -4   /* restore a3 from call[i+1]'s stack frame */
+    l32e    a4,  a11, -48   /* restore a4 from end of call[i]'s stack frame */
+    l32e    a5,  a11, -44   /* restore a5 from end of call[i]'s stack frame */
+    l32e    a6,  a11, -40   /* restore a6 from end of call[i]'s stack frame */
+    l32e    a7,  a11, -36   /* restore a7 from end of call[i]'s stack frame */
+    l32e    a8,  a11, -32   /* restore a8 from end of call[i]'s stack frame */
+    l32e    a9,  a11, -28   /* restore a9 from end of call[i]'s stack frame */
+    l32e    a10, a11, -24   /* restore a10 from end of call[i]'s stack frame */
+    l32e    a11, a11, -20   /* restore a11 from end of call[i]'s stack frame */
+    rfwu
+
+#endif /* XCHAL_HAVE_WINDOWED */
+
+    .section    .UserEnter.text, "ax"
+    .global     call_user_start
+    .type       call_user_start,@function
+    .align      4
+    .literal_position
+
+
+