📄 chap4.c
字号:
// Chapter 4 6812 C programs// Jonathan W. Valvano// This software accompanies the book,// Embedded Microcomputer Systems: Real Time Interfacing// published by Brooks Cole, 1999// Program 4.3. This C function is nonreentrant because of the read-modify-write access to a global. unsigned int Money; /* bank balance implemented as a global *//* add 100 dollars */void more(void){ Money += 100;}// Program 4.5. This C function is nonreentrant because of the write-read access to a global. int temp; /* global temporary *//* calculate x+2*d */int mac(int x, int d){ temp = x+2*d; /* write to a global variable */ return (temp);} /* read from global */// Program 4.7. This C function is nonreentrant because of the multi-step write access to a global. int info[2]; /* 32-bit global */void set(int x, int y){ info[0]=x; info[1]=y;}// Program 4.11. This C function is reentrant because it disables interrupts during the critical section. int Empty; /* -1 means empty, 0 means it contains something */int Message; /* data to be communicated */int SEND(int data){ int OK;char SaveSP; asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical */ OK=0; /* Assume it is not OK */ if(Empty){ Message=data; Empty=0; /* signify it is now contains a message*/ OK=-1;} /* Successfull */ asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(OK);}// Program 4.14. Two pointer implementation of a FIFO. #define FifoSize 10 /* Number of 8 bit data in the Fifo less one */char *PutPt; /* Pointer of where to put next */char *GetPt; /* Pointer of where to get next /* FIFO is empty if PutPt=GetPt */ /* FIFO is full if PutPt+1=GetPt (with wrap) */char Fifo[FifoSize]; /* The statically allocated fifo data */void InitFifo(void) { char SaveSP; asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical */ PutPt=GetPt=&Fifo[0]; /* Empty when PutPt=GetPt */ asm(" ldaa %SaveSP\n tap"); /* end critical section */}int PutFifo (char data) { char *Ppt; /* Temporary put pointer */char SaveSP; asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical */ Ppt=PutPt; /* Copy of put pointer */ *(Ppt++)=data; /* Try to put data into fifo */ if (Ppt == &Fifo[FifoSize]) Ppt = &Fifo[0]; /* Wrap */ if (Ppt == GetPt ) { asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(0);} /* Failed, fifo was full */ else{ PutPt=Ppt; asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(-1); /* Successful */ }}int GetFifo (char *datapt) { char SaveSP; if (PutPt == GetPt ) { return(0);} /* Empty if PutPt=GetPt */ else{ asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical */ *datapt=*(GetPt++); if (GetPt == &Fifo[FifoSize]) GetPt = &Fifo[0]; asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(-1); }}// Program 4.18. C language routines to implement a two pointer with counter FIFO. /* Pointer,counter implementation of the FIFO */#define FifoSize 10 /* Number of 8 bit data in the Fifo */char *PutPt; /* Pointer of where to put next */char *GetPt; /* Pointer of where to get next */unsigned char Size; /* Number of elements currently in the FIFO */ /* FIFO is empty if Size=0 */ /* FIFO is full if Size=FifoSize */char Fifo[FifoSize]; /* The statically allocated fifo data */void InitFifo(void) { char SaveSP; asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical*/ PutPt=GetPt=&Fifo[0]; /* Empty when Size==0 */ Size=0; asm(" ldaa %SaveSP\n tap"); /* end critical section */}int PutFifo (char data) { char SaveSP; if (Size == FifoSize ) { return(0);} /* Failed, fifo was full */ else{ asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical*/ Size++; *(PutPt++)=data; /* put data into fifo */ if (PutPt == &Fifo[FifoSize]) PutPt = &Fifo[0]; /* Wrap */ asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(-1); /* Successful */ }}int GetFifo (char *datapt) { char SaveSP; if (Size == 0 ){ return(0);} /* Empty if Size=0 */ else{ asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical*/ *datapt=*(GetPt++); Size--; if (GetPt == &Fifo[FifoSize]) GetPt = &Fifo[0]; asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(-1); }}// Program 4.22. C implementation of a two index with counter FIFO. /* Index,counter implementation of the FIFO */#define FifoSize 10 /* Number of 8 bit data in the Fifo */unsigned char PutI; /* Index of where to put next */unsigned char GetI; /* Index of where to get next */unsigned char Size; /* Number of elements currently in the FIFO */ /* FIFO is empty if Size=0 */ /* FIFO is full if Size=FifoSize */char Fifo[FifoSize]; /* The statically allocated fifo data */void InitFifo(void) {char SaveSP; asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical*/ PutI=GetI=Size=0; /* Empty when Size==0 */ asm(" ldaa %SaveSP\n tap"); /* end critical section */}int PutFifo (char data) { char SaveSP; if (Size == FifoSize ) return(0); /* Failed, fifo was full */ else{ asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical*/ Size++; Fifo[PutI++]=data; /* put data into fifo */ if (PutI == FifoSize) PutI = 0; /* Wrap */ asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(-1); /* Successful */ }}int GetFifo (char *datapt) { char SaveSP; if (Size == 0 ) return(0); /* Empty if Size=0 */ else{ asm(" tpa\n staa %SaveSP\n sei"); /* make atomic, entering critical*/ *datapt=Fifo[GetI++]; Size--; if (GetI == FifoSize) GetI = 0; asm(" ldaa %SaveSP\n tap"); /* end critical section */ return(-1); }}// Program 4.26. ICC12 C code to set interrupt vectors for the 6812. extern void _start(); /* entry point in crt12.s */extern void SCIhandler();extern void TC4handler();extern void TOFhandler();#define DUMMY_ENTRY (void (*)())0xF000#pragma abs_address:0xffcevoid (*interrupt_vectors[])() = { DUMMY_ENTRY, /* ffce 812 KeyWakeUpH */ DUMMY_ENTRY, /* ffd0 912 BDLC, 812 KeyWakeUpJ */ DUMMY_ENTRY, /* ffd2 ATD */ DUMMY_ENTRY, /* ffd4 812 SCI1 */ SCIhandler, /* ffd6 SCI, 812 SCI0 */ DUMMY_ENTRY, /* ffd8 SPI */ DUMMY_ENTRY, /* ffda PAIE */ DUMMY_ENTRY, /* ffdc PAO */ TOFhandler, /* ffde TOF */ DUMMY_ENTRY, /* ffe0 TC7 */ DUMMY_ENTRY, /* ffe2 TC6 */ DUMMY_ENTRY, /* ffe4 TC5 */ TC4handler, /* ffe6 TC4 */ DUMMY_ENTRY, /* ffe8 TC3 */ DUMMY_ENTRY, /* ffea TC2 */ DUMMY_ENTRY, /* ffec TC1 */ DUMMY_ENTRY, /* ffee TC0 */ DUMMY_ENTRY, /* fff0 RTI */ DUMMY_ENTRY, /* fff2 IRQ, 812 KeyWakeUpD*/ DUMMY_ENTRY, /* fff4 XIRQ */ DUMMY_ENTRY, /* fff6 SWI */ DUMMY_ENTRY, /* fff8 ILLOP */ DUMMY_ENTRY, /* fffa COP */ DUMMY_ENTRY, /* fffc CLM */ _start /* fffe RESET, entry point into ICC12 */ };#pragma end_abs_address// Program 4.30. Interrupting keyboard software. // MC68HC812A4// PJ6-PJ0 inputs = keyboard DATA// PJ7=STROBE interrupt on risevoid Init(void){ asm(" sei"); DDRJ=0x00; // PJ6-0 DATA KPOLJ=0x80; // rise on PJ7 KWIEJ=0x80; // arm PJ7 KWIFJ=0x80; // clear flag7 InitFifo();asm(" cli");}#pragma interrupt_handler ExtHan()void ExtHan(void){ if((KWIFJ&0x80)==0)asm(" swi"); KWIFJ=0x80; // clear flag PutFifo(PORTJ&0x7F);}// Program 4.34. C language software interrupt for the printer. // MC68HC812A4// PH6-PH0 outputs = printer DATA// PJ1=READY interrupt on rise// PJ0=START pulse outunsigned char OK; // 0=busy, 1=doneunsigned char Line[20]; //ASCII dataunsigned char *Pt; // pointer to linevoid Fill(unsigned char *p){ Pt=&Line[0]; while((*Pt++)=(*p++)); // copy Pt=&Line[0]; // initialize pointer OK=0;}unsigned char Get(void){ return(*Pt++);}void Out(unsigned char data){ PORTJ=0; // START=0 PORTH=data; // write DATA PORTJ=1;} // START=1void Init(unsigned char *thePt){ asm(" sei"); // make atomic Fill(thePt); // copy data into global DDRH=0xFF; // PH6-0 output DATA DDRJ=0x01; // PJ0=START output KPOLJ=0x02; // rise on PJ1 KWIEJ=0x02; // arm PJ1 KWIFJ=0x02; // clear flag1 Out(Get()); // start firstasm(" cli");}#pragma interrupt_handler ExtHan()void ExtHan(void){ if((KWIFJ&0x02)==0)asm(" swi"); KWIFJ=0x02; // clear flag1 if(data=Get()) Out(data); // start next else{ KWIEJ=0x00; // disarm OK=1;}} // line complete // Program 4.36. C language software for the XIRQ interrupt. /* Power System interface XIRQ requested on a rise of TooLow PB0, negative logic pulse, will acknowledge XIRQ PB1=1 will activate backup power */#pragma interrupt_handler PowerLow()void PowerLow(void){ PORTB=2; PORTB=3; } /* Ack, turn on backup power */void Ritual(void){ DDRB=0xFF; // Port B outputs (6812 only) PORTB=0; PORTB=1; // Make XIRQ=1 asm(" ldaa #0x10\n" " tap");}// Program 4.42. C language implementation of interrupt polling on the 6812 using linked lists. const struct Node{ unsigned char Mask; /* And Mask */ void (*Handler)(void); /* Handler for this task */ const struct Node *NextPt; /* Link to Next Node */};unsigned char Counter2,Counter1,Counter0;void PJ2Han(void){ // regular functions that return (rts) when done KWIFJ=0x04; // acknowledge Counter2++;}void PJ1Han(void){ // regular functions that return (rts) when done KWIFJ=0x02; // acknowledge Counter1++;}void PJ0Han(void){ // regular functions that return (rts) when done KWIFJ=0x01; // acknowledge Counter0++;}typedef const struct Node NodeType;typedef NodeType * NodePtr;NodeType sys[3]={ {0x04, PJ2Han, &sys[1]}, {0x02, PJ1Han, &sys[2]}, {0x01, PJ0Han, 0 } };#pragma interrupt_handler IRQHan()void IRQHan(void){ NodePtr Pt; unsigned char Status; Pt=&sys[0]; while(Pt){ // executes device handlers for all requests if(KWIFJ&(Pt->Mask)){ (*Pt->Handler)();} /* Execute handler */ Pt=Pt->NextPt; } } // returns after all devices have been polledvoid main(void){ while(1);} // Program 4.44. C language implementation of round robin polling on the 6812. NodeType sys[3]={ {0x04, PJ2Han, &sys[1]}, {0x02, PJ1Han, &sys[2]}, {0x01, PJ0Han, &sys[0]} };#pragma interrupt_handler IRQHan()NodePtr Pt=&sys[0]; // points to the one that got polled first at last interruptvoid IRQHan(void){ unsigned char Counter,Status; Counter=3; // quit after three devices checked Pt=Pt->NextPt; // rotates ABC BCA CAB polling orders while(Counter--){ if(KWIFJ&(Pt->Mask)){ (*Pt->Handler)();} /* Execute handler */ Pt=Pt->NextPt; } } // returns after all devices have been polled// Program 4.49. 6812 C language implementation of a periodic interrupt using real time interrupt. // Real Time Interrupt example 4.14.2 unsigned int Time;#pragma interrupt_handler RTIHan()void RTIHan(void){ if(RTIFLG!=0x80) asm(" swi"); // Illegal interrupt RTIFLG=0x80; // Acknowledge by clearing RTIF Time++;}void Ritual(void){ asm(" sei"); // Make ritual atomic RTICTL=0x86; // Arm, Set RTR to 6, 30.517Hz Time=0; // Initialize global data structures asm(" cli");}void main(void){ unsigned int t; Ritual(); for(t=0;t<10;) if (Time>=61*t){ printf("t= %d seconds\n", t); t++;} asm(" sei"); }// Program 4.51. 6812 C language implementation of a periodic interrupt using timer overflow. // TOF Interrupt example unsigned int Time;#pragma interrupt_handler TOFHan()void TOFHan(void){ if(TFLG2!=0x80) asm(" swi"); // Illegal interrupt TFLG2=0x80; // Acknowledge by clearing TOF Time++; }void Ritual(void){ asm(" sei"); // Make ritual atomic TMSK2=0xB2 ; // Arm, Set PR to 010, 30.517Hz TSCR=0x80; // enable counter Time=0; // Initialize global data structures asm(" cli");}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -