1 |
27 |
unneback |
//=============================================================================
|
2 |
|
|
//
|
3 |
|
|
// external_timer.c - Cyclone Diagnostics
|
4 |
|
|
//
|
5 |
|
|
//=============================================================================
|
6 |
|
|
//####ECOSGPLCOPYRIGHTBEGIN####
|
7 |
|
|
// -------------------------------------------
|
8 |
|
|
// This file is part of eCos, the Embedded Configurable Operating System.
|
9 |
|
|
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
|
10 |
|
|
//
|
11 |
|
|
// eCos is free software; you can redistribute it and/or modify it under
|
12 |
|
|
// the terms of the GNU General Public License as published by the Free
|
13 |
|
|
// Software Foundation; either version 2 or (at your option) any later version.
|
14 |
|
|
//
|
15 |
|
|
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
|
16 |
|
|
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
17 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
18 |
|
|
// for more details.
|
19 |
|
|
//
|
20 |
|
|
// You should have received a copy of the GNU General Public License along
|
21 |
|
|
// with eCos; if not, write to the Free Software Foundation, Inc.,
|
22 |
|
|
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
23 |
|
|
//
|
24 |
|
|
// As a special exception, if other files instantiate templates or use macros
|
25 |
|
|
// or inline functions from this file, or you compile this file and link it
|
26 |
|
|
// with other works to produce a work based on this file, this file does not
|
27 |
|
|
// by itself cause the resulting work to be covered by the GNU General Public
|
28 |
|
|
// License. However the source code for this file must still be made available
|
29 |
|
|
// in accordance with section (3) of the GNU General Public License.
|
30 |
|
|
//
|
31 |
|
|
// This exception does not invalidate any other reasons why a work based on
|
32 |
|
|
// this file might be covered by the GNU General Public License.
|
33 |
|
|
//
|
34 |
|
|
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
|
35 |
|
|
// at http://sources.redhat.com/ecos/ecos-license/
|
36 |
|
|
// -------------------------------------------
|
37 |
|
|
//####ECOSGPLCOPYRIGHTEND####
|
38 |
|
|
//=============================================================================
|
39 |
|
|
//#####DESCRIPTIONBEGIN####
|
40 |
|
|
//
|
41 |
|
|
// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden
|
42 |
|
|
// Contributors:
|
43 |
|
|
// Date: 2001-01-25
|
44 |
|
|
// Purpose:
|
45 |
|
|
// Description:
|
46 |
|
|
//
|
47 |
|
|
//####DESCRIPTIONEND####
|
48 |
|
|
//
|
49 |
|
|
//===========================================================================*/
|
50 |
|
|
|
51 |
|
|
#include <redboot.h>
|
52 |
|
|
#include <cyg/hal/hal_iop310.h> // Hardware definitions
|
53 |
|
|
#include <cyg/hal/hal_intr.h> // Interrupt names
|
54 |
|
|
#include "iq80310.h"
|
55 |
|
|
#include "test_menu.h"
|
56 |
|
|
|
57 |
|
|
extern int enable_external_interrupt (int int_id);
|
58 |
|
|
extern int disable_external_interrupt (int int_id);
|
59 |
|
|
extern int isr_connect(int int_num, void (*handler)(int), int arg);
|
60 |
|
|
extern int isr_disconnect(int int_num);
|
61 |
|
|
extern char xgetchar(void);
|
62 |
|
|
|
63 |
|
|
volatile int timer_ticks;
|
64 |
|
|
|
65 |
|
|
/* interrupt handler for the PAL-based external timer */
|
66 |
|
|
void ext_timer_handler (int arg)
|
67 |
|
|
{
|
68 |
|
|
/* increment tick counter */
|
69 |
|
|
timer_ticks++;
|
70 |
|
|
|
71 |
|
|
/* to clear the timer interrupt, clear the timer interrupt
|
72 |
|
|
enable, then re-set the int. enable bit */
|
73 |
|
|
/* 01/05/01 jwf */
|
74 |
|
|
/* _restart_tmr(); */
|
75 |
|
|
|
76 |
|
|
EXT_TIMER_INT_DISAB();
|
77 |
|
|
EXT_TIMER_INT_ENAB();
|
78 |
|
|
|
79 |
|
|
return;
|
80 |
|
|
}
|
81 |
|
|
|
82 |
|
|
|
83 |
|
|
/* timer count must be written 8 bits at a time */
|
84 |
|
|
void write_timer_count (UINT32 count)
|
85 |
|
|
{
|
86 |
|
|
UINT8 cnt_word;
|
87 |
|
|
|
88 |
|
|
/* first ensure that there are only 22 bits of count data */
|
89 |
|
|
count &= 0x003fffff;
|
90 |
|
|
|
91 |
|
|
/* grab least significant 8 bits of timer value */
|
92 |
|
|
cnt_word = (UINT8)(count & 0xff);
|
93 |
|
|
*TIMER_LA0_REG_ADDR = cnt_word;
|
94 |
|
|
|
95 |
|
|
/* grab next 8 bits of timer value */
|
96 |
|
|
count = (count >> 8);
|
97 |
|
|
cnt_word = (UINT8)(count & 0xff);
|
98 |
|
|
*TIMER_LA1_REG_ADDR = cnt_word;
|
99 |
|
|
|
100 |
|
|
/* grab last 6 bits of timer value */
|
101 |
|
|
count = (count >> 8);
|
102 |
|
|
cnt_word = (UINT8)(count & 0x3f);
|
103 |
|
|
*TIMER_LA2_REG_ADDR = cnt_word;
|
104 |
|
|
|
105 |
|
|
return;
|
106 |
|
|
}
|
107 |
|
|
|
108 |
|
|
/* timer must be read 6 bits at a time */
|
109 |
|
|
UINT32 read_timer_count (void)
|
110 |
|
|
{
|
111 |
|
|
UINT8 timer_cnt0, timer_cnt1, timer_cnt2, timer_cnt3;
|
112 |
|
|
UINT8 timer_byte0, timer_byte1, timer_byte2;
|
113 |
|
|
UINT32 count;
|
114 |
|
|
|
115 |
|
|
/* first read latches the count */
|
116 |
|
|
timer_cnt0 = (*TIMER_LA0_REG_ADDR & TIMER_COUNT_MASK);
|
117 |
|
|
timer_cnt1 = (*TIMER_LA1_REG_ADDR & TIMER_COUNT_MASK);
|
118 |
|
|
timer_cnt2 = (*TIMER_LA2_REG_ADDR & TIMER_COUNT_MASK);
|
119 |
|
|
timer_cnt3 = (*TIMER_LA3_REG_ADDR & 0xf); /* only 4 bits in most sig. */
|
120 |
|
|
|
121 |
|
|
/* now build up the count value */
|
122 |
|
|
timer_byte0 = (((timer_cnt0 & 0x20) >> 1) | (timer_cnt0 & 0x1f));
|
123 |
|
|
timer_byte1 = (((timer_cnt1 & 0x20) >> 1) | (timer_cnt1 & 0x1f));
|
124 |
|
|
timer_byte2 = (((timer_cnt2 & 0x20) >> 1) | (timer_cnt2 & 0x1f));
|
125 |
|
|
|
126 |
|
|
count = ((timer_cnt3 << 18) | (timer_byte2 << 12) | (timer_byte1 << 6) |
|
127 |
|
|
timer_byte0);
|
128 |
|
|
|
129 |
|
|
return (count);
|
130 |
|
|
}
|
131 |
|
|
|
132 |
|
|
|
133 |
|
|
/* 12/18/00 jwf */
|
134 |
|
|
/* This test reads the timer la0-la3 registers on the fly while an up count is in progress. */
|
135 |
|
|
void counter_test (void)
|
136 |
|
|
{
|
137 |
|
|
/* ff max, b0-b7, b0-b7 contain timer load data */
|
138 |
|
|
unsigned char TmrLa0Write=0xff;
|
139 |
|
|
/* ff max, b8-b15, b0-b7 contain timer load data */
|
140 |
|
|
unsigned char TmrLa1Write=0xff;
|
141 |
|
|
/* 3f max, b16-b21, b0-b5 contain timer load data */
|
142 |
|
|
unsigned char TmrLa2Write=0x3f;
|
143 |
|
|
unsigned char TmrLa3Write=0x00; /* x - don't care */
|
144 |
|
|
unsigned long int TmrLa0Read=0;
|
145 |
|
|
unsigned long int TmrLa1Read=0;
|
146 |
|
|
unsigned long int TmrLa2Read=0;
|
147 |
|
|
unsigned long int TmrLa3Read=0;
|
148 |
|
|
unsigned long int temp3=0;
|
149 |
|
|
unsigned long int temp4=0;
|
150 |
|
|
unsigned long int CntInit=0;
|
151 |
|
|
unsigned long int CurrentCount;
|
152 |
|
|
unsigned long int LastCount = 0;
|
153 |
|
|
unsigned long int LastLastCount = 0;
|
154 |
|
|
char Error = FALSE;
|
155 |
|
|
unsigned long int sample;
|
156 |
|
|
unsigned long int index;
|
157 |
|
|
const int MAX_N_PASSES = 10; /* N times the counter shall wrap around */
|
158 |
|
|
/* N samples to cover the full range of count,
|
159 |
|
|
0x3fffff/0x40 = 0xffff <--> 65535d, use 65536 to guarantee
|
160 |
|
|
a counter wrap around occurs */
|
161 |
|
|
const unsigned long int MAX_N_SAMPLES = 65536;
|
162 |
|
|
/* allocate 4 bytes per sample for a 0x0 - 0x3fffff count range to
|
163 |
|
|
hold contents of registers LA0-LA3 */
|
164 |
|
|
unsigned long int MAX_N_SIZE = MAX_N_PASSES * MAX_N_SAMPLES * 4;
|
165 |
|
|
unsigned char *data;
|
166 |
|
|
|
167 |
|
|
// Arbitrarily pick a spot in memory.
|
168 |
|
|
// RedBoot won't ever use more than 1MB.
|
169 |
|
|
data = (unsigned char *) MEMBASE_DRAM + (1*1024*1024);
|
170 |
|
|
|
171 |
|
|
if (data != NULL) {
|
172 |
|
|
printf("Allocated %d bytes\n", MAX_N_SIZE);
|
173 |
|
|
|
174 |
|
|
/* load control data to disable timer enable b0=0 and timer disable
|
175 |
|
|
interrupt b1=0, write to timer enable port */
|
176 |
|
|
EXT_TIMER_INT_DISAB();
|
177 |
|
|
EXT_TIMER_CNT_DISAB();
|
178 |
|
|
|
179 |
|
|
/* write timer la0 port count data */
|
180 |
|
|
*TIMER_LA0_REG_ADDR = TmrLa0Write;
|
181 |
|
|
|
182 |
|
|
/* write timer la1 port count data */
|
183 |
|
|
*TIMER_LA1_REG_ADDR = TmrLa1Write;
|
184 |
|
|
|
185 |
|
|
/* write timer la2 port count data */
|
186 |
|
|
*TIMER_LA2_REG_ADDR = TmrLa2Write;
|
187 |
|
|
|
188 |
|
|
/* write timer la3 port count data */
|
189 |
|
|
*TIMER_LA3_REG_ADDR = TmrLa3Write;
|
190 |
|
|
|
191 |
|
|
CntInit = TmrLa0Write + (TmrLa1Write << 8 ) + (TmrLa2Write << 16 );
|
192 |
|
|
|
193 |
|
|
printf("Timer load data = 0x%x\n", CntInit );
|
194 |
|
|
|
195 |
|
|
printf("Reading Timer registers LA0-LA3 on the fly...\n");
|
196 |
|
|
|
197 |
|
|
/* load control data to enable timer counter and write control data
|
198 |
|
|
to start the counter */
|
199 |
|
|
EXT_TIMER_CNT_ENAB();
|
200 |
|
|
|
201 |
|
|
/* sample the timer counter on the fly and store LA0-3 register
|
202 |
|
|
contents in an array */
|
203 |
|
|
/* read LSB register first to latch 22 bits data into four la
|
204 |
|
|
registers */
|
205 |
|
|
for (sample=0, index=0; sample < (MAX_N_PASSES * MAX_N_SAMPLES); sample++, index += 4) {
|
206 |
|
|
/* bits 0 1 2 3 4 6 contain count data b0-b5 */
|
207 |
|
|
data[index] = *TIMER_LA0_REG_ADDR;
|
208 |
|
|
/* bits 0 1 2 3 4 6 contain count data b6-b11 */
|
209 |
|
|
data[index+1] = *TIMER_LA1_REG_ADDR;
|
210 |
|
|
/* bits 0 1 2 3 4 6 contain count data b12-b17 */
|
211 |
|
|
data[index+2] = *TIMER_LA2_REG_ADDR;
|
212 |
|
|
/* bits 0 1 2 3 contain count data b18-b21 */
|
213 |
|
|
data[index+3] = *TIMER_LA3_REG_ADDR;
|
214 |
|
|
}
|
215 |
|
|
|
216 |
|
|
printf("Checking for errors...\n" );
|
217 |
|
|
|
218 |
|
|
/* Assemble and check recorded register data for errors */
|
219 |
|
|
for (sample=0, index=0; sample < (MAX_N_PASSES * MAX_N_SAMPLES) ;sample++, index += 4) {
|
220 |
|
|
/* Assembles counter data that was read on the fly */
|
221 |
|
|
/* xbxbbbbb */
|
222 |
|
|
/* 01000000 = 0x40 */
|
223 |
|
|
/* 00011111 = 0x1F */
|
224 |
|
|
data[index] &= 0x7f; /* mask all unused bits */
|
225 |
|
|
temp3=data[index];
|
226 |
|
|
temp4=data[index];
|
227 |
|
|
temp3 &= 0x40; /* isolate bit 6 */
|
228 |
|
|
temp3 = temp3 >> 1; /* shift bit 6 to bit 5 */
|
229 |
|
|
temp4 &= 0x1f; /* isolate bits 0-4 */
|
230 |
|
|
TmrLa0Read = temp3 + temp4;
|
231 |
|
|
|
232 |
|
|
data[index+1] &= 0x7f; /* mask all unused bits */
|
233 |
|
|
temp3=data[index+1];
|
234 |
|
|
temp4=data[index+1];
|
235 |
|
|
temp3 &= 0x40; /* isolate bit 6 */
|
236 |
|
|
temp3 = temp3 >> 1; /* shift bit 6 to bit 5 */
|
237 |
|
|
temp4 &= 0x1f; /* isolate bits 0-4 */
|
238 |
|
|
TmrLa1Read = temp3 + temp4;
|
239 |
|
|
|
240 |
|
|
data[index+2] &= 0x7f; /* mask all unused bits */
|
241 |
|
|
temp3=data[index+2];
|
242 |
|
|
temp4=data[index+2];
|
243 |
|
|
temp3 &= 0x40; /* isolate bit 6 */
|
244 |
|
|
temp3 = temp3 >> 1; /* shift bit 6 to bit 5 */
|
245 |
|
|
temp4 &= 0x1f; /* isolate bits 0-4 */
|
246 |
|
|
TmrLa2Read = temp3 + temp4;
|
247 |
|
|
|
248 |
|
|
data[index+3] &= 0x0f; /* mask all unused bits */
|
249 |
|
|
TmrLa3Read = data[index+3];
|
250 |
|
|
|
251 |
|
|
/* sum timer count data */
|
252 |
|
|
CurrentCount = TmrLa0Read + (TmrLa1Read << 6)
|
253 |
|
|
+ (TmrLa2Read << 12) + (TmrLa3Read << 18);
|
254 |
|
|
|
255 |
|
|
if (sample == 0) {
|
256 |
|
|
LastLastCount = 0;
|
257 |
|
|
LastCount = CurrentCount;
|
258 |
|
|
}
|
259 |
|
|
|
260 |
|
|
if (sample == 1) {
|
261 |
|
|
LastLastCount = LastCount;
|
262 |
|
|
LastCount = CurrentCount;
|
263 |
|
|
}
|
264 |
|
|
|
265 |
|
|
/* check for data anomaly, is count value read 2 samples ago
|
266 |
|
|
greater than the count value read 1 sample ago */
|
267 |
|
|
if (sample > 1) {
|
268 |
|
|
/* print error value (LastCount) positioned in between the
|
269 |
|
|
previous and current values */
|
270 |
|
|
if (LastLastCount > LastCount && CurrentCount > LastLastCount) {
|
271 |
|
|
/* show error only, do not show a counter wrap around
|
272 |
|
|
reading, print error value (LastCount) positioned in
|
273 |
|
|
between the previous and current values */
|
274 |
|
|
printf("0x%x 0x%x 0x%x \n", LastLastCount, LastCount, CurrentCount );
|
275 |
|
|
Error = TRUE; /* set flag to error condition */
|
276 |
|
|
}
|
277 |
|
|
LastLastCount = LastCount;
|
278 |
|
|
LastCount = CurrentCount;
|
279 |
|
|
}
|
280 |
|
|
}
|
281 |
|
|
/* load control data to stop timer and reset timer interrupt */
|
282 |
|
|
EXT_TIMER_CNT_DISAB();
|
283 |
|
|
} else
|
284 |
|
|
printf( "Cannot allocate memory.\n" );
|
285 |
|
|
|
286 |
|
|
if (Error == TRUE)
|
287 |
|
|
printf("Timer LA0-3 register read test FAILED.\n");
|
288 |
|
|
else
|
289 |
|
|
printf("Timer LA0-3 register read test PASSED.\n");
|
290 |
|
|
}
|
291 |
|
|
|
292 |
|
|
|
293 |
|
|
/* initialize timer for diagnostic use */
|
294 |
|
|
void init_external_timer(void)
|
295 |
|
|
{
|
296 |
|
|
#if 0
|
297 |
|
|
/* disable timer in case it was running */
|
298 |
|
|
EXT_TIMER_INT_DISAB();
|
299 |
|
|
EXT_TIMER_CNT_DISAB();
|
300 |
|
|
|
301 |
|
|
timer_ticks = 0;
|
302 |
|
|
|
303 |
|
|
/* connect the timer ISR */
|
304 |
|
|
isr_connect (TIMER_INT_ID, ext_timer_handler, 0);
|
305 |
|
|
|
306 |
|
|
/* enable the external interrupt */
|
307 |
|
|
if (enable_external_interrupt(TIMER_INT_ID) != OK)
|
308 |
|
|
printf("ERROR enabling EXT TIMER interrupt!\n");
|
309 |
|
|
#else
|
310 |
|
|
hal_clock_initialize(CYGNUM_HAL_RTC_PERIOD);
|
311 |
|
|
#endif
|
312 |
|
|
|
313 |
|
|
}
|
314 |
|
|
|
315 |
|
|
|
316 |
|
|
/* uninitialize timer after diagnostics */
|
317 |
|
|
void uninit_external_timer(void)
|
318 |
|
|
{
|
319 |
|
|
#if 0
|
320 |
|
|
/* disable timer */
|
321 |
|
|
EXT_TIMER_INT_DISAB();
|
322 |
|
|
EXT_TIMER_CNT_DISAB();
|
323 |
|
|
|
324 |
|
|
/* disable and disconnect timer interrupts */
|
325 |
|
|
disable_external_interrupt(TIMER_INT_ID);
|
326 |
|
|
isr_disconnect (TIMER_INT_ID);
|
327 |
|
|
#endif
|
328 |
|
|
}
|
329 |
|
|
|
330 |
|
|
|
331 |
|
|
/* 02/02/01 jwf */
|
332 |
|
|
/* delay_ms - delay specified number of milliseconds */
|
333 |
|
|
void delay_ms(int num_ms)
|
334 |
|
|
{
|
335 |
|
|
HAL_DELAY_US(num_ms * 1000);
|
336 |
|
|
}
|
337 |
|
|
|
338 |
|
|
|
339 |
|
|
/* test the 32 bit timer inside the CPLD, U17 */
|
340 |
|
|
void timer_test (MENU_ARG arg)
|
341 |
|
|
{
|
342 |
|
|
volatile int i;
|
343 |
|
|
UINT32 count;
|
344 |
|
|
|
345 |
|
|
/***** Perform 10 second count at 100 ticks/sec ****/
|
346 |
|
|
|
347 |
|
|
/* for the test we will setup the timer to generate a 10msec tick */
|
348 |
|
|
count = EXT_TIMER_10MSEC_COUNT;
|
349 |
|
|
|
350 |
|
|
/* write the initial count to the timer */
|
351 |
|
|
write_timer_count (count);
|
352 |
|
|
|
353 |
|
|
/* enable the interrupt at the timer */
|
354 |
|
|
EXT_TIMER_INT_ENAB();
|
355 |
|
|
|
356 |
|
|
/* enable the timer to count */
|
357 |
|
|
EXT_TIMER_CNT_ENAB();
|
358 |
|
|
|
359 |
|
|
printf ("Counting at %d Ticks Per Second.\n", TICKS_10MSEC);
|
360 |
|
|
printf ("Numbers should appear on 1 second increments...\n");
|
361 |
|
|
|
362 |
|
|
for (i = 0; i < 10; i++) {
|
363 |
|
|
while (timer_ticks < TICKS_10MSEC)
|
364 |
|
|
;
|
365 |
|
|
printf ("%d ", i);
|
366 |
|
|
timer_ticks = 0;
|
367 |
|
|
}
|
368 |
|
|
|
369 |
|
|
printf ("\nDone\n\n");
|
370 |
|
|
|
371 |
|
|
/* disable timer */
|
372 |
|
|
EXT_TIMER_INT_DISAB();
|
373 |
|
|
EXT_TIMER_CNT_DISAB();
|
374 |
|
|
|
375 |
|
|
|
376 |
|
|
/***** Perform 10 second count at 200 ticks/sec ****/
|
377 |
|
|
|
378 |
|
|
count = EXT_TIMER_5MSEC_COUNT;
|
379 |
|
|
write_timer_count (count);
|
380 |
|
|
|
381 |
|
|
timer_ticks = 0;
|
382 |
|
|
|
383 |
|
|
/* enable the interrupt at the timer */
|
384 |
|
|
EXT_TIMER_INT_ENAB();
|
385 |
|
|
|
386 |
|
|
/* enable the timer to count */
|
387 |
|
|
EXT_TIMER_CNT_ENAB();
|
388 |
|
|
|
389 |
|
|
printf ("Counting at %d Ticks Per Second.\n", TICKS_5MSEC);
|
390 |
|
|
printf ("Numbers should appear on 1 second increments...\n");
|
391 |
|
|
|
392 |
|
|
for (i = 0; i < 10; i++) {
|
393 |
|
|
while (timer_ticks < TICKS_5MSEC)
|
394 |
|
|
;
|
395 |
|
|
printf ("%d ", i);
|
396 |
|
|
timer_ticks = 0;
|
397 |
|
|
}
|
398 |
|
|
|
399 |
|
|
printf ("\nDone\n\n");
|
400 |
|
|
|
401 |
|
|
/* disable timer */
|
402 |
|
|
EXT_TIMER_INT_DISAB();
|
403 |
|
|
EXT_TIMER_CNT_DISAB();
|
404 |
|
|
|
405 |
|
|
/* 12/18/00 jwf */
|
406 |
|
|
uninit_external_timer(); /* disable interrupt */
|
407 |
|
|
counter_test();
|
408 |
|
|
init_external_timer(); /* enable interrupt */
|
409 |
|
|
|
410 |
|
|
printf("\nExternal Timer Test Done\n");
|
411 |
|
|
|
412 |
|
|
/* 12/18/00 jwf */
|
413 |
|
|
printf("\n\nStrike <CR> to exit this test." );
|
414 |
|
|
while (xgetchar() != 0x0d);
|
415 |
|
|
|
416 |
|
|
return;
|
417 |
|
|
|
418 |
|
|
} /* end timer_test() */
|
419 |
|
|
|
420 |
|
|
|