OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [tick/] [tick.c] - Blame information for rev 98

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 90 jeremybenn
/* tick.c. Test of Or1ksim tick timer
2
 
3
   Copyright (C) 2005 György `nog' Jeney <nog@sdf.lonestar.org>
4
   Copyright (C) 2010 Embecosm Limited
5
 
6
   Contributor György `nog' Jeney <nog@sdf.lonestar.org>
7
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
8
 
9
   This file is part of OpenRISC 1000 Architectural Simulator.
10
 
11
   This program is free software; you can redistribute it and/or modify it
12
   under the terms of the GNU General Public License as published by the Free
13
   Software Foundation; either version 3 of the License, or (at your option)
14
   any later version.
15
 
16
   This program is distributed in the hope that it will be useful, but WITHOUT
17
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
19
   more details.
20
 
21
   You should have received a copy of the GNU General Public License along
22
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
23
 
24
/* ----------------------------------------------------------------------------
25
   This code is commented throughout for use with Doxygen.
26
   --------------------------------------------------------------------------*/
27
 
28
#include "spr-defs.h"
29
#include "support.h"
30
 
31
 
32
/*! Number of spurious interrupts we'll allow before properly disabling them */
33
#define MAX_SPURIOUS  5
34
 
35
/*! Convenience macro to check that a test has passed */
36
#define ASSERT(x, msg) ((x) ? printf ("Test succeeded %s\n", msg) : fail (msg))
37
 
38
/*! Convenience macro to check that a test has passed, but only print a
39
    message on failure. */
40
#define SILENT_ASSERT(x, msg) ((x) ?  : fail (msg))
41
 
42
/*! Convenience macros for accessing SPRs */
43
#define GET_TTMR() (mfspr (SPR_TTMR))
44
#define SET_TTMR(x) (mtspr (SPR_TTMR, x))
45
#define GET_TTCR() (mfspr (SPR_TTCR))
46
#define SET_TTCR(x) (mtspr (SPR_TTCR, x))
47
 
48
/*! Global count of number of times interrupt handler has been called  */
49
static volatile int tick_cnt = 0;
50
 
51
/*! Global flag to indicate if the TTMR_IP flag should be cleared */
52
static int clear_ip = 1;
53
 
54
 
55
/* --------------------------------------------------------------------------*/
56
/*!Report failure
57
 
58
  Terminate execution.
59
 
60
  @param[in] msg  Description of test which failed.                          */
61
/* --------------------------------------------------------------------------*/
62
static void
63
fail (char *msg)
64
{
65
  printf ("Test failed: %s\n", msg);
66
  report (0xeeeeeeee);
67
  exit (1);
68
 
69
}       /* fail () */
70
 
71
 
72
/* --------------------------------------------------------------------------*/
73
/*!Set a tick timer mode.
74
 
75
   All other bits and the period are masked
76
 
77
   @param[in] ttmr  The entire TTMR value.
78
   @param[in] mode  The new mode
79
 
80
   @return  The new TTMR with the mode set                                   */
81
/* --------------------------------------------------------------------------*/
82
static unsigned long int
83
set_mode (unsigned long int  ttmr,
84
          unsigned long int  mode)
85
{
86
  ttmr &= ~SPR_TTMR_M;
87
  ttmr |= mode & SPR_TTMR_M;
88
 
89
  return  ttmr;
90
 
91
}       /* set_mode () */
92
 
93
 
94
/* --------------------------------------------------------------------------*/
95
/*!Set a tick timer period.
96
 
97
   All other bits and the period are masked
98
 
99
   @param[in] ttmr    The entire TTMR value.
100
   @param[in] period  The new period
101
 
102
   @return  The new TTMR with the period set                                 */
103
/* --------------------------------------------------------------------------*/
104
static unsigned long int
105
set_period (unsigned long int  ttmr,
106
            unsigned long int  period)
107
{
108
  ttmr &= ~SPR_TTMR_PERIOD;
109
  ttmr |= period & SPR_TTMR_PERIOD;
110
 
111
  return  ttmr;
112
 
113
}       /* set_period () */
114
 
115
 
116
/* --------------------------------------------------------------------------*/
117
/*!Clear the mode register
118
 
119
   Period is zeroed, interrupt pending and enabled flags are cleared, disabled
120
   mode is set.
121
 
122
   @note  This function exists to allow for the disabled mode to be explicit,
123
          rather than assumed to be zero.
124
 
125
   @return  The new TTMR                                                     */
126
/* --------------------------------------------------------------------------*/
127
static unsigned long int
128
clear_ttmr ()
129
{
130
  unsigned long int  ttmr = SPR_TTMR_DI;
131
 
132
  SET_TTMR (ttmr);
133
 
134
  return  ttmr;
135
 
136
}       /* clear_ttmr () */
137
 
138
 
139
/* --------------------------------------------------------------------------*/
140
/*!Clear the count register
141
 
142
   Count is zeroed
143
 
144
   @return  The new TTCR                                                     */
145
/* --------------------------------------------------------------------------*/
146
static unsigned long int
147
clear_ttcr ()
148
{
149
  unsigned long int  ttcr = 0;
150
 
151
  SET_TTCR (ttcr);
152
 
153
  return  ttcr;
154
 
155
}       /* clear_ttcr () */
156
 
157
 
158
/* --------------------------------------------------------------------------*/
159
/*!Set a new timer.
160
 
161
   Convenience function for a common sequence
162
 
163
   @param[in] period  The period of the timer
164
   @param[in] mode    The timer mode
165
   @param[in] flags   Any falgs to set (usually IE)
166
 
167
   @return  The new value of TTMR                                            */
168
/* --------------------------------------------------------------------------*/
169
static unsigned long int
170
new_timer (unsigned long int  period,
171
           unsigned long int  mode,
172
           unsigned long int  flags)
173
{
174
  unsigned long int  ttmr;
175
 
176
  ttmr  = 0;
177
  ttmr  = set_period (ttmr, period);
178
  ttmr  = set_mode (ttmr, mode);
179
  ttmr |= flags;
180
 
181
  SET_TTMR (ttmr);
182
 
183
  return  ttmr;
184
 
185
}       /* new_timer () */
186
 
187
 
188
/* --------------------------------------------------------------------------*/
189
/*!Standard tick interrupt handler
190
 
191
  Up the count and clear the interrupt appropriately                        */
192
/* --------------------------------------------------------------------------*/
193
static void
194
tick_int (void)
195
{
196
  unsigned long int  ttmr = mfspr (SPR_TTMR);
197
 
198
  /* Make sure that the tick timer interrupt pending bit is set */
199
  SILENT_ASSERT (0 != (ttmr & SPR_TTMR_IP),
200
                 "IP bit not set in normal interrupt handler");
201
 
202
  /* One more interrupt handled */
203
  tick_cnt++;
204
 
205
  /* Clear interrupt (Write a 0 to SPR_TTMR_IP)
206
 
207
     If we programmed a one-shot timer, make sure to disable the interrupts,
208
     else we'd get a spurious interrupt */
209
  if (SPR_TTMR_SR == (ttmr & SPR_TTMR_M))
210
    {
211
      ttmr &= ~(SPR_TTMR_IP | SPR_TTMR_IE);
212
    }
213
  else
214
    {
215
      ttmr &= ~SPR_TTMR_IP;
216
    }
217
 
218
  mtspr (SPR_TTMR, ttmr);
219
 
220
}       /* tick_count () */
221
 
222
 
223
/* --------------------------------------------------------------------------*/
224
/*!Tick interrupt handler generting spurious interrupts
225
 
226
  If we have a one-shot timer set, then when we clear the interrupt (if a
227
  global flag allows), but leave the interrupt enabled we should get a
228
  spurious interrupt.
229
 
230
  Allow this to happen MAX_SPURIOUS times before disabling the interrupt.
231
 
232
  Up the count and clear the interrupt appropriately                        */
233
/* --------------------------------------------------------------------------*/
234
static void
235
tick_int_spurious (void)
236
{
237
  unsigned long int  ttmr = mfspr(SPR_TTMR);
238
 
239
  /* Make sure that the tick timer interrupt pending bit is set */
240
  SILENT_ASSERT (0 != (ttmr & SPR_TTMR_IP),
241
                 "IP bit not set in spurious interrupt handler");
242
 
243
  /* Clear interrupt if global flag allows it (Write a 0 to SPR_TTMR_IP) */
244
  if (clear_ip)
245
    {
246
      ttmr &= ~SPR_TTMR_IP;
247
      mtspr (SPR_TTMR, ttmr);
248
    }
249
 
250
  /* Allow MAX_SPURIOUS spurious spurious interrupt */
251
  if (++tick_cnt == MAX_SPURIOUS)
252
    {
253
      ttmr &= ~SPR_TTMR_IE;
254
      mtspr (SPR_TTMR, ttmr);
255
    }
256
}       /* tick_int_spurious () */
257
 
258
 
259
/* --------------------------------------------------------------------------*/
260
/*!Waste a little time
261
 
262
  We are waiting for TTCR to increment
263
 
264
  @note This is an entirely arbitrary period. In particular excessive use of
265
  printf in an interrupt handler can tie up cycles and cause TTCR not
266
  to increment in time.                                               */
267
/* --------------------------------------------------------------------------*/
268
static void
269
waste_time (void)
270
{
271
  int          i;
272
  volatile int x;
273
 
274
  for (i = 0; i < 50; i++)
275
    {
276
      x = i;
277
    }
278
}       /* waste_time () */
279
 
280
/* --------------------------------------------------------------------------*/
281
/*!Wait for a tick timer exception
282
 
283
  This occurs when the tick count goes up. Reset the count once the
284
  exception is received.                                                    */
285
/* --------------------------------------------------------------------------*/
286
/* Waits for a tick timer exception */
287
static void
288
wait_match (void)
289
{
290
  while (!tick_cnt)
291
    {
292
    }
293
 
294
  tick_cnt = 0;
295
 
296
}       /* wait_match () */
297
 
298
 
299
/* --------------------------------------------------------------------------*/
300
/*!Main program testing tick timer
301
 
302
  Tests all aspecst of tick timer behavior.
303
 
304
  @return  Return code from the program (always zero).                      */
305
/* --------------------------------------------------------------------------*/
306
int
307
main()
308
{
309
  unsigned long int  ttmr;
310
  unsigned long int  ttcr;
311
 
312
  /* Use normal interrupt handler */
313
  excpt_tick = (unsigned long)tick_int;
314
 
315
  /* Enable tick interrupt */
316
  mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_TEE);
317
 
318
  /* Clear interrupt pending and interrupt enabled, zero the period, set
319
     disabled mode and set count to zero. */
320
  ttmr = clear_ttmr ();
321
  ttcr = clear_ttcr ();
322
 
323
  /* Waste some time to check if the timer is really disabled */
324
  waste_time ();
325
 
326
  /* Timer is disabled and shouldn't count, TTCR should still be 0 */
327
  ttcr = GET_TTCR ();
328
  ASSERT (0 == ttcr, "Tick timer not counting while disabled");
329
 
330
  /* Start timer in continous running mode.  Enable timer interrupt and set
331
   * the period to 0x100 */
332
  ttmr = new_timer (0x100, SPR_TTMR_CR, SPR_TTMR_IE);
333
 
334
  /* Wait for the timer to count up to the match value, get the count
335
     register value. Then waste some time and check that couting has
336
     continued. */
337
  wait_match ();
338
  ttcr = GET_TTCR ();
339
  waste_time();
340
 
341
  /* The timer should have kept counting and our saved TTCR should not be the
342
   * same as the current ttcr */
343
  ASSERT (ttcr < GET_TTCR (),
344
          "Tick timer kept counting during continuous mode");
345
 
346
  /* Clear the mode register flags, zero the period and set disabled
347
     mode. Then get the count register which should be unaffected by this. */
348
  ttmr = clear_ttmr ();
349
  ttcr = GET_TTCR ();
350
 
351
  /* Restart the timer in continous run mode and the counter will keep
352
     going. There should be no interrupts, since we haven't enabled
353
     them. Waste some time to allow the counter to advance. */
354
  ttmr = set_mode (ttmr, SPR_TTMR_CR);
355
  SET_TTMR (ttmr);
356
  waste_time ();
357
 
358
  /* The timer should have carried on from what was SPR_TTCR when we started
359
     it. */
360
  ASSERT (ttcr < GET_TTCR (), "Tick timer continued counting after restart");
361
 
362
  /* Disable the timer and waste some time to check that the count does not
363
     advance */
364
  ttmr = clear_ttmr ();
365
  ttcr = GET_TTCR ();
366
  waste_time ();
367
 
368
  /* Timer should be disabled and should not have counted */
369
  ASSERT(ttcr == GET_TTCR (), "Tick timer counter stops when disabled");
370
 
371
  /* Start in single run mode with a count of 0x100. Run until the match is
372
     hit, then check that the counter does not advance further while wasting
373
     time. */
374
  ttcr = clear_ttcr ();
375
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
376
 
377
  wait_match();
378
  ttcr = GET_TTCR ();
379
  waste_time();
380
 
381
  /* The timer should have stoped and the counter advanced no further. */
382
  ASSERT (ttcr == GET_TTCR (), "Timer stopped after match");
383
 
384
  /* The counter should still indicate single run mode */
385
  ttmr = GET_TTMR ();
386
  ASSERT ((ttmr & SPR_TTMR_SR) == SPR_TTMR_SR,
387
          "Timer still indicating one-shot mode after match");
388
 
389
  /* Disable the timer, then start auto-restarting timer every 0x1000 ticks. */
390
  ttmr = clear_ttmr ();
391
  ttcr = clear_ttcr ();
392
  ttmr = new_timer (0x1000, SPR_TTMR_RT, SPR_TTMR_IE);
393
 
394
  /* Wait for two matches, then disable the timer. If this doesn't work the
395
     test will time out, so no ASSERT here. */
396
  wait_match();
397
  ttcr = GET_TTCR ();
398
  wait_match();
399
 
400
  /* Start a one-shot counter but keep interrupts disabled */
401
  ttmr = clear_ttmr ();
402
  ttcr = clear_ttcr ();
403
  ttmr = new_timer (0x100, SPR_TTMR_SR, 0);
404
 
405
  /* Wait for the counter to stop */
406
  while (GET_TTCR () != 0x100)
407
    {
408
    }
409
 
410
  /* Make sure the counter has actually stopped and there have been no more
411
     interrupts (neither tick count nor pending flag. */
412
  waste_time();
413
  ttmr = GET_TTMR ();
414
 
415
  ASSERT (GET_TTCR () == 0x100, "One-shot timer stopped");
416
  ASSERT (tick_cnt == 0, "No more interrupts after one-shot timer");
417
  ASSERT (SPR_TTMR_IP != (ttmr & SPR_TTMR_IP),
418
          "IP flag not set after one-shot timer");
419
 
420
  /* Start a perpetual counter but with no interrupts enabled while it is
421
     still counting. */
422
  ttmr = clear_ttmr ();
423
  ttcr = clear_ttcr ();
424
  ttmr = new_timer (0x100, SPR_TTMR_CR, 0);
425
 
426
  /* Wait until it reaches its count. */
427
  while(GET_TTCR () < 0x100)
428
    {
429
    }
430
 
431
  /* Waste some time and check the counter has carried on past its count and
432
     that there have bee no more interrupts nor interrupts pending. */
433
  waste_time();
434
 
435
  ttmr = GET_TTMR ();
436
  ttcr = GET_TTCR ();
437
 
438
  ASSERT (ttcr > 0x100, "Perptual timer kept counting");
439
  ASSERT (tick_cnt == 0, "No more interrupts during perpetual timer count");
440
  ASSERT (SPR_TTMR_IP != (ttmr & SPR_TTMR_IP),
441
          "IP flag not set during perpetual timer count");
442
 
443
  /* Disable the timer interrupt */
444
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_TEE);
445
 
446
  /* Set a one-shot timer, with the counter started at zero. */
447
  ttmr = clear_ttmr ();
448
  ttcr = clear_ttcr ();
449
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
450
 
451
  /* Wait for the interrupt pending bit to be set. */
452
  do
453
    {
454
      ttmr = GET_TTMR ();
455
    }
456
  while (0 == (ttmr & SPR_TTMR_IP));
457
 
458
  /* Give some time for a potential interrupt to occur */
459
  waste_time();
460
 
461
  /* No interrupt should have occured */
462
  ASSERT (tick_cnt == 0, "No interrupt when tick timer disabled");
463
 
464
  /* Enable tick interrupt */
465
  mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_TEE);
466
 
467
  /* Test Setting TTCR while counting. Set a period of 0x3000 but do not
468
     enable interrupts. */
469
  ttmr = clear_ttmr ();
470
  ttcr = clear_ttcr ();
471
  ttmr = new_timer (0x3000, SPR_TTMR_CR, 0);
472
 
473
  /* Wait for the count to reach 10 times our period. */
474
  while (GET_TTCR () < 0x30000)
475
    {
476
    }
477
 
478
  /* Waste some time and then reset the count to 0x50 */
479
  waste_time();
480
  SET_TTCR (0x50);
481
 
482
  /* Verify that after a short wait we have counted to more than 0x50, but
483
     less than 0x30000 */
484
  waste_time();
485
  ttcr = GET_TTCR ();
