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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [or1ksim/] [testsuite/] [test-code-or1k/] [tick/] [tick.c] - Diff between revs 458 and 538

Only display areas with differences | Details | Blame | View Log

Rev 458 Rev 538
/* tick.c. Test of Or1ksim tick timer
/* tick.c. Test of Or1ksim tick timer
 
 
   Copyright (C) 2005 György `nog' Jeney <nog@sdf.lonestar.org>
   Copyright (C) 2005 György `nog' Jeney <nog@sdf.lonestar.org>
   Copyright (C) 2010 Embecosm Limited
   Copyright (C) 2010 Embecosm Limited
 
 
   Contributor György `nog' Jeney <nog@sdf.lonestar.org>
   Contributor György `nog' Jeney <nog@sdf.lonestar.org>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
 
 
   This file is part of OpenRISC 1000 Architectural Simulator.
   This file is part of OpenRISC 1000 Architectural Simulator.
 
 
   This program is free software; you can redistribute it and/or modify it
   This program is free software; you can redistribute it and/or modify it
   under the terms of the GNU General Public License as published by the Free
   under the terms of the GNU General Public License as published by the Free
   Software Foundation; either version 3 of the License, or (at your option)
   Software Foundation; either version 3 of the License, or (at your option)
   any later version.
   any later version.
 
 
   This program is distributed in the hope that it will be useful, but WITHOUT
   This program is distributed in the hope that it will be useful, but WITHOUT
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
   more details.
   more details.
 
 
   You should have received a copy of the GNU General Public License along
   You should have received a copy of the GNU General Public License along
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
   with this program.  If not, see <http:  www.gnu.org/licenses/>.  */
 
 
/* ----------------------------------------------------------------------------
/* ----------------------------------------------------------------------------
   This code is commented throughout for use with Doxygen.
   This code is commented throughout for use with Doxygen.
   --------------------------------------------------------------------------*/
   --------------------------------------------------------------------------*/
 
 
#include "spr-defs.h"
#include "spr-defs.h"
#include "support.h"
#include "support.h"
 
 
 
/*! Whether to perform spurious interrupt test */
 
#define DO_SPURIOUS_INT_TEST 0
 
 
/*! Number of spurious interrupts we'll allow before properly disabling them */
/*! Number of spurious interrupts we'll allow before properly disabling them */
#define MAX_SPURIOUS  5
#define MAX_SPURIOUS  5
 
 
/*! Convenience macro to check that a test has passed */
/*! Convenience macro to check that a test has passed */
#define ASSERT(x, msg) ((x) ? printf ("Test succeeded %s\n", msg) : fail (msg))
#define ASSERT(x, msg) ((x) ? printf ("Test succeeded %s\n", msg) : fail (msg))
 
 
/*! Convenience macro to check that a test has passed, but only print a
/*! Convenience macro to check that a test has passed, but only print a
    message on failure. */
    message on failure. */
#define SILENT_ASSERT(x, msg) ((x) ?  : fail (msg))
#define SILENT_ASSERT(x, msg) ((x) ?  : fail (msg))
 
 
/*! Convenience macros for accessing SPRs */
/*! Convenience macros for accessing SPRs */
#define GET_TTMR() (mfspr (SPR_TTMR))
#define GET_TTMR() (mfspr (SPR_TTMR))
#define SET_TTMR(x) (mtspr (SPR_TTMR, x))
#define SET_TTMR(x) (mtspr (SPR_TTMR, x))
#define GET_TTCR() (mfspr (SPR_TTCR))
#define GET_TTCR() (mfspr (SPR_TTCR))
#define SET_TTCR(x) (mtspr (SPR_TTCR, x))
#define SET_TTCR(x) (mtspr (SPR_TTCR, x))
 
 
/*! Global count of number of times interrupt handler has been called  */
/*! Global count of number of times interrupt handler has been called  */
static volatile int tick_cnt = 0;
static volatile int tick_cnt = 0;
 
 
 
#if DO_SPURIOUS_INT_TEST==1
/*! Global flag to indicate if the TTMR_IP flag should be cleared */
/*! Global flag to indicate if the TTMR_IP flag should be cleared */
static int clear_ip = 1;
static int clear_ip = 1;
 
#endif
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Report failure
/*!Report failure
 
 
  Terminate execution.
  Terminate execution.
 
 
  @param[in] msg  Description of test which failed.                          */
  @param[in] msg  Description of test which failed.                          */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
