Implement another pseudo operating system (scheduler) using goto and 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.

Compared to the previous implementation, In this implement, switch case can be used in source.

the whole source are listed:

#include <stc89c51.h>
#define MAXTASKS 3

//-------------pseudo operating system (scheduler)  use goto----begin---------------------------------------

//switch case can be used in this implement 


#define _SS(N) static unsigned char STATE=0; switch(STATE){ STATES##N;}
#define _EE    ; STATE=0; return 255;

#define WaitX(A,tickets)  do {STATE=A; return tickets ;} while(0); ST(A):

#define RunTask(TaskName,TaskID) do { if (timers[TaskID]==0) timers[TaskID]=TaskName(); }  while(0);
#define RunTaskA(TaskName,TaskID) { if (timers[TaskID]==0) {timers[TaskID]=TaskName(); continue;} }   //?°??μ?è???ó??è±£?¤?′DD

#define CallSubX(A,SubTaskName) do {unsigned char currdt; STATE=A; return 0; ST(A):  currdt=SubTaskName(); if(currdt!=255) return currdt;} while(0);
#define InitTasks() {unsigned char i; for(i=MAXTASKS;i>0 ;i--) timers[i-1]=0; }
#define UpdateTimers() {unsigned char i; for(i=MAXTASKS;i>0 ;i--){if((timers[i-1]!=0)&&(timers[i-1]!=255)) timers[i-1]--;}}

#define EXIT   do {STATE=0; return 255;} while(0);
#define RESTART  do {STATE=0; return 0;} while(0);

volatile unsigned char timers[MAXTASKS];

#define ST(A) ST##_##A
#define GO(A)  case A: goto ST(A);

#define STATES1  GO(1);
#define STATES2  GO(1);GO(2);
#define STATES3  GO(1);GO(2);GO(3);
#define STATES4  GO(1);GO(2);GO(3);GO(4);
#define STATES5  GO(1);GO(2);GO(3);GO(4);GO(5);
#define STATES6  GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);
#define STATES7  GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);
#define STATES8  GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);
#define STATES9  GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);
#define STATES10 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);
#define STATES11 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);GO(11);
#define STATES12 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);GO(11);GO(12);
#define STATES13 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);GO(11);GO(12);GO(13);
#define STATES14 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);GO(11);GO(12);GO(13);GO(14);
#define STATES15 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);GO(11);GO(12);GO(13);GO(14);GO(15);
#define STATES16 GO(1);GO(2);GO(3);GO(4);GO(5);GO(6);GO(7);GO(8);GO(9);GO(10);GO(11);GO(12);GO(13);GO(14);GO(15);GO(16);
//#define STATESXX ....you can define more 

#define SEM unsigned int 
#define InitSem(sem) sem=0;
#define WaitSem(A,sem) do{ sem=1; WaitX(A,0); if (sem>0) return 1;} while(0);
#define WaitSemX(A,sem,tickets)  do { sem=tickets+1; WaitX(A,0); if(sem>1){ sem--;  return 1;} } while(0);
#define SendSem(sem)  do {sem=0;} while(0);

//------------pseudo operating system (scheduler)  use goto end------------------------------------------


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

sbit LED0 = P2^5;

unsigned char task0(){
_SS(1)  //1 wait used in this task  _SS(1)
  while(1){
   WaitX(1,50);
   LED0=!LED0;   
  }
_EE
}

unsigned char  task1(){
_SS(1)  //1 wait used in this task  _SS(1)
  while(1){
   WaitX(1,100);
   LED1=!LED1;   
  }
_EE
}

unsigned char  task2(){
_SS(3)   //3 wait used in this task  _SS(3)
  while(1){
   WaitX(1,100);
   LED2=!LED2;   
   WaitX(2,100);
   LED2=!LED2;   
   WaitX(3,100);
   LED2=!LED2;   
  }
_EE
}

void InitT0()
{
        TMOD = 0x21;
        IE |= 0x82;  // 12t
        TL0=0Xff;
        TH0=0XDB;
        TR0 = 1;
}

void INTT0(void) interrupt 1 using 1
{
    TL0=0Xff;    //10ms ??
    TH0=0XDB;//b7;    

    UpdateTimers();

    RunTask(task0,0);//High-level tasks, executed in interrupts, can deprive low-level tasks。
}




void main()
{
        InitT0();
        InitTasks(); //?????,?????timers??
        while(1){
//           RunTask(task0,0);
           RunTaskA(task1,1);//??1?????2??????                   
           RunTaskA(task2,2);//??2????????                   
      }
}