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
00107
00108 for (i = 0; i < ARRAY_SIZE(priv->timeout); i++) {
00109 struct timeout_t* tmo = &priv->timeout[i];
00110 if (tmo->expired)
00111 continue;
00112
00113 if (tmo->expire_at_tick > priv->tick)
00114 continue;
00115
00116 if (tmo->cb)
00117 tmo->cb(tmo->ctx);
00118
00119 if (tmo->type == TIMEOUT_PERIODIC)
00120 tmo->expire_at_tick = priv->tick + tmo->tick;
00121 else
00122 tmo->expired = TRUE;
00123 }
00124 }
00125
00126 static U32 timer_sched_timeout(U32 ms, U8 type)
00127 {
00128 struct timer_t* priv = &TIMER;
00129 struct timeout_t* tmo;
00130 U8 id;
00131
00132 Assert(type == TIMEOUT_ONESHOT || type == TIMEOUT_PERIODIC);
00133
00134 for (id = 0; id < ARRAY_SIZE(priv->timeout); id++) {
00135 tmo = &priv->timeout[id];
00136 if (tmo->expired)
00137 break;
00138 }
00139
00140 Assert(id != ARRAY_SIZE(priv->timeout));
00141
00142 tmo->tick = ms / priv->MS_PER_TICK;
00143 tmo->expire_at_tick = priv->tick + tmo->tick;
00144 tmo->type = type;
00145 tmo->expired = FALSE;
00146 return id;
00147 }
00148
00149 U32 timer_sched_timeout_cb(U32 ms, U8 type, void (*cb)(void *ctx), void* ctx)
00150 {
00151 struct timer_t* priv = &TIMER;
00152 struct timeout_t* tmo;
00153 U8 id;
00154
00155 Assert(cb);
00156 id = timer_sched_timeout(ms, type);
00157 tmo = &priv->timeout[id];
00158
00159 tmo->cb = cb;
00160 tmo->ctx = ctx;
00161 return id;
00162 }
00163
00164
00165 void timer_cancel_timeout(U32 id)
00166 {
00167 struct timer_t* priv = &TIMER;
00168 struct timeout_t* tmo;
00169
00170 tmo = &priv->timeout[id];
00171 tmo->expired = TRUE;
00172 }
00173
00174 static __attribute__((__interrupt__)) void irq_handler(void)
00175 {
00176 volatile avr32_rtc_t *rtc = &AVR32_RTC;
00177 struct timer_t* priv = &TIMER;
00178 priv->tick++;
00179
00180 if(priv->tick_isr)
00181 priv->tick_isr(priv->ctx);
00182
00183 rtc->icr = AVR32_RTC_ICR_TOPI_MASK;
00184 rtc->isr;
00185 }