1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29#include <csp/errno.h>
30#include <csp/stdint.h>
31
32#include <csp/tmrHw.h>
33#include <mach/csp/tmrHw_reg.h>
34
35#define tmrHw_ASSERT(a) if (!(a)) *(char *)0 = 0
36#define tmrHw_MILLISEC_PER_SEC (1000)
37
38#define tmrHw_LOW_1_RESOLUTION_COUNT (tmrHw_LOW_RESOLUTION_CLOCK / tmrHw_MILLISEC_PER_SEC)
39#define tmrHw_LOW_1_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_1_RESOLUTION_COUNT)
40#define tmrHw_LOW_16_RESOLUTION_COUNT (tmrHw_LOW_1_RESOLUTION_COUNT / 16)
41#define tmrHw_LOW_16_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_16_RESOLUTION_COUNT)
42#define tmrHw_LOW_256_RESOLUTION_COUNT (tmrHw_LOW_1_RESOLUTION_COUNT / 256)
43#define tmrHw_LOW_256_MAX_MILLISEC (0xFFFFFFFF / tmrHw_LOW_256_RESOLUTION_COUNT)
44
45#define tmrHw_HIGH_1_RESOLUTION_COUNT (tmrHw_HIGH_RESOLUTION_CLOCK / tmrHw_MILLISEC_PER_SEC)
46#define tmrHw_HIGH_1_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_1_RESOLUTION_COUNT)
47#define tmrHw_HIGH_16_RESOLUTION_COUNT (tmrHw_HIGH_1_RESOLUTION_COUNT / 16)
48#define tmrHw_HIGH_16_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_16_RESOLUTION_COUNT)
49#define tmrHw_HIGH_256_RESOLUTION_COUNT (tmrHw_HIGH_1_RESOLUTION_COUNT / 256)
50#define tmrHw_HIGH_256_MAX_MILLISEC (0xFFFFFFFF / tmrHw_HIGH_256_RESOLUTION_COUNT)
51
52static void ResetTimer(tmrHw_ID_t timerId)
53 __attribute__ ((section(".aramtext")));
54static int tmrHw_divide(int num, int denom)
55 __attribute__ ((section(".aramtext")));
56
57
58
59
60
61
62
63
64
65
66
67uint32_t tmrHw_getTimerCapability(tmrHw_ID_t timerId,
68 tmrHw_CAPABILITY_e capability
69) {
70 switch (capability) {
71 case tmrHw_CAPABILITY_CLOCK:
72 return (timerId <=
73 1) ? tmrHw_LOW_RESOLUTION_CLOCK :
74 tmrHw_HIGH_RESOLUTION_CLOCK;
75 case tmrHw_CAPABILITY_RESOLUTION:
76 return 32;
77 default:
78 return 0;
79 }
80 return 0;
81}
82
83
84
85
86
87
88
89
90
91
92
93static void ResetTimer(tmrHw_ID_t timerId
94) {
95
96 pTmrHw[timerId].LoadValue = 0;
97 pTmrHw[timerId].CurrentValue = 0xFFFFFFFF;
98 pTmrHw[timerId].Control = 0;
99 pTmrHw[timerId].BackgroundLoad = 0;
100
101 pTmrHw[timerId].Control |= tmrHw_CONTROL_32BIT;
102
103 if (pTmrHw[timerId].RawInterruptStatus) {
104 pTmrHw[timerId].InterruptClear = 0xFFFFFFFF;
105 }
106}
107
108
109
110
111
112
113
114
115
116
117static tmrHw_INTERVAL_t SetTimerPeriod(tmrHw_ID_t timerId,
118 tmrHw_INTERVAL_t msec
119) {
120 uint32_t scale = 0;
121 uint32_t count = 0;
122
123 if (timerId == 0 || timerId == 1) {
124 if (msec <= tmrHw_LOW_1_MAX_MILLISEC) {
125 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
126 scale = tmrHw_LOW_1_RESOLUTION_COUNT;
127 } else if (msec <= tmrHw_LOW_16_MAX_MILLISEC) {
128 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16;
129 scale = tmrHw_LOW_16_RESOLUTION_COUNT;
130 } else if (msec <= tmrHw_LOW_256_MAX_MILLISEC) {
131 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256;
132 scale = tmrHw_LOW_256_RESOLUTION_COUNT;
133 } else {
134 return 0;
135 }
136
137 count = msec * scale;
138
139 pTmrHw[timerId].LoadValue = count;
140 pTmrHw[timerId].BackgroundLoad = count;
141
142 } else if (timerId == 2 || timerId == 3) {
143 if (msec <= tmrHw_HIGH_1_MAX_MILLISEC) {
144 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
145 scale = tmrHw_HIGH_1_RESOLUTION_COUNT;
146 } else if (msec <= tmrHw_HIGH_16_MAX_MILLISEC) {
147 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16;
148 scale = tmrHw_HIGH_16_RESOLUTION_COUNT;
149 } else if (msec <= tmrHw_HIGH_256_MAX_MILLISEC) {
150 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256;
151 scale = tmrHw_HIGH_256_RESOLUTION_COUNT;
152 } else {
153 return 0;
154 }
155
156 count = msec * scale;
157
158 pTmrHw[timerId].LoadValue = count;
159 pTmrHw[timerId].BackgroundLoad = count;
160 }
161 return count / scale;
162}
163
164
165
166
167
168
169
170
171
172
173
174
175
176tmrHw_RATE_t tmrHw_setPeriodicTimerRate(tmrHw_ID_t timerId,
177 tmrHw_RATE_t rate
178) {
179 uint32_t resolution = 0;
180 uint32_t count = 0;
181 ResetTimer(timerId);
182
183
184 pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC;
185 pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT;
186
187 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
188
189 if (rate && (timerId == 0 || timerId == 1)) {
190 if (rate > tmrHw_LOW_RESOLUTION_CLOCK) {
191 return 0;
192 }
193 resolution = tmrHw_LOW_RESOLUTION_CLOCK;
194 } else if (rate && (timerId == 2 || timerId == 3)) {
195 if (rate > tmrHw_HIGH_RESOLUTION_CLOCK) {
196 return 0;
197 } else {
198 resolution = tmrHw_HIGH_RESOLUTION_CLOCK;
199 }
200 } else {
201 return 0;
202 }
203
204 count = resolution / rate;
205
206 pTmrHw[timerId].LoadValue = count;
207 pTmrHw[timerId].BackgroundLoad = count;
208
209 return resolution / count;
210}
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225tmrHw_INTERVAL_t tmrHw_setPeriodicTimerInterval(tmrHw_ID_t timerId,
226 tmrHw_INTERVAL_t msec
227) {
228 ResetTimer(timerId);
229
230
231 pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC;
232 pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT;
233
234 return SetTimerPeriod(timerId, msec);
235}
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250tmrHw_INTERVAL_t tmrHw_setOneshotTimerInterval(tmrHw_ID_t timerId,
251 tmrHw_INTERVAL_t msec
252) {
253 ResetTimer(timerId);
254
255
256 pTmrHw[timerId].Control |= tmrHw_CONTROL_PERIODIC;
257 pTmrHw[timerId].Control |= tmrHw_CONTROL_ONESHOT;
258
259 return SetTimerPeriod(timerId, msec);
260}
261
262
263
264
265
266
267
268
269
270
271
272tmrHw_RATE_t tmrHw_setFreeRunningTimer(tmrHw_ID_t timerId,
273 uint32_t divider
274) {
275 uint32_t scale = 0;
276
277 ResetTimer(timerId);
278
279 pTmrHw[timerId].Control &= ~tmrHw_CONTROL_PERIODIC;
280 pTmrHw[timerId].Control &= ~tmrHw_CONTROL_ONESHOT;
281
282 if (divider >= 64) {
283 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_256;
284 scale = 256;
285 } else if (divider >= 8) {
286 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_16;
287 scale = 16;
288 } else {
289 pTmrHw[timerId].Control |= tmrHw_CONTROL_PRESCALE_1;
290 scale = 1;
291 }
292
293 if (timerId == 0 || timerId == 1) {
294 return tmrHw_divide(tmrHw_LOW_RESOLUTION_CLOCK, scale);
295 } else if (timerId == 2 || timerId == 3) {
296 return tmrHw_divide(tmrHw_HIGH_RESOLUTION_CLOCK, scale);
297 }
298
299 return 0;
300}
301
302
303
304
305
306
307
308
309
310
311
312
313int tmrHw_startTimer(tmrHw_ID_t timerId
314) {
315 pTmrHw[timerId].Control |= tmrHw_CONTROL_TIMER_ENABLE;
316 return 0;
317}
318
319
320
321
322
323
324
325
326
327
328
329
330int tmrHw_stopTimer(tmrHw_ID_t timerId
331) {
332 pTmrHw[timerId].Control &= ~tmrHw_CONTROL_TIMER_ENABLE;
333 return 0;
334}
335
336
337
338
339
340
341
342
343
344
345
346uint32_t tmrHw_GetCurrentCount(tmrHw_ID_t timerId
347) {
348
349 switch (pTmrHw[timerId].Control & tmrHw_CONTROL_MODE_MASK) {
350 case tmrHw_CONTROL_FREE_RUNNING:
351 if (pTmrHw[timerId].CurrentValue) {
352 return tmrHw_MAX_COUNT - pTmrHw[timerId].CurrentValue;
353 }
354 break;
355 case tmrHw_CONTROL_PERIODIC:
356 case tmrHw_CONTROL_ONESHOT:
357 return pTmrHw[timerId].BackgroundLoad -
358 pTmrHw[timerId].CurrentValue;
359 }
360 return 0;
361}
362
363
364
365
366
367
368
369
370
371
372
373tmrHw_RATE_t tmrHw_getCountRate(tmrHw_ID_t timerId
374) {
375 uint32_t divider = 0;
376
377 switch (pTmrHw[timerId].Control & tmrHw_CONTROL_PRESCALE_MASK) {
378 case tmrHw_CONTROL_PRESCALE_1:
379 divider = 1;
380 break;
381 case tmrHw_CONTROL_PRESCALE_16:
382 divider = 16;
383 break;
384 case tmrHw_CONTROL_PRESCALE_256:
385 divider = 256;
386 break;
387 default:
388 tmrHw_ASSERT(0);
389 }
390
391 if (timerId == 0 || timerId == 1) {
392 return tmrHw_divide(tmrHw_LOW_RESOLUTION_CLOCK, divider);
393 } else {
394 return tmrHw_divide(tmrHw_HIGH_RESOLUTION_CLOCK, divider);
395 }
396 return 0;
397}
398
399
400
401
402
403
404
405
406
407
408
409void tmrHw_enableInterrupt(tmrHw_ID_t timerId
410) {
411 pTmrHw[timerId].Control |= tmrHw_CONTROL_INTERRUPT_ENABLE;
412}
413
414
415
416
417
418
419
420
421
422
423
424void tmrHw_disableInterrupt(tmrHw_ID_t timerId
425) {
426 pTmrHw[timerId].Control &= ~tmrHw_CONTROL_INTERRUPT_ENABLE;
427}
428
429
430
431
432
433
434
435
436
437
438
439
440
441void tmrHw_clearInterrupt(tmrHw_ID_t timerId
442) {
443 pTmrHw[timerId].InterruptClear = 0x1;
444}
445
446
447
448
449
450
451
452
453
454
455tmrHw_INTERRUPT_STATUS_e tmrHw_getInterruptStatus(tmrHw_ID_t timerId
456) {
457 if (pTmrHw[timerId].InterruptStatus) {
458 return tmrHw_INTERRUPT_STATUS_SET;
459 } else {
460 return tmrHw_INTERRUPT_STATUS_UNSET;
461 }
462}
463
464
465
466
467
468
469
470
471
472
473
474
475
476tmrHw_ID_t tmrHw_getInterruptSource(void
477) {
478 int i;
479
480 for (i = 0; i < tmrHw_TIMER_NUM_COUNT; i++) {
481 if (pTmrHw[i].InterruptStatus) {
482 return i;
483 }
484 }
485
486 return 0xFFFFFFFF;
487}
488
489
490
491
492
493
494
495
496
497
498void tmrHw_printDebugInfo(tmrHw_ID_t timerId,
499 int (*fpPrint) (const char *, ...)
500) {
501 (*fpPrint) ("Displaying register contents \n\n");
502 (*fpPrint) ("Timer %d: Load value 0x%X\n", timerId,
503 pTmrHw[timerId].LoadValue);
504 (*fpPrint) ("Timer %d: Background load value 0x%X\n", timerId,
505 pTmrHw[timerId].BackgroundLoad);
506 (*fpPrint) ("Timer %d: Control 0x%X\n", timerId,
507 pTmrHw[timerId].Control);
508 (*fpPrint) ("Timer %d: Interrupt clear 0x%X\n", timerId,
509 pTmrHw[timerId].InterruptClear);
510 (*fpPrint) ("Timer %d: Interrupt raw interrupt 0x%X\n", timerId,
511 pTmrHw[timerId].RawInterruptStatus);
512 (*fpPrint) ("Timer %d: Interrupt status 0x%X\n", timerId,
513 pTmrHw[timerId].InterruptStatus);
514}
515
516
517
518
519
520
521
522
523void tmrHw_udelay(tmrHw_ID_t timerId,
524 unsigned long usecs
525) {
526 tmrHw_RATE_t usec_tick_rate;
527 tmrHw_COUNT_t start_time;
528 tmrHw_COUNT_t delta_time;
529
530 start_time = tmrHw_GetCurrentCount(timerId);
531 usec_tick_rate = tmrHw_divide(tmrHw_getCountRate(timerId), 1000000);
532 delta_time = usecs * usec_tick_rate;
533
534
535 while (delta_time > (tmrHw_GetCurrentCount(timerId) - start_time))
536 ;
537}
538
539
540
541
542
543
544
545
546
547
548
549static int tmrHw_divide(int num, int denom)
550{
551 int r;
552 int t = 1;
553
554
555
556 while ((denom & 0x40000000) == 0) {
557 denom = denom << 1;
558 t = t << 1;
559 }
560
561
562 r = 0;
563
564 do {
565
566 if ((num - denom) >= 0) {
567
568 num = num - denom;
569 r = r + t;
570 }
571
572 denom = denom >> 1;
573 t = t >> 1;
574 } while (t != 0);
575 return r;
576}
577