?? sysduart.c
字號:
/* sysDuart.c - MPC 8245/8241 Duart device initialization */
/* Copyright 1984-2002 Wind River Systems, Inc. */
/*
modification history
--------------------
01a,08jan02,jnz created for sp824x BSP, MPC8241/8245.
*/
/*
DESCRIPTION
This file contains board-specific routines for Motorola MPC8245/8241
Duart device initialization.
*/
#include "vxWorks.h"
#include "config.h"
#include "intLib.h"
#include "iv.h"
#include "sysLib.h"
#include "config.h"
#include "sysDuart.h" /* MPC8241/8245 duart driver */
#include "ns16552Sio.h" /* ns16552Sio driver */
#include "i8250Sio.h"
/* external variables */
/* device description structs */
typedef struct
{
USHORT vector; /* Interrupt vector */
ULONG baseAdrs; /* Register base address */
USHORT regSpace; /* Address Interval */
USHORT intLevel; /* Interrupt level */
} NS16552_CHAN_PARAS;
/* external variable */
IMPORT int epicIntTrace; /* trace epic internal interrupts */
/* global variable */
NS16550_CHAN ns16550Chan[N_DUART_CHANNELS];
char *eumbbar_base; /* eumbbar base address */
/* static variables */
LOCAL NS16552_CHAN_PARAS devDuartParas[] =
{
{EPIC_DUART1_INT_VECT, COM3_ADR, DUART_REG_ADDR_INTERVAL,EPIC_DUART1_INT_VECT},
{EPIC_DUART2_INT_VECT, COM4_ADR, DUART_REG_ADDR_INTERVAL, EPIC_DUART2_INT_VECT}
};
/*
* Array of pointers to all serial channels configured in PPMC 8245 module.
* See sysDuartChanGet(). It is this array that maps channel pointers
* to standard device names. The first entry will become "/tyCo/2",
* the second "/tyCo/3".
*/
SIO_CHAN * sysDuartSioChans [N_SIO_CHANNELS] =
{
(SIO_CHAN *)&ns16550Chan[0].pDrvFuncs, /* /tyCo/2 */
(SIO_CHAN *)&ns16550Chan[1].pDrvFuncs, /* /tyCo/3 */
};
/* definitions */
#define DUART_REG(reg, chan) \
*(volatile UINT8 *)(devDuartParas[chan].baseAdrs + reg * devDuartParas[chan].regSpace)
#define SERIAL_BASE(_x) 0xfc004500
#define UART_REG(reg,chan) (SERIAL_BASE(chan) + reg)
/******************************************************************************
*
* Utility routines
*/
UCHAR sysSerialInByte(int addr)
{
return *(UCHAR *) addr;
}
void sysSerialOutByte(int addr, UCHAR c)
{
*(UCHAR *) addr = c;
}
/******************************************************************************
*
* Serial debugging print routines
*
* The following routines are for debugging, especially useful in early
* boot ROM and ISR code.
*
* sysSerialPutc
* sysSerialGetc
* sysSerialPrintString
* sysSerialPrintHex
*
* The sysSerialPrintString and sysSerialPrintHex routines should
* basically ALWAYS work. They re-initialize the UART and turn off
* interrupts every time.
*/
#define SS_CHAN 0
void sysSerialDelay(void)
{
volatile int i;
for (i = 0; i < 0x10000; i++)
;
}
void sysSerialPutc(int c)
{
int i = 10000;
while (!(sysSerialInByte(UART_REG(UART_LST, SS_CHAN)) & 0x40) && i--)
;
sysSerialOutByte(UART_REG(UART_THR, SS_CHAN), c);
}
int sysSerialGetc(void)
{
while (!(sysSerialInByte(UART_REG(UART_LST, SS_CHAN)) & 0x01))
;
return sysSerialInByte(UART_REG(UART_RDR, SS_CHAN));
}
void sysSerialPrintString(char *s)
{
int c, il;
il = intLock();
/*QDIMCZH debug start
sysSerialOutByte(UART_REG(UART_LCR, SS_CHAN), 0x83);
sysSerialOutByte(UART_REG(UART_BRDL, SS_CHAN), 0x78);
sysSerialOutByte(UART_REG(UART_BRDH, SS_CHAN), 0x00);
sysSerialOutByte(UART_REG(UART_LCR, SS_CHAN), 0x03);
sysSerialOutByte(UART_REG(UART_MDC, SS_CHAN), 0xb);
QDIMCZH debug end */
/*QDIMCZH debug start */
sysSerialOutByte(UART_REG(UART_UDCR, SS_CHAN), 0x00);
sysSerialOutByte(UART_REG(UART_LCR, SS_CHAN), 0x80);
sysSerialOutByte(UART_REG(UART_UAFR, SS_CHAN), 0x00);
sysSerialOutByte(UART_REG(UART_BRDL, SS_CHAN), 0x8b);
sysSerialOutByte(UART_REG(UART_BRDH, SS_CHAN), 0x02);
sysSerialOutByte(UART_REG(UART_LCR, SS_CHAN), 0x03);
sysSerialOutByte(UART_REG(UART_IER, SS_CHAN), 0x00);
/*QDIMCZH debug end */
while ((c = *s++) != 0) {
if (c == '\n')
sysSerialPutc('\r');
sysSerialPutc(c);
}
sysSerialDelay(); /* Allow last char to flush */
intUnlock(il);
}
/******************************************************************************
*
* sysDuartHwInit - initialize 8245 duart devices to a quiescent state
*
* This routine initializes the MPC 8245 Duart device descriptors and puts
* the devices in a quiescent state. It is called from sysHwInit() with
* interrupts locked. Polled mode serial operations are possible, but
* not interrupt mode operations which are enabled by sysDuartHwInit2().
*
* RETURNS: N/A
*
* SEE ALSO: sysHwInit()
*/
void sysDuartHwInit (void)
{
int i;
eumbbar_base = (char *)EUMBBAR_VAL;
for (i = 0; i < N_DUART_CHANNELS; i++)
{
ns16550Chan[i].regs = (UINT8 *)devDuartParas[i].baseAdrs;
ns16550Chan[i].level = devDuartParas[i].intLevel;
ns16550Chan[i].ier = DUART_REG(IER,i);
ns16550Chan[i].lcr = DUART_REG(LCR,i);
ns16550Chan[i].mcr = DUART_REG(MCR,i);
/*ns16550Chan[i].channelMode = SIO_MODE_POLL;*/
ns16550Chan[i].channelMode = SIO_MODE_INT;
ns16550Chan[i].regDelta = devDuartParas[i].regSpace;
ns16550Chan[i].baudRate = DUART_BAUD;
ns16550Chan[i].xtal = XTAL;
ns16550DevInit (&ns16550Chan[i]);
}
if (ns16550Chan[0].channelMode == SIO_MODE_INT)
{
eumbbar_base[UDCR1] = 0x01; /* set duart mode */
eumbbar_base[ULCR1] = 0x80; /* open DLAB */
eumbbar_base[UAFR1] = 0x00;
eumbbar_base[UDMB1] = 0x02; /* for mpc8245 MSB, 9600bps @100Mhz */
eumbbar_base[UDLB1] = 0x8b; /* LSB */
eumbbar_base[ULCR1] = 0x03; /* clear DLAB, no-parity, 1stop bit, 8bit data */
eumbbar_base[UMCR1] = 0x02; /* diable loopback mode */
eumbbar_base[UIER1] = 0x03; /* Tx empty, Rx interrupt enable */
}
if (ns16550Chan[1].channelMode == SIO_MODE_INT)
{
eumbbar_base[UDCR2] = 0x01; /* set duart mode */
eumbbar_base[ULCR2] = 0x80; /* open DLAB */
eumbbar_base[UAFR2] = 0x00;
eumbbar_base[UDMB2] = 0x02; /* for mpc8245 MSB, 9600bps @100Mhz */
eumbbar_base[UDLB2] = 0x8b; /* LSB */
eumbbar_base[ULCR2] = 0x03; /* clear DLAB, no-parity, 1stop bit, 8bit data */
eumbbar_base[UMCR2] = 0x02; /* diable loopback mode */
eumbbar_base[UIER2] = 0x03; /* Tx empty, Rx interrupt enable */
}
} /* sysDuartHwInit () */
/******************************************************************************
*
* sysDuartHwInit2 - connect MPC8241/8245 duart device interrupts
*
* This routine connects the MPC8241/8245 duart device interrupts. It is called
* from sysHwInit2().
*
* Serial device interrupts cannot be connected in sysDuartHwInit() because
* the kernel memory allocator is not initialized at that point and
* intConnect() calls malloc().
*
* RETURNS: N/A
*
* SEE ALSO: sysHwInit2()
*/
void sysDuartHwInit2 (void)
{
int i;
/* connect serial interrupts */
for (i = 0; i < N_DUART_CHANNELS; i++)
{
(void) intConnect ((VOIDFUNCPTR *)((int)devDuartParas[i].vector),
ns16550Int, (int)&ns16550Chan[i] );
intEnable (devDuartParas[i].vector);
}
} /* sysDuartHwInit2 () */
/******************************************************************************
*
* sysDuartChanGet - get the SIO_CHAN device associated with MPC8245 duart channel
*
* This routine returns a pointer to the SIO_CHAN device associated
* with a specified serial channel on MPC8245. It is called by usrRoot() to
* obtain pointers when creating the system serial devices, `/tyCo/x'. It
* is also used by the WDB agent to locate its serial channel.
*
* RETURNS: A pointer to the SIO_CHAN structure for the channel, or ERROR
* if the channel is invalid.
*/
SIO_CHAN * sysDuartChanGet
(
int channel /* serial channel */
)
{
if ( (channel < 0) ||
(channel >= NELEMENTS(sysDuartSioChans)) )
return (SIO_CHAN *) ERROR;
return sysDuartSioChans[channel];
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -