1 | /* |
---|
2 | * Timer Library (TLIB) |
---|
3 | * |
---|
4 | * The Library rely on timer drivers, the timer presented by the |
---|
5 | * timer driver must look like a down-counter timer, which generates |
---|
6 | * interrupt (if configured) when underflown. |
---|
7 | * |
---|
8 | * If Timer hardware is an up-counter the Timer driver must recalculate |
---|
9 | * into values that would match as if it was a down-counter. |
---|
10 | * |
---|
11 | * COPYRIGHT (c) 2011. |
---|
12 | * Cobham Gaisler AB. |
---|
13 | * |
---|
14 | * The license and distribution terms for this file may be |
---|
15 | * found in the file LICENSE in this distribution or at |
---|
16 | * http://www.rtems.org/license/LICENSE. |
---|
17 | */ |
---|
18 | |
---|
19 | #ifndef __TLIB_H__ |
---|
20 | #define __TLIB_H__ |
---|
21 | |
---|
22 | #ifdef __cplusplus |
---|
23 | extern "C" { |
---|
24 | #endif |
---|
25 | |
---|
26 | struct tlib_dev; |
---|
27 | |
---|
28 | typedef void (*tlib_isr_t)(void *data); |
---|
29 | |
---|
30 | enum { |
---|
31 | TLIB_FLAGS_BROADCAST = 0x01 |
---|
32 | }; |
---|
33 | |
---|
34 | struct tlib_drv { |
---|
35 | /*** Functions ***/ |
---|
36 | void (*reset)(struct tlib_dev *hand); |
---|
37 | void (*get_freq)( |
---|
38 | struct tlib_dev *hand, |
---|
39 | unsigned int *basefreq, |
---|
40 | unsigned int *tickrate); |
---|
41 | int (*set_freq)(struct tlib_dev *hand, unsigned int tickrate); |
---|
42 | void (*irq_reg)(struct tlib_dev *hand, tlib_isr_t func, void *data, int flags); |
---|
43 | void (*irq_unreg)(struct tlib_dev *hand, tlib_isr_t func,void *data); |
---|
44 | void (*start)(struct tlib_dev *hand, int once); |
---|
45 | void (*stop)(struct tlib_dev *hand); |
---|
46 | void (*restart)(struct tlib_dev *hand); |
---|
47 | void (*get_counter)(struct tlib_dev *hand, unsigned int *counter); |
---|
48 | int (*custom)(struct tlib_dev *hand, int cmd, void *arg); |
---|
49 | int (*int_pend)(struct tlib_dev *hand, int ack); |
---|
50 | void (*get_widthmask)(struct tlib_dev *hand, unsigned int *widthmask); |
---|
51 | }; |
---|
52 | |
---|
53 | struct tlib_dev { |
---|
54 | struct tlib_dev *next; |
---|
55 | char status; /* 0=closed, 1=open, 2=timer started */ |
---|
56 | char index; /* Timer Index */ |
---|
57 | tlib_isr_t isr_func; |
---|
58 | void *isr_data; |
---|
59 | struct tlib_drv *drv; |
---|
60 | }; |
---|
61 | |
---|
62 | #ifdef RTEMS_DRVMGR_STARTUP |
---|
63 | /* Clock Driver Timer register function. Only used when the TLIB-Clock |
---|
64 | * driver is used. A specific Timer is registered as the System Clock |
---|
65 | * timer. |
---|
66 | */ |
---|
67 | extern void Clock_timer_register(int timer_number); |
---|
68 | #endif |
---|
69 | |
---|
70 | /* Register Timer. Called by Timer Drivers in order to register |
---|
71 | * a Timer to the Timer Library. The registration order determines |
---|
72 | * the Timer Number used in tlib_open() to identify a specific |
---|
73 | * Timer. |
---|
74 | */ |
---|
75 | extern int tlib_dev_reg(struct tlib_dev *newdev); |
---|
76 | |
---|
77 | /* Allocate a Timer. |
---|
78 | * |
---|
79 | * A Timer handle is returned identifying the timer in later calls. |
---|
80 | */ |
---|
81 | extern void *tlib_open(int timer_no); |
---|
82 | |
---|
83 | /* Close Timer */ |
---|
84 | extern void tlib_close(void *hand); |
---|
85 | |
---|
86 | /* Returns Number of Timers currently registered to Timer Library */ |
---|
87 | extern int tlib_ntimer(void); |
---|
88 | |
---|
89 | static inline void tlib_reset(void *hand) |
---|
90 | { |
---|
91 | struct tlib_dev *dev = hand; |
---|
92 | |
---|
93 | dev->drv->reset(dev); |
---|
94 | } |
---|
95 | /* Get Frequencies: |
---|
96 | * - Base Frequency (unchangable base freq rate of timer, prescaler, clkinput) |
---|
97 | * - Current Tick Rate [in multiples of Base Frequency] |
---|
98 | */ |
---|
99 | static inline void tlib_get_freq( |
---|
100 | void *hand, |
---|
101 | unsigned int *basefreq, |
---|
102 | unsigned int *tickrate) |
---|
103 | { |
---|
104 | struct tlib_dev *dev = hand; |
---|
105 | |
---|
106 | dev->drv->get_freq(dev, basefreq, tickrate); |
---|
107 | } |
---|
108 | |
---|
109 | /* Set current Tick Rate in number of "Base-Frequency ticks" */ |
---|
110 | static inline int tlib_set_freq(void *hand, unsigned int tickrate) |
---|
111 | { |
---|
112 | struct tlib_dev *dev = hand; |
---|
113 | |
---|
114 | return dev->drv->set_freq(dev, tickrate); |
---|
115 | } |
---|
116 | |
---|
117 | /* Register ISR at Timer ISR */ |
---|
118 | static inline void tlib_irq_unregister(void *hand) |
---|
119 | { |
---|
120 | struct tlib_dev *dev = hand; |
---|
121 | |
---|
122 | if ( dev->isr_func ) { |
---|
123 | dev->drv->irq_unreg(dev, dev->isr_func, dev->isr_data); |
---|
124 | dev->isr_func = NULL; |
---|
125 | } |
---|
126 | } |
---|
127 | |
---|
128 | /* Register ISR at Timer ISR */ |
---|
129 | static inline void tlib_irq_register(void *hand, tlib_isr_t func, void *data, int flags) |
---|
130 | { |
---|
131 | struct tlib_dev *dev = hand; |
---|
132 | |
---|
133 | /* Unregister previous ISR if installed */ |
---|
134 | tlib_irq_unregister(hand); |
---|
135 | dev->isr_func = func; |
---|
136 | dev->isr_data = data; |
---|
137 | dev->drv->irq_reg(dev, func, data, flags); |
---|
138 | } |
---|
139 | |
---|
140 | /* Start Timer, ISRs will be generated if enabled. |
---|
141 | * |
---|
142 | * once determines if timer should restart (=0) on underflow automatically, |
---|
143 | * or stop when underflow is reached (=1). |
---|
144 | */ |
---|
145 | static inline void tlib_start(void *hand, int once) |
---|
146 | { |
---|
147 | struct tlib_dev *dev = hand; |
---|
148 | |
---|
149 | dev->drv->start(dev, once); |
---|
150 | } |
---|
151 | |
---|
152 | /* Stop Timer, no more ISRs will be generated */ |
---|
153 | static inline void tlib_stop(void *hand) |
---|
154 | { |
---|
155 | struct tlib_dev *dev = hand; |
---|
156 | |
---|
157 | dev->drv->stop(dev); |
---|
158 | } |
---|
159 | |
---|
160 | /* Restart/Reload Timer, may be usefull if a Watchdog Timer */ |
---|
161 | static inline void tlib_restart(void *hand) |
---|
162 | { |
---|
163 | struct tlib_dev *dev = hand; |
---|
164 | |
---|
165 | dev->drv->restart(dev); |
---|
166 | } |
---|
167 | |
---|
168 | /* Get current counter value (since last tick) */ |
---|
169 | static inline void tlib_get_counter(void *hand, unsigned int *counter) |
---|
170 | { |
---|
171 | struct tlib_dev *dev = hand; |
---|
172 | |
---|
173 | dev->drv->get_counter(dev, counter); |
---|
174 | } |
---|
175 | |
---|
176 | /* Do a custom operation */ |
---|
177 | static inline void tlib_custom(void *hand, int cmd, void *arg) |
---|
178 | { |
---|
179 | struct tlib_dev *dev = hand; |
---|
180 | |
---|
181 | dev->drv->custom(dev, cmd, arg); |
---|
182 | } |
---|
183 | |
---|
184 | static inline int tlib_interrupt_pending(void *hand, int ack) |
---|
185 | { |
---|
186 | struct tlib_dev *dev = hand; |
---|
187 | |
---|
188 | return dev->drv->int_pend(dev, ack); |
---|
189 | } |
---|
190 | |
---|
191 | static inline void tlib_get_widthmask(void *hand, unsigned int *widthmask) |
---|
192 | { |
---|
193 | struct tlib_dev *dev = hand; |
---|
194 | |
---|
195 | dev->drv->get_widthmask(dev, widthmask); |
---|
196 | } |
---|
197 | |
---|
198 | #ifdef __cplusplus |
---|
199 | } |
---|
200 | #endif |
---|
201 | |
---|
202 | #endif |
---|