📄 pc16552d.c
字号:
/*
* +-------------------------------------------------------------------+
* | Copyright (c) 1999 by TriMedia Technologies. |
* | |
* | This software is furnished under a license and may only be used |
* | and copied in accordance with the terms and conditions of such a |
* | license and with the inclusion of this copyright notice. This |
* | software or any other copies of this software may not be provided |
* | or otherwise made available to any other person. The ownership |
* | and title of this software is not transferred. |
* | |
* | The information in this software is subject to change without |
* | any prior notice and should not be consTrued as a commitment by |
* | TriMedia Technologies. |
* | |
* | This code and information is provided "as is" without any |
* | warranty of any kind, either expressed or implied, including but |
* | not limited to the implied warranties of merchantability and/or |
* | fitness for any particular purpose. |
* +-------------------------------------------------------------------+
*
* Module name : pc16552D.c 1.6
*
* Last update : 18:43:42 - 00/11/09
*/
#include "pc16552D.h"
#include <tm1/tsaUart.h>
#include <tm1/tmAssert.h>
#include <tmlib/dprintf.h>
#define regTHR 0 /* Transmit Buffer Reg */
#define regRBR 0 /* Receive Buffer Reg */
#define regDLL 0 /* Divisor Latch LSB */
#define regDLM 1 /* Divisor Latch MSB */
#define regIER 1 /* Interrupt Enable Reg */
#define regIIR 2 /* Intr Idetification Reg */
#define regFCR 2 /* Fifo control Reg */
#define regLCR 3 /* Line control Reg */
#define regMCR 4 /* Modem Control Reg */
#define regLSR 5 /* Line Status Reg */
#define regMSR 6 /* Modem Status Reg */
#define regSCR 7 /* Scratch Register. */
#define regMCR_DTR (1 << 0)
#define regMCR_RTS (1 << 1)
#define regMCR_LOOP (1 << 4)
#define regIIR_INT (1 << 0)
#define regIIR_LSR (1 << 1 | 1 << 2)
#define regIIR_RD (1 << 2)
#define regIIR_TIMEOUT (1 << 2 | 1 << 3)
#define regIIR_TD (1 << 1)
#define regIIR_MSR 0
#define regMSR_DCTS (1 << 0)
#define regMSR_DDSR (1 << 1)
#define regMSR_TERI (1 << 2)
#define regMSR_DDCD (1 << 3)
#define regMSR_CTS (1 << 4)
#define regMSR_DSR (1 << 5)
#define regMSR_RI (1 << 6)
#define regMSR_DCD (1 << 7)
#define regIER_RD (1 << 0)
#define regIER_TD (1 << 1)
#define regIER_LSR (1 << 2)
#define regIER_MSR (1 << 3)
#define regLSR_RD (1 << 0)
#define regLSR_OVERRUN (1 << 1)
#define regLSR_PARITY (1 << 2)
#define regLSR_FRAMING (1 << 3)
#define regLSR_BREAK (1 << 4)
#define regLSR_TD (1 << 5)
#define regLCR_DATA (1 << 0 | 1 << 1)
#define regLCR_STOP (1 << 2)
#define regLCR_PARITY (1 << 3)
#define regLCR_EVEN (1 << 4)
#define regLCR_SPACE (1 << 4)
#define regLCR_STICK (1 << 5)
#define regLCR_BREAK (1 << 6)
#define regLCR_DLAB (1 << 7)
static pc16552DReadRegisterFunc_t readRegister = Null;
static pc16552DWriteRegisterFunc_t writeRegister = Null;
static Int crystalType;
volatile static UInt8 iirStore = 0;
static Int baudDivisorTable[3][5] =
{{
12,
6,
3,
2,
0
},
{
20,
10,
5,
0,
0
},
{
120,
60,
30,
21,
9
}};
static UInt32 pc16552DSupportedBaudRates[3] =
{
PC16552D_BAUD_RATES_1_8432,
PC16552D_BAUD_RATES_3_072,
PC16552D_BAUD_RATES_18_432
};
/************************************************************************************************/
extern Bool pc16552DPICSourceDetect(UInt32 * source)
{
UInt8 reg;
reg = readRegister(unit0, regIIR);
if (!(reg & regIIR_INT))
{
iirStore = reg;
*source = 0;
return True;
}
reg = readRegister(unit1, regIIR);
if (!(reg & regIIR_INT))
{
iirStore = reg;
*source = 1;
return True;
}
return False;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DInit(ppc16552DParams_t params)
{
tmAssert(params->readRegisterFunc, BOARD_ERR_NULL_FUNCTION);
tmAssert(params->writeRegisterFunc, BOARD_ERR_NULL_FUNCTION);
tmAssert(params->crystalType < 3, -1);
readRegister = params->readRegisterFunc;
writeRegister = params->writeRegisterFunc;
crystalType = params->crystalType;
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DReadData(unitSelect_t portID, Address data)
{
*data = readRegister(portID, regRBR);
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DWriteData(unitSelect_t portID, Char data)
{
writeRegister(portID, regTHR, data);
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DUartConfig (unitSelect_t portID,
tsaUartConfig_t command, Pointer value)
{
UInt8 reg1;
tmLibdevErr_t err = TMLIBDEV_OK;
switch (command)
{
case UART_DTR_ON:
reg1 = readRegister(portID, regMCR) | regMCR_DTR;
writeRegister(portID, regMCR, reg1);
break;
case UART_DTR_OFF:
reg1 = readRegister(portID, regMCR) & ~regMCR_DTR;
writeRegister(portID, regMCR, reg1);
break;
case UART_RTS_ON:
reg1 = readRegister(portID, regMCR) | regMCR_RTS;
writeRegister(portID, regMCR, reg1);
break;
case UART_RTS_OFF:
reg1 = readRegister(portID, regMCR) & ~regMCR_RTS;
writeRegister(portID, regMCR, reg1);
break;
case UART_GET_SCRATCH_REGI:
tmAssert(value, TMLIBDEV_ERR_NULL_PARAMETER);
*(UInt8*)value = readRegister(portID, regSCR);
break;
case UART_SET_SCRATCH_REGI:
tmAssert(value, TMLIBDEV_ERR_NULL_PARAMETER);
writeRegister(portID, regSCR, *(UInt8*)value);
break;
case UART_SET_LOOP_BACK:
tmAssert(value, TMLIBDEV_ERR_NULL_PARAMETER);
reg1 = readRegister(portID, regMCR);
if (*(Bool *) value)
reg1 |= regMCR_LOOP;
else
reg1 &= ~regMCR_LOOP;
writeRegister(portID, regMCR, reg1);
break;
default:
return UART_ERR_UNSUPPORTED_CONFIG_COMMAND;
}
return err;
}
/************************************************************************************************/
extern Bool pc16552DGetEvent(unitSelect_t portID,
tsaUartConfigEvent_t *event)
{
UInt8 reg;
UInt8 reg2;
tsaUartConfigEvent_t e;
if (iirStore == 0)
reg = readRegister(portID, regIIR) & 0x0f;
else
{
reg = iirStore;
iirStore = 0;
}
if (reg & regIIR_INT)
{
return False;
}
switch (reg)
{
case regIIR_LSR:
e = BOARD_UART_ERR_EVENT;
reg2 = readRegister(portID, regLSR);
if (reg2 & regLSR_OVERRUN)
e |= BOARD_UART_RX_ERR_OVERRUN;
if (reg2 & regLSR_PARITY)
e |= BOARD_UART_RX_ERR_PARITY;
if (reg2 & regLSR_FRAMING)
e |= BOARD_UART_RX_ERR_FRAMING;
if (reg2 & regLSR_BREAK)
e |= BOARD_UART_RX_ERR_BREAK;
break;
case regIIR_RD:
case regIIR_TIMEOUT:
e = BOARD_UART_RX_DATA;
break;
case regIIR_TD:
e = BOARD_UART_TX_COMPLETE;
break;
case regIIR_MSR:
e = BOARD_UART_CONFIG_EVENT;
reg2 = readRegister(portID, regMSR);
if (reg2 & regMSR_DCTS)
{
if (reg2 & regMSR_CTS)
e |= UART_CTS_ON;
else
e |= UART_CTS_OFF;
}
if (reg2 & regMSR_DDSR)
{
if (reg2 & regMSR_DSR)
e |= UART_DSR_ON;
else
e |= UART_DSR_OFF;
}
if (reg & regMSR_TERI)
e |= UART_RI_OFF;
if (reg & regMSR_DDCD)
{
if (reg2 & regMSR_DCD)
e |= UART_DCD_ON;
else
e |= UART_DCD_OFF;
}
if (reg & regMSR_RI)
e |= UART_RI_ON;
break;
default:
e = BOARD_UART_ERR_OTHER;
break;
}
*event = e;
return True;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DInitPort(unitSelect_t portID, pboardUartParam_t params)
{
tmLibdevErr_t err;
tmAssert(readRegister, -1);
err = pc16552DSetBaudRate(portID, params->baudRate);
if (err)
return err;
err = pc16552DSetSerialDataFormat(portID, params->numStopBits, params->numDataBits, params->parity);
if (err)
return err;
err = pc16552DSetTxInt(portID, False);
if (err)
return err;
err = pc16552DSetRxInt(portID, False);
if (err)
return err;
err = pc16552DSetLineStatusInt(portID, False);
if (err)
return err;
err = pc16552DSetModemStatusInt(portID, params->enableControlInt);
if (err)
return err;
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DTermPort(unitSelect_t portID)
{
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetTxInt(unitSelect_t portID, Bool enable)
{
Int8 reg;
reg = readRegister(portID, regIER);
if (enable)
reg |= regIER_TD;
else
reg &= ~regIER_TD;
writeRegister(portID, regIER, reg);
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetRxInt(unitSelect_t portID, Bool enable)
{
Int8 reg;
reg = readRegister(portID, regIER);
if (enable)
reg |= regIER_RD;
else
reg &= ~regIER_RD;
writeRegister(portID, regIER, reg);
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetLineStatusInt(unitSelect_t portID, Bool enable)
{
Int8 reg;
reg = readRegister(portID, regIER);
if (enable)
reg |= regIER_LSR;
else
reg &= ~regIER_LSR;
writeRegister(portID, regIER, reg);
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetModemStatusInt(unitSelect_t portID, Bool enable)
{
Int8 reg;
reg = readRegister(portID, regIER);
if (enable)
reg |= regIER_MSR;
else
reg &= ~regIER_MSR;
writeRegister(portID, regIER, reg);
return TMLIBDEV_OK;
}
/************************************************************************************************/
tmLibdevErr_t pc16552DSetSerialDataFormat (unitSelect_t portID,
Int numStopBits, Int numDataBits, tsaUartParity_t parity)
{
UInt8 reg;
if (!(numStopBits == 1 || numStopBits == 2))
return UART_ERR_INVALID_NUM_STOP_BITS;
if (!(5 <= numDataBits && numDataBits <= 8))
return UART_ERR_INVALID_NUM_DATA_BITS;
if (!(parity == UART_PARITY_NONE || parity == UART_PARITY_EVEN ||
parity == UART_PARITY_ODD || parity == UART_PARITY_MARK ||
parity == UART_PARITY_SPACE))
return UART_ERR_INVALID_PARITY;
reg = readRegister (portID, regLCR);
reg &= regLCR_DLAB; /*clear everything but DLAB*/
reg |= numDataBits - 5 & regLCR_DATA;
if (numStopBits == 2) reg |= regLCR_STOP;
switch (parity)
{
case UART_PARITY_EVEN:
reg |= regLCR_PARITY | regLCR_EVEN;
break;
case UART_PARITY_ODD:
reg |= regLCR_PARITY;
break;
case UART_PARITY_MARK:
reg |= regLCR_PARITY | regLCR_STICK;
break;
case UART_PARITY_SPACE:
reg |= regLCR_PARITY | regLCR_STICK | regLCR_SPACE;
break;
}
writeRegister(portID, regLCR, reg);
return TMLIBDEV_OK;
}
/************************************************************************************************/
extern tmLibdevErr_t pc16552DSetBaudRate(unitSelect_t portID, tsaUartBaud_t baudRate)
{
UInt8 reg1;
UInt8 reg2;
UInt8 reg3;
Int i;
tmAssert(baudRate & pc16552DSupportedBaudRates[crystalType], UART_ERR_INVALID_BAUDRATE);
/* get index for baudrate table */
switch(baudRate)
{
case UART_BAUD_9600:
i = 0;
break;
case UART_BAUD_19200:
i = 1;
break;
case UART_BAUD_38400:
i = 2;
break;
case UART_BAUD_57600:
i = 3;
break;
case UART_BAUD_115200:
i = 4;
break;
default:
return UART_ERR_INVALID_BAUDRATE;
}
/* Set divisor latch access bit, so that the divisor latch of the baud generator
can be accessed. */
reg1 = readRegister(portID, regLCR);
writeRegister(portID, regLCR, reg1 | regLCR_DLAB);
reg2 = baudDivisorTable[crystalType][i];
reg3 = baudDivisorTable[crystalType][i] >> 8;
writeRegister(portID, regDLL, reg2);
writeRegister(portID, regDLM, reg3);
/* reset divisor latch access bit */
writeRegister(portID, regLCR, reg1 & ~regLCR_DLAB);
return TMLIBDEV_OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -