source: arduino-1-6-7/trunk/fuentes/arduino-ide-amd64/hardware/arduino/avr/firmwares/wifishield/wifiHD/src/timer.c @ 4837

Last change on this file since 4837 was 4837, checked in by daduve, 2 years ago

Adding new version

File size: 6.3 KB
Line 
1/*! \page License
2 * Copyright (C) 2009, H&D Wireless AB All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright notice,
8 * this list of conditions and the following disclaimer.
9 *
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 *
14 * 3. The name of H&D Wireless AB may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY H&D WIRELESS AB ``AS IS'' AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
20 * SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <stdint.h>
30#include <rtc.h>
31#include <intc.h>
32#include <timer.h>
33#ifdef FREERTOS_USED
34#include "FreeRTOS.h"
35#include "task.h"
36#endif
37
38#define TIMER_HZ 4
39
40
41struct timeout_t {
42        U32 tick; 
43        U32 expire_at_tick;
44        Bool expired;
45        U8 type;
46        void (*cb)(void* ctx);
47        void* ctx;
48};
49
50struct timer_t {
51        volatile U32 tick;
52        struct timeout_t timeout[10];
53        void (*tick_isr) (void* ctx);
54        const U32 MS_PER_TICK;
55        void *ctx;
56};
57
58#define ARRAY_SIZE(a) sizeof(a) / sizeof(a[0])
59
60
61static struct timer_t TIMER = {
62        .tick = 0,
63#ifdef FREERTOS_USED
64        .MS_PER_TICK = 1 / portTICK_RATE_MS,
65#else
66        .MS_PER_TICK = TIMER_HZ,
67#endif
68        .timeout = { { 0 } },
69};
70
71#ifdef FREERTOS_USED /* Use TICK-hook */
72
73void vApplicationTickHook( void ) {
74        struct timer_t* priv = &TIMER;
75        priv->tick++;
76        if(priv->tick_isr) {
77                priv->tick_isr(priv->ctx);
78        }
79}
80
81#else /* Use interrupt directly */
82
83static __attribute__((__interrupt__)) void irq_handler(void)
84{
85        volatile avr32_rtc_t *rtc = &AVR32_RTC;
86        struct timer_t* priv = &TIMER;
87        priv->tick++;
88
89        if(priv->tick_isr)
90                priv->tick_isr(priv->ctx);
91       
92        rtc->icr = AVR32_RTC_ICR_TOPI_MASK;
93        rtc->isr;
94}
95
96#endif
97
98void timer_init(void (*tick_isr) (void* ctx), void* ctx)
99{
100        struct timer_t* priv = &TIMER;
101        uint8_t id;
102       
103#ifndef FREERTOS_USED
104        INTC_register_interrupt(&irq_handler, AVR32_RTC_IRQ, AVR32_INTC_INT0);
105        if (!rtc_init(&AVR32_RTC, RTC_OSC_RC, 0))
106                Assert(0);
107
108        rtc_set_top_value(&AVR32_RTC, 115 * priv->MS_PER_TICK / 2);
109        rtc_enable_interrupt(&AVR32_RTC);
110        rtc_enable(&AVR32_RTC);
111#else
112        /* With FreeRTOS we use the OS tick instead */
113#endif
114        priv->tick_isr = tick_isr;
115        priv->ctx = ctx;
116
117        for (id = 0; id < ARRAY_SIZE(priv->timeout); id++)
118                priv->timeout[id].expired = TRUE;
119}
120
121
122U32 timer_get_ms(void)
123{
124        struct timer_t* priv = &TIMER;
125        return priv->tick * priv->MS_PER_TICK;
126}
127
128void timer_delay(U32 ms)
129{
130        struct timer_t* priv = &TIMER;
131        U32 expire_at_tick = priv->tick + ms / priv->MS_PER_TICK;
132        while (priv->tick < expire_at_tick);
133}
134
135/**
136 * Called from application main loop to invoke any scheduled timeout cbs.
137 * This function might be called as often as possible rather than at each tick
138 * to support the timeout value '0', e.g a timeout within less than one tick.
139 *
140 */
141void timer_poll(void)
142{
143        struct timer_t* priv = &TIMER;
144        U8 i;
145
146        for (i = 0; i < ARRAY_SIZE(priv->timeout); i++) {
147                struct timeout_t* tmo = &priv->timeout[i];
148                if (tmo->expired)
149                        continue;
150       
151                if (tmo->expire_at_tick > priv->tick)
152                        continue;
153
154                if (tmo->cb)
155                        tmo->cb(tmo->ctx);
156               
157                if (tmo->type == TIMEOUT_PERIODIC)
158                        tmo->expire_at_tick = priv->tick + tmo->tick;
159                else
160                        tmo->expired = TRUE;
161        }
162}
163
164static U32 timer_sched_timeout(U32 ms, U8 type)
165{
166        struct timer_t* priv = &TIMER;
167        struct timeout_t* tmo;
168        U8 id;
169
170        Assert(type == TIMEOUT_ONESHOT || type == TIMEOUT_PERIODIC);
171       
172        for (id = 0; id < ARRAY_SIZE(priv->timeout); id++) {
173                tmo = &priv->timeout[id];
174                if (tmo->expired)
175                        break;
176        }
177
178        Assert(id != ARRAY_SIZE(priv->timeout));
179
180        tmo->tick = ms / priv->MS_PER_TICK;
181        tmo->expire_at_tick = priv->tick + tmo->tick;
182        tmo->type = type;
183        tmo->expired = FALSE;
184        return id;
185}
186
187U32 timer_sched_timeout_cb(U32 ms, U8 type, void (*cb)(void *ctx), void* ctx)
188{
189        struct timer_t* priv = &TIMER;
190        struct timeout_t* tmo;
191        U8 id;
192
193        Assert(cb);
194        id = timer_sched_timeout(ms, type);
195        tmo = &priv->timeout[id];
196
197        tmo->cb = cb;
198        tmo->ctx = ctx;
199        return id;
200}
201
202
203U32 timer_mod(U32 id, U32 ms, U8 type, void (*cb)(void *ctx), void* ctx)
204{
205        struct timer_t* priv = &TIMER;
206
207        if (id != INVALID_TIMER_ID && !priv->timeout[id].expired)
208                timer_cancel_timeout(id);
209       
210        return timer_sched_timeout_cb(ms, type, cb, ctx);
211}
212
213void timer_cancel_timeout(U32 id)
214{
215        struct timer_t* priv = &TIMER;
216        struct timeout_t* tmo;
217   
218        tmo = &priv->timeout[id];
219        tmo->expired = TRUE;
220}
221
222int timer_interval_passed(U32 old, U32 new, U32 diff) {
223        /* New did not wrap */
224        if (new > old && new - old > diff) {
225                return 1;
226        }
227        /* New did wrap */
228        else if (new < old && ( ( (U32)(-1) - old ) + new ) > diff ) {
229                return 1;
230        }
231        return 0;
232}
Note: See TracBrowser for help on using the repository browser.