📄 st16954sio.c
字号:
case SIO_MODE_GET:
*(int *)arg = pChan->channelMode;
break;
case SIO_AVAIL_MODES_GET:
*(int *)arg = SIO_MODE_INT | SIO_MODE_POLL;
break;
case SIO_HW_OPTS_SET:
case SIO_HW_OPTS_GET:
default:
status = ENOSYS;
}
return status;
}
/*******************************************************************************
*
* st16954IntWr - handle a transmitter interrupt
*
* This routine handles write interrupts from the UART.
*
* RETURNS: N/A
*/
void st16954IntWr
(
ST16954_CHAN * pChan /* ptr to struct describing channel */
)
{
char outChar;
if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
{
/* write char. to Transmit Holding Reg. */
ST16954_REG_WRITE(pChan, THR, outChar);
}
else
{
pChan->ier |= RxFIFO_BIT;
pChan->ier &= (~TxFIFO_BIT); /* indicates to disable Tx Int */
ST16954_REG_WRITE(pChan, IER, pChan->ier);
}
/* ST16954_REG_READ(pChan, LSR, outChar);*/
}
/*****************************************************************************
*
* st16954IntRd - handle a receiver interrupt
*
* This routine handles read interrupts from the UART.
*
* RETURNS: N/A
*/
void st16954IntRd
(
ST16954_CHAN * pChan /* ptr to struct describing channel */
)
{
char inchar;
/* read character from Receive Holding Reg. */
ST16954_REG_READ(pChan, RHR, inchar);
(*pChan->putRcvChar) (pChan->putRcvArg, inchar);
}
/**********************************************************************
*
* st16954IntEx - miscellaneous interrupt processing
*
* This routine handles miscellaneous interrupts on the UART.
*
* RETURNS: N/A
*/
void st16954IntEx
(
ST16954_CHAN * pChan /* ptr to struct describing channel */
)
{
/* Nothing for now... */
}
/******************************************************************************
*
* st16954Int - interrupt level processing
*
* This routine handles interrupts from the UART.
*
* RETURNS: N/A
*/
void st16954Int
(
ST16954_CHAN * pChan /* ptr to struct describing channel */
)
{
FAST volatile char intStatus;
FAST volatile char lsr;
char outChar; /* Possible char to be output */
/*
* If this routine has been called from the multiplexed interrupt
* handler, then we have already read the Interrupt Status Register,
* and must not read it again, else this routine has been installled
* directly using intConnect() and we must now read the Interrupt
* Status Register (or Interrupt Identification Register).
*/
if (!multiplexed)
{
ST16954_REG_READ(pChan, ISR, intStatus);
intStatus &= 0x0F;
}
ST16954_REG_READ(pChan, LSR, lsr);
/*
* This UART chip always produces level active interrupts, and the ISR
* only indicates the highest priority interrupt.
* In the case that receive and transmit interrupts happened at
* the same time, we must clear both interrupt pending to prevent
* edge-triggered interrupt(output from interrupt controller) from locking
* up. One way doing it is to disable all the interrupts at the beginning
* of the ISR and enable at the end.
*/
ST16954_REG_WRITE(pChan, IER, 0);
switch (intStatus)
{
case ISR_RLS:
/*
* overrun, parity error and break interrupt:
*
* read LSR to reset interrupt
*/
break;
case ISR_RDA:
/* received data available: FALL THROUGH to timeout */
case ISR_TIMEOUT:
/*
* receiver FIFO interrupt. In some cases, ISR_RDA
* will not be indicated in ISR register when there
* is more than one char. in FIFO.
*/
st16954IntRd (pChan); /* RxChar Avail */
break;
case ISR_THRE:
/* transmitter holding register ready */
if ((*pChan->getTxChar) (pChan->getTxArg, &outChar) != ERROR)
{
/* char. to Transmit Holding Reg. */
ST16954_REG_WRITE(pChan, THR, outChar);
}
else
pChan->ier &= (~TxFIFO_BIT); /* indicates to disable Tx Int */
break;
default:
break;
}
ST16954_REG_WRITE(pChan, IER, pChan->ier);
}
/******************************************************************************
*
* st16954MuxInt - multiplexed interrupt level processing
*
* This routine handles multiplexed interrupts from the DUART. It assumes that
* channels 0 and 1 are connected so that they produce the same interrupt.
*
* RETURNS: N/A
*/
void st16954MuxInt
(
ST16954_MUX * pMux /* ptr to struct describing multiplexed chans */
)
{
FAST volatile char intStatus;
ST16954_CHAN * pChan;
/* get pointer to structure for channel to examine first */
pChan = &(pMux->pChan[pMux->nextChan]);
/*
* Step on the next channel to examine: use round-robin for which to
* examine first.
*/
if (pMux->nextChan == 0)
pMux->nextChan = 1;
else
pMux->nextChan = 0;
/*
* Let the st16954Int() routine know it is called from here, not direct
* from intConnect().
*/
multiplexed = TRUE;
/* check Interrupt Status Register for this channel */
ST16954_REG_READ(pChan, ISR, intStatus);
intStatus &= 0x0F;
if ((intStatus & 0x01) == 0)
{
/* Call int handler if int active */
st16954Int (pChan);
}
else
{
/* step on again */
pChan = &pMux->pChan[pMux->nextChan];
if (pMux->nextChan == 0)
pMux->nextChan = 1;
else
pMux->nextChan = 0;
/* get interrupt status for next channel */
ST16954_REG_READ(pChan, ISR, intStatus);
intStatus &= 0x0F;
/* and call interrupt handler if active */
if ((intStatus & 0x01) == 0)
st16954Int (pChan);
}
multiplexed = FALSE;
return;
}
/*******************************************************************************
*
* st16954TxStartup - transmitter startup routine
*
* Call interrupt level character output routine and enable interrupt!
*
* RETURNS: OK on success, ENOSYS if the device is polled-only, or
* EIO on hardware error.
*/
LOCAL int st16954TxStartup
(
ST16954_CHAN * pChan /* ptr to SIO_CHAN describing this channel */
)
{
/* ST16954_CHAN * pChan = (ST16954_CHAN *)pSioChan;*/
if (pChan->channelMode == SIO_MODE_INT)
{
pChan->ier = IER_ERDAI;
pChan->ier |= TxFIFO_BIT;
ST16954_REG_WRITE(pChan, IER, pChan->ier);
return OK;
}
else
return ENOSYS;
}
/******************************************************************************
*
* st16954PollOutput - output a character in polled mode.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the output buffer is full, ENOSYS if the device is interrupt-only.
*/
int st16954PollOutput
(
ST16954_CHAN * pChan, /* ptr to SIO_CHAN describing this channel */
char *outChar, /* char to be output */
int count
)
{
char pollStatus;
int i;
unsigned int time_out=0;
ST16954_REG_WRITE(pChan, SPR, SPR_ACR); /* SPR = 0, PT ACR */
ST16954_REG_READ(pChan, ACR, pollStatus);/* Get ACR to char inchar */
ST16954_REG_WRITE(pChan, ACR, pollStatus | ACR_ADDEN | ACR_ICREN);/* Set ACR[7], to enable access to RFL, ect */
while((++time_out)<10000)
{
ST16954_REG_READ(pChan, TFL, pollStatus);
if ((pollStatus & 0xFF) == 0x00)
break;
}
ST16954_REG_WRITE(pChan, SPR, SPR_ACR); /* SPR = 0, PT ACR */
ST16954_REG_WRITE(pChan, ACR, pollStatus & (~ACR_ADDEN));
if(pollStatus > 0)
return EAGAIN;
for (i = 0; i < count; i++)
{
ST16954_REG_WRITE(pChan, THR, outChar[i]);
}
return OK;
}
/******************************************************************************
*
* st16954PollInput - poll the device for input.
*
* RETURNS: OK if a character arrived, EIO on device error, EAGAIN
* if the input buffer is empty, ENOSYS if the device is interrupt-only.
*/
int st16954PollInput
(
ST16954_CHAN * pChan, /* ptr to SIO_CHAN describing this channel */
char * thisChar /* ptr to where to return character */
)
{
char pollStatus;
int i, nLen;
ST16954_REG_WRITE(pChan, SPR, SPR_ACR); /* SPR = 0, PT ACR */
ST16954_REG_READ(pChan, ACR, pollStatus);/* Get ACR to char inchar */
ST16954_REG_WRITE(pChan, ACR, pollStatus | ACR_ADDEN | ACR_ICREN);/* Set ACR[7], to enable access to RFL, ect */
ST16954_REG_READ(pChan, RFL, nLen); /* Read RFL to get the number of characters in the receiver FIFO */
nLen=nLen & 0xFF;
ST16954_REG_WRITE(pChan, SPR, SPR_ACR); /* SPR = 0, PT ACR */
ST16954_REG_WRITE(pChan, ACR, pollStatus & (~ACR_ADDEN));
for (i = 0; i < nLen; i++)
{
ST16954_REG_READ(pChan, RHR, thisChar[i]);
}
return nLen;
}
/******************************************************************************
*
* st16954CallbackInstall - install ISR callbacks to get/put chars.
*
* This routine installs interrupt callbacks for transmitting characters
* and receiving characters.
*
* RETURNS: OK on success, or ENOSYS for an unsupported callback type.
*/
int st16954CallbackInstall
(
ST16954_CHAN * pChan, /* ptr to SIO_CHAN describing this channel */
int callbackType, /* type of callback */
STATUS (*callback)(), /* callback */
void * callbackArg /* parameter to callback */
)
{
/* ST16954_CHAN * pChan = (ST16954_CHAN *)pSioChan;*/
switch (callbackType)
{
case SIO_CALLBACK_GET_TX_CHAR:
pChan->getTxChar = callback;
pChan->getTxArg = callbackArg;
return OK;
case SIO_CALLBACK_PUT_RCV_CHAR:
pChan->putRcvChar = callback;
pChan->putRcvArg = callbackArg;
return OK;
default:
return ENOSYS;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -