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

Subversion Repositories openrisc_me

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/rtos/ecos-2.0/packages/devs/serial/powerpc/cme555
    from Rev 27 to Rev 174
    Reverse comparison

Rev 27 → Rev 174

/v2_0/cdl/ser_powerpc_cme555.cdl
0,0 → 1,184
# ====================================================================
#
# ser_powerpc_cme555.cdl
#
# eCos serial PowerPC/cme555 configuration data
#
# ====================================================================
#####ECOSGPLCOPYRIGHTBEGIN####
## -------------------------------------------
## This file is part of eCos, the Embedded Configurable Operating System.
## Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
##
## eCos 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
## Software Foundation; either version 2 or (at your option) any later version.
##
## eCos 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. See the GNU General Public License
## for more details.
##
## You should have received a copy of the GNU General Public License along
## with eCos; if not, write to the Free Software Foundation, Inc.,
## 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
##
## As a special exception, if other files instantiate templates or use macros
## or inline functions from this file, or you compile this file and link it
## with other works to produce a work based on this file, this file does not
## by itself cause the resulting work to be covered by the GNU General Public
## License. However the source code for this file must still be made available
## in accordance with section (3) of the GNU General Public License.
##
## This exception does not invalidate any other reasons why a work based on
## this file might be covered by the GNU General Public License.
##
## Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
## at http://sources.redhat.com/ecos/ecos-license/
## -------------------------------------------
#####ECOSGPLCOPYRIGHTEND####
# ====================================================================
######DESCRIPTIONBEGIN####
#
# Author(s): Bob Koninckx
# Original data:
# Contributors:
# Date: 1999-07-14
#
#####DESCRIPTIONEND####
#
# ====================================================================
 
cdl_package CYGPKG_IO_SERIAL_POWERPC_CME555 {
display "cme555 PowerPC serial device drivers"
 
parent CYGPKG_IO_SERIAL_DEVICES
active_if CYGPKG_IO_SERIAL
active_if CYGPKG_HAL_POWERPC_CME555
 
requires CYGPKG_ERROR
include_dir cyg/io
include_files ; # none _exported_ whatsoever
description "
This option enables the serial device drivers for the
cme555 mpc555 development board."
 
compile -library=libextras.a cme555_serial_with_ints.c
 
define_proc {
puts $::cdl_system_header "/***** serial driver proc output start *****/"
puts $::cdl_system_header "#define CYGDAT_IO_SERIAL_DEVICE_HEADER <pkgconf/io_serial_powerpc_cme555.h>"
puts $::cdl_system_header "/***** serial driver proc output end *****/"
}
 
cdl_component CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_A {
display "cme555 PowerPC serial port A driver"
flavor bool
default_value 0
description "
This option includes the serial device driver for the cme555
PowerPC port A."
 
cdl_option CYGDAT_IO_SERIAL_POWERPC_CME555_SERIAL_A_NAME {
display "Device name for cme555 PowerPC serial port A"
flavor data
default_value {"\"/dev/ser1\""}
description "
This option specifies the device name for the cme555 PowerPC
port A."
}
 
cdl_option CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BAUD {
display "Baud rate for the cme555 PowerPC serial port A driver"
flavor data
legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 57600 115200 }
default_value 38400
description "
This option specifies the default baud rate (speed) for the
cme555 PowerPC port A."
}
 
cdl_option CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BUFSIZE {
display "Buffer size for the cme555 PowerPC serial port A driver"
flavor data
legal_values 0 to 8192
default_value 128
description "
This option specifies the size of the internal buffers used for
the cme555 PowerPC port A."
}
}
 
cdl_component CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_B {
display "cme555 PowerPC serial port B driver"
flavor bool
default_value 1
description "
This option includes the serial device driver for the cme555
PowerPC port B."
 
cdl_option CYGDAT_IO_SERIAL_POWERPC_CME555_SERIAL_B_NAME {
display "Device name for cme555 PowerPC serial port B"
flavor data
default_value {"\"/dev/ser2\""}
description "
This option specifies the device name for the cme555 PowerPC
port B."
}
 
cdl_option CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BAUD {
display "Baud rate for the cme555 PowerPC serial port B driver"
flavor data
legal_values { 300 600 1200 2400 4800 9600 14400 19200 38400 57600 115200 }
default_value 38400
description "
This option specifies the default baud rate (speed) for the
cme555 PowerPC port B."
}
 
cdl_option CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BUFSIZE {
display "Buffer size for the cme555 PowerPC serial port B driver"
flavor data
legal_values 0 to 8192
default_value 128
description "
This option specifies the size of the internal buffers used
for the cme555 PowerPC port B."
}
}
 
cdl_component CYGPKG_IO_SERIAL_POWERPC_CME555_OPTIONS {
display "Serial device driver build options"
flavor none
description "
Package specific build options including control over
compiler flags used only in building this package,
and details of which tests are built."
 
 
cdl_option CYGPKG_IO_SERIAL_POWERPC_CME555_CFLAGS_ADD {
display "Additional compiler flags"
flavor data
no_define
default_value { "" }
description "
This option modifies the set of compiler flags for
building these serial device drivers. These flags are used in addition
to the set of global flags."
}
 
cdl_option CYGPKG_IO_SERIAL_POWERPC_CME555_CFLAGS_REMOVE {
display "Suppressed compiler flags"
flavor data
no_define
default_value { "" }
description "
This option modifies the set of compiler flags for
building these serial device drivers. These flags are removed from
the set of global flags if present."
}
}
 
}
 
# EOF ser_powerpc_cme555.cdl
/v2_0/src/cme555_serial.h
0,0 → 1,157
#ifndef CYGONCE_DEVS_SERIAL_POWERPC_CME555_SERIAL_H
#define CYGONCE_DEVS_SERIAL_POWERPC_CME555_SERIAL_H
//==========================================================================
//
// cme555_serial.h
//
// PowerPC 5xx CME555 Serial I/O definitions.
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos 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. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Bob Koninckx
// Contributors:
// Date: 2002-04-25
// Purpose: CME555 Serial I/O definitions.
// Description:
//
//
//####DESCRIPTIONEND####
//==========================================================================
 
//----------------------------------
// Includes and forward declarations
//----------------------------------
 
//----------------------
// Constants definitions
//----------------------
// Base addresses for the two serial ports
#define MPC555_SERIAL_BASE_A 0x305008
#define MPC555_SERIAL_BASE_B 0x305020
 
// The offset from the base for all serial registers
#define MPC555_SERIAL_SCCxR0 0
#define MPC555_SERIAL_SCCxR1 2
#define MPC555_SERIAL_SCxSR 4
#define MPC555_SERIAL_SCxDR 6
 
// The bits in the serial registers
#define MPC555_SERIAL_SCCxR0_OTHR 0x8000
#define MPC555_SERIAL_SCCxR0_LINKBD 0x4000
#define MPC555_SERIAL_SCCxR0_SCxBR 0x1fff
 
#define MPC555_SERIAL_SCCxR1_LOOPS 0x4000
#define MPC555_SERIAL_SCCxR1_WOMS 0x2000
#define MPC555_SERIAL_SCCxR1_ILT 0x1000
#define MPC555_SERIAL_SCCxR1_PT 0x0800
#define MPC555_SERIAL_SCCxR1_PE 0x0400
#define MPC555_SERIAL_SCCxR1_M 0x0200
#define MPC555_SERIAL_SCCxR1_WAKE 0x0100
#define MPC555_SERIAL_SCCxR1_TIE 0x0080
#define MPC555_SERIAL_SCCxR1_TCIE 0x0040
#define MPC555_SERIAL_SCCxR1_RIE 0x0020
#define MPC555_SERIAL_SCCxR1_ILIE 0x0010
#define MPC555_SERIAL_SCCxR1_TE 0x0008
#define MPC555_SERIAL_SCCxR1_RE 0x0004
#define MPC555_SERIAL_SCCxR1_RWU 0x0002
#define MPC555_SERIAL_SCCxR1_SBK 0x0001
 
