RTX51 Tiny User's Guide: Overview

Overview

RTX51 Tiny is a real-time operating system (RTOS) which allows you to create applications that simultaneously perform multiple functions or tasks. This is often required in an embedded application. While it is certainly possible to create real-time programs without an RTOS (by executing one or more functions or tasks in a loop) there are numerous scheduling, maintenance, and timing issues that an RTOS like RTX51 Tiny can solve for you.

A real-time operating system (RTOS) allows flexible scheduling of system resources like the CPU and memory and offers some way to communicate between tasks. RTX51 Tiny is a powerful RTOS that is easy to use and that works with all 8051 derivatives.

RTX51 Tiny programs are written using standard C constructs and compiled with the Keil C51 C Compiler. Additions to the C language allow you to easily declare task functions without the need for complex stack and variable frame configuration. RTX51 Tiny programs require only that you include a special header file and link the RTX51 Tiny library into your program.

Copyright (c) Keil Software, Inc. All rights reserved.


RTX51 Tiny User's Guide: What's New

What's New

RTX51 Tiny Version 2 includes many new features that make real-time software development easier. For example:

  • Code Banking Support
    RTX51 Tiny now supports code banking. This option must be enabled in the CONF_TNY.A51 configuration file. As with all other code banking applications you must define the code banking hardware configuration in the L51_BANK.A51 file.
  • Explicit Task Switching
    A new function (os_switch_task) allows a task to immediately perform a task switch to another task that is in the READY state.
  • Task Ready Flag
    New RTX51 Tiny library routines (isr_set_ready and os_set_ready allow you to set the READY flag for a task. The READY flag may be used to immediately place a task waiting for an interval, timeout, or signal (refer to os_wait) in the READY state. The task is resumed at the next opportunity.
  • CPU Idle Mode Support
    RTX51 Tiny now allows you to enter Idle Mode (available on many devices) inside the Idle Task.
  • User Code Support in Timer Interrupt
    You may now add your own code to the RTX51 Tiny Timer Tick Interrupt. You may ue the same fixed clock rate as RTX51 Tiny for your own routines. This option must be enabled in the CONF_TNY.A51 configuration file
    • .
  • Interval Adjustment Support
    The os_reset_interval function allows you to adjust the timeout value for an interval when mixing intervals and signals in calls to the os_wait routine.

In addition, RTX51 Tiny has been completely restructured to gain flexibility, accelerate performance, and reduce code and data space requirements. RTX51 Tiny Version 2 is scalable and shows significant code size reductions when the following conditions are met.

  1. Round-Robin Task Switching is disabled.
  2. Few RTX51 Tiny system functions are used.
  3. Stack Checking is disabled.

Disabling Round-Robin Task Switching also reduces data space requirement.


RTX51 Tiny User's Guide: Problems Solved

Problems Solved

Following is a list of known problems in RTX51 Tiny Version 1.06. These problems are corrected in RTX51 Tiny Version 2.

  1. The isr_send_signal function may destroy the READY status when an interrupt occurs during os_wait. This causes the task to hang waiting for the signal from the interrupt.
  2. K_IVL and K_SIG events cannot be combined in a call to the os_wait routine because the interval timer value cannot be adjusted when the signal occurs. RTX51 Tiny Version 2 provides the os_set_interval routine which allows you to properly adjust the interval timer.
  3. The TIMESHARING EQUate for Round-Robin cannot be set to 1. If it was, and if an interrupt occurred before the Round-Robin time is set, the Round-Robin period may be corrupted and delay 256 ticks instead of 1.
  4. When user interrupts execute longer than an RTX51 Tiny System Clock Timer Tick, the RTX51 Tiny System Clock Timer is called recursively. This overwrites the values SAVEPSW and SAVEACC with wrong values and typically causes a system crash.

In RTX51 Tiny V2.0, you should set the LONG_USR_INTR EQUate to a value of 1 if your application contains an interrupt function that may take longer for execution than the RTX51 Tiny System Clock Timer Interval time. You may also require this option flag if your application spends most of its time executing high-priority interrupt routines.


RTX51 Tiny User's Guide: Product Specifications

Product Specifications

Parameter | Limits
Maximum Number of Defined Tasks | 16
Maximum Number of Active Tasks | 16
Required CODE Space | 900 Bytes Max
Required DATA Space | 7 Bytes
Required STACK Space | 3 Bytes/Task
Required XDATA Space | 0 Bytes
Timer | 0
System Clock Divisor | 1,000-65,535
Interrupt Latency | 20 Cycles or Less
Context Switch Time | 100-700 Cycles


RTX51 Tiny User's Guide: Tool Requirements

Tool Requirements

The following software applications are required to use RTX51 Tiny:

  • C51 Compiler
  • A51 Macro Assembler
  • BL51 Linker or Lx51 Linker

The RTX51TNY.LIB and RTX51BT.LIB library files must be stored in the library path. Usually, this is the \KEIL\C51\LIB folder.

The RTX51TNY.H include file must be stored in the include path. Usually, this is the \KEIL\C51\INC folder.


RTX51 Tiny User's Guide: Target Requirements

Target Requirements

RTX51 Tiny runs on most 8051-compatible devices including single-chip variants. Your RTX51 Tiny application may use external data memory, but the kernel has no requirements for it.

RTX51 Tiny works with all memory models supported by the Keil C51 Compiler. The memory model selected influences only the location of application objects. The RTX51 Tiny system variables and the stack area of the application are always stored in internal 8051 memory (DATA or IDATA). Typically, RTX51 Tiny applications are implemented in the SMALL model.

RTX51 Tiny performs cooperative task switching (each tasks calls an operating system routine) and round-robin task switching (each task runs for a fixed amount of time before the operating system switches to the next task). Preemptive task switching and task priorities are not supported. If your application requires preemptive task switching you must use the RTX51 Full Real-Time Executive.


RTX51 Tiny User's Guide: Interrupts

Interrupts

RTX51 Tiny works in parallel with your interrupt functions. Interrupt service routines may communicate with RTX51 Tiny tasks by sending signals (using the isr_send_signal function) or by setting a task's Ready flag (using the isr_set_ready function).

Interrupt routines must be implemented and enabled in your RTX51 Tiny application as they would be in a standard, non-RTX51 Tiny application. There is no interrupt service routine management in RTX51 Tiny.

RTX51 Tiny uses Timer 0 and the Timer 0 interrupt. Globally disabling all interrupts (EA bit) or the Timer 0 interrupt stops the operation of RTX51 Tiny. You should disable interrupts for brief periods only.


RTX51 Tiny User's Guide: Reentrant Functions

Reentrant Functions

Non-reentrant C functions may not be called from more than one task or interrupt procedure. Non-reentrant C51 functions store their parameters and automatic variables (local data) in static memory segments which may be overwritten when the function is called from multiple tasks simultaneously or recursively.

You may invoke non-reentrant functions from multiple tasks if you ensure that they are not called recursively (simultaneously). Usually this means that round-robin task scheduling must be disabled and that your non-reentrant functions may not call any RTX51 Tiny system functions.

C functions which only use registers for parameter and automatic variables are inherently reentrant and can be called without any restrictions from RTX51 Tiny.

The C51 Compiler provides support for reentrant functions. Reentrant functions store parameters and local variables on a reentrant stack. This protects them from recursive or simultaneous calls. RTX51 Tiny does not contain any management for the C51 reentrant stack. So, if you use reentrant functions in your application, you must ensure that these functions do not call any RTX51 Tiny system functions and that reentrant functions are not interrupted by round-robin task switching.

Note

  • You should disable Round-Robin Task Switching if you wish to invoke reentrant or non-reentrant function from more than one task or interrupt.


RTX51 Tiny User's Guide: Library Routines

Library Routines

All C51 library routines which are reentrant may be used in all tasks without any restrictions. For C51 library routines which are non-reentrant, the same restrictions apply as for non-reentrant C functions.


RTX51 Tiny User's Guide: Multiple Data Pointers

Multiple Data Pointers

The Keil C51 Compiler allows you to use multiple data pointers (available in many 8051 derivatives). RTX51 Tiny, however, provides no management for them. Therefore, you must be careful if you use multiple data pointers in your RTX51 Tiny applications.

Essentially, you must ensure that a round-robin task switch does not take place during execution of code that changes the data pointer selector.

Note

  • You should disable Round-Robin Task Switching if you wish to use multiple data pointers.


RTX51 Tiny User's Guide: Arithmetic Units

Arithmetic Units

The Keil C51 Compiler allows you to use the arithmetic units of various 8051 derivatives. RTX51 Tiny, however, provides no management for them. Therefore, you must be careful if you use the arithmetic unit in your RTX51 Tiny application.

Essentially, you must ensure that a round-robin task switch does not take place during execution of code that uses the arithmetic unit.

Note

  • You should disable Round-Robin Task Switching if you wish to use an arithmetic unit.


RTX51 Tiny User's Guide: Register Banks

Register Banks

RTX51 Tiny assigns all tasks to register bank 0. For this reason, all task functions must be compiled with the default C51 setting, REGISTERBANK (0).

Interrupt functions may use the remaining register banks. However, RTX51 Tiny requires 6 permanent bytes in the register bank area. The register bank used by RTX51 Tiny for these bytes may be specified in the configuration file.


RTX51 Tiny User's Guide: Single-Tasking Programs

Single-Tasking Programs

Both embedded and standard C programs start execution with the main C function. In an embedded application, main is usually implemented as an endless loop and can be thought of as a single task which is executed continuously. For example:

void main (void)
{
while (1)               /* repeat forever */
  {
  do_something ();      /* execute the do_something 'task' */
  }
}

In this example, the do_something function can be thought of as a single task. Since there is only one task that executes, there is no need for multitasking capability or a multitasking operating system.


RTX51 Tiny User's Guide: Multi-Tasking Programs

Multi-Tasking Programs

More sophisticated C programs may implement a pseudo-multitasking scheme where several functions (or tasks) are called in a loop. For example:

void main (void)
{
int counter = 0;

while (1)                  /* repeat forever */
  {
  check_serial_io ();      /* check for serial input */
  process_serial_cmds ();  /* process serial input */

  check_kbd_io ();         /* check for keyboard input */
  process_kbd_cmds ();     /* process keyboard input */

  adjust_ctrlr_parms ();   /* adjust the controller */

  counter++;               /* increment counter */
  }
}

In this example, each function performs a separate operation or task. The functions (or tasks) are executed in order, one after another.

Scheduling starts to become an issue as more tasks are added. For example, if the process_kbd_cmds function executes for a long time, the main loop may take too long to get back around to the check_serial_io function and serial data may be lost. Of course, the check_serial_io function can be called more often in the main loop to correct this issue, but eventually this technique will not work.


RTX51 Tiny User's Guide: RTX51 Tiny Programs

RTX51 Tiny Programs

When you use RTX51 Tiny, you create a separate function task for each task in your application. For example:

void check_serial_io_task (void) _task_ 1
{
/* This task checks for serial I/O */
}

void process_serial_cmds_task (void) _task_ 2
{
/* This task processes serial commands */
}

void check_kbd_io_task (void) _task_ 3
{
/* This task checks for keyboard I/O */
}

void process_kbd_cmds_task (void) _task_ 4
{
/* This task processes keyboard commands */
}

void startup_task (void) _task_ 0
{
os_create_task (1);    /* Create serial_io Task */
os_create_task (2);    /* Create serial_cmds Task */
os_create_task (3);    /* Create kbd_io Task */
os_create_task (4);    /* Create kbd_cmds Task */

os_delete_task (0);    /* Delete the Startup Task */
}

In this example, each function defines an RTX51 Tiny task. RTX51 Tiny programs do not have a main C function. Instead, RTX51 Tiny starts executing task 0. In typical applications, task 0 simply creates all the other tasks.


RTX51 Tiny User's Guide: Theory of Operation

Theory of Operation

RTX51 Tiny uses and manages resource of your target system. This chapter discusses resources and how they are used by RTX51 Tiny.

Many asects of RTX51 Tiny can be configured on a project by project basis. This is noted where it is possible.


RTX51 Tiny User's Guide: Timer Tick Interrupt

Timer Tick Interrupt

RTX51 Tiny uses the standard 8051 Timer 0 (mode 1) to generate a periodic interrupt. This interrupt is the RTX51 Tiny Timer Tick. Timeout and interval values specified for the RTX51 Tiny library routines are measured using the RTX51 Tiny Timer Tick.

By default, the RTX51 Timer Tick interrupt occurs every 10,000 machine cycles. So, for a standard 8051 running at 12MHz, the period of the timer tick is 0.01 seconds or a frequency of 100Hz (12MHZ / 12 / 10,000). The value may be changed in the CONF_TNY.A51 configuration file.

Note

  • You may append your own code to the RTX51 Timer Tick Interrupt. Refer to the CONF_TNY.A51 configuration file for more information.


RTX51 Tiny User's Guide: Tasks

Tasks

RTX51 Tiny is basically a task switcher. To create an RTX51 Tiny program, you must create an application with one or more task functions. The following details will help you more quickly gain an understanding of RTX51.

  • Tasks are defined in the C Programming Language using new keywords supported by the Keil C51 Compiler.
  • RTX51 Tiny maintains each task in exactly one state (Running, Ready, Waiting, Deleted, or Time-Out).
  • Only one task at a time may be in the Running State.
  • Many tasks may be in the Ready, Waiting, Deleted, or Time-Out States.
  • An Idle Task is always ready to run in the event that all of your defined tasks are blocked.


RTX51 Tiny User's Guide: Task Management

Task Management

Each RTX51 Tiny task is always in exactly one state which tells the disposition of the task.

State | Description
RUNNING | The task that is currently running is in the RUNNING State. Only one task at a time may be in this state. The os_running_task_id returns the task number of the currently executing task.
READY | Tasks which are ready to run are in the READY State. Once the Running task has completed processing, RTX51 Tiny selects and starts the next Ready task. A task may be made ready immediately (even if the task is waiting for a timeout or signal) by setting its ready flag using the os_set_ready or isr_set_ready functions.
WAITING | Tasks which are waiting for an event are in the WAITING State. Once the event occurs, the task is switched to the READY State. The os_wait function is used to place a task in the WAITING State.
DELETED | Tasks which have not been started or tasks which have been deleted are in the DELETED State. The os_delete_task routine places a task that has been started (with os_create_task) into the DELETED State.
TIME-OUT | Tasks which were interrupted by a Round-Robin Time-Out are in the TIME-OUT State. This state is equivalent to the READY State for Round-Robin programs.


RTX51 Tiny User's Guide: Events

Events

Events in a real-time operating system may be used to control the execution of tasks in the program. A task may wait for an event or may set event flags for other tasks.

The os_wait function allows a task to wait for one or more events.

  • A common event for which a task can wait is the Timeout. A timeout is simply a number of clock ticks. While a task is waiting for a timeout, other tasks may execute. Once the specified number of timer ticks has elapsed, the task may continue execution.
  • A variant of the Timeout is the Interval. An interval is like a timeout except that the specified number of clock ticks is relative to the last time the os_wait function was invoked by the task. The Interval may be used to generate a task which is run on a regular, synchronous schedule (like once every second) regardless of how long the task takes between calls to the os_wait function.
  • A Signal is a simple form of inter-task communication. A task can wait for another task to send it a signal (with the os_send_signal and isr_send_signal functions).
  • Each task has a Ready flag which may be set by other tasks (with the os_set_ready and isr_set_ready functions). A task that is waiting for a timeout, interval, or signal may be started by setting its ready flag.

Each event has an associated event flag that RTX51 Tiny maintains. The following event selectors may be used with the os_wait function to specify what to wait for:

Event Selector | Description
K_IVL | Wait for the specified interval.
K_SIG | Wait for a signal.
K_TMO | Wait for a specified timeout.

When os_wait returns, the events that occurred are specified by the return value:

Return Value | Description
RDY_EVENT | The task's ready flag was set.
SIG_EVENT | A signal was received.
TMO_EVENT | A time-out has completed or an interval has elapsed.

The os_wait function may wait for the following combinations of events:

  • K_SIG | K_TMO: os_wait delays the task until a signal is sent to it or until the specified number of clock ticks has elapsed.
  • K_SIG | K_IVL: os_wait delays the task until a signal is sent to it or until the specified interval has elapsed.

Note

  • The K_IVL and K_TMO event selectors may not be combined.


RTX51 Tiny User's Guide: Task Scheduler

Task Scheduler

The Task Scheduler is the part of RTX51 Tiny that assigns the processor to a task. The RTX51 Tiny scheduler determines which task to run using to the following rules:

The current task is interrupted if:

  1. The task calls the os_wait function and the specified event has not occurred.
  2. The task has executed for longer than the defined round-robin time slice.

Another task is started if:

  1. No other task is running.
  2. The task to be started is in the READY State or TIME-OUT State.


RTX51 Tiny User's Guide: Round-Robin Task Switching

Round-Robin Task Switching

RTX51 Tiny can be configured to use Round-Robin Multitasking (or task switching). Round-Robin allows quasi-parallel execution of several tasks. Tasks are not really executed concurrently but are time-sliced (the available CPU time is divided into time slices and RTX51 Tiny assigns a time slice to each task). Since the time slice is short (only a few milliseconds) it appears as though tasks execute simultaneously.

Tasks execute for the duration of their time-slice (unless the task's time slice is given up). Then, RTX51 Tiny switches to the next task that is ready to run. The duration of a time slice may be defined by the RTX51 Tiny Configuration.

The following example shows a simple RTX51 Tiny program that uses Round-Robin Multitasking. The two tasks in this program are counter loops. RTX51 Tiny starts executing task 0 which is the function named job0. This function creates another task called job1. After job0 executes for its time slice, RTX51 Tiny switches to job1. After job1 executes for its time slice, RTX51 Tiny switches back to job0. This process is repeated indefinitely.

#include

int counter0;
int counter1;

void job0 (void) _task_ 0 {
  os_create (1);	/* mark task 1 as ready */
  while (1) {	/* loop forever */
    counter0++;	/* update the counter */
  }
}

void job1 (void) _task_ 1 {
  while (1) {	/* loop forever */
    counter1++;	/* update the counter */
  }
}

Note

  • Rather than wait for a task's time slice to expire, you may use the os_wait function or the os_switch_task function to signal RTX51 Tiny that it can switch to another task. The os_wait function suspends the current task (changes it to the WAITING State) until the specified event occurs (and the task is changed to the READY State). During this time, any number of other tasks may run.


RTX51 Tiny User's Guide: Cooperative Task Switching

Cooperative Task Switching

If you disable Round-Robin Multitasking you must design and implement your tasks so that they work cooperatively. Specifically, you must call the os_wait function or the os_switch_task function somewhere in each task. These functions signal RTX51 Tiny to switch to another task.

The difference between os_wait and os_switch_task is that os_wait allows your task to wait for an event while os_switch_task switches to another ready task immediately.


RTX51 Tiny User's Guide: Idle Task

Idle Task

When no task is ready to run, RTX51 Tiny executes an Idle Task. The Idle Task is simply an endless loop. For example:

SJMP $

Some 8051-compatible devices provide an idle mode that reduces power consumption by halting program execution until an interrupt occurs. In this mode, all peripherals include the interrupt system still continue operation.

RTX51 Tiny allows you to initiate idle mode in the Idle Task (when no other task is ready for execution). When the RTX51 Tiny Timer Tick Interrupt (or any other interrupt) occurs, the microcontroller resumes program execution. The code executed by the Idle Task may be enabled and configured in the CONF_TNY.A51 configuration file.


RTX51 Tiny User's Guide: Stack Management

Stack Management

RTX51 Tiny maintains a stack for each task using only the internal memory (IDATA) of the 8051. When a task is running, it is given the maximum amount of stack space possible. When a task switch occurs, the previous task stack is shrunk and relocated and the stack for the current task is expanded and relocated.

The following figure illustrates the layout of internal memory for an example application with three separate tasks.

The ?STACK symbol denotes the starting address of the stack. In this example, objects located below the stack include global variables, registers, and bit-addressable memory. The remaining memory is used for the task stacks. The top of memory may be specified in the configuration.


RTX51 Tiny User's Guide: Configuring RTX51 Tiny

Configuring RTX51 Tiny

RTX51 Tiny was designed to customized for each application your create.


RTX51 Tiny User's Guide: Configuration

Configuration

RTX51 Tiny must be configured for the embedded applications you create. All configuration settings are found in the CONF_TNY.A51 file which is located in the \KEIL\C51\RTXTINY2\ folder. Configuration options in CONF_TNY.A51 allow you to:

  • Specify the Timer Tick Interrupt Register Bank.
  • Specify the Timer Tick Interval (in 8051 machine cycles).
  • Specify user code to execute in the Timer Tick Interrupt.
  • Specify the Round-Robin Timeout.
  • Enable or disable Round-Robin Task Switching.
  • Specify that your application includes long duration interrupts.
  • Specify whether or not code banking is used.
  • Define the top of the RTX51 Tiny stack.
  • Specify the minimum stack space required.
  • Specify code to execute in the event of a stack error.
  • Define Idle Task operations.

A default configuration of CONF_TNY.A51 is included in the RTX51 Tiny Library. However, to guarantee the configuration used for your application , you must copy the CONF_TNY.A51 file to your project folder and add it to your project.

To customize the RTX51 Tiny configuration, you must change settings specified in CONF_TNY.A51.

Note

  • If you do not include a configuration file (CONF_TNY.A51) in your project, the default configuration file from the library is included automatically. Subsequent changes to the configuration file stored in the library may have adverse effects on the operation of your application.


RTX51 Tiny User's Guide: Hardware Timer

Hardware Timer

The following EQUates specify how the RTX51 Tiny hardware timer is configured.

  • INT_REGBANK specifies the register bank used by the RTX51 Tiny Timer Interrupt. The default setting is 1 (for register bank 1).
  • INT_CLOCK specifies the number of cycles before the timer generates an interrupt. This number may be a value from 1000-65535. Small numbers generate faster interrupts. This number is used to calculate the reload value for the timer (65536-INT_CLOCK). The default setting is 10000.
  • HW_TIMER_CODE is a macro that allows you to specify code to execute at the end of the RTX51 Tiny Timer Tick Interrupt. The default setting for this macro is to return from the interrupt (RETI). For example:
    HW_TIMER_CODE MACRO
; Empty Macro by default
RETI
ENDM


RTX51 Tiny User's Guide: Round-Robin

Round-Robin

Round-Robin Task Switching is enabled by default. The following EQUate allows you to configure the Round-Robin task switch time or to disable Round-Robin entirely.

  • TIMESHARING specifies the number of RTX51 Tiny timer ticks each task runs before a Round-Robin task switch. A value of 0 disables Round-Robin task switching. The default setting is 5 timer ticks.


RTX51 Tiny User's Guide: Long Interrupts

Long Interrupts

Typically, Interrupt Serice Routines (ISRs) are designed to execute quickly. In some situations, your ISRs may excute for a long period of time. If a high-priority ISR executes longer than the RTX51 timer tick interval, the RTX51 timer interrupt may be interrupted (by your ISR) and may be reentered (by a subsequent RTX51 timer interrupt).

If you use high priority interrupts that execute for long periods of time, you should consider reducing the amount of work performed in your ISR, changing the RTX51 Timer Tick rate to one that is slower, or using the following configuration option.

  • LONG_USR_INTR specifies whether or not the application has interrupts (other than the RTX51 Tiny Timer Tick Interrupt) that execute longer than a timer tick interval. When this configuration option is set to a value of 1, RTX51 Tiny includes code to protect the RTX51 Tiny Timer Tick Interrupt from reentrancy. The default setting is 0 for fast interrupts.


RTX51 Tiny User's Guide: Code Banking

Code Banking

The following configuration option allows you to specify whether or not your RTX51 Tiny application uses code banking.

  • CODE_BANKING specifies whether or not the application uses code banking. This option must be set to a value of 1 if code banking is used or a value of 0 if code banking is not used. The default setting is 0 for no code banking.

Note

  • L51_BANK.A51 Version 2.12 or higher is required for RTX51 Tiny program that use code banking.


RTX51 Tiny User's Guide: Stack

Stack

Several options are available for stack configuration. The following EQUates define the size of the internal RAM used for stack area and the minimum free space on the stack. A macro allows you to specify code that is executed when there is there is not enough free stack on the CPU stack.

  • RAMTOP specifies the top address for the on-chip stack. You should not change this unless you have IDATA variables located above the stack. The default setting is 0xFF.
  • FREE_STACK specifies the minimum number of bytes available on the stack. When switching to a task, if RTX51 Tiny detects fewer than the value specified, the STACK_ERROR macro executes. A value of 0 disables stack checking. The default setting is 20 bytes.
  • STACK_ERROR is a macro that specifies the instructions to execute in the event of a stack error (fewer than FREE_STACK bytes available). The default macro disables interrupts and enters an endless loop. For example:
    STACK_ERROR MACRO
CLR EA ; disable interrupts
SJMP $ ; endless loop if stack space is exhausted
ENDM


RTX51 Tiny User's Guide: Idle Task

Idle Task

When no tasks are ready to run RTX51 Tiny executes an Idle Task. The Idle Task is a simple loop that does nothing—it only waits for an RTX51 Tiny Timer Tick Interrupt to switch to a task that is ready. The following EQUates allow you to configure different aspects of the RTX51 Tiny Idle Task.

  • CPU_IDLE is a macro that specifies the code to execute in the Idle Task. The default instructions set the Idle Mode bit in the PCON register (available on most 8051 devices). This saves power by halting program execution until an interrupt occurs. For example:
    CPU_IDLE MACRO
ORL PCON,#1 ; set 8051 CPU to IDLE
ENDM
  • CPU_IDLE_CODE specifies whether or not the CPU_IDLE macro is executed in the Idle Task. The default setting is 0, so the CPU_IDLE macro is not included in the Idle Task.


RTX51 Tiny User's Guide: Library Files

Library Files

RTX51 Tiny includes two library files:

  • RTX51TNY.LIB is used for non-banking RTX51 Tiny programs.
  • RTX51BT.LIB is used for code-banking RTX51 Tiny programs.

The RTXTINY2.PRJ project found in the \KEIL\C51\RTXTINY2\SOURCECODE\ folder is used to build these two libraries.

Note

  • You should not explicitly include either of the RTX51 Tiny libraries in your application. That is done automatically when you use the µVision2 IDE or when you use the command-line linker.
  • When you build the RTX51 Tiny libraries, the default configuration file (CONF_TNY.A51) is included in the library. If you do not explicitly include a configuration file (CONF_TNY.A51) in your project, the default one from the library will be included. Subsequent changes to the configuration file stored in the library may have adverse effects on the operation of your application.


RTX51 Tiny User's Guide: Optimizing

Optimizing

There are several thing you can do to optimize your RTX51 Tiny programs.

  • If possible, disable Round-Robin task switching. Round-Robin requires 13 bytes of stack space to store the task context and all registers. This space is not required if task switching is triggered by calling an RTX51 Tiny library routine (like os_wait or os_switch_task).
  • Use the os_wait routine instead of relying on the Round-Robin timeout to switch a task. This improves system reaction time and task response time.
  • Avoid setting the timer tick interrupt rate too fast. Setting the time-out for the timer tick to a small value increases the number of ticks per second but decreases the amount of time available for tasks (because the timer tick interrupt takes 100-200 cycles to execute). Set the time-out value high enough to minimize the effects of the timer tick interrupt handler.


RTX51 Tiny User's Guide: Using RTX51 Tiny

Using RTX51 Tiny

To use RTX51 Tiny, you must be able to successfully create RTX51 programs and compile and link them.


RTX51 Tiny User's Guide: Writing Programs

Writing Programs

When you write programs for RTX51 Tiny you define RTX51 Tiny Tasks (using the _task_ keyword) and you use the RTX51 Tiny kernel routines which are prototyped in RTX51TNY.H.


RTX51 Tiny User's Guide: Include Files

Include Files

RTX51 Tiny requires the use of only one include file: RTX51TNY.H. All library routines and constants are defined in this header file. You may include it in your RTX51 Tiny source files as follows:

#include <rtx51tny.h>


RTX51 Tiny User's Guide: Programming Guildelines

Programming Guildelines

There are a few rules you must follow when creating RTX51 Tiny programs.

  • Be sure to include the RTX51TNY.H header file.
  • Do not create a main C function. RTX51 Tiny has its own main function.
  • You program must contain at least one task function.
  • Your program must call at least one RTX51 Tiny library routine (like os_wait). Otherwise, the linker will not include the RTX51 Tiny Library.
  • Task 0 is the first function in your program that executes. You must call the os_create_task function from task 0 to run other tasks.
  • Task functions must never exit or return. The task must repeat using a while(1) or similar construct. Use the os_delete_task function to halt a running task.
  • You must specify RTX51 Tiny in µVision2 or on the linker command line.

Several technical articles about RTX51 Tiny are available on the Keil Software Knowledgebase.


RTX51 Tiny User's Guide: Defining Tasks

Defining Tasks

Real-Time or multitasking applications are composed of one or more tasks that perform specific operations. RTX51 Tiny supports a maximum of 16 tasks.

Tasks are simply C functions that have a void return type and a void argument list and are declared using the _task_ function attribute. For example:

void func (void) _task_ task_id

where

func | is the name of the task function.
task_id | is a task ID number from 0 to 15.

The following example defines the function job0 as task number 0. This task increments a counter and repeats.

void job0 (void) _task_ 0 {
  while (1) {
    counter0++;	/* increment counter */
  }
}

Note

  • All tasks should be implemented as endless loops. A task should never return.


RTX51 Tiny User's Guide: Compiling and Linking

Compiling and Linking

There are basically two ways to compile and link your RTX51 Tiny applications. The following show you how to build RTX51 Tiny Applications...

  • Using the µVision2 IDE.
  • Using the Command-Line Tools.

    • Copyright (c) Keil Software, Inc. All rights reserved.


RTX51 Tiny User's Guide: Command-Line Tools

Command-Line Tools

RTX51 Tiny is fully integrated into the C51 programming language. This makes generation of RTX51 Tiny applications very easy to master. To create an RTX51 Tiny program, you need only write C functions. No assembly programming is required.

To compile your RTX51 Tiny programs from the command line...

Invoke the compiler as normal. No special directives are required. For example:

C51 RTXPROG.C DEBUG OBJECTEXTEND

The resulting RTXPROG.OBJ file contains the C code and RTX51 Tiny tasks you defined.

To link your RTX51 Tiny programs from the command line...

  • Specify the RTX51TINY directive on the linker command line.
  • Include the RTX_CONF.OBJ file in the list of object files (if you made configuration changes).

For example:

BL51 RTXPROG.OBJ, RTX_CONF.OBJ RTX51TINY

The RTX51TINY directive instructs the linker to link RTXPROG.OBJ with RTX_CONF.OBJ and to include the RTX51 Tiny library. An RTX51 Tiny program using the tasks created in your C files is created.

Note

  • Do not create a main C function for your RTX51 Tiny programs. Create only task functions. The main C function is included in the RTX51 Tiny Library to start the operating system and task 0. If you include a main function in your application, you will receive a linker error indicating there are multiple public definitions of main.
  • You must create at least one task function in your program.
  • Your application must call at least one RTX51 Tiny function (like os_wait or os_create_task) for the linker to include the RTX51 Tiny Library.


RTX51 Tiny User's Guide: µVision2 IDE

µVision2 IDE

To create RTX51 Tiny programs with µVision2...

  1. Open the Options for Target dialog (select Options for Target from the Project menu).
  2. Select the Target tab.
  3. Select RTX-51 Tiny from the Operating System option list.


RTX51 Tiny User's Guide: Debugging

Debugging

The µVision2 Simulator allows you to run and test your RTX51 Tiny applications. RTX51 Tiny Applications load just like non-RTX51 Tiny programs. No special commands or options are required for debugging.

A kernel-aware dialog displays all aspects of the RTX51 Tiny kernel and the tasks in your program. Select RTX51 Tiny Tasklist from the Peripherals menu to display this dialog.

  • TID is the Task ID specified in the task definition.
  • Task Name is the name of the task function.
  • State is the current state of the task.
  • Wait for Event specifies the event(s) for which the task is waiting.
  • Sig indicates the state of the task's signal flag (1=set).
  • Timer indicates the number of timer ticks before the task reaches a time-out. This is a free-running timer that is only used when the task is waiting for a timeout or interval.
  • Stack indicates the starting address of the local task stack.


RTX51 Tiny User's Guide: Function Reference

Function Reference

The following pages describe the RTX51 Tiny system functions. The system functions are listed in alphabetical order and each is divided into several sections:

Summary: | Briefly describes the routine's effect, lists include file(s) containing its declaration and prototype, illustrates the syntax, and describes any arguments.
Description: | Provides a detailed description of the routine and how it is used.
Return Value: | Describes the value returned by the routine.
See Also: | Names related routines.
Example: | Gives a function or program fragment demonstrating proper use of the function.

Note

  • Functions that begin with os_ may be called from a task but not from an interrupt service routine.
  • Functions that begin with isr_ may be called from an interrupt service routine but not from a task.


RTX51 Tiny User's Guide: isr_send_signal

isr_send_signal

Summary:
#include <rtx51tny.h>

char isr_send_signal (
  unsigned char task_id);     /* ID of task to signal */
Description: The isr_send_signal function sends a signal to task task_id. If the specified task is already waiting for a signal, this function call readies the task for execution. Otherwise, the signal is stored in the signal flag of the task. The isr_send_signal function may be called only from interrupt functions.
Return Value: The isr_send_signal function returns a value of 0 if successful and -1 if the specified task does not exist.
See Also: os_clear_signal, os_send_signal, os_wait
Example:
#include <rtx51tny.h>

void tst_isr_send_signal (void) interrupt 2
{
isr_send_signal (8);    /* signal task #8 */
}


RTX51 Tiny User's Guide: isr_set_ready

isr_set_ready

Summary:
#include <rtx51tny.h>

char isr_set_ready (
  unsigned char task_id);     /* Task to make ready */
Description: The isr_set_ready function places the task specified by task_id into the ready state.

The isr_set_ready function may be called only from interrupt functions.
Return Value: None.
See Also: os_set_ready, os_wait
Example:
#include <rtx51tny.h>

void tst_isr_set_ready (void) interrupt 2
{
isr_set_ready (1);    /* Set ready flag for task 1 */
}


RTX51 Tiny User's Guide: os_clear_signal

os_clear_signal

Summary:
#include <rtx51tny.h>
char os_clear_signal (
  unsigned char task_id);         /* signal to clear */
Description: The os_clear_signal function clears the signal flag for the task specified by task_id.
Return Value: The os_clear_signal function returns a value of 0 if the signal flag was successfully cleared. A value of -1 is returned if the specified task does not exist.
See Also: isr_send_signal, os_send_signal
Example:
#include <rtx51tny.h>

void tst_os_clear_signal (void) _task_ 8
{
.
.
.
os_clear_signal (5);   /* clear signal flag in task 5 */
.
.
.
}


RTX51 Tiny User's Guide: os_create_task

os_create_task

Summary:
#include <rtx51tny.h>

char os_create_task (
  unsigned char task_id);     /* ID of task to start */
Description: The os_create_task function starts the defined task function using the task number specified by task_id. The task is marked as ready and is executed according to the rules specified for RTX51 Tiny.
Return Value: The os_create_task function returns a value of 0 if the task was successfully started. A value of -1 is returned if the task could not be started or if no task was defined using the specified task number.
See Also: os_delete_task
Example:
#include <rtx51tny.h>
#include <stdio.h>           /* for printf */

void new_task (void) _task_ 2
{
.
.
.
}

void tst_os_create_task (void) _task_ 0
{
.
.
.
if (os_create_task (2))
  {
  printf ("Couldn't start task 2\n");
  }
.
.
.
}


RTX51 Tiny User's Guide: os_delete_task

os_delete_task

Summary:
#include <rtx51tny.h>

char os_delete_task (
  unsigned char task_id);       /* task to delete */
Description: The os_delete_task function stops the task specified by the task_id argument. The specified task is removed from the task list.
Return Value: The os_delete_task function returns a value of 0 if the task was successfully stopped and deleted. A return value of -1 indicates the specified task does not exist or had not been started.
See Also: os_create_task
Example:
#include <rtx51tny.h>
#include <stdio.h>            /* for printf */

void tst_os_delete_task (void) _task_ 0
{
.
.
.
if (os_delete_task (2))
  {
  printf ("Couldn't stop task 2\n");
  }
.
.
.
}


RTX51 Tiny User's Guide: os_running_task_id

os_running_task_id

Summary:
#include <rtx51tny.h>

char os_running_task_id (void);
Description: The os_running_task_id function determines the task id of the task currently executing.
Return Value: The os_running_task_id function returns the task ID of the task currently executing. This value is a number in the range 0-15.
See Also: os_create_task, os_delete_task
Example:
#include <rtx51tny.h>

void tst_os_running_task (void) _task_ 3
{
unsigned char tid;

tid = os_running_task_id ();    /* tid = 3 */
}


RTX51 Tiny User's Guide: os_send_signal

os_send_signal

Summary:
#include <rtx51tny.h>

char os_send_signal (
  unsigned char task_id);     /* ID of task to signal */
Description: The os_send_signal function sends a signal to task task_id. If the specified task is already waiting for a signal, this function call readies the task for execution. Otherwise, the signal is stored in the signal flag of the task.

The os_send_signal function may be called only from task functions.
Return Value: The os_send_signal function returns a value of 0 if successful and -1 if the specified task does not exist.
See Also: isr_send_signal, os_clear_signal, os_wait
Example:
#include <rtx51tny.h>

void signal_func (void) _task_ 2
{
.
.
.
os_send_signal (8);        /* signal task #8 */
.
.
.
}

void tst_os_send_signal (void) _task_ 8
{
.
.
.
os_send_signal (2);        /* signal task #2 */
.
.
.
}


RTX51 Tiny User's Guide: os_reset_interval

os_reset_interval

Summary:
#include <rtx51tny.h>

void os_reset_interval (
  unsigned char ticks);     /* Number of Timer Ticks */
Description: The os_reset_interval function is used to correct timer problems that occur when the os_wait function is used to wait for K_IVL and K_SIG events simultaneously. In such a case, if a signal (K_SIG) event causes os_wait to exit, the interval timer is not adjusted and subsequent calls to os_wait to wait for an interval may not delay for the required time period. The os_reset_interval allows you to reset the interval timer in such an event.
Return Value: None.
See Also: os_wait
Example:
#include <rtx51tny.h>

void task_func (void) _task_ 4
{
.
.
.
switch (os_wait2 (K_SIG | K_IVL, 100))
  {
  case TMO_EVENT:
    /* Timeout occurred - os_reset_interval not required */
    break;

  case SIG_EVENT:
    /* Signal received - os_reset_interval required */
    os_reset_interval (100);
    /* do something with the signal */
    break;
  }
.
.
.
}


RTX51 Tiny User's Guide: os_set_ready

os_set_ready

Summary:
#include <rtx51tny.h>

char os_set_ready (
  unsigned char task_id);     /* Task to make ready */
Description: The os_set_ready function places the task specified by task_id into the ready state.

The os_set_ready function may be called only from task functions.
Return Value: None.
See Also: isr_set_ready, os_wait
Example:
#include <rtx51tny.h>

void ready_func (void) _task_ 2
{
.
.
.
os_set_ready (1);     /* Set ready flag for task 1 */
.
.
.
}


RTX51 Tiny User's Guide: os_switch_task

os_switch_task

Summary:
#include <rtx51tny.h>

char os_create_task (void);
Description: The os_switch_task function allows a task to give up the CPU and allow another task run. If the task calling os_switch_task is the only task ready for execution it resumes running immediately.
Return Value: None.
See Also: os_wait
Example:
#include <rtx51tny.h>
#include <stdio.h>           /* for printf */

void long_job (void) _task_ 1
{
float f1, f2;

f1 = 0.0;

while (1)
  {
  f2  = log (f1);
  f1 += 0.0001;
  os_switch_task ();   // run other tasks
  }
}


RTX51 Tiny User's Guide: os_wait

os_wait

Summary:
#include <rtx51tny.h>

char os_wait (
  unsigned char event_sel,      /* events to wait for */
  unsigned char ticks,          /* timer ticks to wait */
  unsigned int dummy);          /* unused argument */
Description: The os_wait function halts the current task and waits for one or several events such as a time interval, a time-out, or a signal from another task or interrupt. The event_sel argument specifies the event or events to wait for and can be any combination of the following manifest constants:
Event | Description
K_IVL | Wait for the interval specified by ticks.
K_SIG | Wait for a signal.
K_TMO | Wait for a time-out specified by ticks.

The above events can be logically ORed using the vertical bar character ('|'). For example, K_TMO | K_SIG, specifies that the task wait for a time-out or for a signal.

The ticks argument specifies the number of timer ticks to wait for an interval event (K_IVL) or a time-out event (K_TMO).

The dummy argument is provided for compatibility with RTX51 Full and is not used in RTX51 Tiny.

Return Value: When one of the specified events occurs, the task is enabled for execution. Execution is restored and the manifest constant that identifies the event that restarted the task is returned by the os_wait function. Possible return values are:
Return Value | Description
RDY_EVENT | The task's ready flag was set by either the os_set_ready or isr_set_ready routine.
SIG_EVENT | A signal was received.
TMO_EVENT | A time-out has completed or an interval has expired.
NOT_OK | The value of the event_sel argument is invalid.
See Also: os_wait1, os_wait2
Example:
#include <rtx51tny.h>
#include <stdio.h>       /* for printf */

void tst_os_wait (void) _task_ 9
{
while (1)
  {
  char event;

  event = os_wait (K_SIG + K_TMO, 50, 0);

  switch (event)
    {
    default:             /* this never happens */
      break;

    case TMO_EVENT:      /* time-out */
                         /* 50 tick time-out */
      break;

    case SIG_EVENT:      /* signal received */
      break;
    }
  }
}


RTX51 Tiny User's Guide: os_wait1

os_wait1

Summary:
#include <rtx51tny.h>

char os_wait1 (
  unsigned char event_sel);          /* events to wait for */
Description: The os_wait1 function halts the current task and waits for an event to occur. The os_wait1 function is a subset of the os_wait function and does not allow all of the events that os_wait offers. The event_sel argument specifies the event to wait for and can have only the value K_SIG which waits for a signal.
Return Value: When the signal events occurs, the task is enabled for execution. Execution is restored and a manifest constant that identifies the event that restarted the task is returned by the os_wait1 function. Possible return values are:
Return Value | Description
RDY_EVENT | The task's ready flag was set by either the os_set_ready or isr_set_ready routine.
SIG_EVENT | A signal was received.
NOT_OK | The value of the event_sel argument is invalid.
See Also: os_wait, os_wait2
Example: See os_wait.


RTX51 Tiny User's Guide: os_wait2

os_wait2

Summary:
#include <rtx51tny.h>
char os_wait2 (
  unsigned char event_sel,      /* events to wait for */
  unsigned char ticks);         /* timer ticks to wait */
Description: The os_wait2 function halts the current task and waits for one or several events such as a time interval, a time-out, or a signal from another task or interrupt. The event_sel argument specifies the event or events to wait for and can be any combination of the following manifest constants:
Event | Description
K_IVL | Wait for the interval specified by ticks.
K_SIG | Wait for a signal.
K_TMO | Wait for a time-out specified by ticks.

The above events can be logically ORed using the vertical bar character ('|'). For example, K_TMO | K_SIG, specifies that the task wait for a time-out or for a signal.

The ticks argument specifies the number of timer ticks to wait for an interval event (K_IVL) or a time-out event (K_TMO).

Return Value: When one of the specified events occurs, the task is enabled for execution. Execution is restored and the manifest constant that identifies the event that restarted the task is returned by the os_wait2 function. Possible return values are:
Return Value | Description
RDY_EVENT | The task's ready flag was set by either the os_set_ready or isr_set_ready routine.
SIG_EVENT | A signal was received.
TMO_EVENT | A time-out has completed or an interval has expired.
NOT_OK | The value of the event_sel argument is invalid.
See Also: os_wait, os_wait1
Example: See os_wait.