URL
https://opencores.org/ocsvn/or1k_old/or1k_old/trunk
Subversion Repositories or1k_old
Compare Revisions
- This comparison shows the changes necessary to convert path
/
- from Rev 410 to Rev 411
- ↔ Reverse comparison
Rev 410 → Rev 411
/trunk/or1ksim/testbench/acv_uart.c
19,6 → 19,7
#define UART_MCR (UART_ADDR + 4) |
#define UART_LSR (UART_ADDR + 5) |
#define UART_MSR (UART_ADDR + 6) |
#define UART_SCR (UART_ADDR + 7) |
|
#define UART_DLL (UART_ADDR + 0) |
#define UART_DLH (UART_ADDR + 1) |
48,7 → 49,7
#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));} |
printf ("LSR7 (0x%02x) ERR @ %i\n", x, __LINE__); ASSERT(!(x & LSR_ERR) && ((x & 0x60) != 0x40));} |
#define MARK() printf ("Passed line %i\n", __LINE__) |
|
#ifndef __LINE__ |
169,6 → 170,7
ASSERT(getreg (UART_LSR) == 0x60); //5 |
ASSERT(getreg (UART_MSR) == 0x00); //6 |
#endif |
ASSERT(getreg (UART_SCR) == 0x00); //7 |
|
setreg(UART_LCR, LCR_DIVL); //enable latches |
ASSERT(getreg (UART_DLL) == 0x00); //0 |
246,6 → 248,20
} |
ASSERT (!(getreg (UART_LSR) & 0x1f)); |
} |
MARK (); |
|
{ /* SCR Test :))) */ |
int i; |
setreg (UART_SCR, 0); |
ASSERT (getreg (UART_SCR) == 0); |
setreg (UART_SCR, 0xff); |
ASSERT (getreg (UART_SCR) == 0xff); |
for (i = 0; i < 16; i++) { |
unsigned char tmp = 0xdead << i; |
setreg (UART_SCR, tmp); |
ASSERT (getreg (UART_SCR) == tmp); |
} |
} |
MARK(); |
/* Other registers will be tested later, if they function correctly, |
since we cannot test them now, without destroying anything. */ |
256,7 → 272,7
void send_recv_test () |
{ |
char *s; |
printf ("send_recv_test: "); |
printf ("send_recv_test\n"); |
/* Init */ |
MARK(); |
|
312,7 → 328,7
{ |
unsigned x; |
char *s; |
printf ("break_test: "); |
printf ("break_test\n"); |
|
MARK(); |
/* Send a break */ |
401,7 → 417,7
void different_modes_test () |
{ |
int speed, parity, length; |
printf ("different modes test"); |
printf ("different modes test\n"); |
init_8n1(); |
|
/* Init */ |
443,11 → 459,17
MARK(); |
|
/* Restore normal mode */ |
send_char ('T'); |
while (getreg (UART_LSR) != 0x60); /* Wait for THR to be empty */ |
setreg (UART_LCR, LCR_DIVL); |
setreg (UART_DLH, 2 >> 8); |
setreg (UART_DLL, 2 & 0xff); |
setreg (UART_LCR, 0x03); /* 8N1 @ 2 */ |
MARK(); |
|
send_char ('T'); |
while (getreg (UART_LSR) != 0x60); /* Wait for THR to be empty */ |
MARK(); |
printf ("OK\n"); |
} |
|
456,13 → 478,13
void interrupt_test () |
{ |
int i; |
printf ("interrupt_test"); |
printf ("interrupt_test\n"); |
/* 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_LCR, 0x03); /* 8N1 @ 6 */ |
|
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 */ |
587,6 → 609,7
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 */ |
MARK(); |
recv_char (0); |
MARK(); |
|
598,9 → 621,9
MARK(); |
/* Wait for acknowledge */ |
int_rbr = '$'; |
while (!int_cnt); /* Wait for DR */ |
while (!int_cnt); /* Wait for timeout */ |
ASSERT (--int_cnt == 0); |
ASSERT (int_iir == 0xc4); |
ASSERT (int_iir == 0xcc); |
ASSERT (int_lsr == 0x61); |
MARK(); |
|
624,15 → 647,115
MARK(); |
|
send_char ('T'); |
while (!int_cnt); /* Wait for THR to be empty */ |
ASSERT (--int_cnt == 0); |
ASSERT (int_iir == 0xc2); |
ASSERT ((int_lsr & 0xbe) == 0x20); |
MARK(); |
|
setreg (UART_IER, 0x00); /* Disable interrupts */ |
ASSERT (int_cnt == 0); /* no interrupts should be pending */ |
NO_ERROR (); |
|
/* TODO: check if trigger is set up on full fifo */ |
while (getreg (UART_LSR) != 0x60); /* wait till we sent everynthing and then change mode */ |
setreg (UART_LCR, LCR_DIVL); |
setreg (UART_DLH, 2 >> 8); /* Set relatively slow speed, so we can hanlde interrupts properly */ |
setreg (UART_DLL, 2 & 0xff); |
setreg (UART_LCR, 0x03); /* 8N1 @ 2 */ |
send_char ('T'); |
|
MARK (); |
printf ("OK\n"); |
} |
|
/* Test if all control bits are set correctly. Lot of this was already tested |
elsewhere and tests are not duplicated. */ |
|
void control_register_test () |
{ |
/* RBR already tested in send_recv_test() */ |
/* THR already tested in send_recv_test() */ |
/* IER already tested in interrupt_test() */ |
/* IIR already tested in interrupt_test() */ |
/* FCR0 - uart 16450 specific, not tested */ |
|
/* FCR1 - reset rx FIFO */ |
send_char ('*'); |
NO_ERROR (); |
while (!(getreg (UART_LSR) & 0x01)); /* Wait for data ready */ |
setreg (UART_FCR, 2); /* Clears rx fifo */ |
ASSERT (getreg (UART_LSR) == 0x60); /* nothing happening */ |
send_char ('!'); |
recv_char ('!'); |
MARK (); |
|
/* FCR2 - reset tx FIFO */ |
send_char ('1'); |
send_char ('2'); |
setreg (UART_FCR, 4); /* Should clear '2' from fifo, but '1' should be sent OK */ |
ASSERT (getreg (UART_LSR) == 0x00); /* we should still be sending '1' */ |
NO_ERROR(); |
send_char ('*'); |
recv_char ('*'); |
MARK (); |
|
/* LCR already tested in different_modes_test () */ |
/* TODO: MSR */ |
/* LSR already tested in different_modes_test () and interrupt_test() */ |
/* SCR already tested in register_test () */ |
|
MARK (); |
printf ("OK\n"); |
} |
|
/* Tests parity error and frane error behaviour */ |
|
void line_error_test () |
{ |
printf ("line_error_test\n"); |
|
/* Test framing error if we change speed */ |
setreg (UART_LCR, LCR_DIVL); |
setreg (UART_DLH, 2 >> 8); |
setreg (UART_DLL, 2 & 0xff); |
setreg (UART_LCR, 0x03); /* 8N1 @ 2 */ |
MARK(); |
|
send_char ('c'); |
ASSERT (int_cnt == 0); |
setreg (UART_IER, 0x04); /* Enable interrupts: line status */ |
while (!int_cnt); /* Wait for THR to be empty */ |
ASSERT (--int_cnt == 0); |
ASSERT (int_iir == 0xc6); |
ASSERT (int_lsr == 0xe9); /* Framing error and FIFO error */ |
getreg (UART_RBR); /* Ignore the data */ |
MARK (); |
recv_char ('b'); |
MARK (); |
|
#if COMPLETE |
/* Test framing error if we change stop bits */ |
send_char ('*'); |
while (getreg (UART_LSR)); /* wait till we sent everynthing and then change mode */ |
setreg (UART_LCR, 0x07); /* 8N2 */ |
send_char ('*'); |
MARK (); |
|
ASSERT (int_cnt == 0); |
setreg (UART_IER, 0x04); /* Enable interrupts: line status */ |
while (!int_cnt); /* Wait for THR to be empty */ |
ASSERT (--int_cnt == 0); |
ASSERT (int_iir == 0xc6); |
ASSERT (int_lsr == 0xe9); /* Framing error and FIFO error */ |
getreg (UART_RBR); /* Ignore the data */ |
recv_char ('b'); |
MARK(); |
#endif |
|
MARK (); |
printf ("OK\n"); |
} |
|
int main () |
{ |
/* Use our low priority interrupt handler */ |
640,23 → 763,21
|
/* Enable interrupts */ |
mtspr (SPR_SR, mfspr(SPR_SR) | SPR_SR_EXR | SPR_SR_EIR); |
mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << UART_INT_LINE)); |
mtspr (SPR_PICMR, mfspr(SPR_PICMR) | (0x00000001L << UART_INT_LINE)); |
|
// register_test (); |
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 (); |
// interrupt_test (); |
// control_register_test (); |
line_error_test (); |
|
/* loopback_test (); |
modem_test (); |
line_error_test (); |
speed_error_test (); |
frame_error_test (); |
modem_error_test ();*/ |
recv_char ('@'); |
printf ("ALL TESTS PASSED\n"); |
return 0; |
} |
/trunk/or1ksim/peripheral/16450.c
99,11 → 99,7
} else |
uarts[chipsel].regs.txbuf[uarts[chipsel].istat.txbuf_head] = value; |
|
if (uarts[chipsel].istat.txbuf_full < uarts[chipsel].fifo_len) |
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE; |
else |
uarts[chipsel].regs.lsr |= UART_LSR_TXBUFE; |
uarts[chipsel].regs.lsr &= ~UART_LSR_TXSERE; |
uarts[chipsel].regs.lsr &= ~(UART_LSR_TXSERE | UART_LSR_TXBUFE); |
|
uarts[chipsel].istat.thre_int = 0; |
break; |
116,10 → 112,12
if (value & UART_FCR_RTXFI) { |
uarts[chipsel].istat.txbuf_head = uarts[chipsel].istat.txbuf_tail = 0; |
uarts[chipsel].istat.txbuf_full = 0; |
uarts[chipsel].regs.lsr &= ~UART_LSR_TXBUFE; |
} |
if (value & UART_FCR_RRXFI) { |
uarts[chipsel].istat.rxbuf_head = uarts[chipsel].istat.rxbuf_tail = 0; |
uarts[chipsel].istat.rxbuf_full = 0; |
uarts[chipsel].regs.lsr &= ~UART_LSR_RDRDY; |
} |
break; |
case UART_IER: |
314,6 → 312,22
uarts[uart].istat.txser_clks = 0; |
} |
|
/* Adds a character to the FIFO */ |
|
void uart_add_char (int uart, int ch) |
{ |
if (uarts[uart].istat.rxbuf_full + 1 > uarts[uart].fifo_len) |
uarts[uart].regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR; |
else { |
debug(4, "add %02x\n", ch); |
uarts[uart].regs.rxbuf[uarts[uart].istat.rxbuf_head] = ch; |
uarts[uart].istat.rxbuf_head = (uarts[uart].istat.rxbuf_head + 1) % uarts[uart].fifo_len; |
uarts[uart].istat.rxbuf_full++; |
} |
uarts[uart].regs.lsr |= UART_LSR_RDRDY; |
uarts[uart].istat.timeout_count = 0; |
} |
|
/* Reset. It initializes all registers of all UART devices to zero values, |
(re)opens all RX/TX file streams and places devices in memory address |
space. */ |
387,7 → 401,6
if (uarts[i].vapi.next_break_cnt >= 0) |
if (--uarts[i].vapi.next_break_cnt < 0) { |
if (!(uarts[i].vapi.cur_break = uarts[i].vapi.next_break)) |
uarts[i].regs.lsr &= ~UART_LSR_BREAK; |
uarts[i].istat.break_set = 0; |
} |
|
434,23 → 447,14
uarts[i].vapi.cur_break_cnt++; |
if (uarts[i].vapi.cur_break_cnt > UART_BREAK_COUNT * uarts[i].vapi.char_clks) { |
if (!uarts[i].istat.break_set) { |
unsigned lsr; |
uarts[i].istat.break_set = 1; |
uarts[i].regs.lsr |= UART_LSR_BREAK | UART_LSR_FRAME | UART_LSR_RXERR | UART_LSR_RDRDY; |
if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].regs.lsr |= UART_LSR_PARITY; |
lsr = UART_LSR_BREAK | UART_LSR_FRAME | UART_LSR_RXERR | UART_LSR_RDRDY; |
if (uarts[i].regs.lcr & UART_LCR_PARITY) lsr |= UART_LSR_PARITY; |
printf ("[%x]\n", uarts[i].regs.lsr); |
uarts[i].istat.rxser_full = 0; |
uarts[i].istat.rxser_clks = 0; |
|
if (uarts[i].istat.rxbuf_full + 1 > uarts[i].fifo_len) |
uarts[i].regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR; |
else { |
uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_head] = 0; |
debug(4, "add %02x\n", 0); |
uarts[i].istat.rxbuf_head = (uarts[i].istat.rxbuf_head + 1) % uarts[i].fifo_len; |
uarts[i].istat.rxbuf_full++; |
} |
uarts[i].regs.lsr |= UART_LSR_RDRDY; |
uarts[i].istat.timeout_count = 0; |
uart_add_char (i, lsr << 8); |
} else |
uarts[i].vapi.cur_break_cnt = 0; |
} |
461,21 → 465,12
} else { |
if (uarts[i].istat.rxser_full) { |
if (uarts[i].char_clks <= uarts[i].istat.rxser_clks++) { |
uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1); |
/* Set unused character bits to zero and allow lsr register in fifo */ |
uarts[i].iregs.rxser &= ((1 << ((uarts[i].regs.lcr & 3) + 5)) - 1) | 0xff00; |
debug(4, "Receiving 0x%02x'%c' via UART%d...\n", uarts[i].iregs.rxser, uarts[i].iregs.rxser, i); |
uarts[i].istat.rxser_full = 0; |
uarts[i].istat.rxser_clks = 0; |
|
if (uarts[i].istat.rxbuf_full + 1 > uarts[i].fifo_len) |
uarts[i].regs.lsr |= UART_LSR_OVRRUN | UART_LSR_RXERR; |
else { |
debug(4, "add %02x\n", uarts[i].iregs.rxser); |
uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_head] = uarts[i].iregs.rxser; |
uarts[i].istat.rxbuf_head = (uarts[i].istat.rxbuf_head + 1) % uarts[i].fifo_len; |
uarts[i].istat.rxbuf_full++; |
} |
uarts[i].regs.lsr |= UART_LSR_RDRDY; |
uarts[i].istat.timeout_count = 0; |
uart_add_char (i, uarts[i].iregs.rxser); |
} |
} |
} |
503,6 → 498,7
case 0x00: |
uarts[i].vapi.lcr = (data >> 8) & 0xff; |
/* Put data into rx fifo */ |
uarts[i].iregs.rxser = data & 0xff; |
uarts[i].vapi.char_clks = char_clks (uarts[i].vapi.dll, uarts[i].vapi.dlh, uarts[i].vapi.lcr); |
if ((uarts[i].vapi.lcr & ~UART_LCR_SBC) != (uarts[i].regs.lcr & ~UART_LCR_SBC) |
|| uarts[i].vapi.char_clks != uarts[i].char_clks |
510,10 → 506,9
debug (3, "WARNING: unmatched VAPI (%02x) and uart (%02x) modes.\n", |
uarts[i].vapi.lcr & ~UART_LCR_SBC, uarts[i].regs.lcr & ~UART_LCR_SBC); |
/* Set error bits */ |
uarts[i].regs.lsr |= UART_LSR_FRAME | UART_LSR_RXERR; |
if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].regs.lsr |= UART_LSR_PARITY; |
uarts[i].iregs.rxser |= (UART_LSR_FRAME | UART_LSR_RXERR) << 8; |
if (uarts[i].regs.lcr & UART_LCR_PARITY) uarts[i].iregs.rxser |= UART_LSR_PARITY << 8; |
} |
uarts[i].iregs.rxser = data & 0xff; |
uarts[i].istat.rxser_full = 1; |
received = 1; |
break; |
565,6 → 560,13
|
if (uarts[i].regs.lsr & UART_LSR_RDRDY) |
uarts[i].istat.timeout_count++; |
|
/* Update LSR error bits from the ones from rx FIFO */ |
if (uarts[i].istat.rxbuf_full) { |
uarts[i].regs.lsr |= uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] >> 8; |
/* we must delete the lsr status, so that we can clear it from lsr */ |
uarts[i].regs.rxbuf[uarts[i].istat.rxbuf_tail] &= 0xff; |
} |
|
/* Interrupt detection in proper priority order. */ |
uarts[i].regs.iir = UART_IIR_NO_INT; |
/trunk/or1ksim/peripheral/16450.h
33,8 → 33,8
|
struct dev_16450 { |
struct { |
unsigned char txbuf[UART_MAX_FIFO_LEN]; |
unsigned char rxbuf[UART_MAX_FIFO_LEN]; |
unsigned txbuf[UART_MAX_FIFO_LEN]; |
unsigned rxbuf[UART_MAX_FIFO_LEN]; |
unsigned char dll; |
unsigned char dlh; |
unsigned char ier; |
171,7 → 171,7
*/ |
#define UART_FCR_FIE 0x01 /* FIFO enable */ |
#define UART_FCR_RRXFI 0x02 /* Reset rx FIFO */ |
#define UART_FCR_RTXFI 0x02 /* Reset tx FIFO */ |
#define UART_FCR_RTXFI 0x04 /* Reset tx FIFO */ |
#define UART_FIFO_TRIGGER(x) /* Trigger values for indexes 0..3 */\ |
((x)==0?1\ |
:(x)==1?4\ |