486
 
487
  ASSERT ((0x50 < ttcr) && (ttcr < 0x30000), "TTCR reset while counting");
488
 
489
  /* Disable the timer. Set the counter to a high value and start a single run
490
     timer with a low timer period. Demonstrate the counter wraps round and
491
     then triggers at the period. Need to reset the tick counter, since there
492
     may have been an interrupt during the previous period. */
493
  ttmr = clear_ttmr ();
494
  ttcr = 0x20000;
495
  SET_TTCR (ttcr);
496
 
497
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
498
 
499
  /* The counter should start counting from 0x20000 and wrap around to 0x100
500
   * causeing an interrupt. Check we keep on counting. */
501
  waste_time();
502
  ASSERT (GET_TTCR () > 0x20000, "Timer started counting from high value");
503
 
504
  /* If TTCR is greater than TTMR_PERIOD then the interrupt gets delivered after
505
     TTCR wraps around to 0 and counts to SPR_TTMR_PERIOD.
506
 
507
     Set up an auto-restart timer to wrap around. Reset the tick count,
508
     because it may have incremented since the last match. */
509
  ttmr = clear_ttmr ();
510
  ttcr = 0xffffc00;
511
  SET_TTCR (ttcr);
512
 
513
  tick_cnt = 0;
514
  ttmr = new_timer (0x10000, SPR_TTMR_RT, SPR_TTMR_IE);
515
 
516
  /* Wait for the trigger, then check that we have restarted. */
517
  wait_match();
518
  ttcr = GET_TTCR ();
519
 
520
  ASSERT (ttcr < 0x10000, "Auto-restart wrapped round");
521
 
522
  /* Test wrap around in continuous mode. Reset the tick count in case we
523
     have had another interrupt. */
524
  ttmr = clear_ttmr ();
525
  ttcr = 0xffffc00;
526
  SET_TTCR (ttcr);
527
 
528
  tick_cnt = 0;
529
  ttmr = new_timer (0x10000, SPR_TTMR_CR, SPR_TTMR_IE);
530
 
531
  /* Wait for trigger, then check that we have carried on counting. */
532
  wait_match();
533
  ttcr = GET_TTCR () & SPR_TTCR_PERIOD;
534
 
535
  ASSERT ((0x10000 < ttcr) && (ttcr < 0xffffc00),
536
          "Continuous mode wrapped round");
537
 
538
  /* Disable the timer and set up the special spurious interrupt handler, to
539
     check spurious interrupts occur as expected. */
540
  ttmr = clear_ttmr ();
541
  excpt_tick = (unsigned long)tick_int_spurious;
542
 
543
  /* Set up a disabled timer with a period of 0x100. */
544
  clear_ttcr ();
545
  ttmr = new_timer (0x100, SPR_TTMR_DI, SPR_TTMR_IE);
546
 
547
  /* Set up the count to match the period, and check that spurious interrupts
548
     are generated, even though the timer is disabled. */
549
  ttcr = 0x100;
550
  SET_TTCR (ttcr);
551
 
552
  while(tick_cnt != MAX_SPURIOUS)
553
    {
554
    }
555
 
556
  /* Check the count has not changed */
557
  ttcr = GET_TTCR ();
558
  ASSERT (0x100 == ttcr, "Spurious interrupts handled with matching period");
559
 
560
  /* Reset the tick count, then test setting TTCR first then TTMR */
561
  tick_cnt = 0;
562
  ttcr = 0x101;
563
  SET_TTCR (ttcr);
564
  ttmr = new_timer (0x101, SPR_TTMR_DI, SPR_TTMR_IE);
565
 
566
  while(tick_cnt != MAX_SPURIOUS)
567
    {
568
    }
569
 
570
  ttcr = GET_TTCR ();
571
  ASSERT (0x101 == ttcr, "Spurious interrupts handled after TTCR and TTMR");
572
 
573
  /* Set countinous counter, but make sure we never clear the TTMR_IP bit */
574
  tick_cnt = 0;
575
  clear_ip = 0;
576
 
577
  ttcr = clear_ttcr ();
578
  ttmr = new_timer (0x100, SPR_TTMR_CR, SPR_TTMR_IE);
579
 
580
  while(tick_cnt != MAX_SPURIOUS)
581
    {
582
    }
583
 
584
  /* If we get here everything worked. */
585
  report(0xdeaddead);
586
  return 0;
587
 
588
}       /* main () */
589
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.