timer.c

00001 /*
00002   インターバルタイマー
00003   Satofumi KAMIMURA
00004   $Id$
00005 */
00006 
00007 #include "sh7045lib.h"
00008 #include "cpu_spec.h"
00009 
00010 
00014 typedef struct {
00015   timerHandler_t callback;
00016   unsigned long interval;
00017   long interval_left;
00018 } eachTimerHandler_t;
00019 
00020 
00024 typedef struct {
00025   int numHandler;
00026   unsigned long interval_usec;
00027   eachTimerHandler_t handler[TIMER_HANDLER_MAX];
00028 } timerHandlerSet_t;
00029 static timerHandlerSet_t Handler;
00030 
00031 
00032 static unsigned long Usec = 0;
00033 static unsigned long Sec = 0;
00034 
00035 
00036 static void rawTimerHandler(void) {
00037   int i;
00038   eachTimerHandler_t *p;
00039 
00040   Usec += Handler.interval_usec;
00041   if (Usec >= 1000000) {
00042     Usec -= 1000000;
00043     ++Sec;
00044   }
00045   for (i = 0; i < Handler.numHandler; ++i) {
00046     p = &Handler.handler[i];
00047     p->interval_left -= Handler.interval_usec;
00048     while (Handler.interval_usec > p->interval_left) {
00049       p->interval_left += p->interval;
00050       p->callback();
00051     }
00052   }
00053 }
00054 
00055 
00056 int set_timerHandler(timerHandler_t callback, int interval_usec) {
00057   if (Handler.numHandler >= TIMER_HANDLER_MAX) {
00058     return -1;
00059   }
00060   Handler.handler[Handler.numHandler].callback = callback;
00061   Handler.handler[Handler.numHandler].interval = interval_usec;
00062   Handler.handler[Handler.numHandler].interval_left = interval_usec;
00063 
00064   ++Handler.numHandler;
00065   return 0;
00066 }
00067 
00068 
00069 void unset_timerHandler(timerHandler_t callback) {
00070   int i;
00071 
00072   if (Handler.numHandler <= 1) {
00073     Handler.numHandler = 0;
00074   }
00075 
00076   for (i = 0; i < Handler.numHandler; ++i) {
00077     if (Handler.handler[i].callback == callback) {
00078       Handler.handler[i] = Handler.handler[Handler.numHandler];
00079       --Handler.numHandler;
00080       return;
00081     }
00082   }
00083 }
00084 
00085 
00086 void init_timer(int level) {
00087   Handler.numHandler = 0;
00088   Handler.interval_usec = ~0;
00089 
00090   MTU.TSTR.BYTE &= ~0x80;       /* stop MTU4 */
00091   MTU4.TCR.BYTE = 0x20;         /* use TGRA, 1/1clk */
00092   MTU4.TMDR.BYTE = 0x00;        /* normal timer mode */
00093   MTU4.TIOR.BYTE.H = 0x03;      /* toggle output */
00094   MTU.TOER.BYTE |= 0x02;        /* MTU4 output setting */
00095 
00096   INTC.IPRF.WORD &= ~0xf000;    /* interrupt level */
00097   INTC.IPRF.WORD |= level << 12;
00098 
00099   MTU4.TIER.BYTE |= 0x01;       /* enable TGRA interrupt */
00100 
00101   PFC.PECR1.WORD |= 0x0100;     /* use TIOC4A port */
00102   PFC.PEIOR.WORD |= 0x1000;
00103 }
00104 
00105 
00106 int start_timer(int usec) {
00107   unsigned long cnt = (MTU4_MSEC_CNT * usec) >> 10;
00108   if (cnt > 0xffff) {
00109     return -1;
00110   }
00111   Handler.interval_usec = usec;
00112   MTU4.TGRA = cnt;
00113   MTU4.TCNT = 0;
00114   MTU.TSTR.BYTE |= 0x80;
00115 
00116   return 0;
00117 }
00118 
00119 
00120 void stop_timer(void) {
00121   MTU.TSTR.BYTE &= ~0x80;
00122 }
00123 
00124 
00125 void getRawCount(unsigned short *cnt) {
00126   int level = get_imask();
00127 
00128   set_imask((INTC.IPRF.WORD >> 12) & 0xf);
00129   *cnt = MTU4.TCNT;
00130   set_imask(level);
00131 }
00132 
00133 
00134 void getTimestamp(unsigned long *msec, unsigned short *usec) {
00135   int level = get_imask();
00136 
00137   set_imask((INTC.IPRF.WORD >> 12) & 0xf);
00138   if (usec) {
00139     *usec = Usec % 1000;
00140   }
00141   if (msec) {
00142     *msec = Sec * 1000 + Usec / 1000;
00143   }
00144   set_imask(level);
00145 }
00146 
00147 
00148 #pragma interrupt
00149 void tgi4a(void) {
00150   MTU4.TSR.BYTE &= ~0x01;
00151   rawTimerHandler();
00152 }
00153 

Generated on Mon Apr 13 22:52:04 2009 by  doxygen 1.5.7.1