forked from Imagelibrary/rtems
Patch from "John M. Mills" <jmills@tga.com> with subsequent cleanup from
Ralf Corsepius <corsepiu@faw.uni-ulm.de> that adds initial Hitachi SH-2 support to RTEMS. Ralf's comments are: Changes: ------ 1. SH-Port: * Many files renamed. * CONSOLE_DEVNAME and MHZ defines removed from libcpu. * console.c moved to libbsp/sh/shared, build in libbsp/sh/<BSP>/console applying VPATH. * CONSOLE_DEVNAME made BSP-specific, replacement is defined in bsp.h * MHZ define replaced with HZ (extendent resolution) in custom/*.cfg * -DHZ=HZ used in bspstart.c, only * Makefile variable HZ used in bsp-dependent directories only. 2. SH1-Port * clock-driver rewritten to provide better resolution for odd CPU frequencies. This driver is only partially tested on hardware, ie. sightly experimental, but I don't expect severe problems with it. * Polling SCI-driver added. This driver is experimental and completly untested yet. Therefore it is not yet used for the console (/dev/console is still pointing to /dev/null, cf. gensh1/bsp.h). * minor changes to the timer driver * SH1 specific delay()/CPU_delay() now is implemented as a function 3. SH2-Port * Merged * IMO, the code is still in its infancy. Therefore I have interspersed comments (FIXME) it for items which I think John should look after. * sci and console drivers partially rewritten and extended (John, I hope you don't mind). * Copyright notices are not yet adapted
This commit is contained in:
208
c/src/lib/libcpu/sh/sh7045/timer/timer.c
Normal file
208
c/src/lib/libcpu/sh/sh7045/timer/timer.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/*
|
||||
* timer for the Hitachi SH 704X
|
||||
*
|
||||
* This file manages the benchmark timer used by the RTEMS Timing Test
|
||||
* Suite. Each measured time period is demarcated by calls to
|
||||
* Timer_initialize() and Read_timer(). Read_timer() usually returns
|
||||
* the number of microseconds since Timer_initialize() exitted.
|
||||
*
|
||||
* NOTE: It is important that the timer start/stop overhead be
|
||||
* determined when porting or modifying this code.
|
||||
*
|
||||
* Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
|
||||
* Bernd Becker (becker@faw.uni-ulm.de)
|
||||
*
|
||||
* COPYRIGHT (c) 1997-1998, FAW Ulm, Germany
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* COPYRIGHT (c) 1998.
|
||||
* On-Line Applications Research Corporation (OAR).
|
||||
* Copyright assigned to U.S. Government, 1994.
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.OARcorp.com/rtems/license.html.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#include <rtems.h>
|
||||
|
||||
#include <rtems/score/sh_io.h>
|
||||
#include <rtems/score/iosh7045.h>
|
||||
|
||||
/*
|
||||
* We use a Phi/4 timer
|
||||
*/
|
||||
#define SCALE (Timer_MHZ/4)
|
||||
|
||||
#define MTU1_STARTMASK 0xfd
|
||||
#define MTU1_SYNCMASK 0xfd
|
||||
#define MTU1_MODEMASK 0xc0
|
||||
#define MTU1_TCRMASK 0x01
|
||||
#define MTU1_TIORMASK 0x88
|
||||
#define MTU1_STAT_MASK 0xf8
|
||||
#define MTU1_TIERMASK 0xfc
|
||||
#define IPRC_MTU1_MASK 0xfff0
|
||||
|
||||
#ifndef MTU1_PRIO
|
||||
#define MTU1_PRIO 15
|
||||
#endif
|
||||
|
||||
#define MTU1_VECTOR 86
|
||||
|
||||
rtems_isr timerisr();
|
||||
|
||||
static rtems_unsigned32 Timer_interrupts;
|
||||
|
||||
rtems_boolean Timer_driver_Find_average_overhead;
|
||||
|
||||
static rtems_unsigned32 Timer_MHZ ;
|
||||
|
||||
void Timer_initialize( void )
|
||||
{
|
||||
rtems_unsigned8 temp8;
|
||||
rtems_unsigned16 temp16;
|
||||
rtems_unsigned32 level;
|
||||
rtems_isr *ignored;
|
||||
|
||||
Timer_MHZ = rtems_cpu_configuration_get_clicks_per_second() / 1000000 ;
|
||||
|
||||
/*
|
||||
* Timer has never overflowed. This may not be necessary on some
|
||||
* implemenations of timer but ....
|
||||
*/
|
||||
|
||||
Timer_interrupts /* .i */ = 0;
|
||||
_CPU_ISR_Disable( level);
|
||||
|
||||
/*
|
||||
* Somehow start the timer
|
||||
*/
|
||||
/* stop Timer 1 */
|
||||
temp8 = read8( MTU_TSTR) & MTU1_STARTMASK;
|
||||
write8( temp8, MTU_TSTR);
|
||||
|
||||
/* initialize counter 1 */
|
||||
write16( 0, MTU_TCNT1);
|
||||
|
||||
/* Timer 1 is independent of other timers */
|
||||
temp8 = read8( MTU_TSYR) & MTU1_SYNCMASK;
|
||||
write8( temp8, MTU_TSYR);
|
||||
|
||||
/* Timer 1, normal mode */
|
||||
temp8 = read8( MTU_TMDR1) & MTU1_MODEMASK;
|
||||
write8( temp8, MTU_TMDR1);
|
||||
|
||||
/* x0000000
|
||||
* |||||+++--- Internal Clock
|
||||
* |||++------ Count on rising edge
|
||||
* |++-------- disable TCNT clear
|
||||
* +---------- don`t care
|
||||
*/
|
||||
write8( MTU1_TCRMASK, MTU_TCR1);
|
||||
|
||||
/* gra and grb are not used */
|
||||
write8( MTU1_TIORMASK, MTU_TIOR1);
|
||||
|
||||
/* reset all status flags */
|
||||
temp8 = read8( MTU_TSR1) & MTU1_STAT_MASK;
|
||||
write8( temp8, MTU_TSR1);
|
||||
|
||||
/* enable overflow interrupt */
|
||||
write8( MTU1_TIERMASK, MTU_TIER1);
|
||||
|
||||
/* set interrupt priority */
|
||||
temp16 = read16( INTC_IPRC) & IPRC_MTU1_MASK;
|
||||
temp16 |= MTU1_PRIO;
|
||||
write16( temp16, INTC_IPRC);
|
||||
|
||||
/* initialize ISR */
|
||||
_CPU_ISR_install_raw_handler( MTU1_VECTOR, timerisr, &ignored );
|
||||
_CPU_ISR_Enable( level);
|
||||
|
||||
/* start timer 1 */
|
||||
temp8 = read8( MTU_TSTR) | ~MTU1_STARTMASK;
|
||||
write8( temp8, MTU_TSTR);
|
||||
}
|
||||
|
||||
/*
|
||||
* The following controls the behavior of Read_timer().
|
||||
*
|
||||
* AVG_OVERHEAD is the overhead for starting and stopping the timer. It
|
||||
* is usually deducted from the number returned.
|
||||
*
|
||||
* LEAST_VALID is the lowest number this routine should trust. Numbers
|
||||
* below this are "noise" and zero is returned.
|
||||
*/
|
||||
|
||||
#define AVG_OVERHEAD 1 /* It typically takes X.X microseconds */
|
||||
/* (Y countdowns) to start/stop the timer. */
|
||||
/* This value is in microseconds. */
|
||||
#define LEAST_VALID 0 /* 20 */ /* Don't trust a clicks value lower than this */
|
||||
|
||||
int Read_timer( void )
|
||||
{
|
||||
rtems_unsigned32 clicks;
|
||||
rtems_unsigned32 total ;
|
||||
/*
|
||||
* Read the timer and see how many clicks it has been since we started.
|
||||
*/
|
||||
|
||||
|
||||
clicks = read16( MTU_TCNT1); /* XXX: read some HW here */
|
||||
|
||||
/*
|
||||
* Total is calculated by taking into account the number of timer overflow
|
||||
* interrupts since the timer was initialized and clicks since the last
|
||||
* interrupts.
|
||||
*/
|
||||
|
||||
total = clicks + Timer_interrupts * 65536 ;
|
||||
|
||||
if ( Timer_driver_Find_average_overhead )
|
||||
return total / SCALE; /* in XXX microsecond units */
|
||||
else
|
||||
{
|
||||
if ( total < LEAST_VALID )
|
||||
return 0; /* below timer resolution */
|
||||
/*
|
||||
* Somehow convert total into microseconds
|
||||
*/
|
||||
return (total / SCALE - AVG_OVERHEAD) ;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Empty function call used in loops to measure basic cost of looping
|
||||
* in Timing Test Suite.
|
||||
*/
|
||||
|
||||
rtems_status_code Empty_function( void )
|
||||
{
|
||||
return RTEMS_SUCCESSFUL;
|
||||
}
|
||||
|
||||
void Set_find_average_overhead(
|
||||
rtems_boolean find_flag
|
||||
)
|
||||
{
|
||||
Timer_driver_Find_average_overhead = find_flag;
|
||||
}
|
||||
|
||||
/* Timer 1 is used */
|
||||
|
||||
#pragma interrupt
|
||||
void timerisr( void )
|
||||
{
|
||||
unsigned8 temp8;
|
||||
|
||||
/* reset the flags of the status register */
|
||||
temp8 = read8( MTU_TSR1) & MTU1_STAT_MASK;
|
||||
write8( temp8, MTU_TSR1);
|
||||
|
||||
Timer_interrupts += 1;
|
||||
}
|
||||
Reference in New Issue
Block a user