Purdue University Mark

Purdue University

Help for PBO/RT

PBO/RT Module Library

RecoNode Software Tutorials

RecoNode Hardware Tutorials

PBO/RT (SCHED2) Overview

PBO/RT (Port-Based Objects/Real-Time) is a library of routines that provide task scheduling and task dispatch functions on the PC, UM003 (ATmega128 board), RecoNode (Virtex 4), and PSX embedded platforms. Some variations exist in the different implementations, so beware. This scheduler is not pre-emptive (though a pre-emptive version is available), so you must use co-routines (as discussed in class) and careful attention to implementation to meet task deadlines.

To use the PBO/RT routines with DOS, see the TurboC Help Page.

The PBO/RT library is modeled after the Chimera Port-Based Object interface for subsystems servers (SBS). It is a coarse object-oriented model of a task in which each task consists of several standard "methods" that govern its real-time operation. These methods include:

There is no concept of inheritance, however.


Because the scheduler for the Atmel AVR microcontrollers is more restricted, find detailed help on the links below:

DOS, PSX, and RecoNode PBO/RT versions

DOS, PSX, and RecoNode PBO/RT plus ReFrESH versions

Atmel AVR PBO/RT versions


What is a Scheduler?

A scheduler is something like an operating system. More accurately, it is part of the kernel of an operating system. An operating system is a piece of software that provides some basic services on a computer. As seen below, the operating system provides some APIs (Application Programming Interfaces) for user applications to allow basic I/O (disk access, keyboard, terminal) and extended I/O (mouse internet, audio, etc) as well as some sort of user interface to make access to programs and data simple. (This could be command-line oriented, as in Unix, or graphically-oriented as in Windows.)

A kernel, which is part of the inner workings of an operating system, provides three things:

The scheduler, described here, is a micro-kernel, in that it provides task dispatching and task scheduling for periodic, real-time tasks.

An Example

Suppose you have a green LED and a red LED and you want to blink the green LED at 4 Hz and the red LED at 2 Hz. One way to approach this is to create a program with a simple while loop:

void main()
{
  volatile long i;

  while (1){
    redON();	/* turn both LEDs on */
    greenON();

    /* pause for 1/8 second */
    for (i=0; i<153598; i++);

    greenOFF();

    /* pause for 1/8 second */
    for (i=0; i<153598; i++);

    greenON();
    redOFF();
    /* pause for 1/8 second */
    for (i=0; i<153598; i++);

    greenOFF();

    /* pause for 1/8 second */
    for (i=0; i<153598; i++);

  } /* end while */
}
While it might take some experimenting to arrive at the number for 1/8th of a second (or you could use a delay() command), the above program is simple and easy to get working. But what would happen if you then wanted to change the green LED to 5 Hz? Worse, what if you decide you need to read a temperature sensor at 3 Hz while the LEDs are blinking? What if the temperature sensor has variable delays?

The problem with the above code is that it is very brittle. If you change anything, you change the timing of the blinks. Every time you make a change to one part of the code, it affects the timing of all parts of the code.

A scheduler is perfect for periodic tasks such as these. It handles all the timing and task dispatching automatically so changes to one part of code don't affect other parts of code. This can be a tremendous benefit! However, the drawback is that you must learn how to use the scheduler and you must write your code according to a pre-defined "formula."

Using PBO/RT, your code would look something like this (details may vary):


#include "pbort.h"

redLED_cycle(void *vptr)
{
  if (redLEDisOn())
	redOFF();
  else 
	redON();

  return I_OK;
}

redLED_init(processT *P_ptr, void *vptr)
{
  /* set up method function pointers */
  p_ptr->on_fptr = NULL;
  p_ptr->cycle_fptr = redLED_cycle;
  p_ptr->off_fptr = NULL;

  /* other code may be required here for your platform */

  return I_OK;
}

greenLED_cycle(void *vptr)
{
  if (greenLEDisOn())
	greenOFF();
  else 
	greenON();

  return I_OK;
}

greenLED_init(processT *P_ptr, void *vptr)
{
  /* set up method function pointers */
  p_ptr->on_fptr = NULL;
  p_ptr->cycle_fptr = greenLED_cycle;

  /* other code may be required here for your platform */

  return I_OK;
}

void main()
{
  processT *redMod, *greenMod;	/* handles to the MODULEs */

  /* initialize the scheduler */
  sched_init(500);

  /* Spawn the red LED task at 2 Hz */
  redMod = sbsSpawn(redLED_init, 2, 100, NULL);		
  /* Spawn the green LED task at 4 Hz */
  greenMod = sbsSpawn(greenLED_init, 4, 100, NULL);

  /* start the red LED blinking */
  sbsControl(redMod, SBS_ON);

  /* start the green LED blinking */
  sbsControl(greenMod, SBS_ON);

  while (1)
    sched();

  shutdown();

}

While this code is far more complex than the first example, adding new modules will not affect the existing modules and changes to existing modules are easy.


Prof. Voyles' Home Page

Copyright: © 2001,2008,2009,2015 by Richard Voyles. All rights reserved.
School of Engineering Technology, Purdue University.

Maintained by Richard Voyles
Last modified: Dec 3, 2016