2001-10-11 Alexandra Kossovsky <sasha@oktet.ru>

* clock/Makefile.am, clock/ckinit.c, clock/.cvsignore, Makefile.am,
	include/Makefile.am, include/iosh7750.h, include/ipl.h,
	include/ispsh7750.h, include/sh4_regs.h, include/sh4uart.h,
	include/sh7750_regs.h, include/.cvsignore, sci/Makefile.am,
	sci/console.c, sci/sh4uart.c, sci/.cvsignore, score/Makefile.am,
	score/cpu_asm.c, score/ispsh7750.c, score/.cvsignore,
	timer/Makefile.am, timer/timer.c, timer/.cvsignore, configure.ac,
	.cvsignore, ChangeLog:  New files.
	Reviewed and updated to latest automake and autoconf standards
	by Ralf Corsepius <corsepiu@faw.uni-ulm.de>.
This commit is contained in:
Joel Sherrill
2001-10-12 13:19:08 +00:00
parent 38db58f82b
commit ba71076168
26 changed files with 4989 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
Makefile
Makefile.in
aclocal.m4
autom4te.cache
config.cache
config.guess
config.log
config.status
config.sub
configure
depcomp
install-sh
missing
mkinstalldirs

View File

@@ -0,0 +1,13 @@
2001-10-11 Alexandra Kossovsky <sasha@oktet.ru>
* clock/Makefile.am, clock/ckinit.c, clock/.cvsignore, Makefile.am,
include/Makefile.am, include/iosh7750.h, include/ipl.h,
include/ispsh7750.h, include/sh4_regs.h, include/sh4uart.h,
include/sh7750_regs.h, include/.cvsignore, sci/Makefile.am,
sci/console.c, sci/sh4uart.c, sci/.cvsignore, score/Makefile.am,
score/cpu_asm.c, score/ispsh7750.c, score/.cvsignore,
timer/Makefile.am, timer/timer.c, timer/.cvsignore, configure.ac,
.cvsignore, ChangeLog: New files.
Reviewed and updated to latest automake and autoconf standards
by Ralf Corsepius <corsepiu@faw.uni-ulm.de>.

View File

@@ -0,0 +1,11 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
ACLOCAL_AMFLAGS = -I ../../../../../../aclocal
SUBDIRS = include score clock sci timer
include $(top_srcdir)/../../../../../../automake/subdirs.am
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,31 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
PGM = $(ARCH)/clock.rel
C_FILES = ckinit.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
OBJS = $(C_O_FILES)
include $(top_srcdir)/../../../../../../make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
#
# (OPTIONAL) Add local stuff here using +=
#
$(PGM): $(OBJS)
$(make-rel)
all-local: $(ARCH) $(OBJS) $(PGM)
.PRECIOUS: $(PGM)
EXTRA_DIST = ckinit.c
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,324 @@
/*
* This file contains the generic RTEMS clock driver the Hitachi SH 7750
*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
* COPYRIGHT (c) 2001
* 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 <stdlib.h>
#include <rtems/libio.h>
#include <rtems/score/sh_io.h>
#include <rtems/score/sh.h>
#include <rtems/score/ispsh7750.h>
#include <rtems/score/iosh7750.h>
#ifndef CLOCKPRIO
#define CLOCKPRIO 10
#endif
/* Clock timer prescaler division ratio */
#define CLOCK_PRESCALER 4
#define TCR0_TPSC SH7750_TCR_TPSC_DIV4
/*
* The interrupt vector number associated with the clock tick device
* driver.
*/
#define CLOCK_VECTOR SH7750_EVT_TO_NUM(SH7750_EVT_TUNI0)
/*
* Clock_driver_ticks is a monotonically increasing counter of the
* number of clock ticks since the driver was initialized.
*/
volatile rtems_unsigned32 Clock_driver_ticks;
static void Clock_exit( void );
static rtems_isr Clock_isr( rtems_vector_number vector );
/*
* These are set by clock driver during its init
*/
rtems_device_major_number rtems_clock_major = ~0;
rtems_device_minor_number rtems_clock_minor;
/*
* The previous ISR on this clock tick interrupt vector.
*/
rtems_isr_entry Old_ticker;
/*
* Isr Handler
*/
/* Clock_isr --
* Clock interrupt handling routine.
*
* PARAMETERS:
* vector - interrupt vector number
*
* RETURNS:
* none
*/
rtems_isr
Clock_isr(rtems_vector_number vector)
{
unsigned16 tcr;
/* reset the timer underflow flag */
tcr = read16(SH7750_TCR0);
write16(tcr & ~SH7750_TCR_UNF, SH7750_TCR0);
/* Increment the clock interrupt counter */
Clock_driver_ticks++ ;
/* Invoke rtems clock service routine */
rtems_clock_tick();
}
/* Install_clock --
* Install a clock tick handler and reprograms the chip. This
* is used to initially establish the clock tick.
*
* PARAMETERS:
* clock_isr - Clock interrupt stay routine
*
* RETURNS:
* none
*
* SIDE EFFECTS:
* Establish clock interrupt handler, configure Timer 0 hardware
*/
void
Install_clock(rtems_isr_entry clock_isr)
{
int cpudiv = 1; /* CPU frequency divider */
int tidiv = 1; /* Timer input frequency divider */
unsigned32 timer_divider; /* Calculated Timer Divider value */
unsigned8 temp8;
unsigned16 temp16;
/*
* Initialize the clock tick device driver variables
*/
Clock_driver_ticks = 0;
/* Get CPU frequency divider from clock unit */
switch (read16(SH7750_FRQCR) & SH7750_FRQCR_IFC)
{
case SH7750_FRQCR_IFCDIV1:
cpudiv = 1;
break;
case SH7750_FRQCR_IFCDIV2:
cpudiv = 2;
break;
case SH7750_FRQCR_IFCDIV3:
cpudiv = 3;
break;
case SH7750_FRQCR_IFCDIV4:
cpudiv = 4;
break;
case SH7750_FRQCR_IFCDIV6:
cpudiv = 6;
break;
case SH7750_FRQCR_IFCDIV8:
cpudiv = 8;
break;
default:
rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
}
/* Get peripheral module frequency divider from clock unit */
switch (read16(SH7750_FRQCR) & SH7750_FRQCR_PFC)
{
case SH7750_FRQCR_PFCDIV2:
tidiv = 2 * CLOCK_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV3:
tidiv = 3 * CLOCK_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV4:
tidiv = 4 * CLOCK_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV6:
tidiv = 6 * CLOCK_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV8:
tidiv = 8 * CLOCK_PRESCALER;
break;
default:
rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
}
timer_divider =
(rtems_cpu_configuration_get_clicks_per_second() *
cpudiv / (tidiv*1000000)) *
rtems_configuration_get_microseconds_per_tick();
/*
* Hardware specific initialization
*/
/* Stop the Timer 0 */
temp8 = read8(SH7750_TSTR);
temp8 &= ~SH7750_TSTR_STR0;
write8(temp8, SH7750_TSTR);
/* Establish interrupt handler */
rtems_interrupt_catch( Clock_isr, CLOCK_VECTOR, &Old_ticker );
/* Reset counter */
write32(timer_divider, SH7750_TCNT0);
/* Load divider */
write32(timer_divider, SH7750_TCOR0);
write16(
SH7750_TCR_UNIE | /* Enable Underflow Interrupt */
SH7750_TCR_CKEG_RAISE | /* Count on rising edge */
TCR0_TPSC, /* Timer prescaler ratio */
SH7750_TCR0);
/* Set clock interrupt priority */
temp16 = read16(SH7750_IPRA);
temp16 = (temp16 & ~SH7750_IPRA_TMU0) | (CLOCKPRIO << SH7750_IPRA_TMU0_S);
write16(temp16, SH7750_IPRA);
/* Start the Timer 0 */
temp8 = read8(SH7750_TSTR);
temp8 |= SH7750_TSTR_STR0;
write8(temp8, SH7750_TSTR);
/*
* Schedule the clock cleanup routine to execute if the application exits.
*/
atexit( Clock_exit );
}
/* Clock_exit --
* Clean up before the application exits
*
* PARAMETERS:
* none
*
* RETURNS:
* none
*
* SIDE EFFECTS:
* Stop Timer 0 counting, set timer 0 interrupt priority level to 0.
*/
void
Clock_exit(void)
{
unsigned8 temp8 = 0;
unsigned16 temp16 = 0;
/* turn off the timer interrupts */
/* Stop the Timer 0 */
temp8 = read8(SH7750_TSTR);
temp8 &= ~SH7750_TSTR_STR0;
write8(temp8, SH7750_TSTR);
/* Lower timer interrupt priority to 0 */
temp16 = read16(SH7750_IPRA);
temp16 = (temp16 & ~SH7750_IPRA_TMU0) | (0 << SH7750_IPRA_TMU0_S);
write16(temp16, SH7750_IPRA);
/* old vector shall not be installed */
}
/* Clock_initialize --
* Device driver entry point for clock tick driver initialization.
*
* PARAMETERS:
* major - clock major device number
* minor - clock minor device number
* pargp - driver initialize primitive argument, not used
*
* RETURNS:
* RTEMS_SUCCESSFUL
*/
rtems_device_driver
Clock_initialize(rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp)
{
Install_clock( Clock_isr );
/*
* make major/minor avail to others such as shared memory driver
*/
rtems_clock_major = major;
rtems_clock_minor = minor;
return RTEMS_SUCCESSFUL;
}
/* Clock_control --
* Device driver entry point for clock driver IOCTL functions.
*
* PARAMETERS:
* major - clock major device number
* minor - clock minor device number
* pargp - driver ioctl primitive argument, not used
*
* RETURNS:
* RTEMS_SUCCESSFUL
*/
rtems_device_driver
Clock_control(rtems_device_major_number major,
rtems_device_minor_number minor,
void *pargp)
{
rtems_unsigned32 isrlevel;
rtems_libio_ioctl_args_t *args = pargp;
if (args != 0)
{
/*
* This is hokey, but until we get a defined interface
* to do this, it will just be this simple...
*/
if (args->command == rtems_build_name('I', 'S', 'R', ' '))
{
Clock_isr(CLOCK_VECTOR);
}
else if (args->command == rtems_build_name('N', 'E', 'W', ' '))
{
rtems_isr_entry ignored ;
rtems_interrupt_disable( isrlevel );
rtems_interrupt_catch( args->buffer, CLOCK_VECTOR, &ignored );
rtems_interrupt_enable( isrlevel );
}
}
return RTEMS_SUCCESSFUL;
}

View File

@@ -0,0 +1,37 @@
dnl Process this file with autoconf to produce a configure script.
dnl
dnl $Id$
AC_PREREQ(2.52)
AC_INIT
AC_CONFIG_SRCDIR([include])
RTEMS_TOP(../../../../../..)
AC_CONFIG_AUX_DIR(../../../../../..)
RTEMS_CANONICAL_TARGET_CPU
AM_INIT_AUTOMAKE(rtems-c-src-lib-libcpu-sh-sh7750,$RTEMS_VERSION,no)
AM_MAINTAINER_MODE
RTEMS_ENABLE_BARE
RTEMS_ENV_RTEMSBSP
RTEMS_CHECK_CPU
RTEMS_CANONICAL_HOST
RTEMS_PROJECT_ROOT
RTEMS_PROG_CC_FOR_TARGET
RTEMS_CANONICALIZE_TOOLS
RTEMS_CHECK_CUSTOM_BSP(RTEMS_BSP)
RTEMS_CHECK_BSP_CACHE(RTEMS_BSP)
# Explicitly list all Makefiles here
AC_CONFIG_FILES([Makefile
clock/Makefile
include/Makefile
score/Makefile
sci/Makefile
timer/Makefile])
AC_OUTPUT

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,38 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
# NOTE: Unlike other CPUS, we install into a subdirectory to avoid
# file name conflicts
include_shdir = $(includedir)/sh
include_rtems_scoredir = $(includedir)/rtems/score
include_sh_HEADERS = sh4uart.h
include_rtems_score_HEADERS = ispsh7750.h iosh7750.h
$(PROJECT_INCLUDE)/sh:
$(mkinstalldirs) $@
$(PROJECT_INCLUDE)/sh/%.h: %.h
$(INSTALL_DATA) $< $@
$(PROJECT_INCLUDE)/rtems/score/%.h: %.h
$(INSTALL_DATA) $< $@
TMPINSTALL_FILES = $(PROJECT_INCLUDE)/sh \
$(include_sh_HEADERS:%=$(PROJECT_INCLUDE)/sh/%) \
$(include_rtems_score_HEADERS:%=$(PROJECT_INCLUDE)/rtems/score/%)
all-local: $(TMPINSTALL_FILES)
# FIXME: What are these files here?
# They should either be installed or removed
EXTRA_DIST = \
ipl.h \
sh4_regs.h \
sh4uart.h \
sh7750_regs.h
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,50 @@
/*
* This include file contains information pertaining to the Hitachi SH
* processor.
*
* NOTE: NOT ALL VALUES HAVE BEEN CHECKED !!
*
* Authors: Ralf Corsepius (corsepiu@faw.uni-ulm.de) and
* Bernd Becker (becker@faw.uni-ulm.de)
*
* Based on "iosh7030.h" distributed with Hitachi's EVB's tutorials, which
* contained no copyright notice.
*
* 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.
*
* Modified to reflect on-chip registers for sh7045 processor, based on
* "Register.h" distributed with Hitachi's EVB7045F tutorials, and which
* contained no copyright notice:
* John M. Mills (jmills@tga.com)
* TGA Technologies, Inc.
* 100 Pinnacle Way, Suite 140
* Norcross, GA 30071 U.S.A.
* August, 1999
*
* This modified file may be copied and distributed in accordance
* the above-referenced license. It is provided for critique and
* developmental purposes without any warranty nor representation
* by the authors or by TGA Technologies.
*
* $Id$
*/
#ifndef __IOSH7750_H
#define __IOSH7750_H
#include "sh7750_regs.h"
#endif

View File

@@ -0,0 +1,76 @@
/* ipl.h
*
* IPL console driver
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
* Based on work:
* Author: Ralf Corsepius (corsepiu@faw.uni-ulm.de)
*
* COPYRIGHT (c) 1989-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$
*/
#ifndef __IPL_DRIVER_h
#define __IPL_DRIVER_h
#ifdef __cplusplus
extern "C" {
#endif
#define IPL_DRIVER_TABLE_ENTRY \
{ ipl_console_initialize, ipl_console_open, ipl_console_close, \
ipl_console_read, ipl_console_write, ipl_console_control }
#define NULL_SUCCESSFUL RTEMS_SUCCESSFUL
rtems_device_driver ipl_console_initialize(
rtems_device_major_number,
rtems_device_minor_number,
void *
);
rtems_device_driver ipl_console_open(
rtems_device_major_number,
rtems_device_minor_number,
void *
);
rtems_device_driver ipl_console_close(
rtems_device_major_number,
rtems_device_minor_number,
void *
);
rtems_device_driver ipl_console_read(
rtems_device_major_number,
rtems_device_minor_number,
void *
);
rtems_device_driver ipl_console_write(
rtems_device_major_number,
rtems_device_minor_number,
void *
);
rtems_device_driver ipl_console_control(
rtems_device_major_number,
rtems_device_minor_number,
void *
);
#ifdef __cplusplus
}
#endif
#endif
/* end of include file */

View File

@@ -0,0 +1,65 @@
/*
* This include file contains information pertaining to the Hitachi
* SH7750 processor.
*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
* Based on work of:
* 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.
*
* Modified to reflect isp entries for sh7045 processor:
* John M. Mills (jmills@tga.com)
* TGA Technologies, Inc.
* 100 Pinnacle Way, Suite 140
* Norcross, GA 30071 U.S.A.
*
*
* This modified file may be copied and distributed in accordance
* the above-referenced license. It is provided for critique and
* developmental purposes without any warranty nor representation
* by the authors or by TGA Technologies.
*
* $Id$
*/
#ifndef __CPU_ISPS_H
#define __CPU_ISPS_H
#ifdef __cplusplus
extern "C" {
#endif
#include <rtems/score/shtypes.h>
/* dummy ISP */
extern void _dummy_isp( void );
extern void __ISR_Handler( unsigned32 vector );
/* This variable contains VBR value used to pass control when debug, error
* or virtual memory exceptions occured.
*/
extern void *_VBR_Saved;
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,53 @@
/*
* Bits on SH-4 registers.
* See SH-4 Programming manual for more details.
*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Alexandra Kossovsky <sasha@oktet.ru>
*
* 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$
*/
#ifndef __SH4_REGS_H__
#define __SH4_REGS_H__
/* SR -- Status Register */
#define SH4_SR_MD 0x40000000 /* Priveleged mode */
#define SH4_SR_RB 0x20000000 /* General register bank specifier */
#define SH4_SR_BL 0x10000000 /* Exeption/interrupt masking bit */
#define SH4_SR_FD 0x00008000 /* FPU disable bit */
#define SH4_SR_M 0x00000200 /* For signed division:
divisor (module) is negative */
#define SH4_SR_Q 0x00000100 /* For signed division:
dividend (and quotient) is negative */
#define SH4_SR_IMASK 0x000000f0 /* Interrupt mask level */
#define SH4_SR_IMASK_S 4
#define SH4_SR_S 0x00000002 /* Saturation for MAC instruction:
if set, data in MACH/L register
is restricted to 48/32 bits
for MAC.W/L instructions */
#define SH4_SR_T 0x00000001 /* 1 if last condiyion was true */
#define SH4_SR_RESERV 0x8fff7d0d /* Reserved bits, read/write as 0 */
/* FPSCR -- FPU Starus/Control Register */
#define SH4_FPSCR_FR 0x00200000 /* FPU register bank specifier */
#define SH4_FPSCR_SZ 0x00100000 /* FMOV 64-bit transfer mode */
#define SH4_FPSCR_PR 0x00080000 /* Double-percision floating-point
operations flag */
/* SH4_FPSCR_SZ & SH4_FPSCR_PR != 1 */
#define SH4_FPSCR_DN 0x00040000 /* Treat denormalized number as zero */
#define SH4_FPSCR_CAUSE 0x0003f000 /* FPU exeption cause field */
#define SH4_FPSCR_CAUSE_S 12
#define SH4_FPSCR_ENABLE 0x00000f80 /* FPU exeption enable field */
#define SH4_FPSCR_ENABLE_s 7
#define SH4_FPSCR_FLAG 0x0000007d /* FPU exeption flag field */
#define SH4_FPSCR_FLAG_S 2
#define SH4_FPSCR_RM 0x00000001 /* Rounding mode:
1/0 -- round to zero/nearest */
#define SH4_FPSCR_RESERV 0xffd00000 /* Reserved bits, read/write as 0 */
#endif

View File

@@ -0,0 +1,178 @@
/*
* Generic UART Serial driver for SH-4 processors definitions
*
* Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
* Author: Alexandra Kossovsky <sasha@oktet.ru>
*
* 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$
*
*/
#ifndef __SH4UART_H__
#define __SH4UART_H__
#include "bsp.h"
#include "rtems/score/sh7750_regs.h"
/*
* Define this to work from gdb stub
*/
#define SH4_WITH_IPL
#define SH4_SCI 1 /* Serial Communication Interface - SCI */
#define SH4_SCIF 2 /* Serial Communication Interface with FIFO - SCIF */
#define TRANSMIT_TRIGGER_VALUE(ttrg) ((ttrg) == SH7750_SCFCR2_RTRG_1 ? 1 : \
(ttrg) == SH7750_SCFCR2_RTRG_4 ? 4 : \
(ttrg) == SH7750_SCFCR2_RTRG_8 ? 8 : 14)
/*
* Macros to call UART registers
*/
#define SCRDR(n) (*(volatile rtems_unsigned8 *)SH7750_SCRDR(n))
#define SCRDR1 SCRDR(1)
#define SCRDR2 SCRDR(2)
#define SCTDR(n) (*(volatile rtems_unsigned8 *)SH7750_SCTDR(n))
#define SCTDR1 SCTDR(1)
#define SCTDR2 SCTDR(2)
#define SCSMR(n) ((n) == 1 ? *(volatile rtems_unsigned8 *)SH7750_SCSMR1 : \
*(volatile rtems_unsigned16 *)SH7750_SCSMR2)
#define SCSMR1 SCSMR(1)
#define SCSMR2 SCSMR(2)
#define SCSCR(n) ((n) == 1 ? *(volatile rtems_unsigned8 *)SH7750_SCSCR1 : \
*(volatile rtems_unsigned16 *)SH7750_SCSCR2)
#define SCSCR1 SCSCR(1)
#define SCSCR2 SCSCR(2)
#define SCSSR(n) ((n) == 1 ? *(volatile rtems_unsigned8 *)SH7750_SCSSR1 : \
*(volatile rtems_unsigned16 *)SH7750_SCSSR2)
#define SCSSR1 SCSSR(1)
#define SCSSR2 SCSSR(2)
#define SCSPTR1 (*(volatile rtems_unsigned8 *)SH7750_SCSPTR1)
#define SCSPTR2 (*(volatile rtems_unsigned16 *)SH7750_SCSPTR2)
#define SCBRR(n) (*(volatile rtems_unsigned8 *)SH7750_SCBRR(n))
#define SCBRR1 SCBRR(1)
#define SCBRR2 SCBRR(2)
#define SCFCR2 (*(volatile rtems_unsigned16 *)SH7750_SCFCR2)
#define SCFDR2 (*(volatile rtems_unsigned16 *)SH7750_SCFDR2)
#define SCLSR2 (*(volatile rtems_unsigned16 *)SH7750_SCLSR2)
#define IPRB (*(volatile rtems_unsigned16 *)SH7750_IPRB)
#define IPRC (*(volatile rtems_unsigned16 *)SH7750_IPRC)
/*
* The following structure is a descriptor of single UART channel.
* It contains the initialization information about channel and
* current operating values
*/
typedef struct sh4uart {
rtems_unsigned8 chn; /* UART channel number */
rtems_unsigned8 int_driven; /* UART interrupt vector number, or
0 if polled I/O */
void *tty; /* termios channel descriptor */
volatile const char *tx_buf; /* Transmit buffer from termios */
volatile rtems_unsigned32 tx_buf_len; /* Transmit buffer length */
volatile rtems_unsigned32 tx_ptr; /* Index of next char to transmit*/
rtems_isr_entry old_handler_transmit; /* Saved interrupt handlers */
rtems_isr_entry old_handler_receive;
tcflag_t c_iflag; /* termios input mode flags */
rtems_boolean parerr_mark_flag; /* Parity error processing state */
} sh4uart;
/*
* Functions from sh4uart.c
*/
/* sh4uart_init --
* This function verifies the input parameters and perform initialization
* of the Motorola Coldfire on-chip UART descriptor structure.
*
*/
rtems_status_code
sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven);
/* sh4uart_reset --
* This function perform the hardware initialization of Motorola
* Coldfire processor on-chip UART controller using parameters
* filled by the sh4uart_init function.
*/
rtems_status_code
sh4uart_reset(sh4uart *uart);
/* sh4uart_disable --
* This function disable the operations on Motorola Coldfire UART
* controller
*/
rtems_status_code
sh4uart_disable(sh4uart *uart);
/* sh4uart_set_attributes --
* This function parse the termios attributes structure and perform
* the appropriate settings in hardware.
*/
rtems_status_code
sh4uart_set_attributes(sh4uart *mcf, const struct termios *t);
/* sh4uart_poll_read --
* This function tried to read character from MCF UART and perform
* error handling.
*/
int
sh4uart_poll_read(sh4uart *uart);
#ifdef SH4_WITH_IPL
/* ipl_console_poll_read --
* This function tried to read character from MCF UART over SH-IPL.
*/
int
ipl_console_poll_read(int minor);
/* sh4uart_interrupt_write --
* This function initiate transmitting of the buffer in interrupt mode.
*/
rtems_status_code
sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len);
/* sh4uart_poll_write --
* This function transmit buffer byte-by-byte in polling mode.
*/
int
sh4uart_poll_write(sh4uart *uart, const char *buf, int len);
/* ipl_console_poll_write --
* This function transmit buffer byte-by-byte in polling mode over SH-IPL.
*/
int
ipl_console_poll_write(int minor, const char *buf, int len);
/*
* ipl_finish --
* Says gdb that program finished to get out from it.
*/
extern void ipl_finish(void);
#endif
/* sh4uart_stop_remote_tx --
* This function stop data flow from remote device.
*/
rtems_status_code
sh4uart_stop_remote_tx(sh4uart *uart);
/* sh4uart_start_remote_tx --
* This function resume data flow from remote device.
*/
rtems_status_code
sh4uart_start_remote_tx(sh4uart *uart);
/* Descriptor structures for two on-chip UART channels */
extern sh4uart sh4_uarts[2];
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,29 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
PGM = $(ARCH)/sci.rel
C_FILES = console.c sh4uart.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
OBJS = $(C_O_FILES)
include $(top_srcdir)/../../../../../../make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
#
# (OPTIONAL) Add local stuff here using +=
#
$(PGM): $(OBJS)
$(make-rel)
all-local: $(ARCH) $(OBJS) $(PGM)
.PRECIOUS: $(PGM)
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,484 @@
/*
* Console driver for SH-4 UART modules
*
* Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russia
* Author: Alexandra Kossovsky <sasha@oktet.ru>
*
* COPYRIGHT (c) 1989-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 <termios.h>
#include <rtems/libio.h>
#include "sh/sh4uart.h"
/* Descriptor structures for two on-chip UART channels */
sh4uart sh4_uarts[2];
/* Console operations mode:
* 0 - raw (non-termios) polled input/output
* 1 - termios-based polled input/output
* 2 - termios-based interrupt-driven input/output
* 3 - non-termios over gdb stub
*/
int console_mode = 3;
#define CONSOLE_MODE_RAW (0)
#define CONSOLE_MODE_POLL (1)
#define CONSOLE_MODE_INT (2)
#define CONSOLE_MODE_IPL (3)
/* Wrapper functions for SH-4 UART generic driver */
/* console_poll_read --
* wrapper for poll read function
*
* PARAMETERS:
* minor - minor device number
*
* RETURNS:
* character code readed from UART, or -1 if there is no characters
* available
*/
static int
console_poll_read(int minor)
{
return sh4uart_poll_read(&sh4_uarts[minor]);
}
/* console_interrupt_write --
* wrapper for interrupt write function
*
* PARAMETERS:
* minor - minor device number
* buf - output buffer
* len - output buffer length
*
* RETURNS:
* result code
*/
static int
console_interrupt_write(int minor, const char *buf, int len)
{
return sh4uart_interrupt_write(&sh4_uarts[minor], buf, len);
}
/* console_poll_write --
* wrapper for polling mode write function
*
* PARAMETERS:
* minor - minor device number
* buf - output buffer
* len - output buffer length
*
* RETURNS:
* result code
*/
static int
console_poll_write(int minor, const char *buf, int len)
{
return sh4uart_poll_write(&sh4_uarts[minor], buf, len);
}
/* console_set_attributes --
* wrapper for hardware-dependent termios attributes setting
*
* PARAMETERS:
* minor - minor device number
* t - pointer to the termios structure
*
* RETURNS:
* result code
*/
static int
console_set_attributes(int minor, const struct termios *t)
{
return sh4uart_set_attributes(&sh4_uarts[minor], t);
}
/* console_stop_remote_tx --
* wrapper for stopping data flow from remote party.
*
* PARAMETERS:
* minor - minor device number
*
* RETURNS:
* result code
*/
static int
console_stop_remote_tx(int minor)
{
if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0]))
return sh4uart_stop_remote_tx(&sh4_uarts[minor]);
else
return RTEMS_INVALID_NUMBER;
}
/* console_start_remote_tx --
* wrapper for resuming data flow from remote party.
*
* PARAMETERS:
* minor - minor device number
*
*/
static int
console_start_remote_tx(int minor)
{
if (minor < sizeof(sh4_uarts)/sizeof(sh4_uarts[0]))
return sh4uart_start_remote_tx(&sh4_uarts[minor]);
else
return RTEMS_INVALID_NUMBER;
}
/* console_first_open --
* wrapper for UART controller initialization functions
*
* PARAMETERS:
* major - major device number
* minor - minor device number
* arg - libio device open argument
*
* RETURNS:
* error code
*/
static int
console_first_open(int major, int minor, void *arg)
{
rtems_libio_open_close_args_t *args = arg;
rtems_status_code sc;
sc = sh4uart_init(&sh4_uarts[minor], /* uart */
args->iop->data1, /* tty */
minor+1, /* channel */
(console_mode == CONSOLE_MODE_INT));
if (sc == RTEMS_SUCCESSFUL)
sc = sh4uart_reset(&sh4_uarts[minor]);
return sc;
}
/* console_last_close --
* wrapper for UART controller close function
*
* PARAMETERS:
* major - major device number
* minor - minor device number
* arg - libio device close argument
*
* RETURNS:
* error code
*/
static int
console_last_close(int major, int minor, void *arg)
{
return sh4uart_disable(&sh4_uarts[minor]);
}
/* console_reserve_resources --
* reserve termios resources for 2 UART channels
*
* PARAMETERS:
* configuration -- pointer to the RTEMS configuration table
*
* RETURNS:
* none
*/
void
console_reserve_resources(rtems_configuration_table *configuration)
{
if ((console_mode != CONSOLE_MODE_RAW) &&
(console_mode != CONSOLE_MODE_IPL))
rtems_termios_reserve_resources (configuration, 2);
}
/* console_initialize --
* This routine initializes the console IO drivers and register devices
* in RTEMS I/O system.
*
* PARAMETERS:
* major - major console device number
* minor - minor console device number (not used)
* arg - device initialize argument
*
* RETURNS:
* RTEMS error code (RTEMS_SUCCESSFUL if device initialized successfuly)
*/
rtems_device_driver
console_initialize(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
rtems_status_code status;
#ifdef SH4_WITH_IPL
/* booting from flash we cannot have IPL console */
if (boot_mode != SH4_BOOT_MODE_IPL && console_mode == CONSOLE_MODE_IPL)
console_mode = CONSOLE_MODE_INT;
/* break out from gdb if neccessary */
if (boot_mode == SH4_BOOT_MODE_IPL && console_mode != CONSOLE_MODE_IPL)
ipl_finish();
#endif
/*
* Set up TERMIOS
*/
if ((console_mode != CONSOLE_MODE_RAW) &&
(console_mode != CONSOLE_MODE_IPL))
rtems_termios_initialize ();
/*
* Register the devices
*/
status = rtems_io_register_name ("/dev/console", major, 0);
if (status != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred (status);
status = rtems_io_register_name ("/dev/aux", major, 1);
if (status != RTEMS_SUCCESSFUL)
rtems_fatal_error_occurred (status);
if (console_mode == CONSOLE_MODE_RAW)
{
rtems_status_code sc;
sc = sh4uart_init(&sh4_uarts[0], /* uart */
NULL, /* tty */
1, /* UART channel number */
0); /* Poll-mode */
if (sc == RTEMS_SUCCESSFUL)
sc = sh4uart_reset(&sh4_uarts[0]);
sc = sh4uart_init(&sh4_uarts[1], /* uart */
NULL, /* tty */
2, /* UART channel number */
0); /* Poll-mode */
if (sc == RTEMS_SUCCESSFUL)
sc = sh4uart_reset(&sh4_uarts[1]);
return sc;
}
return RTEMS_SUCCESSFUL;
}
/* console_open --
* Open console device driver. Pass appropriate termios callback
* functions to termios library.
*
* PARAMETERS:
* major - major device number for console devices
* minor - minor device number for console
* arg - device opening argument
*
* RETURNS:
* RTEMS error code
*/
rtems_device_driver
console_open(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
static const rtems_termios_callbacks intr_callbacks = {
console_first_open, /* firstOpen */
console_last_close, /* lastClose */
NULL, /* pollRead */
console_interrupt_write, /* write */
console_set_attributes, /* setAttributes */
console_stop_remote_tx, /* stopRemoteTx */
console_start_remote_tx, /* startRemoteTx */
1 /* outputUsesInterrupts */
};
static const rtems_termios_callbacks poll_callbacks = {
console_first_open, /* firstOpen */
console_last_close, /* lastClose */
console_poll_read, /* pollRead */
console_poll_write, /* write */
console_set_attributes, /* setAttributes */
console_stop_remote_tx, /* stopRemoteTx */
console_start_remote_tx, /* startRemoteTx */
0 /* outputUsesInterrupts */
};
switch (console_mode)
{
case CONSOLE_MODE_RAW:
case CONSOLE_MODE_IPL:
return RTEMS_SUCCESSFUL;
case CONSOLE_MODE_INT:
return rtems_termios_open(major, minor, arg, &intr_callbacks);
case CONSOLE_MODE_POLL:
return rtems_termios_open(major, minor, arg, &poll_callbacks);
default:
rtems_fatal_error_occurred(0xC07A1310);
}
return RTEMS_INTERNAL_ERROR;
}
/* console_close --
* Close console device.
*
* PARAMETERS:
* major - major device number for console devices
* minor - minor device number for console
* arg - device close argument
*
* RETURNS:
* RTEMS error code
*/
rtems_device_driver
console_close(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
if ((console_mode != CONSOLE_MODE_RAW) &&
(console_mode != CONSOLE_MODE_IPL))
return rtems_termios_close (arg);
else
return RTEMS_SUCCESSFUL;
}
/* console_read --
* Read from the console device
*
* PARAMETERS:
* major - major device number for console devices
* minor - minor device number for console
* arg - device read argument
*
* RETURNS:
* RTEMS error code
*/
rtems_device_driver
console_read(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
if ((console_mode != CONSOLE_MODE_RAW) &&
(console_mode != CONSOLE_MODE_IPL))
{
return rtems_termios_read (arg);
}
else
{
rtems_libio_rw_args_t *argp = arg;
char *buf = argp->buffer;
int count = argp->count;
int n = 0;
int c;
while (n < count)
{
do {
c = (console_mode == CONSOLE_MODE_RAW) ?
sh4uart_poll_read(&sh4_uarts[minor]) :
ipl_console_poll_read(minor);
} while (c == -1);
if (c == '\r')
c = '\n';
*(buf++) = c;
n++;
if (c == '\n')
break;
}
argp->bytes_moved = n;
return RTEMS_SUCCESSFUL;
}
}
/* console_write --
* Write to the console device
*
* PARAMETERS:
* major - major device number for console devices
* minor - minor device number for console
* arg - device write argument
*
* RETURNS:
* RTEMS error code
*/
rtems_device_driver
console_write(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
switch (console_mode)
{
case CONSOLE_MODE_POLL:
case CONSOLE_MODE_INT:
return rtems_termios_write (arg);
case CONSOLE_MODE_RAW:
{
rtems_libio_rw_args_t *argp = arg;
char cr = '\r';
char *buf = argp->buffer;
int count = argp->count;
int i;
for (i = 0; i < count; i++)
{
if (*buf == '\n')
sh4uart_poll_write(&sh4_uarts[minor], &cr, 1);
sh4uart_poll_write(&sh4_uarts[minor], buf, 1);
buf++;
}
argp->bytes_moved = count;
return RTEMS_SUCCESSFUL;
}
#ifdef SH4_WITH_IPL
case CONSOLE_MODE_IPL:
{
rtems_libio_rw_args_t *argp = arg;
char *buf = argp->buffer;
int count = argp->count;
ipl_console_poll_write(minor, buf, count);
argp->bytes_moved = count;
return RTEMS_SUCCESSFUL;
}
#endif
default: /* Unreachable */
return RTEMS_NOT_DEFINED;
}
}
/* console_control --
* Handle console device I/O control (IOCTL)
*
* PARAMETERS:
* major - major device number for console devices
* minor - minor device number for console
* arg - device ioctl argument
*
* RETURNS:
* RTEMS error code
*/
rtems_device_driver
console_control(rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg)
{
if ((console_mode != CONSOLE_MODE_RAW) &&
(console_mode != CONSOLE_MODE_IPL))
{
return rtems_termios_ioctl (arg);
}
else
{
return RTEMS_SUCCESSFUL;
}
}

View File

@@ -0,0 +1,945 @@
/*
* Generic UART Serial driver for SH-4 processors
*
* This driver uses variable SH4_CPU_HZ_Frequency,
* which should be defined in bsp to HZ macro.
*
* Copyright (C) 2000 OKTET Ltd., St.-Petersburg, Russian Fed.
* Author: Alexandra Kossovsky <sasha@oktet.ru>
*
* COPYRIGHT (c) 1989-2000.
* 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 <termios.h>
#include <rtems/libio.h>
#include "sh/sh4uart.h"
#ifndef SH4_UART_INTERRUPT_LEVEL
#define SH4_UART_INTERRUPT_LEVEL 4
#endif
/* Forward function declarations */
static rtems_isr
sh4uart1_interrupt_transmit(rtems_vector_number vec);
static rtems_isr
sh4uart1_interrupt_receive(rtems_vector_number vec);
static rtems_isr
sh4uart2_interrupt_transmit(rtems_vector_number vec);
static rtems_isr
sh4uart2_interrupt_receive(rtems_vector_number vec);
/*
* sh4uart_init --
* This function verifies the input parameters and perform initialization
* of the SH-4 on-chip UART descriptor structure.
*
* PARAMETERS:
* uart - pointer to the UART channel descriptor structure
* tty - pointer to termios structure
* chn - channel number (SH4_SCI/SH4_SCIF -- 1/2)
* int_driven - interrupt-driven (1) or polled (0) I/O mode
*
* RETURNS:
* RTEMS_SUCCESSFUL if all parameters are valid, or error code
*/
rtems_status_code
sh4uart_init(sh4uart *uart, void *tty, int chn, int int_driven)
{
if (uart == NULL)
return RTEMS_INVALID_ADDRESS;
if ((chn != SH4_SCI) && (chn != SH4_SCIF))
return RTEMS_INVALID_NUMBER;
uart->chn = chn;
uart->tty = tty;
uart->int_driven = int_driven;
#if 0
sh4uart_poll_write(uart, "init", 4);
#endif
return RTEMS_SUCCESSFUL;
}
/*
* sh4uart_get_Pph --
* Get current peripheral module clock.
*
* PARAMETERS: none;
* Cpu clock is get from SH4_CPU_HZ_Frequency.
* This variable should be defined in bsp.
*
* RETURNS:
* peripheral module clock in Hz.
*/
rtems_unsigned32
sh4uart_get_Pph(void)
{
rtems_unsigned16 frqcr = *(volatile rtems_unsigned16 *)SH7750_FRQCR;
rtems_unsigned32 Pph = SH4_CPU_HZ_Frequency;
switch (frqcr & SH7750_FRQCR_IFC)
{
case SH7750_FRQCR_IFCDIV1:
break;
case SH7750_FRQCR_IFCDIV2:
Pph *= 2;
break;
case SH7750_FRQCR_IFCDIV3:
Pph *= 3;
break;
case SH7750_FRQCR_IFCDIV4:
Pph *= 4;
break;
case SH7750_FRQCR_IFCDIV6:
Pph *= 6;
break;
case SH7750_FRQCR_IFCDIV8:
Pph *= 8;
break;
default: /* unreachable */
break;
}
switch (frqcr & SH7750_FRQCR_PFC)
{
case SH7750_FRQCR_PFCDIV2:
Pph /= 2;
break;
case SH7750_FRQCR_PFCDIV3:
Pph /= 3;
break;
case SH7750_FRQCR_PFCDIV4:
Pph /= 4;
break;
case SH7750_FRQCR_PFCDIV6:
Pph /= 6;
break;
case SH7750_FRQCR_PFCDIV8:
Pph /= 8;
break;
default: /* unreachable */
break;
}
return Pph;
}
/*
* sh4uart_set_baudrate --
* Program the UART timer to specified baudrate
*
* PARAMETERS:
* uart - pointer to UART descriptor structure
* baud - termios baud rate (B50, B9600, etc...)
*
* ALGORITHM:
* see SH7750 Hardware Manual.
*
* RETURNS:
* none
*/
static void
sh4uart_set_baudrate(sh4uart *uart, speed_t baud)
{
rtems_unsigned32 rate;
rtems_signed16 div;
int n;
rtems_unsigned32 Pph = sh4uart_get_Pph();
switch (baud)
{
case B50: rate = 50; break;
case B75: rate = 75; break;
case B110: rate = 110; break;
case B134: rate = 134; break;
case B150: rate = 150; break;
case B200: rate = 200; break;
case B300: rate = 300; break;
case B600: rate = 600; break;
case B1200: rate = 1200; break;
case B2400: rate = 2400; break;
case B4800: rate = 4800; break;
case B9600: rate = 9600; break;
case B19200: rate = 19200; break;
case B38400: rate = 38400; break;
case B57600: rate = 57600; break;
#ifdef B115200
case B115200: rate = 115200; break;
#endif
#ifdef B230400
case B230400: rate = 230400; break;
#endif
default: rate = 9600; break;
}
for (n = 0; n < 4; n++)
{
div = Pph / (32 * (1 << (2 * n)) * rate) - 1;
if (div < 0x100)
break;
}
/* Set default baudrate if specified baudrate is impossible */
if (n >= 4)
sh4uart_set_baudrate(uart, B9600);
SCSMR(uart->chn) &= ~SH7750_SCSMR_CKS;
SCSMR(uart->chn) |= n << SH7750_SCSMR_CKS_S;
SCBRR(uart->chn) = div;
/* Whait at least 1 bit interwal */
rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(1000 / rate));
}
/*
* sh4uart_reset --
* This function perform the hardware initialization of SH-4
* on-chip UART controller using parameters
* filled by the sh4uart_init function.
*
* PARAMETERS:
* uart - pointer to UART channel descriptor structure
*
* RETURNS:
* RTEMS_SUCCESSFUL if channel is initialized successfully, error
* code in other case
*/
rtems_status_code
sh4uart_reset(sh4uart *uart)
{
register int chn;
register int int_driven;
rtems_status_code rc;
if (uart == NULL)
return RTEMS_INVALID_ADDRESS;
chn = uart->chn;
int_driven = uart->int_driven;
SCSCR(chn) = 0x0; /* Is set properly at the end of this function */
SCSMR(chn) = 0x0; /* 8-bit, non-parity, 1 stop bit, pf/1 clock */
if (chn == SH4_SCIF)
SCFCR2 = SH7750_SCFCR2_TFRST | SH7750_SCFCR2_RFRST |
SH7750_SCFCR2_RTRG_1 | SH7750_SCFCR2_TTRG_4;
if (chn == SH4_SCI)
SCSPTR1 = int_driven ? 0x0 : SH7750_SCSPTR1_EIO;
else
SCSPTR2 = SH7750_SCSPTR2_RTSDT;
if (int_driven)
{
rtems_unsigned16 ipr;
if (chn == SH4_SCI)
{
ipr = IPRB;
ipr &= ~SH7750_IPRB_SCI1;
ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRB_SCI1_S;
IPRB = ipr;
rc = rtems_interrupt_catch(sh4uart1_interrupt_transmit,
SH7750_EVT_TO_NUM(SH7750_EVT_SCI_TXI),
&uart->old_handler_transmit);
if (rc != RTEMS_SUCCESSFUL)
return rc;
rc = rtems_interrupt_catch(sh4uart1_interrupt_receive,
SH7750_EVT_TO_NUM(SH7750_EVT_SCI_RXI),
&uart->old_handler_receive);
if (rc != RTEMS_SUCCESSFUL)
return rc;
}
else
{
ipr = IPRC;
ipr &= ~SH7750_IPRC_SCIF;
ipr |= SH4_UART_INTERRUPT_LEVEL << SH7750_IPRC_SCIF_S;
IPRC = ipr;
rc = rtems_interrupt_catch(sh4uart2_interrupt_transmit,
SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_TXI),
&uart->old_handler_transmit);
if (rc != RTEMS_SUCCESSFUL)
return rc;
rc = rtems_interrupt_catch(sh4uart2_interrupt_receive,
SH7750_EVT_TO_NUM(SH7750_EVT_SCIF_RXI),
&uart->old_handler_receive);
if (rc != RTEMS_SUCCESSFUL)
return rc;
}
uart->tx_buf = NULL;
uart->tx_ptr = uart->tx_buf_len = 0;
}
sh4uart_set_baudrate(uart, B38400); /* debug defaults (unfortunately,
it is differ to termios default */
SCSCR(chn) = SH7750_SCSCR_TE | SH7750_SCSCR_RE |
(chn == SH4_SCI ? 0x0 : SH7750_SCSCR2_REIE) |
(int_driven ? (SH7750_SCSCR_RIE | SH7750_SCSCR_TIE) : 0x0);
return RTEMS_SUCCESSFUL;
}
/*
* sh4uart_disable --
* This function disable the operations on SH-4 UART controller
*
* PARAMETERS:
* uart - pointer to UART channel descriptor structure
*
* RETURNS:
* RTEMS_SUCCESSFUL if UART closed successfuly, or error code in
* other case
*/
rtems_status_code
sh4uart_disable(sh4uart *uart)
{
rtems_status_code rc;
SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
if (uart->int_driven)
{
rc = rtems_interrupt_catch(uart->old_handler_transmit,
uart->chn == SH4_SCI ?
SH7750_EVT_SCI_TXI : SH7750_EVT_SCIF_TXI,
NULL);
if (rc != RTEMS_SUCCESSFUL)
return rc;
rc = rtems_interrupt_catch(uart->old_handler_receive,
uart->chn == SH4_SCI ?
SH7750_EVT_SCI_RXI : SH7750_EVT_SCIF_RXI,
NULL);
if (rc != RTEMS_SUCCESSFUL)
return rc;
}
return RTEMS_SUCCESSFUL;
}
/*
* sh4uart_set_attributes --
* This function parse the termios attributes structure and perform
* the appropriate settings in hardware.
*
* PARAMETERS:
* uart - pointer to the UART descriptor structure
* t - pointer to termios parameters
*
* RETURNS:
* RTEMS_SUCCESSFUL
*/
rtems_status_code
sh4uart_set_attributes(sh4uart *uart, const struct termios *t)
{
int level;
speed_t baud;
rtems_unsigned16 smr;
smr = (rtems_unsigned16)(*(rtems_unsigned8 *)SH7750_SCSMR(uart->chn));
baud = cfgetospeed(t);
/* Set flow control XXX*/
if ((t->c_cflag & CRTSCTS) != 0)
{
}
/* Set character size -- only 7 or 8 bit */
switch (t->c_cflag & CSIZE)
{
case CS5:
case CS6:
case CS7: smr |= SH7750_SCSMR_CHR_7; break;
case CS8: smr &= ~SH7750_SCSMR_CHR_7; break;
}
/* Set number of stop bits */
if ((t->c_cflag & CSTOPB) != 0)
smr |= SH7750_SCSMR_STOP_2;
else
smr &= ~SH7750_SCSMR_STOP_2;
/* Set parity mode */
if ((t->c_cflag & PARENB) != 0)
{
smr |= SH7750_SCSMR_PE;
if ((t->c_cflag & PARODD) != 0)
smr |= SH7750_SCSMR_PM_ODD;
else
smr &= ~SH7750_SCSMR_PM_ODD;
}
else
smr &= ~SH7750_SCSMR_PE;
rtems_interrupt_disable(level);
/* wait untill all data is transmitted */
rtems_task_wake_after(RTEMS_MILLISECONDS_TO_TICKS(100));
/* disable operations */
SCSCR(uart->chn) &= ~(SH7750_SCSCR_TE | SH7750_SCSCR_RE);
sh4uart_set_baudrate(uart, baud);
SCSMR(uart->chn) = (rtems_unsigned8)smr;
/* enable operations */
SCSCR(uart->chn) |= SH7750_SCSCR_TE | SH7750_SCSCR_RE;
rtems_interrupt_enable(level);
return RTEMS_SUCCESSFUL;
}
/*
* sh4uart_handle_error --
* Perfoms error (Overrun, Framing & Parity) handling
*
* PARAMETERS:
* uart - pointer to UART descriptor structure
*
* RETURNS:
* nothing
*/
void
sh4uart_handle_error(sh4uart *uart)
{
#if 0
int status_reg = SCSSR(uart->chn);
#endif
if(uart->chn == SH4_SCI)
{
SCSSR1 &= ~(SH7750_SCSSR1_ORER | SH7750_SCSSR1_FER | SH7750_SCSSR1_PER);
}
else
{
SCSSR2 &= ~(SH7750_SCSSR2_ER | SH7750_SCSSR2_BRK | SH7750_SCSSR2_FER);
SCLSR2 &= ~(SH7750_SCLSR2_ORER);
}
}
/*
* sh4uart_poll_read --
* This function tried to read character from SH-4 UART and perform
* error handling. When parity or framing error occured, return
* value dependent on termios input mode flags:
* - received character, if IGNPAR == 1
* - 0, if IGNPAR == 0 and PARMRK == 0
* - 0xff and 0x00 on next poll_read invocation, if IGNPAR == 0 and
* PARMRK == 1
*
* PARAMETERS:
* uart - pointer to UART descriptor structure
*
* RETURNS:
* code of received character or -1 if no characters received.
*/
int
sh4uart_poll_read(sh4uart *uart)
{
int chn = uart->chn;
int error_occured = 0;
int parity_error = 0;
int break_occured = 0;
int ch;
if (uart->parerr_mark_flag == 1)
{
uart->parerr_mark_flag = 0;
return 0;
}
if (chn == SH4_SCI)
{
if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
SH7750_SCSSR1_ORER)) != 0)
{
error_occured = 1;
if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
parity_error = 1;
sh4uart_handle_error(uart);
}
if ((SCSSR1 & SH7750_SCSSR1_RDRF) == 0)
return -1;
}
else
{
if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
SH7750_SCSSR2_BRK)) != 0 ||
(SCLSR2 & SH7750_SCLSR2_ORER) != 0)
{
error_occured = 1;
if (SCSSR2 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
parity_error = 1;
if (SCSSR2 & SH7750_SCSSR2_BRK)
break_occured = 1;
sh4uart_handle_error(uart);
}
if ((SCSSR2 & SH7750_SCSSR2_RDF) == 0)
return -1;
}
if (parity_error && !(uart->c_iflag & IGNPAR))
{
if (uart->c_iflag & PARMRK)
{
uart->parerr_mark_flag = 1;
return 0xff;
}
else
return 0;
}
if (break_occured && !(uart->c_iflag & BRKINT))
{
if (uart->c_iflag & IGNBRK)
return 0;
else
return 0; /* XXX -- SIGINT */
}
ch = SCRDR(chn);
if (uart->chn == SH4_SCI)
SCSSR1 &= ~SH7750_SCSSR1_RDRF;
else
SCSSR2 &= ~SH7750_SCSSR2_RDF;
return ch;
}
/*
* sh4uart_poll_write --
* This function transmit buffer byte-by-byte in polling mode.
*
* PARAMETERS:
* uart - pointer to the UART descriptor structure
* buf - pointer to transmit buffer
* len - transmit buffer length
*
* RETURNS:
* 0
*/
int
sh4uart_poll_write(sh4uart *uart, const char *buf, int len)
{
while (len)
{
if (uart->chn == SH4_SCI)
{
while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0)
{
SCTDR1 = *buf++;
len--;
SCSSR1 &= ~SH7750_SCSSR1_TDRE;
}
}
else
{
while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0)
{
int i;
for (i = 0;
i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
SH7750_SCFCR2_TTRG);
i++)
{
SCTDR2 = *buf++;
len--;
}
while ((SCSSR2 & SH7750_SCSSR2_TDFE) == 0 ||
(SCSSR2 & SH7750_SCSSR2_TEND) == 0);
SCSSR2 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
}
}
}
return 0;
}
/**********************************
* Functions to handle interrupts *
**********************************/
/* sh4uart1_interrupt_receive --
* UART interrupt handler routine -- SCI
* Receiving data
*
* PARAMETERS:
* vec - interrupt vector number
*
* RETURNS:
* none
*/
static rtems_isr
sh4uart1_interrupt_receive(rtems_vector_number vec)
{
register int bp = 0;
char buf[32];
/* Find UART descriptor from vector number */
sh4uart *uart = &sh4_uarts[0];
while (1)
{
if ((bp < sizeof(buf) - 1) && ((SCSSR1 & SH7750_SCSSR1_RDRF) != 0))
{
/* Receive character and handle frame/parity errors */
if ((SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER |
SH7750_SCSSR1_ORER)) != 0)
{
if (SCSSR1 & (SH7750_SCSSR1_PER | SH7750_SCSSR1_FER))
{
if(!(uart->c_iflag & IGNPAR))
{
if (uart->c_iflag & PARMRK)
{
buf[bp++] = 0xff;
buf[bp++] = 0x00;
}
else
buf[bp++] = 0x00;
}
else
buf[bp++] = SCRDR1;
}
sh4uart_handle_error(uart);
}
else
buf[bp++] = SCRDR1;
SCSSR1 &= ~SH7750_SCSSR1_RDRF;
}
else
{
if (bp != 0)
rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
break;
}
}
}
/* sh4uart2_interrupt_receive --
* UART interrupt handler routine -- SCIF
* Receiving data
*
* PARAMETERS:
* vec - interrupt vector number
*
* RETURNS:
* none
*/
static rtems_isr
sh4uart2_interrupt_receive(rtems_vector_number vec)
{
register int bp = 0;
char buf[32];
/* Find UART descriptor from vector number */
sh4uart *uart = &sh4_uarts[1];
while (1)
{
if ((bp < sizeof(buf) - 1) && ((SCSSR2 & SH7750_SCSSR2_RDF) != 0))
{
if ((SCSSR2 & (SH7750_SCSSR2_ER | SH7750_SCSSR2_DR |
SH7750_SCSSR2_BRK)) != 0 ||
(SH7750_SCLSR2 & SH7750_SCLSR2_ORER) != 0)
{
if (SCSSR2 & SH7750_SCSSR2_ER)
{
if(!(uart->c_iflag & IGNPAR))
{
if (uart->c_iflag & PARMRK)
{
buf[bp++] = 0xff;
buf[bp++] = 0x00;
}
else
buf[bp++] = 0x00;
}
else
buf[bp++] = SCRDR1;
}
if (SCSSR2 & SH7750_SCSSR2_BRK)
{
if (uart->c_iflag & IGNBRK)
buf[bp++] = 0x00;
else
buf[bp++] = 0x00; /* XXX -- SIGINT */
}
sh4uart_handle_error(uart);
}
else
buf[bp++] = SCRDR1;
SCSSR2 &= ~SH7750_SCSSR2_RDF;
}
else
{
if (bp != 0)
rtems_termios_enqueue_raw_characters(uart->tty, buf, bp);
break;
}
}
}
/* sh4uart1_interrupt_transmit --
* UART interrupt handler routine -- SCI
* It continues transmit data when old part of data is transmitted
*
* PARAMETERS:
* vec - interrupt vector number
*
* RETURNS:
* none
*/
static rtems_isr
sh4uart1_interrupt_transmit(rtems_vector_number vec)
{
/* Find UART descriptor from vector number */
sh4uart *uart = &sh4_uarts[0];
if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len)
{
while ((SCSSR1 & SH7750_SCSSR1_TDRE) != 0 &&
uart->tx_ptr < uart->tx_buf_len)
{
SCTDR1 = uart->tx_buf[uart->tx_ptr++];
SCSSR1 &= ~SH7750_SCSSR1_TDRE;
}
}
else
{
register int dequeue = uart->tx_buf_len;
uart->tx_buf = NULL;
uart->tx_ptr = uart->tx_buf_len = 0;
/* Disable interrupts while we do not have any data to transmit */
SCSCR1 &= ~SH7750_SCSCR_TIE;
rtems_termios_dequeue_characters(uart->tty, dequeue);
}
}
/* sh4uart2_interrupt_transmit --
* UART interrupt handler routine -- SCI
* It continues transmit data when old part of data is transmitted
*
* PARAMETERS:
* vec - interrupt vector number
*
* RETURNS:
* none
*/
static rtems_isr
sh4uart2_interrupt_transmit(rtems_vector_number vec)
{
/* Find UART descriptor from vector number */
sh4uart *uart = &sh4_uarts[1];
if (uart->tx_buf != NULL && uart->tx_ptr < uart->tx_buf_len)
{
while ((SCSSR2 & SH7750_SCSSR2_TDFE) != 0)
{
int i;
for (i = 0;
i < 16 - TRANSMIT_TRIGGER_VALUE(SCFCR2 &
SH7750_SCFCR2_TTRG);
i++)
SCTDR2 = uart->tx_buf[uart->tx_ptr++];
while ((SCSSR1 & SH7750_SCSSR1_TDRE) == 0 ||
(SCSSR1 & SH7750_SCSSR1_TEND) == 0);
SCSSR1 &= ~(SH7750_SCSSR1_TDRE | SH7750_SCSSR2_TEND);
}
}
else
{
register int dequeue = uart->tx_buf_len;
uart->tx_buf = NULL;
uart->tx_ptr = uart->tx_buf_len = 0;
/* Disable interrupts while we do not have any data to transmit */
SCSCR2 &= ~SH7750_SCSCR_TIE;
rtems_termios_dequeue_characters(uart->tty, dequeue);
}
}
/* sh4uart_interrupt_write --
* This function initiate transmitting of the buffer in interrupt mode.
*
* PARAMETERS:
* uart - pointer to the UART descriptor structure
* buf - pointer to transmit buffer
* len - transmit buffer length
*
* RETURNS:
* 0
*/
rtems_status_code
sh4uart_interrupt_write(sh4uart *uart, const char *buf, int len)
{
int level;
while ((SCSSR1 & SH7750_SCSSR1_TEND) == 0);
rtems_interrupt_disable(level);
uart->tx_buf = buf;
uart->tx_buf_len = len;
uart->tx_ptr = 0;
if (uart->chn == SH4_SCI)
{
SCSCR1 |= SH7750_SCSCR_TIE;
}
else
SCSCR2 |= SH7750_SCSCR_TIE;
rtems_interrupt_enable(level);
return RTEMS_SUCCESSFUL;
}
/* sh4uart_stop_remote_tx --
* This function stop data flow from remote device.
*
* PARAMETERS:
* uart - pointer to the UART descriptor structure
*
* RETURNS:
* RTEMS_SUCCESSFUL
*/
rtems_status_code
sh4uart_stop_remote_tx(sh4uart *uart)
{
SCSCR(uart->chn) &= ~(SH7750_SCSCR_RIE | SH7750_SCSCR_RE);
return RTEMS_SUCCESSFUL;
}
/* sh4uart_start_remote_tx --
* This function resume data flow from remote device.
*
* PARAMETERS:
* uart - pointer to the UART descriptor structure
*
* RETURNS:
* RTEMS_SUCCESSFUL
*/
rtems_status_code
sh4uart_start_remote_tx(sh4uart *uart)
{
SCSCR(uart->chn) |= SH7750_SCSCR_RIE | SH7750_SCSCR_RE;
return RTEMS_SUCCESSFUL;
}
#ifdef SH4_WITH_IPL
/*********************************
* Functions for SH-IPL gdb stub *
*********************************/
/*
* ipl_finish --
* Says gdb that program finished to get out from it.
*/
extern void ipl_finish(void);
asm(
" .global _ipl_finish\n"
"_ipl_finish:\n"
" mov.l __ipl_finish_value, r0\n"
" trapa #0x3f\n"
" nop\n"
" rts\n"
" nop\n"
" .align 4\n"
"__ipl_finish_value:\n"
" .long 255"
);
extern int ipl_serial_input(int poll_count);
asm(
" .global _ipl_serial_input\n"
"_ipl_serial_input:\n"
" mov #1,r0\n"
" trapa #0x3f\n"
" nop\n"
" rts\n"
" nop\n");
extern void ipl_serial_output(const char *buf, int len);
asm (
" .global _ipl_serial_output\n"
"_ipl_serial_output:\n"
" mov #0,r0\n"
" trapa #0x3f\n"
" nop\n"
" rts\n"
" nop\n");
/* ipl_console_poll_read --
* poll read operation for simulator console through ipl mechanism.
*
* PARAMETERS:
* minor - minor device number
*
* RETURNS:
* character code red from UART, or -1 if there is no characters
* available
*/
int
ipl_console_poll_read(int minor)
{
unsigned char buf;
buf = ipl_serial_input(0x100000);
return buf;
}
/* ipl_console_poll_write --
* wrapper for polling mode write function
*
* PARAMETERS:
* minor - minor device number
* buf - output buffer
* len - output buffer length
*
* RETURNS:
* result code (0)
*/
int
ipl_console_poll_write(int minor, const char *buf, int len)
{
int c;
while (len > 0)
{
c = (len < 64 ? len : 64);
ipl_serial_output(buf, c);
len -= c;
buf += c;
}
return 0;
}
#endif

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,31 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
PGM = $(ARCH)/score.rel
C_FILES = cpu_asm.c ispsh7750.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
OBJS = $(C_O_FILES)
include $(top_srcdir)/../../../../../../make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
#
# (OPTIONAL) Add local stuff here using +=
#
$(PGM): $(OBJS)
$(make-rel)
all-local: $(ARCH) $(OBJS) $(PGM)
.PRECIOUS: $(PGM)
EXTRA_DIST = ispsh7750.c cpu_asm.c
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,312 @@
/*
* This file contains the basic algorithms for all assembly code used
* in an specific CPU port of RTEMS. These algorithms must be implemented
* in assembly language
*
* NOTE: This port uses a C file with inline assembler instructions
*
* 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$
*
* This material may be reproduced by or for the U.S. Government pursuant
* to the copyright license under the clause at DFARS 252.227-7013. This
* notice must appear in all copies of this file and its derivatives.
*
*/
/*
* This is supposed to be an assembly file. This means that system.h
* and cpu.h should not be included in a "real" cpu_asm file. An
* implementation in assembly should include "cpu_asm.h"
*/
#include <rtems/system.h>
#include <rtems/score/cpu.h>
#include <rtems/score/isr.h>
#include <rtems/score/thread.h>
#include <rtems/score/sh.h>
#include <rtems/score/ispsh7750.h>
#include <rtems/score/iosh7750.h>
#include <rtems/score/sh4_regs.h>
#include <rtems/score/sh_io.h>
/* from cpu_isps.c */
extern proc_ptr _Hardware_isr_Table[];
#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
unsigned long *_old_stack_ptr;
#endif
register unsigned long *stack_ptr asm("r15");
/*
* _CPU_Context_save_fp_context
*
* This routine is responsible for saving the FP context
* at *fp_context_ptr. If the point to load the FP context
* from is changed then the pointer is modified by this routine.
*
* Sometimes a macro implementation of this is in cpu.h which dereferences
* the ** and a similarly named routine in this file is passed something
* like a (Context_Control_fp *). The general rule on making this decision
* is to avoid writing assembly language.
*/
void _CPU_Context_save_fp(
void **fp_context_ptr /* r4 */
)
{
#if SH_HAS_FPU
asm volatile("
mov.l @%0,r4
add %1,r4
sts.l fpscr,@-r4
sts.l fpul,@-r4
lds %2,fpscr
fmov dr14,@-r4
fmov dr12,@-r4
fmov dr10,@-r4
fmov dr8,@-r4
fmov dr6,@-r4
fmov dr4,@-r4
fmov dr2,@-r4
fmov dr0,@-r4
"
#ifdef SH4_USE_X_REGISTERS
"
lds %3,fpscr
fmov xd14,@-r4
fmov xd12,@-r4
fmov xd10,@-r4
fmov xd8,@-r4
fmov xd6,@-r4
fmov xd4,@-r4
fmov xd2,@-r4
fmov xd0,@-r4
"
#endif
"lds %4,fpscr
"
:
: "r"(fp_context_ptr), "r"(sizeof(Context_Control_fp)),
"r"(SH4_FPSCR_SZ), "r"(SH4_FPSCR_PR | SH4_FPSCR_SZ), "r"(SH4_FPSCR_PR)
: "r4", "r0");
#endif
}
/*
* _CPU_Context_restore_fp_context
*
* This routine is responsible for restoring the FP context
* at *fp_context_ptr. If the point to load the FP context
* from is changed then the pointer is modified by this routine.
*
* Sometimes a macro implementation of this is in cpu.h which dereferences
* the ** and a similarly named routine in this file is passed something
* like a (Context_Control_fp *). The general rule on making this decision
* is to avoid writing assembly language.
*/
void _CPU_Context_restore_fp(
void **fp_context_ptr /* r4 */
)
{
#if SH_HAS_FPU
asm volatile("
mov.l @%0,r4
"
#ifdef SH4_USE_X_REGISTERS
"
lds %1,fpscr
fmov @r4+,xd0
fmov @r4+,xd2
fmov @r4+,xd4
fmov @r4+,xd6
fmov @r4+,xd8
fmov @r4+,xd10
fmov @r4+,xd12
fmov @r4+,xd14
"
#endif
"
lds %2,fpscr
fmov @r4+,dr0
fmov @r4+,dr2
fmov @r4+,dr4
fmov @r4+,dr6
fmov @r4+,dr8
fmov @r4+,dr10
fmov @r4+,dr12
fmov @r4+,dr14
lds.l @r4+,fpul
lds.l @r4+,fpscr
" :
: "r"(fp_context_ptr), "r"(SH4_FPSCR_PR | SH4_FPSCR_SZ), "r"(SH4_FPSCR_SZ)
: "r4", "r0");
#endif
}
/* _CPU_Context_switch
*
* This routine performs a normal non-FP context switch.
*/
/* within __CPU_Context_switch:
* _CPU_Context_switch
* _CPU_Context_restore
*
* This routine is generally used only to restart self in an
* efficient manner. It may simply be a label in _CPU_Context_switch.
*
* NOTE: It should be safe not to store r4, r5
*
* NOTE: It is doubtful if r0 is really needed to be stored
*
* NOTE: gbr is added, but should not be necessary, as it is
* only used globally in this port.
*/
/*
* FIXME: This is an ugly hack, but we wanted to avoid recalculating
* the offset each time Context_Control is changed
*/
void __CPU_Context_switch(
Context_Control *run, /* r4 */
Context_Control *heir /* r5 */
)
{
asm volatile("
.global __CPU_Context_switch
__CPU_Context_switch:
add %0,r4
stc.l sr,@-r4
stc.l gbr,@-r4
mov.l r0,@-r4
mov.l r1,@-r4
mov.l r2,@-r4
mov.l r3,@-r4
mov.l r6,@-r4
mov.l r7,@-r4
mov.l r8,@-r4
mov.l r9,@-r4
mov.l r10,@-r4
mov.l r11,@-r4
mov.l r12,@-r4
mov.l r13,@-r4
mov.l r14,@-r4
sts.l pr,@-r4
sts.l mach,@-r4
sts.l macl,@-r4
mov.l r15,@-r4
mov r5, r4"
:: "I" (sizeof(Context_Control))
);
asm volatile("
.global __CPU_Context_restore
__CPU_Context_restore:
mov.l @r4+,r15
lds.l @r4+,macl
lds.l @r4+,mach
lds.l @r4+,pr
mov.l @r4+,r14
mov.l @r4+,r13
mov.l @r4+,r12
mov.l @r4+,r11
mov.l @r4+,r10
mov.l @r4+,r9
mov.l @r4+,r8
mov.l @r4+,r7
mov.l @r4+,r6
mov.l @r4+,r3
mov.l @r4+,r2
mov.l @r4+,r1
mov.l @r4+,r0
ldc.l @r4+,gbr
ldc.l @r4+,sr
rts
nop" );
}
/*
* This routine provides the RTEMS interrupt management.
*/
void __ISR_Handler( unsigned32 vector)
{
register unsigned32 level;
_CPU_ISR_Disable( level );
_Thread_Dispatch_disable_level++;
#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
if( _ISR_Nest_level == 0 )
{
/* Install irq stack */
_old_stack_ptr = stack_ptr;
stack_ptr = _CPU_Interrupt_stack_high;
}
#endif
_ISR_Nest_level++;
_CPU_ISR_Enable( level );
/* call isp */
if( _ISR_Vector_table[ vector])
(*_ISR_Vector_table[ vector ])( vector );
_CPU_ISR_Disable( level );
_ISR_Nest_level--;
#if( CPU_HAS_SOFTWARE_INTERRUPT_STACK == TRUE)
if( _ISR_Nest_level == 0 )
/* restore old stack pointer */
stack_ptr = _old_stack_ptr;
#endif
_Thread_Dispatch_disable_level--;
_CPU_ISR_Enable( level );
if ( _Thread_Dispatch_disable_level == 0 )
{
if(( _Context_Switch_necessary) || (! _ISR_Signals_to_thread_executing))
{
_ISR_Signals_to_thread_executing = FALSE;
_Thread_Dispatch();
}
}
}

View File

@@ -0,0 +1,351 @@
/*
* SH7750 interrupt support.
*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
* Based on work:
* 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.
*
* Modified to reflect isp entries for sh7045 processor:
* John M. Mills (jmills@tga.com)
* TGA Technologies, Inc.
* 100 Pinnacle Way, Suite 140
* Norcross, GA 30071 U.S.A.
* August, 1999
*
* This modified file may be copied and distributed in accordance
* the above-referenced license. It is provided for critique and
* developmental purposes without any warranty nor representation
* by the authors or by TGA Technologies.
*
* $Id$
*/
#include <rtems/system.h>
#include <rtems/score/shtypes.h>
#include <rtems/score/isr.h>
#if !defined (sh7750)
#error Wrong CPU MODEL
#endif
/*
* This is a exception vector table
*
* It has the same structure as the actual vector table (vectab)
*/
#include <rtems/score/ispsh7750.h>
#include <rtems/score/sh7750_regs.h>
/* VBR register contents saved on startup -- used to hook exception by debug
* agent */
void *_VBR_Saved;
/*PAGE
*
* _CPU_ISR_install_vector
*
* This kernel routine installs the RTEMS handler for the
* specified vector.
*
* Input parameters:
* vector - interrupt vector number
* old_handler - former ISR for this vector number
* new_handler - replacement ISR for this vector number
*
* Output parameters: NONE
*
*/
void _CPU_ISR_install_vector(
unsigned32 vector,
proc_ptr new_handler,
proc_ptr *old_handler
)
{
*old_handler = _ISR_Vector_table[vector];
_ISR_Vector_table[vector] = new_handler;
}
#define __STRINGIFY1__(x) #x
#define __STRINGIFY__(x) __STRINGIFY1__(x)
#define STOP_TIMER \
" mov.l TSTR_k,r0 \n" \
" mov.b @r0,r1 \n" \
" and #" __STRINGIFY__(~SH7750_TSTR_STR0) ",r1\n" \
" mov.b r1,@r0 \n"
#define START_TIMER \
" mov.l TSTR_k,r0 \n" \
" mov.b @r0,r1 \n" \
" or #" __STRINGIFY__(SH7750_TSTR_STR0) ",r1\n" \
" mov.b r1,@r0 \n"
asm (" .text\n"
" .balign 256\n"
" .global __vbr_base\n"
"__vbr_base:\n"
" .org __vbr_base + 0x100\n"
"vbr_100:\n"
" mov.l r0,@-r15\n"
" mov.l r1,@-r15\n"
" mov.l __VBR_Saved100_k, r0\n"
" mov.l offset100_k,r1\n"
" mov.l @r0,r0\n"
" add r1,r0\n"
" mov.l @r15+,r1\n"
" jmp @r0\n"
" mov.l @r15+,r0\n"
" .align 2\n"
"__VBR_Saved100_k:\n"
" .long __VBR_Saved\n"
"offset100_k:\n"
" .long 0x100\n"
" .org __vbr_base + 0x400\n"
"vbr_400:\n"
" mov.l r0,@-r15\n"
" mov.l r1,@-r15\n"
" mov.l __VBR_Saved400_k, r0\n"
" mov.l offset400_k,r1\n"
" mov.l @r0,r0\n"
" add r1,r0\n"
" mov.l @r15+,r1\n"
" jmp @r0\n"
" mov.l @r15+,r0\n"
" .align 2\n"
"__VBR_Saved400_k:\n"
" .long __VBR_Saved\n"
"offset400_k:\n"
" .long 0x400\n"
" .org __vbr_base + 0x600\n"
"vbr_600:\n"
" mov.l r0,@-r15 \n"
" mov.l r1,@-r15 \n"
" stc sr,r0 \n"
" mov.l __vbr_600_sr_and_k,r1\n"
" and r1,r0 \n"
" mov.l __vbr_600_sr_or_k,r1\n"
" or r1,r0 \n"
" ldc r0,sr \n"
" ldc.l @r15+,r1_bank\n"
" ldc.l @r15+,r0_bank\n"
" mov.l r0,@-r15 \n"
" mov.l r1,@-r15 \n"
" mov.l r2,@-r15 \n"
" mov.l r3,@-r15 \n"
" mov.l r4,@-r15 \n"
" mov.l r5,@-r15 \n"
" mov.l r6,@-r15 \n"
" mov.l r7,@-r15 \n"
#if 0
" mov.l r8,@-r15 \n"
" mov.l r9,@-r15 \n"
" mov.l r10,@-r15 \n"
" mov.l r11,@-r15 \n"
" mov.l r12,@-r15 \n"
" mov.l r13,@-r15 \n"
#endif
" mov.l r14,@-r15 \n"
" sts.l fpscr,@-r15\n"
" sts.l fpul,@-r15 \n"
" mov.l __ISR_temp_fpscr_k,r0 \n"
" lds r0,fpscr \n"
" fmov fr0,@-r15 \n"
" fmov fr1,@-r15 \n"
" fmov fr2,@-r15 \n"
" fmov fr3,@-r15 \n"
" fmov fr4,@-r15 \n"
" fmov fr5,@-r15 \n"
" fmov fr6,@-r15 \n"
" fmov fr7,@-r15 \n"
" fmov fr8,@-r15 \n"
" fmov fr9,@-r15 \n"
" fmov fr10,@-r15 \n"
" fmov fr11,@-r15 \n"
" fmov fr12,@-r15 \n"
" fmov fr13,@-r15 \n"
" fmov fr14,@-r15 \n"
" fmov fr15,@-r15 \n"
" sts.l pr,@-r15 \n"
" sts.l mach,@-r15 \n"
" sts.l macl,@-r15 \n"
" stc.l spc,@-r15 \n"
" stc.l ssr,@-r15 \n"
" mov r15,r14 \n"
#if 0
" stc ssr,r0 \n"
" ldc r0,sr \n"
#endif
" mov.l __ISR_Handler_k, r1\n"
" mov.l _INTEVT_k,r4\n"
" mov.l @r4,r4 \n"
" shlr2 r4 \n"
" shlr r4 \n"
" mov.l _ISR_Table_k,r0\n"
" mov.l @r0,r0 \n"
" add r4,r0 \n"
" mov.l @r0,r0 \n"
" cmp/eq #0,r0 \n"
" bt _ipl_hook \n"
" jsr @r1 \n"
" shlr2 r4 \n"
" mov r14,r15 \n"
" ldc.l @r15+,ssr \n"
" ldc.l @r15+,spc \n"
" lds.l @r15+,macl \n"
" lds.l @r15+,mach \n"
" lds.l @r15+,pr \n"
" mov.l __ISR_temp_fpscr_k,r0 \n"
" lds r0,fpscr \n"
" fmov @r15+,fr15 \n"
" fmov @r15+,fr14 \n"
" fmov @r15+,fr13 \n"
" fmov @r15+,fr12 \n"
" fmov @r15+,fr11 \n"
" fmov @r15+,fr10 \n"
" fmov @r15+,fr9 \n"
" fmov @r15+,fr8 \n"
" fmov @r15+,fr7 \n"
" fmov @r15+,fr6 \n"
" fmov @r15+,fr5 \n"
" fmov @r15+,fr4 \n"
" fmov @r15+,fr3 \n"
" fmov @r15+,fr2 \n"
" fmov @r15+,fr1 \n"
" fmov @r15+,fr0 \n"
" lds.l @r15+,fpul \n"
" lds.l @r15+,fpscr\n"
" mov.l @r15+,r14 \n"
#if 0
" mov.l @r15+,r13 \n"
" mov.l @r15+,r12 \n"
" mov.l @r15+,r11 \n"
" mov.l @r15+,r10 \n"
" mov.l @r15+,r9 \n"
" mov.l @r15+,r8 \n"
#endif
" mov.l @r15+,r7 \n"
" mov.l @r15+,r6 \n"
" mov.l @r15+,r5 \n"
" mov.l @r15+,r4 \n"
" mov.l @r15+,r3 \n"
" mov.l @r15+,r2 \n"
" mov.l @r15+,r1 \n"
" mov.l @r15+,r0 \n"
" rte \n"
" nop \n"
" .align 2 \n"
"__vbr_600_sr_and_k: \n"
" .long " __STRINGIFY__(~(SH4_SR_RB | SH4_SR_BL)) "\n"
"__vbr_600_sr_or_k: \n"
" .long " __STRINGIFY__(SH4_SR_IMASK) "\n"
"__ISR_Handler_k: \n"
" .long ___ISR_Handler\n"
"_INTEVT_k: \n"
" .long " __STRINGIFY__(SH7750_INTEVT) "\n"
"_ISR_Table_k: \n"
" .long __ISR_Vector_table\n"
"_ipl_hook: \n"
" mov r14,r15 \n"
" ldc.l @r15+,ssr \n"
" ldc.l @r15+,spc \n"
" lds.l @r15+,macl \n"
" lds.l @r15+,mach \n"
" lds.l @r15+,pr \n"
" mov.l __ISR_temp_fpscr_k,r0 \n"
" lds r0,fpscr \n"
" fmov @r15+,fr15 \n"
" fmov @r15+,fr14 \n"
" fmov @r15+,fr13 \n"
" fmov @r15+,fr12 \n"
" fmov @r15+,fr11 \n"
" fmov @r15+,fr10 \n"
" fmov @r15+,fr9 \n"
" fmov @r15+,fr8 \n"
" fmov @r15+,fr7 \n"
" fmov @r15+,fr6 \n"
" fmov @r15+,fr5 \n"
" fmov @r15+,fr4 \n"
" fmov @r15+,fr3 \n"
" fmov @r15+,fr2 \n"
" fmov @r15+,fr1 \n"
" fmov @r15+,fr0 \n"
" lds.l @r15+,fpul \n"
" lds.l @r15+,fpscr\n"
" mov.l @r15+,r14 \n"
" mov.l @r15+,r13 \n"
" mov.l @r15+,r12 \n"
" mov.l @r15+,r11 \n"
" mov.l @r15+,r10 \n"
" mov.l @r15+,r9 \n"
" mov.l @r15+,r8 \n"
" mov.l @r15+,r7 \n"
" mov.l @r15+,r6 \n"
" mov.l @r15+,r5 \n"
" mov.l @r15+,r4 \n"
" mov.l @r15+,r3 \n"
" mov.l @r15+,r2 \n"
" mov.l __VBR_Saved600_k, r0\n"
" mov.l offset600_k,r1\n"
" mov.l @r0,r0\n"
" add r1,r0\n"
" mov.l @r15+,r1\n"
" jmp @r0\n"
" mov.l @r15+,r0\n"
" .align 2\n"
"__ISR_temp_fpscr_k: \n"
" .long " __STRINGIFY__(SH4_FPSCR_PR) " \n"
"__VBR_Saved600_k:\n"
" .long __VBR_Saved\n"
"offset600_k:\n"
" .long 0x600\n"
);
/************************************************
* Dummy interrupt service procedure for
* interrupts being not allowed --> Trap 2
************************************************/
asm(" .section .text
.global __dummy_isp
__dummy_isp:
mov.l r14,@-r15
mov r15, r14
trapa #2
mov.l @r15+,r14
rte
nop");

View File

@@ -0,0 +1,2 @@
Makefile
Makefile.in

View File

@@ -0,0 +1,31 @@
##
## $Id$
##
AUTOMAKE_OPTIONS = foreign 1.4
PGM = $(ARCH)/timer.rel
C_FILES = timer.c
C_O_FILES = $(C_FILES:%.c=$(ARCH)/%.o)
OBJS = $(C_O_FILES)
include $(top_srcdir)/../../../../../../make/custom/@RTEMS_BSP@.cfg
include $(top_srcdir)/../../../../../../automake/compile.am
include $(top_srcdir)/../../../../../../automake/lib.am
#
# (OPTIONAL) Add local stuff here using +=
#
$(PGM): $(OBJS)
$(make-rel)
all-local: $(ARCH) $(OBJS) $(PGM)
.PRECIOUS: $(PGM)
EXTRA_DIST = timer.c
include $(top_srcdir)/../../../../../../automake/local.am

View File

@@ -0,0 +1,292 @@
/*
* timer driver for the Hitachi SH 7750
*
* 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.
*
* Copyright (C) 2001 OKTET Ltd., St.-Petersburg, Russia
* Author: Victor V. Vengerov <vvv@oktet.ru>
*
* 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/iosh7750.h>
#ifndef TIMER_PRIO
#define TIMER_PRIO 15
#endif
/* Timer prescaler division ratio */
#define TIMER_PRESCALER 4
#define TCR1_TPSC SH7750_TCR_TPSC_DIV4
#define TIMER_VECTOR SH7750_EVT_TO_NUM(SH7750_EVT_TUNI1)
rtems_isr timerisr();
static rtems_unsigned32 Timer_interrupts;
/* Counter should be divided to this value to obtain time in microseconds */
static rtems_unsigned32 microseconds_divider;
/* Interrupt period in microseconds */
static rtems_unsigned32 microseconds_per_int;
rtems_boolean Timer_driver_Find_average_overhead;
/* Timer_initialize --
* Initialize Timer 1 to operate as a RTEMS benchmark timer:
* - determine timer clock frequency
* - install timer interrupt handler
* - configure the Timer 1 hardware
* - start the timer
*
* PARAMETERS:
* none
*
* RETURNS:
* none
*/
void
Timer_initialize(void)
{
rtems_unsigned8 temp8;
rtems_unsigned16 temp16;
rtems_interrupt_level level;
rtems_isr *ignored;
int cpudiv = 1;
int tidiv = 1;
Timer_interrupts = 0;
_CPU_ISR_Disable(level);
/* Get CPU frequency divider from clock unit */
switch (read16(SH7750_FRQCR) & SH7750_FRQCR_IFC)
{
case SH7750_FRQCR_IFCDIV1:
cpudiv = 1;
break;
case SH7750_FRQCR_IFCDIV2:
cpudiv = 2;
break;
case SH7750_FRQCR_IFCDIV3:
cpudiv = 3;
break;
case SH7750_FRQCR_IFCDIV4:
cpudiv = 4;
break;
case SH7750_FRQCR_IFCDIV6:
cpudiv = 6;
break;
case SH7750_FRQCR_IFCDIV8:
cpudiv = 8;
break;
default:
rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
}
/* Get peripheral module frequency divider from clock unit */
switch (read16(SH7750_FRQCR) & SH7750_FRQCR_PFC)
{
case SH7750_FRQCR_PFCDIV2:
tidiv = 2 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV3:
tidiv = 3 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV4:
tidiv = 4 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV6:
tidiv = 6 * TIMER_PRESCALER;
break;
case SH7750_FRQCR_PFCDIV8:
tidiv = 8 * TIMER_PRESCALER;
break;
default:
rtems_fatal_error_occurred( RTEMS_NOT_CONFIGURED);
}
microseconds_divider =
rtems_cpu_configuration_get_clicks_per_second() * cpudiv /
(tidiv * 1000000);
microseconds_per_int = 0xFFFFFFFF / microseconds_divider;
/*
* Hardware specific initialization
*/
/* Stop the Timer 0 */
temp8 = read8(SH7750_TSTR);
temp8 &= ~SH7750_TSTR_STR1;
write8(temp8, SH7750_TSTR);
/* Establish interrupt handler */
_CPU_ISR_install_raw_handler( TIMER_VECTOR, timerisr, &ignored );
/* Reset timer constant and counter */
write32(0xFFFFFFFF, SH7750_TCOR1);
write32(0xFFFFFFFF, SH7750_TCNT1);
/* Select timer mode */
write16(
SH7750_TCR_UNIE | /* Enable Underflow Interrupt */
SH7750_TCR_CKEG_RAISE | /* Count on rising edge */
TCR1_TPSC, /* Timer prescaler ratio */
SH7750_TCR1);
/* Set timer interrupt priority */
temp16 = read16(SH7750_IPRA);
temp16 = (temp16 & ~SH7750_IPRA_TMU1) | (TIMER_PRIO << SH7750_IPRA_TMU1_S);
write16(temp16, SH7750_IPRA);
_CPU_ISR_Enable(level);
/* Start the Timer 1 */
temp8 = read8(SH7750_TSTR);
temp8 |= SH7750_TSTR_STR1;
write8(temp8, SH7750_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 0 /* 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 */
/* Read_timer --
* Read timer value in microsecond units since timer start.
*
* PARAMETERS:
* none
*
* RETURNS:
* number of microseconds since timer has been started
*/
int
Read_timer(void)
{
rtems_unsigned32 clicks;
rtems_unsigned32 ints;
rtems_unsigned32 total ;
rtems_interrupt_level level;
rtems_unsigned32 tcr;
_CPU_ISR_Disable(level);
clicks = 0xFFFFFFFF - read32(SH7750_TCNT1);
tcr = read32(SH7750_TCR1);
ints = Timer_interrupts;
_CPU_ISR_Enable(level);
/* Handle the case when timer overflowed but interrupt was not processed */
if ((clicks > 0xFF000000) && ((tcr & SH7750_TCR_UNF) != 0))
{
ints++;
}
total = microseconds_per_int * ints + (clicks / microseconds_divider);
if ( Timer_driver_Find_average_overhead )
return total; /* in microsecond units */
else
{
if ( total < LEAST_VALID )
return 0; /* below timer resolution */
/*
* Somehow convert total into microseconds
*/
return (total - AVG_OVERHEAD) ;
}
}
/* Empty_function --
* Empty function call used in loops to measure basic cost of looping
* in Timing Test Suite.
*
* PARAMETERS:
* none
*
* RETURNS:
* RTEMS_SUCCESSFUL
*/
rtems_status_code
Empty_function( void )
{
return RTEMS_SUCCESSFUL;
}
/* Set_find_average_overhead --
* This routine is invoked by the "Check Timer" (tmck) test in the
* RTEMS Timing Test Suite. It makes the Read_timer routine not
* subtract the overhead required to initialize and read the benchmark
* timer.
*
* PARAMETERS:
* find_flag - boolean flag, TRUE if overhead must not be subtracted.
*
* RETURNS:
* none
*/
void
Set_find_average_overhead(rtems_boolean find_flag)
{
Timer_driver_Find_average_overhead = find_flag;
}
/* timerisr --
* Timer interrupt handler routine. This function invoked on timer
* underflow event; once per 2^32 clocks. It should reset the timer
* event and increment timer interrupts counter.
*/
void
timerisr(void)
{
unsigned8 temp8;
/* reset the flags of the status register */
temp8 = read8(SH7750_TCR1) & ~SH7750_TCR_UNF;
write8(temp8, SH7750_TCR1);
Timer_interrupts += 1;
}