📄 sc28l198serial.c
字号:
return(OK);
} /* sc28l198Ioctl() */
/******************************************************************************
* Reset a specific channel in the SC28L198.
******************************************************************************/
LOCAL void
sc28l198ResetChan(int uart, int chan)
{
SC28L198_DEV_CHAN *pTxChan;
SC28L198_DEV_CHAN *pRxChan;
pTxChan = (SC28L198_DEV_CHAN*) &(sc28l198Uart[uart].channel[chan].devHdr);
pRxChan = SAME_PCHANNEL_IN_OTHER_OCTART(pTxChan);
/* Reset the receiver, error status, and break change interrupts.
*/
pRxChan->lastCR &= CR_ENABLES_MASK;
pRxChan->lastCR |= RST_RCVR;
*pRxChan->uartCommandReg = pRxChan->lastCR;
pRxChan->lastCR &= CR_ENABLES_MASK;
pRxChan->lastCR |= RST_ERR;
*pRxChan->uartCommandReg = pRxChan->lastCR;
pRxChan->lastCR &= CR_ENABLES_MASK;
pRxChan->lastCR |= RST_BCI;
*pRxChan->uartCommandReg = pRxChan->lastCR;
/* Reset the transmitter.
*/
pTxChan->lastCR &= CR_ENABLES_MASK;
pTxChan->lastCR |= RST_XMIT;
*pTxChan->uartCommandReg = pTxChan->lastCR;
/* Disable receiver and transmitter */
pTxChan->lastCR &= CR_ENABLES_MASK;
pTxChan->lastCR &= ~(TX_ENABLE);
*pTxChan->uartCommandReg = pTxChan->lastCR;
pRxChan->lastCR &= CR_ENABLES_MASK;
pRxChan->lastCR &= ~(RX_ENABLE);
*pRxChan->uartCommandReg = pRxChan->lastCR;
} /* sc28l198ResetChan() */
/******************************************************************************
* Convert the user specified data bits to SC28L198-specific value.
******************************************************************************/
LOCAL int
sc28l198DataBits(int dataBits)
{
switch(dataBits)
{
case 5:
return(BPC_CS5);
case 6:
return(BPC_CS6);
case 7:
return(BPC_CS7);
case 8:
return(BPC_CS8);
default:
return(ERROR);
} /* switch */
} /* sc28l198DataBits */
/******************************************************************************
* Convert the user specified stop bits to SC28L198-specific value.
******************************************************************************/
LOCAL int
sc28l198StopBits(int stopBits)
{
switch(stopBits)
{
case 1:
return(STOP_BIT_1);
case 2:
return(STOP_BIT_2);
default:
return(ERROR);
} /* switch */
} /* sc28l198StopBits() */
/******************************************************************************
* Convert the user specified parity setting to SC28L198-specific value.
******************************************************************************/
LOCAL int
sc28l198Parity(char *parity)
{
/* Normal parity modes */
if(strcmp(parity, "NONE" ) == 0) return(PARITY_NONE);
if(strcmp(parity, "EVEN" ) == 0) return(PARITY_EVEN);
if(strcmp(parity, "ODD" ) == 0) return(PARITY_ODD);
/* Special wake up mode */
if(strcmp(parity, "SPECIAL") == 0) return(PARITY_SPECIAL);
return(ERROR);
} /* sc28l198Parity() */
/******************************************************************************
* Convert the user specified baud setting to SC28L198-specific value.
******************************************************************************/
LOCAL int
sc28l198BaudRate(int baudRate)
{
FAST int baud; /* Counter to index the baud rate table */
/* Search the baud rate table looking for a match. When one is found,
* return the correct value
*/
for (baud = 0; baud < NELEMENTS(baudTable); baud++)
{
if (baudTable[baud].baudRate == baudRate)
return (baudTable[baud].baudValue);
} /* for */
/* Specified baud rate not available */
return(ERROR);
} /* sc28l198BaudRate() */
/******************************************************************************
* Configure the operational mode of a given channel.
*
* Including setting the line parameters (stop, data & parity bits)
* using the actual bit settings for the SC28L198.
******************************************************************************/
void
sc28l198ConfigChan(int uart, int chan, int dataBits, int stopBits, int parity)
{
/* Configure same channel (by channel index) in other octart the same
* way to ensure that Tx and Rx use the same settings. This demands
* a restriction that both octarts always use the same number of data
* bits, stop bits, and parity in the channels with the same indices.
*
* For example, octart0 channel 3 and octart1 channel 3 must set these
* parameters the same, but octart0 channel 3 can be set differently than
* octart1 channel 4.
*/
int otherUart = (uart ? 0 : 1);
/* Disable Xon/Xoff and address recognition */
/* Set Tx interrupt on empty */
/* Disable internal flow control */
*SC28L198_MR0(uart, chan) = XON_XOFF_TRANS_OFF | ADDR_TRANS_OFF |
TXINT_MT | FLOW_CTRL_HOST | ADDR_CTRL_NONE;
*SC28L198_MR0(otherUart, chan) = XON_XOFF_TRANS_OFF | ADDR_TRANS_OFF |
TXINT_MT | FLOW_CTRL_HOST | ADDR_CTRL_NONE;
/* Disable internal receiver RTS control */
/* Enable interrupt status masking */
/* Status bits provided on a character by character basis */
/* Initialize parity and data bit settings */
*SC28L198_MR1(uart, chan) = RXRTS_CTRL_OFF | ISR_RD_MASKED |
ERR_MODE_CHAR | parity | dataBits;
*SC28L198_MR1(otherUart, chan) = RXRTS_CTRL_OFF | ISR_RD_MASKED |
ERR_MODE_CHAR | parity | dataBits;
/* Put the device in mormal mode */
/* Disable internal transmitter RTS control */
/* Trasmitter ignores CTS */
/* Set Rx interrupt on a single character */
/* Initialize stop bit setting */
*SC28L198_MR2(uart, chan) = NORMAL_MODE | TXRTS_CTRL_OFF |
CTSN_CTRL_TX_OFF | RXINT_RRDY | stopBits;
*SC28L198_MR2(otherUart, chan) = NORMAL_MODE | TXRTS_CTRL_OFF |
CTSN_CTRL_TX_OFF | RXINT_RRDY | stopBits;
} /* sc28l198ConfigChan() */
/******************************************************************************
* Set the baud rate using the actual bit settings for the SC28L198.
******************************************************************************/
void
sc28l198SetBaudRate(int uart, int chan, int baudRate)
{
int otherUart = (uart ? 0 : 1);
/* Configure the xmit/rcvr baud rates. Rx channel is actually in the
* other uart.
*/
*SC28L198_TXCSR(uart,chan)=baudRate;
*SC28L198_RXCSR(otherUart,chan)=baudRate;
} /* sio32SetBaudRate() */
/******************************************************************************
* Initialize the SC28L198.
******************************************************************************/
LOCAL STATUS
sc28l198HrdInit(int uart)
{
FAST int chan;
/* Setup the GCCR:
*
* !!!! NOTE that the datasheet states that the GCCR must be the first
* register addressed during initialization.
*
* Configure to:
* - Support arbitrarily long (asynchronous) bus cycles.
* - Chip is not to supply an interrupt vector at interrupt time.
* - Power on (enable chip).
*/
*SC28L198_GCCR(uart)=ASYNC_BUS | (IVC_MASK&IVC_NONE) | PWR_ON;
/* Initialize all the channels in the uart. */
for(chan = 0; chan < SC28L198_CHAN_PER_UART; chan ++)
{
/* Disable Tx and Rx. */
sc28l198Uart[uart].channel[chan].lastCR = 0;
*SC28L198_CR(uart,chan)=sc28l198Uart[uart].channel[chan].lastCR;
/* Disable all interrupts for this channel */
sc28l198Uart[uart].channel[chan].lastIMR = 0;
*SC28L198_IMR(uart,chan) = sc28l198Uart[uart].channel[chan].lastIMR;
} /* for */
return(OK);
} /* sc28l198HrdInit() */
/******************************************************************************
* SC28L198 Driver Initialization Routine.
******************************************************************************/
STATUS
sc28l198Drv(void)
{
FAST int chan;
FAST int uart;
/* Get the physical location of the IMMR register for use later by
* interrupt routine.
*/
immrVal = vxImmrGet();
/* Set the number of channels in the second octart based on which
* SBC number (3 or 4) on the Axcelis board we are plugged into.
*/
if (ptrGetBoardID() == 2) /* Note ID 2 == SBC3 */
{
sc28l198Cfg[1].numChannels = SC28L198_NUM_CHANNELS_SBC3;
}
else
{
sc28l198Cfg[1].numChannels = SC28L198_NUM_CHANNELS_SBC4;
}
/* For each physical device in the system */
for(uart=0; uart<SC28L198_MAX_UARTS; uart++ )
{
/* check if driver already installed */
if(sc28l198Uart[uart].drvNum > 0)
{
DRV_LOG(DRV_DEBUG_INIT,
"Driver already installed for device %d with driver %d\n",
uart, sc28l198Uart[uart].drvNum,0,0,0,0);
return(OK);
}
/* Minimal initialization of the device hardware */
sc28l198HrdInit(uart);
sc28l198Uart[uart].exists = TRUE;
/* Allocate channel control structure. */
if((sc28l198Uart[uart].channel =
calloc(SC28L198_CHAN_PER_UART, sizeof(SC28L198_DEV_CHAN))) == NULL)
{
sc28l198Error(1, "Channel structure malloc failed\n");
return(ERROR);
} /* if */
/* Fill in the channel control structure for each channel */
for (chan = 0; chan < SC28L198_CHAN_PER_UART; chan++)
{
/* Initialize channel control data structers */
sc28l198Uart[uart].channel[chan].uart = uart;
sc28l198Uart[uart].channel[chan].chan = chan;
sc28l198Uart[uart].channel[chan].created = FALSE;
sc28l198Uart[uart].channel[chan].chanOpen = FALSE;
sc28l198Uart[uart].channel[chan].wrtStateBusy = FALSE;
/* Address of Channel Command reg */
sc28l198Uart[uart].channel[chan].uartCommandReg =
SC28L198_CR(uart, chan);
/* Address of RX/TX Data reg for channel */
sc28l198Uart[uart].channel[chan].uartTxDataReg =
SC28L198_TXFIFO(uart, chan);
sc28l198Uart[uart].channel[chan].uartRxDataReg =
SC28L198_RXFIFO(uart, chan);
/* Address of interrupt status reg for channel */
sc28l198Uart[uart].channel[chan].uartIntStatusReg =
SC28L198_ISR(uart, chan);
/* Allocate read and write ring buffers */
sc28l198Uart[uart].channel[chan].wrtBuf = rngCreate(BUFFER_SIZE);
sc28l198Uart[uart].channel[chan].rdBuf = rngCreate(BUFFER_SIZE);
if ((sc28l198Uart[uart].channel[chan].wrtBuf == NULL) ||
(sc28l198Uart[uart].channel[chan].rdBuf == NULL))
{
sc28l198Error(0, "Cannot allocate ring buffers\n");
return(ERROR);
} /* if */
/* Create our mutex */
sc28l198Uart[uart].channel[chan].mutexSem =
semMCreate (SEM_Q_FIFO | SEM_DELETE_SAFE);
} /* for */
} /* for */
/* This loop continues the initialization. Since some of these
* initializations reference the Rx channels in the "other" octart,
* they cannot be done until after the above init loop has setup
* the basic fields in all channels of both octarts.
*/
/* For each physical device in the system */
for(uart=0; uart<SC28L198_MAX_UARTS; uart++ )
{
for (chan = 0; chan < SC28L198_CHAN_PER_UART; chan++)
{
/* Reset the channel to a known good state */
sc28l198ResetChan(uart, chan);
/* Set the channel to a default baud rate of 9600 baud */
sc28l198SetBaudRate(uart, chan, B9600);
/* Configure the channel with a default configuration */
sc28l198ConfigChan(uart, chan, BPC_CS8, STOP_BIT_1, PARITY_NONE);
} /* for */
/* Initialize Interrupt Handling */
sc28l198InitInterrupts(uart);
/* Add the driver to the vxWorks IO System */
if((sc28l198Uart[uart].drvNum =
iosDrvInstall( (FUNCPTR) sc28l198Open, (FUNCPTR) NULL,
(FUNCPTR) sc28l198Open, (FUNCPTR) sc28l198Close,
(FUNCPTR) sc28l198Read, (FUNCPTR) sc28l198Write,
(FUNCPTR) sc28l198Ioctl)) < 0)
{
/* error number set by iosDrvInstall */
return(ERROR);
}
DRV_LOG(DRV_DEBUG_INIT,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -