1) Super portability, has nothing to do with the CPU, almost any CPU that supports C language programming can be used! (This article only takes 51 single-chip microcomputers as an example, but it can be transplanted arbitrarily.)
2) It is small, the principle is very simple, and you can understand it at a glance.
3) It can be said that it saves RAM and ROM to the extreme.
4) Take the essence of protothread and fuse the timer with the state machine and pseudo-thread syntax into one framework. The task function can be written in two ways.
5) Timer-based triggering, high scheduling efficiency, minimizing invalid code running time.

 

#include <stc89c51.h>
/ **** Little Scheduler starts ************************************ ****** /
#define MAXTASKS 3
volatile unsigned char timers [MAXTASKS];
#define _SS static unsigned char _lc = 0; switch (_lc) {default:
#define _EE;}; _lc = 0; return 255;
#define WaitX (tickets) do (_lc = (__ LINE __ + ((__ LINE __% 256) == 0))% 256; return tickets;) while (0); case (__LINE __% 256) == 0) )% 256:

#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;}} // The preceding task is guaranteed to execute first

#define CallSub (SubTaskName) do (unsigned char currdt; _lc = (__ LINE __ + ((__ LINE __% 256) == 0))% 256; return 0; case (__LINE __ + ((__ LINE __% 256) == 0))% 256: 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 SEM unsigned int
// Initial semaphore
#define InitSem (sem) sem = 0;
// wait for semaphore
#define WaitSem (sem) do {sem = 1; WaitX (0); if (sem> 0) return 1;} while (0);
// Wait for semaphore or timer overflow, timer tickets are up to 0xFFFE
#define WaitSemX (sem, tickets) do {sem = tickets + 1; WaitX (0); if (sem> 1) {sem--; return 1;}} while (0);
// Send semaphore
#define SendSem (sem) do {sem = 0;} while (0);

/ ***** End of Little Scheduler *********************************** **************** /

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

sbit LED0 = P2 ^ 5;

unsigned char task0 () {
_SS
while (1) {
WaitX (50);
LED0 =! LED0;
}
_EE
}

unsigned char task1 () {
_SS
while (1) {
WaitX (100);
LED1 =! LED1;
}
_EE
}

unsigned char task2 () {
_SS
while (1) {
WaitX (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 reload
TH0 = 0XDB; // b7;

UpdateTimers ();

RunTask (task0,0); // Task 0 has the right to get the execution right on time. Requirements: task0 consumes less than 0.5 tickets per execution
}

void main ()
{
InitT0 ();
InitTasks (); // Initialize tasks, which is actually clearing timers
while (1) {
// RunTask (task0,0);
RunTaskA (task1,1); // Task 1 has higher run permissions than Task 2
RunTaskA (task2,2); // Task 2 has low run permissions
}
}