4 #define DLAB_SET() bset((void*)&_uart_regs[UART_LINE_CTL], LC_DLAB);
5 #define DLAB_CLR() bclr((void*)&_uart_regs[UART_LINE_CTL], LC_DLAB);
7 char tx_buffer[TX_BUFFER_LEN+2];
8 volatile char rx_buffer[RX_BUFFER_LEN+1];
9 volatile u8 rx_buf_pos; /* -ve denotes not sending/receiving */
10 volatile char msg_buf[RX_BUFFER_LEN+1]; /* rx_buffer copied here without \n */
11 volatile u8 rx_queue_state, tx_queue_state;
12 volatile bool packet_is_bad;
14 /* If we were controlling a modem we'd probably do a lot more such as toggling
15 * the control lines (DTR,RTS etc). But given this is a very stripped down
16 * version talking over merely TX/RX, we don't care about these control lines.
18 * This code speak 8 data bits, No parity, 1 Stop bit, at the baud rate specified
19 * in comm.h (should be 9600 bps)
24 * Because in our daughterboard circuit we are not connecting the reset line
25 * to the CPU's, we can not make any assumptions about the state of the UART.
26 * Hence we initialize all registers and flush the FIFOs
30 lock(); /* disable interrupts for this */
33 divisor = UART_SPEED / BAUD_RATE;
35 _uart_regs[UART_DLAB_MSB] = (u8)(divisor >> 8);
36 _uart_regs[UART_DLAB_LSB] = (u8)(divisor & 0xff);
39 /* set RX, TX & LS interrupts */
40 _uart_regs[UART_INT_ENABLE] =
41 IE_RECEIVER_READY | IE_TRANSMITTER_READY | IE_LINE_STATUS_CHANGE;
43 /* Enable the FIFO and empty them */
44 _uart_regs[UART_FIFO_CTL] =
45 FIFO_ENABLE | FIFO_RX_CLEAR | FIFO_TX_CLEAR | FIFO_LVL_1;
47 /* 8 data bits, 1 stop bit, no parity. */
48 _uart_regs[UART_LINE_CTL] = LC_8BITS;
50 /* modem controls: clear them all */
51 _uart_regs[UART_MODEM_CTL] = 0;
61 /*******************************************************************************
62 * Interrupt handler for UART.
64 * This actually consists of several functions, rolled into one.
67 extern inline void rx_int() {
68 char c = _uart_regs[UART_RX_BUFFER];
69 if (rx_queue_state == 2) return; /* buffers full. too bad */
71 if (rx_buf_pos < RX_BUFFER_LEN) {
72 rx_buffer[rx_buf_pos] = c;
78 /* just forget this packet ever happened */
80 rx_buffer[rx_buf_pos] = 0;
81 switch (rx_queue_state) {
83 my_strncpy((char*)msg_buf, (char*)rx_buffer, RX_BUFFER_LEN);
86 /* we can't copy it in yet. will be done from msg_clr() */
89 case 2: /* another weird case? */
96 } /* else drop it (buffer full) - probably a corrupt packet */
99 extern inline void tx_int() {
100 /* this interrupt is called with the precondition that the TX fifo of the UART
101 * is completely empty and will hold a complete message (of less than 14 chars)
103 if (tx_queue_state & 0x01) { /* msg to be sent pending */
106 for (i=0; tx_buffer[i]; i++)
107 _uart_regs[UART_TX_BUFFER] = tx_buffer[i];
108 bclr((void*)&tx_queue_state, 0x01);
110 bclr((void*)&tx_queue_state, 0x02); /* mark the FIFO as free */
113 void uart_interrupt() {
116 status = _uart_regs[UART_INT_IDENT];
118 case IS_FIFO_TIMEOUT:
119 case IS_RECEIVER_READY:
122 case IS_TRANSMITTER_READY:
125 case IS_MODEM_STATUS_CHANGE:
126 /* read the modem status register to clear the interrupt */
127 (void)_uart_regs[UART_MODEM_STATUS];
129 case IS_LINE_STATUS_CHANGE:
130 status = _uart_regs[UART_LINE_STATUS];
131 if (status & LS_OVERRUN_ERR) packet_is_bad = 1;
132 if (status & LS_PARITY_ERR) packet_is_bad = 1;
133 if (status & LS_FRAMING_ERR) packet_is_bad = 1;
134 /* LS_BREAK_INTERRUPT ignored for now. Do we want it? */
142 /*******************************************************************************
143 * End of interrupt handler
162 /* sends the packet in tx_buffer and doesn't return until it's been sent */
164 bset((void*)&tx_queue_state, 0x01);
168 while (tx_queue_state & 0x01); /* wait for completion */
172 /* called when a msg in msg_buf has been read */
173 switch (rx_queue_state) {
174 case 0: /* this shouldn't happen */
182 /* copy the rx_buffer into msg_buf */
183 my_strncpy((char*)msg_buf, (char*)rx_buffer, RX_BUFFER_LEN);
199 tx_buffer[0] = rx_buffer[0] = msg_buf[0] = 0;