Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

A Simple Real-Time Executive


November 1992/A Simple Real-Time Executive/Listing 2

Listing 2 tinyexec.c

/***************************************
*                                      *
*              tiny exec               *
*                                      *
****************************************
  written by: Charles B. Allison
  Allison Technical Services
  8343 Carvel
  Houston, TX 77036
  PHONE#  (713) 777-0401 | BBS/FAX (713) 77-4746
****************************************
version 1.1
last change 6-3-92 11:35
*/
/* ***** include files ****** */
#include <dos.h>
#include <conio.h>
#include <stdio.h>
#include <time.h>
#include "tinyexec.h"
/* ********* define statements ********* */
/* #define DEBUG 1*/
#define MICROSOFT 1
#define NUM_TIMERS 3 /* number of timers */
#define NUM_TASKS 3  /* number of tasks  */
#define TASK_TICKS 2 /* TASK_TICKS is the # of */
       /* rtc clock ticks between task exec runs */
#define OLD_TICKS 1
/* OLD_TICKS is the number of rtc clock ticks between
running oldtimer, the system clock at 18.2Hz */
#define NORMAL_COUNT 0
/* value normally used in counter 65536 (= 0)*/
#define RTC_COUNT (unsigned)((65536L/OLD_TICKS)&0xffff)
/* value to be used in rtc interrupt rate
      -- relates to OLD_TICKS */
#ifdef MICROSOFT /* Microsoft compatibility */
#include <graph.h>
#pragma intrinsic (inp, outp, _enable, _disable)
#define gotoxy(x,y) _settextposition(y,x)
#define clrscr()_clearscreen(_GWINDOW)
#endif
/* ********** Inline Functions ************ */
/* -------- set_timer ----------- */
/* set timer i to count down in time t */
#define set timer(i,t) _disable();\
timers [i] =t;\
_enable();
/* -------- req_task ----------- */
/* request task i */
#define req_task(i)_disable();\
task_flag[i] = REQ_TASK;\
_enable();
/* -------resume_task -------- */
#define resume_task(i)_disable();\
task_flag[i] |= REQ_TASK;\
task_flag[i]++;\
_enable();
/* use following inline when ints are disabled */
/* -------- iset_timer ----------- */
/* set timer i to count down in time t */
#define iset_timer(i,t) timers[i]=t;
/* -------- ireq_task ----------- */
/* request task i ints disabled */
#define ireq_task(i) task_flag[i] = REQ_TASK;
/* -------iresume_task -------- */
/* resume task - interrupts disabled */
#define iresume_task(i) task_flag[i] |= REQ_TASK;\
task_flag[i]++;
/* ******** function prototypes ************* */
void main(void);
void task0(void);
void task1(void);
void init_rtc(void);  /* set up rtc/tasker */
void close_rtc(void); /* shut down rtc/tasker */
void init_cntr(unsigned count);
void interrupt rtcint(void);
void timr0(void);
void timr1(void);
void timr2(void);
/* ******* tiny exec variables ******** */
/* timer counter and function arrays */
unsigned timers[NUM_TIMERS] = { 0, 0, 0 };
void (*timer[NUM_TIMERS]) (void)={timr0,timr1,timr2};
/* ticks between task exec */
unsigned task_time = TASK_TICKS;
/* new timer ticks between old timer calls */
unsigned old_time=OLD_TICKS;
/* storage for old system clock int vector*/
void (interrupt far *oldtimer)(void);
/* task flag and function arrays */
unsigned task_flag[NUM_TASKS] = {0,0,IN_PROC};
void (*task[NUM_TASKS])(void) = {task0,task1,main};
int cur_task_num;/* indicates what is current task */
/* *************** functions ***************** */
/* combination real time clock and task exec */
void interrupt rtcint(void)
{
int i; /* local stack variable */
/* handle timers here, then 18.2Hz system clock
then do tasks
***************************************** */
for(i = 0;i < NUM_TIMERS;i++ )
   {
    if (timers[i])
      {
       if(!(--timers[i])) (*timer[i])();
      }
   }
/* call system clock 18.2 x per second */
if(!(--old_time))
  {
   old_time=OLD_TICKS;
#ifndef DEBUG
  (*oldtimer)();      /* call old timer here */
  }  else {
    outp (XT8259,CLR_INT);  /* clear int req */
#endif
  }
/* ------end of timers ---------- */
task_time--;    /* one less time tick */
if(task_time) return; /*not time for task exec */
task_time = TASK_TICKS; /* do tasks now*/
/* --------- task exec section ---------- */
for(i = 0; i < NUM_TASKS;i++)
 {
 if (task_flag[i] & IN_PROC)
  {
   cur_task_num = i;
   return;  /* found one in process so return */
  }
 if(task_flag[i] & REQ_TASK)
  {
   task_flag[i]=IN_PROC | (task_flag[i] & ~REQ_TASK);
       /* begin task */
       cur_task_num = i; /* current task in process*/
       _enable();        /* now allow interrupts */
       (*task[i])();     /* do task */
       _disable();
       task_flag[i] &: ~IN_PROC;  /* done */
      }
  }
}
/* ***************** init_rtc ******************** */
void init_rtc(void)  /* routine to set up rtc/tasker */
{
 _disable();
 oldtimer = _dos_getvect(TIMER); /* get timer vector*/
 _dos_setvect(TIMER,rtcint); /* set real time timer */
 init_cntr( RTC_COUNT);
 _enable();
}
/* ****************** close_rtc ******************* */
void close_rtc(void) /* shut down rtc/tasker */
{
 _disable();
 _dos_setvect(TIMER,oldtimer); /* restore timer */
 init_cntr( NORMAL_COUNT);
 _enable();
}
/* *************** init_cntr ***************** */
void init_cntr(unsigned count)
{
 int lowb, highb;
 lowb = count % 256;
 highb = count / 256;
 outp (TIMR1_C,LOAD_T1); /* load count for 8253 */
 outp (TIMRI_T1, lowb);
 outp (TIMRI_T1, highb);
}
/* **** Example main and tasks *********** */
void set_beep(void);
void clr_beep(void);
void tsk1sub1 (void); /*subtasks for task 1 */
void tsk1sub2 (void);
int beep_len = 6; /* default to about 1/3 sec */

#define SPKR_CNTRL 0x61
#define SPKR_ENABLE 0x03
#define SPKR_DISABLE 0xfc

int t0_flag =0, t1_flag = 0;
int timer0= 0,timer1 = 0,timer2 = 0;
int state_of_tasks[NUM_TASKS];
int state_of_timers[NUM_TIMERS];
/* --------- main ------------ */
void main (void)
{
int i,oldt0,oldtmr0=0,endit = 1;
time_t t;
#ifndef DEBUG
 init_rtc(); /* open rtc */
#endif
clrscr();
gotoxy(1,1);
printf("Counts for t0_flag t1_flag ");
printf("timer0 timer1 timer2");
gotoxy(1,4);
printf("task and timer flag images");
gotoxy(1,5);
printf("task0 task1 timer0 timer1 timer2");
set_timer(0,18); /* begin timer 0 in 12 ticks */
req_task(0);     /* request task 0 to run once */
set_timer(1,90); /*begin timer 1 in 90 ticks */
while(endit)
 {
  if(kbhit())
   {
    switch(getch()){
     case '\x1b':  /* exit on Esc */
      endit = 0;
      break;
     case ' ':
      req_task(1); /* do a beep*/
      break;
     default:
      break;
    } /* end of switch */
  } /* end of if */
if(t0_flag != oldt0)
 {
  oldt0=t0_flag;
  gotoxy(1,6); /* show current tasks and timers */
  for(i=0;i<NUM_TASKS-1;i++)
    printf("%4x ",state_of_tasks[i]);
  for(i=0;i<NUM_TIMERS;i++)
    printf(" %4d ",state_of_timers[i]);
 }
#ifdef DEBUG
 rtcint();
#endif
gotoxy(1,2);
printf("           %4d    %4d     %4d   %4d   %4d",\
     t0_flag,t0_flag,timer0,timer1,timer2);
if(timer0 != oldtmr0)
   {
    oldtmr0 = timer0;
    t=time(NULL);
    gotoxy(1,20);
    printf("%s",ctime(&t));
   }
 } /* end of while */
#ifndef DEBUG
 close_rtc();  /* restore rtc */
#endif
}
/* *********** tasks ************** */
/* -------- task0 ----------- */
void task0(void)
{
/* get current timer and task states */
int i;
t0_flag++;
for(i=0;i<NUM_TIMERS;i++)
  state_of_timers[i] = timers[i];
for(i=0;i<NUM_TASKS;i++)
 state_of_tasks[i] = task_flag[i];
}
/* ------- task1 --------- */
void task1(void)
{ /* handle beeps - 2 subtasks */
static void (*subexec1[])(void) = {
  tsk1sub1,
  tsk1sub2
  };
t1_flag++;
(*subexec1[task_flag[cur_task_num] & 0x01])();
} /* end task 1 */
void tsk1sub1 (void)
{                /* turn on beep */
outp(SPKR_CNTRL,inp(SPKR_CNTRL)| SPKR_ENABLE);
set_timer(2,beep_len); /*beep length*/
}
void tsk1sub2(void)
{              /* turn off beep here */
outp(SPKR_CNTRL, inp(SPKR_CNTRL) & SPKR_DISABLE);
}
/* ***************** timers ********************** */
/*Note - timers are run with interrupts disabled*/
void timr0(void)
{
timer0++; /* count of timer runs */
timers[0]=18; /* set time again */
}
void timr1(void)
{
timer1++; /* count of timer runs */
timers[1]=2; /* set timer again */
ireq_task(0);  /* request task 0 */
}
void timr2(void)
/* beep turn off timer */
{
timer2++; /* count of timer runs */
iresume_task(1);
}
/* End of File */


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.