⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 isr.c

📁 完整的RTX串口驱动程序 供大家分享 谢谢
💻 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 + -