📄 uart.c
字号:
/* * This software is Copyright (C) 1998 by T.sqware - all rights limited * It is provided in to the public domain "as is", can be freely modified * as far as this copyight notice is kept unchanged, but does not imply * an endorsement by T.sqware of the product in which it is included. * * $Id: uart.c,v 1.11 2002/07/16 22:30:11 joel Exp $ */#include <stdio.h>#include <bsp.h>#include <irq.h>#include <uart.h>#include <rtems/libio.h>#include <rtems/termiostypes.h>#include <termios.h>#include <assert.h>/* * Basic 16552 driver */struct uart_data{ int ioMode; int hwFlow; unsigned int ier; unsigned long baud; unsigned long databits; unsigned long parity; unsigned long stopbits;};static struct uart_data uart_data[2];/* * Macros to read/write register of uart, if configuration is * different just rewrite these macros */ static inline unsigned charuread(int uart, unsigned int reg){ register unsigned char val; if (uart == 0) { inport_byte(COM1_BASE_IO+reg, val); } else { inport_byte(COM2_BASE_IO+reg, val); } return val;}static inline void uwrite(int uart, int reg, unsigned int val){ if (uart == 0) { outport_byte(COM1_BASE_IO+reg, val); } else { outport_byte(COM2_BASE_IO+reg, val); }}#ifdef UARTDEBUG static voiduartError(int uart){ unsigned char uartStatus, dummy; uartStatus = uread(uart, LSR); dummy = uread(uart, RBR); if (uartStatus & OE) printk("********* Over run Error **********\n"); if (uartStatus & PE) printk("********* Parity Error **********\n"); if (uartStatus & FE) printk("********* Framing Error **********\n"); if (uartStatus & BI) printk("********* Parity Error **********\n"); if (uartStatus & ERFIFO) printk("********* Error receive Fifo **********\n");}#elseinline void uartError(int uart){ unsigned char uartStatus; uartStatus = uread(uart, LSR); uartStatus = uread(uart, RBR);}#endif/* * Uart initialization, it is hardcoded to 8 bit, no parity, * one stop bit, FIFO, things to be changed * are baud rate and nad hw flow control, * and longest rx fifo setting */voidBSP_uart_init( int uart, unsigned long baud, unsigned long databits, unsigned long parity, unsigned long stopbits, int hwFlow){ unsigned char tmp; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); switch(baud) { case 50: case 75: case 110: case 134: case 300: case 600: case 1200: case 2400: case 9600: case 19200: case 38400: case 57600: case 115200: break; default: assert(0); return; } /* Set DLAB bit to 1 */ uwrite(uart, LCR, DLAB); /* Set baud rate */ uwrite(uart, DLL, (BSPBaseBaud/baud) & 0xff); uwrite(uart, DLM, ((BSPBaseBaud/baud) >> 8) & 0xff); /* 8-bit, no parity , 1 stop */ uwrite(uart, LCR, databits | parity | stopbits); /* Set DTR, RTS and OUT2 high */ uwrite(uart, MCR, DTR | RTS | OUT_2); /* Enable FIFO */ uwrite(uart, FCR, FIFO_EN | XMIT_RESET | RCV_RESET | RECEIVE_FIFO_TRIGGER12); /* Disable Interrupts */ uwrite(uart, IER, 0); /* Read status to clear them */ tmp = uread(uart, LSR); tmp = uread(uart, RBR); tmp = uread(uart, MSR); /* Remember state */ uart_data[uart].baud = baud; uart_data[uart].databits = databits; uart_data[uart].parity = parity; uart_data[uart].stopbits = stopbits; uart_data[uart].hwFlow = hwFlow; return;}/* * Set baud */voidBSP_uart_set_baud( int uart, unsigned long baud){ /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); BSP_uart_set_attributes( uart, baud, uart_data[uart].databits, uart_data[uart].parity, uart_data[uart].stopbits );}/* * Set all attributes */voidBSP_uart_set_attributes( int uart, unsigned long baud, unsigned long databits, unsigned long parity, unsigned long stopbits){ unsigned char mcr, ier; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); /* * This function may be called whenever TERMIOS parameters * are changed, so we have to make sure that baud change is * indeed required */ if( (baud == uart_data[uart].baud) && (databits == uart_data[uart].databits) && (parity == uart_data[uart].parity) && (stopbits == uart_data[uart].stopbits) ) { return; } mcr = uread(uart, MCR); ier = uread(uart, IER); BSP_uart_init(uart, baud, databits, parity, stopbits, uart_data[uart].hwFlow); uwrite(uart, MCR, mcr); uwrite(uart, IER, ier); return;}/* * Enable/disable interrupts */void BSP_uart_intr_ctrl(int uart, int cmd){ int iStatus = (int)INTERRUPT_DISABLE; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); switch(cmd) { case BSP_UART_INTR_CTRL_ENABLE: iStatus |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE | TRANSMIT_ENABLE); if ( uart_data[uart].hwFlow ) { iStatus |= MODEM_ENABLE; } break; case BSP_UART_INTR_CTRL_TERMIOS: iStatus |= (RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); if ( uart_data[uart].hwFlow ) { iStatus |= MODEM_ENABLE; } break; case BSP_UART_INTR_CTRL_GDB: iStatus |= RECEIVE_ENABLE; break; } uart_data[uart].ier = iStatus; uwrite(uart, IER, iStatus); return;}voidBSP_uart_throttle(int uart){ unsigned int mcr; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); if(!uart_data[uart].hwFlow) { /* Should not happen */ assert(0); return; } mcr = uread (uart, MCR); /* RTS down */ mcr &= ~RTS; uwrite(uart, MCR, mcr); return;}voidBSP_uart_unthrottle(int uart){ unsigned int mcr; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); if(!uart_data[uart].hwFlow) { /* Should not happen */ assert(0); return; } mcr = uread (uart, MCR); /* RTS up */ mcr |= RTS; uwrite(uart, MCR, mcr); return;}/* * Status function, -1 if error * detected, 0 if no received chars available, * 1 if received char available, 2 if break * is detected, it will eat break and error * chars. It ignores overruns - we cannot do * anything about - it execpt count statistics * and we are not counting it. */int BSP_uart_polled_status(int uart){ unsigned char val; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); val = uread(uart, LSR); if(val & BI) { /* BREAK found, eat character */ uread(uart, RBR); return BSP_UART_STATUS_BREAK; } if((val & (DR | OE | FE)) == 1) { /* No error, character present */ return BSP_UART_STATUS_CHAR; } if((val & (DR | OE | FE)) == 0) { /* Nothing */ return BSP_UART_STATUS_NOCHAR; } /* * Framing or parity error * eat character */ uread(uart, RBR); return BSP_UART_STATUS_ERROR;}/* * Polled mode write function */void BSP_uart_polled_write(int uart, int val){ unsigned char val1; /* Sanity check */ assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); for(;;) { if((val1=uread(uart, LSR)) & THRE) { break; } } if(uart_data[uart].hwFlow) { for(;;) { if(uread(uart, MSR) & CTS) { break; } } } uwrite(uart, THR, val & 0xff); /* * Wait for character to be transmitted. * This ensures that printk and printf play nicely together * when using the same serial port. * Yes, there's a performance hit here, but if we're doing * polled writes to a serial port we're probably not that * interested in efficiency anyway..... */ for(;;) { if((val1=uread(uart, LSR)) & THRE) { break; } } return;}voidBSP_output_char_via_serial(int val){ BSP_uart_polled_write(BSPConsolePort, val); if (val == '\n') BSP_uart_polled_write(BSPConsolePort,'\r');}/* * Polled mode read function */int BSP_uart_polled_read(int uart){ unsigned char val; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); for(;;) { if(uread(uart, LSR) & DR) { break; } } val = uread(uart, RBR); return (int)(val & 0xff);}unsigned BSP_poll_char_via_serial(){ return BSP_uart_polled_read(BSPConsolePort);}/* ================ Termios support =================*/static volatile int termios_stopped_com1 = 0;static volatile int termios_tx_active_com1 = 0;static void* termios_ttyp_com1 = NULL;static char termios_tx_hold_com1 = 0;static volatile char termios_tx_hold_valid_com1 = 0;static volatile int termios_stopped_com2 = 0;static volatile int termios_tx_active_com2 = 0;static void* termios_ttyp_com2 = NULL;static char termios_tx_hold_com2 = 0;static volatile char termios_tx_hold_valid_com2 = 0;static void ( *driver_input_handler_com1 )( void *, char *, int ) = 0;static void ( *driver_input_handler_com2 )( void *, char *, int ) = 0;/* * This routine sets the handler to handle the characters received * from the serial port. */void uart_set_driver_handler( int port, void ( *handler )( void *, char *, int ) ){ switch( port ) { case BSP_UART_COM1: driver_input_handler_com1 = handler; break; case BSP_UART_COM2: driver_input_handler_com2 = handler; break; }}/* * Set channel parameters */voidBSP_uart_termios_set(int uart, void *ttyp){ struct rtems_termios_tty *p = (struct rtems_termios_tty *)ttyp; unsigned char val; assert(uart == BSP_UART_COM1 || uart == BSP_UART_COM2); if(uart == BSP_UART_COM1) { uart_data[uart].ioMode = p->device.outputUsesInterrupts; if(uart_data[uart].hwFlow) { val = uread(uart, MSR); termios_stopped_com1 = (val & CTS) ? 0 : 1; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -