mn10300_serial.c

来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,037 行 · 第 1/3 页

C
1,037
字号
//==========================================================================
//
//      mn10300_serial.c
//
//      Serial device driver for mn10300 on-chip serial devices
//
//==========================================================================
//####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):   nickg
// Contributors: nickg
// Date:        1999-02-25
// Purpose:     MN10300 serial device driver
// Description: MN10300 serial device driver
//
//####DESCRIPTIONEND####
//
//==========================================================================

#include <pkgconf/hal.h>
#include <pkgconf/io_serial.h>
#include <cyg/hal/hal_io.h>

#include <cyg/io/io.h>
#include <cyg/io/devtab.h>
#include <cyg/io/serial.h>
#include <cyg/hal/hal_intr.h>

#ifdef CYGPKG_IO_SERIAL_MN10300

#define CYG_HAL_MN10300_SERIAL_RX_FIFO

//-------------------------------------------------------------------------

extern void diag_printf(const char *fmt, ...);

//-------------------------------------------------------------------------
// Forward definitions

static bool mn10300_serial_init(struct cyg_devtab_entry *tab);
static bool mn10300_serial_putc(serial_channel *chan, unsigned char c);
static Cyg_ErrNo mn10300_serial_lookup(struct cyg_devtab_entry **tab, 
                                   struct cyg_devtab_entry *sub_tab,
                                   const char *name);
static unsigned char mn10300_serial_getc(serial_channel *chan);
static Cyg_ErrNo mn10300_serial_set_config(serial_channel *chan, cyg_uint32 key,
                                           const void *xbuf, cyg_uint32 *len);
static void mn10300_serial_start_xmit(serial_channel *chan);
static void mn10300_serial_stop_xmit(serial_channel *chan);

#ifndef CYGPKG_IO_SERIAL_MN10300_POLLED_MODE
static cyg_uint32 mn10300_serial_rx_ISR(cyg_vector_t vector, cyg_addrword_t data);
static cyg_uint32 mn10300_serial_tx_ISR(cyg_vector_t vector, cyg_addrword_t data);
static void       mn10300_serial_rx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
static void       mn10300_serial_tx_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data);
#endif

//-------------------------------------------------------------------------

#define BUFSIZE 128

//-------------------------------------------------------------------------
// MN10300 serial line control register values:

// Offsets to serial control registers from base
#define SERIAL_CTR      0x0
#define SERIAL_ICR      0x4
#define SERIAL_TXB      0x8
#define SERIAL_RXB      0x9
#define SERIAL_STR      0xc
#define SERIAL_TIM      0xd

// Status register bits
#define SR_RBF          0x10
#define SR_TBF          0x20
#define SR_RXF          0x40
#define SR_TXF          0x80

// Control register bits
#define LCR_SB1         0x00
#define LCR_SB1_5       0x00
#define LCR_SB2         0x04
#define LCR_PN          0x00    // Parity mode - none
#define LCR_PS          0x40    // Forced "space" parity
#define LCR_PM          0x50    // Forced "mark" parity
#define LCR_PE          0x60    // Parity mode - even
#define LCR_PO          0x70    // Parity mode - odd
#define LCR_WL5         0x00    // not supported - use 7bit
#define LCR_WL6         0x00    // not supported - use 7bit
#define LCR_WL7         0x00    // 7 bit chars
#define LCR_WL8         0x80    // 8 bit chars
#define LCR_RXE         0x4000  // receive enable
#define LCR_TXE         0x8000  // transmit enable

#if defined(CYGPKG_HAL_MN10300_AM31)
#define LCR_TWE         0x0100  // interrupt enable (only on serial2/AM31)
#else
#define LCR_TWE         0x0000  // Bit does not exist in other variants
#endif

//-------------------------------------------------------------------------
// MN10300 timer registers:

#undef TIMER_BR
#undef TIMER_MD
#define TIMER_MD        0x00
#define TIMER_BR        0x10

//-------------------------------------------------------------------------
// Serial and timer base registers:

#if defined(CYGPKG_HAL_MN10300_AM31)

#define SERIAL0_BASE            0x34000800
#define SERIAL1_BASE            0x34000810
#define SERIAL2_BASE            0x34000820

#define TIMER0_BASE             0x34001000
#define TIMER1_BASE             0x34001001
#define TIMER2_BASE             0x34001002

#define SERIAL0_TIMER_SELECT    0x0004          // timer 0
#define SERIAL1_TIMER_SELECT    0x0004          // timer 1
#define SERIAL2_TIMER_SELECT    0x0001          // timer 2

#ifdef CYGPKG_HAL_MN10300_AM31_STDEVAL1
// The use of PORT3 to provide CTS/CTR is specific to
// the STDEVAL1 board only.
#define PORT3_MD                0x36008025
#endif

#define ENABLE_TRANSMIT_INTERRUPT(mn10300_chan) \
CYG_MACRO_START                                 \
    if( mn10300_chan->is_serial2 )              \
        cr |= LCR_TWE;                          \
    else                                        \
        cr |= LCR_TXE;                          \
CYG_MACRO_END

#define DISABLE_TRANSMIT_INTERRUPT(mn10300_chan)        \
CYG_MACRO_START                                         \
    if( mn10300_chan->is_serial2 )                      \
        cr &= ~LCR_TWE;                                 \
    else                                                \
        cr &= ~LCR_TXE;                                 \
CYG_MACRO_END

#elif defined(CYGPKG_HAL_MN10300_AM33)

#define SERIAL0_BASE            0xd4002000
#define SERIAL1_BASE            0xd4002010
#define SERIAL2_BASE            0xd4002020

#define TIMER0_BASE             0xd4003002
#define TIMER1_BASE             0xd4003001
#define TIMER2_BASE             0xd4003003

#define SERIAL0_TIMER_SELECT    0x0005          // timer 2
#define SERIAL1_TIMER_SELECT    0x0004          // timer 1
#define SERIAL2_TIMER_SELECT    0x0003          // timer 3

#define HW_TIMER0               0xd4003000

#define ENABLE_TRANSMIT_INTERRUPT(mn10300_chan)

#define DISABLE_TRANSMIT_INTERRUPT(mn10300_chan)

#else

#error Unsupported MN10300 variant

#endif

//-------------------------------------------------------------------------
// Tables to map input values to hardware settings

static unsigned char select_word_length[] = {
    LCR_WL5,    // 5 bits / word (char)
    LCR_WL6,
    LCR_WL7,
    LCR_WL8
};

static unsigned char select_stop_bits[] = {
    0,
    LCR_SB1,    // 1 stop bit
    LCR_SB1_5,  // 1.5 stop bit
    LCR_SB2     // 2 stop bits
};

static unsigned char select_parity[] = {
    LCR_PN,     // No parity
    LCR_PE,     // Even parity
    LCR_PO,     // Odd parity
    LCR_PM,     // Mark parity
    LCR_PS,     // Space parity
};

#if defined(CYGPKG_HAL_MN10300_AM31)

static unsigned short select_baud_01[] = {
    0,          // Unused
    0,          // 50
    0,          // 75
    0,          // 110
    0,          // 134.5
    0,          // 150
    0,          // 200
    0,          // 300
    0,          // 600
    0,          // 1200
    0,          // 1800
    0,          // 2400
    0,          // 3600
    0,          // 4800
    0,          // 7200
    195,        // 9600
    130,        // 14400
    98,         // 19200
    48,         // 38400
    32,         // 57600
    16,         // 115200
    8,          // 230400
};

// Serial 2 has its own timer register in addition to using timer 2 to
// supply the baud rate generator. Both of these must be proframmed to
// get the right baud rate. The following values come from Matsushita
// with some modifications from Cygmon.
static struct
{
    cyg_uint8   serial2_val;
    cyg_uint8   timer2_val;
} select_baud_2[] = {
    {   0,   0 },       // Unused
    {   0,   0 },       // 50
    {   0,   0 },       // 75
    {   0,   0 },       // 110
    {   0,   0 },       // 134.5
    {   0,   0 },       // 150
    {   0,   0 },       // 200
    {   0,   0 },       // 300
    { 126, 196 },       // 600
    { 125,  98 },       // 1200
    {   0,   0 },       // 1800
    { 124,  49 },       // 2400
    { 0,     0 },       // 3600
    { 124,  24 },       // 4800
    {   0,   0 },       // 7200
    {  70,  21 },       // 9600
    {   0,   0 },       // 14400
    {  70,  10 },       // 19200
    {  22,  16 },       // 38400
    {  88,   2 },       // 57600
    {  64,   1 },       // 115200
    {  62,   0 },       // 230400
};

#elif defined(CYGPKG_HAL_MN10300_AM33)

// The AM33 runs at a different clock rate and therefore has a
// different set of dividers for the baud rate.

static unsigned short select_baud_01[] = {
    0,          // Unused
    0,          // 50
    0,          // 75
    0,          // 110
    0,          // 134.5
    0,          // 150
    0,          // 200
    0,          // 300
    0,          // 600
    3168,       // 1200
    0,          // 1800
    1584,       // 2400
    0,          // 3600
    792,        // 4800
    0,          // 7200
    396,        // 9600
    0,          // 14400
    198,        // 19200
    99,         // 38400
     0,         // 57600
    33,         // 115200
    16,         // 230400
};

// Serial 2 has its own timer register in addition to using timer 2 to
// supply the baud rate generator. Both of these must be proframmed to
// get the right baud rate. The following values come from Matsushita
// with some modifications from Cygmon.

// The values in the following table differ significantly from those
// given in the Matsushita documentation. These have been determined
// by (somewhat exhaustive) experiment, the values in the documentation
// do not appear to work at all.

static struct
{
    cyg_uint8   serial2_val;
    cyg_uint8   timer2_val;
} select_baud_2[] = {
    {   0,   0 },       // Unused
    {   0,   0 },       // 50
    {   0,   0 },       // 75
    {   0,   0 },       // 110
    {   0,   0 },       // 134.5
    {   0,   0 },       // 150
    {   0,   0 },       // 200
    {   0,   0 },       // 300
    {   0,   0 },       // 600
    {   0,   0 },       // 1200

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?