home *** CD-ROM | disk | FTP | other *** search
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Communications and Multitasking Library
- For Datalight C
- by
- Matt Brandt
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Overview
-
- This library contains a multitasking kernel and a
- communications kernel. The communications kernel allows you
- to control the com ports of a PC in a simple way but allows
- any speed the com port is capable of running. The
- communications routines are interrupt driven so that even in
- very fast transfers a program will not have any trouble
- keeping up. The multitasking kernel allows a program to have
- several apparently simultaneous execution threads. This is
- especially usefull in communications because there is
- usually traffic in both directions. A small terminal program
- "mini.c" is included in this archive to demonstrate the
- concepts. While you may use the communications routines
- without worring about the multitasking I urge you to take
- the time to understand the multasking kernel. It will make
- your life much easier for many applications, not just
- communications. In the following pages I will discuss the
- concepts of the communications and multitasking routines and
- demonstrate how each routine is called. The last section
- deals with the example program mini.c and shows how it
- works.
-
- This package is being distributed as shareware. You may try
- it out, see if it is what you want, and if it fits a need
- you have then I ask that you send me 20 dollars. For your
- twenty dollars you will get the complete source code, a
- license to use any and all of these routines in your own
- code for profit without any royalties, and the other three
- models (P,D, and L) of the library. If you do not need this
- package and do not use it then you are under no obligation
- to send me any money. Please feel free to pass this archive
- on in it's original form to friends and BBS's that you think
- might be interested.
-
- If you want to send in a contribution send your check to:
-
- Matt Brandt
- PO Box 920337
- Norcross, GA 30092
-
- Your comments and suggestions are also welcome.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Multitasking Concepts
-
- This library implements what is called a non-preemptive
- scheduler. This means that when one task is running it will
- not be "preempted" by a task of higher priority. A task is
- only suspended when it makes one of two tasking calls. It is
- up to the programmer to make sure that all tasks get a
- chance to run. Each task has it's own stack area. The global
- and static data of the program is available to all tasks.
- The task scheduler does not "hook" any interrupts or take
- over any of the machine resources so any task can return to
- DOS at any time. This will have the effect of killing all of
- the other tasks.
-
- There can be up to 32 seperate tasks. The main program is
- assigned task number zero at program startup. The tasks are
- prioritized by task number with task zero being the highest
- priority task and task 31 being the lowest priority. You do
- not need to assign task numbers sequentially. It is
- perfectly acceptable to have only tasks zero and ten for
- instance. The scheduler will perform slightly better,
- however, when there are a minimum number of "holes" in the
- task assignments.
-
- Tasks can syncronize and communicate through signals. It is
- also possible for interrupt service routines to send signals
- to tasks. There are 32 signals available [0..31]. Any task
- can wait for a signal. It will then be suspended until that
- signal is sent by another task or an interrupt routine. If a
- signal is sent and there is nobody waiting for it then it
- will be saved until the next wait is performed. That wait
- will not suspend the task but instead will receive the
- signal that was previously sent. Only one occurance of each
- signal can be saved. Multiple unwaited occurrances are the
- same as one unwaited occurrance. More that one task may wait
- for a given signal. In this case the highest priority
- waiting task will be readied when the signal is sent.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- The task calls are as follows:
-
- t_create(tasknum,func,stk,stksiz);
- int tasknum;
- void (*func)();
- int *stk;
- int stksiz;
-
- This call creates a task whose task number is given by
- tasknum. If a task is already running at that task
- number it is replaced by the new task. func should be
- the address of a function to be executed as the new
- task. stk should point to an area of memory and stksiz
- should be the size of the task's stack area in bytes.
- If a task function returns the task is deleted. The new
- task is placed in a ready to run state but is not given
- control until scheduling occurs by way of a t_wait or
- t_yield call. If the new task number is the same as the
- currently running task then this call will have no
- effect.
-
- EXAMPLE:
-
- int t1stk[512];
-
- task1()
- {
- ..code to do a job
- }
-
- .
- t_create(1,task1,t1stk,sizeof(t1stk));
-
- t_kill(tasknum)
- int tasknum;
-
- This call will delete the task whose task number is
- given by tasknum. If tasknum matches the task number of
- the currently running task the current task will be
- killed and rescheduling will occur.
-
- t_wait(signo)
- int signo;
-
- The task issuing this call will wait until signal
- number signo is issued by another task or an interrupt
- service routine. If the signal was already issued then
- the current task will continue unhindered. When a task
- suspends then the highest priority ready task is
- continued at the point where it left off.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- t_signal(signo)
-
- This call causes an occurrance of signal number signo.
- The highest priority task waiting for that signal will
- be made ready. This call will NOT cause scheduling to
- occur. That must be done by a call to t_wait or
- t_yield.
-
- t_yield()
-
- This call will allow any higher priority tasks to
- execute. If the current task is the highest priority
- ready task then it will continue. Note that a yield
- from the main program (task zero) will always have no
- effect because it is always the highest priority task.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Communications overview
-
- The communications module contains procedures to initialize
- either (or both) com ports, send and receive characters on
- the ports, and set the mode and baud rates for the ports.
- Each routine is shown below with a description. These
- routines use the task scheduler to suspend tasks and signal
- when new input is available. Signals two thru five are used
- by these routines. You may ignore the multitasking, however,
- with no ill effects since the main task will be the only one
- running.
-
- int copen(portno,ibufsiz,obufsiz)
- int portno;
- int ibufsiz;
- int obufsiz;
-
- Open a com port and return a port handle. The portno
- should be 0 for com1 and 1 for com2. This sets up the
- input and output buffers and "hooks" the interrupt
- vector used to service the port. ibufsiz is the input
- buffer size in bytes and obufsiz is the output buffer
- size in bytes. Note that the input buffer should
- normally be much larger than then output buffer.
-
- cbaud(phand,br)
- int phand;
- int br;
-
- This routine will set the port described by phand to
- the specified baud rate. Note that any baud rate can be
- used, not just the normal ones. The maximum allowed by
- the port is about 50K. Normally, of course, you should
- stick to the standard baud rates for compatability with
- other programs.
-
- cmode(phand,par,bits,stopb)
- int phand, par, bits, stopb;
-
- This sets the mode of a port. parity is described by
- the par argument and can be one of ['n','e','o']. bits
- describes the number of bits in each byte transmitted
- (either 7 or 8) and stopb tells how many stop bits
- (either 1 or 2).
-
- cclose(phand)
- int phand;
-
- This routine turns the port off and unhooks the
- interrupt vector. It is important to do this before
- exiting your program so that a spurious interrupt does
- not occur.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- cputc(phand,c)
- int phand, c;
-
- outputs a character to the port described by phand. If
- the output buffer is full then the task making this
- call will be suspended until there is room for the
- character.
-
- int cgetc(phand)
- int phand;
-
- reads a character from the port described by phand. If
- there are no characters available then the task making
- this call will be suspended until one becomes
- available.
-
- int cpoll(phand)
-
- returns the number of characters available in the input
- buffer for the port described by phand. You can use
- this to keep from waiting for input if you don't want
- to use the multitasking facility.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- MiniTerminal program discussion
-
- The file "mini.c" contains an example of the use of this
- library to do a standard job in an elegant way. The main
- program of mini opens com1 and sets the port to 1200 baud.
- It then intercepts the keyboard interrupt and creates a new
- task (task1) and starts an infinite loop. The main program
- then becomes a receiver task which just gets a character
- from the port and puts it on the screen. Meanwhile, task1 is
- getting a character from the keyboard, checking whether or
- not it is the key designated to terminate the program (F1)
- and if not sending the character out the com port. When
- task1 tries to get a character from the keyboard it first
- checks to see if there is a character available, if not it
- waits for signal zero which is sent by kbsvc when the next
- keyboard interrupt happens. Likewise, when the main task
- tries to get a character from the port it will wait till one
- is available. The multitasking makes the program a lot
- easier to follow.
-
- But wait, you say! I could do the same thing without a
- multitasking kernel and all of that bruhaha. In that case
- you would check to see if a key was available, if so process
- it, then check to see if a com character was available, and
- if so process it, in a single loop. That works out ok for
- the simple case but think of what you would have to do to do
- the job of the routine escseq which interprets incomming
- ansi escape sequences. Remember, you don't want to hold up
- keyboard input while all the rest of the characters come in!
- At 300 baud that would be a noticable delay. You would have
- to keep track of what had been received already in an escape
- sequence and what the current state was. The multitasker
- takes a lot of the bother out of the job. You can just write
- the receiver routine as though no keyboard work had to be
- done at all.
-
- To compile and link mini.c do the following command:
-
- dlc mini.c xlib.lib
-
- Well, that about wraps it up. Remember, for just twenty
- bucks you get the source code, all four memory models (this
- is just the small model) and an unlimited license to use
- this nifty library in your own programs. Sorry, no ginsu
- knives.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-