Atmel AT91FR40008 (ARM7) RTOS Port
The port was developed by John Feller on an ATEB40X prototyping board
from Embest (Atmel AT91EB40 clone) using the open source GCC development tools (instructions are provided should you wish to use an alternative development board).
The development board came with a parallel port JTAG interface and flash programming utility.
IMPORTANT! Notes on using the AT91R40008 RTOS port
Please read all the following points before using this RTOS port.
See also the FAQ My application does not run, what could be wrong?
- Source Code Organisation
- The Demo Application
- Configuration and Usage Details
Source Code Organization
The FreeRTOS download contains the source code for all the FreeRTOS ports.
See the Source Code Organization section for a description of the
downloaded files and information on creating a new project.
The AT91R40008 GCC demo application makefile is contained in the FreeRTOS/Demo/ARM7_AT91FR40008_GCC directory.
The directory FreeRTOS/Demo/ARM7_AT91FR40008_GCC/Serial contains a sample interrupt driven serial port driver.
The Demo Application
The FreeRTOS source code download includes a fully preemptive multitasking demo application for the AT91 GCC RTOS port.
ARM, THUMB, ROM and RAM builds
The following batch files are provided to build the demo application. The batch files set the environment
variables necessary for the relevant built before calling make.
The batch files are contained in the Demo/ARM7_AT91FR40008_GCC directory. Switching from one batch file to
the other requires a complete rebuild. To force a complete rebuild 'touch' the makefile.
- ROM_ARM.bat - Creates an ARM mode release build suitable for programming into flash.
- RAM_ARM.bat - Creates an ARM mode debug build suitable for execution from RAM.
- ROM_THUMB.bat - Creates a THUMB mode release build suitable for programming into flash.
- RAM_THUMB.bat - Creates a THUMB mode debug build suitable for execution from RAM.
RTOS Demo application hardware setup
The demo application includes the ComTest tasks - where one task transmits RS232 characters to another. For correct operation
of this real time task a loopback connector must be fitted to the RS232 port 0 of the Embest prototyping board (pins 2 and 3
must be connected together on the 9Way connector).
The demo application uses the LEDs built onto the prototyping board so no further hardware setup is required.
Building and executing the RTOS demo application - Standalone from flash
The RTOS demo application can be executed either from flash or from RAM. This section provides instructions on creating and
programming a release build into the AT91FR40008 flash memory. It is assumed that the GNUARM and UNXUTILS development tools are
already installed correctly and included in your PATH (to make them available from a Windows DOS prompt).
To build the application:
- Open a DOS prompt, and navigate to the Demo/ARM7_AT91FR40008_GCC directory.
- Type "rom_arm" (or "rom_thumb") to execute the rom_arm.bat batch file. The batch file sets up the environment necessary for a release build then
calls make. The build should complete with no errors or warnings.
To download the RTOS demo to flash:
Connect the parallel port JTAG interface between your host computer and the target hardware.
Open the Embest flash programming utility.
From within the flash programming utility, open the ATEB40x.cfg configuration file. This will setup all the
necessary flash parameters for the target board.
Still within the flash programming utility, set the file to be programmed to Demo/ARM7_AT91FR40008/rtosdemo.hex.
This is the hex file output from the build process described above.
Selecting the file to download
Erase the flash contents by pressing the Erase button, then reprogram the flash by pressing the Program button.
Executing the demo application:
Power down the prototyping board, remove the JTAG interface, then apply power again. The demo application will start to
Building and executing the RTOS demo application - Debug from RAM
The port authour has also tested and provided linker scripts for RAM execution.
See the corresponding section on the LPC2106 ARM7 GCC port
documentation page for details of using the GCC debug tools.
The demo application creates all of the standard minimal demo application real time tasks (see the
demo application section for details of the individual tasks).
When executing correctly the demo application will behave as follows:
- LEDs D3, D4 and D5 are under control of the 'flash' tasks. Each will flash at a constant frequency, with LED D3
being the fastest and LED D5 being the slowest.
When the loopback connector is in place every character transmitted by the ComTest Tx task is received by the ComTest
Rx task. Each transmitted character causes LED D8 to toggle, each correctly received character causes LED D7 to
toggle. LED D7 will only toggle if the received character matches the character the ComTest Rx task expected to receive.
- Not all the tasks update an LED so have no visible indication that they are operating correctly.
Therefore a 'Check' task is created whose job it is to ensure that no errors have been detected in any of the other tasks.
LED D10 is under control of the 'Check' task. Every three
seconds the 'Check' task examines all the tasks in the system to ensure they are executing without error. It
then toggles LED D10. If LED D10 is toggling every three seconds then no errors have ever been detected.
The toggle rate increasing to 500ms indicates that the 'Check' task has
discovered at least one error. This mechanism can be checked by removing the loopback connector from the serial port
(described above), and in doing so deliberately generating an error.
Win32 GNU Development Tools
The GNU ARM7 development tools can be obtained pre-built from a number of locations.
I used the build available from http://www.gnuarm.com on a Win2K host. The binary
distribution includes a convenient installation program that installs everything required. Some GNU development tool
distributions require Cygwin to be installed separately which is less convenient.
A GNU make compatible utility is also required. I use the UNXUTILS version.
RTOS port specific configuration
Configuration items specific to this port are contained in Source/Demo/ARM7_AT91FR40008_GCC/FreeRTOSConfig.h. The constants defined in
this file can be edited to suit your application. In particular - the definition configTICK_RATE_HZ is used to set the frequency
of the RTOS tick. The supplied value of 1000Hz is useful for testing the RTOS kernel functionality but is faster than most applications
require. Lowering this value will improve efficiency.
Each port #defines 'BaseType_t' to equal the most efficient data type for that processor. This port defines
BaseType_t to be of type long.
Note that vPortEndScheduler() has not been implemented.
Interrupt service routines
An interrupt service routine that does not cause a context switch has no special requirements and can be written as normal. For
void vASimpleISR( void ) __attribute__((interrupt("IRQ")));
void vASimpleISR( void )
/* ISR code goes here. */
Note: The method of forcing a context switch from within an ISR has changed since FreeRTOS V4.5.0. Unfortunately the new method
requires different syntax, but is no longer dependent on the version of the compiler used, the command line switches, or the optimisation level.
Changing to the method described here should therefore remove the need to make any further alterations in the future.
The example here assumes that the interrupt handler is vectored to directly - that is, there is no entry code that is common to all
interrupts. Some of the other FreeRTOS demo applications are configured to use a common entry point as an alternative to this method.
To write an interrupt service routine that can cause a context switch:
- Write a handler function. This will do the actual ISR processing. The handler function is a standard C function that has no
- Write a wrapper function. This is the ISR entry point and must be declared using the "naked" attribute. The wrapper function
is the function that must be installed as the interrupt handler. It must call the actual handler function between calls to portSAVE_CONTEXT()
and portRESTORE_CONTEXT(). As with all ISR functions, the wrapper must be compiled to ARM code (as opposed to THUMB code).
- Performing a context switch from within the ISR means that the task that executes when the ISR completes will not necessarily
be the task that was executing when the interrupt was taken. Such a context switch can be performed by calling portYIELD_FROM_ISR().
/* Declare the wrapper function using the naked attribute.*/
void vASwitchCompatibleISR_Wrapper( void ) __attribute__ ((naked));
/* Declare the handler function as an ordinary function.*/
void vASwitchCompatibleISR_Handler( void );
/* The handler function is just an ordinary function. */
void vASwitchCompatibleISR_Handler( void )
long lSwitchRequired = pdFALSE;
/* ISR code comes here. If the ISR wakes a task then
lSwitchRequired should be set to 1. */
/* If the ISR caused a task to unblock, and the priority
of the unblocked task is higher than the priority of the
interrupted task then the ISR should return directly into
the unblocked task. portYIELD_FROM_ISR() is used for this
if( lSwitchRequired )
void vASwitchCompatibleISR_Wrapper( void )
/* Save the context of the interrupted task. */
Call the handler function. This must be a separate
function unless you can guarantee that handling the
interrupt will never use any stack space. */
/* Restore the context of the task that is going to
execute next. This might not be the same as the originally
See vUART_ISR() defined in Demo/ARM7_AT91FR40008_GCC/serial/serialISR.c for a full example.
To use a part other than an AT91R40008
The AT91R40008 uses a standard ARM7 core with processor specific peripherals. The core real time kernel components should be portable
across all ARM7 devices - but the peripheral setup and memory requirements will require consideration. Items to consider:
- prvSetupTimerInterrupt() in Source/portable/GCC/ARM7_AT91R40008/port.c configures the AT91R40008 timers to generate the RTOS tick.
- Port, memory access and system clock configuration is performed by prvSetupHardware() within Demo/ARM7_AT91FR40008_GCC/main.c.
- The interrupt service routine setup and management assume the existence of the interrupt controller.
- The serial port drivers.
- Register location definitions are provided by the file AT91R40008.h which is included at the top of Demo/ARM7_AT91FR40008_GCC/FreeRTOSConfig.h.
- Startup code, memory map and vector table setup is contained within Demo/ARM7_AT91FR40008_GCC/boot.s.
- RAM size - see Memory Allocation below.
Switching between the pre-emptive and co-operative RTOS kernels
Set the definition configUSE_PREEMPTION within Demo/ARM7_AT91FR40008_GCC/FreeRTOSConfig.h to 1 to use pre-emption or 0
to use co-operative.
As with all the ports, it is essential that the correct compiler options are used. The best way to ensure this is to base your
application on the provided demo application makefile.
The RTOS scheduler executes in supervisor mode, tasks execute in system mode.
The processor MUST be in supervisor mode when the RTOS scheduler is started (vTaskStartScheduler is
called). The demo applications included in the FreeRTOS download switch
to supervisor mode prior to main being called. If you are not using one of
these demo application projects then ensure Supervisor mode is entered before calling vTaskStartScheduler().
Interrupt service routines always run in ARM mode. All other code will run in either ARM or THUMB mode depending on the build.
It should be noted that some of the macros defined in portmacro.h can only be called from ARM mode code, and use from THUMB code
will result in a compile time error.
Demo/ARM7_AT91FR40008_GCC/boot.s configures stacks for system/user, IRQ and SWI modes only.
SWI instructions are used by the real time kernel and can therefore not be used by the application code.
Source/Portable/MemMang/heap_2.c is included in the AT91FR40008 demo application makefile to provide the memory
allocation required by the RTOS kernel.
Please refer to the Memory Management section of the API documentation for
Serial port driver
It should also be noted that the serial drivers are written to test some of the real time kernel features - and they are not
intended to represent an optimised solution.
Notes for Linux users
I have only tested the makefile with Win32 builds of the GNUARM development tools.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.