please dont rip this site

Simple C18 Cooperative Multitasking

A simple cooperative multitasking system by Harold Hallikainen.

See "PIC 18C Microcontoller - Preemptive real-time multitasking kernel" /techref/microchip/18c/multitask-rtk-ba.htm for a more complex multutasker for the PIC18C. See "multitasking" /techref/method/multitask.htm for multitasking in general.


// main.c
// SIMPLE COOPERATIVE MULTITASKING SYSTEM
// Harold Hallikainen
// harold@hallikainen.org
// December 2006
// This is a test of a SIMPLE cooperative multitasker. For each task, the system keeps a copy of the
// stack pointer and a copy of the stack.
// Initialization -
// Each task starts with a call of InitTask(n) where n is the task number. The task follows the InitTask
// call with any other required initialization, then enters a loop. InitTask saves the return address into
// the task in the SavedStack array. It then pops the return address off the stack so we return to main()
// instead of the function that called InitTask(). This allows us to continue setting up other tasks in main().
// Running-
// After each task has been initialized, main calls StartMultiTask(). This loads the stack with the values
// stored for task 0 by InitTask(). 
// Task Switching-
// Whenever a task is waiting for something (typically input, perhaps waiting for an output device to be ready),
// the loop contains a call of NextTask(). NextTask saves the current stack, loads the stack for the next task,
// then returns into that function where IT had called NextTask. Note that this return may be several 
// function call levels down. It need not be in the original task loop, but, instead, in a function called
// by that loop. This is makes multitasking much simpler than use of state machines for each task and function
// within that task.
// Variables and Function Parameters
// If a particular function contains a NextTask call, local variables and parameters to the function MUST
// be static. This keeps them from being located on the software stack (as automatic variables would be).
// Automatic variables and function parameters are lost during a task switch. In addition, the software stack
// may undeflow or overflow if you do a task switch while automatic variables or parameters exist. However,
// functions that do NOT include a task switch may use automatic parameters and functions since these are
// destroyed before the NextTask is called.
 
#include <p18f8627.h>
#include "types.h"
 
#define MaxTask 3
 
// Function Prototypes
void InitTask(static uint8_t TaskNum); 	// Save return address for this function to continue,
				//   then throw it out, dropping to main()
void StartMultiTask(void); 		// loads stack with initial data for task 0, then returns to task 0.
void NextTask(void); 			// save current stack and load stack for next task
void task0(void);
void task1(void);
void task2(void);
void task3(void);
uint8_t Task3SubFunction(static uint8_t n); // testing a subfunction
uint8_t Task3subSub(uint8_t n);
 
#pragma udata MultiTask 		// generally requires more than 256 bytes or ram, so put in bigger section
union{
    uint24_t u24b; 			// access as 24 bit unsigned int
    uint8_t u8b[sizeof(uint24_t)]; 	// or array of bytes
}SavedStack[MaxTask+1][31]; 		// Each stack entry is 3 bytes and there are 31 of them in each stack.
// MaxTask is highest task number. Since they start at zero, dimension to MaxTask+1 
 
static uint8_t SavedStackPointer[MaxTask+1]; // stack pointer saved for a particular task
#pragma udata 			// let linker allocate rest of stuff
 
void main(void){
    task0(); 
    task1();
    task2();
    task3(); 			// init each task
    StartMultiTask(); 		// go run multitask
}
 
void InitTask(static uint8_t TaskNum){
// Call from within a task. Puts the Saves the return address in SavedStack[TaskNum][1] so a later call
// of NextTask will continue from this address. Uses static parameter to avoid use of parameter stack which
// would be messed up when we do a return to main instead of calling function.
    INTCONbits.GIEH=0; 		// disable high priority interrupts
    INTCONbits.GIEL=0; 		// and low priority interrupts while messing with stack
    SavedStackPointer[TaskNum]=STKPTR; 	// save the current stack pointer
    SavedStack[TaskNum][STKPTR & 0b11111].u24b=TOS; // save current tos, which is where this function should start
    _asm POP _endasm; 		// remove return address so we drop back to main()
    INTCONbits.GIEL=1; 		// interrupts ok now
    INTCONbits.GIEH=1;
} 
 
