URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [tags/] [tn_m001/] [or1ksim/] [testbench/] [acv_uart.c] - Rev 409
Go to most recent revision | Compare with Previous | Blame | View Log
/* UART test using ACV */ #include "spr_defs.h" #include "support.h" /* use this macro to comment out nonworking parts */ #define COMPLETE 0 /* Whether to do test in more detail */ #define DETAILED 0 #define UART_ADDR (0x9c000000) #define UART_RBR (UART_ADDR + 0) #define UART_THR (UART_ADDR + 0) #define UART_IER (UART_ADDR + 1) #define UART_IIR (UART_ADDR + 2) #define UART_FCR (UART_ADDR + 2) #define UART_LCR (UART_ADDR + 3) #define UART_MCR (UART_ADDR + 4) #define UART_LSR (UART_ADDR + 5) #define UART_MSR (UART_ADDR + 6) #define UART_DLL (UART_ADDR + 0) #define UART_DLH (UART_ADDR + 1) #define LCR_DIVL (0x80) #define LCR_BREAK (0x40) #define LCR_STICK (0x20) #define LCR_EVENP (0x10) #define LCR_PAREN (0x08) #define LCR_NSTOP (0x04) #define LCR_NBITS (0x03) #define LSR_DR (0x01) #define LSR_OE (0x02) #define LSR_PE (0x04) #define LSR_FE (0x08) #define LSR_BREAK (0x10) #define LSR_TXFE (0x20) #define LSR_TXE (0x40) #define LSR_ERR (0x80) #define UART_INT_LINE 4 /* To which interrupt is uart connected */ /* fails if x is false */ #define ASSERT(x) ((x)?1: fail (__FUNCTION__, __LINE__)) /* Waits a few cycles that uart can prepare its data */ #define WAIT() {asm ("l.nop");asm ("l.nop");asm ("l.nop");asm ("l.nop");} /* fails if there is an error */ #define NO_ERROR() { unsigned x = getreg (UART_LSR); if ((x & (LSR_BREAK|LSR_FE|LSR_PE|LSR_OE)) && !(x & LSR_ERR)) \ printf ("LSR7 (0x%02x) ERR @ %i\n", x, __LINE__); ASSERT(!(x & LSR_ERR));} #define MARK() printf ("Passed line %i\n", __LINE__) #ifndef __LINE__ #define __LINE__ 0 #endif void fail (char *func, int line) { #ifndef __FUNCTION__ #define __FUNCTION__ "?" #endif printf ("Test failed in %s:%i\n", func, line); report(0xeeeeeeee); exit (1); } inline void setreg (unsigned long addr, unsigned char value) { *((volatile unsigned char *)addr) = value; } inline unsigned long getreg (unsigned long addr) { return *((volatile unsigned char *)addr); } static volatile int int_cnt = 0; static volatile unsigned int_iir = 0; static volatile unsigned int_lsr = 0; static int int_rbr = 0; void interrupt_handler () { unsigned x; printf ("Int\n"); report(0xdeaddead); report(int_iir = getreg (UART_IIR)); report(int_lsr = getreg (UART_LSR)); int_cnt++; ASSERT (int_iir != 1); switch (int_iir & 0xf) { case 0x6: printf ("Receiver LS int.\n"); break; case 0x4: printf ("Received Data available. Expecting %02x, received %02x\n", int_rbr, x = getreg(UART_RBR)); ASSERT (x == int_rbr); report (x); report (int_rbr); break; case 0xc: printf ("Character timeout. Expecting %02x, received %02x\n", int_rbr, x = getreg(UART_RBR)); ASSERT (x == int_rbr); report (x); report (int_rbr); break; case 0x2: printf ("THR empty.\n"); break; case 0x0: printf ("Modem Status.\n"); break; default: printf ("Invalid iir @ %i\n", __LINE__); exit (1); } mtspr(SPR_PICSR, 0); } /* Receives a char and checks for errors */ void recv_char (int ch) { unsigned x; char r; report (ch); /* Wait for rx fifo to be */ while (!((x = getreg (UART_LSR)) & LSR_DR)); if ((x & (LSR_BREAK|LSR_FE|LSR_PE|LSR_OE)) && !(x & LSR_ERR)) printf ("LSR7 (0x%02x) ERR @ recv_char\n", x); ASSERT(!(x & LSR_ERR)); printf ("expected %02x, read %02x\n", ch, r = getreg (UART_RBR)); ASSERT (r == ch); /* compare character */ } /* Sends a char and checks for errors */ void send_char (int ch) { report (ch); while (!(getreg (UART_LSR) & LSR_TXFE)); NO_ERROR(); setreg (UART_THR, ch); /* send character */ NO_ERROR(); } void init_8n1 () { setreg (UART_IER, 0x00); /* disable interrupts */ WAIT(); ASSERT(getreg (UART_IIR) == 0xc1); /* nothing should be happening */ setreg (UART_FCR, 0x07); /* clear RX and TX FIFOs */ setreg (UART_LCR, LCR_DIVL); setreg (UART_DLH, 2 >> 8); setreg (UART_DLL, 2 & 0xff); setreg (UART_LCR, 0x03); /* 8N1 @ 2 */ ASSERT(getreg (UART_LCR) == 0x03); ASSERT (!(getreg (UART_LSR) & 0x1f)); } /* Test reset values and r/w properties of some registers */ void register_test () { printf ("register test\n"); MARK(); { /* test reset values */ ASSERT(getreg (UART_RBR) == 0x00); //0 ASSERT(getreg (UART_IER) == 0x00); //1 ASSERT(getreg (UART_IIR) == 0xc1); //2 ASSERT(getreg (UART_LCR) == 0x03); //3 ASSERT(getreg (UART_MCR) == 0x00); //4 #if COMPLETE ASSERT(getreg (UART_LSR) == 0x60); //5 ASSERT(getreg (UART_MSR) == 0x00); //6 #endif setreg(UART_LCR, LCR_DIVL); //enable latches ASSERT(getreg (UART_DLL) == 0x00); //0 ASSERT(getreg (UART_DLH) == 0x00); //1 setreg(UART_LCR, 0x00); //disable latches } #if COMPLETE MARK(); { /* test if status registers are read only */ unsigned long tmp; int i; tmp = getreg (UART_LSR); setreg (UART_LSR, ~tmp); ASSERT(getreg (UART_LSR) == tmp); for (i = 0; i < 9; i++) { setreg (UART_LSR, 1 << i); ASSERT(getreg (UART_LSR) == tmp); } tmp = getreg (UART_MSR); setreg (UART_MSR, ~tmp); ASSERT(getreg (UART_MSR) == tmp); for (i = 0; i < 9; i++) { setreg (UART_MSR, 1 << i); ASSERT(getreg (UART_MSR) == tmp); } } #endif MARK(); { /* test whether MCR is write only, be careful not to set the loopback bit */ #if COMPLETE ASSERT(getreg (UART_MCR) == 0x00); setreg (UART_MCR, 0x45); ASSERT(getreg (UART_MCR) == 0x00); setreg (UART_MCR, 0xaa); ASSERT(getreg (UART_MCR) == 0x00); #endif } ASSERT (!(getreg (UART_LSR) & 0x1f)); MARK(); { /* Test if Divisor latch byte holds the data */ int i; setreg(UART_LCR, LCR_DIVL); //enable latches ASSERT(getreg (UART_LCR) == LCR_DIVL); for (i = 0; i < 16; i++) { unsigned short tmp = 0xdead << i; setreg (UART_DLH, tmp >> 8); setreg (UART_DLL, tmp & 0xff); ASSERT(getreg (UART_DLL) == (tmp & 0xff)); //0 ASSERT(getreg (UART_DLH) == (tmp >> 8)); //1 } ASSERT (!(getreg (UART_LSR) & 0x1f)); for (i = 0; i < 16; i++) { unsigned short tmp = 0xdead << i; setreg (UART_DLL, tmp >> 8); setreg (UART_DLH, tmp & 0xff); ASSERT(getreg (UART_DLL) == (tmp >> 8)); //1 ASSERT(getreg (UART_DLH) == (tmp & 0xff)); //0 } setreg(UART_LCR, 0x00); //disable latches ASSERT(getreg (UART_LCR) == 0x00); ASSERT (!(getreg (UART_LSR) & 0x1f)); } MARK(); { /* Test LCR, if it holds our data */ int i; for (i = 0; i < 6; i++) { unsigned short tmp = (0xde << i) & 0x3f; setreg (UART_LCR, tmp); ASSERT(getreg (UART_LCR) == tmp); } ASSERT (!(getreg (UART_LSR) & 0x1f)); } MARK(); /* Other registers will be tested later, if they function correctly, since we cannot test them now, without destroying anything. */ } /* Initializes uart and sends a few bytes to VAPI. It is then activated and send something back. */ void send_recv_test () { char *s; printf ("send_recv_test: "); /* Init */ MARK(); //printf ("basic\n"); ASSERT (!(getreg (UART_LSR) & LSR_DR)); MARK(); /* Send a string */ s = "send_"; while (*s) { /* Wait for tx fifo to be empty */ send_char (*s); report((unsigned long)*s); s++; } ASSERT (!(getreg (UART_LSR) & LSR_DR)); s = "test_"; while (*s) { /* Wait for tx fifo and tx to be empty */ while (!(getreg (UART_LSR) & LSR_TXE)); NO_ERROR(); setreg (UART_THR, *s); /* send character */ NO_ERROR(); s++; } ASSERT (!(getreg (UART_LSR) & LSR_DR)); MARK(); /* Send characters with delay inbetween */ s = "is_running"; while (*s) { int i; send_char (*s); // igor for (i = 0; i < 1600; i++) /* wait at least ten chars before sending next one */ for (i = 0; i < 16; i++) /* wait at few chars before sending next one */ asm volatile ("l.nop"); s++; } send_char (0); /* send terminate char */ MARK(); /* Receives and compares the string */ s = "recv"; while (*s) recv_char (*s++); MARK(); printf ("OK\n"); } /* sends break in both directions */ void break_test () { unsigned x; char *s; printf ("break_test: "); MARK(); /* Send a break */ NO_ERROR(); MARK(); setreg (UART_LCR, 0x03 | LCR_BREAK); /* 8N1 */ MARK(); send_char ('b'); /* make sure it is recognised as a break */ send_char ('b'); send_char ('b'); send_char ('b'); MARK(); recv_char ('*'); setreg (UART_LCR, 0x03); /* deleting break bit, 8N1 */ MARK(); /* Receive a break */ send_char ('!'); MARK(); while (!((x = getreg (UART_LSR)) & LSR_DR)); /* we should receive zero character with broken frame and break bit should be set */ printf("[%x]\n", (LSR_DR | LSR_FE | LSR_BREAK | LSR_ERR | LSR_TXFE | LSR_TXE)); ASSERT (x == (LSR_DR | LSR_FE | LSR_BREAK | LSR_ERR | LSR_TXFE | LSR_TXE)); ASSERT (getreg (UART_RBR) == 0); MARK(); /* Send a # to release break */ setreg (UART_THR, '#'); while (!(getreg (UART_LSR) & LSR_DR)); NO_ERROR(); /* BREAK bit should be cleared now */ ASSERT (getreg (UART_RBR) == '$'); MARK(); /* Break while sending characters */ s = "ns"; while (*s) send_char (*s++); ASSERT (!(getreg (UART_LSR) & LSR_DR)); while (!(getreg (UART_LSR) & LSR_TXE)); /* Wait till we send everything */ /* this should break the * char, so it should not be received */ setreg (UART_THR, '*'); setreg (UART_LCR, 0x3 | LCR_BREAK); MARK(); /* Drop the break, when we get acknowledge */ recv_char ('?'); setreg (UART_LCR, 0x3); NO_ERROR(); MARK(); /* Receive a break */ send_char ('#'); while (!((x = getreg (UART_LSR)) & LSR_DR)); /* we should receive zero character with broken frame and break bit should not be set, because we cleared it */ printf("[%x:%x]\n", x, (LSR_DR | LSR_FE | LSR_BREAK |LSR_ERR | LSR_TXFE | LSR_TXE)); ASSERT (x == (LSR_DR | LSR_FE | LSR_BREAK |LSR_ERR | LSR_TXFE | LSR_TXE)); ASSERT (getreg (UART_RBR) == 0); MARK(); send_char ('?'); MARK(); while (!(getreg (UART_LSR) & LSR_DR)); recv_char ('!'); printf ("OK\n"); } /* Tries to send data in different modes in both directions */ /* Utility function, that tests current configuration */ void test_mode (int nbits) { unsigned mask = (1 << nbits) - 1; send_char (0x55); #if DETAILED send_char (0x55); recv_char (0x55 & mask); #endif recv_char (0x55 & mask); send_char ('a'); // 0x61 #if DETAILED send_char ('a'); // 0x61 recv_char ('a' & mask); #endif recv_char ('a' & mask); } void different_modes_test () { int speed, parity, length; printf ("different modes test"); init_8n1(); /* Init */ MARK(); ASSERT(getreg (UART_IIR) == 0xc1); /* nothing should be happening */ MARK(); /* Test different speeds */ for (speed = 1; speed < 5; speed++) { setreg (UART_LCR, LCR_DIVL); setreg (UART_DLH, speed >> 8); setreg (UART_DLL, speed & 0xff); setreg (UART_LCR, 0x03); /* 8N1 @ 10 => 160 instructions for one cycle */ test_mode (8); MARK(); } MARK(); setreg (UART_LCR, LCR_DIVL); setreg (UART_DLH, 1 >> 8); setreg (UART_DLL, 1 & 0xff); MARK(); /* Test all parity modes with different char lengths */ for (parity = 0; parity < 8; parity++) for (length = 0; length < 4; length++) { setreg (UART_LCR, length | (0 << 2) | (parity << 3)); test_mode (5 + length); MARK(); } MARK(); /* Test configuration, if we have >1 stop bits */ for (length = 0; length < 4; length++) { setreg (UART_LCR, length | (1 << 2) | (0 << 3)); test_mode (5 + length); MARK(); } MARK(); /* Restore normal mode */ setreg (UART_LCR, LCR_DIVL); setreg (UART_DLH, 2 >> 8); setreg (UART_DLL, 2 & 0xff); setreg (UART_LCR, 0x03); /* 8N1 @ 2 */ MARK(); printf ("OK\n"); } /* Test various FIFO levels, break and framing error interrupt, etc */ void interrupt_test () { int i; printf ("interrupt_test"); /* Configure UART for interrupt mode */ ASSERT(getreg (UART_IIR) == 0xc1); /* nothing should be happening */ setreg (UART_LCR, LCR_DIVL); setreg (UART_DLH, 6 >> 8); /* Set relatively slow speed, so we can hanlde interrupts properly */ setreg (UART_DLL, 6 & 0xff); setreg (UART_LCR, 0x03); /* 8N1 @ 2 */ setreg (UART_IER, 0x07); /* Enable interrupts: line status, THR empty, data ready */ setreg (UART_FCR, 0x01); /* Set trigger level = 1 char, fifo should not be reset */ ASSERT (int_cnt == 0); /* We should not have got any interrupts before this test */ MARK(); /* I am configured - start interrupt test */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); int_rbr = '0'; while (!int_cnt); /* Wait for DR */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc4); ASSERT (int_lsr == 0x61); ASSERT (int_cnt == 0); /* no interrupts should be pending */ MARK(); setreg (UART_FCR, 0x41); /* Set trigger level = 4 chars, fifo should not be reset */ /* Everything ok here, send me 4 more */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); int_rbr = '1'; while (!int_cnt); /* Wait for DR */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc4); ASSERT (int_lsr == 0x61); MARK(); setreg (UART_FCR, 0x81); /* Set trigger level = 8 chars, fifo should not be reset */ /* Everything ok here, send me 5 more */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); int_rbr = '2'; while (!int_cnt); /* Wait for DR */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc4); ASSERT (int_lsr == 0x61); MARK(); setreg (UART_FCR, 0xc1); /* Set trigger level = 14 chars, fifo should not be reset */ /* Everything ok here, send me 7 more */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); int_rbr = '3'; while (!int_cnt); /* Wait for DR */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc4); ASSERT (int_lsr == 0x61); MARK(); /* Everything ok here, send me 4 more - fifo should be full OE should occur */ setreg (UART_IER, 0x06); /* Enable interrupts: line status, THR empty */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); while (!int_cnt); /* Wait for OE */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc6); ASSERT (int_lsr == 0xe3); /* OE flag should be set */ ASSERT (getreg (UART_LSR) == 0x61); /* LSR should be cleared by previous read */ ASSERT (getreg (UART_IIR) == 0xc1); /* No interrupts should be pending */ MARK(); /* Check if we got everything */ ASSERT (int_cnt == 0); /* no interrupts should be pending */ for (i = 0; i < 3; i++) { recv_char ("456"[i]); /* WARNING: read should not cause interrupt even if we step over trigger */ MARK (); } /* It is now safe to enable data ready interrupt */ setreg (UART_IER, 0x07); /* Enable interrupts: line status, THR empty, data ready */ /* Check if we got everything */ for (i = 0; i < 13; i++) { recv_char ("789abcdefghij"[i]); /* WARNING: read should not cause interrupt even if we step over trigger */ MARK (); } ASSERT (int_cnt == 0); /* no interrupts should be pending */ ASSERT (getreg (UART_LSR) == 0x60); /* FIFO should be empty */ getreg (UART_RBR); /* check for FIFO counter overflow - fifo must still be empty */ ASSERT (getreg (UART_LSR) == 0x60); /* FIFO should be empty */ /* check for break interrupt */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); while (!int_cnt); /* Wait for break interrupt */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc6); ASSERT (int_lsr == 0xf9); /* BE flag should be set */ ASSERT (getreg (UART_LSR) == 0x61); /* BE flag should be cleared by previous read */ recv_char (0); MARK(); send_char ('B'); /* Release break */ while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); /* Wait for acknowledge */ int_rbr = '$'; while (!int_cnt); /* Wait for DR */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc4); ASSERT (int_lsr == 0x61); MARK(); /* TODO: Check for parity error */ /* TODO: Check for frame error */ /* Check for timeout */ send_char ('I'); while (!int_cnt); /* Wait for THR to be empty */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xc2); ASSERT ((int_lsr & 0xbe) == 0x20); MARK(); int_rbr = 'T'; while (!int_cnt); /* Wait for timeout */ ASSERT (--int_cnt == 0); ASSERT (int_iir == 0xcc); /* timeout interrupt occured */ ASSERT (int_lsr == 0x61); /* DR flag should be set */ ASSERT (getreg (UART_LSR) == 0x60); /* DR flag should be cleared - timeout occurred */ MARK(); send_char ('T'); setreg (UART_IER, 0x00); /* Disable interrupts */ ASSERT (int_cnt == 0); /* no interrupts should be pending */ /* TODO: check if trigger is set up on full fifo */ MARK (); } int main () { /* Use our low priority interrupt handler */ excpt_lpint = (unsigned long)interrupt_handler; /* Enable interrupts */ mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_EXR | SPR_SR_EIR); mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << UART_INT_LINE)); // register_test (); init_8n1 (); // send_recv_test (); // break_test (); // different_modes_test (); interrupt_test (); /*control_register_test (); loopback_send_rcv_test (); fifo_test (); loopback_test (); modem_test (); line_error_test (); speed_error_test (); frame_error_test (); modem_error_test ();*/ printf ("ALL TESTS PASSED\n"); return 0; }
Go to most recent revision | Compare with Previous | Blame | View Log