📄 serialapi.c
字号:
//---------------------------------------------------------------------------
// Module: serialAPI
//
// Author: D.P. De Simone
//
// Date: December 1998
//
// Description: This module contains the API interface to RTX
// serial communications and the UART initialization
// code.
//
// Change Log:
// Date Person Code Description
// ---- ------- ---- -----------
// 4/1/99 R. Lee rl001 Coded explicit return in gunction
// RtConfigComPort
//---------------------------------------------------------------------------
#include <windows.h>
#include <stdio.h>
#include <rtapi.h>
#include "..\inc\types.h"
#include "..\inc\serial.h"
#include "..\inc\serialAPI.h"
#include "data.h" //initialized data
//------------------------------
// global data
//------------------------------
RINGBUFFER receiveRingBuffer[COM_MAX_PORTS]; //allocate these statically
RINGBUFFER transmitRingBuffer[COM_MAX_PORTS]; //allocate these statically
LARGE_INTEGER timerPeroid; //alocate a time period
HANDLE hTimer; //a timer handle
//------------------------
// prototypes
//------------------------
extern void RTFCNDCL COM1Isr( void *junk);
extern void RTFCNDCL COM2Isr( void *junk);
extern COMSTATS csb[];
extern UCB ucbList[];
WORD InitializePort( UCB *ucb );
VOID SendNextFIFO ( UCB *ucb );
VOID DumpUcb( char *s, UCB *ucb );
VOID ReadPic( void );
WORD RtOpenComPort ( BYTE port, WORD baudRate, BYTE wordSize,
BYTE stopBits, BYTE parity )
//-----------------------------------------------------------------------------
// function: RtOpenComPort
//
// description: RtOpenComPort intializes the com port by:
// - validating the input parameters
// - updating and initalizing the COM port UCB
// - calling RTX to allow access to I/O data space
// - initalizing the COM port
// - initializing the COM port interrupt vector
//
// inputs: port - Com port identifier { COM1 | COM2 }
// baudeRate - baud rate, default 9600
// wordSize - size of a transfer entity { 5 | 6 | 7 | 8 }
// bits. Default = 8
// stopBits - default = 2
// parity - { PARITY_NONE | PARITY_ODD | PARITY_EVEN |
// PARITY_HIGH | PARITY_LOW }
//
//------------------------------------------------------------------------------
{
UCB *thisUcb;
WORD return_code;
WORD isrArg;
if ( (port != COM1) && (port != COM2 ))
{
return ( COM_INVALID_DEVICE );
}
//----------------------------------------
// its a valid port, now map the UCB and
// transfer the parameters, using the UCB
// defaults for null parameters
//----------------------------------------
thisUcb = (UCB *) &ucbList[port];
//DumpUcb( "Driver:Open",thisUcb );
if ( thisUcb->state ) //is this port already active
{
return ( COM_DEVICE_OPEN ); //--yes, cannot open
}
if ( parity )
{
thisUcb->parity = parity; //tranfer the parity
}
if ( stopBits )
{
thisUcb->stopBits = stopBits; //transfer number of stop bits
}
if ( baudRate )
{
thisUcb->baudRate = (BYTE)baudRate; //transfer baud rate
}
if ( wordSize )
{
thisUcb->wordSize = wordSize; //transfer word size
}
//-------------------------------------------
// now we start setting up the hardware. But
// first we need access to the I/O space
//-------------------------------------------
if ( !RtEnablePortIo ( thisUcb->baseAddress, COM_IO_RANGE ) )
{
return ( COM_PORT_IO_FAILURE );
}
//---------------------------------------------------------
// the com port is configured, now initialize the hardware
// setup the interrupt vector and the ring buffers
// note:
// for now we'll use statically alllocated ring buffers
//----------------------------------------------------------
thisUcb->inBuffer = (RINGBUFFER *)&receiveRingBuffer[port];
thisUcb->outBuffer = (RINGBUFFER *)&transmitRingBuffer[port];
//----------------------------------------------------------
// now setup the interrupt vector. later, we'll create
// a table of ISRs, but for now,we'll do it the easy way.
//----------------------------------------------------------
if ( port == COM1 )
{
thisUcb->isrHandle = RtAttachInterruptVector
(
NULL,0,COM1Isr,(void *)&isrArg,
RT_PRIORITY_MAX, Isa,0,
thisUcb->irq, thisUcb->irq
);
}
else
{
thisUcb->isrHandle = RtAttachInterruptVector
(
NULL,0,COM2Isr,(void *)&isrArg,
RT_PRIORITY_MAX, Isa,0,
thisUcb->irq, thisUcb->irq
);
}
if ( !thisUcb->isrHandle )
{
printf("Connect to int failed. error =%d\n",GetLastError());
return( COM_CONNECT_INTERRUPT_FAILED );
}
if ( (return_code = InitializePort( thisUcb )) )
{
return ( return_code );
}
thisUcb->state = COM_STATE_OPEN;
return( COM_NORMAL );
}
WORD RtReadComPort ( BYTE port, BYTE *buffer, WORD bytesToRead, WORD *bytesRead )
//-----------------------------------------------------------------------------------
// function: RtReadComPort
//
// description: Read bytes from COM port for a maximum of 'bytesToRead.' This
// function actually read all byted currently in the Ring Buffer,
// up to the maximum specified
//
// inputs:
// port - the COM port to read from
// Buffer - buffer for read characters
// bytesToRead - maximum number of bytes to read
//
// outputs:
// bytesRead - actual number of bytes read
// return code - COM_NORMAL or error code
//-------------------------------------------------------------------------------------
{
register idx;
BYTE *tBuff;
UCB *ucb;
RINGBUFFER *rb;
WORD count = 0;
//-----------------------------------------
// map the ucb and validate parameters
//-----------------------------------------
ucb = &ucbList[port];
if ( !ucb->state )
{
return (COM_PORT_NOT_OPEN );
}
tBuff = buffer;
*bytesRead = 0;
rb = ucb->inBuffer;
if ( !rb->count ) //any characters??
{
return( COM_NORMAL );
}
if( ucb->statsActive )
{
csb[port].readRequests++;
}
//----------------------------------
// the ring buffer is a critical
// section...block interrupts while
// accessing it
//-----------------------------------
DISABLE_INTERRUPTS;
for ( idx = 0; idx < bytesToRead; idx++ )
{
*tBuff++ = rb->buffer[rb->nextSlotOut++];
count++;
if ( rb->nextSlotOut == RING_BUFFER_SIZE )
{
rb->nextSlotOut = 0;
}
if ( !(--rb->count) ) //no more characters in buffer
{
break;
}
}
ENABLE_INTERRUPTS;
*bytesRead = count;
return( COM_NORMAL );
}
WORD RtWriteComPort ( BYTE port, BYTE *buffer, WORD bytesToWrite, WORD *bytesWritten )
//-----------------------------------------------------------------------------------
// function: RtReadComPort
//
// description: Write bytes to COM port for a maximum of 'bytesToWrite.'
//
// inputs:
// port - the COM port to write to
// Buffer - buffer of characters to write
// bytesToWrite - count of bytes to write
//
// outputs:
// bytesWritten - actual number of bytes written
// return code - COM_NORMAL or error code
//-------------------------------------------------------------------------------------
{
register idx;
BYTE *tBuff;
UCB *ucb;
RINGBUFFER *rb;
WORD count = 0;
//-----------------------------------------
// map the ucb and validate parameters
//-----------------------------------------
ucb = &ucbList[port];
if ( !ucb->state )
{
return (COM_PORT_NOT_OPEN );
}
tBuff = buffer;
*bytesWritten = 0;
rb = ucb->outBuffer;
if ( (RING_BUFFER_SIZE - rb->count) < bytesToWrite )
{
ucb->lastError = COM_TRANSMIT_BUFFER_OVERFLOW;
ucb->errorCount++;
return ( COM_TRANSMIT_BUFFER_OVERFLOW );
}
if( ucb->statsActive )
{
csb[port].writeRequests++;
}
//---------------------------------------------------
// we have space in the ring buffer, lets pack it
//---------------------------------------------------
DISABLE_INTERRUPTS;
for ( idx = 0; idx < bytesToWrite; idx++ )
{
rb->buffer[rb->nextSlotIn++] = *tBuff++;
rb->count++;
count++;
if ( rb->nextSlotIn == RING_BUFFER_SIZE )
{
rb->nextSlotIn = 0;
}
}
ENABLE_INTERRUPTS;
//----------------------------------------------------
// we've packed the ring buffer.
// if the transmit side is idle, send the fisrt FIFO
// and the ISR will send all subsequent FIFOs
//-----------------------------------------------------
if ( !ucb->transmitISRActive )
{
#ifdef ORIGINAL_DENNIS
SendNextFIFO ( ucb );
#else
//kick the TRH interrupt by disabling all, and re-enabling
//see write.c in the NT driver
RtWritePortUchar(ucb->baseAddress+UART_IER,0);
RtWritePortUchar(ucb->baseAddress+UART_IER,IER_RECEIVE_DATA|IER_TRANSMIT_DATA);
#endif
}
*bytesWritten = count;
return( COM_NORMAL );
}
WORD RtGetComStatus ( BYTE port, CSB * csb )
//---------------------------------------------------------------------
// function: RtGetComStatus
//
// description: Returns a filled in COM Status Block
//
//----------------------------------------------------------------------
{
UCB *ucb;
ucb = &ucbList[port];
if ( !ucb->state )
{
return (COM_PORT_NOT_OPEN );
}
csb->state = ucb->state;
csb->lastError = ucb->lastError;
csb->errorCount = ucb->errorCount;
return (COM_NORMAL );
}
WORD RtGetComBufferCount ( BYTE port )
//----------------------------------------------------------------------
// function: RtGetCOMBufferCount
//
// description: Returns the number of character in the imput buffer.
//
//-----------------------------------------------------------------------
{
UCB *ucb;
RINGBUFFER *rb;
ucb = &ucbList[port];
if ( !ucb->state )
{
return (COM_PORT_NOT_OPEN );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -