2010-08-03 Joel Sherrill <joel.sherrilL@OARcorp.com>

* console/console.c: Add BSP_poll_char. Reformat.
This commit is contained in:
Joel Sherrill
2010-08-03 14:15:39 +00:00
parent fc7482bc4d
commit e77c8b5117
2 changed files with 588 additions and 595 deletions

View File

@@ -1,3 +1,7 @@
2010-08-03 Joel Sherrill <joel.sherrilL@OARcorp.com>
* console/console.c: Add BSP_poll_char. Reformat.
2010-04-27 Joel Sherrill <joel.sherrilL@OARcorp.com>
* network/network.c, startup/bspstart.c: Remove warnings. hwaddr

View File

@@ -2,6 +2,8 @@
* Multi UART console serial I/O.
*
* TO DO: Add DMA input/output
*
* $Id$
*/
#include <stdio.h>
@@ -25,22 +27,25 @@
static ssize_t IntUartPollWrite(int minor, const char *buf, size_t len);
static ssize_t IntUartInterruptWrite (int minor, const char *buf, size_t len);
static void
_BSP_null_char( char c )
static void _BSP_null_char( char c )
{
int level;
rtems_interrupt_level level;
if (c == '\n')
_BSP_null_char('\r');
rtems_interrupt_disable(level);
while ( (MCF5282_UART_USR(CONSOLE_PORT) & MCF5282_UART_USR_TXRDY) == 0 )
continue;
MCF5282_UART_UTB(CONSOLE_PORT) = c;
while ( (MCF5282_UART_USR(CONSOLE_PORT) & MCF5282_UART_USR_TXRDY) == 0 )
continue;
rtems_interrupt_enable(level);
}
BSP_output_char_function_type BSP_output_char = _BSP_null_char;
BSP_polling_getchar_function_type BSP_poll_char = NULL;
#define MAX_UART_INFO 3
#define RX_BUFFER_SIZE 512
@@ -62,28 +67,34 @@ struct IntUartInfoStruct
struct IntUartInfoStruct IntUartInfo[MAX_UART_INFO];
/***************************************************************************
Function : IntUartSet
Description : This updates the hardware UART settings.
***************************************************************************/
static void
IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwflow)
/*
* Function : IntUartSet
*
* Description : This updates the hardware UART settings.
*/
static void IntUartSet(
int minor,
int baud,
int databits,
int parity,
int stopbits,
int hwflow
)
{
int divisor;
uint32_t clock_speed;
uint8_t umr1 = 0;
uint8_t umr2 = 0;
struct IntUartInfoStruct *info = &IntUartInfo[minor];
int level;
rtems_interrupt_level level;
rtems_interrupt_disable(level);
/* disable interrupts, clear RTS line, and disable the UARTS */
MCF5282_UART_UIMR(minor) = 0;
MCF5282_UART_UOP0(minor) = 1;
MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_DISABLED | MCF5282_UART_UCR_RX_DISABLED);
MCF5282_UART_UCR(minor) =
(MCF5282_UART_UCR_TX_DISABLED | MCF5282_UART_UCR_RX_DISABLED);
/* save the current values */
info->uimr = 0;
@@ -100,8 +111,7 @@ IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwfl
divisor = 2;
/* check to see if doing hardware flow control */
if ( hwflow )
{
if ( hwflow ) {
/* set hardware flow options */
umr1 |= MCF5282_UART_UMR1_RXRTS;
umr2 |= MCF5282_UART_UMR2_TXCTS;
@@ -122,44 +132,44 @@ IntUartSet(int minor, int baud, int databits, int parity, int stopbits, int hwfl
MCF5282_UART_UMR(minor) = umr2;
/* set the baud rate values */
MCF5282_UART_UCSR(minor) = (MCF5282_UART_UCSR_RCS_SYS_CLK | MCF5282_UART_UCSR_TCS_SYS_CLK);
MCF5282_UART_UCSR(minor) =
(MCF5282_UART_UCSR_RCS_SYS_CLK | MCF5282_UART_UCSR_TCS_SYS_CLK);
MCF5282_UART_UBG1(minor) = (divisor & 0xff00) >> 8;
MCF5282_UART_UBG2(minor) = (divisor & 0x00ff);
/* enable the uart */
MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_ENABLED | MCF5282_UART_UCR_RX_ENABLED);
MCF5282_UART_UCR(minor) =
(MCF5282_UART_UCR_TX_ENABLED | MCF5282_UART_UCR_RX_ENABLED);
/* check to see if interrupts need to be enabled */
if ( info->iomode != TERMIOS_POLLED )
{
if ( info->iomode != TERMIOS_POLLED ) {
/* enable rx interrupts */
info->uimr |= MCF5282_UART_UIMR_FFULL;
MCF5282_UART_UIMR(minor) = info->uimr;
}
/* check to see if doing hardware flow control */
if ( hwflow )
{
if ( hwflow ) {
/* assert the RTS line */
MCF5282_UART_UOP1(minor) = 1;
}
rtems_interrupt_enable(level);
}
/***************************************************************************
Function : IntUartSetAttributes
Description : This provides the hardware-dependent portion of tcsetattr().
value and sets it. At the moment this just sets the baud rate.
Note: The highest baudrate is 115200 as this stays within
an error of +/- 5% at 25MHz processor clock
***************************************************************************/
static int
IntUartSetAttributes(int minor, const struct termios *t)
/*
* Function : IntUartSetAttributes
*
* Description : This provides the hardware-dependent portion of tcsetattr().
* value and sets it. At the moment this just sets the baud rate.
*
* Note: The highest baudrate is 115200 as this stays within
* an error of +/- 5% at 25MHz processor clock
*/
static int IntUartSetAttributes(
int minor,
const struct termios *t
)
{
/* set default index values */
int baud = (int)19200;
@@ -170,14 +180,12 @@ IntUartSetAttributes(int minor, const struct termios *t)
struct IntUartInfoStruct *info = &IntUartInfo[minor];
/* check to see if input is valid */
if ( t != (const struct termios *)0 )
{
if ( t != (const struct termios *)0 ) {
/* determine baud rate index */
baud = rtems_termios_baud_to_number(t->c_cflag & CBAUD);
/* determine data bits */
switch ( t->c_cflag & CSIZE )
{
switch ( t->c_cflag & CSIZE ) {
case CS5:
databits = (int)MCF5282_UART_UMR1_BC_5;
break;
@@ -193,30 +201,24 @@ IntUartSetAttributes(int minor, const struct termios *t)
}
/* determine if parity is enabled */
if ( t->c_cflag & PARENB )
{
if ( t->c_cflag & PARODD )
{
if ( t->c_cflag & PARENB ) {
if ( t->c_cflag & PARODD ) {
/* odd parity */
parity = (int)MCF5282_UART_UMR1_PM_ODD;
}
else
{
} else {
/* even parity */
parity = (int)MCF5282_UART_UMR1_PM_EVEN;
}
}
/* determine stop bits */
if ( t->c_cflag & CSTOPB )
{
if ( t->c_cflag & CSTOPB ) {
/* two stop bits */
stopbits = (int)MCF5282_UART_UMR2_STOP_BITS_2;
}
/* check to see if hardware flow control */
if ( t->c_cflag & CRTSCTS )
{
if ( t->c_cflag & CRTSCTS ) {
hwflow = 1;
}
}
@@ -226,39 +228,33 @@ IntUartSetAttributes(int minor, const struct termios *t)
( databits != info->databits ) ||
( parity != info->parity ) ||
( stopbits != info->stopbits ) ||
( hwflow != info->hwflow ) )
{
( hwflow != info->hwflow ) ) {
/* call function to set values */
IntUartSet(minor, baud, databits, parity, stopbits, hwflow);
}
return( RTEMS_SUCCESSFUL );
return RTEMS_SUCCESSFUL;
}
/***************************************************************************
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)
/*
* 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 )
{
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 )
{
while ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_RXRDY ) {
if ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_ERROR )
{
if ( MCF5282_UART_USR(chan) & MCF5282_UART_USR_ERROR ) {
/* clear the error */
MCF5282_UART_UCR(chan) = MCF5282_UART_UCR_RESET_ERROR;
}
@@ -268,25 +264,22 @@ IntUartInterruptHandler(rtems_vector_number v)
/* update buffer values */
info->rx_in++;
if ( info->rx_in >= RX_BUFFER_SIZE )
{
if ( info->rx_in >= RX_BUFFER_SIZE ) {
info->rx_in = 0;
}
}
/* Make sure the port has been opened */
if ( info->ttyp )
{
if ( info->ttyp ) {
/* check to see if task driven */
if ( info->iomode == TERMIOS_TASK_DRIVEN )
{
if ( info->iomode == TERMIOS_TASK_DRIVEN ) {
/* notify rx task that rx buffer has data */
rtems_termios_rxirq_occured(info->ttyp);
}
else
{
} else {
/* Push up the received data */
rtems_termios_enqueue_raw_characters(info->ttyp, info->rx_buffer, info->rx_in);
rtems_termios_enqueue_raw_characters(
info->ttyp, info->rx_buffer, info->rx_in);
info->rx_in = 0;
}
}
@@ -307,25 +300,21 @@ IntUartInterruptHandler(rtems_vector_number v)
}
}
/***************************************************************************
Function : IntUartInitialize
Description : This initialises the internal uart hardware for all
internal uarts. If the internal uart is to be interrupt driven then the
interrupt vectors are hooked.
***************************************************************************/
static void
IntUartInitialize(void)
/*
* Function : IntUartInitialize
*
* Description : This initialises the internal uart hardware for all
* internal uarts. If the internal uart is to be interrupt driven then the
* interrupt vectors are hooked.
*/
static void IntUartInitialize(void)
{
unsigned int chan;
struct IntUartInfoStruct *info;
rtems_isr_entry old_handler;
int level;
rtems_interrupt_level level;
for ( chan = 0; chan < MAX_UART_INFO; chan++ )
{
for ( chan = 0; chan < MAX_UART_INFO; chan++ ) {
info = &IntUartInfo[chan];
info->ttyp = NULL;
@@ -340,8 +329,7 @@ IntUartInitialize(void)
MCF5282_UART_UACR(chan) = 0;
MCF5282_UART_UIMR(chan) = 0;
if ( info->iomode != TERMIOS_POLLED )
{
if ( info->iomode != TERMIOS_POLLED ) {
rtems_interrupt_catch (IntUartInterruptHandler,
UART_INTC0_IRQ_VECTOR(chan),
&old_handler);
@@ -382,18 +370,21 @@ IntUartInitialize(void)
} /* IntUartInitialise */
/***************************************************************************
Function : IntUartInterruptWrite
Description : This writes a single character to the appropriate uart
channel. This is either called during an interrupt or in the user's task
to initiate a transmit sequence. Calling this routine enables Tx
interrupts.
***************************************************************************/
static ssize_t
IntUartInterruptWrite (int minor, const char *buf, size_t len)
/*
* Function : IntUartInterruptWrite
*
* Description : This writes a single character to the appropriate uart
* channel. This is either called during an interrupt or in the user's task
* to initiate a transmit sequence. Calling this routine enables Tx
* interrupts.
*/
static ssize_t IntUartInterruptWrite(
int minor,
const char *buf,
size_t len
)
{
int level;
rtems_interrupt_level level;
rtems_interrupt_disable(level);
@@ -405,55 +396,59 @@ IntUartInterruptWrite (int minor, const char *buf, size_t len)
MCF5282_UART_UIMR(minor) = IntUartInfo[minor].uimr;
rtems_interrupt_enable(level);
return( 0 );
return 0;
}
/***************************************************************************
Function : IntUartInterruptOpen
Description : This enables interrupts when the tty is opened.
***************************************************************************/
static int
IntUartInterruptOpen(int major, int minor, void *arg)
/*
* Function : IntUartInterruptOpen
*
* Description : This enables interrupts when the tty is opened.
*/
static int IntUartInterruptOpen(
int major,
int minor,
void *arg
)
{
struct IntUartInfoStruct *info = &IntUartInfo[minor];
/* enable the uart */
MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_ENABLED | MCF5282_UART_UCR_RX_ENABLED);
MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_ENABLED |
MCF5282_UART_UCR_RX_ENABLED);
/* check to see if interrupts need to be enabled */
if ( info->iomode != TERMIOS_POLLED )
{
if ( info->iomode != TERMIOS_POLLED ) {
/* enable rx interrupts */
info->uimr |= MCF5282_UART_UIMR_FFULL;
MCF5282_UART_UIMR(minor) = info->uimr;
}
/* check to see if doing hardware flow control */
if ( info->hwflow )
{
if ( info->hwflow ) {
/* assert the RTS line */
MCF5282_UART_UOP1(minor) = 1;
}
return( 0 );
return 0;
}
/***************************************************************************
Function : IntUartInterruptClose
Description : This disables interrupts when the tty is closed.
***************************************************************************/
static int
IntUartInterruptClose(int major, int minor, void *arg)
/*
* Function : IntUartInterruptClose
*
* Description : This disables interrupts when the tty is closed.
*/
static int IntUartInterruptClose(
int major,
int minor,
void *arg
)
{
struct IntUartInfoStruct *info = &IntUartInfo[minor];
/* disable the interrupts and the uart */
MCF5282_UART_UIMR(minor) = 0;
MCF5282_UART_UCR(minor) = (MCF5282_UART_UCR_TX_DISABLED | MCF5282_UART_UCR_RX_DISABLED);
MCF5282_UART_UCR(minor) =
(MCF5282_UART_UCR_TX_DISABLED | MCF5282_UART_UCR_RX_DISABLED);
/* reset values */
info->ttyp = NULL;
@@ -461,18 +456,17 @@ IntUartInterruptClose(int major, int minor, void *arg)
info->rx_in = 0;
info->rx_out = 0;
return( 0 );
return 0;
}
/***************************************************************************
Function : IntUartTaskRead
Description : This reads all available characters from the internal uart
and places them into the termios buffer. The rx interrupts will be
re-enabled after all data has been read.
***************************************************************************/
static int
IntUartTaskRead(int minor)
/*
* Function : IntUartTaskRead
*
* Description : This reads all available characters from the internal uart
* and places them into the termios buffer. The rx interrupts will be
* re-enabled after all data has been read.
*/
static int IntUartTaskRead(int minor)
{
char buffer[RX_BUFFER_SIZE];
int count;
@@ -482,72 +476,68 @@ IntUartTaskRead(int minor)
/* determine number of values to copy out */
rx_in = info->rx_in;
if ( info->rx_out <= rx_in )
{
if ( info->rx_out <= rx_in ) {
count = rx_in - info->rx_out;
}
else
{
} else {
count = (RX_BUFFER_SIZE - info->rx_out) + rx_in;
}
/* copy data into local buffer from rx buffer */
while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) )
{
while ( ( index < count ) && ( index < RX_BUFFER_SIZE ) ) {
/* copy data byte */
buffer[index] = info->rx_buffer[info->rx_out];
index++;
/* increment rx buffer values */
info->rx_out++;
if ( info->rx_out >= RX_BUFFER_SIZE )
{
if ( info->rx_out >= RX_BUFFER_SIZE ) {
info->rx_out = 0;
}
}
/* check to see if buffer is not empty */
if ( count > 0 )
{
if ( count > 0 ) {
/* set characters into termios buffer */
rtems_termios_enqueue_raw_characters(info->ttyp, buffer, count);
}
return( EOF );
return EOF;
}
/***************************************************************************
Function : IntUartPollRead
Description : This reads a character from the internal uart. It returns
to the caller without blocking if not character is waiting.
***************************************************************************/
static int
IntUartPollRead (int minor)
/*
* Function : IntUartPollRead
*
* Description : This reads a character from the internal uart. It returns
* to the caller without blocking if not character is waiting.
*/
static int IntUartPollRead(int minor)
{
if ( (MCF5282_UART_USR(minor) & MCF5282_UART_USR_RXRDY) == 0 )
return(-1);
return-1;
return(MCF5282_UART_URB(minor));
return MCF5282_UART_URB(minor);
}
/***************************************************************************
Function : IntUartPollWrite
Description : This writes out each character in the buffer to the
appropriate internal uart channel waiting till each one is sucessfully
transmitted.
***************************************************************************/
static ssize_t
IntUartPollWrite (int minor, const char *buf, size_t len)
/*
* Function : IntUartPollWrite
*
* Description : This writes out each character in the buffer to the
* appropriate internal uart channel waiting till each one is sucessfully
* transmitted.
*/
static ssize_t IntUartPollWrite(
int minor,
const char *buf,
size_t len
)
{
size_t retval = len;
/* loop over buffer */
while ( len-- )
{
while ( len-- ) {
/* block until we can transmit */
while ( (MCF5282_UART_USR(minor) & MCF5282_UART_USR_TXRDY) == 0 )
continue;
@@ -557,20 +547,20 @@ IntUartPollWrite (int minor, const char *buf, size_t len)
return retval;
}
/***************************************************************************
Function : console_initialize
Description : This initialises termios, both sets of uart hardware before
registering /dev/tty devices for each channel and the system /dev/console.
***************************************************************************/
/*
* Function : console_initialize
*
* Description : This initialises termios, both sets of uart hardware before
* registering /dev/tty devices for each channel and the system /dev/console.
*/
rtems_device_driver console_initialize(
rtems_device_major_number major,
rtems_device_minor_number minor,
void *arg )
void *arg
)
{
rtems_status_code status;
/* Set up TERMIOS */
rtems_termios_initialize ();
@@ -580,44 +570,40 @@ rtems_device_driver console_initialize(
/* Register the console port */
status = rtems_io_register_name ("/dev/console", major, CONSOLE_PORT);
if ( status != RTEMS_SUCCESSFUL )
{
if ( status != RTEMS_SUCCESSFUL ) {
rtems_fatal_error_occurred (status);
}
/* Register the other port */
if ( CONSOLE_PORT != 0 )
{
if ( CONSOLE_PORT != 0 ) {
status = rtems_io_register_name ("/dev/tty00", major, 0);
if ( status != RTEMS_SUCCESSFUL )
{
if ( status != RTEMS_SUCCESSFUL ) {
rtems_fatal_error_occurred (status);
}
}
if ( CONSOLE_PORT != 1 )
{
if ( CONSOLE_PORT != 1 ) {
status = rtems_io_register_name ("/dev/tty01", major, 1);
if ( status != RTEMS_SUCCESSFUL )
{
if ( status != RTEMS_SUCCESSFUL ) {
rtems_fatal_error_occurred (status);
}
}
return(RTEMS_SUCCESSFUL);
return RTEMS_SUCCESSFUL;
}
/***************************************************************************
Function : console_open
Description : This actually opens the device depending on the minor
number set during initialisation. The device specific access routines are
passed to termios when the devices is opened depending on whether it is
polled or not.
***************************************************************************/
/*
* Function : console_open
*
* Description : This actually opens the device depending on the minor
* number set during initialisation. The device specific access routines are
* passed to termios when the devices is opened depending on whether it is
* polled or not.
*/
rtems_device_driver console_open(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg)
void * arg
)
{
rtems_status_code status = RTEMS_INVALID_NUMBER;
rtems_libio_open_close_args_t *args = (rtems_libio_open_close_args_t *)arg;
@@ -656,11 +642,9 @@ rtems_device_driver console_open(
};
/* open the port depending on the minor device number */
if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) )
{
if ( ( minor >= 0 ) && ( minor < MAX_UART_INFO ) ) {
info = &IntUartInfo[minor];
switch ( info->iomode )
{
switch ( info->iomode ) {
case TERMIOS_POLLED:
status = rtems_termios_open(major, minor, arg, &IntUartPollCallbacks);
break;
@@ -675,61 +659,65 @@ rtems_device_driver console_open(
}
}
return( status );
return status;
}
/***************************************************************************
Function : console_close
Description : This closes the device via termios
***************************************************************************/
/*
* Function : console_close
*
* Description : This closes the device via termios
*/
rtems_device_driver console_close(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg)
void * arg
)
{
return(rtems_termios_close (arg));
return rtems_termios_close(arg);
}
/******************
*********************************************************
Function : console_read
Description : Read from the device via termios
***************************************************************************/
/*
* Function : console_read
*
* Description : Read from the device via termios
*/
rtems_device_driver console_read(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg)
void *arg
)
{
return(rtems_termios_read (arg));
return rtems_termios_read(arg);
}
/***************************************************************************
Function : console_write
Description : Write to the device via termios
***************************************************************************/
/*
* Function : console_write
*
* Description : Write to the device via termios
*/
rtems_device_driver console_write(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg)
void *arg
)
{
return(rtems_termios_write (arg));
return rtems_termios_write(arg);
}
/***************************************************************************
Function : console_ioctl
Description : Pass the IOCtl call to termios
***************************************************************************/
/*
* Function : console_ioctl
*
* Description : Pass the IOCtl call to termios
*/
rtems_device_driver console_control(
rtems_device_major_number major,
rtems_device_minor_number minor,
void * arg)
void *arg
)
{
return( rtems_termios_ioctl (arg) );
return rtems_termios_ioctl(arg);
}
int DEBUG_OUTCHAR(int c)
{
if (c == '\n')
@@ -746,6 +734,7 @@ void DEBUG_OUTNUM(int i)
{
int n;
static const char map[] = "0123456789ABCDEF";
DEBUG_OUTCHAR(' ');
for (n = 28 ; n >= 0 ; n -= 4)
DEBUG_OUTCHAR(map[(i >> n) & 0xF]);