From 757be61d575b69486c56635133174d8fadd5eb0c Mon Sep 17 00:00:00 2001 From: Jim Kowalkowski Date: Tue, 13 May 1997 14:36:57 +0000 Subject: [PATCH] library support for the tick timers on the mvme167 --- src/libvxWorks/timerLib.c | 439 ++++++++++++++++++++++++++++++++++++++ src/libvxWorks/timerLib.h | 54 +++++ 2 files changed, 493 insertions(+) create mode 100644 src/libvxWorks/timerLib.c create mode 100644 src/libvxWorks/timerLib.h diff --git a/src/libvxWorks/timerLib.c b/src/libvxWorks/timerLib.c new file mode 100644 index 000000000..920b41af1 --- /dev/null +++ b/src/libvxWorks/timerLib.c @@ -0,0 +1,439 @@ +/* + * Author: Jim Kowalkowski + * Date: 4/97 + * + * $Id$ + * $Log$ + */ + +#include +#include +#include +#include +#include +#include + +#define MV167 1 +#include "timerLib.h" + +typedef unsigned long _UL; +typedef volatile unsigned long _VUL; +typedef unsigned char _UC; +typedef volatile unsigned char _VUC; + +struct _timerHandle { + _UL (*res)(void); + _UL (*val)(void); + int (*comp)(_UL); + int (*level)(int); + int (*cmd)(timerCmds); + INTFUNC user_func; + void* user_parm; + struct _timerHandle* next; +}; +typedef struct _timerHandle timerHandle; + +#define timerLevelValid(x) (x>=0 && x<=7) + +static SEM_ID lock; +static timerHandle* freelist=NULL; +static void tick_func(void* v); + +#ifdef MV167 +/* ---------- pcc API ---------- */ +static int pccInit(void); +static _UL pccRes(void); +static _UL pccValue1(void); +static _UL pccValue2(void); +static int pccComp1(_UL usec); +static int pccComp2(_UL usec); +static int pccLevel1(int level); +static int pccLevel2(int level); +static int pccCmd1(timerCmds cmd); +static int pccCmd2(timerCmds cmd); +#endif + +#ifdef MV162 +/* ---------- mcchip API -------- */ +static int mcInit(void); +static _UL mcRes(void); +static _UL mcValue1(void); +static _UL mcValue2(void); +static _UL mcValue3(void); +static _UL mcValue4(void); +static int mcComp1(_UL usec); +static int mcComp2(_UL usec); +static int mcComp3(_UL usec); +static int mcComp4(_UL usec); +static int mcLevel1(int level); +static int mcLevel2(int level); +static int mcLevel3(int level); +static int mcLevel4(int level); +static int mcCmd1(timerCmds cmd); +static int mcCmd2(timerCmds cmd); +static int mcCmd3(timerCmds cmd); +static int mcCmd4(timerCmds cmd); +#endif + +#if defined(MV162) || defined(MV167) +/* ---------- vmechip2 API --------- */ +static int vmeInit(void); +static _UL vmeRes(void); +static _UL vmeValue1(void); +static _UL vmeValue2(void); +static int vmeComp1(_UL usec); +static int vmeComp2(_UL usec); +static int vmeLevel1(int level); +static int vmeLevel2(int level); +static int vmeCmd1(timerCmds cmd); +static int vmeCmd2(timerCmds cmd); +#endif + +/* ---------- user functions --------- */ +int timerSystemInit(void) +{ + if(freelist) return -1; + lock=semBCreate(SEM_Q_PRIORITY,SEM_FULL); +#ifdef MV162 + if(mcInit()<0) return -1; + if(vmeInit()<0) return -1; +#endif +#ifdef MV167 + if(pccInit()<0) return -1; + if(vmeInit()<0) return -1; +#endif + return 0; +} + +void* timerAlloc(void) /* returns handle */ +{ + timerHandle* rc; + semTake(lock,WAIT_FOREVER); + if(freelist) + { + rc=freelist; + freelist=rc->next; + rc->next=NULL; + } + else + rc=NULL; + semGive(lock); + return (void*)rc; +} +void timerFree(void* handle) +{ + timerHandle* h=(timerHandle*)handle; + if(h) + { + semTake(lock,WAIT_FOREVER); + h->next=freelist; + freelist=h; + semGive(lock); + } +} + +int timerCmd(void* handle, timerCmds cmd) +{ + timerHandle* h=(timerHandle*)handle; + return h?(*h->cmd)(cmd):-1; +} +unsigned long timerResolution(void* handle) +{ + timerHandle* h=(timerHandle*)handle; + return h?(*h->res)():-1; +} +unsigned long timerCurrentValue(void* handle) +{ + timerHandle* h=(timerHandle*)handle; + return h?(*h->val)():-1; +} +int timerCompareValue(void* handle,unsigned long usec) +{ + timerHandle* h=(timerHandle*)handle; + return h?(*h->comp)(usec):-1; +} +int timerIntLevel(void* handle,int level) +{ + timerHandle* h=(timerHandle*)handle; + return h?(*h->level)(level):-1; +} +int timerPeriodic(void* handle,unsigned long usec,int level, + INTFUNC func,void* parm) +{ + timerHandle* h=(timerHandle*)handle; + int rc=0; + + if(h) + { + rc|=(*h->cmd)(timerDisable); + rc|=(*h->cmd)(timerClear); + rc|=(*h->comp)(usec); + rc|=(*h->level)(level); + rc|=timerIntFunction(handle,func,parm); + rc|=(*h->cmd)(timerIntClear); + if(rc==0) + { + rc|=(*h->cmd)(timerIntEnable); + rc|=(*h->cmd)(timerEnable); + } + } + return rc; +} +int timerIntFunction(void* handle,INTFUNC func, void* parm) +{ + timerHandle* h=(timerHandle*)handle; + int rc=0; + if(h) + { + h->user_func=func; + h->user_parm=parm; + } + else + rc=-1; + + return rc; +} + +/* -------------------- pcc functions -------------------- */ +#ifdef MV167 +static int pccInit(void) +{ + /* + vxWorks uses one of the timers on the pcc as the tick timer + so do not make this one available to the users. It also makes the + second one available to users with sysAuxClockConnect() so don't + use this one either. This leaves no timers available on the pcc + using vxWorks. Don't do anything here for now. + */ + return 0; +} +static _UL pccRes(void) { return 1000000; } +static _UL pccValue1(void) { return 0; } +static _UL pccValue2(void) { return 0; } +static int pccComp1(_UL usec) { return -1; } +static int pccComp2(_UL usec) { return -1; } +static int pccLevel1(int level) { return -1; } +static int pccLevel2(int level) { return -1; } +static int pccCmd1(timerCmds cmd) { return -1; } +static int pccCmd2(timerCmds cmd) { return -1; } +#endif +/* -------------------- mcchip2 functions -------------------- */ +#ifdef MV162 +/* MCCHIP_BASE = 0xfff42000 */ + +static int mcInit(void) +{ + /* + First two timers are used by vxWorks, see note in pccInit(). + */ + timerHandle* h; + int vec,rc=0; +#if 0 + /* do not use these in version 1 */ + /* first available timer (3) */ + mcCmd3(timerDisable); + h=(timerHandle*)malloc(sizeof(timerHandle)); + h->user_func=NULL; + h->user_parm=NULL; + h->res=mcRes; + h->val=mcValue3; + h->comp=mcComp3; + h->cmd=mcCmd3; + h->level=mcLevel3; + vec=(*((_VUC*)(0xfff42003))&0xf0)+0x04; /* VBR */ + if(intConnect(INUM_TO_IVEC(vec),tick_func,(int)h)!=OK) rc=-1; + h->next=freelist; + freelist=h; + + /* second available timer (4) */ + mcCmd4(timerDisable); + h=(timerHandle*)malloc(sizeof(timerHandle)); + h->user_func=NULL; + h->user_parm=NULL; + h->res=mcRes; + h->val=mcValue4; + h->comp=mcComp4; + h->cmd=mcCmd4; + h->level=mcLevel4; + vec=(*((_VUC*)(0xfff42003))&0xf0)+0x03; /* VBR */ + if(intConnect(INUM_TO_IVEC(vec),tick_func,(int)h)!=OK) rc=-1; + h->next=freelist; + freelist=h; +#endif + return rc; +} + +static _UL mcValue1(void) { return 0; } +static _UL mcValue2(void) { return 0; } +static int mcComp1(_UL usec) { return -1; } +static int mcComp2(_UL usec) { return -1; } +static int mcLevel1(int level) { return -1; } +static int mcLevel2(int level) { return -1; } +static int mcCmd1(timerCmds cmd) { return -1; } +static int mcCmd2(timerCmds cmd) { return -1; } + +static _UL mcRes(void) { return 1000000; } +static _UL mcValue3(void) { return *((_VUL*)(0xfff42034)); } +static _UL mcValue4(void) { return *((_VUL*)(0xfff4203c)); } +static int mcComp3(_UL usec) { *((_VUL*)(0xfff42030))=usec; return 0; } +static int mcComp4(_UL usec) { *((_VUL*)(0xfff42038))=usec; return 0; } + +static int mcLevel3(int level) +{ + _UC x=(_UC)level; + if(!timerLevelValid(level)) return -1; + *((_VUC*)(0xfff42019))&=0xf8; /* intctrl3 */ + *((_VUC*)(0xfff42019))|=x; /* intctrl3 */ + return 0; +} +static int mcLevel4(int level) +{ + _UC x=(_UC)level; + if(!timerLevelValid(level)) return -1; + *((_VUC*)(0xfff42018))&=0xf8; /* intctrl4 */ + *((_VUC*)(0xfff42018))|=x; /* intctrl4 */ + return 0; +} +static int mcCmd3(timerCmds cmd) +{ + switch(cmd) + { + case timerClear: *((_VUC*)(0xfff42034))=0; break; /* current3 */ + case timerDisable: *((_VUC*)(0xfff4201f))&=0x02; break; /* control3 */ + case timerEnable: *((_VUC*)(0xfff4201f))|=0x01; break; /* control3 */ + case timerResetMode: *((_VUC*)(0xfff4201f))|=0x02; break; /* control3 */ + case timerCycleMode: *((_VUC*)(0xfff4201f))&=0xfd; break; /* control3 */ + /* !!!!!check the interrupt enable/disable registers!!!!!*/ + case timerIntEnable: *((_VUC*)(0xfff42019))|=0x10; break; /* intctrl3 */ + case timerIntDisable: *((_VUC*)(0xfff42019))|=0x07; break; /* intctrl3 */ + /* !!!!!check the interrupt enable/disable registers!!!!!*/ + case timerIntClear: *((_VUC*)(0xfff42019))|=0x08; break; /* intctrl3 */ + default: break; + } + return 0; +} +static int mcCmd4(timerCmds cmd) +{ + switch(cmd) + { + case timerClear: *((_VUC*)(0xfff4203c))=0; break; /* current4 */ + case timerDisable: *((_VUC*)(0xfff4201e))&=0x02; break; /* control4 */ + case timerEnable: *((_VUC*)(0xfff4201e))|=0x01; break; /* control4 */ + case timerResetMode: *((_VUC*)(0xfff4201e))|=0x02; break; /* control4 */ + case timerCycleMode: *((_VUC*)(0xfff4201e))&=0xfd; break; /* control4 */ + /* !!!!!check the interrupt enable/disable registers!!!!!*/ + case timerIntEnable: *((_VUC*)(0xfff42018))|=0x10; break; /* intctrl4 */ + case timerIntDisable: *((_VUC*)(0xfff42018))|=0x07; break; /* intctrl4 */ + /* !!!!!check the interrupt enable/disable registers!!!!!*/ + case timerIntClear: *((_VUC*)(0xfff42018))|=0x08; break; /* intctrl4 */ + default: break; + } + return 0; +} +#endif +/* -------------------- vmechip2 functions -------------------- */ +#if defined(MV162) || defined(MV167) +static int vmeInit(void) +{ + timerHandle* h; + int vec,rc=0; + + /* first available timer (1) */ + vmeCmd1(timerDisable); + h=(timerHandle*)malloc(sizeof(timerHandle)); + h->user_func=NULL; + h->user_parm=NULL; + h->res=vmeRes; + h->val=vmeValue1; + h->comp=vmeComp1; + h->cmd=vmeCmd1; + h->level=vmeLevel1; + vec=(*((_VUC*)(0xfff4008b))&0xf0)|0x08; /* VBR */ + if(intConnect(INUM_TO_IVEC(vec),tick_func,(int)h)!=OK) rc=-1; + h->next=freelist; + freelist=h; + + /* second available timer (2) */ + vmeCmd2(timerDisable); + h=(timerHandle*)malloc(sizeof(timerHandle)); + h->user_func=NULL; + h->user_parm=NULL; + h->res=vmeRes; + h->val=vmeValue2; + h->comp=vmeComp2; + h->cmd=vmeCmd2; + h->level=vmeLevel2; + vec=(*((_VUC*)(0xfff4008b))&0xf0)|0x09; /* VBR */ + if(intConnect(INUM_TO_IVEC(vec),tick_func,(int)h)!=OK) rc=-1; + h->next=freelist; + freelist=h; + + return rc; +} + +static _UL vmeRes(void) { return 1000000; } +static _UL vmeValue1(void) { return *((_VUL*)(0xfff40054)); } +static _UL vmeValue2(void) { return *((_VUL*)(0xfff4005c)); } +static int vmeComp1(_UL usec) { *((_VUL*)(0xfff40050))=usec; return 0; } +static int vmeComp2(_UL usec) { *((_VUL*)(0xfff40058))=usec; return 0; } + +static int vmeLevel1(int level) +{ + _UC x=(_UC)level; + if(!timerLevelValid(level)) return -1; + *((_VUC*)(0xfff40078))&=0xf8; /* int level */ + *((_VUC*)(0xfff40078))|=x; /* int level */ + return 0; +} +static int vmeLevel2(int level) +{ + _UC x=(_UC)level; + if(!timerLevelValid(level)) return -1; + *((_VUC*)(0xfff40078))&=0x8f; /* int level */ + *((_VUC*)(0xfff40078))|=(x<<4); /* int level */ + return 0; +} + +static int vmeCmd1(timerCmds cmd) +{ + switch(cmd) + { + case timerClear: *((_VUC*)(0xfff40054))=0; break; /* current1 */ + case timerDisable: *((_VUC*)(0xfff40060))&=0x02; break; /* control1 */ + case timerEnable: *((_VUC*)(0xfff40060))|=0x01; break; /* control1 */ + case timerResetMode: *((_VUC*)(0xfff40060))|=0x02; break; /* control1 */ + case timerCycleMode: *((_VUC*)(0xfff40060))&=0xfd; break; /* control1 */ + case timerIntEnable: *((_VUC*)(0xfff4006f))|=0x01; break; /* intctrl1 */ + case timerIntDisable: *((_VUC*)(0xfff4006f))&=0xfe; break; /* intctrl1 */ + case timerIntClear: *((_VUC*)(0xfff40077))|=0x01; break; /* intclear1 */ + default: break; + } + return 0; +} +static int vmeCmd2(timerCmds cmd) +{ + switch(cmd) + { + case timerClear: *((_VUC*)(0xfff4005c))=0; break; /* current2 */ + case timerDisable: *((_VUC*)(0xfff40061))&=0x02; break; /* control2 */ + case timerEnable: *((_VUC*)(0xfff40061))|=0x01; break; /* control2 */ + case timerResetMode: *((_VUC*)(0xfff40061))|=0x02; break; /* control2 */ + case timerCycleMode: *((_VUC*)(0xfff40061))&=0xfd; break; /* control2 */ + case timerIntEnable: *((_VUC*)(0xfff4006f))|=0x02; break; /* intctrl2 */ + case timerIntDisable: *((_VUC*)(0xfff4006f))&=0xfd; break; /* intctrl2 */ + case timerIntClear: *((_VUC*)(0xfff40077))|=0x02; break; /* intclear2 */ + default: break; + } + return 0; +} +#endif + +/* ------------------------ shared functions ------------------------ */ + +static void tick_func(void* v) +{ + timerHandle* h = (timerHandle*)v; + (*h->cmd)(timerIntClear); + if(h->user_func) (*h->user_func)(h->user_parm); +} + diff --git a/src/libvxWorks/timerLib.h b/src/libvxWorks/timerLib.h new file mode 100644 index 000000000..d3105d039 --- /dev/null +++ b/src/libvxWorks/timerLib.h @@ -0,0 +1,54 @@ +#ifndef TIMERLIB_H +#define TIMERLIB_H + +/* + * Author: Jim Kowalkowski + * Date: 4/97 + * + * Based heavily on the HiDEOS ticktimer scheme - but using c instead of c++ + * + * $Id$ + * $Log$ + */ + +typedef enum { + timerClear=0, /* clear the timer value */ + timerDisable=1, /* disable the timer from counting */ + timerEnable=2, /* enable counting */ + timerResetMode=3, /* reset counter to zero upon compare (periodic) */ + timerCycleMode=4, /* counter stays at compare value and stops counting */ + timerIntEnable=5, /* enable timer interrupt upon compare */ + timerIntDisable=6,/* disable timer interrupt */ + timerIntClear=7 /* clear the interrupt condition (done automatically) */ +} timerCmds; + +#define timerTotalCmds 8 + +typedef void (*INTFUNC)(void*); + +/* must be run before the timerLib functions can be used */ +int timerSystemInit(void); +void* timerAlloc(void); /* get a timer to use, returns handle to it */ +void timerFree(void* handle); /* return a timer back to the timer pool */ + +/* tell the timer to do something - see above timerCmds */ +int timerCmd(void* handle, timerCmds cmd); + +/* information about the timer */ +unsigned long timerResolution(void* handle); +unsigned long timerCurrentValue(void* handle); /* read the timer value */ + +/* set the number of microsecond before timer goes off */ +int timerCompareValue(void* handle,unsigned long usec); +/* the timer's interrupt level */ +int timerIntLevel(void* handle,int level); + +/* provide function called when the timer goes off (at interrupt level) */ +int timerIntFunction(void* handle,INTFUNC func, void* parm); + +/* simple way to set up a periodic interrupt every usec microseconds at + interrupt level lev. The function func will be called with parameter + parm */ +int timerPeriodic(void* h,unsigned long usec,int lev,INTFUNC func,void* parm); + +#endif