00001
00029 #include <stdint.h>
00030 #include <rtc.h>
00031 #include <intc.h>
00032 #include "timer.h"
00033
00034
00035 struct timeout_t {
00036 U32 tick;
00037 U32 expire_at_tick;
00038 Bool expired;
00039 U8 type;
00040 void (*cb)(void* ctx);
00041 void* ctx;
00042 };
00043
00044 struct timer_t {
00045 volatile U32 tick;
00046 struct timeout_t timeout[8];
00047 void (*tick_isr) (void* ctx);
00048 const U32 MS_PER_TICK;
00049 void *ctx;
00050 };
00051
00052 #define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
00053
00054 static __attribute__((__interrupt__)) void irq_handler(void);
00055
00056 static struct timer_t TIMER = {
00057 .tick = 0,
00058 .MS_PER_TICK = TIMER_HZ,
00059 .timeout = { { 0 } },
00060 };
00061
00062 void timer_init(void (*tick_isr) (void* ctx), void* ctx)
00063 {
00064 struct timer_t* priv = &TIMER;
00065 uint8_t id;
00066
00067 INTC_register_interrupt(&irq_handler, AVR32_RTC_IRQ, AVR32_INTC_INT0);
00068 if (!rtc_init(&AVR32_RTC, RTC_OSC_RC, 0))
00069 Assert(0);
00070
00071 priv->tick_isr = tick_isr;
00072 priv->ctx = ctx;
00073 rtc_set_top_value(&AVR32_RTC, 115 * priv->MS_PER_TICK / 2);
00074 rtc_enable_interrupt(&AVR32_RTC);
00075 rtc_enable(&AVR32_RTC);
00076
00077 for (id = 0; id < ARRAY_SIZE(priv->timeout); id++)
00078 priv->timeout[id].expired = TRUE;
00079 }
00080
00081
00082 U32 timer_get_ms(void)
00083 {
00084 struct timer_t* priv = &TIMER;
00085 return priv->tick * priv->MS_PER_TICK;
00086 }
00087
00088 void timer_delay(U32 ms)
00089 {
00090 struct timer_t* priv = &TIMER;
00091 U32 expire_at_tick = priv->tick + ms / priv->MS_PER_TICK;
00092 while (priv->tick < expire_at_tick);
00093 }
00094
00101 void timer_poll(void)
00102 {
00103 struct timer_t* priv = &TIMER;
00104 U8 i;
00105
00106 for (i = 0; i < ARRAY_SIZE(priv->timeout); i++) {
00107 struct timeout_t* tmo = &priv->timeout[i];
00108 if (tmo->expired)
00109 continue;
00110
00111 if (tmo->expire_at_tick > priv->tick)
00112 continue;
00113
00114 if (tmo->cb)
00115 tmo->cb(tmo->ctx);
00116
00117 if (tmo->type == TIMEOUT_PERIODIC)
00118 tmo->expire_at_tick = priv->tick + tmo->tick;
00119 else
00120 tmo->expired = TRUE;
00121 }
00122 }
00123
00124 static U32 timer_sched_timeout(U32 ms, U8 type)
00125 {
00126 struct timer_t* priv = &TIMER;
00127 struct timeout_t* tmo;
00128 U8 id;
00129
00130 Assert(type == TIMEOUT_ONESHOT || type == TIMEOUT_PERIODIC);
00131
00132 for (id = 0; id < ARRAY_SIZE(priv->timeout); id++) {
00133 tmo = &priv->timeout[id];
00134 if (tmo->expired)
00135 break;
00136 }
00137
00138 Assert(id != ARRAY_SIZE(priv->timeout));
00139
00140 tmo->tick = ms / priv->MS_PER_TICK;
00141 tmo->expire_at_tick = priv->tick + tmo->tick;
00142 tmo->type = type;
00143 tmo->expired = FALSE;
00144 return id;
00145 }
00146
00147 U32 timer_sched_timeout_cb(U32 ms, U8 type, void (*cb)(void *ctx), void* ctx)
00148 {
00149 struct timer_t* priv = &TIMER;
00150 struct timeout_t* tmo;
00151 U8 id;
00152
00153 Assert(cb);
00154 id = timer_sched_timeout(ms, type);
00155 tmo = &priv->timeout[id];
00156
00157 tmo->cb = cb;
00158 tmo->ctx = ctx;
00159 return id;
00160 }
00161
00162
00163 void timer_cancel_timeout(U32 id)
00164 {
00165 struct timer_t* priv = &TIMER;
00166 struct timeout_t* tmo;
00167
00168 tmo = &priv->timeout[id];
00169 tmo->expired = TRUE;
00170 }
00171
00172 static __attribute__((__interrupt__)) void irq_handler(void)
00173 {
00174 volatile avr32_rtc_t *rtc = &AVR32_RTC;
00175 struct timer_t* priv = &TIMER;
00176 priv->tick++;
00177
00178 if(priv->tick_isr)
00179 priv->tick_isr(priv->ctx);
00180
00181 rtc->icr = AVR32_RTC_ICR_TOPI_MASK;
00182 rtc->isr;
00183 }