1 | /** |
---|
2 | * @file timer.c |
---|
3 | * |
---|
4 | * GBA Timer driver. |
---|
5 | */ |
---|
6 | /* |
---|
7 | * RTEMS GBA BSP |
---|
8 | * |
---|
9 | * Copyright (c) 2002 by Jay Monkman <jtm@smoothsmoothie.com> |
---|
10 | * |
---|
11 | * Copyright (c) 2004 Markku Puro <markku.puro@kopteri.net> |
---|
12 | * |
---|
13 | * The license and distribution terms for this file may be |
---|
14 | * found in the file LICENSE in this distribution or at |
---|
15 | * http://www.rtems.org/license/LICENSE. |
---|
16 | * |
---|
17 | * |
---|
18 | * Notes: |
---|
19 | * This file manages the benchmark timer used by the RTEMS Timing Test |
---|
20 | * Suite. Each measured time period is demarcated by calls to |
---|
21 | * benchmark_timer_initialize() and benchmark_timer_read(). benchmark_timer_read() usually returns |
---|
22 | * the number of microseconds since benchmark_timer_initialize() exitted. |
---|
23 | * |
---|
24 | * It is important that the timer start/stop overhead be determined |
---|
25 | * when porting or modifying this code. |
---|
26 | */ |
---|
27 | |
---|
28 | #include <rtems.h> |
---|
29 | #include <bsp.h> |
---|
30 | #include <rtems/btimer.h> |
---|
31 | #include <bsp/irq.h> |
---|
32 | #include <gba.h> |
---|
33 | |
---|
34 | /* |
---|
35 | * Set up the timer hardware |
---|
36 | * 1 / 16.78Mhz => 59.595 ns |
---|
37 | * 64 / 16.78Mhz => 3.814 us |
---|
38 | * 256 / 16.78Mhz => 15.256 us |
---|
39 | * 1024 / 16.78Mhz => 61.025 us |
---|
40 | */ |
---|
41 | #define __TimePreScaler 1 |
---|
42 | #define __TickTime_ns ((1000000000L/__ClockFrequency)*__TimePreScaler) |
---|
43 | #define __TickTime_us ((1000000L/__ClockFrequency)*__TimePreScaler) |
---|
44 | |
---|
45 | #if (__TimePreScaler==1) |
---|
46 | #define GBA_TM0CNT_PS 0x0000 |
---|
47 | #elif (__TimePreScaler==64) |
---|
48 | #define GBA_TM0CNT_PS 0x0001 |
---|
49 | #elif (__TimePreScaler==256) |
---|
50 | #define GBA_TM0CNT_PS 0x0002 |
---|
51 | #elif (__TimePreScaler==1024) |
---|
52 | #define GBA_TM0CNT_PS 0x0003 |
---|
53 | #else |
---|
54 | #define GBA_TM0CNT_PS 0x0003 |
---|
55 | #endif |
---|
56 | |
---|
57 | bool benchmark_timer_find_average_overhead; |
---|
58 | |
---|
59 | /** |
---|
60 | * @brief benchmark_timer_initialize start TM0 and TM1 |
---|
61 | * |
---|
62 | * @param None |
---|
63 | * @return None |
---|
64 | */ |
---|
65 | void benchmark_timer_initialize( void ) |
---|
66 | { |
---|
67 | GBA_REG_TM1CNT = 0x0000; /* Stop Counters */ |
---|
68 | GBA_REG_TM0CNT = 0x0000; |
---|
69 | GBA_REG_TM1D = 0x0000; /* Reset Counters */ |
---|
70 | GBA_REG_TM0D = 0x0000; |
---|
71 | /* Start Counters */ |
---|
72 | GBA_REG_TM1CNT = 0x0084; /* Start Count Up timing */ |
---|
73 | GBA_REG_TM0CNT = (0x0080|GBA_TM0CNT_PS); /* Start Count */ |
---|
74 | } |
---|
75 | |
---|
76 | /* |
---|
77 | * The following controls the behavior of benchmark_timer_read(). |
---|
78 | * |
---|
79 | * AVG_OVEREHAD is the overhead for starting and stopping the timer. It |
---|
80 | * is usually deducted from the number returned. |
---|
81 | * |
---|
82 | * LEAST_VALID is the lowest number this routine should trust. Numbers |
---|
83 | * below this are "noise" and zero is returned. |
---|
84 | */ |
---|
85 | |
---|
86 | #define AVG_OVERHEAD 3 /**< It typically takes 3 microseconds */ |
---|
87 | #define LEAST_VALID 1 /**< Don't trust a clicks value lower than this */ |
---|
88 | |
---|
89 | /** |
---|
90 | * @brief benchmark_timer_read return timer countervalue in microseconds. |
---|
91 | * |
---|
92 | * Used in Timing Test Suite. |
---|
93 | * |
---|
94 | * @param None |
---|
95 | * @return Timer value in microseconds |
---|
96 | */ |
---|
97 | uint32_t benchmark_timer_read( void ) |
---|
98 | { |
---|
99 | uint32_t ticks; |
---|
100 | uint32_t total; |
---|
101 | |
---|
102 | /* Stop Counters */ |
---|
103 | GBA_REG_TM0CNT = 0x0000; |
---|
104 | GBA_REG_TM1CNT = 0x0000; |
---|
105 | /* Read Counters */ |
---|
106 | ticks = (GBA_REG_TM1D<<16) | GBA_REG_TM0D; |
---|
107 | if ( ticks < LEAST_VALID ) { |
---|
108 | return 0; /* below timer resolution */ |
---|
109 | } |
---|
110 | /* convert to uS */ |
---|
111 | total = ((ticks * __TickTime_ns) / 1000); |
---|
112 | if ( benchmark_timer_find_average_overhead == true ) { |
---|
113 | return total; /* in microseconds */ |
---|
114 | } |
---|
115 | else { |
---|
116 | if ( total < AVG_OVERHEAD ) { |
---|
117 | return 0; |
---|
118 | } |
---|
119 | return (total - AVG_OVERHEAD); |
---|
120 | } |
---|
121 | } |
---|
122 | |
---|
123 | /** |
---|
124 | * @brief Set benchmark_timer_find_average_overhead flag. |
---|
125 | * |
---|
126 | * Used in Timing Test Suite. |
---|
127 | * |
---|
128 | * @param find_flag bool find_flag |
---|
129 | * @return None |
---|
130 | */ |
---|
131 | void benchmark_timer_disable_subtracting_average_overhead(bool find_flag) |
---|
132 | { |
---|
133 | benchmark_timer_find_average_overhead = find_flag; |
---|
134 | } |
---|