Using FreeRTOS on ARM Cortex-A9 Embedded Processors
That use a proprietary interrupt controller
Introduction
Some ARM Cortex-A processors incorporate ARM's own Generic Interrupt Controller
(GIC), while others incorporate proprietary interrupt controllers. Separate web
pages are provided to give instructions on using the RTOS in both scenarios.
This page provides information on running the RTOS on an ARM Cortex-A
embedded processor that does not incorporates ARM's own Generic Interrupt Controller (GIC).
See also the web page that describes
running the RTOS on an ARM Cortex-A
embedded processor that also includes ARM's GIC.
On this page:
The FreeRTOS ARM Cortex-A port for microprocessors that use a proprietary
interrupt controller:
-
Extends the use of the familiar, small, simple, deterministic,
de facto standard FreeRTOS kernel beyond the microcontroller
market
-
Supports interrupt nesting (note that, unlike the
RTOS version for ARM
Cortex-A parts that incorporate a GIC, the version for processors
with a proprietary interrupt controller does not
keep a subset of interrupt priorities permanently enabled - this is
because no assumptions are made as to the interrupt controller in use).
-
Includes hardware floating point support
-
Uses a flat/linear memory model (the MMU is not supported).
Tasks that make use of the hardware floating point unit must call portTASK_USES_FLOATING_POINT()
before any floating point calculations are executed. It is only necessary to
call portTASK_USES_FLOATING_POINT() once per task. For example:
void vATaskFunction( void *pvParameters )
{
double x, y;
portTASK_USES_FLOATING_POINT();
for( ;; )
{
x = [whatever];
y = [whatever];
}
}
Calling portTASK_USES_FLOATING_POINT() before any floating point calculations are performed
It should be noted that, by default, the Cortex-A9 port does not support the use of the floating point
unit in interrupts. If it is necessary to use the floating point unit in interrupts
then it will also be necessary to save the entire floating point context to the
stack on entry to each (potentially nested) interrupt.
The following settings must be included in FreeRTOSConfig.h. Note these settings
are specific to the ARM Cortex-A RTOS port for processors that use a proprietary
interrupt controller. The settings for the RTOS port for ARM Cortex-A processors
that use the ARM GIC are different because they also configure the GIC.
-
configFPU_D32
If the FPU has 16 'd' registers then set configFPU_D32 to 0. If the
FPU has 32 'd' registers then set configFPU_D32 to 1.
-
configINTERRUPT_VECTOR_ADDRESS
Most interrupt controllers contain a register from which the address of
the currently asserted (executing) interrupt handler can be read. If
such a register exists then set configINTERRUPT_VECTOR_ADDRESS to its
address. If such a register does not exist then set configINTERRUPT_VECTOR_ADDRESS
to the address of a variable that points to a central interrupt handler.
-
configEOI_ADDRESS
Most interrupt controllers contain an End of Interrupt (EOI) register
that must be written to at the end of an interrupt handing routine. If
such a register exists then set configEIO_ADDRESS to its address. If a
register does not exist then set configEIO_ADDRESS to the address of a
variable to which writes will be harmless.
-
configCLEAR_TICK_INTERRUPT()
As described in the "Configuring and installing the RTOS tick interrupt"
section below, the RTOS tick interrupt can be generated from any
convenient timer source. If the interrupt generated by the selected
timer must be cleared within its handling function then defined
configCLEAR_TICK_INTERRUPT() to clear the interrupt. If the interrupt
generated by the selected timer does not require explicit clearing then
configCLEAR_TICK_INTERRUPT() can be defined to nothing (so it does not
generate any code).
Note: If there is an official demo for
the Cortex-A9 processor you are using then the
FreeRTOSConfig.h file provided with the demo will already contain the correct
settings.
Every official FreeRTOS demo that targets an ARM Cortex-A based embedded processor
includes code to configure a timer to generate the RTOS tick interrupt, and install
the FreeRTOS tick interrupt handler. The following information is only required
if you need to change the provided implementation.
The macro configSETUP_TICK_INTERRUPT() is called by the RTOS kernel port layer.
configSETUP_TICK_INTERRUPT() must be #defined in FreeRTOSConfig.h to configure
a peripheral to generate a periodic interrupt at the frequency set by the
configTICK_RATE_HZ FreeRTOSConfig.h setting. FreeRTOS_Tick_Handler() must then
be installed as the interrupt's handling function. For example:
void vSetupTickInterrupt( void )
{
extern void FreeRTOS_Tick_Handler( void );
TIMER1_configure( configTICK_RATE_HZ );
Install_Interrupt( TIMER1, FreeRTOS_Tick_Handler );
}
Defining a function that configures a timer to generate a periodic tick
#define configSETUP_TICK_INTERRUPT() vSetupTickInterrupt()
#defining configSETUP_TICK_INTERRUPT() to the function that generates the periodic tick
Official RTOS demo applications
include example interrupt handlers. Refer to the official RTOS demo application
for the processor in use to find examples and reference source code.
Interrupt entry, nesting, and exit is managed by the RTOS kernel port layer so
interrupt handlers provided by the application writer can be standard C functions.
Specific interrupt related pragmas, assembly code wrappers or attribute
qualifiers are not required.
Interrupt handling routes provided by the application writer are called by the
RTOS with interrupts enabled.
Also see the description of the configINTERRUPT_VECTOR_ADDRESS FreeRTOSConfig.h
setting above.
FreeRTOS_IRQ_Handler() must be installed as the Cortex-A's IRQ handler.
FreeRTOS_SWI_Handler() must be installed as the Cortex-A's SWI (SVC) handler.
If it is not possible to edit the interrupt vector code then map the FreeRTOS
handlers to the required handler names using #defines in FreeRTOSConfig.h. For example,
if the installed handlers are called IRQ_Handler() and SWI_Handler() respectively, then
the FreeRTOS handlers can be mapped to these names by adding the following two lines
to FreeRTOSConfig.h.
#define FreeRTOS_IRQ_Handler IRQ_Handler
#define FreeRTOS_SWI_Handler SWI_Handler
Mapping the FreeRTOS interrupt handler names to alternative handler names
The C start up code must, as a minimum, configure stacks for the IRQ and Supervisor modes
of the Cortex-A processor. main() must be called from a privileged mode, preferably
Supervisor mode.
It is not necessary to allocate a stack to User/System mode unless main() is
called from System mode (main() must not be called from User mode). If a stack
is allocated to User/System mode it will not be used after the RTOS kernel has
been started.
The RTOS stack overflow detection functionality only detects overflows in
task stacks, not IRQ or Supervisor stacks.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.