Home    Resources    Monitoring    Equipment    Forums    Links    Pictures Gallery    Contact    

Links
Home
Resources
Monitoring
Equipment
Forums
Links
Pictures Gallery
Contact
Admin

    

Search

        

Your account





Lost Password?
No account yet? Register

            

            

Who is online ?

            



Simple task sequencer (RTOS) for small microcontrollers
Written by Stephane   
lundi, 18 août 2008

This article is available in french in the following PDF file : sequenceur de tâches temps réel.pdf 

 

This task sequencer is a small RTOS (Real Time Operating System) written in C language which can easily be implemented in a small microcontroller like 8051, 68hc08, PIC or so...

The compiled code for 68hc08 requires 371 bytes of ROM and uses 4 bytes of RAM. It has been ported without modification from Infineon (Siemens) C166 to Freescale HC08 and S08 famillies via 8051 without any modification.

 

Principle

The sequencer has differents tasks groups : for instance, 10, 20, 50, 100 ,250 ,500 and 1000ms. In each tasks group, an applicative function call can be inserted. Thus the function will run every 'x' milliseconds depending on the tasks group the call has been inserted.

rrex_figure1.jpg

On low-speed microcontrollers, the main cycle basetime can be increased from 10 to 20ms for instance depending on the speed of the 16-bits timer used.

Example : A project with data received from an UART (RS232) under interrupt : each interrupt allows to store the received byte into a rolling buffer and the buffer can be processed every 50ms to decode the data while a matrix keyboard is read every 20ms and analog acquisitions every 100ms...

In this way the written code has no waiting loops ! If an event has not occured then the function exits and the condition will be tested again in the next cyclic call. The main benefit of implementing a such sequencer is that the code architecture becomes very clear, a function call can be moved easily without  corrupting the program architecture. This also reduce bugs in code as no functions are waiting something which could never happen and could block the code and generate a watchdog interrupt !

 

Description of the sequencer 

The figure above shows a sequencer with a basetime of 10ms. There are 3 tasks called respectively every 10, 50 and 100ms and each task duration is 2.5ms.

The smallest remaining time of all cycles is stored in a variable which enables the code designer to check if any cycle has exceeded the cycle basetime (10ms in the example). In a such case the remaining time will be 0 of course and the following cycle time will be reduced in order to avoid time shifts. Obviously, if all the cycles are lasting more than the basetime (10ms) then the sequencer will be unable to make up for lost time.

This is the reason why some groups are split up in several parts in order to spread over the functions calls of each group. For instance let imagine 4 new tasks to insert into the software which are called every 100ms. Each task last 1ms. The diagram below shows that it is not acceptable : one cycle will last 11.5ms ! 

rrex_figure2.jpg

 

 

 

 

So the new tasks are going to be spread over differents groups. The 100 ms group is indeed split up in 5 100ms groups shifted between themselves by 20ms. Thus there will be a task in 4 out of 5 groups as shown below :

rrex_figure3.jpg 

 

 

 

Despite the main cycle basetime is 10ms, it is split up into 2 parts : the first one at the begining and the second one at the end. This allows to manage priorities in the calls : priorities the highest will be called in the first group, and the lowest in the second group. The following chart shows the worst case cycle where all the groups are called in the same cycle :

rrex_figure4.jpg

 

 

 

 

 

As the sequencer uses a timer and is not interrupt driven, the 10ms cycle time  may be not very accurate. There might have a small jitter of about few microseonds . In most applications it won't be a problem.

 

Settings

Some settings are located in the file RREX.H. The designer may modify this file according to the platform he uses : clock frequency, sequencer period and the name of the timer(counter) register. Please note that the maximum period depends on the clock speed. The timer(counter) used is a 16-bits (i.e. 65535). With a 4MHz clock speed this means the overflow occurs at 65535/4e6 = 16.38ms. Only integers can be used in this variable which means that the maximum period will be 16ms ! In order to increase this period if needed, one way is to use the timer prescaler often implemented in microcontrollers. (PS register in the 68hc08).

 

The source code

The project you can download here has been compiled using Metrowerks CodeWarrior for 68hc08. However it can easily be ported on any other platform as it is written in ANSI C.

The main() function only calls the initilization routines and the sequencer main task. All the applicatives functions calls are located in the file RREX.C, spread over in all the groups.

Note that interrupt routines may happen in any cycle of the sequencer. This means you have to take into account this when designing you timing schedule.

The following excel file is a usefull tool to graphically monitor and optimize the sequencer workload. I've made it in order to move easily the differents task and see what happens on the microcontroller load. 

RREX Monitor.xls

In order to keep this code clear, the RREX.C file should have the less code as possible which means only calls to functions located in other C files.

 

Download the Codewarrior project with sourcecode

RREX example Project

 

Example

Fichier MAIN.C 
void main(void)
{
   /* Initialization */
   INIT_Init ();

      /* Main loop */       
      while (1)
      {
         /* Call the regular runtime sequencer */
         RREX_RegularRuntimeExecutive();
      }
}

 
Fichier RREX.C
/*------------------------------------------------
         10ms Group 1 routines
------------------------------------------------*/
void Rrex10msec_Group1(void)
{
         ASIP_ReadADC ();
         DISP_ReadIO ();
         DISP_ReadKeyboard ();
         DDSD_UpdateDDSFrequency ();
         UART_ProcessTheBuffer ();
        
}

 

Last Updated ( lundi, 18 août 2008 )
 





  © Copyright 2008. Hamradio Experiments is powered by F1TJJ - Stéphane Rey