📄 pid.c
字号:
/* * File: pid.c * * uC/OS Real-time multitasking kernel for the ARM processor. * * PID board specific functions. * Created by Marco Graziano (marcog@crl.com). * */#include "ucos.h" #include "pid.h" #include "osdefs.h" #pragma no_check_stack#pragma no_optimise_crossjump#pragma no_optimise_multiple_loads#pragma no_optimise_cse/* * * Functions defined in this module. * */void PIDInit(void); /* called by locore startup code */static int DispatchIRQ(void); /* called by low-level IRQ trap handler */void IRQEnable(int);void IRQDisable(int);void IRQReset(int);PFV IRQInstall(int, PFV);static void DispatchFIQ(void); /* called by low-level FIQ trap handler */void FIQEnable(int);void FIQDisable(int);PFV FIQInstall(int, PFV);static void DispatchSWI(int); /* called by low-level SWI trap handler */PFV SWIInstall(int, PFV);void PutByte(byte);byte GetByte(void);void SetLED(uint);/* interrupt registers pointer */static struct INTC *INTCReg = (struct INTC *)INTCREGS;/* 16C551 parallel port registers pointer */static struct PARP *PARPReg = (struct PARP *)PARPREGS;/* 16C551 UART registers pointer */static struct UART *UARTReg = (struct UART *)UARTREGS;/* high-level IRQ handlers */static PFV IRQVector[MAXIRQNUM];/* high-level FIQ handlers */static PFV FIQVector[MAXFIQNUM];/* high-level SWI handlers */static PFV SWIVector[MAXSWINUM];/* INTC masks */static uint SavedIRQMask;static uint SavedFIQMask;/* * Reset the serial port in the 16C551 controller. */ voidResetPort(void){ /* ---- initialize 16C551 ------------------------------------------ */ UARTReg->Reg2.IER = 0x0; /* disable interrupts */ UARTReg->LCR = 0x80; /* enable divisor latch access */ UARTReg->Reg1.DLL = 12; /* configure divisor latch 9600 bauds */ UARTReg->Reg2.DLM = 0; UARTReg->LCR = 0x03; /* disable divisor latch access */ /* configure 8 bit data */ UARTReg->Reg3.FCR = 0; /* disable FIFO */ UARTReg->MCR = 0x0B; /* set modem control register */ /* assert RTS, DTR, interrupt enable */ UARTReg->Reg2.IER = 0x5; /* enable receive interrupt */}/* * Initialize the PID board and PID support global data. */voidPIDInit(void){ int i; /* ---- initialize interrupt controller ---------------------------- */ INTCReg->IRQMask = 0x80; /* disable interrupts in INTC */ INTCReg->FIQMask = 0x80; SavedIRQMask = SavedFIQMask = 0x80; /* ---- initialize 16C551 ------------------------------------------ */ ResetPort(); /* ---- soft vectors ---------------------------------------------- */ for (i = 0; i < MAXIRQNUM; i++) IRQVector[i] = (PFV)0; for (i = 0; i < MAXFIQNUM; i++) FIQVector[i] = (PFV)0; for (i = 0; i < MAXSWINUM; i++) SWIVector[i] = (PFV)0; /* ---- install new trap handlers -------------------------------- */ NewIRQ(DispatchIRQ); NewFIQ(DispatchFIQ); NewSWI((PFV)DispatchSWI); } /* PIDInit *//* * Set and reset PID LEDs. * The general purpose register on the 16C551 parallel port is used to * set and reset LEDs. * * * | bit3 | bit2 | bit1 | bit0 | * --------------------------- * | led3 | led2 | led1 | led0 | * */voidSetLED(uint Conf){ Conf = (Conf ^ 0xF) << 4; /* complement the configuration and */ /* shift left the LS nibble*/ PARPReg->GPR = Conf; } /* SetLED *//* * IRQ interrupt numbers: * * 0 - serial port * 1 - timer * 2 - parallel port * 3 - expansion slot * 4 - expansion slot * 5 - expansion slot * 6 - expansion slot * 7 - panic (button sw1) *//* * Interrupt service routine dispatcher. * * This is the IRQ handler called when an IRQ trap is taken. */static intDispatchIRQ(void){ extern uint OSIntNesting; /* defined in os.c */ extern void rplev(void); /* defined in subr.s */ extern int OSIntExit(void); /* defined in os.c */ uint Mask = 0x0080; uint Status; int IRQNum = 7; /* increment nesting counter */ OSIntNesting++; Status = INTCReg->IRQ.Status; while (IRQNum >= 0) { if (Status & Mask) { /* clear interrupt to allow nesting */ INTCReg->IRQ.Reset = (1 << IRQNum); /* restore processor level before interrupt occurred */ rplev(); /* re-enable interrupts if needed */ /* call registered interrupt handler */ if (IRQVector[IRQNum]) (*(IRQVector[IRQNum]))(); else ; /* spurious interrupt */ break; } Mask = Mask >> 1; IRQNum--; } /* call exit routine - return TRUE if a context switch is needed */ return(OSIntExit()); } /* DispatchIRQ */ /* * Enable interrupt request. * * int IRQNum - interrupt request number */voidIRQEnable(int IRQNum){ uint Mask; /* Get the old INTC mask */ Mask = SavedIRQMask; /* Set new INTC mask enabling the new IRQ */ Mask = (Mask | (1 << IRQNum)) & 0x7F; INTCReg->IRQMask = Mask; /* this register is write only */ /* Save new value in the workspace */ SavedIRQMask = Mask;} /* IRQEnable *//* * Disable interrupt request. * * int IRQNum - interrupt request number */void IRQDisable(int IRQNum){ uint Mask; /* Get the old INTC mask */ Mask = SavedIRQMask; /* Set new INTC mask disabling the IRQ */ Mask = (Mask & ~(1 << IRQNum)) & 0x7F; INTCReg->IRQMask = Mask; /* Save the new value */ SavedIRQMask = Mask;} /* IRQDisable */ /* * Reset interrupt bit in the INTC. * * int IRQNum - interrupt number */voidIRQReset(int IRQNum){ /* Writing 1 will reset interrupt bit */ INTCReg->IRQ.Reset = (1 << IRQNum);} /* IRQReset */ /* * Install and enable a new Interrupt Service Routine. * * int IRQNum - interrupt request number * PFV ISRFun - new interrupt handler * * Return: * The old interrupt service routine address. */PFVIRQInstall(int IRQNum, PFV ISRFun){ PFV OldISR; /* Sanity check */ if (IRQNum < 0 || MAXIRQNUM < IRQNum) return((PFV)0); /* Get old ISR function */ OldISR = IRQVector[IRQNum]; /* Replace with new ISR function */ IRQVector[IRQNum] = ISRFun; /* Enable the interrupt */ IRQEnable(IRQNum); return(OldISR);} /* IRQInstall *//* * FIQ interrupt numbers: * * 0 - serial port receive pseudo DMA * 1 - serial port transmit pseudo DMA * 2 - expansion slot * 3 - logic analyzer port * 4 - expansion slot pseudo DMA * 5 - expansion slot pseudo DMA * 6 - expansion slot pseudo DMA * 7 - expansion slot pseudo DMA *//* * Fast Interrupt service routine dispatcher. * * This is the FIQ trap handler called when an FIQ is detected. */static voidDispatchFIQ(void){ uint Mask = 0x0080; uint Status; int FIQNum = 7; Status = INTCReg->FIQStatus; while (FIQNum >= 0) { if (Status & Mask) { /* restore processor level before interrupt */ /* call interrupt handler */ if (FIQVector[FIQNum]) (*(FIQVector[FIQNum]))(); else ; /* spurious interrupt */ } Mask = Mask >> 1; FIQNum--; }} /* DispatchFIQ */ /* * Enable fast interrupt request. * * int FIQNum - interrupt request number */voidFIQEnable(int FIQNum){ uint Mask; /* Get the old INTC mask */ Mask = SavedFIQMask; /* Set new INTC mask enabling the new FIQ */ Mask = (Mask | (1 << FIQNum)) & 0x7F; INTCReg->FIQMask = Mask; /* this register is write only */ /* Save new value in the workspace */ SavedFIQMask = Mask;} /* FIQEnable *//* * Disable fast interrupt request. * * int FIQNum - interrupt request number */void FIQDisable(int FIQNum){ uint Mask; /* Get the old INTC mask */ Mask = SavedFIQMask; /* Set new INTC mask disabling the FIQ */ Mask = (Mask & ~(1 << FIQNum)) & 0x7F; INTCReg->FIQMask = Mask; /* Save the new value */ SavedFIQMask = Mask;} /* FIQDisable */ /* * Install and enable a new Fast Interrupt Service Routine. * * int FIQNum - interrupt request number * PFV ISRFun - new interrupt handler * * Return: * The old interrupt service routine address. */PFVFIQInstall(int FIQNum, PFV ISRFun){ PFV OldISR; /* Sanity check */ if (FIQNum < 0 || MAXFIQNUM < FIQNum) return((PFV)0); /* Get old ISR function */ OldISR = FIQVector[FIQNum]; /* Replace with new ISR function */ FIQVector[FIQNum] = ISRFun; /* Enable the interrupt */ FIQEnable(FIQNum); return(OldISR);} /* FIQInstall *//* * Software interrupt dispatcher. * * int SWINum - SWI number * * This is the SWI trap handler called when an SWI is detected. */static voidDispatchSWI(int SwiNum){ if (SwiNum < 0 || MAXSWINUM < SwiNum) /* illegal swi */ return; if (SWIVector[SwiNum]) (*(SWIVector[SwiNum]))(); else ; /* swi not registered */ return;} /* DispatchSWI */ /* * Install a new SWI Service Routine. * * int SWINum - SWI number * PFV ISRFun - new service routine * * Return: * The old service routine address. */PFVSWIInstall(int SWINum, PFV ISRFun){ PFV OldISR; /* Sanity check */ if (SWINum < 0 || MAXSWINUM < SWINum) return((PFV)0); /* Get old ISR function */ OldISR = SWIVector[SWINum]; /* Replace with new ISR function */ SWIVector[SWINum] = ISRFun; return(OldISR);} /* SWIInstall */ /* * Get a byte from the serial port. * * Return: * The byte read or 0 if not available. */byteGetByte(void){ ureg Status; byte Ch; if ((Status = UARTReg->Reg3.IIR) != 1) if ((Status & 0x06) == 0x04) { Ch = UARTReg->Reg1.RBR & 0xFF; return(Ch); } return(0);} /* GetByte *//* * Send a byte to the serial port. * * byte Ch - the byte to send * */voidPutByte(byte Ch){ ureg LineStatus; int i; do { LineStatus = UARTReg->LSR; } while(!(LineStatus & 0x20)); /* wait until ready */ for (i = 0; i < 5000; i++) /* pause */ ; UARTReg->Reg1.THR = Ch; /* send the byte */} /* PutByte */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -