mirror of
https://github.com/eclipse-threadx/threadx.git
synced 2026-08-17 09:33:32 +08:00
Updated Xtensa support (#525)
* Add LX8 support for > 32 interrupts Also fix inconsistent SWPRI define in interrupt handler * ThreadX: Fix context switch logic - Disable interrupts prior to allocating a large exception frame; only reenable them after deallocating the extra memory. - Any user tasks with stacks based on TX_MINIMUM_STACK do not have sufficient space for both a context switch frame and an ISR frame; ill-timed interrupts were causing stack overruns. * ThreadX: Interrupt fixes for TX_ENABLE_EXECUTION_CHANGE_NOTIFY - Must reload register trashed by notify hook function call - Must ensure PS.WOE is set before using call8 - Remove unused XT_USE_INT_WRAPPER define and associated changes, which had a bug in XEA2 usage - Fix another case where enabling the thread notify hooks for call0 ABI corrupted a register * ThreadX: Support for __DYNAMIC_REENT__ - ThreadX change to handle dynamic reent for both newlib and xclib - Adapt ThreadX xclib interface code to handle dynamic reent pointers * ThreadX: Xtensa execution profiling support - Update upstream execution profiling for Xtensa port * ThreadX: Update xtensa port readme * ThreadX: Add Xtensa example to EPK - tx_execution_profile.h now defines an Xtensa example in addition to the existing Cortex example * ThreadX: Add xtensa.cmake * ThreadX: Update XSHAL_CLIB ifdefs in __getreent() - Prevent a fall-through with no return value when neither xclib nor newlib are used.
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
set(CMAKE_SYSTEM_NAME Generic)
|
||||
set(CMAKE_SYSTEM_PROCESSOR xtensa)
|
||||
|
||||
set(CMAKE_C_COMPILER xt-clang)
|
||||
set(CMAKE_CXX_COMPILER xt-clang++)
|
||||
set(AS xt-clang)
|
||||
set(AR xt-ar)
|
||||
set(OBJCOPY xt-objcopy)
|
||||
set(OBJDUMP xt-objdump)
|
||||
set(SIZE xt-size)
|
||||
|
||||
set(THREADX_ARCH "xtensa")
|
||||
set(THREADX_TOOLCHAIN "xcc")
|
||||
|
||||
if (DEFINED ENV{XCC_OPTS})
|
||||
set(XCC_OPTS $ENV{XCC_OPTS})
|
||||
else()
|
||||
set(XCC_OPTS "")
|
||||
endif()
|
||||
|
||||
set(XCC_FLAGS "${XCC_OPTS} -mlongcalls -mno-l32r-flix -mno-coproc -Wall -Wextra -Werror")
|
||||
|
||||
set(CMAKE_C_FLAGS "${XCC_FLAGS} -Os -g" CACHE INTERNAL "c compiler flags")
|
||||
set(CMAKE_CXX_FLAGS "${XCC_FLAGS} -Os -g -fno-rtti -fno-exceptions" CACHE INTERNAL "cxx compiler flags")
|
||||
set(CMAKE_ASM_FLAGS "${XCC_FLAGS} -Os -g" CACHE INTERNAL "asm compiler flags")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${XCC_FLAGS} ${LD_FLAGS} -Wl,--gc-sections" CACHE INTERNAL "exe link flags")
|
||||
|
||||
SET(CMAKE_C_FLAGS_DEBUG "-O0 -g" CACHE INTERNAL "c debug compiler flags")
|
||||
SET(CMAKE_CXX_FLAGS_DEBUG "-O0 -g" CACHE INTERNAL "cxx debug compiler flags")
|
||||
SET(CMAKE_ASM_FLAGS_DEBUG "-O0 -g" CACHE INTERNAL "asm debug compiler flags")
|
||||
|
||||
SET(CMAKE_C_FLAGS_RELEASE "-Os -g" CACHE INTERNAL "c release compiler flags")
|
||||
SET(CMAKE_CXX_FLAGS_RELEASE "-Os -g" CACHE INTERNAL "cxx release compiler flags")
|
||||
SET(CMAKE_ASM_FLAGS_RELEASE "-Os -g" CACHE INTERNAL "asm release compiler flags")
|
||||
|
||||
# this makes the test compiles use static library option so that we don't need to pre-set linker flags and scripts
|
||||
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
|
||||
@@ -340,7 +340,10 @@ typedef unsigned short USHORT;
|
||||
#define TX_THREAD_EXTENSION_2
|
||||
|
||||
/* Execution profile related */
|
||||
#define TX_THREAD_EXTENSION_3
|
||||
#define TX_THREAD_EXTENSION_3 \
|
||||
unsigned long long tx_thread_execution_time_total; \
|
||||
unsigned long tx_thread_execution_time_last_start;
|
||||
|
||||
|
||||
/* Define the port extensions of the remaining ThreadX objects. */
|
||||
|
||||
|
||||
@@ -373,19 +373,8 @@ XSTRUCT_END(XtExcFrame)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
-------------------------------------------------------------------------------
|
||||
This flag is meant for internal use. Have all interrupts be dispatched via a
|
||||
common wrapper, which takes care of doing some OS-specific stuff common to
|
||||
all interrupt handlers. Said stuff cannot safely be handled in the RTOS_ENTER
|
||||
and RTOS_EXIT macros.
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
#if (defined TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || (defined XT_INTEXC_HOOKS)
|
||||
#define XT_USE_INT_WRAPPER 1
|
||||
#else
|
||||
#define XT_USE_INT_WRAPPER 0
|
||||
#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS > 32) && (defined XT_USE_SWPRI)
|
||||
#error "Software prioritization of interrupts (XT_USE_SWPRI) not supported for XEA2 with > 32 interrupts."
|
||||
#endif
|
||||
|
||||
#if XCHAL_HAVE_XEA3
|
||||
@@ -500,12 +489,15 @@ XSTRUCT_END(XtExcFrame)
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
// Call the thread entry function to indicate the thread is executing.
|
||||
// SP should be pointing to a safe region at this point.
|
||||
// SP should be pointing to a safe region at this point. Note that a9
|
||||
// may be trashed by this call, must be reloaded.
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
call0 _tx_execution_thread_enter
|
||||
#else
|
||||
call8 _tx_execution_thread_enter
|
||||
#endif
|
||||
movi a9, _tx_thread_current_ptr // a9 <- &_tx_thread_current_ptr
|
||||
l32i a9, a9, 0 // a9 <- _tx_thread_current_ptr
|
||||
#endif
|
||||
|
||||
l32i a2, a9, tx_thread_solicited // a2 = solicited flag
|
||||
|
||||
@@ -181,7 +181,11 @@ To enable interrupt/exception hooks, compile the RTOS with '-DXT_INTEXC_HOOKS'.
|
||||
#define XT_INTEXC_HOOK_NUM (1 + XCHAL_NUM_INTLEVELS + XCHAL_HAVE_NMI)
|
||||
|
||||
#ifndef __ASSEMBLER__
|
||||
#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS > 32)
|
||||
typedef uint32_t (*XT_INTEXC_HOOK)(uint32_t cause, uint32_t block);
|
||||
#else
|
||||
typedef uint32_t (*XT_INTEXC_HOOK)(uint32_t cause);
|
||||
#endif
|
||||
extern volatile XT_INTEXC_HOOK _xt_intexc_hooks[XT_INTEXC_HOOK_NUM];
|
||||
#endif
|
||||
|
||||
|
||||
@@ -108,7 +108,19 @@ Otherwise select the first low or medium priority interrupt timer available.
|
||||
#define XT_TIMER_INTPRI XCHAL_INT_LEVEL(XT_TIMER_INTNUM)
|
||||
|
||||
#if XCHAL_HAVE_XEA2
|
||||
#define XT_TIMER_INTEN (1 << XT_TIMER_INTNUM)
|
||||
/*
|
||||
* Xtensa LX8 supports up to 128 interrupts whereas LX7 supports up to 32.
|
||||
*
|
||||
* Redefine the legacy XT_TIMER_INTEN (which limited the interrupt number to
|
||||
* be in the lower 32 or lower 64 bits depending on data type) as two defines
|
||||
* describing the INTEN bit within a 32-bit component and a 4-block component,
|
||||
* where each block contains a group of 32 interrupt bits.
|
||||
*
|
||||
* Name changes are intentional such that any dependencies are caught at
|
||||
* compile-time and are found regardless of timer configuration.
|
||||
*/
|
||||
#define XT_TIMER_INTEN_BIT (1 << (XT_TIMER_INTNUM & 31U))
|
||||
#define XT_TIMER_INTEN_BLK (XT_TIMER_INTNUM >> 5)
|
||||
#endif
|
||||
|
||||
#if XT_TIMER_INDEX == 0
|
||||
|
||||
@@ -22,7 +22,6 @@ processor configuration options:
|
||||
- Timer interrupt option with at least one interruptible timer for ThreadX.
|
||||
- Interrupt option (implied by the timer interrupt option).
|
||||
- Xtensa Exception Architecture 2 (XEA2) or Exception Architecture 3 (XEA3).
|
||||
Please note that XEA1 is NOT supported.
|
||||
|
||||
Minimal support for certain evaluation boards is provided via a board
|
||||
independent "XTBSP" API implemented by a board specific library. This
|
||||
@@ -35,143 +34,66 @@ this board support (a "raw" platform), but you will have to provide the
|
||||
clock frequency and drivers for any on-board devices you want to use.
|
||||
|
||||
|
||||
2. Building the ThreadX run-time Library
|
||||
2. Building the ThreadX Library and the Xtensa Example
|
||||
|
||||
By default, you will build for the Xtensa instruction set simulator. If
|
||||
you have a supported emulation board, you can build to run on that. You
|
||||
can also build to run on a raw Xtensa core with no "board support", a
|
||||
good starting point for supporting your own target platform. Cadence Design Systems
|
||||
recommends doing functional development on the simulator because it
|
||||
is easier to debug with, then move to a board if/when you need to test
|
||||
hardware drivers or real-time performance.
|
||||
will have to provide the XTBSP functions for any other board you want to
|
||||
run on. We recommend you start by running on the simulator, then moving
|
||||
to your hardware target or emulation platform.
|
||||
|
||||
ThreadX/Xtensa comes with a Makefile as well as DOS .bat file, taking
|
||||
advantage of xt-make, a version of GNU make that comes with Xtensa Tools
|
||||
(you can just as well use generic GNU make if you have it installed).
|
||||
The Makefile works on any host platform and provides for incremental builds.
|
||||
The .bat file works on DOS/Windows only and always cleans before building.
|
||||
The build for each target platform is placed in a sub-directory so several
|
||||
platform builds can coexist even with incremental rebuilds.
|
||||
ThreadX/Xtensa is built using the ThreadX Cmake infrastructure. See the
|
||||
standard ThreadX documentation for details of the build process. In the
|
||||
cmake/ directory there is a file named xtensa.cmake which defines the
|
||||
Cmake configuration for the Xtensa target. Both Cmake and the Ninja tool
|
||||
need to be installed to build ThreadX.
|
||||
|
||||
First, make sure you have installed Xtensa Tools and your processor
|
||||
configuration, and be sure that Xtensa Tools are in your search path.
|
||||
You will also need to ensure that the Xtensa SDK tools have been installed
|
||||
and are on the path, and XTENSA_SYSTEM and XTENSA_CORE are set appropriately
|
||||
in the environment. Refer to the SDK documentation for details.
|
||||
|
||||
If you wish to build for an evaluation board that is supported by an
|
||||
external package, be sure the appropriate package is installed. See the
|
||||
introduction (section 0) to determine if you need an external package.
|
||||
If you are using an external board package, set the environment variable
|
||||
XTENSA_BOARDS to the absolute path of the root of the installed support
|
||||
package (or you can pass this to xt-make commands on the command line).
|
||||
eg. XTENSA_BOARDS = C:\usr\xtensa\RB-2007.1-xtav60 for Avnet LX60 board.
|
||||
You do not need to set XTENSA_BOARDS if using a Cadence Design Systems supported
|
||||
board with Xtensa Tools RB-2007.2 and up (support is bundled with the tools).
|
||||
The following commands will build the ThreadX library (some changes may be
|
||||
required based on your setup) -
|
||||
|
||||
Next, change directories to the ThreadX installation directory, as follows:
|
||||
cmake -S $(TX_SRCDIR) -B $(TX_BLDDIR) -DCMAKE_TOOLCHAIN_FILE=$(TX_SRCDIR)/cmake/xtensa.cmake -GNinja $(TX_SRCDIR)
|
||||
cmake --build $(TX_BLDDIR)
|
||||
|
||||
> cd c:\threadx\xtensa\gnu
|
||||
where TX_SRCDIR is the root of the ThreadX source tree, and TX_BLDDIR is
|
||||
the location where you want the build output to go.
|
||||
|
||||
Now build the ThreadX library (tx.a) by executing the build_threadx.bat
|
||||
batch file (or using the Makefile directly) while inside the threadx
|
||||
directory, as follows:
|
||||
Once the library is built, the Xtensa example can be built by going into
|
||||
the directory ports/xtensa/xcc/example_build and running this command -
|
||||
|
||||
> build_threadx.bat
|
||||
xt-clang -mlongcalls -Os -g -I../../../../common/inc -I../../../../common_smp/inc
|
||||
-I../../../../ports/xtensa/xcc/inc -o demo_threadx.exe demo_threadx.c
|
||||
../../../../build/libthreadx.a -lxtutil
|
||||
|
||||
which always builds for the simulator (but you can edit it), or
|
||||
|
||||
> xt-make
|
||||
|
||||
which by default builds for the simulator (PLATFORM=sim), or either of
|
||||
|
||||
> xt-make PLATFORM=board BOARD=<board>
|
||||
or
|
||||
> xt-make BOARD=<board>
|
||||
|
||||
which builds for a specified supported board (note PLATFORM=board is
|
||||
default when BOARD is defined). eg. BOARD=xtav60 for the Avnet LX60
|
||||
(XT-AV60) board.
|
||||
|
||||
> xt-make PLATFORM=raw
|
||||
|
||||
which builds for a raw Xtensa core with no "board support".
|
||||
|
||||
> xt-make PLATFORM=gdbio
|
||||
|
||||
Provides some very slow I/O support through the xt-gdb debugger.
|
||||
For GDBIO to work, xt-gdb must remain connected to the target.
|
||||
|
||||
If you are building for an Xtensa processor configuration that is not the
|
||||
default you selected when you installed Xtensa Tools, you need to define the
|
||||
environment variable XTENSA_CORE. If your configuration is not in the
|
||||
default registry you selected when you installed Xtensa Tools, you also
|
||||
need to define the environment variable XTENSA_SYSTEM. See tools manuals.
|
||||
You can avoid defining these in your environment if you pass the variables
|
||||
you need to redefine into xt-make as follows:
|
||||
|
||||
> xt-make XTENSA_CORE=<your_config_name> XTENSA_SYSTEM=<your_registry> ...
|
||||
|
||||
There are more details about build options in the comment in the Makefile.
|
||||
|
||||
At this point, all the ThreadX objects are located in a library file: tx.a .
|
||||
This file must be linked with your application in order to use ThreadX.
|
||||
This library and all the intermediate object files are placed in a platform
|
||||
specific sub-directory named the same as BOARD or PLATFORM (if BOARD is not
|
||||
defined), for example "sim", "xtkc705".
|
||||
|
||||
To build ThreadX with thread-safe C library support, define TX_THREAD_SAFE_CLIB
|
||||
in your build, as described in section 5 and in the Makefile. Please note
|
||||
that the C library is only safe for use in threads, not in interrupt handlers.
|
||||
It may also safely be used in tx_application_define (after tx_kernel_enter,
|
||||
before threads are running).
|
||||
to 1 (this is set by default in tx_port.h). Note that the C library is only
|
||||
safe for use in threads, not in interrupt handlers. It may also safely be used
|
||||
in tx_application_define (after tx_kernel_enter, before threads are running).
|
||||
|
||||
|
||||
3. Demonstration System
|
||||
3. Running the Example
|
||||
|
||||
The ThreadX demonstration is designed to execute under Xtensa instruction set
|
||||
simulator (ISS) or on a supported evaluation board programmed with your Xtensa
|
||||
processor configuration.
|
||||
The ThreadX Xtensa example is designed to be run on the Xtensa simulator (ISS)
|
||||
or a hardware target. By default the example is built for the simulator target.
|
||||
To run it,
|
||||
|
||||
Building the demonstration is easy, simply execute the build_threadx_demo.bat
|
||||
batch file while inside threadx directory, as follows:
|
||||
|
||||
> build_threadx_demo.bat
|
||||
xt-run demo_threadx.exe
|
||||
|
||||
or
|
||||
|
||||
> xt-make demo
|
||||
xt-gdb demo_threadx.exe (if you want to run it under the debugger)
|
||||
|
||||
Be sure to set or pass into xt-make the variables described in section 2 above
|
||||
for building the ThreadX library, including the PLATFORM or BOARD you want to
|
||||
run on.
|
||||
|
||||
This compiles demo_threadx.c (which is the demonstration application) and links
|
||||
it with the ThreadX objects in tx.a. The resulting file demo_threadx.out is a
|
||||
ELF binary file that can be downloaded and executed on the target.
|
||||
|
||||
The demo binary appears in the platform specific sub-directory described earlier.
|
||||
For the following commands, change to that directory or prepend it as the path
|
||||
of demo_threadx.out.
|
||||
|
||||
|
||||
To execute on the simulator:
|
||||
|
||||
> xt-run [--turbo] demo_threadx.out
|
||||
|
||||
The option --turbo provides much faster, but non-cycle-accurate simulation.
|
||||
Refer to the Xtensa simulator user manual for further simulator options.
|
||||
|
||||
|
||||
To execute on the simulator using the Xplorer GUI based debugger:
|
||||
|
||||
> xplorer --debug demo_threadx.out
|
||||
|
||||
|
||||
To execute on a supported evaluation board, download demo_threadx.out per
|
||||
instructions in the tools manuals. Be sure the board has been programmed
|
||||
with the correct configuration and is set up to boot from RAM and debug
|
||||
a downloaded program! Optionally you may connect a terminal or terminal
|
||||
emulator to the serial port on the board with settings as described in
|
||||
the board user manual, and see the output of printf on the terminal (if
|
||||
the demo was compiled with DEMO_USE_PRINTF or DEMO_USE_XTUTIL).
|
||||
To execute on a supported hardware target, download the example to the board
|
||||
following instructions in the SDK manuals. Make sure the board has been set
|
||||
up with the correct configuration (if emulation board) and is set up to boot
|
||||
from RAM and debug a downloaded program. Optionally you may connect a terminal
|
||||
or terminal emulator to the serial port on the board with settings as described
|
||||
in the board user manual, and see the output of printf on the terminal (if
|
||||
the board support package supports directing standard output to the port).
|
||||
|
||||
To obtain I/O on a "raw" platform such as an unsupported board, you need
|
||||
to provide low level I/O drivers (eg. inbyte() and outbyte() for character
|
||||
@@ -179,13 +101,8 @@ I/O if you want to use printf etc.). You can run "raw" executables on
|
||||
any Xtensa platform, including simulator and any board, but you will not
|
||||
see any behavior specific to the platform (eg. display, printed output,
|
||||
stopping simulation at end of program). You can, while debugging, use a
|
||||
debugger mechanism called GDBIO to obtain basic I/O. Use PLATFORM=GDBIO
|
||||
on your xt-make command line - this is the same as "raw" except it links
|
||||
some stubs that communicate through the debugger. It is very slow!
|
||||
|
||||
WARNING: It is tempting to add printf calls to other threads in the demo.
|
||||
If you modify the code in any way, you may need adjust affected threads'
|
||||
stack sizes. This is especially true if you add a printf call. See 4.5.
|
||||
debugger mechanism called GDBIO to obtain basic I/O. This requires linking
|
||||
with the gdbio support library. See the SDK documentation for details.
|
||||
|
||||
|
||||
4. System Initialization
|
||||
@@ -272,16 +189,14 @@ are provided in tx_port.h assuming no optimization (default, -O0).
|
||||
Threads that call C library functions may need larger stacks than those
|
||||
that don't. In particular, use of printf requires a very large stack and
|
||||
will usually cause a stack overflow if inserted in a thread without
|
||||
enlarging its stack size. See DEMO_STACK_SIZE_PRINTF in demo_threadx.c
|
||||
for a guideline. Use printf with care!
|
||||
enlarging its stack size.
|
||||
|
||||
|
||||
5. Assembler / Compiler Switches
|
||||
|
||||
The following are compiler switches used in building the ThreadX library
|
||||
and demonstration system. These can be supplied by editing the Makefile
|
||||
or by overriding the COPT or CFLAGS variables in the make command line
|
||||
(eg. make COPT="-O2 -DTX_THREAD_SAFE_CLIB"). More details in Makefile.
|
||||
and demonstration system. These can be supplied by editing the xtensa.cmake
|
||||
file or by overriding from the environment or command line.
|
||||
|
||||
Compiler Switch Meaning
|
||||
|
||||
@@ -291,7 +206,6 @@ Compiler Switch Meaning
|
||||
-mlongcalls Allows assembler and linker to convert call
|
||||
instructions to longer indirect call sequences
|
||||
when target is out of range.
|
||||
-x assembler-with-cpp Passes .s and .S files through C preprocessor.
|
||||
-Dmacro Define a preprocessor macro with no value.
|
||||
-Dmacro=value Define a preprocessor macro with a value.
|
||||
|
||||
@@ -306,9 +220,6 @@ Application Defines (preprocessor macros definable with the -D option):
|
||||
can be customized in tx_application_define.
|
||||
Default off.
|
||||
|
||||
NOTE: Thread safe support for Xtensa C library requires Xtensa Tools
|
||||
version RF-2015.2 or later.
|
||||
|
||||
TX_ENABLE_STACK_CHECKING Enable generic ThreadX support for stack
|
||||
overflow checking. This can help avoid long
|
||||
debugging sessions or customer support calls
|
||||
@@ -382,7 +293,8 @@ Application Defines (preprocessor macros definable with the -D option):
|
||||
higher bit numbers over those with lower bit
|
||||
numbers at the same level. This works only for
|
||||
low and medium priority interrupts that can be
|
||||
dispatched to C handlers.
|
||||
dispatched to C handlers on either NX cores or
|
||||
on LX cores with 32 or fewer interrupts.
|
||||
|
||||
TX_SYSTEM_STACK_SIZE=n Specify the size of the interrupt stack, which
|
||||
is the stack that all interrupt handlers switch
|
||||
@@ -455,7 +367,7 @@ If multiple threads use a register, the caller must save and restore it.
|
||||
|
||||
The saved context stack frames for context switches that occur as a result
|
||||
of interrupt handling (interrupt frame) or from thread-level API calls
|
||||
(solicited frame) are described in human readable form in xtensa_context.h .
|
||||
(solicited frame) are described in human readable form in xtensa_context.h.
|
||||
All suspended threads have one of these two types of stack frames. The top
|
||||
of the suspended thread's stack is pointed to by tx_thread_stack_ptr in the
|
||||
associated thread control block TX_THREAD. An Xtensa architecture port-specific
|
||||
|
||||
@@ -66,6 +66,8 @@ TX_MUTEX clib_lock_mutex;
|
||||
void
|
||||
__malloc_lock (struct _reent * ptr)
|
||||
{
|
||||
(void) ptr;
|
||||
|
||||
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
|
||||
return;
|
||||
}
|
||||
@@ -80,6 +82,8 @@ __malloc_lock (struct _reent * ptr)
|
||||
void
|
||||
__malloc_unlock (struct _reent * ptr)
|
||||
{
|
||||
(void) ptr;
|
||||
|
||||
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
|
||||
return;
|
||||
}
|
||||
@@ -99,6 +103,8 @@ __malloc_unlock (struct _reent * ptr)
|
||||
void
|
||||
__env_lock (struct _reent * ptr)
|
||||
{
|
||||
(void) ptr;
|
||||
|
||||
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
|
||||
return;
|
||||
}
|
||||
@@ -113,6 +119,8 @@ __env_lock (struct _reent * ptr)
|
||||
void
|
||||
__env_unlock (struct _reent * ptr)
|
||||
{
|
||||
(void) ptr;
|
||||
|
||||
if (_tx_thread_system_state != TX_INITIALIZE_IS_FINISHED) {
|
||||
return;
|
||||
}
|
||||
@@ -128,6 +136,12 @@ __env_unlock (struct _reent * ptr)
|
||||
#include <errno.h>
|
||||
#include <sys/reent.h>
|
||||
|
||||
#if defined(__DYNAMIC_REENT__)
|
||||
// Helps to keep code similar between dynamic and non-dynamic.
|
||||
#undef _reent_ptr
|
||||
struct _reent * _reent_ptr;
|
||||
#endif
|
||||
|
||||
#define XT_NUM_CLIB_LOCKS (_MAX_LOCK + FOPEN_MAX)
|
||||
|
||||
typedef TX_MUTEX * _Rmtx;
|
||||
@@ -201,6 +215,32 @@ _Mtxunlock (_Rmtx * mtx)
|
||||
|
||||
#endif /* XSHAL_CLIB == XTHAL_CLIB_XCLIB */
|
||||
|
||||
#if defined(__DYNAMIC_REENT__)
|
||||
/**************************************************************************/
|
||||
/* Return libc context pointer for current thread. Overrides weak */
|
||||
/* version in libc. Until real threads are active, use the libc's */
|
||||
/* global reent struct. */
|
||||
/**************************************************************************/
|
||||
struct _reent *
|
||||
__getreent(void)
|
||||
{
|
||||
TX_THREAD * thread_ptr = _tx_thread_current_ptr;
|
||||
|
||||
if (thread_ptr) {
|
||||
return &(thread_ptr->tx_thread_clib_reent);
|
||||
}
|
||||
|
||||
#if XSHAL_CLIB == XTHAL_CLIB_XCLIB
|
||||
extern struct _reent g_reent; /* from xclib */
|
||||
return &g_reent;
|
||||
#elif XSHAL_CLIB == XTHAL_CLIB_NEWLIB
|
||||
extern struct _reent * _impure_ptr; /* from newlib */
|
||||
return _impure_ptr;
|
||||
#else
|
||||
#error "Unsupported C library for __DYNAMIC_REENT__"
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/**************************************************************************/
|
||||
/* _sbrk_r - heap allocator. This function is called when the memory */
|
||||
|
||||
@@ -80,6 +80,8 @@ VOID _tx_initialize_low_level(VOID)
|
||||
|
||||
/* Disable interrupts - don't want any that interact with ThreadX yet. */
|
||||
TX_DISABLE
|
||||
/* Suppress compiler warning about set but not used variable. */
|
||||
(void) interrupt_save;
|
||||
|
||||
/*
|
||||
Disable stack limit checking if present. Whatever was set up earlier
|
||||
|
||||
@@ -166,9 +166,18 @@ _tx_thread_schedule:
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread entry function to indicate the thread is executing. */
|
||||
/* Note a2 may be trashed by this call, must be reloaded. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
call0 _tx_execution_thread_enter
|
||||
movi a2, _tx_thread_current_ptr
|
||||
l32i a2, a2, 0
|
||||
#else
|
||||
/* Ensure that PS.WOE is set for windowed call */
|
||||
movi a0, PS_WOE
|
||||
rsr.ps a3
|
||||
or a3, a3, a0
|
||||
wsr.ps a3
|
||||
rsync
|
||||
call8 _tx_execution_thread_enter
|
||||
#endif
|
||||
#endif
|
||||
@@ -229,14 +238,24 @@ _tx_thread_schedule:
|
||||
rsync /* ensure wsr.CPENABLE has completed */
|
||||
#endif
|
||||
|
||||
/* De-allocate the remainder of the frame before reenabling interrupts
|
||||
* to avoid overrunning a task stack of TX_MINIMUM_STACK bytes, which
|
||||
* can only handle one XT_STK_FRMSZ.
|
||||
*/
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/* 'addi sp, sp, imm' could turn into 'addmi, addi' sequence and make */
|
||||
/* the sp briefly point to an illegal stack location. Avoid that. */
|
||||
addi a2, sp, XT_STK_FRMSZ /* fully deallocate stack frame */
|
||||
mov sp, a2
|
||||
#else
|
||||
addi a2, sp, XT_STK_FRMSZ - 48 /* initial SP at solicited entry; */
|
||||
movsp sp, a2 /* retw will deallocate remainder */
|
||||
#endif
|
||||
|
||||
wsr a3, PS /* no need to sync PS, delay is OK */
|
||||
|
||||
/* This does not return to its caller, but to the selected thread. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/* 'addi sp, sp, imm' could turn into 'addmi, addi' sequence and make */
|
||||
/* the sp briefly point to an illegal stack location. Avoid that. */
|
||||
addi a2, sp, XT_STK_FRMSZ
|
||||
mov sp, a2
|
||||
ret
|
||||
#else
|
||||
retw
|
||||
|
||||
@@ -70,26 +70,25 @@ _tx_thread_system_return:
|
||||
Since this is solicited, no need to save regs compiler doesn't preserve.
|
||||
*/
|
||||
|
||||
#if XCHAL_HAVE_XEA3
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
addi sp, sp, -16
|
||||
addi a2, sp, -16 /* avoid addi/addmi relaxation that */
|
||||
mov sp, a2 /* might temporarily move sp up */
|
||||
#else
|
||||
entry sp, 48
|
||||
#endif
|
||||
#if XCHAL_HAVE_XEA3
|
||||
s32i a0, sp, 0 /* save return address */
|
||||
#else
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
addi a2, sp, -XT_STK_FRMSZ /* avoid addi/addmi relaxation that */
|
||||
mov sp, a2 /* might temporarily move sp up */
|
||||
#else
|
||||
entry sp, XT_STK_FRMSZ
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE))
|
||||
/* Call the thread exit function to indicate the thread is no longer executing. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/* Preserve a0 across the call. */
|
||||
#if !XCHAL_HAVE_XEA3
|
||||
s32i a0, sp, 0
|
||||
#endif
|
||||
call0 _tx_execution_thread_exit
|
||||
l32i a0, sp, 0
|
||||
#else
|
||||
call8 _tx_execution_thread_exit
|
||||
#endif
|
||||
@@ -109,6 +108,7 @@ _tx_thread_system_return:
|
||||
interrupts enabled, but we will have to revert SP to point above
|
||||
the exception frame because that is what the dispatch code expects.
|
||||
Must disable interrupts before that.
|
||||
TODO: disable interrupts prior to stack allocation as we do for XEA2
|
||||
*/
|
||||
|
||||
movi a0, .Lret
|
||||
@@ -185,7 +185,27 @@ _tx_thread_system_return:
|
||||
|
||||
#else /* XEA1 or XEA2 */
|
||||
|
||||
/* Disable interrupts before allocating the full stack frame. Taking
|
||||
* an interrupt will allocate a second exception stack frame, which will
|
||||
* overrun a task stack of TX_MINIMUM_STACK bytes.
|
||||
* Read PS so it can be saved off after stack adjustment.
|
||||
*/
|
||||
rsr a2, PS
|
||||
XT_INTS_DISABLE(a3)
|
||||
|
||||
/* Allocate the remainder of the frame here; we already allocated
|
||||
* 16 bytes for call0 or 48 bytes for windowed upon entry.
|
||||
* This memory will be deallocated in the solicited exit logic prior
|
||||
* to reenabling interrupts.
|
||||
*/
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
addi a3, sp, -XT_STK_FRMSZ + 16 // avoid addi/addmi relaxation again
|
||||
mov sp, a3
|
||||
#else
|
||||
addi a3, sp, -XT_STK_FRMSZ + 48
|
||||
movsp sp, a3
|
||||
#endif
|
||||
|
||||
s32i a0, sp, XT_STK_PC
|
||||
s32i a2, sp, XT_STK_PS
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
@@ -205,8 +225,6 @@ _tx_thread_system_return:
|
||||
wsr a2, PS
|
||||
rsync
|
||||
call0 xthal_window_spill_nw
|
||||
l32i a0, sp, XT_STK_PS
|
||||
wsr a0, PS // Restore PS value
|
||||
rsync
|
||||
#endif
|
||||
|
||||
@@ -226,10 +244,9 @@ _tx_thread_system_return:
|
||||
a4 = &_tx_timer_time_slice
|
||||
*/
|
||||
|
||||
/* Lock out interrupts (except hi-pri). */
|
||||
/* Already locked out interrupts (except hi-pri). */
|
||||
/* Grab thread control block of current thread. */
|
||||
movi a2, _tx_thread_current_ptr /* a2 = &_tx_thread_current_ptr */
|
||||
XT_INTS_DISABLE(a0)
|
||||
l32i a3, a2, 0 /* a3 points to TCB */
|
||||
|
||||
/* Mark as having solicited entry to kernel (used on exit). */
|
||||
|
||||
@@ -131,7 +131,7 @@ _xt_context_save:
|
||||
s32i a3, sp, XT_STK_ATOMCTL
|
||||
#endif
|
||||
|
||||
#if XT_USE_SWPRI
|
||||
#ifdef XT_USE_SWPRI
|
||||
/* Save virtual priority mask */
|
||||
movi a3, _xt_vpri_mask
|
||||
l32i a3, a3, 0
|
||||
@@ -318,7 +318,7 @@ _xt_context_restore:
|
||||
|
||||
ret
|
||||
|
||||
#endif /* XCHAL_HAVE_XEA3 */
|
||||
#endif /* XCHAL_HAVE_XEA2 */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
Copyright (c) 2006-2019 Cadence Design Systems Inc.
|
||||
Copyright (c) 2006-2023 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
|
||||
@@ -80,7 +80,7 @@ xt_exc_handler xt_set_exception_handler(uint32_t n, xt_exc_handler f)
|
||||
|
||||
#if XCHAL_HAVE_INTERRUPTS
|
||||
|
||||
#if XCHAL_HAVE_XEA2
|
||||
#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
|
||||
/* Defined in xtensa_intr_asm.S */
|
||||
extern uint32_t _xt_intenable;
|
||||
extern uint32_t _xt_vpri_mask;
|
||||
@@ -93,7 +93,7 @@ typedef struct xt_handler_table_entry {
|
||||
void * arg;
|
||||
} xt_handler_table_entry;
|
||||
|
||||
#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3)
|
||||
#if XCHAL_HAVE_XEA3
|
||||
extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS + 1];
|
||||
#else
|
||||
extern xt_handler_table_entry _xt_interrupt_table[XCHAL_NUM_INTERRUPTS];
|
||||
@@ -131,7 +131,7 @@ xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if (XT_USE_INT_WRAPPER || XCHAL_HAVE_XEA3)
|
||||
#if XCHAL_HAVE_XEA3
|
||||
entry = _xt_interrupt_table + n + 1;
|
||||
#else
|
||||
entry = _xt_interrupt_table + n;
|
||||
@@ -157,7 +157,7 @@ xt_handler xt_set_interrupt_handler(uint32_t n, xt_handler f, void * arg)
|
||||
*/
|
||||
void xt_interrupt_enable(uint32_t intnum)
|
||||
{
|
||||
#if XCHAL_HAVE_XEA2
|
||||
#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
|
||||
uint32_t ps = XT_RSIL(15);
|
||||
|
||||
// New INTENABLE = (_xt_intenable | mask) & _xt_vpri_mask.
|
||||
@@ -177,7 +177,7 @@ void xt_interrupt_enable(uint32_t intnum)
|
||||
*/
|
||||
void xt_interrupt_disable(uint32_t intnum)
|
||||
{
|
||||
#if XCHAL_HAVE_XEA2
|
||||
#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
|
||||
uint32_t ps = XT_RSIL(15);
|
||||
|
||||
// New INTENABLE = (_xt_intenable & ~mask) & _xt_vpri_mask.
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
-------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#if XCHAL_HAVE_XEA2
|
||||
#if XCHAL_HAVE_XEA2 && (XCHAL_NUM_INTERRUPTS <= 32)
|
||||
|
||||
.data
|
||||
.global _xt_intdata
|
||||
@@ -112,9 +112,6 @@ _xt_interrupt_table:
|
||||
#if XCHAL_HAVE_XEA3
|
||||
.word xt_interrupt_wrapper
|
||||
.word 0
|
||||
#elif XT_USE_INT_WRAPPER
|
||||
.word 0
|
||||
.word 0
|
||||
#endif
|
||||
|
||||
.set i, 0
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "tx_thread.h"
|
||||
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#include "tx_execution_profile.h"
|
||||
#include "../../utility/execution_profile_kit/tx_execution_profile.h"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@@ -75,6 +75,12 @@
|
||||
/* Enable stack backtrace across exception/interrupt - see below */
|
||||
#define XT_DEBUG_BACKTRACE 1
|
||||
|
||||
#if (XCHAL_NUM_INTERRUPTS > 32)
|
||||
#define XT_EXTD_INTERRUPTS 1
|
||||
#else
|
||||
#define XT_EXTD_INTERRUPTS 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
@@ -103,6 +109,97 @@
|
||||
addi \aout, \aout, 1 /* return aout + 1 */
|
||||
.endm
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Macro debug_backtrace
|
||||
|
||||
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.
|
||||
|
||||
Input : "ra" - Return address register (clobbered)
|
||||
Input : "tmp" - Temp register (clobbered), must be a different register
|
||||
Input : "level" - Numeric interrupt level
|
||||
Output : "ra" - Return address modified to simulate call4
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.macro debug_backtrace ra, tmp, level
|
||||
#if XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
rsr \ra, EPC_1 + \level - 1 /* return address */
|
||||
movi \tmp, 0xC0000000 /* constant with top 2 bits set (call size) */
|
||||
or \ra, \ra, \tmp /* set top 2 bits */
|
||||
addx2 \ra, \tmp, \ra /* clear top bit -- simulating call4 size */
|
||||
#endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Macro call_exec_isr_entry_fn
|
||||
|
||||
Call the ISR enter function to indicate an ISR is executing.
|
||||
|
||||
Inputs : None
|
||||
Output : Nothing
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
.macro call_exec_isr_entry_fn
|
||||
#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
/* Preserve a2 across the call, a12 is callee-saved for call0 ABI. */
|
||||
mov a12, a2
|
||||
call0 _tx_execution_isr_enter
|
||||
mov a2, a12
|
||||
#else
|
||||
call4 _tx_execution_isr_enter
|
||||
#endif
|
||||
#endif
|
||||
.endm
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Macro call_int_hook
|
||||
|
||||
Call interrupt hook if present to (pre)handle interrupts.
|
||||
NOTE: macro does not parameterize all used registers since they cannot freely
|
||||
be changed, either due to ABI conventions or other assembly code in this file.
|
||||
|
||||
Input : "level" - Interrupt level being processed
|
||||
Input : "block" - Index of interrupt block being processed [0..3]
|
||||
Input : "goto_on_done" - Label where control proceeds to if hook returns 0
|
||||
Input : a2 - bitmask of pending interrupts in block being processed [0..3]
|
||||
Output : a2 - updated bitmask of pending interrupts
|
||||
Clobbers : a2, a4, and:
|
||||
Clobbers : for windowed ABI: a6, a7
|
||||
Clobbers : for call0 ABI: a3
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
.macro call_int_hook level, block, goto_on_done
|
||||
#ifdef XT_INTEXC_HOOKS
|
||||
movi a4, _xt_intexc_hooks
|
||||
l32i a4, a4, \level << 2
|
||||
beqz a4, 2f
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
movi a3, \block
|
||||
callx0 a4
|
||||
beqz a2, \goto_on_done
|
||||
#else
|
||||
mov a6, a2
|
||||
movi a7, \block
|
||||
callx4 a4
|
||||
beqz a6, \goto_on_done
|
||||
mov a2, a6
|
||||
#endif
|
||||
2:
|
||||
#endif
|
||||
.endm
|
||||
|
||||
|
||||
/*
|
||||
--------------------------------------------------------------------------------
|
||||
Macro dispatch_c_isr - dispatch interrupts to user ISRs.
|
||||
@@ -124,59 +221,134 @@
|
||||
NOTE: This macro will use registers a0 and a2-a6. The arguments are:
|
||||
level -- interrupt level
|
||||
mask -- interrupt bitmask for this level
|
||||
mask1 -- interrupt bitmask for this level for bits 63:32 (XT_EXTD_INTERRUPTS)
|
||||
mask2 -- interrupt bitmask for this level for bits 95:64 (XT_EXTD_INTERRUPTS)
|
||||
mask3 -- interrupt bitmask for this level for bits 127:96 (XT_EXTD_INTERRUPTS)
|
||||
--------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
.macro dispatch_c_isr level mask
|
||||
.macro dispatch_c_isr level mask mask1 mask2 mask3
|
||||
|
||||
/* Get mask of pending, enabled interrupts at this level into a2. */
|
||||
|
||||
.L_xt_user_int_&level&:
|
||||
rsr a2, INTENABLE
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
|
||||
/* When > 32 interrupts are configured, maintain at least 2 instructions
|
||||
between RSR.INTERRUPT and branch instructions to avoid interlocks.
|
||||
*/
|
||||
#if (XCHAL_NUM_INTERRUPTS > 96)
|
||||
rsr a6, INTERRUPT3
|
||||
#endif
|
||||
#if (XCHAL_NUM_INTERRUPTS > 64)
|
||||
rsr a5, INTERRUPT2
|
||||
#endif
|
||||
rsr a4, INTERRUPT1
|
||||
rsr a3, INTERRUPT
|
||||
#if (XCHAL_NUM_INTERRUPTS > 96)
|
||||
_bnez a6, .L_xt_user_int_&level&_chk_blk3
|
||||
#endif
|
||||
#if (XCHAL_NUM_INTERRUPTS > 64)
|
||||
_bnez a5, .L_xt_user_int_&level&_chk_blk2
|
||||
#endif
|
||||
_bnez a4, .L_xt_user_int_&level&_chk_blk1
|
||||
_bnez a3, .L_xt_user_int_&level&_chk
|
||||
j 9f /* spurious */
|
||||
|
||||
#if (XCHAL_NUM_INTERRUPTS > 96)
|
||||
/* Identify and process block 3 interrupts. If none are active,
|
||||
proceed to check subsequent blocks; thus preserve a3-a5.
|
||||
*/
|
||||
.L_xt_user_int_&level&_chk_blk3:
|
||||
rsr a2, INTENABLE3
|
||||
and a2, a2, a6
|
||||
movi a6, \mask3
|
||||
and a2, a2, a6
|
||||
beqz a2, .L_xt_user_int_&level&_chk_blk2
|
||||
|
||||
/* Block 3 interrupt(s) pending */
|
||||
debug_backtrace a0, a4, \level
|
||||
call_exec_isr_entry_fn
|
||||
call_int_hook \level, 3, 9f
|
||||
extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
|
||||
wsr a4, INTCLEAR3 /* clear sw or edge-triggered interrupt */
|
||||
#ifndef TX_NO_TIMER
|
||||
#if (XT_TIMER_INTEN_BLK == 3)
|
||||
movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
|
||||
beq a3, a4, 7f /* if timer interrupt then skip table */
|
||||
#endif
|
||||
#endif
|
||||
movi a5, _xt_interrupt_table + 8*96 /* a5 = dispatch table for block 3 */
|
||||
j .L_xt_user_int_&level&_post_clear
|
||||
#endif
|
||||
|
||||
#if (XCHAL_NUM_INTERRUPTS > 64)
|
||||
/* Identify and process block 2 interrupts. If none are active,
|
||||
proceed to check subsequent blocks; thus preserve a3-a4.
|
||||
*/
|
||||
.L_xt_user_int_&level&_chk_blk2:
|
||||
rsr a2, INTENABLE2
|
||||
movi a6, \mask2
|
||||
and a2, a2, a5
|
||||
and a2, a2, a6
|
||||
beqz a2, .L_xt_user_int_&level&_chk_blk1
|
||||
|
||||
/* Block 2 interrupt(s) pending */
|
||||
debug_backtrace a0, a4, \level
|
||||
call_exec_isr_entry_fn
|
||||
call_int_hook \level, 2, 9f
|
||||
extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
|
||||
wsr a4, INTCLEAR2 /* clear sw or edge-triggered interrupt */
|
||||
#ifndef TX_NO_TIMER
|
||||
#if (XT_TIMER_INTEN_BLK == 2)
|
||||
movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
|
||||
beq a3, a4, 7f /* if timer interrupt then skip table */
|
||||
#endif
|
||||
#endif
|
||||
movi a5, _xt_interrupt_table + 8*64 /* a5 = dispatch table for block 2 */
|
||||
j .L_xt_user_int_&level&_post_clear
|
||||
#endif
|
||||
|
||||
/* Identify and process block 1 interrupts. If none are active,
|
||||
proceed to check subsequent blocks; thus preserve a3.
|
||||
*/
|
||||
.L_xt_user_int_&level&_chk_blk1:
|
||||
rsr a2, INTENABLE1
|
||||
movi a6, \mask1
|
||||
and a2, a2, a4
|
||||
and a2, a2, a6
|
||||
beqz a2, .L_xt_user_int_&level&_chk
|
||||
|
||||
/* Block 1 interrupt(s) pending */
|
||||
debug_backtrace a0, a4, \level
|
||||
call_exec_isr_entry_fn
|
||||
call_int_hook \level, 1, 9f
|
||||
extract_msb a4, a2 /* a4 = MSB of a2, a2 trashed */
|
||||
wsr a4, INTCLEAR1 /* clear sw or edge-triggered interrupt */
|
||||
#ifndef TX_NO_TIMER
|
||||
#if (XT_TIMER_INTEN_BLK == 1)
|
||||
movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
|
||||
beq a3, a4, 7f /* if timer interrupt then skip table */
|
||||
#endif
|
||||
#endif
|
||||
movi a5, _xt_interrupt_table + 8*32 /* a5 = dispatch table for block 1 */
|
||||
j .L_xt_user_int_&level&_post_clear
|
||||
|
||||
#else /* !XT_EXTD_INTERRUPTS */
|
||||
rsr a3, INTERRUPT
|
||||
#endif
|
||||
|
||||
.L_xt_user_int_&level&_chk:
|
||||
rsr a2, INTENABLE
|
||||
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.
|
||||
*/
|
||||
#if XT_DEBUG_BACKTRACE
|
||||
#ifndef __XTENSA_CALL0_ABI__
|
||||
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 TX_ENABLE_EXECUTION_CHANGE_NOTIFY
|
||||
/* Call the ISR enter function to indicate an ISR is executing. */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
call0 _tx_execution_isr_enter
|
||||
#else
|
||||
call4 _tx_execution_isr_enter
|
||||
#endif
|
||||
#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
|
||||
debug_backtrace a0, a4, \level
|
||||
call_exec_isr_entry_fn
|
||||
call_int_hook \level, 0, 9f
|
||||
|
||||
/* Now look up in the dispatch table and call user ISR if any. */
|
||||
/* If multiple bits are set then MSB has highest priority. */
|
||||
@@ -186,7 +358,7 @@
|
||||
#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.
|
||||
priority. NOTE: SWPRI disabled for XT_EXTD_INTERRUPTS.
|
||||
*/
|
||||
movi a3, \mask /* a3 = all interrupts at this level */
|
||||
add a2, a4, a4 /* a2 = a4 << 1 */
|
||||
@@ -205,33 +377,42 @@
|
||||
#endif
|
||||
|
||||
wsr a4, INTCLEAR /* clear sw or edge-triggered interrupt */
|
||||
|
||||
#ifndef TX_NO_TIMER
|
||||
movi a3, XT_TIMER_INTEN /* a3 = timer interrupt bit */
|
||||
#if (XT_TIMER_INTEN_BLK == 0)
|
||||
movi a3, XT_TIMER_INTEN_BIT /* a3 = timer interrupt bit */
|
||||
beq a3, a4, 7f /* if timer interrupt then skip table */
|
||||
#endif
|
||||
#endif
|
||||
movi a5, _xt_interrupt_table
|
||||
|
||||
/* Execution could arrive here from the direct, <= 32 interrupt case, or
|
||||
from one of the XT_EXTD_INTERRUPTS blocks. Regardless, we have:
|
||||
a4 = MSB (of 32-bit block) of pending interrupt bits, already cleared
|
||||
a5 = Base of interrupt table (of 32-bit block)
|
||||
*/
|
||||
.L_xt_user_int_&level&_post_clear:
|
||||
find_ms_setbit a3, a4, a3, 0 /* a3 = interrupt number */
|
||||
|
||||
movi a4, _xt_interrupt_table
|
||||
addx8 a3, a3, a4 /* a3 = address of interrupt table entry */
|
||||
addx8 a3, a3, a5 /* a3 = address of interrupt table entry */
|
||||
l32i a4, a3, XIE_HANDLER /* a4 = handler address */
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
#ifdef XT_USE_SWPRI
|
||||
mov a12, a6 /* save in callee-saved reg */
|
||||
#endif
|
||||
l32i a2, a3, XIE_ARG /* a2 = handler arg */
|
||||
callx0 a4 /* call handler */
|
||||
#ifdef XT_USE_SWPRI
|
||||
mov a2, a12
|
||||
#else
|
||||
#endif
|
||||
#else /* !__XTENSA_CALL0_ABI__ */
|
||||
#ifdef XT_USE_SWPRI
|
||||
mov a2, a6 /* save in windowed reg */
|
||||
#endif
|
||||
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:
|
||||
|
||||
@@ -245,24 +426,24 @@
|
||||
*/
|
||||
|
||||
#ifdef __XTENSA_CALL0_ABI__
|
||||
#ifdef XT_USE_SWPRI
|
||||
mov a12, a6
|
||||
#endif
|
||||
call0 XT_RTOS_TIMER_INT
|
||||
#ifdef XT_USE_SWPRI
|
||||
mov a2, a12
|
||||
#endif
|
||||
#else
|
||||
#ifdef XT_USE_SWPRI
|
||||
mov a2, a6
|
||||
#endif
|
||||
call4 XT_RTOS_TIMER_INT
|
||||
#endif
|
||||
.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:
|
||||
#ifdef XT_USE_SWPRI
|
||||
/*
|
||||
Restore old value of _xt_vpri_mask from a2. Also update INTENABLE from
|
||||
virtual _xt_intenable which _could_ have changed during interrupt
|
||||
@@ -275,7 +456,17 @@
|
||||
s32i a2, a3, 4 /* update _xt_vpri_mask */
|
||||
and a4, a4, a2 /* a4 = masked intenable */
|
||||
wsr a4, INTENABLE /* update INTENABLE */
|
||||
#endif
|
||||
|
||||
#elif XT_EXTD_INTERRUPTS
|
||||
|
||||
rsr a2, INTPBL /* INTPBL bit(n-1): pending Ln interrupt */
|
||||
bbsi.l a2, \level - 1, .L_xt_user_int_&level&
|
||||
|
||||
#else
|
||||
|
||||
j .L_xt_user_int_&level& /* check for more interrupts */
|
||||
|
||||
#endif /* XT_USE_SWPRI */
|
||||
|
||||
9:
|
||||
/* done */
|
||||
@@ -769,7 +960,11 @@ _xt_lowint1:
|
||||
|
||||
/* OK to call C code at this point, dispatch user ISRs */
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK XCHAL_INTLEVEL1_MASK1 XCHAL_INTLEVEL1_MASK2 XCHAL_INTLEVEL1_MASK3
|
||||
#else
|
||||
dispatch_c_isr 1 XCHAL_INTLEVEL1_MASK
|
||||
#endif
|
||||
|
||||
/* Done handling interrupts, transfer control to OS */
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
@@ -849,7 +1044,11 @@ _xt_medint2:
|
||||
|
||||
/* OK to call C code at this point, dispatch user ISRs */
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK XCHAL_INTLEVEL2_MASK1 XCHAL_INTLEVEL2_MASK2 XCHAL_INTLEVEL2_MASK3
|
||||
#else
|
||||
dispatch_c_isr 2 XCHAL_INTLEVEL2_MASK
|
||||
#endif
|
||||
|
||||
/* Done handling interrupts, transfer control to OS */
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
@@ -920,7 +1119,11 @@ _xt_medint3:
|
||||
|
||||
/* OK to call C code at this point, dispatch user ISRs */
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK XCHAL_INTLEVEL3_MASK1 XCHAL_INTLEVEL3_MASK2 XCHAL_INTLEVEL3_MASK3
|
||||
#else
|
||||
dispatch_c_isr 3 XCHAL_INTLEVEL3_MASK
|
||||
#endif
|
||||
|
||||
/* Done handling interrupts, transfer control to OS */
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
@@ -990,7 +1193,11 @@ _xt_medint4:
|
||||
|
||||
/* OK to call C code at this point, dispatch user ISRs */
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK XCHAL_INTLEVEL4_MASK1 XCHAL_INTLEVEL4_MASK2 XCHAL_INTLEVEL4_MASK3
|
||||
#else
|
||||
dispatch_c_isr 4 XCHAL_INTLEVEL4_MASK
|
||||
#endif
|
||||
|
||||
/* Done handling interrupts, transfer control to OS */
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
@@ -1060,7 +1267,11 @@ _xt_medint5:
|
||||
|
||||
/* OK to call C code at this point, dispatch user ISRs */
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK XCHAL_INTLEVEL5_MASK1 XCHAL_INTLEVEL5_MASK2 XCHAL_INTLEVEL5_MASK3
|
||||
#else
|
||||
dispatch_c_isr 5 XCHAL_INTLEVEL5_MASK
|
||||
#endif
|
||||
|
||||
/* Done handling interrupts, transfer control to OS */
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
@@ -1130,7 +1341,11 @@ _xt_medint6:
|
||||
|
||||
/* OK to call C code at this point, dispatch user ISRs */
|
||||
|
||||
#if XT_EXTD_INTERRUPTS
|
||||
dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK XCHAL_INTLEVEL6_MASK1 XCHAL_INTLEVEL6_MASK2 XCHAL_INTLEVEL6_MASK3
|
||||
#else
|
||||
dispatch_c_isr 6 XCHAL_INTLEVEL6_MASK
|
||||
#endif
|
||||
|
||||
/* Done handling interrupts, transfer control to OS */
|
||||
call0 XT_RTOS_INT_EXIT /* does not return directly here */
|
||||
|
||||
@@ -56,10 +56,28 @@ typedef unsigned long EXECUTION_TIME_SOURCE_TYPE;
|
||||
|
||||
/* Define basic constants for the execution profile kit. */
|
||||
|
||||
#if defined(__XTENSA__)
|
||||
|
||||
/* Example for Xtensa targets: */
|
||||
#ifndef TX_EXECUTION_TIME_SOURCE
|
||||
#include <xtensa/config/core.h>
|
||||
#if XCHAL_HAVE_CCOUNT
|
||||
#include <xtensa/tie/xt_timer.h>
|
||||
#define TX_EXECUTION_TIME_SOURCE (EXECUTION_TIME_SOURCE_TYPE) XT_RSR_CCOUNT()
|
||||
#else
|
||||
#define TX_EXECUTION_TIME_SOURCE 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else /* __XTENSA__ */
|
||||
|
||||
/* Example for Cortex-M targets: */
|
||||
#ifndef TX_EXECUTION_TIME_SOURCE
|
||||
#define TX_EXECUTION_TIME_SOURCE (EXECUTION_TIME_SOURCE_TYPE) *((volatile ULONG *) 0xE0001004)
|
||||
#endif
|
||||
|
||||
#endif /* __XTENSA__ */
|
||||
|
||||
#ifndef TX_EXECUTION_MAX_TIME_SOURCE
|
||||
#define TX_EXECUTION_MAX_TIME_SOURCE 0xFFFFFFFF
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user