FreeRTOS Port for Xtensa Configurable and Diamond Processors | |
============================================================ | |
FreeRTOS Kernel Version 10.0.0 | |
Introduction | |
------------ | |
This document describes the Xtensa port for FreeRTOS multitasking RTOS. | |
For an introduction to FreeRTOS itself, please refer to FreeRTOS | |
documentation. | |
This port currently works with FreeRTOS kernel version 10.0.0. | |
Xtensa Configuration Requirements and Restrictions | |
-------------------------------------------------- | |
The Xtensa configurable architecture supports a vast space of processor | |
features. This port supports all of them, including custom processor | |
extensions defined in the TIE language, with certain minimum | |
requirements. You must use Xtensa Tools to compile and link FreeRTOS and | |
your application for your Xtensa configuration. The port uses the Xtensa | |
Hardware Abstraction Layer (HAL) to adapt to your Xtensa configuration. | |
NOTE: It may be possible to build and run this with the open-source | |
xtensa-linux tools provided you have the correct overlay for your Xtensa | |
configuration. However, this has not been tested and is currently not | |
supported by Cadence. | |
This port includes optional reentrancy support for the 'newlib' and | |
'xclib' C runtime libraries distributed with Xtensa Tools, providing | |
thread-safety on a per task basis (for use in tasks only, not interrupt | |
handlers). | |
NOTE: At this time only 'newlib' and 'xclib' C libraries are supported | |
for thread safety. The 'uclibc' library is not reentrant and does not | |
provide thread safety at this time. However, if you are not concerned | |
with reentrancy then you can use any of these libraries. | |
This port also includes a simple example application that may run on | |
a supported board or the Xtensa instruction set simulator (ISS). There | |
are also a couple of test programs used in maintaining the port, which | |
serve as additional examples. | |
FreeRTOS for Xtensa configurable processors requires the following minimum | |
processor configuration options: | |
- Timer interrupt option with at least one interruptible timer. | |
- Interrupt option (implied by the timer interrupt option). | |
- Exception Architecture 2 (XEA2). Please note that XEA1 is NOT supported. | |
All 'Diamond', 'Xtensa 6', 'Xtensa LX' and 'Xtensa LX2' processors and | |
most 'Xtensa T1050' processors are configured with XEA2. | |
All Diamond processor cores meet these requirements and are supported. | |
Minimal support for certain evaluation boards is provided via a board | |
independent XTBSP API implemented by a board specific library distributed | |
with the Xtensa Tools. This provides the board clock frequency and basic | |
polled drivers for the display and console device. Note that XTBSP | |
is not a tradtional RTOS "board support package" with RTOS specific | |
interrupt-driven drivers - it is not specific to any RTOS. Note that | |
FreeRTOS can run on any Xtensa or Diamond board without 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. | |
Installation | |
------------ | |
The Xtensa port of FreeRTOS is available at this location: | |
https://github.com/foss-xtensa/amazon-freertos | |
This download includes the core FreeRTOS source and include files needed | |
to build the port. You can also download the official release of FreeRTOS | |
version 1.0.0 or later from this location: | |
https://github.com/aws/amazon-freertos | |
The Xtensa port files are currently not included in the official package. | |
All source is provided along with a Makefile that works for any host | |
platform supported by Xtensa Tools (Windows, Linux). These instructions | |
are written for Windows users, but can easily be understood and adapted | |
to other host platforms. | |
First install the FreeRTOS common package in a directory of your choosing. | |
The structure of that package will look like this: | |
<install directory> | |
|-- demos | |
| `-- cadence | |
| `-- sim | |
| |-- common | |
| | |-- application_code | |
| | | `-- cadence_code | |
| | `-- config_files | |
| `-- xplorer | |
`-- lib | |
|-- FreeRTOS | |
| `-- portable | |
| |-- Common | |
| |-- MemMang | |
| `-- XCC | |
| `-- Xtensa | |
`-- include | |
`-- private | |
The Xtensa Tools are available from Cadence as part of a processor | |
license. Be sure you have installed the Xtensa Tools and your processor | |
configuration. | |
Building FreeRTOS for Xtensa | |
---------------------------- | |
To build the FreeRTOS library and the example programs, go into the | |
directory 'demos/cadence/sim' and use the makefile in that directory. | |
"make all" will build all the examples. There is another makefile in | |
the 'lib/FreeRTOS/portable/XCC/Xtensa' directory that builds just the | |
FreeRTOS library. | |
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 | |
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. | |
The provided makefile simplifies building FreeRTOS and the example | |
for your Xtensa configuration and platform (ISS, board, etc.). There | |
are detailed instructions in the comments at the top of the makefile. | |
The makefiles work on Windows and Linux and support incremental builds. | |
The build for each Xtensa configuration and target platform is placed in | |
a subdirectory so several core and platform builds can co-exist even with | |
incremental rebuilds. You may specify the root of the build area (if tou | |
want it to be elsewhere than under the source tree) by defining BLDROOT | |
either in the make command or your shell environment. | |
Building the FreeRTOS Library | |
----------------------------- | |
First, be sure you have installed Xtensa Tools and your processor | |
configuration, and be sure that Xtensa Tools are in your search path. | |
You can use xt-make, which comes with the Xtensa Tools, to run the | |
makefiles. | |
Change directories to the Xtensa port directory: | |
> cd lib/FreeRTOS/portable/XCC/Xtensa | |
Now build the FreeRTOS RTOS as a library (libfreertos.a) as follows: | |
> xt-make | |
which by default builds for the simulator (TARGET=sim), or: | |
> xt-make TARGET=board | |
which builds for a supported board. Note that the board type does not | |
need to be specified when building the FreeRTOS library. | |
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. | |
After the library has been built, you must link your application with this | |
library in order to use FreeRTOS. | |
Building the FreeRTOS Examples | |
------------------------------ | |
The provided examples are designed to run on the Xtensa instruction set | |
simulator (ISS) or a supported evaluation board programmed with your | |
Xtensa processor configuration. | |
To build the examples for the default platform (simulator): | |
> cd demos/cadence/sim | |
> xt-make all | |
which is the same as | |
> xt-make all TARGET=sim | |
The boards currently supported are the Xilinx ML605 and KC705 FPGA | |
development boards. To target these boards, type | |
> xt-make all TARGET=ml605 | |
or | |
> xt-make all TARGET=kc705 | |
To build in a location other than the default, specify the new location | |
using the BLDROOT variable. Note that this makefile will invoke the | |
FreeRTOS library build makefile automatically, passing on the relevant | |
parameters based on what you specified. | |
You can override the default compilation options by specifying the new | |
options via CFLAGS. For example: | |
> xt-make all TARGET=sim CFLAGS="-O2 -Os -g" | |
This compiles the examples and links them with the FreeRTOS library | |
libfreertos.a and the appropriate linker-support package (LSP) for your | |
target platform (you can override the LSP by adding LSP=<lsp> to the | |
xt-make command line). The resulting ELF files can be downloaded and | |
executed on the target. The example binaries appear in the platform | |
specific subdirectory described earlier. | |
To build your application with thread-safe C library support, you | |
need to make certain modifications to the application to plug in and | |
invoke the reentrancy support. This allows each task to use the library | |
without interference with other tasks (it is not safe for interrupt | |
handlers to call the C library). | |
First, you must define | |
XT_USE_THREAD_SAFE_CLIB | |
to a nonzero value either in xtensa_config.h or on the compiler's command | |
line. Note that the default xtensa_config.h provided with this port does | |
define this to 1 if either newlib or xclib is detected. | |
Then, you must also make sure to allocate extra space on the stack for | |
each task that will use the C library reentrant functions. This extra | |
space is to be allocated over and above the actual stack space required | |
by the task itself. The define | |
XT_STACK_EXTRA_CLIB | |
specifies the amount of extra space to be added on to the stack to allow | |
saving the context for the C library as well as the coprocessors if any. | |
E.g. if your task requires 2000 bytes of stack space, you must allocate | |
(2000 + XT_STACK_EXTRA_CLIB) bytes for the stack. | |
IMPORTANT NOTE | |
-------------- | |
The header file FreeRTOS.h, which is a part of the core FreeRTOS sources, | |
includes <reent.h> if thread safety for the C libraries is enabled. For | |
xclib, this file exists in <sys/reent.h> and so is reported as missing. | |
To work around this, the makefiles supplied with this port will copy the | |
reent.h header into the build directory during the build process. If you | |
use a different build process, then you must make sure to copy this file | |
to a location that is included in the list of include paths. This can be | |
the build directory or the directory that contains the Xtensa port source | |
files. | |
Running or Debugging an Application | |
----------------------------------- | |
To execute the example application on the simulator: | |
> xt-run [--turbo] example.exe | |
The option --turbo provides much faster, but non-cycle-accurate simulation | |
(the --turbo option is only available with Xtensa Tools version 7 or later). | |
To execute on the simulator using the Xplorer GUI based debugger: | |
> xplorer --debug example.exe | |
To execute on a supported evaluation board, download example.exe 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. | |
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 | |
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. To use GDBIO, link | |
with the gdbio LSP. Refer to Xtensa tools documentation for details. | |
Task Stack Sizes | |
---------------- | |
The application must ensure that every task has enough space for its | |
stack. Each task needs enough space for its own use, its own interrupt | |
stack frame (defined in xtensa_context.h) and space to save coprocessor | |
state, if any. Several factors influence the size of the stack required, | |
including the compiler optimization level and the use of the C library. | |
Calls to standard output functions such as printf() can use up a lot of | |
stack space. The tool xt-stack-usage is helpful in determining safe stack | |
sizes for your application. | |
Some macros are provided in xtensa_config.h to help determine the stack | |
size for tasks that do and do not use the C library. Use these as the | |
basis for each task's stack size. They are minimum requirements taking | |
into account your configuration and use of the C library. In particular, | |
the define | |
XT_STACK_MIN_SIZE | |
defines the minimum stack size for any task. Be very careful if you try | |
to use a stack size smaller than this minimum. Stack overruns can cause | |
all kinds of hard-to-debug errors. It is recommended that you enable the | |
FreeRTOS stack checking features during development. | |
WARNING: The newlib printf() function uses a lot of stack space. Be very | |
careful in using it. Optionally you can use the 'libxtutil' library for | |
output - it implements a subset of printf() that has smaller code size | |
and uses far less stack space. More information about this library is in | |
the Xtensa Tools documentation. | |
Interrupt Stack | |
--------------- | |
Beginning with port version 1.2, the port uses a separate interrupt stack | |
for handling interrupts. Thus, it is no longer necessary for each task to | |
reserve space on its stack to handle interrupts. The size of the interrupt | |
stack is controlled by the parameter "configISR_STACK_SIZE" defined in | |
FreeRTOSConfig.h. Define this carefully to match your system requirements. | |
Assembler / Compiler Switches | |
----------------------------- | |
The following are compiler switches are used by the provided | |
Makefile in building the FreeRTOS library and example application. | |
These can be modified by editing the Makefile or by overriding the | |
CFLAGS variable in the make command line, for example: | |
> xt-make CFLAGS="-O2 -DXT_USE_THREAD_SAFE_CLIB" | |
-g Specifies debug information. | |
-c Specifies object code generation. | |
-On Sets compiler optimization level n (default -O0). | |
-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. | |
See the compiler / linker documentation for a full list of switches and | |
their use. | |
Many definitions can be provided at compile-time via the -D option | |
without editing the source code. Here are some of the more useful ones: | |
XT_USE_THREAD_SAFE_CLIB Enable support for the reentrancy to provide | |
thread-safety for the newlib and xclib libraries | |
supplied with Xtensa Tools. Default ON. | |
Note, the follwing defines are unique to the Xtensa port so have names | |
beginning with "XT_". | |
XT_SIMULATOR Set this if building to run on the simulator. | |
Takes advantage of certain simulator control | |
and reporting facilities, and adjusts timing | |
of periodic tick to provide a more acceptable | |
performance in simulation (see XT_CLOCK_FREQ). | |
Set by default unless PLATFORM is overridden. | |
XT_BOARD Set this if building for a supported board. | |
Be sure to specify the correct LSP for the | |
board. See the example makefile for usage. | |
XT_CLOCK_FREQ=freq Specifies the target processor's clock | |
frequency in Hz. Used primarily to set the | |
timer that generates the periodic interrupt. | |
Defaults are provided and may be edited in | |
xtensa_timer.h (see comments there also). | |
Default for simulator provides more acceptable | |
performance, but cannot provide real-time | |
performance due to variation in simulation | |
speed per host platform and insufficient | |
cycles between interrupts to process them. | |
Supported board platforms by default leave | |
this undefined and compute the clock frequency | |
at initialization unless this is explicitly | |
defined. | |
XT_TICK_PER_SEC=n Specifies the frequency of the periodic tick. | |
XT_TIMER_INDEX=n Specifies which timer to use for periodic tick. | |
Set this if your Xtensa processor configuration | |
provides more than one suitable timer and you | |
want to override the default. See xtensa_timer.h . | |
XT_INTEXC_HOOKS Enables hooks in interrupt vector handlers | |
to support dynamic installation of exception | |
and interrupt handlers. Disabled by default. | |
XT_USE_OVLY Enable code overlay support. It uses a mutex, | |
hence configUSE_MUTEX must be enabled. This | |
option is currently unsupported. | |
XT_USE_SWPRI Enable software prioritization of interrupts. | |
Enabling this will prioritize interrupts with | |
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. | |
Register Usage and Stack Frames | |
------------------------------- | |
The Xtensa architecture specifies two ABIs that determine how the general | |
purpose registers a0-a15 are used: the standard windowed ABI use with | |
the Xtensa windowed register file architecture, and the optional and | |
more conventional Call0 ABI (required for Xtensa configurations without | |
a windowed register file). | |
Xtensa processors may have other special registers (including co-processor | |
registers and other TIE "states") that are independent of this choice | |
of ABI. See Xtensa documentation for more details. | |
In the windowed ABI the registers of the current window are used as follows: | |
a0 = return address | |
a1 = stack pointer (alias sp) | |
a2 = first argument and result of call (in simple cases) | |
a3-7 = second through sixth arguments of call (in simple cases). | |
Note that complex or large arguments are passed on the | |
stack. Details are in the Xtensa Tools manuals. | |
a8-a15 = available for use as temporaries. | |
There are no callee-save registers. The windowed hardware automatically | |
saves registers a0-a3 on a call4, a0-a8 on a call8, a0-a12 on a call12, | |
by rotating the register window. Hardware triggers window overflow and | |
underflow exceptions as necessary when registers outside the current | |
window need to be spilled to preallocated space in the stack frame, or | |
restored. Complete details are in the Xtensa manuals. The entire windowed | |
register file is saved and restored on interrupt or task context switch. | |
The Call0 ABI does not make use of register windows, relying instead | |
on a fixed set of 16 registers without window rotation. | |
The Call0 ABI is more conventional and uses registers as follows: | |
a0 = return address | |
a1 = stack pointer (alias sp) | |
a2 = first argument and result of call (in simple cases) | |
a3-7 = second through sixth arguments of call (in simple cases). | |
Note that complex or large arguments are passed on the | |
stack. Details are in the Xtensa Tools manuals. | |
a8-a11 = scratch. | |
a12-a15 = callee-save (a function must preserve these for its caller). | |
On a FreeRTOS API call, callee-save registers are saved only when a task | |
context switch occurs, and other registers are not saved at all (the caller | |
does not expect them to be preserved). On an interrupt, callee-saved | |
registers might only be saved and restored when a task context-switch | |
occurs, but all other registers are always saved and restored. | |
An Xtensa processor has other special registers independent of the ABI, | |
depending on the configuration (including co-processor registers and other | |
TIE state) that are part of the task context. FreeRTOS preserves all such | |
registers over an unsolicited context-switch triggered by an interrupt. | |
However it does NOT preserve these over a solicited context-switch during | |
a FreeRTOS API call. This bears some explanation. These special registers | |
are either ignored by the compiler or treated as caller-saved, meaning | |
that if kept "live" over a function call (ie. need to be preserved) | |
they must be saved and restored by the caller. Since solicited entry to | |
FreeRTOS is always made by a function call, FreeRTOS assumes the caller | |
has saved any of these registers that are "live". FreeRTOS avoids a lot | |
of overhead by not having to save and restore every special register | |
(there can be many) on every solicited context switch. | |
As a consequence, the application developer should NOT assume that special | |
registers are preserved over a FreeRTOS API call such as vTaskDelay(). | |
If multiple tasks 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 task-level | |
API calls (solicited frame) are described in human readable form in | |
xtensa_context.h . All suspended tasks have one of these two types | |
of stack frames. The top of the suspended task's stack is pointed to | |
by pxCurrentTCB->pxTopOfStack. A special location common to both stack | |
frames differentiates solicited and interrupt stack frames. | |
Improving Performance, Footprint, or Ease of Debugging | |
------------------------------------------------------ | |
By default FreeRTOS for Xtensa is built with debug (-g) and without | |
compiler optimizations (-O0). This makes debugging easier. Of course, | |
-O0 costs performance and usually also increases stack usage. To make | |
FreeRTOS run faster you can change the Makefile to enable the desired | |
optimizations or set a predefined optimization level (-O<level>) . | |
Maximum performance is achieved with -O3 -ipa, but that might increase | |
the footprint substantially. A good compromise is -O2. See the compiler | |
manual for details. | |
Minimal footprint is achieved by optimizing for space with -Os, at the | |
cost of some performance. See the compiler manual for details. | |
The Xtensa architecture port-specific assembly files are coded with no | |
file-scope labels inside functions (all labels inside functions begin with | |
".L"). This allows a profiler to accurately associate an address with a | |
function, and also allows the debugger's stack trace to show the correct | |
function wherever the program counter is within that function. However | |
there are some tradeoffs in debugging. Local (".L") labels are not | |
visible to the debugger, so the following limitations may be observed | |
during debugging: | |
- You cannot set a breakpoint on a local label inside a function. | |
- Disassembly will show the entire function, but will get out of sync and | |
show incorrect opcodes if it crosses any padding before an aligned local | |
branch target (".L" label, not ".Ln"). Restart disassembly specifying an | |
address range explicitly between points where there is padding. | |
Since FreeRTOS is provided in source form, it is not difficult to remove | |
the ".L" and ".Ln" prefixes from local labels if you want them visible. | |
They can also be made visible by passing the '-L' option to the assembler | |
and linker (see the assembler and linker manuals for details). | |
Interrupt and Exception Handling | |
-------------------------------- | |
FreeRTOS provides a complete set of efficient exception and first-level | |
interrupt handlers installed at the appropriate exception and interrupt | |
vector locations. The Xtensa architecture supports several different | |
classes of exceptions and interrupts. Being a configurable architecture, | |
many of these are optional, and the vector locations are determined by | |
your processor configuration. (Note that Diamond cores are pre-configured | |
with specific vector locations.) The handlers provided use conditional | |
compilation to adapt to your processor configuration and include only | |
the code that is needed. | |
Xtensa vector locations may reside almost anywhere, including in ROM. | |
The amount of code space available at each of these locations is | |
often very small (e.g. due to following vectors). A small stub of | |
code installed at the vector jumps to the corresponding handler, | |
usually in RAM. The exception and interrupt handlers are defined in | |
xtensa_vectors.S. They are not specific to FreeRTOS, but call into | |
FreeRTOS where appropriate via macros defined in xtensa_rtos.h . | |
The handlers provided for low and medium priority interrupts are just | |
dispatchers that save relevant state and call user-definable handlers. | |
See the files xtensa_vectors.S and xtensa_api.h for more details of how | |
to create and install application-specific user interrupt handlers. | |
Similarly, user-defined handlers can be installed for exceptions (other | |
than a few which are always handled by the OS). | |
The high priority interrupt handlers provided may be considered templates | |
into which the application adds code to service specific interrupts. | |
The places where application handlers should be inserted are tagged with | |
the comment "USER_EDIT" in xtensa_vectors.S. | |
This FreeRTOS port supports strict priority-based nesting of interrupts. | |
An interrupt may only nest on top of one of strictly lower priority. | |
Equal priority interrupts concurrently pending are handled in an | |
application-defined sequence before any lower priority interrupts | |
are handled. During interrupt and exception handling, the processor's | |
interrupt level (PS.INTLEVEL) is used to control the interrupt priority | |
level that can be accepted; interrupt sources are not controlled | |
individually by FreeRTOS (the application is free to access the INTENABLE | |
register directly to enable/disable individual interrupts, eg. using | |
Xtensa HAL services). This approach provides the most deterministic | |
bounds on interrupt latency (for a given priority) and stack depth. | |
Software prioritization of interrupts at the same priority is controlled | |
by the definition of XT_USE_SWPRI. See above for a description of this | |
parameter. | |
The following subsections describe the handling of each class of exception | |
and interrupt in more detail. Many have nothing to do with FreeRTOS but | |
are mentioned because there is code to handle them in xtensa_vectors.S. | |
User Exception and Interrupt Handler (Low/Medium Priority): | |
All Xtensa 'general exceptions' come to the user, kernel, or double | |
exception vector. The exception type is identified by the EXCCAUSE | |
special register (level 1 interrupts are one particular cause of a | |
general exception). This port sets up PS to direct all such exceptions | |
to the user vector. Exceptions taken at the other two vectors usually | |
indicate a kernel or application bug. | |
Level 1 interrupts are identified at the beginning of the handler | |
and are dispatched to a dedicated handler. Then, syscall and alloca | |
exceptions are identified and dispatched to special handlers described | |
below. After this, coprocessor exceptions are identified and dispatched | |
to the coprocessor handler. | |
Any remaining exceptions are processed as follows: | |
Having allocated the exception stack frame, the user exception handler | |
saves the current task state and sets up a C environment and enables | |
the high-priority class of interrupts (which do not interact with | |
FreeRTOS), then reads EXCCAUSE and uses the cause (number) to index | |
into a table of user-specified handlers. The correct handler is then | |
called. If the handler returns, the context is restored and control is | |
returned to the code that caused the exception. The user-defined handler | |
may alter the saved context, or any other system state, that allows the | |
faulting instruction to be retried. | |
If the cause is a level 1 (low-priority) or medium-priority interrupt, | |
the handler enables all interrupts above that priority level after | |
saving the task context. It then sets up the environment for C code | |
and then calls the handler (found in the handler table) for the | |
interrupt number. If the user has not specified a handler, then the | |
default handler will be called, which will terminate the program. | |
If the interrupt is for the system timer, it calls a special interrupt | |
handler for the system timer tick, which calls _frxt_timer_int then | |
clears its bit from the mask. This interrupt cannot be hooked by the | |
user-defined handler. | |
Finally, the handler calls _frxt_int_exit to allow FreeRTOS to perform | |
any scheduling necessary and return either to the interrupted task | |
or another. | |
If software prioritization is enabled, the handler will re-enable all | |
interrupts at the same level that are numerically higher than the current | |
one, before calling the user handler. This allows a higher priority | |
interrupt to pre-empt the lower priority handler. | |
Medium Priority Interrupt Handlers: | |
Medium priority interrupts are those at levels 2 up to XCHAL_EXCM_LEVEL, | |
a configuration-specific maximum interrupt level affected by the global | |
'exception mode' bit in the processor status word (PS.EXCM). | |
Interrupt levels above XCHAL_EXCM_LEVEL are of the high-priority class. | |
The Xtensa hardware documentation considers medium priority interrupts | |
to be a special case of high-priority interrupts, but from a software | |
perspective they are very different. | |
Dispatch of medium-priority interrupts is discussed in the section | |
above. | |
High Priority Interrupt Handlers: | |
High priority interrupts are those strictly above XCHAL_EXCM_LEVEL, | |
a configuration-specific maximum interrupt level affected by the | |
global 'exception mode' bit in the processor status word (PS.EXCM). | |
High priority handlers may not directly interact with FreeRTOS at all, | |
and are described here only for the sake of completeness. They must | |
be coded in assembler (may not be coded in C) and are intended to be | |
used for handling extremely high frequency hardware events that need | |
to be handled in only a few cycles. A high priority interrupt handler | |
may trigger a software interrupt at a medium or low priority level to | |
occasionally signal FreeRTOS. Please see Xtensa documentation. | |
There is a separate vector and a few special registers for each high | |
priority interrupt, providing for fast dispatch and efficient nesting | |
on top of lower priority interrupts. Handlers are templates included | |
only for the vectors that exist in your Xtensa processor configuration. | |
These templates are written for only one interrupt per high priority | |
level to minimize latency servicing very fast time-critical interrupts. | |
The vector code jumps to the corresponding first-level interrupt handler, | |
which then executes application-provided assembler code before returning | |
quickly to the interrupted task or lower priority handler. | |
Kernel Exception Handler: | |
Kernel mode is not used in this port of FreeRTOS, and therefore kernel | |
exceptions should not happen. A stub is provided for the vector that | |
triggers the debugger (if connected) or calls _xt_panic to freeze the | |
processor should a kernel exception occur. | |
Alloca Exception Handler: | |
Alloca exceptions are generated by the 'movsp' instruction, which | |
is used only in the windowed ABI. Its purpose is to allocate some | |
space on top of the stack. Because the window hardware may have | |
spilled some registers to the 16 byte "base save" area below the | |
stack pointer, it is necessary to protect those values. The alloca | |
handler accomplishes this quickly without setting up an interrupt | |
frame or entering FreeRTOS, by emulating a register underflow and | |
re-executing 'movsp'. | |
Syscall Exception Handler: | |
Syscall exceptions are generated by a 'syscall' instruction. | |
The windowed ABI specifies that executing this instruction with | |
a value of zero in register a2 must spill any unsaved registers | |
in the windowed register file to their pre-determined locations | |
on the caller's stack. The handler does exactly that, and skips | |
over the 'syscall' instruction before returning to the caller. | |
If a2 is non-zero, the handler returns a2 == -1 to the caller. | |
Co-Processor Exception Handler: | |
A co-processor exception is generated when a task accesses a | |
co-processor that it does not "own". Ownership represents which | |
task's state is currently in the co-processor. Co-processors are | |
context-switched "lazily" (on demand) only when a non-owning task | |
uses a co-processor instruction, otherwise a task retains ownership | |
even when it is preempted from the main processor. The co-processor | |
exception handler performs the context-switch and manages ownership. | |
Co-processors may not be used by any code outside the context of a | |
task. A co-processor exception triggered by code that is not part | |
of a running task is a fatal error and FreeRTOS for Xtensa will panic. | |
This restriction is intended to reduce the overhead of saving and | |
restoring co-processor state (which can be quite large) and in | |
particular remove that overhead from interrupt handlers. | |
Debug Exception Handler: | |
A debug exception is caused as a result of running code, such as by | |
a 'break' instruction or hardware breakpoints and watchpoints, or | |
as a result of an external debug interrupt, such as from an OCD based | |
debugger or multiprocessor debug events ("breakin/breakout"). If the | |
processor is running in OCD mode under control of an OCD-based debugger, | |
the trigger event immediately halts the processor and gives control to | |
the OCD debugger. Otherwise control is transferred to the debug vector. | |
The debug vector handler calls the simulator if running on the ISS, | |
which then takes control and interacts with any attached debugger. | |
If running on hardware and not in OCD mode, debug exceptions are not | |
expected, so the debug handler calls _xt_panic to freeze the processor. | |
Double Exception Handler: | |
A double exception is a general exception that happens while the | |
processor is in exception mode (PS.EXCM set), and thus indicates a | |
bug in kernel code. The double exception vector handler triggers | |
the debugger (if connected) or calls _xt_panic to freeze the | |
processor. | |
Window Overflow and Underflow Exception Handlers: | |
Window overflow and underflow handlers are required for use of the | |
windowed ABI. Each has its own dedicated vector and highly optimized | |
code that is independent of OS. See Xtensa documentation for details. | |
Hooks for Dynamic Installation of Handlers: | |
Optional hooks are provided in the user exception and low level | |
interrupt handler and all medium and high priority interrupt handlers, | |
to dynamically install a handler function (which may be coded in C, | |
unless in a high-priority interrupt handler). These hooks are enabled | |
and used by automatic regression tests, they are not part of a normal | |
FreeRTOS build. However an application is free to take advantage of | |
them. The interrupt/exception hooks are described in xtensa_rtos.h . | |
It is recommended that the application not make use of these hooks, but | |
rather use xt_set_interrupt_handler() and xt_set_exception_handler() | |
to install application-specific handlers. This method is more convenient | |
and allows arguments to be passed to the handlers. Software prioritization | |
of interrupts works only with this method. See xtensa_api.h for details. | |
Overlay Support | |
Code overlays are currently not supported for FreeRTOS. This will be | |
supported in a future release. Make sure that the option XT_USE_OVLY is | |
never defined when building. | |
-End- | |