diff options
Diffstat (limited to 'doc/bsp_howto/console.t')
-rw-r--r-- | doc/bsp_howto/console.t | 377 |
1 files changed, 377 insertions, 0 deletions
diff --git a/doc/bsp_howto/console.t b/doc/bsp_howto/console.t new file mode 100644 index 0000000000..95a0916ec1 --- /dev/null +++ b/doc/bsp_howto/console.t @@ -0,0 +1,377 @@ +@c +@c COPYRIGHT (c) 1988-2002. +@c On-Line Applications Research Corporation (OAR). +@c All rights reserved. +@c +@c $Id$ +@c + +@chapter Console Driver + +@section Introduction + +This chapter describes the operation of a console driver using +the RTEMS POSIX Termios support. Traditionally RTEMS has referred +to all serial device drivers as console device drivers. A +console driver can be used to do raw data processing in addition +to the "normal" standard input and output device functions required +of a console. + +The serial driver may be called as the consequence of a C Library +call such as @code{printf} or @code{scanf} or directly via the +@code{read} or @code{write} system calls. +There are two main functioning modes: + +@itemize @bullet + +@item console: formatted input/output, with special characters (end of +line, tabulations, etc.) recognition and processing, + +@item raw: permits raw data processing. + +@end itemize + +One may think that two serial drivers are needed to handle these two types +of data, but Termios permits having only one driver. + +@section Termios + +Termios is a standard for terminal management, included in the POSIX 1003.1b +standard. It is commonly provided on UNIX implementations. +Having RTEMS support for Termios is beneficial: + +@itemize @bullet + +@item from the user's side because it provides standard primitive operations +to access the terminal and change configuration settings. These operations +are the same under Unix and Rtems. + +@item from the BSP developer's side because it frees the +developer from dealing with buffer states and mutual exclusions on them. +Early RTEMS console device drivers also did their own special +character processing. + +@end itemize + +Termios support includes: + +@itemize @bullet + +@item raw and console handling, + +@item blocking or non-blocking characters receive, with or without +Timeout. + +@end itemize + +At this time, RTEMS documentation does not include a thorough discussion +of the Termios functionality. For more information on Termios, +type @code{man termios} on a Unix box or point a web browser +at +@uref{http://www.freebsd.org/cgi/man.cgi}. + +@section Driver Functioning Modes + +There are generally two main functioning modes for an UART (Universal +Asynchronous Receiver-Transmitter, i.e. the serial chip): + +@itemize @bullet + +@item polled mode +@item interrupt driven mode + +@end itemize + +In polled mode, the processor blocks on sending/receiving characters. +This mode is not the most efficient way to utilize the UART. But +polled mode is usually necessary when one wants to print an +error message in the event of a fatal error such as a fatal error +in the BSP. This is also the simplest mode to +program. Polled mode is generally preferred if the serial port is +to be used primarily as a debug console. In a simple polled driver, +the software will continuously check the status of the UART when +it is reading or writing to the UART. Termios improves on this +by delaying the caller for 1 clock tick between successive checks +of the UART on a read operation. + +In interrupt driven mode, the processor does not block on sending/receiving +characters. Data is buffered between the interrupt service routine +and application code. Two buffers are used to insulate the application +from the relative slowness of the serial device. One of the buffers is +used for incoming characters, while the other is used for outgoing characters. + +An interrupt is raised when a character is received by the UART. +The interrupt subroutine places the incoming character at the end +of the input buffer. When an application asks for input, +the characters at the front of the buffer are returned. + +When the application prints to the serial device, the outgoing characters +are placed at the end of the output buffer. The driver will place +one or more characters in the UART (the exact number depends on the UART) +An interrupt will be raised when all the characters have been transmitted. +The interrupt service routine has to send the characters +remaining in the output buffer the same way. When the transmitting side +of the UART is idle, it is typically necessary to prime the transmitter +before the first interrupt will occur. + +@section Serial Driver Functioning Overview + +The following Figure shows how a Termios driven serial driver works: + +@example +Figure not included in this draft +@end example + +The following list describes the basic flow. + +@itemize @bullet + +@item the application programmer uses standard C library call (printf, +scanf, read, write, etc.), + +@item C library (in fact that's Cygnus Newlib) calls RTEMS +system call interface. This code can be found in the +@code{c/src/lib/libc} directory. + +@item Glue code calls the serial driver entry routines. + +@end itemize + +@subsection Termios and Polled I/O + +The following functions are provided by the driver and invoked by +Termios for simple character input/output. The specific names of +these routines are not important as Termios invokes them indirectly +via function pointers. + +@subsubsection pollWrite + +The @code{pollWrite} routine is responsible for writing @code{len} characters +from @code{buf} to the serial device specified by @code{minor}. + +@example +@group +int pollWrite (int minor, const char *buf, int len) +@{ + for (i=0; i<len; i++) @{ + put buf[i] into the UART channel minor + wait for the character to be transmitted + on the serial line + @} + return 0 +@} +@end group +@end example + +@subsubsection pollRead + +The @code{pollRead} routine is responsible for reading a single character +from the serial device specified by @code{minor}. If no character is +available, then the routine should return -1. + +@example +@group +int pollRead(int minor) +@{ + read status of UART + if status indicates a character is available + return character + return -1 +@} +@end group +@end example + +@subsection Termios and Interrupt Driven I/O + +The UART generally generates interrupts when it is ready to accept or to +emit a number of characters. In this mode, the interrupt subroutine is the +core of the driver. + +@subsubsection InterruptHandler + +The @code{InterruptHandler} is responsible for processing asynchronous +interrupts from the UART. There may be multiple interrupt handlers for +a single UART. Some UARTs can generate a unique interrupt vector for +each interrupt source such as a character has been received or the +transmitter is ready for another character. + +In the simplest case, the @code{InterruptHandler} will have to check +the status of the UART and determine what caused the interrupt. +The following describes the operation of an @code{InterruptHandler} +which has to do this: + +@example +@group +rtems_isr InterruptHandler (rtems_vector_number v) +@{ + check whether there was an error + + if some characters were received: + Ask Termios to put them on his input buffer + + if some characters have been transmitted + (i.e. the UART output buffer is empty) + Tell TERMIOS that the characters have been + transmitted. The TERMIOS routine will call + the InterruptWrite function with the number + of characters not transmitted yet if it is + not zero. +@} +@end group +@end example + +@subsubsection InterruptWrite + +The @code{InterruptWrite} is responsible for telling the UART +that the @code{len} characters at @code{buf} are to be transmitted. + +@example +static int InterruptWrite(int minor, const char *buf, int len) +@{ + tell the UART to transmit len characters from buf + return 0 +@} +@end example + +The driver has to put the @i{n} first buf characters in the UART channel minor +buffer (@i{n} is the UART channel size, @i{n}=1 on the MC68640). Generally, an +interrupt is raised after these @i{n} characters being transmitted. So +UART interrupts may have to be enabled after putting the characters in the +UART. + + +@subsection Initialization + +The driver initialization is called once during the RTEMS initialization +process. + +The @code{console_initialize} function has to: + +@itemize @bullet + +@item initialize Termios support: call @code{rtems_termios_initialize()}. If +Termios has already been initialized by another device driver, then +this call will have no effect. + +@item Initialize the UART: This procedure should +be described in the UART manual. This procedure @b{MUST} be +followed precisely. This procedure varies but +usually consists of: + +@itemize @bullet +@item reinitialize the UART channels + +@item set the channels configuration to the Termios default: +9600 bauds, no parity, 1 stop bit, and 8 bits per character +@end itemize + +@item If interrupt driven, register the console interrupt routine to RTEMS: + +@example +rtems_interrupt_catch( + InterruptHandler, CONSOLE_VECTOR, &old_handler); +@end example + +@item enable the UART channels. + +@item register the device name: in order to use the console (i.e. being +able to do printf/scanf on stdin, stdout, and stderr), some device +must be registered as "/dev/console": + +@example +rtems_io_register_name ("dev/console", major, i); +@end example + +@end itemize + +@subsection Opening a serial device + +The @code{console_open} function is called whenever a serial +device is opened. The device registered as @code{"/dev/console"} +is opened automatically during RTEMS initialization. +For instance, if UART channel 2 is registered as "/dev/tty1", +the @code{console_open} entry point will be called as +the result of an @code{fopen("/dev/tty1", mode)} in the +application. + +The @code{console_open} function has to inform Termios of the low-level +functions for serial line support; the "callbacks". + +The gen68340 BSP defines two sets of callback tables: + +@itemize @bullet + +@item one with functions for polled input/output + +@item another with functions for interrupt driven input/output + +@end itemize + +This code can be found in the file @code{$BSPROOT/console/console.c}. + +@subsubsection Polled I/O + +Termios must be told the addresses of the functions that are to be +used for simple character input/output, i.e. pointers to the +@code{pollWrite} and @code{pollRead} functions +defined earlier in @ref{Console Driver Termios and Polled I/O}. + +@subsubsection Interrupt Driven I/O + +Driver functioning is quite different in this mode. There is no +device driver read function to be passed to Termios. Indeed a +@code{console_read} call returns the contents of Termios input buffer. +This buffer is filled in the driver interrupt subroutine +(see @ref{Console Driver Termios and Interrupt Driven I/O}). + +The driver is responsible for providing a pointer to the +@code{InterruptWrite} function. + +@subsection Closing a Serial Device + +The @code{console_close} is invoked when the serial device is to +be closed. This entry point corresponds to the device driver +close entry point. + +This routine is responsible for notifying Termios that the serial +device was closed. This is done with a call to @code{rtems_termios_close}. + +@subsection Reading Characters From a Serial Device + +The @code{console_read} is invoked when the serial device is to +be read from. This entry point corresponds to the device driver +read entry point. + +This routine is responsible for returning the content of the +Termios input buffer. This is done by invoking the +@code{rtems_termios_read} routine. + +@subsection Writing Characters to a Serial Device + +The @code{console_write} is invoked when the serial device is to +be written to. This entry point corresponds to the device driver +write entry point. + +This routine is responsible for adding the requested characters to +the Termios output queue for this device. This is done by +calling the routine @code{rtems_termios_write} +to add the characters at the end of the Termios output +buffer. + +@subsection Changing Serial Line Parameters + +The @code{console_control} is invoked when the line parameters +for a particular serial device are to be changed. +This entry point corresponds to the device driver +io_control entry point. + +The application write is able to control the serial line configuration +with Termios calls (such as the @code{ioctl} command, see +the Termios documentation for +more details). If the driver is to support dynamic configuration, then +is must have the @code{console_control} piece of code. Refer to the gen68340 +BSP for an example of how it is done. Basically @code{ioctl} +commands call @code{console_control} with the serial line +configuration in a Termios defined data structure. The driver +is responsible for reinitializing the UART with the correct settings. + |