diff --git a/cmake/xtensa.cmake b/cmake/xtensa.cmake new file mode 100644 index 000000000..2f5fa6939 --- /dev/null +++ b/cmake/xtensa.cmake @@ -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) diff --git a/ports/xtensa/xcc/inc/tx_port.h b/ports/xtensa/xcc/inc/tx_port.h index a8897815d..d6503b4fe 100644 --- a/ports/xtensa/xcc/inc/tx_port.h +++ b/ports/xtensa/xcc/inc/tx_port.h @@ -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. */ diff --git a/ports/xtensa/xcc/inc/xtensa_context.h b/ports/xtensa/xcc/inc/xtensa_context.h index 11174fff5..2d06948b9 100644 --- a/ports/xtensa/xcc/inc/xtensa_context.h +++ b/ports/xtensa/xcc/inc/xtensa_context.h @@ -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 diff --git a/ports/xtensa/xcc/inc/xtensa_rtos.h b/ports/xtensa/xcc/inc/xtensa_rtos.h index d8db73bcf..ef62035ee 100644 --- a/ports/xtensa/xcc/inc/xtensa_rtos.h +++ b/ports/xtensa/xcc/inc/xtensa_rtos.h @@ -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 diff --git a/ports/xtensa/xcc/inc/xtensa_timer.h b/ports/xtensa/xcc/inc/xtensa_timer.h index 957a42ed7..fbbe48718 100644 --- a/ports/xtensa/xcc/inc/xtensa_timer.h +++ b/ports/xtensa/xcc/inc/xtensa_timer.h @@ -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 diff --git a/ports/xtensa/xcc/readme_threadx.txt b/ports/xtensa/xcc/readme_threadx.txt index 3ad4aec2e..3f45c95f1 100644 --- a/ports/xtensa/xcc/readme_threadx.txt +++ b/ports/xtensa/xcc/readme_threadx.txt @@ -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= -or -> xt-make 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= XTENSA_SYSTEM= ... - -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 -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. +3. Running the Example -Building the demonstration is easy, simply execute the build_threadx_demo.bat -batch file while inside threadx directory, as follows: +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, -> 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 diff --git a/ports/xtensa/xcc/src/tx_clib_lock.c b/ports/xtensa/xcc/src/tx_clib_lock.c index 9e3087202..12ee09427 100644 --- a/ports/xtensa/xcc/src/tx_clib_lock.c +++ b/ports/xtensa/xcc/src/tx_clib_lock.c @@ -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 #include +#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,31 @@ _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; +#endif +#if XSHAL_CLIB == XTHAL_CLIB_NEWLIB + extern struct _reent * _impure_ptr; /* from newlib */ + return _impure_ptr; +#endif +} +#endif /**************************************************************************/ /* _sbrk_r - heap allocator. This function is called when the memory */ diff --git a/ports/xtensa/xcc/src/tx_initialize_low_level.c b/ports/xtensa/xcc/src/tx_initialize_low_level.c index de2c2b935..d52689cf4 100644 --- a/ports/xtensa/xcc/src/tx_initialize_low_level.c +++ b/ports/xtensa/xcc/src/tx_initialize_low_level.c @@ -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 diff --git a/ports/xtensa/xcc/src/tx_thread_schedule.S b/ports/xtensa/xcc/src/tx_thread_schedule.S index 448dc6d76..6c5951707 100644 --- a/ports/xtensa/xcc/src/tx_thread_schedule.S +++ b/ports/xtensa/xcc/src/tx_thread_schedule.S @@ -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 - wsr a3, PS /* no need to sync PS, delay is OK */ - - /* This does not return to its caller, but to the selected thread. */ + /* 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 + 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__ ret #else retw diff --git a/ports/xtensa/xcc/src/tx_thread_system_return.S b/ports/xtensa/xcc/src/tx_thread_system_return.S index d1fc4a9ff..af0fa24bf 100644 --- a/ports/xtensa/xcc/src/tx_thread_system_return.S +++ b/ports/xtensa/xcc/src/tx_thread_system_return.S @@ -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). */ diff --git a/ports/xtensa/xcc/src/xtensa_context.S b/ports/xtensa/xcc/src/xtensa_context.S index e4b9aa0a7..7e58ba14c 100644 --- a/ports/xtensa/xcc/src/xtensa_context.S +++ b/ports/xtensa/xcc/src/xtensa_context.S @@ -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 */ /******************************************************************************* diff --git a/ports/xtensa/xcc/src/xtensa_intr.c b/ports/xtensa/xcc/src/xtensa_intr.c index c5f320cb5..2f0622cda 100644 --- a/ports/xtensa/xcc/src/xtensa_intr.c +++ b/ports/xtensa/xcc/src/xtensa_intr.c @@ -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. diff --git a/ports/xtensa/xcc/src/xtensa_intr_asm.S b/ports/xtensa/xcc/src/xtensa_intr_asm.S index e972378a6..c2bf15741 100644 --- a/ports/xtensa/xcc/src/xtensa_intr_asm.S +++ b/ports/xtensa/xcc/src/xtensa_intr_asm.S @@ -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 diff --git a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c index 4ccb29f5b..76efec68c 100644 --- a/ports/xtensa/xcc/src/xtensa_intr_wrapper.c +++ b/ports/xtensa/xcc/src/xtensa_intr_wrapper.c @@ -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 diff --git a/ports/xtensa/xcc/src/xtensa_vectors.S b/ports/xtensa/xcc/src/xtensa_vectors.S index 7b09638e4..1dedd83d1 100644 --- a/ports/xtensa/xcc/src/xtensa_vectors.S +++ b/ports/xtensa/xcc/src/xtensa_vectors.S @@ -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 - movi a4, \mask - and a2, a2, a3 - and a2, a2, a4 - beqz a2, 9f /* nothing to do */ + #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 */ - /* 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 (XCHAL_NUM_INTERRUPTS > 96) + /* Identify and process block 3 interrupts. If none are active, + proceed to check subsequent blocks; thus preserve a3-a5. */ - #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 */ +.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 - #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 + #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 - #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 + /* 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 -2: #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 */ + + 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 */ diff --git a/utility/execution_profile_kit/tx_execution_profile.h b/utility/execution_profile_kit/tx_execution_profile.h index fa09ac2ed..0b82082cf 100644 --- a/utility/execution_profile_kit/tx_execution_profile.h +++ b/utility/execution_profile_kit/tx_execution_profile.h @@ -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 +#if XCHAL_HAVE_CCOUNT +#include +#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