fail (char *msg)
fail (char *msg)
{
{
  printf ("Test failed: %s\n", msg);
  printf ("Test failed: %s\n", msg);
  report (0xeeeeeeee);
  report (0xeeeeeeee);
  exit (1);
  exit (1);
 
 
}       /* fail () */
}       /* fail () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Set a tick timer mode.
/*!Set a tick timer mode.
 
 
   All other bits and the period are masked
   All other bits and the period are masked
 
 
   @param[in] ttmr  The entire TTMR value.
   @param[in] ttmr  The entire TTMR value.
   @param[in] mode  The new mode
   @param[in] mode  The new mode
 
 
   @return  The new TTMR with the mode set                                   */
   @return  The new TTMR with the mode set                                   */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long int
static unsigned long int
set_mode (unsigned long int  ttmr,
set_mode (unsigned long int  ttmr,
          unsigned long int  mode)
          unsigned long int  mode)
{
{
  ttmr &= ~SPR_TTMR_M;
  ttmr &= ~SPR_TTMR_M;
  ttmr |= mode & SPR_TTMR_M;
  ttmr |= mode & SPR_TTMR_M;
 
 
  return  ttmr;
  return  ttmr;
 
 
}       /* set_mode () */
}       /* set_mode () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Set a tick timer period.
/*!Set a tick timer period.
 
 
   All other bits and the period are masked
   All other bits and the period are masked
 
 
   @param[in] ttmr    The entire TTMR value.
   @param[in] ttmr    The entire TTMR value.
   @param[in] period  The new period
   @param[in] period  The new period
 
 
   @return  The new TTMR with the period set                                 */
   @return  The new TTMR with the period set                                 */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long int
static unsigned long int
set_period (unsigned long int  ttmr,
set_period (unsigned long int  ttmr,
            unsigned long int  period)
            unsigned long int  period)
{
{
  ttmr &= ~SPR_TTMR_PERIOD;
  ttmr &= ~SPR_TTMR_TP;
  ttmr |= period & SPR_TTMR_PERIOD;
  ttmr |= period & SPR_TTMR_TP;
 
 
  return  ttmr;
  return  ttmr;
 
 
}       /* set_period () */
}       /* set_period () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Clear the mode register
/*!Clear the mode register
 
 
   Period is zeroed, interrupt pending and enabled flags are cleared, disabled
   Period is zeroed, interrupt pending and enabled flags are cleared, disabled
   mode is set.
   mode is set.
 
 
   @note  This function exists to allow for the disabled mode to be explicit,
   @note  This function exists to allow for the disabled mode to be explicit,
          rather than assumed to be zero.
          rather than assumed to be zero.
 
 
   @return  The new TTMR                                                     */
   @return  The new TTMR                                                     */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long int
static unsigned long int
clear_ttmr ()
clear_ttmr ()
{
{
  unsigned long int  ttmr = SPR_TTMR_DI;
  unsigned long int  ttmr = SPR_TTMR_DI;
 
 
  SET_TTMR (ttmr);
  SET_TTMR (ttmr);
 
 
  return  ttmr;
  return  ttmr;
 
 
}       /* clear_ttmr () */
}       /* clear_ttmr () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Clear the count register
/*!Clear the count register
 
 
   Count is zeroed
   Count is zeroed
 
 
   @return  The new TTCR                                                     */
   @return  The new TTCR                                                     */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long int
static unsigned long int
clear_ttcr ()
clear_ttcr ()
{
{
  unsigned long int  ttcr = 0;
  unsigned long int  ttcr = 0;
 
 
  SET_TTCR (ttcr);
  SET_TTCR (ttcr);
 
 
  return  ttcr;
  return  ttcr;
 
 
}       /* clear_ttcr () */
}       /* clear_ttcr () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Set a new timer.
/*!Set a new timer.
 
 
   Convenience function for a common sequence
   Convenience function for a common sequence
 
 
   @param[in] period  The period of the timer
   @param[in] period  The period of the timer
   @param[in] mode    The timer mode
   @param[in] mode    The timer mode
   @param[in] flags   Any falgs to set (usually IE)
   @param[in] flags   Any falgs to set (usually IE)
 
 
   @return  The new value of TTMR                                            */
   @return  The new value of TTMR                                            */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static unsigned long int