#define MPC555_SERIAL_SCxSR_TDRE 0x0100
#define MPC555_SERIAL_SCxSR_TC 0x0080
#define MPC555_SERIAL_SCxSR_RDRF 0x0040
#define MPC555_SERIAL_SCxSR_RAF 0x0020
#define MPC555_SERIAL_SCxSR_IDLE 0x0010
#define MPC555_SERIAL_SCxSR_OR 0x0008
#define MPC555_SERIAL_SCxSR_NF 0x0004
#define MPC555_SERIAL_SCxSR_FE 0x0002
#define MPC555_SERIAL_SCxSR_PF 0x0001
 
// The available baud rates
// These are calculated for a busclock of 40 MHz
// It is not necessary to let the compiler calculate these
// values, we did not provide clockfrequency as a configuarion
// option anyway.
static unsigned short select_baud[] = {
0, // Unused
0, // 50 bps unsupported
0, // 75 bps unsupported
0, // 110 bps unsupported
0, // 134_5 bps unsupported
0, // 150 bps unsupported
0, // 200 bps unsupported
4167, // 300 bps
2083, // 600 bps
1042, // 1200 bps
0, // 1800 bps unsupported
521, // 2400 bps
0, // 3600 bps unsupported
260, // 4800 bps
0, // 7200 bps unsupported
130, // 9600 bps
87, // 14400 bps
65, // 19200 bps
33, // 38400 bps
22, // 57600 bps
11, // 115200 bps
0 // 230400 bps unsupported
};
 
static unsigned char select_word_length[] = {
0, // 5 bits / word (char) not supported
0, // 6 bits / word (char) not supported
7, // 7 bits / word (char) ->> 7 bits per frame
8 // 8 bits / word (char) ->> 8 bits per frame
};
 
static unsigned char select_stop_bits[] = {
0,
1, // 1 stop bit ->> 1 bit per frame
0, // 1.5 stop bit not supported
2 // 2 stop bits ->> 2 bits per frame
};
 
static unsigned char select_parity[] = {
0, // No parity ->> 0 bits per frame
1, // Even parity ->> 1 bit per frame
1, // Odd parityv ->> 1 bit per frame
0, // Mark parity not supported
0, // Space parity not supported
};
 
#endif // CYGONCE_DEVS_SERIAL_POWERPC_CME555_SERIAL_H
 
// EOF cme555_serial.h
/v2_0/src/cme555_serial_with_ints.c
0,0 → 1,632
//==========================================================================
//
// cme555_serial_with_ints.c
//
// PowerPC 5xx CME555 Serial I/O Interface Module (interrupt driven)
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos 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. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//==========================================================================
//#####DESCRIPTIONBEGIN####
//
// Author(s): Bob Koninckx
// Contributors:
// Date: 2002-04-25
// Purpose: CME555 Serial I/O module (interrupt driven version)
// Description:
//
//
//####DESCRIPTIONEND####
//==========================================================================
//----------------------------------
// Includes and forward declarations
//----------------------------------
#include <pkgconf/io_serial.h>
#include <pkgconf/io.h>
 
#include <cyg/io/io.h>
#include <cyg/hal/hal_intr.h>
#include <cyg/hal/hal_arbiter.h>
#include <cyg/io/devtab.h>
#include <cyg/infra/diag.h>
#include <cyg/io/serial.h>
 
// Only build this driver for the MPC555 based CME555 board
#ifdef CYGPKG_IO_SERIAL_POWERPC_CME555
 
#include "cme555_serial.h"
 
//-----------------
// Type definitions
//-----------------
typedef struct mpc555_serial_info {
CYG_ADDRWORD base; // The base address of the serial port
CYG_WORD tx_interrupt_num; // trivial
CYG_WORD rx_interrupt_num; // trivial
cyg_priority_t tx_interrupt_priority; // trivial
cyg_priority_t rx_interrupt_priority; // trivial
bool tx_interrupt_enable; // tells if the transmit interrupt may be re-enabled
cyg_interrupt tx_interrupt; // the tx interrupt object
cyg_handle_t tx_interrupt_handle; // the tx interrupt handle
cyg_interrupt rx_interrupt; // the rx interrupt object
cyg_handle_t rx_interrupt_handle; // the rx interrupt handle
} mpc555_serial_info;
 
//--------------------
// Function prototypes
//--------------------
static bool mpc555_serial_init(struct cyg_devtab_entry * tab);
static bool mpc555_serial_putc(serial_channel * chan, unsigned char c);
static Cyg_ErrNo mpc555_serial_lookup(struct cyg_devtab_entry ** tab,
struct cyg_devtab_entry * sub_tab,
const char * name);
static unsigned char mpc555_serial_getc(serial_channel *chan);
static Cyg_ErrNo mpc555_serial_set_config(serial_channel *chan, cyg_uint32 key,
const void *xbuf, cyg_uint32 *len);
static void mpc555_serial_start_xmit(serial_channel *chan);
static void mpc555_serial_stop_xmit(serial_channel *chan);
 
// The interrupt servers
static cyg_uint32 mpc555_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 mpc555_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
static void mpc555_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
static void mpc555_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
 
//-------------------------------------------
// Register the device driver with the kernel
//-------------------------------------------
static SERIAL_FUNS(mpc555_serial_funs,
mpc555_serial_putc,
mpc555_serial_getc,
mpc555_serial_set_config,
mpc555_serial_start_xmit,
mpc555_serial_stop_xmit);
 
//-------------------
// Device driver data
//-------------------
#ifdef CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_A
static mpc555_serial_info mpc555_serial_info0 = {MPC555_SERIAL_BASE_A,
CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX,
CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX,
CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX_PRIORITY,
CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX_PRIORITY,
false};
#if CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BUFSIZE > 0
static unsigned char mpc555_serial_out_buf0[CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BUFSIZE];
static unsigned char mpc555_serial_in_buf0[CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BUFSIZE];
 
static SERIAL_CHANNEL_USING_INTERRUPTS(mpc555_serial_channel0,
mpc555_serial_funs,
mpc555_serial_info0,
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BAUD),
CYG_SERIAL_STOP_DEFAULT,
CYG_SERIAL_PARITY_DEFAULT,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT,
&mpc555_serial_out_buf0[0],
sizeof(mpc555_serial_out_buf0),
&mpc555_serial_in_buf0[0],
sizeof(mpc555_serial_in_buf0));
#else
static SERIAL_CHANNEL(mpc555_serial_channel0,
mpc555_serial_funs,
mpc555_serial_info0,
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_A_BAUD),
CYG_SERIAL_STOP_DEFAULT,
CYG_SERIAL_PARITY_DEFAULT,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT);
#endif
DEVTAB_ENTRY(mpc555_serial_io0,
CYGDAT_IO_SERIAL_POWERPC_CME555_SERIAL_A_NAME,
0, // does not depend on a lower level device driver
&cyg_io_serial_devio,
mpc555_serial_init,
mpc555_serial_lookup,
&mpc555_serial_channel0);
#endif // ifdef CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_A
 
#ifdef CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_B
static mpc555_serial_info mpc555_serial_info1 = {MPC555_SERIAL_BASE_B,
CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX,
CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX,
CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX_PRIORITY,
CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX_PRIORITY,
false};
#if CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BUFSIZE > 0
static unsigned char mpc555_serial_out_buf1[CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BUFSIZE];
static unsigned char mpc555_serial_in_buf1[CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BUFSIZE];
 
static SERIAL_CHANNEL_USING_INTERRUPTS(mpc555_serial_channel1,
mpc555_serial_funs,
mpc555_serial_info1,
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BAUD),
CYG_SERIAL_STOP_DEFAULT,
CYG_SERIAL_PARITY_DEFAULT,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT,
&mpc555_serial_out_buf1[0],
sizeof(mpc555_serial_out_buf1),
&mpc555_serial_in_buf1[0],
sizeof(mpc555_serial_in_buf1));
#else
static SERIAL_CHANNEL(mpc555_serial_channel1,
mpc555_serial_funs,
mpc555_serial_info1,
CYG_SERIAL_BAUD_RATE(CYGNUM_IO_SERIAL_POWERPC_CME555_SERIAL_B_BAUD),
CYG_SERIAL_STOP_DEFAULT,
CYG_SERIAL_PARITY_DEFAULT,
CYG_SERIAL_WORD_LENGTH_DEFAULT,
CYG_SERIAL_FLAGS_DEFAULT);
#endif
DEVTAB_ENTRY(mpc555_serial_io1,
CYGDAT_IO_SERIAL_POWERPC_CME555_SERIAL_B_NAME,
0, // does not depend on a lower level device driver
&cyg_io_serial_devio,
mpc555_serial_init,
mpc555_serial_lookup,
&mpc555_serial_channel1);
#endif // ifdef CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_B
 
//-----------------------------
// Device driver implementation
//-----------------------------
 
// The arbitration isr.
// I think this is the best place to implement it. The device driver is the only place
// in the code where the knowledge is present about how the hardware is used
static cyg_uint32 hal_arbitration_isr_qsci(CYG_ADDRWORD a_vector, CYG_ADDRWORD a_data)
{
cyg_uint16 status;
cyg_uint16 control;
 
#ifdef CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_A // Do not waist time on unused hardware
HAL_READ_UINT16(CYGARC_REG_IMM_SC1SR, status);
HAL_READ_UINT16(CYGARC_REG_IMM_SCC1R1, control);
if((status & CYGARC_REG_IMM_SCxSR_TDRE) && (control & CYGARC_REG_IMM_SCCxR1_TIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TX);
// Don't waist time on unused interrupts
// if((status & CYGARC_REG_IMM_SCxSR_TC) && (control & CYGARC_REG_IMM_SCCxR1_TCIE))
// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_TXC);
if((status & CYGARC_REG_IMM_SCxSR_RDRF) && (control & CYGARC_REG_IMM_SCCxR1_RIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_RX);
// Don't waist time on unused interrupts
// if((status & CYGARC_REG_IMM_SCxSR_IDLE) && (control & CYGARC_REG_IMM_SCCxR1_ILIE))
// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI0_IDLE);
#endif
 
#ifdef CYGPKG_IO_SERIAL_POWERPC_CME555_SERIAL_B // Do not waist time on unused hardware
HAL_READ_UINT16(CYGARC_REG_IMM_SC2SR, status);
HAL_READ_UINT16(CYGARC_REG_IMM_SCC2R1, control);
if((status & CYGARC_REG_IMM_SCxSR_TDRE) && (control & CYGARC_REG_IMM_SCCxR1_TIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TX);
// Don't waist time on unused interrupts
// if((status & CYGARC_REG_IMM_SCxSR_TC) && (control & CYGARC_REG_IMM_SCCxR1_TCIE))
// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXC);
if((status & CYGARC_REG_IMM_SCxSR_RDRF) && (control & CYGARC_REG_IMM_SCCxR1_RIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RX);
// Don't waist time on unused interrupts
// if((status & CYGARC_REG_IMM_SCxSR_IDLE) && (control & CYGARC_REG_IMM_SCCxR1_ILIE))
// return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_IDLE);
 
#if 0
// The driver doesn't use the queue operation of the hardware (It would need different code for serial 1 and 2
// since oly one port supports queue mode). So the following is not needed.
// Leave it there. It is easyer for later implementations to remove the comments than finding
// out how the hardware works again.
HAL_READ_UINT16(CYGARC_REG_IMM_QSCI1SR, status);
HAL_READ_UINT16(CYGARC_REG_IMM_QSCI1CR, control);
if((status & CYGARC_REG_IMM_QSCI1SR_QTHF) && (control & CYGARC_REG_IMM_QSCI1CR_QTHFI))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RXQTHF);
if((status & CYGARC_REG_IMM_QSCI1SR_QBHF) && (control & CYGARC_REG_IMM_QSCI1CR_QBHFI))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_RXQBHF);
if((status & CYGARC_REG_IMM_QSCI1SR_QTHE) && (control & CYGARC_REG_IMM_QSCI1CR_QTHEI))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXQTHE);
if((status & CYGARC_REG_IMM_QSCI1SR_QBHE) && (control & CYGARC_REG_IMM_QSCI1CR_QBHEI))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SCI1_TXQBHE);
 
cyg_uint16 status;
cyg_uint16 control;
 
HAL_READ_UINT16(CYGARC_REG_IMM_SPSR, status);
HAL_READ_UINT16(CYGARC_REG_IMM_SPCR2, control);
if((status & CYGARC_REG_IMM_SPSR_SPIF) && (control & CYGARC_REG_IMM_SPCR2_SPIFIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_FI);
 
HAL_READ_UINT16(CYGARC_REG_IMM_SPCR3, control);
if((status & CYGARC_REG_IMM_SPSR_MODF) && (control & CYGARC_REG_IMM_SPCR3_HMIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_MODF);
 
if((status & CYGARC_REG_IMM_SPSR_HALTA) && (control & CYGARC_REG_IMM_SPCR3_HMIE))
return hal_call_isr(CYGNUM_HAL_INTERRUPT_IMB3_SPI_HALTA);
#endif
#endif
 
return 0;
}
 
//--------------------------------------------------------------------------------
// Internal function to actually configure the hardware to desired baud rate, etc.
//--------------------------------------------------------------------------------
static bool mpc555_serial_config_port(serial_channel * chan, cyg_serial_info_t * new_config, bool init)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)(chan->dev_priv);
 
cyg_addrword_t port = mpc555_chan->base;
cyg_uint16 baud_rate = select_baud[new_config->baud];
unsigned char frame_length = 1; // The start bit
 
cyg_uint16 old_isrstate;
cyg_uint16 sccxr;
 
if(!baud_rate)
return false; // Invalid baud rate selected
 
if((new_config->word_length != CYGNUM_SERIAL_WORD_LENGTH_7) &&
(new_config->word_length != CYGNUM_SERIAL_WORD_LENGTH_8))
return false; // Invalid word length selected
 
if((new_config->parity != CYGNUM_SERIAL_PARITY_NONE) &&
(new_config->parity != CYGNUM_SERIAL_PARITY_EVEN) &&
(new_config->parity != CYGNUM_SERIAL_PARITY_ODD))
return false; // Invalid parity selected
 
if((new_config->stop != CYGNUM_SERIAL_STOP_1) &&
(new_config->stop != CYGNUM_SERIAL_STOP_2))
return false; // Invalid stop bits selected
 
frame_length += select_word_length[new_config->word_length - CYGNUM_SERIAL_WORD_LENGTH_5];
frame_length += select_stop_bits[new_config->stop];
frame_length += select_parity[new_config->parity];
 
if((frame_length != 10) && (frame_length != 11))
return false; // Invalid frame format selected
 
// Disable port interrupts while changing hardware
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
old_isrstate = sccxr;
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_LOOPS);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_WOMS);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_ILT);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PT);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_M);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_WAKE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RE);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RWU);
old_isrstate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_SBK);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TIE);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_TCIE);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_RIE);
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_ILIE);
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
 
// Set databits, stopbits and parity.
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
 
if(frame_length == 11)
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_M;
else
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_M);
 
switch(new_config->parity)
{
case CYGNUM_SERIAL_PARITY_NONE:
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PE);
break;
case CYGNUM_SERIAL_PARITY_EVEN:
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PE;
sccxr &= ~((cyg_uint16)MPC555_SERIAL_SCCxR1_PT);
break;
case CYGNUM_SERIAL_PARITY_ODD:
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PE;
sccxr |= (cyg_uint16)MPC555_SERIAL_SCCxR1_PT;
break;
default:
break;
}
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
 
// Set baud rate.
baud_rate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR0_OTHR);
baud_rate &= ~((cyg_uint16)MPC555_SERIAL_SCCxR0_LINKBD);
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR0, sccxr);
sccxr &= ~(MPC555_SERIAL_SCCxR0_SCxBR);
sccxr |= baud_rate;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR0, sccxr);
 
// Enable the device
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
sccxr |= MPC555_SERIAL_SCCxR1_TE;
sccxr |= MPC555_SERIAL_SCCxR1_RE;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
 
if(init)
{ // enable the receiver interrupt
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
sccxr |= MPC555_SERIAL_SCCxR1_RIE;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
}
else // Restore the old interrupt state
{
HAL_READ_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
sccxr |= old_isrstate;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCCxR1, sccxr);
}
 
if(new_config != &chan->config)
chan->config = *new_config;
 
return true;
}
 
//--------------------------------------------------------------
// Function to initialize the device. Called at bootstrap time.
//--------------------------------------------------------------
static hal_mpc5xx_arbitration_data arbiter;
 
static bool mpc555_serial_init(struct cyg_devtab_entry * tab)
{
serial_channel * chan = (serial_channel *)tab->priv;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
 
if(!mpc555_serial_config_port(chan, &chan->config, true))
return false;
 
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
if(chan->out_cbuf.len != 0)
{
arbiter.priority = CYGNUM_HAL_ISR_SOURCE_PRIORITY_QSCI;
arbiter.data = 0;
arbiter.arbiter = hal_arbitration_isr_qsci;
// Install the arbitration isr, Make sure that is is not installed twice
hal_mpc5xx_remove_arbitration_isr(&arbiter);
hal_mpc5xx_install_arbitration_isr(&arbiter);
 
// Create the Tx interrupt, do not enable it yet
cyg_drv_interrupt_create(mpc555_chan->tx_interrupt_num,
mpc555_chan->tx_interrupt_priority,
(cyg_addrword_t)chan, // Data item passed to interrupt handler
mpc555_serial_tx_ISR,
mpc555_serial_tx_DSR,
&mpc555_chan->tx_interrupt_handle,
&mpc555_chan->tx_interrupt);
cyg_drv_interrupt_attach(mpc555_chan->tx_interrupt_handle);
 
// Create the Rx interrupt, this can be safely unmasked now
cyg_drv_interrupt_create(mpc555_chan->rx_interrupt_num,
mpc555_chan->rx_interrupt_priority,
(cyg_addrword_t)chan,
mpc555_serial_rx_ISR,
mpc555_serial_rx_DSR,
&mpc555_chan->rx_interrupt_handle,
&mpc555_chan->rx_interrupt);
cyg_drv_interrupt_attach(mpc555_chan->rx_interrupt_handle);
cyg_drv_interrupt_unmask(mpc555_chan->rx_interrupt_num);
}
 
return true;
}
 
//----------------------------------------------------------------------
// This routine is called when the device is "looked" up (i.e. attached)
//----------------------------------------------------------------------
static Cyg_ErrNo mpc555_serial_lookup(struct cyg_devtab_entry ** tab,
struct cyg_devtab_entry * sub_tab,
const char * name)
{
serial_channel * chan = (serial_channel *)(*tab)->priv;
(chan->callbacks->serial_init)(chan); // Really only required for interrupt driven devices
 
return ENOERR;
}
 
//----------------------------------------------
// Send a character to the device output buffer.
// Return 'true' if character is sent to device
//----------------------------------------------
static bool mpc555_serial_putc(serial_channel * chan, unsigned char c)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_addrword_t port = mpc555_chan->base;
 
cyg_uint16 scsr;
cyg_uint16 scdr;
 
HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
if(scsr & MPC555_SERIAL_SCxSR_TDRE)
{ // Ok, we have space, write the character and return success
scdr = (cyg_uint16)c;
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxDR, scdr);
return true;
}
else
// We cannot write to the transmitter, return failure
return false;
}
 
//---------------------------------------------------------------------
// Fetch a character from the device input buffer, waiting if necessary
//---------------------------------------------------------------------
static unsigned char mpc555_serial_getc(serial_channel * chan)
{
unsigned char c;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_addrword_t port = mpc555_chan->base;
 
cyg_uint16 scsr;
cyg_uint16 scdr;
 
do {
HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
} while(!(scsr & MPC555_SERIAL_SCxSR_RDRF));
 
// Ok, data is received, read it out and return
HAL_READ_UINT16(port + MPC555_SERIAL_SCxDR, scdr);
c = (unsigned char)scdr;
 
return c;
}
 
//---------------------------------------------------
// Set up the device characteristics; baud rate, etc.
//---------------------------------------------------
static bool mpc555_serial_set_config(serial_channel * chan, cyg_uint32 key,
const void *xbuf, cyg_uint32 * len)
{
switch(key) {
case CYG_IO_SET_CONFIG_SERIAL_INFO:
{
cyg_serial_info_t *config = (cyg_serial_info_t *)xbuf;
if(*len < sizeof(cyg_serial_info_t)) {
return -EINVAL;
}
*len = sizeof(cyg_serial_info_t);
if(true != mpc555_serial_config_port(chan, config, false))
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return ENOERR;
}
 
//-------------------------------------
// Enable the transmitter on the device
//-------------------------------------
static void mpc555_serial_start_xmit(serial_channel * chan)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
 
mpc555_chan->tx_interrupt_enable = true;
cyg_drv_interrupt_unmask(mpc555_chan->tx_interrupt_num);
 
// No need to call xmt_char, this will generate an interrupt immediately.
}
 
//--------------------------------------
// Disable the transmitter on the device
//--------------------------------------
static void mpc555_serial_stop_xmit(serial_channel * chan)
{
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
 
cyg_drv_dsr_lock();
mpc555_chan->tx_interrupt_enable = false;
cyg_drv_interrupt_mask(mpc555_chan->tx_interrupt_num);
cyg_drv_dsr_unlock();
}
 
//-----------------------------------------
// The low level transmit interrupt handler
//-----------------------------------------
static cyg_uint32 mpc555_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
 
cyg_drv_interrupt_mask(mpc555_chan->tx_interrupt_num);
cyg_drv_interrupt_acknowledge(mpc555_chan->tx_interrupt_num);
 
return CYG_ISR_CALL_DSR; // cause the DSR to run
}
 
//----------------------------------------
// The low level receive interrupt handler
//----------------------------------------
static cyg_uint32 mpc555_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
 
cyg_drv_interrupt_mask(mpc555_chan->rx_interrupt_num);
cyg_drv_interrupt_acknowledge(mpc555_chan->rx_interrupt_num);
 
return CYG_ISR_CALL_DSR; // cause the DSR to run
}
 
//------------------------------------------
// The high level transmit interrupt handler
//------------------------------------------
static void mpc555_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
 
(chan->callbacks->xmt_char)(chan);
if(mpc555_chan->tx_interrupt_enable)
cyg_drv_interrupt_unmask(mpc555_chan->tx_interrupt_num);
}
 
//-----------------------------------------
// The high level receive interrupt handler
//-----------------------------------------
#define MPC555_SERIAL_SCxSR_ERRORS (MPC555_SERIAL_SCxSR_OR | \
MPC555_SERIAL_SCxSR_NF | \
MPC555_SERIAL_SCxSR_FE | \
MPC555_SERIAL_SCxSR_PF)
 
static void mpc555_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
{
serial_channel * chan = (serial_channel *)data;
mpc555_serial_info * mpc555_chan = (mpc555_serial_info *)chan->dev_priv;
cyg_addrword_t port = mpc555_chan->base;
cyg_uint16 scdr;
cyg_uint16 scsr;
 
// Allways read out the received character, in order to clear receiver flags
HAL_READ_UINT16(port + MPC555_SERIAL_SCxDR, scdr);
 
HAL_READ_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
if(scsr & (cyg_uint16)MPC555_SERIAL_SCxSR_ERRORS)
{
scsr &= ~((cyg_uint16)MPC555_SERIAL_SCxSR_ERRORS);
HAL_WRITE_UINT16(port + MPC555_SERIAL_SCxSR, scsr);
}
else
{
(chan->callbacks->rcv_char)(chan, (cyg_uint8)scdr);
}
 
cyg_drv_interrupt_unmask(mpc555_chan->rx_interrupt_num);
}
 
#endif // CYGPKG_IO_SERIAL_POWERPC_CME555
 
// EOF cmd555_serial_with_ints.c
/v2_0/ChangeLog
0,0 → 1,42
2003-02-24 Jonathan Larmour <jifl@eCosCentric.com>
 
* cdl/ser_powerpc_cme555.cdl: Remove irrelevant doc link.
 
2002-04-24 Bob Koninckx <bob.koninckx@mech.kuleuven.ac.be>
 
* New package.
 
//===========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
//
// eCos 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
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos 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. See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND####
//===========================================================================

powered by: WebSVN 2.1.0

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