1 | @c |
---|
2 | @c COPYRIGHT (c) 1988-1998. |
---|
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 how to do a console driver using RTEMS Termios |
---|
14 | support. |
---|
15 | |
---|
16 | The serial driver is called as soon as printf/scanf or read/write kind of |
---|
17 | input/output are needed. There are two main functioning modes: |
---|
18 | |
---|
19 | @itemize @bullet |
---|
20 | |
---|
21 | @item console: formatted input/output, with special characters (end of |
---|
22 | line, tabulations, etc...) recognition and processing, |
---|
23 | |
---|
24 | @item raw: permits raw data processing. |
---|
25 | |
---|
26 | @end itemize |
---|
27 | |
---|
28 | We may think that one need two serial drivers to deal with those two types |
---|
29 | of data, but Termios permits having only one driver. |
---|
30 | |
---|
31 | @section Termios |
---|
32 | |
---|
33 | Termios is a standard for terminal management, included in several Unix |
---|
34 | versions. Termios is good because: |
---|
35 | |
---|
36 | @itemize @bullet |
---|
37 | |
---|
38 | @item from the user's side: primitives to access the terminal and change |
---|
39 | configuration settings are the same under Unix and Rtems. |
---|
40 | |
---|
41 | @item from the BSP developer's side: it frees you from dealing with buffer |
---|
42 | states and mutual exclusions on them. |
---|
43 | |
---|
44 | @end itemize |
---|
45 | |
---|
46 | Termios support includes: |
---|
47 | |
---|
48 | @itemize @bullet |
---|
49 | |
---|
50 | @item raw and console handling, |
---|
51 | |
---|
52 | @item blocking or non-blocking characters receive, with or without |
---|
53 | Timeout. |
---|
54 | |
---|
55 | @end itemize |
---|
56 | |
---|
57 | For more information on Termios, type man termios in your Unix box or go |
---|
58 | to http://www.freebsd.org/cgi/man.cgi. |
---|
59 | |
---|
60 | @section Driver Functioning Modes |
---|
61 | |
---|
62 | There are generally two main functioning modes for an UART (Universal |
---|
63 | Asynchronous Receiver-Transmitter, i.e. the serial chip): |
---|
64 | |
---|
65 | @itemize @bullet |
---|
66 | |
---|
67 | @item polling mode: the processor blocks on sending/receiving characters. |
---|
68 | This mode is not powerful, but is necessary when one wants to print an |
---|
69 | error message when the board hung. This is also the most simple mode to |
---|
70 | program, |
---|
71 | |
---|
72 | @item interrupt mode: the processor doesn't block on sending/receiving |
---|
73 | characters. Two buffers (one for the in-going characters, the others for |
---|
74 | the characters to be sent) are used. An interrupt is raised as soon as a |
---|
75 | character is in the UART. Then the int errupt subroutine insert the |
---|
76 | character at the input buffer queue. When a character is asked for input, |
---|
77 | this at the head of the buffer is returned. When characters have to be |
---|
78 | sent, one have to put the first characters (the number depends on the |
---|
79 | UART) in th e UART. Then an interrupt is raised when all the characters |
---|
80 | have been emitted. The interrupt subroutine has to send the characters |
---|
81 | remaining in the output buffer the same way. |
---|
82 | |
---|
83 | @end itemize |
---|
84 | |
---|
85 | @section Serial Driver Functioning Overview |
---|
86 | |
---|
87 | Figure 5 is an attempt of showing how a Termios driven serial driver works : |
---|
88 | |
---|
89 | @itemize @bullet |
---|
90 | |
---|
91 | @item the application programmer uses standard C library call (printf, |
---|
92 | scanf, read, write, etc.), |
---|
93 | |
---|
94 | @item C library (in fact that's Cygnus Newlib) calls RTEMS procedure: glue |
---|
95 | is made in newlib*.c files which can be found under |
---|
96 | $RTEMS_ROOT/c/src/lib/libc directory, |
---|
97 | |
---|
98 | @item Glue code calls your serial driver entry routines. |
---|
99 | |
---|
100 | @end itemize |
---|
101 | |
---|
102 | @subsection Termios and Polled I/O |
---|
103 | |
---|
104 | You have to point Termios out which functions are used for simple |
---|
105 | character input/output: |
---|
106 | |
---|
107 | |
---|
108 | Function |
---|
109 | |
---|
110 | Description |
---|
111 | |
---|
112 | @example |
---|
113 | int pollWrite (int minor, const char *buf, int len) |
---|
114 | |
---|
115 | for (i=0; i<len; i++) @{ |
---|
116 | put buf[i] into the UART channel minor |
---|
117 | wait for the character to be transmitted |
---|
118 | on the serial line |
---|
119 | @} |
---|
120 | int pollread(int minor) |
---|
121 | @end example |
---|
122 | |
---|
123 | wait for a character to be available in the UART channel minor, then return it. |
---|
124 | |
---|
125 | @subsection Termios and Interrupt Driven I/O |
---|
126 | |
---|
127 | The UART generally generates interrupts when it is ready to accept or to |
---|
128 | emit a number of characters. In this mode, the interrupt subroutine is the |
---|
129 | core of the driver: |
---|
130 | |
---|
131 | @example |
---|
132 | rtems_isr InterruptHandler (rtems_vector_number v) |
---|
133 | @end example |
---|
134 | |
---|
135 | check whether there was an error |
---|
136 | |
---|
137 | if some characters were received: |
---|
138 | ask Termios to put them on his input buffer |
---|
139 | |
---|
140 | if some characters have been transmitted (i.e. the UART output buffer is empty) |
---|
141 | tell TERMIOS that the characters have been |
---|
142 | transmitted. The TERMIOS routine will call |
---|
143 | the InterruptWrite function with the number |
---|
144 | of characters not transmitted yet if it is |
---|
145 | not zero. |
---|
146 | |
---|
147 | @example |
---|
148 | static int InterruptWrite(int minor, const char *buf, int len) |
---|
149 | @end example |
---|
150 | |
---|
151 | you have to put the n first buf characters in the UART channel minor |
---|
152 | buffer (n is the UART channel size, n=1 on the MC68640). Generally, an |
---|
153 | interrupt is raised after these n characters being transmitted. So you may |
---|
154 | have to enable the UART interrupts after having put the characters in the |
---|
155 | UART. |
---|
156 | |
---|
157 | |
---|
158 | Figure 5: general TERMIOS driven serial driver functioning |
---|
159 | |
---|
160 | @subsection Initialization |
---|
161 | |
---|
162 | The driver initialization is called once during RTEMS initialization |
---|
163 | process. |
---|
164 | |
---|
165 | The console_initialize function has to : |
---|
166 | |
---|
167 | @itemize @bullet |
---|
168 | |
---|
169 | @item initialize Termios support: call rtems_termios_initialize(), |
---|
170 | |
---|
171 | @item initialize your integrated processor's UART: the operation is |
---|
172 | normally described in your user's manual and you must follow these |
---|
173 | instructions but it usually consists in: |
---|
174 | |
---|
175 | @item reinitialize the UART channels, |
---|
176 | |
---|
177 | @item set the channels configuration to Termios default one, i.e.: 9600 |
---|
178 | bauds, no parity, 1 stop bit, 8 bits per character, |
---|
179 | |
---|
180 | @item register your console interrupt routine to RTEMS: |
---|
181 | |
---|
182 | @example |
---|
183 | rtems_interrupt_catch (InterruptHandler,CONSOLE_VECTOR,&old_handler); |
---|
184 | @end example |
---|
185 | |
---|
186 | @item enable the UART channels, |
---|
187 | |
---|
188 | @item register your device name: in order to use the console (i.e. being |
---|
189 | able to do printf/scanf on stdin, stdout, and stderr), you have to |
---|
190 | register the "/dev/console" device: |
---|
191 | |
---|
192 | @example |
---|
193 | rtems_io_register_name ("dev/console", major, i); |
---|
194 | @end example |
---|
195 | |
---|
196 | @end itemize |
---|
197 | |
---|
198 | @subsection Opening a serial device |
---|
199 | |
---|
200 | The console device is opened during RTEMS initialization but the |
---|
201 | console_open function is called when a new device is opened. For instance, |
---|
202 | if you register the "/dev/tty1" device for the UART channel 2, the |
---|
203 | console_open will be called with a fopen("/dev/t ty", mode) in your |
---|
204 | application. |
---|
205 | |
---|
206 | The console_open function has to inform Termios of your low-level function |
---|
207 | for serial line support; the "callbacks". |
---|
208 | |
---|
209 | The gen68340 BSP defines two kinds of callbacks: |
---|
210 | |
---|
211 | @itemize @bullet |
---|
212 | |
---|
213 | @item functions to use with polled input/output, |
---|
214 | |
---|
215 | @item functions to use with interrupt input/output. |
---|
216 | |
---|
217 | @end itemize |
---|
218 | |
---|
219 | @subsubsection Polled I/O |
---|
220 | |
---|
221 | You have to point Termios out which functions are used for simple |
---|
222 | character input/output, i.e. pointers to pollWrite and pollRead functions |
---|
223 | defined in 8.4.1. |
---|
224 | |
---|
225 | @subsubsection Interrupt Driven I/O |
---|
226 | |
---|
227 | Driver functioning is quite different in this mode. You can see there's no |
---|
228 | read function passed to Termios. Indeed a console_read call returns the |
---|
229 | content of Termios input buffer. This buffer is filled in the driver |
---|
230 | interrupt subroutine (cf. 8.4.2). |
---|
231 | |
---|
232 | But you actually have to provide a pointer to the InterruptWrite function. |
---|
233 | |
---|
234 | @subsection Closing a serial device |
---|
235 | |
---|
236 | The driver entry point is: console_close. |
---|
237 | |
---|
238 | You just have to notify Termios that the serial device was closed, with a |
---|
239 | call to rtems_termios_close. |
---|
240 | |
---|
241 | @subsection Reading characters from the serial device |
---|
242 | |
---|
243 | The driver entry point is: console_read. |
---|
244 | |
---|
245 | You just have to return the content of the Termios input buffer. |
---|
246 | |
---|
247 | Call rtems_termios_read. |
---|
248 | |
---|
249 | @subsection Writing characters to the serial device |
---|
250 | |
---|
251 | The driver entry point is: console_write. |
---|
252 | |
---|
253 | You just have to add the characters at the end of the Termios output |
---|
254 | buffer. |
---|
255 | |
---|
256 | Call rtems_termios_write. |
---|
257 | |
---|
258 | @subsection Changing serial line parameters |
---|
259 | |
---|
260 | The driver entry point is: console_control. |
---|
261 | |
---|
262 | The application write is able to control the serial line configuration |
---|
263 | with Termios calls (such as the ioctl command, see Termios man page for |
---|
264 | more details). If you want to support dynamic configuration, you have to |
---|
265 | write the console_control piece of code . Look at the gen68340 BSP for an |
---|
266 | example of how it is done. Basically ioctl commands call console_control |
---|
267 | with the serial line configuration in a Termios structure. You just have |
---|
268 | to reinitialize the UART with the correct settings. |
---|
269 | |
---|