/* File **********THREAD.C*********** Simulator example for the MC68HC11EVB This example accompanies the book "Embedded Microcomputer Systems: Real Time Interfacing", Brooks-Cole, copyright (c) 2000, Jonathan W. Valvano 7/6/99 Interface between the TExaS simulator running a MC68HC11 EVB with ICC11 freeware compiler TExaS Copyright 1999 by Jonathan W. Valvano for more information about ICC11 see http://www.imagecraft.com You may use this file without restrictions Statically allocated thread example with spin lock semaphores PortB bits 0,1,2,3 specify which thread is running PortC bit program 0 Put 1 Get 2 Producer 3 Consumer 4 Wait 5 Signal */ #include "HC11.h" #include "SCI11a.h" #include "SPIN.H" #include "SFIFO.H" /* global variables */ unsigned int ElapsedTime; /* in timeslices */ int DisplayFree; /* Semaphore used to share Display */ #define timeslice 1000 #define stacksize 75 /* stacksize must be odd */ struct TCB { struct TCB *Next; /* Link to Next TCB */ unsigned char *Spt; /* Stack Pointer */ unsigned char Id; /* 1,2 or 4 */ unsigned char MoreStack[stacksize-9]; /* additional stack */ unsigned char CCR; /* Initial CCR */ unsigned char RegB; /* Initial RegB */ unsigned char RegA; /* Initial RegA */ unsigned int RegX; /* Initial RegX */ unsigned int RegY; /* Initial RegY */ void (*PC)(void); /* Initial Program Counter */ }; typedef struct TCB TCBType; typedef TCBType * TCBPtr; TCBPtr RunPt; /* Pointer to thread currently running */ unsigned int last; unsigned int CreateData(void){ unsigned int i; /* will generate the data stream 1,2,3,4,...,99 */ asm(" sei"); /* read modify write nonreentrant code */ if((last++)==100){ OutString("done"); OutChar(13); asm(" stop");} /* halt execution */ asm(" cli"); return(last);} void pseudo(unsigned int loopcnt){ unsigned int i; for(i=0;iId; while(1) { PORTC=4; x=CreateData(); pseudo(x); Message(myId," puts ",x); Put(x); } } void Consumer(void){ unsigned int x; unsigned int myId; myId=RunPt->Id; while(1) { PORTC=8; x=Get(); pseudo(x); Message(myId," gets ",x); }} TCBType sys[4]={ { &sys[1], /* Pointer to Next */ &sys[0].MoreStack[stacksize-10], /* Initial SP */ 1, /* Id */ { 0}, 0x40,0,0,0,0, /* CCR,B,A,X,Y */ Producer, }, /* Initial PC */ { &sys[2], /* Pointer to Next */ &sys[1].MoreStack[stacksize-10], /* Initial SP */ 2, /* Id */ { 0}, 0x40,0,0,0,0, /* CCR,B,A,X,Y */ Producer, }, /* Initial PC */ { &sys[3], /* Pointer to Next */ &sys[2].MoreStack[stacksize-10], /* Initial SP */ 4, /* Id */ { 0}, 0x40,0,0,0,0, /* CCR,B,A,X,Y */ Consumer, }, /* Initial PC */ { &sys[0], /* Pointer to Next */ &sys[3].MoreStack[stacksize-10], /* Initial SP */ 8, /* Id */ { 0}, 0x40,0,0,0,0, /* CCR,B,A,X,Y */ Consumer, }}; /* Initial PC */ void IncTime(void){ if((ElapsedTime++)==0) ElapsedTime=65535; } void ThreadSwitch(void){ /* suspend current tread */ asm(" ldx _RunPt\n" " sts 2,x"); IncTime(); RunPt=RunPt->Next; /* find next thread to watch */ PORTB=RunPt->Id; /* PortB shows which thread is running */ asm(" ldx _RunPt\n" " lds 2,x"); TOC3=TCNT+timeslice; /* Thread runs for fixed amount of time */ TFLG1=0x20; /* acknowledge by clearing OC3F */ asm(" rti"); } void main(void){ InitSCI(); DDRC=0xFF; DisplayFree=1; last=0; ElapsedTime=0; OutString("Fixed allocation spinlock semaphore system"); OutChar(CR); RunPt=&sys[0]; /* Specify first thread to run */ asm(" sei"); InitFifo(); TFLG1 = 0x20; /* Clear OC3F */ TMSK1 = 0x20; /* Arm TOC3 */ TOC3=TCNT+timeslice; /* time slice for first thread */ PORTB=RunPt->Id; asm(" ldx _RunPt\n" " lds 2,x\n" " cli\n" " rti");} /* Launch First Thread */ #include "SCI11a.C" #include "SPIN.C" #include "SFIFO.C" void resetVectors(void){ /* not really a function, but this must be last */ asm(" org $FFD6"); asm(" FDB _SciHandler"); asm(" org $FFE4"); asm(" FDB _ThreadSwitch"); asm(" org $FFFE"); asm(" FDB __start"); asm(" org $FC00"); /* puts rts in a harmless place */ /* string constants also placed here */ /* the value FC00 means you can have up to 1000 characters of strings */ }