void StartMultiTask(void){
// loads stack with initial data for task 0, then returns to task 0.
    INTCONbits.GIEH=0; 		// disable high priority interrupts
    INTCONbits.GIEL=0; 		// and low priority interrupts while messing with stack
    STKPTR=0; 			// start with clear stack pointer
    while(STKPTR<=SavedStackPointer[0]){
        //TOS=SavedStack[0][STKPTR & 0b11111]; // restore stack value - use below code to avoid movff to tos
        WREG=SavedStack[0][STKPTR & 0b11111].u8b[0];
        TOSL=WREG;
        WREG=SavedStack[0][STKPTR & 0b11111].u8b[1];
        TOSH=WREG;
        WREG=SavedStack[0][STKPTR & 0b11111].u8b[2];
        TOSU=WREG;
        _asm PUSH _endasm; 		// and increment stack pointer
    }
    _asm POP _endasm; 		// get rid of extra stack pointer increment at end 
    INTCONbits.GIEL=1; 		// interrupts ok now
    INTCONbits.GIEH=1;
} 
 
 
void NextTask(void){
// save away the current stack, load the one for the next task, then exit
static uint8_t TaskNum=0; 
    INTCONbits.GIEH=0; 		// disable high priority interrupts
    INTCONbits.GIEL=0; 		// and low priority interrupts while messing with stack
    SavedStackPointer[TaskNum]=STKPTR; 	// save the current stack pointer
    while(STKPTR & 0b11111){ 		// while stuff still on the stack
        SavedStack[TaskNum][STKPTR & 0b11111].u24b=TOS; // save current tos
       _asm POP _endasm; 		// decrement the stack pointer
    }
    TaskNum++; 			// on to next task
    if(TaskNum>MaxTask)
    TaskNum=0; 			// roll over if past last
    while(STKPTR<=SavedStackPointer[TaskNum]){
        //TOS=SavedStack[TaskNum][STKPTR & 0b11111]; // restore stack value - use below code to avoid movff to tos
        WREG=SavedStack[TaskNum][STKPTR & 0b11111].u8b[0];
        TOSL=WREG;
        WREG=SavedStack[TaskNum][STKPTR & 0b11111].u8b[1];
        TOSH=WREG;
        WREG=SavedStack[TaskNum][STKPTR & 0b11111].u8b[2];
        TOSU=WREG;
        _asm PUSH _endasm; 		// and increment stack pointer
     }
    _asm POP _endasm; 		// get rid of extra stack pointer increment at end 
    INTCONbits.GIEL=1; 		// interrupts ok now
    INTCONbits.GIEH=1;
    } 
 
 
 
void task0(void){
static uint8_t n=0;
    InitTask(0); 			// set up return address for here
    while(1){ 			// task loop
        ClrWdt();
        n++;
        NextTask();
    } // end while
} // end function 
 
void task1(void){
static uint8_t n=0;
    InitTask(1); 			// set up return address for here
    while(1){ 			// task loop
        ClrWdt();
        n++;
        NextTask();
    } // end while
}
 
void task2(void){
static uint8_t n=0;
    InitTask(2); 			// set up return address for here
    while(1){ 			// task loop
        ClrWdt();
        n++;
        NextTask();
    } // end while
}
 
void task3(void){
static uint8_t n=0;
     InitTask(3); 			// set up return address for here
     while(1){ 			// task loop
          ClrWdt();
          n++;
          n=Task3SubFunction(n);
          ClrWdt();
     } // end while
}
 
uint8_t Task3SubFunction(static uint8_t n){
// testing a subfunction. Make parameters and local variables static on any functions that include NextTask.
     ClrWdt();
     n=3*n;
     NextTask();
     ClrWdt();
     n=Task3subSub(n);
     return(n);
}
 
uint8_t Task3subSub(uint8_t n){
// since this function does not call NextTask, we don't need to use statics
     uint8_t y=3;
     uint8_t z;
     z=n*y;
     return(z);
} 

See also:


file: /Techref/microchip/language/c/MultiTask.c.htm, 13KB, , updated: 2007/1/24 17:19, local time: 2017/12/16 03:54, owner: harold-hallikainen-,
TOP NEW HELP FIND: 
54.163.61.66:LOG IN

 ©2017 These pages are served without commercial sponsorship. (No popup ads, etc...).Bandwidth abuse increases hosting cost forcing sponsorship or shutdown. This server aggressively defends against automated copying for any reason including offline viewing, duplication, etc... Please respect this requirement and DO NOT RIP THIS SITE. Questions?
Please DO link to this page! Digg it! / MAKE! / 

<A HREF="http://www.piclist.com/techref/microchip/language/c/MultiTask.c.htm"> Simple C18 Cooperative Multitasking</A>

After you find an appropriate page, you are invited to your to this massmind site! (posts will be visible only to you before review) Just type in the box and press the Post button. (HTML welcomed, but not the <A tag: Instead, use the link box to link to another page. A tutorial is available Members can login to post directly, become page editors, and be credited for their posts.


Link? Put it here: 
if you want a response, please enter your email address: 
Attn spammers: All posts are reviewed before being made visible to anyone other than the poster.
Did you find what you needed?

  PICList 2017 contributors:
o List host: MIT, Site host massmind.org, Top posters @20171216 RussellMc, Van Horn, David, Sean Breheny, James Cameron, alan.b.pearce, IVP, Neil, Bob Blick, David C Brown, John Gardner,
* Page Editors: James Newton, David Cary, and YOU!
* Roman Black of Black Robotics donates from sales of Linistep stepper controller kits.
* Ashley Roll of Digital Nemesis donates from sales of RCL-1 RS232 to TTL converters.
* Monthly Subscribers: Gregg Rew. on-going support is MOST appreciated!
* Contributors: Richard Seriani, Sr.
 

Welcome to www.piclist.com!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  .