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

📄 serial.c

📁 ucos_ii基础上加上网络功能
💻 C
字号:
/* 
 * $Id: serial.c,v 1.5 2002/02/07 01:08:53 linfusheng Exp $
 */


#include "includes.h"
#include "serial.h"
#include "debug.h"
#include "interrupt.h"


/*
 * These are two static variables used in SERIAL.C.  pserial is
 * the pointer to the port that will be serviced by the
 * ISR.  The old break handler points to the CTRL-BREAK
 * handler that was in place before the port was opened.
 * It will be restored when the port is closed.
 */

static PORT serialport[4];
int serialport_found = 0;

/*
 * This is the interrupt service routine for the SERIAL port.
 * It sits in a loop reading the interrrupt ID register, then
 * servicing one of the four different types of interrupts.
 * Note that we shouldn't even get Modem Status and Line
 * interrupts in this implementation, but they are left
 * in for later enhancements.
 */
int OSSerial_interrupt(void *arg)
{
	unsigned char c;
	PORT *pserial = (PORT *)arg;
	switch (_inp( pserial->uart_base + IIR ) & IIR_INT_BITMASK ) {

/*
 * When a new character pseriales in and generates an
 * interrupt, it is read in.  If there is room in the input
 * buffer, it is stored, otherwise it is discarded.
 */
	case IIR_RX_ID :
		c = (unsigned char) _inp( pserial->uart_base+RXR );
		if ((pserial->in.write_index+1 ) != pserial->in.read_index)
			pserial->in.buffer[ pserial->in.write_index++ ] =  c ;
		break;

/*
 * If there are no valid interrupts left to service, an EOI
 * is written to the 8259 interrupt controller, and the
 * routine exits.
 */
	default :
		break;
	}


	return 0;
}


PORT *port_open( int address, int int_number )
{
	unsigned char temp;
	PORT *port = NULL;
	port = &serialport[serialport_found ++];
	port->in.write_index = port->in.read_index = 0;
	port->uart_base = address;
	port->irq_mask = (char) 1 << (int_number);
	port->interrupt_number = int_number;
//	SetIntVector( int_number+OSIRQ_OFFSET, OSSerialISR);
	IRQ_REQUEST(int_number,OSSerial_interrupt,port);
	
	/*
	 *The (IMR) tells the (PIC) to service an interrupt only if it
	 * is not masked (FALSE).
	 */
	// Turn on the interrupte bit 
	temp = (char) _inp( IMR_A );
	_outp( IMR_A, ~port->irq_mask & temp );

	return( port );
}


void port_set( PORT *port,
               long speed,
               char parity,
               int data,
               int stopbits )
{
	unsigned char lcr_out = 0;
	unsigned char mcr_out = 0;
	unsigned char low_divisor = 0 ;
	unsigned char high_divisor = 0;
/*
 * First disable all interrupts from the port.  I also read
 * RBR just in case their is a char sitting there ready to
 * generate an interupt.
 */
	_outp( port->uart_base + IER, 0 );
	_inp( port->uart_base );
/*
 * Writing the baud rate means first enabling the divisor
 * latch registers, then writing the 16 bit divisor int
 * two steps, then disabling the divisor latch so the other
 * registers can be accessed normally.
 */
	low_divisor = (char) (115200L / speed ) & 0xff;
	high_divisor = (char) ((115200L /  speed ) >> 8);
	_outp( port->uart_base + LCR, LCR_DLAB );
	_outp( port->uart_base + DLL, low_divisor );
	_outp( port->uart_base + DLH, high_divisor );
	_outp( port->uart_base + LCR, 0 );

	/* PARITY AND ODD/EVEN PARITY */
	switch(parity) {
	case 'O':
		lcr_out |= LCR_PARITY;
		break;
	case 'E':
		lcr_out |= LCR_PARITY;
		lcr_out |= LCR_PARITY_EVEN;
		break;
	default:
		break;
	}

	/* STOP BITS */	
	if (stopbits == 2 )
		lcr_out |= LCR_2_STOP;
	else 
		;	/* 1 stop bits */


	/* DATA BITS */
	switch(data) {
	case 5:
		lcr_out |= LCR_5_DATA_BITS;
		break;
	case 6:
		lcr_out |= LCR_6_DATA_BITS;
		break;
	case 7:
		lcr_out |= LCR_7_DATA_BITS;
		break;
	case 8:
		lcr_out |= LCR_8_DATA_BITS;
		break;
	default:
		break;
	}

	_outp( port->uart_base + LCR, lcr_out );

/*
 * I turn on RTS and DTR, as well as OUT2.  OUT2 is needed
 * to allow interrupts on PC pserialpatible cards.
 */
	mcr_out = MCR_RTS | MCR_DTR | MCR_OUT2 ;
	_outp( port->uart_base + MCR, mcr_out );

/*
 * Finally, restart receiver interrupts, and exit.
 */
	_outp( port->uart_base + IER, IER_RX_DATA);

}
/*
 * This routine is used to send a single character out to
 * the UART.  If there is room in the output buffer, the
 * character is inserted in the buffer.  Then the routine
 * checks to see if Transmit interrupts are presently
 * enabled for this UART.  If they aren't, they are turned
 * on so the ISR will see this new character.
 */
int port_putc( unsigned char c, PORT *port )
{
	unsigned long timeout = 0x0000ffff;
/*
	_outp( port->uart_base+MCR,MCR_DTR | MCR_RTS | MCR_OUT2);
	while((_inp(port->uart_base + MSR) & MSR_CTS) == 0)
		if(!(--timeout))
				return -1;
	timeout = 0x0000ffff;

*/
	while((_inp(port->uart_base + LSR) & LSR_XMTRDY) == 0)
		if(!(--timeout))
				return -1;

	_outp( port->uart_base+TXR,c);
	return( c );
}
/*
 * This routine checks to see if there is a character
 * available in the input buffer for the specified port.
 * If there is, it is pulled out and returned to the
 * caller.
 */
int port_getc(PORT *port)
{
	if ( port->in.write_index == port->in.read_index )
		return( -1 );
	else
		return( port->in.buffer[ port->in.read_index++ ] );
}


////////////////////////////////////////////////////////


void OSport_init(void)
{
	PORT *pserial;
	pserial = port_open(SERIAL1_UART,SERIAL1_INTERRUPT);
	if(pserial == NULL) {
		return;
	}
	port_set(pserial,9600,0,8,1);

	pserial = port_open(SERIAL2_UART,SERIAL2_INTERRUPT);
	if(pserial == NULL) {
		return;
	}
	port_set(pserial,9600,0,8,1);





}


int OSport_getc(int portnum,unsigned char flag)
{
	char  ch;

	PORT *pserial = &serialport[portnum];
	ch = port_getc(pserial);
	if(ch < 0)
		return -1;

	if(ch == '\r')
		OSport_putc(portnum,'\n');

	switch(flag){
	case SERIAL_NOECHO:	//没有回显
		break;
	case SERIAL_ECHOP:	//明文回显
		OSport_putc(portnum,ch);	
		break;
	case SERIAL_ECHOC:	//密文回显
		OSport_putc(portnum,'*');
		break;
	}
	return ch;
}


int OSport_gets(int portnum, unsigned char *buf,int max_get)
{
	int len = 0;
	while (1) {
		char  c = OSport_getc(portnum, SERIAL_NOECHO); /* We only receive the asicc char */
		if(c <= 0 ) 
			continue;
		switch(c) {
		case 0x08:
			if(len > 0) {
				buf[--len] = '\0';
				OSport_putc(portnum,0x08);
				OSport_putc(portnum,' ');
				OSport_putc(portnum,0x08);
			}
			break;
		case '\n':
		case '\r':
			buf[len] = '\0';
			OSport_putc(portnum,c);
			return len;
		default:
			buf[len++] = c;
			OSport_putc(portnum,c);
			break;
		}
		if(len == max_get)
			break;
	}
	return len;
}
int OSport_putc(int portnum, unsigned char ch)
{
	PORT *pserial = &serialport[portnum];
	return port_putc(ch,pserial);
}

int OSport_puts(int portnum,unsigned char *buf,int len)
{
	int i;
	for( i = 0 ; i < len ;i  ++)
		OSport_putc(portnum, buf[i]);
	return len;
}
/* 
 * $Log: serial.c,v $
 * Revision 1.5  2002/02/07 01:08:53  linfusheng
 * update
 *
 * Revision 1.4  2002/02/06 07:28:51  linfusheng
 * update
 *
 * Revision 1.3  2002/01/28 01:13:52  linfusheng
 * update
 *
 * Revision 1.2  2002/01/28 00:46:25  linfusheng
 * update
 *
 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -