📄 isr.c
字号:
//-----------------------------------------------------------------------------
// Module: isr.c
//
// Author: Dennis De Simone
//
// Date: November 1998
//
// Description: This is the Interrupt Service Routine of a
// serial port device driver for Venturcom's
// Real Time Extentions (RTX).
//
// Change Log:
// Date Person Code Description
// ---- ------- ---- -----------
// 4/1/99 R. Lee rl001 1) changed spurious interrupt test in function
// Isr()
// 2) Added Do loop around interrupt processing
// switch to check for pending interrupt.
//
//-----------------------------------------------------------------------------
#include <windows.h>
#include <rtapi.h>
#include "..\inc\types.h"
#include "..\inc\serial.h"
#include "..\inc\serialAPI.h"
extern UCB ucbList[];
extern BYTE *pOutBuff;
COMSTATS csb[2];
VOID isr( UCB *ucb );
VOID SendNextFIFO ( UCB *ucb );
VOID EmptyFIFO ( UCB *ucb );
void RTFCNDCL COM1Isr( void *junk)
//-----------------------------------------------------------
// function: COM1Isr
//
// description: This is the stub ISR for COM1. It sets up
// the COM1 data structures and registers and
// passes control to the generic COM ISR
//------------------------------------------------------------
{
isr( &ucbList[COM1] );
}
void RTFCNDCL COM2Isr( void *junk)
//-----------------------------------------------------------
// function: COM2Isr
//
// description: This is the styb ISR for COM1. It sets up
// the COM1 data structures and registers and
// passes control to the generic COM ISR
//------------------------------------------------------------
{
isr( &ucbList[COM2] );
}
void isr( UCB *ucb )
{
BYTE tempRegister;
//-----------------------------------------------
// Validate the interrupt by first checking if
// we had one pending. If we did, then handle it
// in the appropriate case statement
//------------------------------------------------
tempRegister = RtReadPortUchar ( ucb->baseAddress + UART_IIR );
//if ( !(tempRegister && IIR_NO_INT_PENDING) ) //**rl001
if ( tempRegister & IIR_NO_INT_PENDING ) //**rl001
{
//-----------------------------------
// unsolicited interrupt - record it
// and dismiss it
//-----------------------------------
ucb->lastError = COM_PORT_UNSOLICITED_INTERRUPT;
ucb->errorCount++;
return;
}
//--------------------------------------
// **rl001
// added 'do' logic to look for more
// than one pending interrupt
//---------------------------------------
do
{
switch ( tempRegister & 0x0e )
{
case IIR_MODEM_STATUS:
break;
case IIR_XMIT_HOLDING_EMPTY:
if( ucb->statsActive )
{
csb[ucb->port].xmtInts++;
}
SendNextFIFO ( ucb );
break;
case IIR_RECEIVE_DATA_TIMEOUT:
case IIR_RECEIVED_DATA_READY:
if( ucb->statsActive )
{
csb[ucb->port].xmtInts++;
}
EmptyFIFO ( ucb );
break;
case IIR_RECEIVER_LINE_STATUS:
break;
default:
ucb->lastError = COM_PORT_UNSUPPORTED_INTERRUPT;
ucb->errorCount++;
break;
}
//--------------------------------
// **rl001
// refetch the IIR and service
// while any pending interrupt
//--------------------------------
tempRegister = RtReadPortUchar ( ucb->baseAddress + UART_IIR );
if( !(tempRegister & IIR_NO_INT_PENDING) )
{
if( ucb->statsActive )
{
csb[ucb->port].secondaryInts++;
}
}
// and service while any pending interrupt
} while ( !(tempRegister & IIR_NO_INT_PENDING ));
}
VOID SendNextFIFO ( UCB *ucb )
//-------------------------------------------------------------------------
// function: SendNextFIFO
//
// description: Called by the Transmit Buffer Empty Interrupt, this
// functions checks the Ring Buffer for more data to send
// and sets up the transmission.
//
//--------------------------------------------------------------------------
{
WORD idx;
BYTE aChar;
RINGBUFFER *rb;
WORD count;
COMSTATS *thisCsb;
thisCsb = &csb[ucb->port];
rb = ucb->outBuffer;
//printf("sendfifo. rb->count = %d\n", rb->count );
if ( rb->count == 0 )
{
ucb->transmitISRActive = FALSE;
return;
}
//--------------------------------
// we have some data to send
//-------------------------------
count = rb->count;
ucb->transmitISRActive = TRUE;
for ( idx = 0; idx < ucb->fifoSize; idx++ )
{
DISABLE_INTERRUPTS;
#ifdef ORIGINAL_DENNIS
aChar = rb->buffer[rb->nextSlotOut++];
#else
aChar = rb->buffer[rb->nextSlotOut];
rb->buffer[rb->nextSlotOut++]=0x2A;
#endif
rb->count--;
if ( rb->nextSlotOut == RING_BUFFER_SIZE )
{
rb->nextSlotOut = 0;
}
ENABLE_INTERRUPTS;
RtWritePortUchar( ucb->baseAddress + UART_XMIT_BUFFER, aChar );
if( ucb->statsActive )
{
thisCsb->bytesWritten++;
}
if ( !rb->count )
{
break;
}
}
DISABLE_INTERRUPTS;
if( !rb->count )
{
ucb->transmitISRActive = FALSE;
}
ENABLE_INTERRUPTS;
return;
}
VOID EmptyFIFO ( UCB *ucb )
//-------------------------------------------------------------------------
// function: EmptyFIFO
//
// description: This function is called as a result of a Receive
// buffer full interrupt. It transfers the FIFO contents
// into the ring buffer, updating the appropriate pointers.
//
//--------------------------------------------------------------------------
{
BYTE aChar;
BYTE controlChar;
RINGBUFFER *rb;
COMSTATS *thisCsb;
rb = ucb->inBuffer;
thisCsb = &csb[ucb->port];
do
{
aChar = RtReadPortUchar( ucb->baseAddress + UART_RCVR_BUFFER );
controlChar = RtReadPortUchar( ucb->baseAddress + UART_LSR );
rb->buffer[rb->nextSlotIn++] = aChar;
rb->count++;
if( ucb->statsActive )
{
thisCsb->bytesRead++;
}
if ( rb->count > RING_BUFFER_SIZE )
{
ucb->lastError = COM_RECEIVE_BUFFER_OVERFLOW;
ucb->errorCount++;
}
if ( rb->nextSlotIn == RING_BUFFER_SIZE )
{
rb->nextSlotIn = 0;
}
}while ( controlChar & LSR_DATA_READY );
return;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -