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#### |
//=========================================================================== |