/* File **********THREAD3.C*********** Statically allocated thread example with blocking 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 Jonathan W. Valvano There are 2 producers and two consumers. The data is a simple numerical sequence 1,2,3,4,...to 50. The producers will create data (the sequence 1,2,3,...) and transmit it to the consumers via the FIFO queue (files BFIFO.H and BFIFO.C). All I/O is done explicitly in this system (files SERIAL.H and SERIAL.C) so that you can see all of the code. There is some problem in BUFFALO that sometimes will crash this system, so don't use putchar, getchar, scanf, or printf. No external hardware is required, Ports B,C contain debugging information, so look at them while the program is running. The "50" in CreateData can be increased to make the program execute longer. Because of the static linked list, this program must be reloaded to be executed a second time. */ #include #include "vector.h" #include "SERIAL.H" #include "BLOCK.H" #include "BFIFO.H" unsigned int ElapsedTime; // in msec #define timeslice 20000 #define stacksize 100 sema4Type DisplayFree; /* Semaphore used to share Display */ struct TCB { struct TCB *Next; /* Link to Next TCB */ unsigned char *SP; /* 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){ // will generate the data stream 1,2,3,4,...,50 asm(" sei"); // read modify write nonreentrant code if((last)==50){ OutString("Elapsed time"); OutUDec(ElapsedTime); OutString(" ms\n"); asm(" swi");} // go to BUFFALO last++; asm(" cli"); return(last);} void pseudo(unsigned int loopcnt){ unsigned int i,j; for(i=0;iId; while(1) { PORTC=4; x=CreateData(); pseudo(x); Message("The data Put by producer",myId,x); Put(x); } } void Consumer(void){ unsigned int x; unsigned int myId; myId=RunPt->Id; while(1) { PORTC=8; x=Get(); pseudo(x); Message("The data Get by consumer",myId,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 */ #pragma interrupt_handler ThreadSwitch() void ThreadSwitch(void){ asm(" ldx _RunPt\n" " sts 2,x"); RunPt=RunPt->Next; PORTB=RunPt->Id; /* PortB shows which thread is running */ asm(" ldx _RunPt\n" " lds 2,x"); TOC3=TCNT+timeslice; /* Thread runs for 10 ms */ TFLG1=0x20; } /* acknowledge by clearing OC3F */ #pragma interrupt_handler ClockHandler() void ClockHandler(void){ if((++ElapsedTime)==0)ElapsedTime=65535; TOC4=TOC4+2000; /* Thread runs every 1 ms */ TFLG1=0x10; } /* acknowledge by clearing OC4F */ void main(void){ DDRC=0xFF; last=0; ElapsedTime=0; DisplayFree.value=1; DisplayFree.BlockPt=null; OutString("Starting fixed allocation blocking semaphore system\n"); RunPt=&sys[0]; /* Specify first thread to run */ asm(" sei"); InitFifo(); TOC3vector=&ThreadSwitch; TOC4vector=&ClockHandler; TFLG1 = 0x30; /* Clear OC3F, OC4F */ TMSK1 = 0x30; /* Arm TOC3, TOC4 */ TOC3=TCNT+timeslice; // time slice for first thread TOC4=TCNT+2000; PORTB=RunPt->Id; asm(" ldx _RunPt\n" " lds 2,x\n" " cli\n" " rti");} /* Launch First Thread */ #include "SERIAL.C" #include "BLOCK.C" #include "BFIFO.C"