/* Handle UART interrupts */ static void apbuart_cons_isr(void *arg) { rtems_termios_tty *tty = arg; rtems_termios_device_context *base; struct console_dev *condev = rtems_termios_get_device_context(tty); struct apbuart_priv *uart = condev_get_priv(condev); struct apbuart_regs *regs = uart->regs; unsigned int status; char buf[33]; int cnt; if (uart->mode == TERMIOS_TASK_DRIVEN) { if ((status = regs->status) & APBUART_STATUS_DR) { rtems_interrupt_lock_context lock_context; /* Turn off RX interrupts */ base = rtems_termios_get_device_context(tty); rtems_termios_device_lock_acquire(base, &lock_context); regs->ctrl &= ~(APBUART_CTRL_DI | APBUART_CTRL_RI | APBUART_CTRL_RF); rtems_termios_device_lock_release(base, &lock_context); /* Activate termios RX daemon task */ rtems_termios_rxirq_occured(tty); } } else { /* * Get all new characters from APBUART RX (FIFO) and store them * on the stack. Then tell termios about the new characters. * Maximum APBUART RX FIFO size is 32 characters. */ cnt = 0; while ( ((status=regs->status) & APBUART_STATUS_DR) && (cnt < sizeof(buf)) ) { buf[cnt] = regs->data; cnt++; } if (0 < cnt) { /* Tell termios layer about new characters */ rtems_termios_enqueue_raw_characters(tty, &buf[0], cnt); } } if (uart->sending && (status & APBUART_STATUS_TE)) { /* Tell close that we sent everything */ cnt = uart->sending; /* * Tell termios how much we have sent. dequeue() may call * write_interrupt() to refill the transmitter. * write_interrupt() will eventually be called with 0 len to * disable TX interrupts. */ rtems_termios_dequeue_characters(tty, cnt); } }
rtems_timer_service_routine Rx_ISR( rtems_id ignored_id, void *ignored_address ) { uint8_t ch; if ( Rx_Index >= Rx_Length ) return; ch = Rx_Buffer[ Rx_Index++ ]; rtems_termios_enqueue_raw_characters (Ttyp, (char *)&ch, 1); #if defined(TASK_DRIVEN) rtems_termios_rxirq_occured(Ttyp); #endif (void) rtems_timer_fire_after( Rx_Timer, 10, Rx_ISR, NULL ); }
void BSP_uart_termios_isr_com2(void *ignored) { unsigned char buf[40]; unsigned char val; int off, ret, vect; off = 0; for(;;) { vect = uread(BSP_UART_COM2, IIR) & 0xf; switch(vect) { case MODEM_STATUS : val = uread(BSP_UART_COM2, MSR); if(uart_data[BSP_UART_COM2].hwFlow) { if(val & CTS) { /* CTS high */ termios_stopped_com2 = 0; if(termios_tx_hold_valid_com2) { termios_tx_hold_valid_com2 = 0; BSP_uart_termios_write_com2(0, &termios_tx_hold_com2, 1); } } else { /* CTS low */ termios_stopped_com2 = 1; } } break; case NO_MORE_INTR : /* No more interrupts */ if(off != 0) { /* Update rx buffer */ if( driver_input_handler_com2 ) { driver_input_handler_com2( termios_ttyp_com2, (char *)buf, off ); } else { rtems_termios_enqueue_raw_characters(termios_ttyp_com2, (char *)buf, off); } } return; case TRANSMITTER_HODING_REGISTER_EMPTY : /* * TX holding empty: we have to disable these interrupts * if there is nothing more to send. */ /* If nothing else to send disable interrupts */ ret = rtems_termios_dequeue_characters(termios_ttyp_com2, 1); if ( ret == 0 ) { termios_tx_active_com2 = 0; uart_data[BSP_UART_COM2].ier &= ~(TRANSMIT_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); } break; case RECEIVER_DATA_AVAIL : case CHARACTER_TIMEOUT_INDICATION: if ( uart_data[BSP_UART_COM2].ioMode == TERMIOS_TASK_DRIVEN ) { /* ensure interrupts are enabled */ if ( uart_data[BSP_UART_COM2].ier & RECEIVE_ENABLE ) { /* disable interrupts and notify termios */ uart_data[BSP_UART_COM2].ier &= ~(RECEIVE_ENABLE | RECEIVER_LINE_ST_ENABLE); uwrite(BSP_UART_COM2, IER, uart_data[BSP_UART_COM2].ier); rtems_termios_rxirq_occured(termios_ttyp_com2); } } else { /* RX data ready */ assert(off < sizeof(buf)); buf[off++] = uread(BSP_UART_COM2, RBR); } break; case RECEIVER_ERROR: /* RX error: eat character */ uartError(BSP_UART_COM2); break; default: /* Should not happen */ assert(0); return; } } }
/*************************************************************************** Function : IntUartInterruptHandler Description : This is the interrupt handler for the internal uart. It determines which channel caused the interrupt before queueing any received chars and dequeueing chars waiting for transmission. ***************************************************************************/ static rtems_isr IntUartInterruptHandler(rtems_vector_number v) { unsigned int chan = v - UART_INTC0_IRQ_VECTOR(0); struct IntUartInfoStruct *info = &IntUartInfo[chan]; /* check to see if received data */ if ( MCF5282_UART_UISR(chan) & MCF5282_UART_UISR_RXRDY ) { /* read data and put into the receive buffer */ while ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_RXRDY ) { if ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_ERROR ) { /* clear the error */ MCF5282_UART_UCR(chan) = MCF5282_UART_UCR_RESET_ERROR; } /* put data in rx buffer and check for errors */ info->rx_buffer[info->rx_in] = MCF5282_UART_URB(chan); /* update buffer values */ info->rx_in++; if ( info->rx_in >= RX_BUFFER_SIZE ) { info->rx_in = 0; } } /* Make sure the port has been opened */ if ( info->ttyp ) { /* check to see if task driven */ if ( info->iomode == TERMIOS_TASK_DRIVEN ) { /* notify rx task that rx buffer has data */ rtems_termios_rxirq_occured(info->ttyp); } else { /* Push up the received data */ rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in); info->rx_in = 0; } } } /* check to see if data needs to be transmitted */ if ( ( info->uimr & MCF5282_UART_UIMR_TXRDY ) && ( MCF5282_UART_UISR(chan) & MCF5282_UART_UISR_TXRDY ) ) { /* disable tx interrupts */ info->uimr &= ~MCF5282_UART_UIMR_TXRDY; MCF5282_UART_UIMR(chan) = info->uimr; /* tell upper level that character has been sent */ if ( info->ttyp ) rtems_termios_dequeue_characters(info->ttyp, 1); } }