📄 cycduart.c
字号:
//=============================================================================//// cycduart.c - Cyclone UART Diagnostics////=============================================================================//####COPYRIGHTBEGIN####// // ------------------------------------------- // The contents of this file are subject to the Red Hat eCos Public License // Version 1.1 (the "License"); you may not use this file except in // compliance with the License. You may obtain a copy of the License at // http://www.redhat.com/ // // Software distributed under the License is distributed on an "AS IS" // basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the // License for the specific language governing rights and limitations under // the License. // // The Original Code is eCos - Embedded Configurable Operating System, // released September 30, 1998. // // The Initial Developer of the Original Code is Red Hat. // Portions created by Red Hat are // Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc. // All Rights Reserved. // ------------------------------------------- // //####COPYRIGHTEND####//=============================================================================//#####DESCRIPTIONBEGIN####//// Author(s): Scott Coulter, Jeff Frazier, Eric Breeden// Contributors:// Date: 2001-01-25// Purpose: // Description: ////####DESCRIPTIONEND####////===========================================================================*/#include "cycduart.h"#include "iq80310.h"#define DFLTLOOPERMS 500extern int printf(char*,...);extern long hexIn();int break_flag = 0;unsigned long baud_rate = 0;static int duart_already_init = FALSE;static unsigned int uart_unit = DFLTPORT;static int looperms;static int calc_looperms(void);void serial_init(void);int inreg(int);void outreg(int, unsigned char);void serial_set(unsigned long);void serial_loopback(int);int serial_getc();void serial_putc(int);int serial_write(int, const unsigned char *, int);int serial_read(int, unsigned char *, int, int);extern int enable_external_interrupt (int int_id);extern int disable_external_interrupt (int int_id);extern int isr_connect(int int_num, void (*handler)(int), int arg);extern int isr_disconnect(int int_num);void duart_initialize(){ if (duart_already_init == FALSE) { /* Calculate the time constant for timeouts on serial_read. */ if ((looperms = calc_looperms()) <= 0) looperms = DFLTLOOPERMS; } /* Initialize the serial port and set the baud rate. * The baud rate is set here for sanity only; the autobaud * mechanism will change it as required when the host connects. */ serial_init(); serial_set(baud_rate?baud_rate:9600L); duart_already_init = TRUE;} /* Establish the loop/time constant to be used in the timing loop in * serial_read. This is done by putting the UART into loopback mode. * After transmitting a character at 300 baud, we wait for the character * to be received. Then divide the number of loops waited by the number * of milliseconds it takes to transmit 10 bits at 300 baud. * If your transmitter doesn't have a loopback mode, this value can be * calculated using a timer or some other facility, or an approximate * constant can be used. */#define TESTBAUD 300L#define NBYTES 10#define BITS_PER_BYTE 10 /* 1 start bit, 8 data bits, 1 stop bit */#define TOTAL_MS (NBYTES*BITS_PER_BYTE*1000/TESTBAUD)static intcalc_looperms(void){ int i, count, c; int totalloops = 0; serial_init(); serial_set(TESTBAUD); /* set 300 baud */ serial_loopback(1); /* enable loop back mode */ for (i=0; i < NBYTES; i++) { count = 1; serial_putc(0xaa); /* xmit character */ /* * The timing loop is the same as the loops in serial_read. * Any changes to the loops in serial_read should be reflected * here. */ do { c = serial_getc(); } while (c < 0 && count++ > 0); totalloops += count; } serial_loopback(0); return(totalloops/TOTAL_MS);}/* * Initialize the device driver. */void serial_init(void){ /* If the serial port has been init'd before, there may be data in it */ /* Wait for the transmit FIFO to empty out before resetting anything */ if (duart_already_init == TRUE) { while (!(inreg(LSR) & LSR_TSRE)); } /* * Configure active port, (uart_unit already set.) * * Set 8 bits, 1 stop bit, no parity. * * LCR<7> 0 divisor latch access bit * LCR<6> 0 break control (1=send break) * LCR<5> 0 stick parity (0=space, 1=mark) * LCR<4> 0 parity even (0=odd, 1=even) * LCR<3> 0 parity enable (1=enabled) * LCR<2> 0 # stop bits (0=1, 1=1.5) * LCR<1:0> 11 bits per character(00=5, 01=6, 10=7, 11=8) */ outreg(LCR, 0x3); /* Assert DTR and RTS to prevent hardware handshake problems with serial terminals, etc. which can be connected to the serial port */ outreg(MCR, MCR_DTR | MCR_RTS); outreg(FCR, FIFO_ENABLE); /* Enable the FIFO */ outreg(IER, INT_ENABLE); /* Enable appropriate interrupts */}/* Read a received character if one is available. Return -1 otherwise. */int serial_getc(){ if (inreg(LSR) & LSR_DR) { return inreg(DataIn); } return -1;}/* Transmit a character. */void serial_putc(int c){ while ((inreg(LSR) & LSR_THRE) == 0) ; outreg(DataOut, c);}/* * Set the baud rate. */void serial_set(unsigned long baud){ unsigned char sav_lcr; if(baud == 0) baud = 9600L; /* * Enable access to the divisor latches by setting DLAB in LCR. * */ sav_lcr = inreg(LCR); outreg(LCR, LCR_DLAB | sav_lcr); /* * Set divisor latches. */ outreg(BaudLsb, XTAL/(16*baud)); outreg(BaudMsb, (XTAL/(16*baud)) >> 8); /* * Restore line control register */ outreg(LCR, sav_lcr);}/* * This routine is used by calc_looperms to put the UART in loopback mode. */void serial_loopback(int flag){ if (flag) outreg(MCR, inreg(MCR) | MCR_LOOP); /* enable loop back mode */ else outreg(MCR, inreg(MCR) & ~MCR_LOOP); /* disable loop back mode */}/* * These routines are used to read and write to the registers of the * 16552. The delay routine guarantees the required recovery time between * cycles to the 16552. * DUART is the base address of the 16552. * DUART_DELTA gives the spacing between adjacent registers of the 16552. * For example, if A0,A1,A2 of the 16552 are connected to A2,A3,A4 of * the processor, DUART_DELTA must be 4. */int inreg(int reg){ int val; val = *((volatile unsigned char *)TERMINAL + (uart_unit * SCALE + reg)); return val;}void outreg(int reg, unsigned char val){ *((volatile unsigned char *)TERMINAL + (uart_unit * SCALE + reg)) = val;}/****************************************************************//* The following functions are all part of the Breeze UART test *//****************************************************************/ static volatile int uart_int;/************************************************//* BUS_TEST *//* This routine performs a walking ones test *//* on the given uart chip to test it's bus *//* interface. It writes to the scratchpad reg. *//* then reads it back. During *//* this test all 8 data lines from the chip *//* get written with both 1 and 0. *//************************************************/static int bus_test (){ unsigned char out, in; int bitpos; volatile int junk; junk = (int) &junk; /* Don't let compiler optimize or "registerize" */ outreg(SCR,0); /* Clear scratchpad register */ for (bitpos = 0; bitpos < 8; bitpos++) { out = 1 << bitpos; outreg(SCR,out); /* Write data to scratchpad reg. */ junk = ~0; /* Force data lines high */ in = inreg(SCR); /* Read data */ printf ("%02X ", in); /* make sure it's what we wrote */ if (in != out) return (0); } outreg(SCR,0); /* Clear scratchpad register */ printf ("\n"); return (1);}/************************************************//* DISABLE_UART_INTS *//* This routine disables uart interrupts *//************************************************/static void disable_uart_ints (){ outreg(IER,0); /* Make the uart shut up */}/************************************************//* UART_ISR *//* This routine responds to uart interrupts *//* must return 1 to indicate that an interrupt *//* was serviced. *//************************************************/static void uart_isr (int unused){ unsigned char iir; disable_uart_ints (); uart_int = 1; /* read the IIR to clear the interrupt */ iir = inreg(IIR); return ;}/************************************************//* INIT_UART *//* This routine initializes the 16550 interrupt *//* and uart registers and initializes the uart *//* count. *//************************************************/static void init_uart (){ outreg(IER,0x02); /* Enable Tx Empty interrupt - should generate an interrupt since Tx is empty to begin with */}/****************************************//* UART DIAGNOSTIC TEST *//****************************************/void uart_test (){volatile int loop;int looplim;int int_id;unsigned long* reg_ptr;int i, baud;/*11/01/00 */char info[] = {"Move Console Cable back to Connector J9 and hit <CR> to exit test"};int index; looplim = 400000; /* perform tests on both UARTs */ for (uart_unit = 0; uart_unit < 2; uart_unit++) { if (uart_unit == 0) int_id = UART1_INT_ID; else int_id = UART2_INT_ID; if (!bus_test ()) printf ("\nERROR: bus_test for UART Unit %d failed\n", uart_unit); else { printf ("\nbus_test for UART Unit %d passed\n", uart_unit); uart_int = 0; isr_connect (int_id, uart_isr, 0); if (enable_external_interrupt(int_id) != OK) printf("ERROR enabling UART UINT %d interrupt!\n", uart_unit); init_uart (); loop = 0; while (!uart_int && (loop < looplim)) loop++; if (!uart_int) printf ("UART Unit %d INTERRUPT test failed %X\n", uart_unit, loop) ; else printf ("UART Unit %d INTERRUPT test passed\n", uart_unit); serial_putc(' '); } /* disable UART interrupt */ if (disable_external_interrupt(int_id)!= OK) printf("ERROR disabling UART UNIT %d interrupt!\n", uart_unit); /* disconnect test handler */ isr_disconnect (int_id); }/* 11/01/00 *//* #if 0 */ /* writing to port 2 doesnt work yet... */#if 1 /* writing to port 2 doesnt work yet... *//* printf ("\nMove the Console Cable to the 2nd Serial Port,\n"); printf ("Connector J10,\n"); printf ("and Hit <CR> when the cable is connected.\n\n"); printf ("After alphabet prints, move Console Cable back to 1st Serial Port,\n"); printf ("Connector J9,\n"); printf ("and hit <CR> to exit test\n");*/ /* 10/30/00 */ uart_unit = DFLTPORT; /* test J10, the PCI-700 GDB port */ printf ("\nMove the Console Cable to the 2nd Serial Port, Connector J10,\n"); printf ("and Hit <CR> when the cable is connected.\n"); printf ("The alphabet should print on the screen.\n\n");/* 11/01/00 *//* printf ("After alphabet prints, move Console Cable back to 1st Serial Port,\n"); printf ("Connector J9,\n"); printf ("and hit <CR> to exit test\n");*/ baud = 115200; serial_init(); serial_set(baud?baud:115200L);/* while (serial_getc() == -1); */ while (serial_getc() != 0x0d); /* wait for a carriage return character to start test *//* while (1) { for ( i = 65; i <= 90; i++ ) serial_putc(i); }*/ for ( i = 65; i <= 90; i++ ) /* transmit the alphabet */ serial_putc(i); serial_putc(10); /* transmit a New Line */ serial_putc(13); /* transmit a Carriage Return */ serial_putc(10); /* transmit a New Line */ for (index=0; info[index] != '\0'; index++) /* transmit some instructions to the user */ { serial_putc(info[index]); } /* point at default port before returning *//* uart_unit = DFLTPORT; */ (void)hexIn(); #endif printf ("\n\nUART tests done.\n"); printf ("Press return to continue.\n"); (void) hexIn();}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -