1 |
1026 |
ivang |
@c
|
2 |
|
|
@c COPYRIGHT (c) 1988-2002.
|
3 |
|
|
@c On-Line Applications Research Corporation (OAR).
|
4 |
|
|
@c All rights reserved.
|
5 |
|
|
@c
|
6 |
|
|
@c console.t,v 1.11 2002/01/17 21:47:44 joel Exp
|
7 |
|
|
@c
|
8 |
|
|
|
9 |
|
|
@chapter Console Driver
|
10 |
|
|
|
11 |
|
|
@section Introduction
|
12 |
|
|
|
13 |
|
|
This chapter describes the operation of a console driver using
|
14 |
|
|
the RTEMS POSIX Termios support. Traditionally RTEMS has referred
|
15 |
|
|
to all serial device drivers as console device drivers. A
|
16 |
|
|
console driver can be used to do raw data processing in addition
|
17 |
|
|
to the "normal" standard input and output device functions required
|
18 |
|
|
of a console.
|
19 |
|
|
|
20 |
|
|
The serial driver may be called as the consequence of a C Library
|
21 |
|
|
call such as @code{printf} or @code{scanf} or directly via the
|
22 |
|
|
@code{read} or @code{write} system calls.
|
23 |
|
|
There are two main functioning modes:
|
24 |
|
|
|
25 |
|
|
@itemize @bullet
|
26 |
|
|
|
27 |
|
|
@item console: formatted input/output, with special characters (end of
|
28 |
|
|
line, tabulations, etc.) recognition and processing,
|
29 |
|
|
|
30 |
|
|
@item raw: permits raw data processing.
|
31 |
|
|
|
32 |
|
|
@end itemize
|
33 |
|
|
|
34 |
|
|
One may think that two serial drivers are needed to handle these two types
|
35 |
|
|
of data, but Termios permits having only one driver.
|
36 |
|
|
|
37 |
|
|
@section Termios
|
38 |
|
|
|
39 |
|
|
Termios is a standard for terminal management, included in the POSIX 1003.1b
|
40 |
|
|
standard. It is commonly provided on UNIX implementations.
|
41 |
|
|
Having RTEMS support for Termios is beneficial:
|
42 |
|
|
|
43 |
|
|
@itemize @bullet
|
44 |
|
|
|
45 |
|
|
@item from the user's side because it provides standard primitive operations
|
46 |
|
|
to access the terminal and change configuration settings. These operations
|
47 |
|
|
are the same under Unix and Rtems.
|
48 |
|
|
|
49 |
|
|
@item from the BSP developer's side because it frees the
|
50 |
|
|
developer from dealing with buffer states and mutual exclusions on them.
|
51 |
|
|
Early RTEMS console device drivers also did their own special
|
52 |
|
|
character processing.
|
53 |
|
|
|
54 |
|
|
@end itemize
|
55 |
|
|
|
56 |
|
|
Termios support includes:
|
57 |
|
|
|
58 |
|
|
@itemize @bullet
|
59 |
|
|
|
60 |
|
|
@item raw and console handling,
|
61 |
|
|
|
62 |
|
|
@item blocking or non-blocking characters receive, with or without
|
63 |
|
|
Timeout.
|
64 |
|
|
|
65 |
|
|
@end itemize
|
66 |
|
|
|
67 |
|
|
At this time, RTEMS documentation does not include a thorough discussion
|
68 |
|
|
of the Termios functionality. For more information on Termios,
|
69 |
|
|
type @code{man termios} on a Unix box or point a web browser
|
70 |
|
|
at
|
71 |
|
|
@uref{http://www.freebsd.org/cgi/man.cgi}.
|
72 |
|
|
|
73 |
|
|
@section Driver Functioning Modes
|
74 |
|
|
|
75 |
|
|
There are generally two main functioning modes for an UART (Universal
|
76 |
|
|
Asynchronous Receiver-Transmitter, i.e. the serial chip):
|
77 |
|
|
|
78 |
|
|
@itemize @bullet
|
79 |
|
|
|
80 |
|
|
@item polled mode
|
81 |
|
|
@item interrupt driven mode
|
82 |
|
|
|
83 |
|
|
@end itemize
|
84 |
|
|
|
85 |
|
|
In polled mode, the processor blocks on sending/receiving characters.
|
86 |
|
|
This mode is not the most efficient way to utilize the UART. But
|
87 |
|
|
polled mode is usually necessary when one wants to print an
|
88 |
|
|
error message in the event of a fatal error such as a fatal error
|
89 |
|
|
in the BSP. This is also the simplest mode to
|
90 |
|
|
program. Polled mode is generally preferred if the serial port is
|
91 |
|
|
to be used primarily as a debug console. In a simple polled driver,
|
92 |
|
|
the software will continuously check the status of the UART when
|
93 |
|
|
it is reading or writing to the UART. Termios improves on this
|
94 |
|
|
by delaying the caller for 1 clock tick between successive checks
|
95 |
|
|
of the UART on a read operation.
|
96 |
|
|
|
97 |
|
|
In interrupt driven mode, the processor does not block on sending/receiving
|
98 |
|
|
characters. Data is buffered between the interrupt service routine
|
99 |
|
|
and application code. Two buffers are used to insulate the application
|
100 |
|
|
from the relative slowness of the serial device. One of the buffers is
|
101 |
|
|
used for incoming characters, while the other is used for outgoing characters.
|
102 |
|
|
|
103 |
|
|
An interrupt is raised when a character is received by the UART.
|
104 |
|
|
The interrupt subroutine places the incoming character at the end
|
105 |
|
|
of the input buffer. When an application asks for input,
|
106 |
|
|
the characters at the front of the buffer are returned.
|
107 |
|
|
|
108 |
|
|
When the application prints to the serial device, the outgoing characters
|
109 |
|
|
are placed at the end of the output buffer. The driver will place
|
110 |
|
|
one or more characters in the UART (the exact number depends on the UART)
|
111 |
|
|
An interrupt will be raised when all the characters have been transmitted.
|
112 |
|
|
The interrupt service routine has to send the characters
|
113 |
|
|
remaining in the output buffer the same way. When the transmitting side
|
114 |
|
|
of the UART is idle, it is typically necessary to prime the transmitter
|
115 |
|
|
before the first interrupt will occur.
|
116 |
|
|
|
117 |
|
|
@section Serial Driver Functioning Overview
|
118 |
|
|
|
119 |
|
|
The following Figure shows how a Termios driven serial driver works:
|
120 |
|
|
|
121 |
|
|
@example
|
122 |
|
|
Figure not included in this draft
|
123 |
|
|
@end example
|
124 |
|
|
|
125 |
|
|
The following list describes the basic flow.
|
126 |
|
|
|
127 |
|
|
@itemize @bullet
|
128 |
|
|
|
129 |
|
|
@item the application programmer uses standard C library call (printf,
|
130 |
|
|
scanf, read, write, etc.),
|
131 |
|
|
|
132 |
|
|
@item C library (in fact that's Cygnus Newlib) calls RTEMS
|
133 |
|
|
system call interface. This code can be found in the
|
134 |
|
|
@code{c/src/lib/libc} directory.
|
135 |
|
|
|
136 |
|
|
@item Glue code calls the serial driver entry routines.
|
137 |
|
|
|
138 |
|
|
@end itemize
|
139 |
|
|
|
140 |
|
|
@subsection Termios and Polled I/O
|
141 |
|
|
|
142 |
|
|
The following functions are provided by the driver and invoked by
|
143 |
|
|
Termios for simple character input/output. The specific names of
|
144 |
|
|
these routines are not important as Termios invokes them indirectly
|
145 |
|
|
via function pointers.
|
146 |
|
|
|
147 |
|
|
@subsubsection pollWrite
|
148 |
|
|
|
149 |
|
|
The @code{pollWrite} routine is responsible for writing @code{len} characters
|
150 |
|
|
from @code{buf} to the serial device specified by @code{minor}.
|
151 |
|
|
|
152 |
|
|
@example
|
153 |
|
|
@group
|
154 |
|
|
int pollWrite (int minor, const char *buf, int len)
|
155 |
|
|
@{
|
156 |
|
|
for (i=0; i
|
157 |
|
|
put buf[i] into the UART channel minor
|
158 |
|
|
wait for the character to be transmitted
|
159 |
|
|
on the serial line
|
160 |
|
|
@}
|
161 |
|
|
return 0
|
162 |
|
|
@}
|
163 |
|
|
@end group
|
164 |
|
|
@end example
|
165 |
|
|
|
166 |
|
|
@subsubsection pollRead
|
167 |
|
|
|
168 |
|
|
The @code{pollRead} routine is responsible for reading a single character
|
169 |
|
|
from the serial device specified by @code{minor}. If no character is
|
170 |
|
|
available, then the routine should return -1.
|
171 |
|
|
|
172 |
|
|
@example
|
173 |
|
|
@group
|
174 |
|
|
int pollRead(int minor)
|
175 |
|
|
@{
|
176 |
|
|
read status of UART
|
177 |
|
|
if status indicates a character is available
|
178 |
|
|
return character
|
179 |
|
|
return -1
|
180 |
|
|
@}
|
181 |
|
|
@end group
|
182 |
|
|
@end example
|
183 |
|
|
|
184 |
|
|
@subsection Termios and Interrupt Driven I/O
|
185 |
|
|
|
186 |
|
|
The UART generally generates interrupts when it is ready to accept or to
|
187 |
|
|
emit a number of characters. In this mode, the interrupt subroutine is the
|
188 |
|
|
core of the driver.
|
189 |
|
|
|
190 |
|
|
@subsubsection InterruptHandler
|
191 |
|
|
|
192 |
|
|
The @code{InterruptHandler} is responsible for processing asynchronous
|
193 |
|
|
interrupts from the UART. There may be multiple interrupt handlers for
|
194 |
|
|
a single UART. Some UARTs can generate a unique interrupt vector for
|
195 |
|
|
each interrupt source such as a character has been received or the
|
196 |
|
|
transmitter is ready for another character.
|
197 |
|
|
|
198 |
|
|
In the simplest case, the @code{InterruptHandler} will have to check
|
199 |
|
|
the status of the UART and determine what caused the interrupt.
|
200 |
|
|
The following describes the operation of an @code{InterruptHandler}
|
201 |
|
|
which has to do this:
|
202 |
|
|
|
203 |
|
|
@example
|
204 |
|
|
@group
|
205 |
|
|
rtems_isr InterruptHandler (rtems_vector_number v)
|
206 |
|
|
@{
|
207 |
|
|
check whether there was an error
|
208 |
|
|
|
209 |
|
|
if some characters were received:
|
210 |
|
|
Ask Termios to put them on his input buffer
|
211 |
|
|
|
212 |
|
|
if some characters have been transmitted
|
213 |
|
|
(i.e. the UART output buffer is empty)
|
214 |
|
|
Tell TERMIOS that the characters have been
|
215 |
|
|
transmitted. The TERMIOS routine will call
|
216 |
|
|
the InterruptWrite function with the number
|
217 |
|
|
of characters not transmitted yet if it is
|
218 |
|
|
not zero.
|
219 |
|
|
@}
|
220 |
|
|
@end group
|
221 |
|
|
@end example
|
222 |
|
|
|
223 |
|
|
@subsubsection InterruptWrite
|
224 |
|
|
|
225 |
|
|
The @code{InterruptWrite} is responsible for telling the UART
|
226 |
|
|
that the @code{len} characters at @code{buf} are to be transmitted.
|
227 |
|
|
|
228 |
|
|
@example
|
229 |
|
|
static int InterruptWrite(int minor, const char *buf, int len)
|
230 |
|
|
@{
|
231 |
|
|
tell the UART to transmit len characters from buf
|
232 |
|
|
return 0
|
233 |
|
|
@}
|
234 |
|
|
@end example
|
235 |
|
|
|
236 |
|
|
The driver has to put the @i{n} first buf characters in the UART channel minor
|
237 |
|
|
buffer (@i{n} is the UART channel size, @i{n}=1 on the MC68640). Generally, an
|
238 |
|
|
interrupt is raised after these @i{n} characters being transmitted. So
|
239 |
|
|
UART interrupts may have to be enabled after putting the characters in the
|
240 |
|
|
UART.
|
241 |
|
|
|
242 |
|
|
|
243 |
|
|
@subsection Initialization
|
244 |
|
|
|
245 |
|
|
The driver initialization is called once during the RTEMS initialization
|
246 |
|
|
process.
|
247 |
|
|
|
248 |
|
|
The @code{console_initialize} function has to:
|
249 |
|
|
|
250 |
|
|
@itemize @bullet
|
251 |
|
|
|
252 |
|
|
@item initialize Termios support: call @code{rtems_termios_initialize()}. If
|
253 |
|
|
Termios has already been initialized by another device driver, then
|
254 |
|
|
this call will have no effect.
|
255 |
|
|
|
256 |
|
|
@item Initialize the UART: This procedure should
|
257 |
|
|
be described in the UART manual. This procedure @b{MUST} be
|
258 |
|
|
followed precisely. This procedure varies but
|
259 |
|
|
usually consists of:
|
260 |
|
|
|
261 |
|
|
@itemize @bullet
|
262 |
|
|
@item reinitialize the UART channels
|
263 |
|
|
|
264 |
|
|
@item set the channels configuration to the Termios default:
|
265 |
|
|
9600 bauds, no parity, 1 stop bit, and 8 bits per character
|
266 |
|
|
@end itemize
|
267 |
|
|
|
268 |
|
|
@item If interrupt driven, register the console interrupt routine to RTEMS:
|
269 |
|
|
|
270 |
|
|
@example
|
271 |
|
|
rtems_interrupt_catch(
|
272 |
|
|
InterruptHandler, CONSOLE_VECTOR, &old_handler);
|
273 |
|
|
@end example
|
274 |
|
|
|
275 |
|
|
@item enable the UART channels.
|
276 |
|
|
|
277 |
|
|
@item register the device name: in order to use the console (i.e. being
|
278 |
|
|
able to do printf/scanf on stdin, stdout, and stderr), some device
|
279 |
|
|
must be registered as "/dev/console":
|
280 |
|
|
|
281 |
|
|
@example
|
282 |
|
|
rtems_io_register_name ("dev/console", major, i);
|
283 |
|
|
@end example
|
284 |
|
|
|
285 |
|
|
@end itemize
|
286 |
|
|
|
287 |
|
|
@subsection Opening a serial device
|
288 |
|
|
|
289 |
|
|
The @code{console_open} function is called whenever a serial
|
290 |
|
|
device is opened. The device registered as @code{"/dev/console"}
|
291 |
|
|
is opened automatically during RTEMS initialization.
|
292 |
|
|
For instance, if UART channel 2 is registered as "/dev/tty1",
|
293 |
|
|
the @code{console_open} entry point will be called as
|
294 |
|
|
the result of an @code{fopen("/dev/tty1", mode)} in the
|
295 |
|
|
application.
|
296 |
|
|
|
297 |
|
|
The @code{console_open} function has to inform Termios of the low-level
|
298 |
|
|
functions for serial line support; the "callbacks".
|
299 |
|
|
|
300 |
|
|
The gen68340 BSP defines two sets of callback tables:
|
301 |
|
|
|
302 |
|
|
@itemize @bullet
|
303 |
|
|
|
304 |
|
|
@item one with functions for polled input/output
|
305 |
|
|
|
306 |
|
|
@item another with functions for interrupt driven input/output
|
307 |
|
|
|
308 |
|
|
@end itemize
|
309 |
|
|
|
310 |
|
|
This code can be found in the file @code{$BSPROOT/console/console.c}.
|
311 |
|
|
|
312 |
|
|
@subsubsection Polled I/O
|
313 |
|
|
|
314 |
|
|
Termios must be told the addresses of the functions that are to be
|
315 |
|
|
used for simple character input/output, i.e. pointers to the
|
316 |
|
|
@code{pollWrite} and @code{pollRead} functions
|
317 |
|
|
defined earlier in @ref{Console Driver Termios and Polled I/O}.
|
318 |
|
|
|
319 |
|
|
@subsubsection Interrupt Driven I/O
|
320 |
|
|
|
321 |
|
|
Driver functioning is quite different in this mode. There is no
|
322 |
|
|
device driver read function to be passed to Termios. Indeed a
|
323 |
|
|
@code{console_read} call returns the contents of Termios input buffer.
|
324 |
|
|
This buffer is filled in the driver interrupt subroutine
|
325 |
|
|
(see @ref{Console Driver Termios and Interrupt Driven I/O}).
|
326 |
|
|
|
327 |
|
|
The driver is responsible for providing a pointer to the
|
328 |
|
|
@code{InterruptWrite} function.
|
329 |
|
|
|
330 |
|
|
@subsection Closing a Serial Device
|
331 |
|
|
|
332 |
|
|
The @code{console_close} is invoked when the serial device is to
|
333 |
|
|
be closed. This entry point corresponds to the device driver
|
334 |
|
|
close entry point.
|
335 |
|
|
|
336 |
|
|
This routine is responsible for notifying Termios that the serial
|
337 |
|
|
device was closed. This is done with a call to @code{rtems_termios_close}.
|
338 |
|
|
|
339 |
|
|
@subsection Reading Characters From a Serial Device
|
340 |
|
|
|
341 |
|
|
The @code{console_read} is invoked when the serial device is to
|
342 |
|
|
be read from. This entry point corresponds to the device driver
|
343 |
|
|
read entry point.
|
344 |
|
|
|
345 |
|
|
This routine is responsible for returning the content of the
|
346 |
|
|
Termios input buffer. This is done by invoking the
|
347 |
|
|
@code{rtems_termios_read} routine.
|
348 |
|
|
|
349 |
|
|
@subsection Writing Characters to a Serial Device
|
350 |
|
|
|
351 |
|
|
The @code{console_write} is invoked when the serial device is to
|
352 |
|
|
be written to. This entry point corresponds to the device driver
|
353 |
|
|
write entry point.
|
354 |
|
|
|
355 |
|
|
This routine is responsible for adding the requested characters to
|
356 |
|
|
the Termios output queue for this device. This is done by
|
357 |
|
|
calling the routine @code{rtems_termios_write}
|
358 |
|
|
to add the characters at the end of the Termios output
|
359 |
|
|
buffer.
|
360 |
|
|
|
361 |
|
|
@subsection Changing Serial Line Parameters
|
362 |
|
|
|
363 |
|
|
The @code{console_control} is invoked when the line parameters
|
364 |
|
|
for a particular serial device are to be changed.
|
365 |
|
|
This entry point corresponds to the device driver
|
366 |
|
|
io_control entry point.
|
367 |
|
|
|
368 |
|
|
The application write is able to control the serial line configuration
|
369 |
|
|
with Termios calls (such as the @code{ioctl} command, see
|
370 |
|
|
the Termios documentation for
|
371 |
|
|
more details). If the driver is to support dynamic configuration, then
|
372 |
|
|
is must have the @code{console_control} piece of code. Refer to the gen68340
|
373 |
|
|
BSP for an example of how it is done. Basically @code{ioctl}
|
374 |
|
|
commands call @code{console_control} with the serial line
|
375 |
|
|
configuration in a Termios defined data structure. The driver
|
376 |
|
|
is responsible for reinitializing the UART with the correct settings.
|
377 |
|
|
|