Download FreeRTOS
 

Quality RTOS & Embedded Software

KERNEL
WHAT'S NEW
Simplifying Authenticated Cloud Connectivity for Any Device.
Designing an energy efficient and cloud-connected IoT solution with CoAP.
Introducing FreeRTOS Kernel version 11.0.0:
FreeRTOS Roadmap and Code Contribution process.
OPC-UA over TSN with FreeRTOS.

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:


Features of the FreeRTOS ARM Cortex-A RTOS port

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).


Using the floating point unit (FPU)

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;

/* This task is going to use floating point operations. Therefore it calls
portTASK_USES_FLOATING_POINT() once on task entry, before entering the loop
that implements its functionality. From this point on the task has a floating
point context. */

portTASK_USES_FLOATING_POINT();

/* Enter the loop that implements the task's function. */
for( ;; )
{
/* portTASK_USES_FLOATING_POINT() has already been called, so it is safe
to use the floating point x and y variables here... */

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.


ARM Cortex-A specific FreeRTOSConfig.h settings

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.


Configuring and installing the RTOS tick interrupt

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:


/* Implement a function in a C file to generate a periodic interrupt at the
required frequency. */

void vSetupTickInterrupt( void )
{
/* FreeRTOS_Tick_Handler() is itself defined in the RTOS port layer. An extern
declaration is required to allow the following code to compile. */

extern void FreeRTOS_Tick_Handler( void );

/* Assume TIMER1_configure() configures a hypothetical timer peripheral called
TIMER1 to generate a periodic interrupt with a frequency set by its parameter. */

TIMER1_configure( configTICK_RATE_HZ );

/* Next assume Install_Interrupt() installs the function passed as its second
parameter as the handler for the peripheral passed as its first parameter. */

Install_Interrupt( TIMER1, FreeRTOS_Tick_Handler );
}

Defining a function that configures a timer to generate a periodic tick


/* Given the function definition above, add the following line to FreeRTOSConfig.h. */
#define configSETUP_TICK_INTERRUPT() vSetupTickInterrupt()

#defining configSETUP_TICK_INTERRUPT() to the function that generates the periodic tick


Interrupt handling

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.


Installing the FreeRTOS IRQ and SWI (SVC) interrupt handlers

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


Cortex-A processor modes and stacks

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.