?? ser_gen.c
字號:
else /* rxcount > 0 */
{
/*
Get remainder of Block of data from the serial port, recsize characters
and store them in rxbuf
*/
if ((rxchar = waitforchar(comport)) >= 0) /* no errors */
{
/*
Check Phase bit
*/
if (rxchar & 0x80) /* check to see that phase bit = '0' */
{
if (outputmode == STREAM)
{
phaseerror_count[comport]++; /* keep track of phase errors */
resynch = TRUE; /* loop again flag */
continue;
}
else
{
return(RXPHASEERROR); /* return phase error */
}
}
}
else
{
if (outputmode == STREAM)
{
phaseerror_count[comport]++; /* keep track of phase errors */
resynch = TRUE; /* loop again flag */
continue;
}
else
{
return(RXERRORS);
}
}
}
/*
Store the received character
*/
*rxbufptr++ = rxchar; /* store and adjust pointer */
rxcount++; /* increment */
}
while ((resynch) || (rxcount < recsize));
/*
Return the number of characters received
*/
return(rxcount);
}
/*
send_serial_cmd - Send Serial Command to the Bird port
Prototype in: serial.h
Parameters Passed: short comport
cmd - string to send to the serial point
cmdsize - size of the cmd string (cmd is NOT
NULL terminated, since the data can
be NULL)
Return Value: number of characters transmitted
Remarks: Routine will send a string of characters to the serial
port. The string is pointed to by cmd and all
characters will be sent upto but NOT including
the NULL
*/
int send_serial_cmd(comport, cmd, cmdsize)
short comport;
unsigned char * cmd;
short cmdsize;
{
short txcount = 0;
DISABLE();
/*
Disable the Receive Interrupts
*/
OUTPORTB(com_base[comport] + INTERENABLE, 0);
OUTPORTB(com_base[comport] + INTERENABLE, 0);
/*
Turn the Transmitter to Transmit
*/
if(port_type[comport] == RS485_PORT)
OUTPORTB(com_base[comport] + MODEMCONT, DTRON + OUT2);
/*
Transmit the CMD and DATA Characters NOW
*/
while (txcount < cmdsize)
{
/*
Store the character in the TX buffer
*/
if (txcount == 0)
{
if(port_type[comport] == RS485_PORT)
while (send_serial_cmdchar(comport,*cmd) == TXBUFFERFULL);
else
while (send_serial_datachar(comport,*cmd) == TXBUFFERFULL);
}
else
{
while (send_serial_datachar(comport,*cmd) == TXBUFFERFULL);
}
cmd++;
txcount++;
}
/*
Clear the Receive Buffer in case of a dirty char
*/
while (INPORTB(com_base[comport] + LINESTATUS) & DATARDY)
INPORTB(com_base[comport] + RXBUF);
/*
Turn the Transceiver to Receive
*/
if(port_type[comport] == RS485_PORT)
OUTPORTB(com_base[comport] + MODEMCONT, OUT2);
/*
Enable the Receive Interrupts
*/
OUTPORTB (com_base[comport] + INTERENABLE,
RXDATAAVAILINTENABLE | RXLINESTATUSINTENABLE);
OUTPORTB (com_base[comport] + INTERENABLE,
RXDATAAVAILINTENABLE | RXLINESTATUSINTENABLE);
ENABLE();
return(txcount);
}
/*
send_serial_cmdchar - Send one serial CMD char to the serial port
send_serial_datachar - Send one serial DATA char to the serial port
Prototype in: serial.h
Parameters Passed: short comport
chr - character to send to the serial port
Return Value: returns TRUE if successful, or TXBUFFERFULL if the
TXBUF is full
Remarks: The routine is used to send a single character
out to the UART if there is room in the output buffer.
The routine checks to see if the Transmit interrupts
are presently enabled...if not they are turned out
so the ISR will get the character.
*/
int send_serial_cmdchar(comport,chr)
short comport;
unsigned char chr;
{
/*
Check for a full TX Hardware buffer...
*/
if (!(INPORTB(com_base[comport] + LINESTATUS) & TXSHIFTEMPTY))
return(TXBUFFERFULL);
/*
Set the Parity to a MARK
*/
if(port_type[comport] == RS485_PORT)
OUTPORTB(com_base[comport] + LINECONT, STOP_WORDLEN_MARKPARITY);
/*
Write the character to the Hardware
*/
OUTPORTB(com_base[comport] + TXBUF, chr);
/*
Wait for the Buffer to EMPTY
*/
while (!(INPORTB(com_base[comport] + LINESTATUS) & TXSHIFTEMPTY));
/*
Set the Parity back to a SPACE
*/
if(port_type[comport] == RS485_PORT)
OUTPORTB(com_base[comport] + LINECONT, STOP_WORDLEN_SPACEPARITY);
return(TRUE);
}
int send_serial_datachar(comport,chr)
short comport;
unsigned char chr;
{
/*
Check for a full TX Hardware buffer...
*/
if (!(INPORTB(com_base[comport] + LINESTATUS) & TXSHIFTEMPTY))
return(TXBUFFERFULL);
/*
Write the character to the Hardware
*/
OUTPORTB(com_base[comport] + TXBUF, chr);
/*
Wait for the Buffer to EMPTY
*/
while (!(INPORTB(com_base[comport] + LINESTATUS) & TXSHIFTEMPTY));
return(TRUE);
}
/*
get_serial_char - Get 1 Character from the serial port if one is available
Prototype in: serial.h
Parameters Passed: short comport
Return Value: returns the
Remarks: returns the receive character if successful,
RXERRORS if recieve errors
NODATAAVAIL if no characer available
*/
int get_serial_char(comport)
short comport;
{
short rxchar;
if ((!rxerrors[comport]) && (!rxbufoverruns[comport]))
{
/*
get character if available...else return
*/
if (rxbufinptr[comport] == rxbufoutptr[comport])
return(NODATAAVAIL);
/*
get the character
*/
rxchar = *rxbufoutptr[comport]++;
/*
check for End of Rx buffer..if so, wrap pointer to start
*/
if (rxbufoutptr[comport] == &rxbuf[comport][RXBUFSIZE])
rxbufoutptr[comport] = rxbuf[comport];
/*
return the character
*/
return(rxchar);
}
else
{
/*
Reset Error flags and Announce the Errors
*/
if (rxerrors[comport])
{
DISABLE();
printf("** ERROR ** rx line errors have occured\n");
rxerrors[comport] = FALSE;
ENABLE();
}
if (rxbufoverruns[comport])
{
DISABLE();
printf("** ERROR ** rx buffer overrun errors have occured\n");
rxbufoverruns[comport] = FALSE;
ENABLE();
}
return(RXERRORS);
}
}
/*
waitforchar - Wait for a Character from the Serial Port
Prototype in: serial.h
Parameters Passed: short comport
Return Value: returns the receive character if successful,
RXERRORS if recieve errors,
RXTIMEOUT if a time out occurs before a
character is ready
Remarks: Routine waits for the TIMEOUTINTICKS period
for a character
*/
int waitforchar(comport)
short comport;
{
short rxchar;
long starttime;
/*
Get the time now in ticks
*/
starttime = GETTICKS;
/*
Wait until a character is available
....leave loop if errors or character available
*/
while ((rxchar = get_serial_char(comport)) == NODATAAVAIL)
{
/*
Check to see if a timeout occured
*/
if ((GETTICKS - starttime) > (long) (RXTIMEOUTINSECS * 1000) / tick_msec)
{
printf("\n** ERROR ** receiver timed out\n");
return(RXTIMEOUT);
}
}
/*
return if RX errors
*/
if (rxchar < 0)
return(RXERRORS);
/*
Everything is OK...return the character
*/
return(rxchar);
}
/*
waitforphase - Wait for a Character with phase bit set
Prototype in: serial.h
Parameters Passed: short comport
Return Value: returns the received character if successful,
or RXERRORS if an error occurs
Remarks: waits for a character to be received with the
most significant bit (bit 7) set to a '1'. Characters
received with bit 7 = '0' are thrown away.
Routine waits for the TIMEOUTINTICKS period.
*/
int waitforphase(comport)
short comport;
{
short rxchar;
/*
Wait until waitforchar returns a character or error
*/
while (((rxchar = waitforchar(comport)) & 0x80) == 0)
{
/*
return if errors
*/
if (rxchar < 0)
return(RXERRORS);
}
/*
Everything is OK...return the character
*/
return(rxchar);
}
/*
serialisr - Serial Interrupt Service Routine for COM*
Prototype in: serial.h
Parameters Passed: void
Return Value: void
Remarks: Routine processes the interrupt request from the
8250 UART. There are four possible interrupts from
the UART...all are processed while in the ISR.
*/
void interrupt far serialisr_com1()
{
serial_isr(COM1);
return; /* go home via IRET */
}
void interrupt far serialisr_com2()
{
serial_isr(COM2);
return; /* go home via IRET */
}
void interrupt far serialisr_com3()
{
serial_isr(COM3);
return; /* go home via IRET */
}
void interrupt far serialisr_com4()
{
serial_isr(COM4);
return; /* go home via IRET */
}
void serial_isr(comport)
short comport;
{
short intid; /* holds the interrupt ID from the UART */
short txchar; /* Character to transmit */
short sts;
ENABLE(); /* enable higher priority interrupts to occur */
/*
Verify that the Interrupt is from the UART
...do all the possible pending interrupts while here...until
there are NO interrupts pending
*/
while (!((intid = (0x0F & INPORTB(com_base[comport] + INTERIDENT))) & 1)) /* bit 0 = 0 if interrupts pending */
{
/*
Do the Serial Interrupt in Priority order
..RXLINESTATUS, RXDATAAVAIL,TXEMPTY, MODEMSTATUS
*/
switch (intid)
{
/*
Line Status
...just increment error counter
*/
case RXLINESTATUS: /* line status changed ... check RX errors */
/*
Get the error from Linestatus
*/
if ((rxerrorvalue[comport] = (INPORTB(com_base[comport] + LINESTATUS) & RXERRORMSK)) != 0) /* clears interrupt */
rxerrors[comport] = TRUE;
break;
/*
RX Data Available
...get the byte and store it in the RX circular buffer
.....check for RX buffer overruns when storing character
*/
case RXDATAAVAIL:
/*
Get the RX data and store in the circular buffer
*/
*rxbufinptr[comport]++ = INPORTB(com_base[comport] + RXBUF);
/*
Check for RX circular buffer overrun
*/
if (rxbufinptr[comport] == rxbufoutptr[comport]) /* ck overrrun? */
rxbufoverruns[comport]=TRUE; /* increment overrun count */
/*
Check for top of buffer...adjust if necessary
*/
if (rxbufinptr[comport] == &rxbuf[comport][RXBUFSIZE]) /* at top ? */
rxbufinptr[comport] = rxbuf[comport]; /* reset */
break;
/*
TX Holding Register Empty
...transmit a character from the TX buffer if one is available
else, shut down the TX interrupt until more characters are
available
*/
case TXEMPTY:
/*
Get the Character to transmit
*/
txchar = *txbufoutptr[comport]++;
/*
check for top of buffer
...reset if at top
*/
if (txbufoutptr[comport] == &txbuf[comport][TXBUFSIZE])
txbufoutptr[comport] = txbuf[comport];
if (txbufoutptr[comport] == txbufinptr[comport]) /* no data to send */
{
/*
Disable the Tx Interrupt Enable
....don't bother until more TX chars in buffer
*/
OUTPORTB(com_base[comport] + INTERENABLE,
RXDATAAVAILINTENABLE | RXLINESTATUSINTENABLE);
OUTPORTB(com_base[comport] + INTERENABLE,
RXDATAAVAILINTENABLE | RXLINESTATUSINTENABLE);
/*
Set flag to indicate buffer empty
*/
txbufempty[comport] = TRUE;
}
/*
Send the next TX character and increment the pointer
*/
OUTPORTB(com_base[comport] + TXBUF, txchar);
break;
/*
Modem Status Change
...currently should never get here since it is never enabled,
but if we do...clear the request by reading the register
*/
case MODEMSTATUSCHG: /* CTS, DSR, RI, DCD change */
INPORTB(com_base[comport] + MODEMSTATUS); /* clear the request */
case FIFORECV:
while ((sts = INPORTB(com_base[comport] + LINESTATUS)) & DATARDY)
{
/*
Check for Errors
*/
if (sts & FIFORCVERR)
{
rxerrors[comport] = TRUE;
break;
}
/*
Get the RX data and store in the circular buffer
*/
*rxbufinptr[comport]++ = INPORTB(com_base[comport] + RXBUF);
/*
Check for RX circular buffer overrun
*/
if (rxbufinptr[comport] == rxbufoutptr[comport]) /* ck overrrun? */
rxbufoverruns[comport]=TRUE; /* increment overrun count */
/*
Check for top of buffer...adjust if necessary
*/
if (rxbufinptr[comport] == &rxbuf[comport][RXBUFSIZE]) /* at top ? */
rxbufinptr[comport] = rxbuf[comport]; /* reset */
}
break;
}
}
/*
Send End of Interrupt Command to the 8259
*/
PCPIC_OUTEOI;
}
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -