This page describes the FreeRTOS port for the Tern range of x186 based controllers, with the Tern E-Engine controller (Ethernet Engine)
chosen as the target for the pre-configured demo
application (instructions are provided should you wish to use an alternative development board). The E-Engine control board includes an i2chip based WizNET embedded TCP/IP processor which the demo application uses via a (currently) simple HTTP interface to
display RTOS status information.
The demo application is limited to the small memory model to enable it to be build and debugged using the evaluation version of the Paradigm C/C++ compiler - Tern edition delivered with
the controller kit.
The E-Engine interfaces to the i2chip through a memory mapped interface. A separate FreeRTOS demo application
demonstrates interfacing to the same TCP/IP co-processor via an I2C interface using an ARM7 processor.
Please note the files socket.c, i2chip_hw.c and associated headers and libraries are included with kind permission of Tern Inc. These files are copyright Tern Inc
and are not covered by the modified GPL.
Note for Paradigm C/C++ Version 7 Users: Version 7 uses a slightly different stack frame and therefore requires a few modifications to the RTOS kernel port
files. Dave Lyneham has generously provided a project that contains the changes necessary, along with a readme.txt file to explain why they are needed.
The files can be obtained from the FreeRTOS Interactive x86 forum.
IMPORTANT! Notes on using the Tern Inc. 80x186 RTOS Demo
Please read all the following points before using this RTOS port.
The FreeRTOS download contains the source code for all the FreeRTOS ports, so contains more files than used by this demo.
See the Source Code Organization section for a description of the
downloaded files and information on creating a new project.
The E-Engine demo application can be built using the preconfigured Paradigm Tern Edition compiler project file which is called RTOSDemo.ide and is located in the
Connect the E-Engine controller board to a computer running a web browser either directly using a point to point (crossover)
cable, or via a hub/router using a standard Ethernet cable.
The IP address used by the demo is set by the constant "ucIPAddress" defined at the top of FreeRTOS/Demo/WizNET_DEMO_TERN_186/HTTPTask.c.
The IP addresses used by the web browser computer and the controller board must be compatible.
This can be ensured by making the first three octets of both IP addresses identical.
For example, if the web browser computer uses IP address
192.168.100.1, then the controller board can be given any address in the range 192.168.100.2 to 192.168.100.254 (barring
any addresses already present on the network).
The MAC address used by the demo is set by the constant "ucMacAddress" within the same file.
You must ensure that the configured MAC address is unique on the network to which the controller board is being connected.
The demo application includes tasks that send and receive characters over the serial port. The characters sent by one task
need to be received by another - if any character is missed or received out of sequence an error condition is flagged. A
loopback connector is required on the serial port for this mechanism to operate. The serial port test is preconfigured to use COM2 on the controller board as
the debugger interface defaults to use COM1. The simplest way of looping the COM2 Tx pin to the COM2 Rx pin on the E-Engine board is to place a jumper
on pins 2 and 3 of the COM2 connector, so that the two pins are shorted together.
Building and executing the demo application
The Tern edition of the Paradigm development tools permits remote debugging directly from within the Paradigm IDE. These instructions assume that the
Tern debug monitor is already programmed into the controller board flash - the default for newly purchased controller boards.
Connect the E-Engine to your host PC using the RS232 ribbon cable provided with the control board. COM1 should be used on the controller board.
Open up the RTOSDemo.ide project file from within the Paradigm IDE.
The demo project shown in the Paradigm IDE.
The project is partitioned as follows:
i2chip_src - source pool containing the i2chip driver. The majority of this code is provided by and copyright to Tern Inc.
FreeRTOS_source - source pool containing the FreeRTOS kernel source code.
DemmoApp_source - source pool containing the standard FreeRTOS demo application files.
RTOSDemo - this is the project which contains references to the three source pools described above. It also contains main.c and httptask.c. main.c
is the program entry point. It creates all the demo application tasks then starts the RTOS scheduler. httptask.c contains the simple http service.
In the project window (as per the image above), right click on the "RTOSDemo [.axe]" line, then select "Edit local options" from the pop up menu. The
project options dialogue will be displayed, as shown below.
In the project options window, select the "Directories" topic, then edit the include and library path names to point be correct for your Paradigm C/C++
installation (my installation being in the c:\devtools\paradigm directory as per the image below).
Close the project options windows, then select "Build All" from the IDE's "Project" menu. The source should build and link with no errors or warnings.
Finally select "Run" from the IDE's "Debug" menu. The IDE should connect to the target board, download the executable, and start the application running.
Note that when using this method the program is executing from RAM and will be lost should the target board be power cycled.
Open a web browser, and in the address bar type "http://192.168.0.23", replacing this IP address with that set by the ucIPAddress constant.
Entering the IP address into the web browser (obviously use the correct IP address for your system)
The demo application creates twenty five tasks - consisting predominantly of the standard demo application tasks (see the
demo application section for details of the individual tasks).
In addition a further four tasks are repeatedly dynamically created and deleted (by the standard "death" demo).
When executing correctly the demo application will serve the web page shown on the left. The page will automatically refresh every second.
The table lists each task under control of the RTOS scheduler, along with the tasks:
The amount of unused stack space remaining (from the high water mark).
The tasks number.
The count of the number of idle task execution loops originates from the idle task hook, which is defined in HTTPTask.c.
The tick count should increment at the rate specified by the configTICK_RATE_HZ constant, defined in FreeRTOSConfig.h.
Finally, main() also creates a "check" task. The check task monitors all the other tasks in the system. If the check task discovers a potential error in any
other task a red error message will be displayed. If no errors have ever been detected "No errors detected" is displayed. This mechanism can be tested by
removing the loopback connector on COM2, and in so doing deliberately generating an error.
As downloaded only a single dynamically generated page is returned, as hard coded within HTTPTask.c. However, the Tern development kit includes a
compact flash driver for the E-Engine controller which could easily be integrated into the RTOS demo. This would allow standard HTML pages to be created and
written to a flash card from a Windows host, then served from the E-Engine controller. In addition, the FreeRTOS download includes the uIP source code.
uIP includes a very simple cgi type function that permits pages that include dynamic data to be easily created.
The table displayed on the served web page is interesting for demonstration purposes, but as it is necessary to leave the RTOS scheduler disabled for an extended
period during its creation it is not recommended for use in production applications.
Interrupt service routines
For simplicity the RTOS scheduler context switching mechanism relies on the compiler generated interrupt service routine prologue and epilogue code. It is therefore
essential that each ISR that can cause a context switch has identical entry and exit code. As a result of this an ISR that can cause a context switch cannot
define any stack variables directly in the ISR function. A simple way around this is to have the top level ISR function call another lower level function, for
/* This is the lower level function called from the top level
ISR function. */
int iCalledFunction( void )
/* Variables can be declared here. */
int iSwitchRequired = false;
/* ... ISR code goes here ... */
/* Assume the ISR code necessitates a context switch. */
iSwitchRequired = true;
/* This is the top level function in which variables cannot be
declared on the stack. This is the function installed on the
void __interrupt prvISRFunction( void )
/* Variables cannot be declared here! */
/* Call the lower level function to do the work. */
if( iCalledFunction() )
/* If the called function necessitates a context switch
then call portEND_SWITCHING_ISR() immediately prior to
This mechanism is demonstrated by the serial port and WIZnet drivers included in the E-Engine demo application.
Declaring variables used by the ISR as static would probably have the same effect.
Interrupt service routines that do not cause a context switch have no special requirements.
The i2chip driver included in the download is a slightly modified version of the driver supplied by Tern Inc (the modification being the inclusion of the
semaphore in the interrupt service routine used to unblock the HTTPTask). This driver was not written for a multitasking system and is therefore not
optimised for use with FreeRTOS.org. Efficiency gains could be obtained by:
Selecting which interrupts should wake the HTTPTask, and which should not. Currently any event wakes the HTTPTask, even if there is no processing
to be performed.
Removing the polling of status bits within the driver code that is outside of the ISR, and instead using a more state machine orientated organisation
between the ISR and task code.
The Borland floating point libraries are not reentrant and should not be used with the RTOS scheduler. Information on how to make them reentrant is fairly well documented,
information on which can be found on the web.
RTOS port specific configuration
Configuration items specific to this port are contained in Source/Demo/WizNET_DEMO_TERN_186/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 short (16 bits).
Note that vPortEndScheduler() has not been implemented.
The RTOS Tick interrupt uses timers 1 and 2. Using a fast tick rate will remove the requirement to prescale the timer, and therefore use only timer 2.
The 'Global Register Allocation' optimisation option appears to break the code.
Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2015 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd..
See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.