static unsigned long int
new_timer (unsigned long int  period,
new_timer (unsigned long int  period,
           unsigned long int  mode,
           unsigned long int  mode,
           unsigned long int  flags)
           unsigned long int  flags)
{
{
  unsigned long int  ttmr;
  unsigned long int  ttmr;
 
 
  ttmr  = 0;
  ttmr  = 0;
  ttmr  = set_period (ttmr, period);
  ttmr  = set_period (ttmr, period);
  ttmr  = set_mode (ttmr, mode);
  ttmr  = set_mode (ttmr, mode);
  ttmr |= flags;
  ttmr |= flags;
 
 
  SET_TTMR (ttmr);
  SET_TTMR (ttmr);
 
 
  return  ttmr;
  return  ttmr;
 
 
}       /* new_timer () */
}       /* new_timer () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Standard tick interrupt handler
/*!Standard tick interrupt handler
 
 
  Up the count and clear the interrupt appropriately                        */
  Up the count and clear the interrupt appropriately                        */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
tick_int (void)
tick_int (void)
{
{
  unsigned long int  ttmr = mfspr (SPR_TTMR);
  unsigned long int  ttmr = mfspr (SPR_TTMR);
 
 
  /* Make sure that the tick timer interrupt pending bit is set */
  /* Make sure that the tick timer interrupt pending bit is set */
  SILENT_ASSERT (0 != (ttmr & SPR_TTMR_IP),
  SILENT_ASSERT (0 != (ttmr & SPR_TTMR_IP),
                 "IP bit not set in normal interrupt handler");
                 "IP bit not set in normal interrupt handler");
 
 
  /* One more interrupt handled */
  /* One more interrupt handled */
  tick_cnt++;
  tick_cnt++;
 
 
  /* Clear interrupt (Write a 0 to SPR_TTMR_IP)
  /* Clear interrupt (Write a 0 to SPR_TTMR_IP)
 
 
     If we programmed a one-shot timer, make sure to disable the interrupts,
     If we programmed a one-shot timer, make sure to disable the interrupts,
     else we'd get a spurious interrupt */
     else we'd get a spurious interrupt */
  if (SPR_TTMR_SR == (ttmr & SPR_TTMR_M))
  if (SPR_TTMR_SR == (ttmr & SPR_TTMR_M))
    {
    {
      ttmr &= ~(SPR_TTMR_IP | SPR_TTMR_IE);
      ttmr &= ~(SPR_TTMR_IP | SPR_TTMR_IE);
    }
    }
  else
  else
    {
    {
      ttmr &= ~SPR_TTMR_IP;
      ttmr &= ~SPR_TTMR_IP;
    }
    }
 
 
  mtspr (SPR_TTMR, ttmr);
  mtspr (SPR_TTMR, ttmr);
 
 
}       /* tick_count () */
}       /* tick_count () */
 
 
 
 
 
#if DO_SPURIOUS_INT_TEST==1
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Tick interrupt handler generting spurious interrupts
/*!Tick interrupt handler generting spurious interrupts
 
 
  If we have a one-shot timer set, then when we clear the interrupt (if a
  If we have a one-shot timer set, then when we clear the interrupt (if a
  global flag allows), but leave the interrupt enabled we should get a
  global flag allows), but leave the interrupt enabled we should get a
  spurious interrupt.
  spurious interrupt.
 
 
  Allow this to happen MAX_SPURIOUS times before disabling the interrupt.
  Allow this to happen MAX_SPURIOUS times before disabling the interrupt.
 
 
  Up the count and clear the interrupt appropriately                        */
  Up the count and clear the interrupt appropriately                        */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
tick_int_spurious (void)
tick_int_spurious (void)
{
{
  unsigned long int  ttmr = mfspr(SPR_TTMR);
  unsigned long int  ttmr = mfspr(SPR_TTMR);
 
 
  /* Make sure that the tick timer interrupt pending bit is set */
  /* Make sure that the tick timer interrupt pending bit is set */
  SILENT_ASSERT (0 != (ttmr & SPR_TTMR_IP),
  SILENT_ASSERT (0 != (ttmr & SPR_TTMR_IP),
                 "IP bit not set in spurious interrupt handler");
                 "IP bit not set in spurious interrupt handler");
 
 
  /* Clear interrupt if global flag allows it (Write a 0 to SPR_TTMR_IP) */
  /* Clear interrupt if global flag allows it (Write a 0 to SPR_TTMR_IP) */
  if (clear_ip)
  if (clear_ip)
    {
    {
      ttmr &= ~SPR_TTMR_IP;
      ttmr &= ~SPR_TTMR_IP;
      mtspr (SPR_TTMR, ttmr);
      mtspr (SPR_TTMR, ttmr);
    }
    }
 
 
  /* Allow MAX_SPURIOUS spurious spurious interrupt */
  /* Allow MAX_SPURIOUS spurious spurious interrupt */
  if (++tick_cnt == MAX_SPURIOUS)
  if (++tick_cnt == MAX_SPURIOUS)
    {
    {
      /* Clear mode register completely */
      /* Clear mode register completely */
      ttmr = 0;
      ttmr = 0;
      mtspr (SPR_TTMR, ttmr);
      mtspr (SPR_TTMR, ttmr);
 
 
 
 
    }
    }
}       /* tick_int_spurious () */
}       /* tick_int_spurious () */
 
#endif
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Waste a little time
/*!Waste a little time
 
 
  We are waiting for TTCR to increment
  We are waiting for TTCR to increment
 
 
  @note This is an entirely arbitrary period. In particular excessive use of
  @note This is an entirely arbitrary period. In particular excessive use of
  printf in an interrupt handler can tie up cycles and cause TTCR not
  printf in an interrupt handler can tie up cycles and cause TTCR not
  to increment in time.                                               */
  to increment in time.                                               */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
static void
static void
waste_time (void)
waste_time (void)
{
{
  int          i;
  int          i;
  volatile int x;
  volatile int x;
 
 
  for (i = 0; i < 50; i++)
  for (i = 0; i < 50; i++)
    {
    {
      x = i;
      x = i;
    }
    }
}       /* waste_time () */
}       /* waste_time () */
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Wait for a tick timer exception
/*!Wait for a tick timer exception
 
 
  This occurs when the tick count goes up. Reset the count once the
  This occurs when the tick count goes up. Reset the count once the
  exception is received.                                                    */
  exception is received.                                                    */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/* Waits for a tick timer exception */
/* Waits for a tick timer exception */
static void
static void
wait_match (void)
wait_match (void)
{
{
  while (!tick_cnt)
  while (!tick_cnt)
    {
    {
    }
    }
 
 
  tick_cnt = 0;
  tick_cnt = 0;
 
 
}       /* wait_match () */
}       /* wait_match () */
 
 
 
 
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
/*!Main program testing tick timer
/*!Main program testing tick timer
 
 
  Tests all aspecst of tick timer behavior.
  Tests all aspecst of tick timer behavior.
 
 
  @return  Return code from the program (always zero).                      */
  @return  Return code from the program (always zero).                      */
/* --------------------------------------------------------------------------*/
/* --------------------------------------------------------------------------*/
int
int
main()
main()
{
{
  unsigned long int  ttmr;
  unsigned long int  ttmr;
  unsigned long int  ttcr;
  unsigned long int  ttcr;
 
 
  /* Use normal interrupt handler */
  /* Use normal interrupt handler */
  excpt_tick = (unsigned long)tick_int;
  excpt_tick = (unsigned long)tick_int;
 
 
  /* Enable tick interrupt */
  /* Enable tick interrupt */
  mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_TEE);
  mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_TEE);
 
 
  /* Clear interrupt pending and interrupt enabled, zero the period, set
  /* Clear interrupt pending and interrupt enabled, zero the period, set
     disabled mode and set count to zero. */
     disabled mode and set count to zero. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
 
 
  /* Waste some time to check if the timer is really disabled */
  /* Waste some time to check if the timer is really disabled */
  waste_time ();
  waste_time ();
 
 
  /* Timer is disabled and shouldn't count, TTCR should still be 0 */
  /* Timer is disabled and shouldn't count, TTCR should still be 0 */
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  ASSERT (0 == ttcr, "Tick timer not counting while disabled");
  ASSERT (0 == ttcr, "Tick timer not counting while disabled");
 
 
  /* Start timer in continous running mode.  Enable timer interrupt and set
  /* Start timer in continous running mode.  Enable timer interrupt and set
   * the period to 0x100 */
   * the period to 0x100 */
  ttmr = new_timer (0x100, SPR_TTMR_CR, SPR_TTMR_IE);
  ttmr = new_timer (0x100, SPR_TTMR_CR, SPR_TTMR_IE);
 
 
  /* Wait for the timer to count up to the match value, get the count
  /* Wait for the timer to count up to the match value, get the count
     register value. Then waste some time and check that couting has
     register value. Then waste some time and check that couting has
     continued. */
     continued. */
  wait_match ();
  wait_match ();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  waste_time();
  waste_time();
 
 
  /* The timer should have kept counting and our saved TTCR should not be the
  /* The timer should have kept counting and our saved TTCR should not be the
   * same as the current ttcr */
   * same as the current ttcr */
  ASSERT (ttcr < GET_TTCR (),
  ASSERT (ttcr < GET_TTCR (),
          "Tick timer kept counting during continuous mode");
          "Tick timer kept counting during continuous mode");
 
 
  /* Clear the mode register flags, zero the period and set disabled
  /* Clear the mode register flags, zero the period and set disabled
     mode. Then get the count register which should be unaffected by this. */
     mode. Then get the count register which should be unaffected by this. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
 
 
  /* Restart the timer in continous run mode and the counter will keep
  /* Restart the timer in continous run mode and the counter will keep
     going. There should be no interrupts, since we haven't enabled
     going. There should be no interrupts, since we haven't enabled
     them. Waste some time to allow the counter to advance. */
     them. Waste some time to allow the counter to advance. */
  ttmr = set_mode (ttmr, SPR_TTMR_CR);
  ttmr = set_mode (ttmr, SPR_TTMR_CR);
  SET_TTMR (ttmr);
  SET_TTMR (ttmr);
  waste_time ();
  waste_time ();
 
 
  /* The timer should have carried on from what was SPR_TTCR when we started
  /* The timer should have carried on from what was SPR_TTCR when we started
     it. */
     it. */
  ASSERT (ttcr < GET_TTCR (), "Tick timer continued counting after restart");
  ASSERT (ttcr < GET_TTCR (), "Tick timer continued counting after restart");
 
 
  /* Disable the timer and waste some time to check that the count does not
  /* Disable the timer and waste some time to check that the count does not
     advance */
     advance */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  waste_time ();
  waste_time ();
 
 
  /* Timer should be disabled and should not have counted */
  /* Timer should be disabled and should not have counted */
  ASSERT(ttcr == GET_TTCR (), "Tick timer counter stops when disabled");
  ASSERT(ttcr == GET_TTCR (), "Tick timer counter stops when disabled");
 
 
  /* Start in single run mode with a count of 0x100. Run until the match is
  /* Start in single run mode with a count of 0x100. Run until the match is
     hit, then check that the counter does not advance further while wasting
     hit, then check that the counter does not advance further while wasting
     time. */
     time. */
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
 
 
  wait_match();
  wait_match();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  waste_time();
  waste_time();
 
 
  /* The timer should have stoped and the counter advanced no further. */
  /* The timer should have stoped and the counter advanced no further. */
  ASSERT (ttcr == GET_TTCR (), "Timer stopped after match");
  ASSERT (ttcr == GET_TTCR (), "Timer stopped after match");
 
 
  /* The counter should still indicate single run mode */
  /* The counter should still indicate single run mode */
  ttmr = GET_TTMR ();
  ttmr = GET_TTMR ();
  ASSERT ((ttmr & SPR_TTMR_SR) == SPR_TTMR_SR,
  ASSERT ((ttmr & SPR_TTMR_SR) == SPR_TTMR_SR,
          "Timer still indicating one-shot mode after match");
          "Timer still indicating one-shot mode after match");
 
 
  /* Disable the timer, then start auto-restarting timer every 0x1000 ticks. */
  /* Disable the timer, then start auto-restarting timer every 0x1000 ticks. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
  ttmr = new_timer (0x1000, SPR_TTMR_RT, SPR_TTMR_IE);
  ttmr = new_timer (0x1000, SPR_TTMR_RT, SPR_TTMR_IE);
 
 
  /* Wait for two matches, then disable the timer. If this doesn't work the
  /* Wait for two matches, then disable the timer. If this doesn't work the
     test will time out, so no ASSERT here. */
     test will time out, so no ASSERT here. */
  wait_match();
  wait_match();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  wait_match();
  wait_match();
 
 
  /* Start a one-shot counter but keep interrupts disabled */
  /* Start a one-shot counter but keep interrupts disabled */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
  ttmr = new_timer (0x100, SPR_TTMR_SR, 0);
  ttmr = new_timer (0x100, SPR_TTMR_SR, 0);
 
 
  /* Wait for the counter to stop */
  /* Wait for the counter to stop */
  while (GET_TTCR () != 0x100)
  while (GET_TTCR () != 0x100)
    {
    {
    }
    }
 
 
  /* Make sure the counter has actually stopped and there have been no more
  /* Make sure the counter has actually stopped and there have been no more
     interrupts (neither tick count nor pending flag. */
     interrupts (neither tick count nor pending flag. */
  waste_time();
  waste_time();
  ttmr = GET_TTMR ();
  ttmr = GET_TTMR ();
 
 
  ASSERT (GET_TTCR () == 0x100, "One-shot timer stopped");
  ASSERT (GET_TTCR () == 0x100, "One-shot timer stopped");
  ASSERT (tick_cnt == 0, "No more interrupts after one-shot timer");
  ASSERT (tick_cnt == 0, "No more interrupts after one-shot timer");
  ASSERT (SPR_TTMR_IP != (ttmr & SPR_TTMR_IP),
  ASSERT (SPR_TTMR_IP != (ttmr & SPR_TTMR_IP),
          "IP flag not set after one-shot timer");
          "IP flag not set after one-shot timer");
 
 
  /* Start a perpetual counter but with no interrupts enabled while it is
  /* Start a perpetual counter but with no interrupts enabled while it is
     still counting. */
     still counting. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
  ttmr = new_timer (0x100, SPR_TTMR_CR, 0);
  ttmr = new_timer (0x100, SPR_TTMR_CR, 0);
 
 
  /* Wait until it reaches its count. */
  /* Wait until it reaches its count. */
  while(GET_TTCR () < 0x100)
  while(GET_TTCR () < 0x100)
    {
    {
    }
    }
 
 
  /* Waste some time and check the counter has carried on past its count and
  /* Waste some time and check the counter has carried on past its count and
     that there have bee no more interrupts nor interrupts pending. */
     that there have bee no more interrupts nor interrupts pending. */
  waste_time();
  waste_time();
 
 
  ttmr = GET_TTMR ();
  ttmr = GET_TTMR ();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
 
 
  ASSERT (ttcr > 0x100, "Perptual timer kept counting");
  ASSERT (ttcr > 0x100, "Perptual timer kept counting");
  ASSERT (tick_cnt == 0, "No more interrupts during perpetual timer count");
  ASSERT (tick_cnt == 0, "No more interrupts during perpetual timer count");
  ASSERT (SPR_TTMR_IP != (ttmr & SPR_TTMR_IP),
  ASSERT (SPR_TTMR_IP != (ttmr & SPR_TTMR_IP),
          "IP flag not set during perpetual timer count");
          "IP flag not set during perpetual timer count");
 
 
  /* Disable the timer interrupt */
  /* Disable the timer interrupt */
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_TEE);
  mtspr (SPR_SR, mfspr (SPR_SR) & ~SPR_SR_TEE);
 
 
  /* Set a one-shot timer, with the counter started at zero. */
  /* Set a one-shot timer, with the counter started at zero. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
 
 
  /* Wait for the interrupt pending bit to be set. */
  /* Wait for the interrupt pending bit to be set. */
  do
  do
    {
    {
      ttmr = GET_TTMR ();
      ttmr = GET_TTMR ();
    }
    }
  while (0 == (ttmr & SPR_TTMR_IP));
  while (0 == (ttmr & SPR_TTMR_IP));
 
 
  /* Give some time for a potential interrupt to occur */
  /* Give some time for a potential interrupt to occur */
  waste_time();
  waste_time();
 
 
  /* No interrupt should have occured */
  /* No interrupt should have occured */
  ASSERT (tick_cnt == 0, "No interrupt when tick timer disabled");
  ASSERT (tick_cnt == 0, "No interrupt when tick timer disabled");
 
 
  /* Enable tick interrupt */
  /* Enable tick interrupt */
  mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_TEE);
  mtspr (SPR_SR, mfspr (SPR_SR) | SPR_SR_TEE);
 
 
  /* Test Setting TTCR while counting. Set a period of 0x3000 but do not
  /* Test Setting TTCR while counting. Set a period of 0x3000 but do not
     enable interrupts. */
     enable interrupts. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = clear_ttcr ();
  ttcr = clear_ttcr ();
  ttmr = new_timer (0x3000, SPR_TTMR_CR, 0);
  ttmr = new_timer (0x3000, SPR_TTMR_CR, 0);
 
 
  /* Wait for the count to reach 10 times our period. */
  /* Wait for the count to reach 10 times our period. */
  while (GET_TTCR () < 0x30000)
  while (GET_TTCR () < 0x30000)
    {
    {
    }
    }
 
 
  /* Waste some time and then reset the count to 0x50 */
  /* Waste some time and then reset the count to 0x50 */
  waste_time();
  waste_time();
  SET_TTCR (0x50);
  SET_TTCR (0x50);
 
 
  /* Verify that after a short wait we have counted to more than 0x50, but
  /* Verify that after a short wait we have counted to more than 0x50, but
     less than 0x30000 */
     less than 0x30000 */
  waste_time();
  waste_time();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
 
 
  ASSERT ((0x50 < ttcr) && (ttcr < 0x30000), "TTCR reset while counting");
  ASSERT ((0x50 < ttcr) && (ttcr < 0x30000), "TTCR reset while counting");
 
 
  /* Disable the timer. Set the counter to a high value and start a single run
  /* Disable the timer. Set the counter to a high value and start a single run
     timer with a low timer period. Demonstrate the counter wraps round and
     timer with a low timer period. Demonstrate the counter wraps round and
     then triggers at the period. Need to reset the tick counter, since there
     then triggers at the period. Need to reset the tick counter, since there
     may have been an interrupt during the previous period. */
     may have been an interrupt during the previous period. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = 0x20000;
  ttcr = 0x20000;
  SET_TTCR (ttcr);
  SET_TTCR (ttcr);
 
 
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
  ttmr = new_timer (0x100, SPR_TTMR_SR, SPR_TTMR_IE);
 
 
  /* The counter should start counting from 0x20000 and wrap around to 0x100
  /* The counter should start counting from 0x20000 and wrap around to 0x100
   * causeing an interrupt. Check we keep on counting. */
   * causeing an interrupt. Check we keep on counting. */
  waste_time();
  waste_time();
  ASSERT (GET_TTCR () > 0x20000, "Timer started counting from high value");
  ASSERT (GET_TTCR () > 0x20000, "Timer started counting from high value");
 
 
  /* If TTCR is greater than TTMR_PERIOD then the interrupt gets delivered after
  /* If TTCR is greater than TTMR_TP then the interrupt gets delivered after
     TTCR wraps around to 0 and counts to SPR_TTMR_PERIOD.
     TTCR wraps around to 0 and counts to SPR_TTMR_TP.
 
 
     Set up an auto-restart timer to wrap around. Reset the tick count,
     Set up an auto-restart timer to wrap around. Reset the tick count,
     because it may have incremented since the last match. */
     because it may have incremented since the last match. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = 0xffffc00;
  ttcr = 0xffffc00;
  SET_TTCR (ttcr);
  SET_TTCR (ttcr);
 
 
  tick_cnt = 0;
  tick_cnt = 0;
  ttmr = new_timer (0x10000, SPR_TTMR_RT, SPR_TTMR_IE);
  ttmr = new_timer (0x10000, SPR_TTMR_RT, SPR_TTMR_IE);
 
 
  /* Wait for the trigger, then check that we have restarted. */
  /* Wait for the trigger, then check that we have restarted. */
  wait_match();
  wait_match();
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
 
 
  ASSERT (ttcr < 0x10000, "Auto-restart wrapped round");
  ASSERT (ttcr < 0x10000, "Auto-restart wrapped round");
 
 
  /* Test wrap around in continuous mode. Reset the tick count in case we
  /* Test wrap around in continuous mode. Reset the tick count in case we
     have had another interrupt. */
     have had another interrupt. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  ttcr = 0xffffc00;
  ttcr = 0xffffc00;
  SET_TTCR (ttcr);
  SET_TTCR (ttcr);
 
 
  tick_cnt = 0;
  tick_cnt = 0;
  ttmr = new_timer (0x10000, SPR_TTMR_CR, SPR_TTMR_IE);
  ttmr = new_timer (0x10000, SPR_TTMR_CR, SPR_TTMR_IE);
 
 
  /* Wait for trigger, then check that we have carried on counting. */
  /* Wait for trigger, then check that we have carried on counting. */
  wait_match();
  wait_match();
  ttcr = GET_TTCR () & SPR_TTCR_PERIOD;
  ttcr = GET_TTCR () & SPR_TTCR_CNT;
 
 
  ASSERT ((0x10000 < ttcr) && (ttcr < 0xffffc00),
  ASSERT ((0x00010000 < ttcr) && (ttcr < 0xfffffc00),
          "Continuous mode wrapped round");
          "Continuous mode wrapped round");
 
 
 
#if DO_SPURIOUS_INT_TEST==1
 
 
  /* Disable the timer and set up the special spurious interrupt handler, to
  /* Disable the timer and set up the special spurious interrupt handler, to
     check spurious interrupts occur as expected. */
     check spurious interrupts occur as expected. */
  ttmr = clear_ttmr ();
  ttmr = clear_ttmr ();
  excpt_tick = (unsigned long)tick_int_spurious;
  excpt_tick = (unsigned long)tick_int_spurious;
 
 
  /* Set up a disabled timer with a period of 0x100. */
  /* Set up a disabled timer with a period of 0x100. */
  clear_ttcr ();
  clear_ttcr ();
  ttmr = new_timer (0x100, SPR_TTMR_DI, SPR_TTMR_IE);
  ttmr = new_timer (0x100, SPR_TTMR_DI, SPR_TTMR_IE);
 
 
  /* Set up the count to match the period, and check that spurious interrupts
  /* Set up the count to match the period, and check that spurious interrupts
     are generated, even though the timer is disabled. */
     are generated, even though the timer is disabled. */
  ttcr = 0x100;
  ttcr = 0x100;
  SET_TTCR (ttcr);
  SET_TTCR (ttcr);
 
 
  while(tick_cnt != MAX_SPURIOUS)
  while(tick_cnt != MAX_SPURIOUS)
    {
    {
    }
    }
 
 
  /* Check the count has not changed */
  /* Check the count has not changed */
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  ASSERT (0x100 == ttcr, "Spurious interrupts handled with matching period");
  ASSERT (0x100 == ttcr, "Spurious interrupts handled with matching period");
 
 
  /* Reset the tick count, then test setting TTCR first then TTMR */
  /* Reset the tick count, then test setting TTCR first then TTMR */
  tick_cnt = 0;
  tick_cnt = 0;
  ttcr = 0x101;
  ttcr = 0x101;
  SET_TTCR (ttcr);
  SET_TTCR (ttcr);
  ttmr = new_timer (0x101, SPR_TTMR_DI, SPR_TTMR_IE);
  ttmr = new_timer (0x101, SPR_TTMR_DI, SPR_TTMR_IE);
 
 
  while(tick_cnt != MAX_SPURIOUS)
  while(tick_cnt != MAX_SPURIOUS)
    {
    {
    }
    }
 
 
  ttcr = GET_TTCR ();
  ttcr = GET_TTCR ();
  ASSERT (0x101 == ttcr, "Spurious interrupts handled after TTCR and TTMR");
  ASSERT (0x101 == ttcr, "Spurious interrupts handled after TTCR and TTMR");
 
 
  /* Set countinous counter, but make sure we never clear the TTMR_IP bit */
  /* Set countinous counter, but make sure we never clear the TTMR_IP bit */
  tick_cnt = 0;
  tick_cnt = 0;
  clear_ip = 0;
  clear_ip = 0;
 
 
  clear_ttcr ();
  clear_ttcr ();
  ttmr = new_timer (0x100, SPR_TTMR_CR, SPR_TTMR_IE);
  ttmr = new_timer (0x100, SPR_TTMR_CR, SPR_TTMR_IE);
 
 
  while(tick_cnt != MAX_SPURIOUS)
  while(tick_cnt != MAX_SPURIOUS)
    {
    {
    }
    }
 
 
 
#endif
 
 
  /* If we get here everything worked. */
  /* If we get here everything worked. */
  report(0xdeaddead);
  report(0xdeaddead);
  return 0;
  return 0;
 
 
}       /* main () */
}       /* main () */
 
 
 
 

powered by: WebSVN 2.1.0

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