[f96e8ee] | 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 | |
---|
[abfbfa7] | 9 | @chapter Console Driver |
---|
[07b3693f] | 10 | |
---|
[abfbfa7] | 11 | @section Introduction |
---|
[07b3693f] | 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 | |
---|
[abfbfa7] | 31 | @section Termios |
---|
[07b3693f] | 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 | |
---|
[abfbfa7] | 60 | @section Driver Functioning Modes |
---|
[07b3693f] | 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 | |
---|
[abfbfa7] | 85 | @section Serial Driver Functioning Overview |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 102 | @subsection Termios and Polled I/O |
---|
[07b3693f] | 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 | |
---|
[abfbfa7] | 115 | for (i=0; i<len; i++) @{ |
---|
[07b3693f] | 116 | put buf[i] into the UART channel minor |
---|
| 117 | wait for the character to be transmitted |
---|
| 118 | on the serial line |
---|
[abfbfa7] | 119 | @} |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 125 | @subsection Termios and Interrupt Driven I/O |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 160 | @subsection Initialization |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 198 | @subsection Opening a serial device |
---|
[07b3693f] | 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 | |
---|
[abfbfa7] | 215 | @item functions to use with interrupt input/output. |
---|
[07b3693f] | 216 | |
---|
| 217 | @end itemize |
---|
| 218 | |
---|
[3351d41] | 219 | @subsubsection Polled I/O |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 225 | @subsubsection Interrupt Driven I/O |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 234 | @subsection Closing a serial device |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 241 | @subsection Reading characters from the serial device |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 249 | @subsection Writing characters to the serial device |
---|
[07b3693f] | 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 | |
---|
[3351d41] | 258 | @subsection Changing serial line parameters |
---|
[07b3693f] | 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 | |
---|