mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-09-02 12:24:07 -04:00
Add Xtensa port
The project file is for Xtensa Xplorer simulator. Also add tests for one size stream buffer.
This commit is contained in:
parent
7d92e4dd8f
commit
c4b1afc4ef
34 changed files with 8564 additions and 5 deletions
764
FreeRTOS/Source/portable/ThirdParty/XCC/Xtensa/readme_xtensa.txt
vendored
Normal file
764
FreeRTOS/Source/portable/ThirdParty/XCC/Xtensa/readme_xtensa.txt
vendored
Normal file
|
@ -0,0 +1,764 @@
|
|||
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-
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue