1 | @c |
---|
2 | @c COPYRIGHT (c) 1988-2002. |
---|
3 | @c On-Line Applications Research Corporation (OAR). |
---|
4 | @c All rights reserved. |
---|
5 | @c |
---|
6 | @c $Id$ |
---|
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<len; 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 | |
---|