Threading allows functions to execute concurrently. The example below shows two threads switching between running and sleeping. As the RTI ISR executes it takes the current process off the schedule (list of processes) and switches in the next process on the schedule. Once all processes have been removed from the schedule the “Scheduler” steps in and creates a new schedule.
Cooperative multitasking allows for threads to switch themselves out of processing during down time. Below is an example of this. If you find problems with the code please let me know with a comment.
typedef unsigned char u8; typedef unsigned short u16; typedef unsigned int u32; typedef unsigned int size_t; #define THREADMAX 16 #define STACKSIZE 0x200 void* threads[THREADMAX]; unsigned int threadcount; void* _stackpointer; struct sStack { //GCC Stack Vars u16 xy; //Soft Register XY u16 z; //Soft Register Z u16 tmp; //Register Backup Pointer u16 frame; //Frame Pointer //HC12 Stack Vars u8 CCR; //Condition Code Register u8 A; //Accumulator A u8 B; //Accumulator B u16 X; //Index Register X u16 Y; //Index Register Y u16 PC; //Program Counter (Starts at functions address) u16 RS; //Return Service }; void Spawn(void* function, void* callback) { void* newstack = Allocate(STACKSIZE); sStack* sp = (sStack*)((u16)newstack + (u16)STACKSIZE - sizeof(sStack)); sp->xy = 0x0000; sp->z = 0x0000; sp->tmp = 0x0000; sp->frame = 0x0000; sp->CCR = 0xC0; sp->A = 0x00; sp->B = 0x00; sp->X = 0x0000; sp->Y = 0x0000; sp->PC = (u16)function; sp->RS = (u16)callback; if( threadcount < THREADMAX ) { threads[threadcount++] = sp; } } // void __attribute__((interrupt)) Switch_RTI_ISR(void) { asm volatile("sei"); //Set interrupt mask //Save off the stack pointer asm volatile("LDX #_stackpointer"); asm volatile("STS 0, X"); threads[current] = _stackpointer; //Schedule the next thread current += 1; current %= threadcount; //Load the next stack pointer _stackpointer = threads[current]; asm volatile("LDX #_stackpointer"); asm volatile("LDS 0, X"); CRGFLG |= 0x80; //Real Time Interrupt Flag asm volatile("cli"); //Enable Interrupts } //More of a bootloader that sets up variables void Main(void) { //Disable Interrupts asm volatile("sei"); //Spawn Threads threadcount = 0; //Init Spawn((void*)Thread1, 0x4000); Spawn((void*)Thread2, 0x4000); //Setup Thread Swap *(void(**)())0x3FF0 = Swith_RTI_ISR; asm volatile("cli"); while(1) { asm volatile("swi"); } } void Thread1(void) while(1) { Print("Thread 1"); Pause(500); asm volatile("swi"); } } void Thread2(void) { while(1) { Print("Thread 2"); Pause(500); asm volatile("swi"); } } |