Implement a pseudo operating system (scheduler) using C macro definitions, this is not a real embedded operating system, it is a pseudo operating system, or a scheduler for MCU, it costs a few ram and rom, but can do a lot works for you and save your time and easy your software.

the whole source are listed:

#ifndef __OS_H
#define __OS_H
/****pseudo operating system (scheduler) start********************************************/
#define MAXTASKS 3          //define task count:1-255
#define BITS 16             //define bits width:8/16/32
#define SEM unsigned int    //signal macro

#if (BITS==8)
#define TASK unsigned char
#define TICKET_MAX 0xFF

#if (BITS==16)
#define TASK unsigned short

#if (BITS==32)
#define TASK unsigned long

volatile TASK timers[MAXTASKS];

//task start
#define _SS static unsigned char _lc=0; switch(_lc){default:

//task end
#define _EE ;}; _lc=0; return TICKET_MAX;

//wait X ticks
#define WaitX(tickets)  do { _lc=(__LINE__%255)+1; return (tickets) ;case (__LINE__%255)+1:;} while(0);

//wait conditon
#define WaitUntil(A)    do { while(!(A)) WaitX(1);} while(0);

//wait var ==value        A variable;VAL value
#define WAITUNTIL(A,VAL)  do { WaitX(1);} while((A)!=VAL);

//only used in task called by RunTask   wait condition
#define WaitUntilR(A)    do { while(!(A)) WaitX(0);} while(0);

//only used in task called by RunTask A variable;VAL value
#define WAITUNTILR(A,VAL)  do { WaitX(0);} while((A)!=VAL);

//Run a task
#define RunTask(TaskName,TaskID)  do { if (timers[TaskID]==0) { TASK d=TaskName(); while(timers[TaskID]!=d) timers[TaskID]=d;} }  while(0);

//Run task , make sure the pre tasks executue
#define RunTaskA(TaskName,TaskID) do { if (timers[TaskID]==0) {TASK d=TaskName(); while(timers[TaskID]!=d) timers[TaskID]=d;   continue;} }while(0);

//call sub task
#define CallSub(SubTaskName) do {TASK currdt; _lc=(__LINE__%255)+1; return 0; case (__LINE__%255)+1:  currdt=SubTaskName(); if(currdt!=TICKET_MAX) return currdt;} while(0);

//call sub task,  pass in a parameter, the parameters passed in need to be used before releasing the CPU调用子任务,传入一个参数,传入的参数需在释放CPU前使用
#define CallSub1(SubTaskName,p1) do {TASK currdt; _lc=(__LINE__%255)+1; return 0; case (__LINE__%255)+1:  currdt=SubTaskName(p1); if(currdt!=TICKET_MAX) return currdt;} while(0);

//Call the subtask, pass in two parameters, the parameters passed in need to be used before releasing the CPU
#define CallSub2(SubTaskName,p1,p2) do {TASK currdt; _lc=(__LINE__%255)+1; return 0; case (__LINE__%255)+1:  currdt=SubTaskName(p1,p2); if(currdt!=TICKET_MAX) return currdt;} while(0);

//init task scheduler
#define InitTasks() do {unsigned char i; for(i=MAXTASKS;i>0 ;i--) timers[i-1]=0; } while(0);

//update tasks
#define UpdateTimers() do{unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers[i-1]!=0)&&(timers[i-1]!=TICKET_MAX)) timers[i-1]--;}} while(0);

//Init signals
#define InitSem(sem) do{sem=0;}while(0);

//wait signal
#define WaitSem(sem) do{ sem=1; WaitX(0); if (sem>0) return 1;} while(0);

//send signal
#define SendSem(sem)  do {sem=0;} while(0);

//wait signal with timeout
#define WaitSemX(sem, tickets) do{sem=tickets+1;WaitX(0);if(sem>1){sem--;return 1;}}while (0);

/*****pseudo operating system (scheduler) start*******************************************************/

#include "OS.h"

sbit LED1 = P2^1;
sbit LED2 = P2^2;
sbit LED0 = P2^5;

//  Task 0 task definition starts with TASK
TASK task0(){
//  Task 1 task definition starts with TASK
TASK task1(){
//  Task 2 task definition starts with TASK
TASK task2(){
//  TIME0 Init
void InitT0()
    TMOD = 0x21;
    IE |= 0x82;  // 12t
    TR0 = 1;
//  TIM0 ISR
void INTT0(void) interrupt 1 using 1
    TL0=0Xff;           //10ms reload
    TH0=0XDB;           //b7;    
    UpdateTimers();     //update Tasks
    RunTask(task0,0);   //Task 0 has the right to execute execution on time, requiring: task0 consumes <0.5 tickets per execution
//  main loop
void main()
//      RunTask(task0,0);
        RunTaskA(task1,1);//Task 1 has a higher priority than task 2.                   
        RunTaskA(task2,2);//Task 2 has a low priority