Changeset 87894c0 in rtems
- Timestamp:
- 07/11/14 11:29:53 (9 years ago)
- Branches:
- 4.11, 5, master
- Children:
- 6b0a7efc
- Parents:
- 742402b5
- git-author:
- Sebastian Huber <sebastian.huber@…> (07/11/14 11:29:53)
- git-committer:
- Sebastian Huber <sebastian.huber@…> (07/21/14 15:43:11)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
doc/bsp_howto/console.t
r742402b5 r87894c0 8 8 @section Introduction 9 9 10 This chapter describes the operation of a console driver using 10 This chapter describes the operation of a console driver using 11 11 the RTEMS POSIX Termios support. Traditionally RTEMS has referred 12 12 to all serial device drivers as console device drivers. A … … 17 17 The serial driver may be called as the consequence of a C Library 18 18 call such as @code{printf} or @code{scanf} or directly via the 19 @code{read} or @code{write} system calls. 20 There are two main functioning modes: 19 @code{read} or @code{write} system calls. 20 There are two main functioning modes: 21 21 22 22 @itemize @bullet … … 25 25 line, tabulations, etc.) recognition and processing, 26 26 27 @item raw: permits raw data processing. 27 @item raw: permits raw data processing. 28 28 29 29 @end itemize 30 30 31 31 One may think that two serial drivers are needed to handle these two types 32 of data, but Termios permits having only one driver. 32 of data, but Termios permits having only one driver. 33 33 34 34 @section Termios … … 39 39 Open Group has the termios portion of the POSIX standard online 40 40 at @uref{http://opengroup.org/onlinepubs/007908775/xbd/termios.html 41 ,http://opengroup.org/onlinepubs/007908775/xbd/termios.html}. 41 ,http://opengroup.org/onlinepubs/007908775/xbd/termios.html}. 42 42 The requirements for the @code{<termios.h>} file are also provided 43 43 and are at @uref{http://opengroup.org/onlinepubs/007908775/xsh/termios.h.html, … … 50 50 @item from the user's side because it provides standard primitive operations 51 51 to access the terminal and change configuration settings. These operations 52 are the same under UNIX and RTEMS. 52 are the same under UNIX and RTEMS. 53 53 54 54 @item from the BSP developer's side because it frees the 55 developer from dealing with buffer states and mutual exclusions on them. 55 developer from dealing with buffer states and mutual exclusions on them. 56 56 Early RTEMS console device drivers also did their own special 57 57 character processing. … … 63 63 @end itemize 64 64 65 Termios support includes: 65 Termios support includes: 66 66 67 67 @itemize @bullet … … 70 70 71 71 @item blocking or non-blocking characters receive, with or without 72 Timeout. 72 Timeout. 73 73 74 74 @end itemize … … 82 82 @section Driver Functioning Modes 83 83 84 There are generally t womain functioning modes for an UART (Universal85 Asynchronous Receiver-Transmitter, i.e. the serial chip): 84 There are generally three main functioning modes for an UART (Universal 85 Asynchronous Receiver-Transmitter, i.e. the serial chip): 86 86 87 87 @itemize @bullet … … 89 89 @item polled mode 90 90 @item interrupt driven mode 91 @item task driven mode 91 92 92 93 @end itemize 93 94 94 95 In polled mode, the processor blocks on sending/receiving characters. 95 This mode is not the most efficient way to utilize the UART. But 96 This mode is not the most efficient way to utilize the UART. But 96 97 polled mode is usually necessary when one wants to print an 97 98 error message in the event of a fatal error such as a fatal error … … 121 122 The interrupt service routine has to send the characters 122 123 remaining in the output buffer the same way. When the transmitting side 123 of the UART is idle, it is typically necessary to prime the transmitter 124 of the UART is idle, it is typically necessary to prime the transmitter 124 125 before the first interrupt will occur. 125 126 127 The task driven mode is similar to interrupt driven mode, but the actual data 128 processing is done in dedicated tasks instead of interrupt routines. 129 126 130 @section Serial Driver Functioning Overview 127 131 128 The following Figure shows how a Termios driven serial driver works: 132 The following Figure shows how a Termios driven serial driver works: 129 133 130 134 @ifset use-ascii … … 150 154 scanf, read, write, etc.), 151 155 152 @item C library ( e.g. RedHat (formerly Cygnus) Newlib) calls156 @item C library (ctx.g. RedHat (formerly Cygnus) Newlib) calls 153 157 the RTEMS system call interface. This code can be found in the 154 @ code{cpukit/libcsupport/src} directory.155 156 @item Glue code calls the serial driver entry routines. 158 @file{cpukit/libcsupport/src} directory. 159 160 @item Glue code calls the serial driver entry routines. 157 161 158 162 @end itemize … … 160 164 @subsection Basics 161 165 162 You need to include the following header files in your Termios device driver 163 source file: 164 @example 165 @group 166 #include <unistd.h> 167 #include <termios.h> 168 169 #include <rtems.h> 170 #include <rtems/libio.h> 171 #include <rtems/console.h> 172 @end group 173 @end example 174 175 You need to provide a data structure for the Termios driver interface. The 176 functions are described later in this chapter. The functions should return 177 zero on succes and minus one in case of an error. Currently the return value 178 will be not checked from the Termios infrastructure in most cases. One notable 179 exception is the polled read function, here is the return value important. 180 181 If you want to use polled IO it should look like the following. You may also 182 have a look at @code{c/src/lib/libbsp/shared/console-polled.c} for a shared 183 implementation of the basic framework. Termios must be told the addresses of 184 the functions that are to be used for simple character IO, i.e. pointers to the 185 @code{my_driver_poll_read} and @code{my_driver_poll_write} functions described 186 later in @ref{Console Driver Termios and Polled IO}. 187 188 @example 189 @group 190 static const rtems_termios_callbacks my_driver_callbacks_polled = @{ 191 .firstOpen = my_driver_first_open, 192 .lastClose = my_driver_last_close, 193 .pollRead = my_driver_poll_read, 194 .write = my_driver_poll_write, 195 .setAttributes = my_driver_set_attributes, 196 .stopRemoteTx = NULL, 197 .startRemoteTx = NULL, 198 .outputUsesInterrupts = TERMIOS_POLLED 199 @}; 166 The low-level driver API changed between RTEMS 4.10 and RTEMS 4.11. The legacy 167 callback API is still supported, but its use is discouraged. The following 168 functions are deprecated: 169 170 @itemize @bullet 171 172 @item @code{rtems_termios_open()} - use @code{rtems_termios_device_open()} in 173 combination with @code{rtems_termios_device_install()} instead. 174 175 @item @code{rtems_termios_close()} - use @code{rtems_termios_device_close()} 176 instead. 177 178 @end itemize 179 180 This manual describes the new API. A new console driver should consist of 181 three parts. 182 183 @enumerate 184 185 @item The basic console driver functions using the Termios support. Add this 186 the BSPs Makefile.am: 187 188 @example 189 @group 190 [...] 191 libbsp_a_SOURCES += ../../shared/console-termios.c 192 [...] 193 @end group 194 @end example 195 196 @item A general serial module specific low-level driver providing the handler 197 table for the Termios @code{rtems_termios_device_install()} function. This 198 low-level driver could be used for more than one BSP. 199 200 @item A BSP specific initialization routine @code{console_initialize()}, that 201 calls @code{rtems_termios_device_install()} providing a low-level driver 202 context for each installed device. 203 204 @end enumerate 205 206 You need to provide a device handler structure for the Termios device 207 interface. The functions are described later in this chapter. The first open 208 and set attributes handler return a boolean status to indicate success (true) 209 or failure (false). The polled read function returns an unsigned character in 210 case one is available or minus one otherwise. 211 212 If you want to use polled IO it should look like the following. Termios must 213 be told the addresses of the handler that are to be used for simple character 214 IO, i.e. pointers to the @code{my_driver_poll_read()} and 215 @code{my_driver_poll_write()} functions described later in @ref{Console Driver 216 Termios and Polled IO}. 217 218 @example 219 @group 220 const rtems_termios_handler my_driver_handler_polled = @{ 221 .first_open = my_driver_first_open, 222 .last_close = my_driver_last_close, 223 .poll_read = my_driver_poll_read, 224 .write = my_driver_poll_write, 225 .set_attributes = my_driver_set_attributes, 226 .stop_remote_tx = NULL, 227 .start_remote_tx = NULL, 228 .mode = TERMIOS_POLLED 229 @} 200 230 @end group 201 231 @end example … … 203 233 For an interrupt driven implementation you need the following. The driver 204 234 functioning is quite different in this mode. There is no device driver read 205 function to be passed to Termios. Indeed a @code{console_read} call returns 206 thecontents of Termios input buffer. This buffer is filled in the driver207 interrupt subroutine, see also 208 @ref{Console Driver Termios and Interrupt Driven IO}. 209 The driver is responsible for providing a pointer to the 210 @code{my_driver_interrupt_write} function. 211 212 @ example213 @group 214 static const rtems_termios_callbacks my_driver_callbacks_interrupt = @{ 215 .firstOpen = my_driver_first_open,216 .lastClose = my_driver_last_close,217 .pollRead = NULL,218 .write = my_driver_interrupt_write,219 .setAttributes = my_driver_set_attributes,220 .stopRemoteTx = NULL,221 .startRemoteTx = NULL,222 .outputUsesInterrupts= TERMIOS_IRQ_DRIVEN235 handler to be passed to Termios. Indeed a @code{console_read()} call returns the 236 contents of Termios input buffer. This buffer is filled in the driver 237 interrupt subroutine, see also @ref{Console Driver Termios and Interrupt Driven 238 IO}. The driver is responsible for providing a pointer to the 239 @code{my_driver_interrupt_write()} function. 240 241 @example 242 @group 243 const rtems_termios_handler my_driver_handler_interrupt = @{ 244 .first_open = my_driver_first_open, 245 .last_close = my_driver_last_close, 246 .poll_read = NULL, 247 .write = my_driver_interrupt_write, 248 .set_attributes = my_driver_set_attributes, 249 .stopRemoteTx = NULL, 250 .stop_remote_tx = NULL, 251 .start_remote_tx = NULL, 252 .mode = TERMIOS_IRQ_DRIVEN 223 253 @}; 224 254 @end group 225 255 @end example 226 256 227 You can also provide callback functionsfor remote transmission control. This228 is not covered in this manual, so th ay are set to @code{NULL} in the above257 You can also provide hander for remote transmission control. This 258 is not covered in this manual, so they are set to @code{NULL} in the above 229 259 examples. 230 260 231 Normally the device specific data structures are stored in a table which is 232 indexed by the minor number. You may need an entry for the Termios handler 233 pointer in your data structure. For simplicity of the console initialization 234 example the device name is also present. 235 236 @example 237 @group 238 /* Driver specific data structure */ 261 The low-level driver should provide a data structure for its device context. 262 The initialization routine must provide a context for each installed device via 263 @code{rtems_termios_device_install()}. For simplicity of the console 264 initialization example the device name is also present. Her is an example header file. 265 266 @example 267 @group 268 #ifndef MY_DRIVER_H 269 #define MY_DRIVER_H 270 271 #include <rtems/termiostypes.h> 272 273 #include <some-chip-header.h> 274 275 /* Low-level driver specific data structure */ 239 276 typedef struct @{ 240 const char *device_name; 241 struct rtems_termios_tty *tty; 242 @} my_driver_entry; 243 244 /* 245 * This table contains the driver specific data. It is later 246 * indexed by the minor number. 247 */ 248 static my_driver_entry my_driver_table [MY_DRIVER_DEVICE_NUMBER]; 277 const char *device_name; 278 volatile module_register_block *regs; 279 /* More stuff */ 280 @} my_driver_context; 281 282 extern const rtems_termios_handler my_driver_handler_polled; 283 284 extern const rtems_termios_handler my_driver_handler_interrupt; 285 286 #endif /* MY_DRIVER_H */ 249 287 @end group 250 288 @end example … … 252 290 @subsection Termios and Polled IO 253 291 254 The following functions are provided by thedriver and invoked by292 The following handler are provided by the low-level driver and invoked by 255 293 Termios for simple character IO. 256 294 257 The @code{my_driver_poll_write} routine is responsible for writing @code{n} 258 characters from @code{buf} to the serial device specified by @code{minor}. 259 260 On success, the number of bytes written is returned (zero indicates nothing 261 was written). On error, @code{-1} is returned. 262 263 NOTE: Due to the current implementation of termios, any data passed into 264 the write function will be lost. 265 266 @example 267 @group 268 static ssize_t my_driver_poll_write(int minor, const char *buf, size_t n) 269 @{ 270 my_driver_entry *e = &my_driver_table [minor]; 271 int i = 0; 272 273 /* 274 * There is no need to check the minor number since it is derived 275 * from a file descriptor. The upper layer takes care that it is 276 * in a valid range. 277 */ 278 279 /* Write */ 280 for (i = 0; i < n; ++i) @{ 281 my_driver_write_char(e, buf [i]); 282 @} 283 284 return n; 295 The @code{my_driver_poll_write()} routine is responsible for writing @code{n} 296 characters from @code{buf} to the serial device specified by @code{tty}. 297 298 @example 299 @group 300 static void my_driver_poll_write( 301 rtems_termios_tty *tty, 302 const char *buf, 303 size_t n 304 ) 305 @{ 306 my_driver_context *ctx = rtems_termios_get_device_context(tty); 307 size_t i; 308 309 /* Write */ 310 for (i = 0; i < n; ++i) @{ 311 my_driver_write_char(ctx, buf[i]); 312 @} 285 313 @} 286 314 @end group … … 288 316 289 317 The @code{my_driver_poll_read} routine is responsible for reading a single 290 character from the serial device specified by @code{ minor}. If no character is318 character from the serial device specified by @code{tty}. If no character is 291 319 available, then the routine should return minus one. 292 320 293 321 @example 294 322 @group 295 static int my_driver_poll_read(int minor) 296 @{ 297 my_driver_entry *e = &my_driver_table [minor]; 298 299 /* 300 * There is no need to check the minor number since it is derived 301 * from a file descriptor. The upper layer takes care that it is 302 * in a valid range. 303 */ 304 305 /* Check if a character is available */ 306 if (my_driver_can_read_char(e)) @{ 307 /* Return the character */ 308 return my_driver_read_char(e); 309 @} else @{ 310 /* Return an error status */ 311 return -1; 312 @} 323 static int my_driver_poll_read(rtems_termios_tty *tty) 324 @{ 325 my_driver_context *ctx = rtems_termios_get_device_context(tty); 326 327 /* Check if a character is available */ 328 if (my_driver_can_read_char(ctx)) @{ 329 /* Return the character */ 330 return my_driver_read_char(ctx); 331 @} else @{ 332 /* Return an error status */ 333 return -1; 334 @} 313 335 @} 314 336 @end group … … 321 343 the driver. 322 344 323 The @code{my_driver_interrupt_handler } is responsible for processing345 The @code{my_driver_interrupt_handler()} is responsible for processing 324 346 asynchronous interrupts from the UART. There may be multiple interrupt 325 347 handlers for a single UART. Some UARTs can generate a unique interrupt vector … … 327 349 transmitter is ready for another character. 328 350 329 In the simplest case, the @code{my_driver_interrupt_handler } will have to check351 In the simplest case, the @code{my_driver_interrupt_handler()} will have to check 330 352 the status of the UART and determine what caused the interrupt. The following 331 353 describes the operation of an @code{my_driver_interrupt_handler} which has to … … 335 357 @group 336 358 static void my_driver_interrupt_handler( 337 rtems_vector_numbervector,338 void*arg359 rtems_vector_number vector, 360 void *arg 339 361 ) 340 362 @{ 341 my_driver_entry *e = (my_driver_entry *) arg; 342 char buf [N]; 343 int n = 0; 344 363 rtems_termios_tty *tty = arg; 364 my_driver_context *ctx = rtems_termios_get_device_context(tty); 365 char buf[N]; 366 size_t n; 367 368 /* 369 * Check if we have received something. The function reads the 370 * received characters from the device and stores them in the 371 * buffer. It returns the number of read characters. 372 */ 373 n = my_driver_read_received_chars(ctx, buf, N); 374 if (n > 0) @{ 375 /* Hand the data over to the Termios infrastructure */ 376 rtems_termios_enqueue_raw_characters(tty, buf, n); 377 @} 378 379 /* 380 * Check if we have something transmitted. The functions returns 381 * the number of transmitted characters since the last write to the 382 * device. 383 */ 384 n = my_driver_transmitted_chars(ctx); 385 if (n > 0) @{ 345 386 /* 346 * Check if we have received something. The function reads the347 * received characters from the device and stores them in the348 * buffer. It returns the number of read characters.387 * Notify Termios that we have transmitted some characters. It 388 * will call now the interrupt write function if more characters 389 * are ready for transmission. 349 390 */ 350 n = my_driver_read_received_chars(e, buf, N); 351 if (n > 0) @{ 352 /* Hand the data over to the Termios infrastructure */ 353 rtems_termios_enqueue_raw_characters(e->tty, buf, n); 354 @} 355 356 /* 357 * Check if we have something transmitted. The functions returns 358 * the number of transmitted characters since the last write to the 359 * device. 360 */ 361 n = my_driver_transmitted_chars(e); 362 if (n > 0) @{ 363 /* 364 * Notify Termios that we have transmitted some characters. It 365 * will call now the interrupt write function if more characters 366 * are ready for transmission. 367 */ 368 rtems_termios_dequeue_characters(e->tty, n); 369 @} 370 @} 371 @end group 372 @end example 373 374 The @code{my_driver_interrupt_write} function is responsible for telling the 375 device that the @code{n} characters at @code{buf} are to be transmitted. The 376 return value may be arbitrary since it is not checked from Termios. It is 377 guaranteed that @code{n} is greater than zero. This routine is invoked either 378 from task context with disabled interrupts to start a new transmission process 379 with exactly one character in case of an idle output state or from the 391 rtems_termios_dequeue_characters(tty, n); 392 @} 393 @} 394 @end group 395 @end example 396 397 The @code{my_driver_interrupt_write()} function is responsible for telling the 398 device that the @code{n} characters at @code{buf} are to be transmitted. It 399 the value @code{n} is zero to indicate that no more characters are to send. 400 The driver can disable the transmit interrupts now. This routine is invoked 401 either from task context with disabled interrupts to start a new transmission 402 process with exactly one character in case of an idle output state or from the 380 403 interrupt handler to refill the transmitter. If the routine is invoked to 381 404 start the transmit process the output state will become busy and Termios starts … … 384 407 character. 385 408 386 On error, the function should return @code{-1}. On success, it should return 387 @code{0}, since it the interrupt handler will report the actual number of 388 characters transmitted. 389 390 @example 391 @group 392 static ssize_t my_driver_interrupt_write(int minor, const char *buf, size_t n) 393 @{ 394 my_driver_entry *e = &my_driver_table [minor]; 395 409 @example 410 @group 411 static void my_driver_interrupt_write( 412 rtems_termios_tty *tty, 413 const char *buf, 414 size_t n 415 ) 416 @{ 417 my_driver_context *ctx = rtems_termios_get_device_context(tty); 418 419 /* 420 * Tell the device to transmit some characters from buf (less than 421 * or equal to n). When the device is finished it should raise an 422 * interrupt. The interrupt handler will notify Termios that these 423 * characters have been transmitted and this may trigger this write 424 * function again. You may have to store the number of outstanding 425 * characters in the device data structure. 426 */ 427 428 /* 429 * Termios will set n to zero to indicate that the transmitter is 430 * now inactive. The output buffer is empty in this case. The 431 * driver may disable the transmit interrupts now. 432 */ 433 @} 434 @end group 435 @end example 436 437 @subsection Initialization 438 439 The BSP specific driver initialization is called once during the RTEMS 440 initialization process. 441 442 The @code{console_initialize()} function may look like this: 443 444 @example 445 @group 446 #include <my-driver.h> 447 #include <rtems/console.h> 448 #include <bsp.h> 449 #include <bsp/fatal.h> 450 451 static my_driver_context driver_context_table[M] = @{ /* Some values */ @}; 452 453 rtems_device_driver console_initialize( 454 rtems_device_major_number major, 455 rtems_device_minor_number minor, 456 void *arg 457 ) 458 @{ 459 rtems_status_code sc; 460 #ifdef SOME_BSP_USE_INTERRUPTS 461 const rtems_termios_handler *handler = &my_driver_handler_interrupt; 462 #else 463 const rtems_termios_handler *handler = &my_driver_handler_polled; 464 #endif 465 466 /* 467 * Initialize the Termios infrastructure. If Termios has already 468 * been initialized by another device driver, then this call will 469 * have no effect. 470 */ 471 rtems_termios_initialize(); 472 473 /* Initialize each device */ 474 for ( 475 minor = 0; 476 minor < RTEMS_ARRAY_SIZE(driver_context_table); 477 ++minor 478 ) @{ 479 my_driver_context *ctx = &driver_context_table[minor]; 480 396 481 /* 397 * There is no need to check the minor number since it is derived 398 * from a file descriptor. The upper layer takes care that it is 399 * in a valid range. 482 * Install this device in the file system and Termios. In order 483 * to use the console (i.e. being able to do printf, scanf etc. 484 * on stdin, stdout and stderr), one device must be registered as 485 * "/dev/console" (CONSOLE_DEVICE_NAME). 400 486 */ 401 402 /*403 * Tell the device to transmit some characters from buf (less than404 * or equal to n). When the device is finished it should raise an405 * interrupt. The interrupt handler will notify Termios that these406 * characters have been transmitted and this may trigger this write407 * function again. You may have to store the number of outstanding408 * characters in the device data structure.409 */410 411 /*412 * Termios will set n to zero to indicate that the transmitter is 413 * now inactive. The output buffer is empty in this case. The414 * driver may disable the transmit interrupts now. 415 */ 416 417 return 0; 418 @ }419 @end group 420 @end example 421 422 @ subsection Initialization423 424 The driver initialization is called once during the RTEMS initialization 425 process. 426 427 The @code{console_initialize} function may look like this: 428 429 @example 430 @ group431 rtems_device_driver console_initialize( 432 rtems_device_major_number major, 433 rtems_device_minor_number minor,434 void *arg487 sc = rtems_termios_device_install( 488 ctx->device_name, 489 major, 490 minor, 491 handler, 492 ctx 493 ); 494 if (sc != RTEMS_SUCCESSFUL) @{ 495 bsp_fatal(SOME_BSP_FATAL_CONSOLE_DEVICE_INSTALL); 496 @} 497 @} 498 499 return RTEMS_SUCCESSFUL; 500 @} 501 @end group 502 @end example 503 504 @subsection Opening a serial device 505 506 The @code{console_open()} function provided by @file{console-termios.c} is 507 called whenever a serial device is opened. The device registered as 508 @code{"/dev/console"} (@code{CONSOLE_DEVICE_NAME}) is opened automatically 509 during RTEMS initialization. For instance, if UART channel 2 is registered as 510 @code{"/dev/tty1"}, the @code{console_open()} entry point will be called as the 511 result of an @code{fopen("/dev/tty1", mode)} in the application. 512 513 During the first open of the device Termios will call the 514 @code{my_driver_first_open()} handler. 515 516 @example 517 @group 518 static bool my_driver_first_open( 519 rtems_termios_tty *tty, 520 rtems_libio_open_close_args_t *args 435 521 ) 436 522 @{ 437 rtems_status_code sc = RTEMS_SUCCESSFUL; 438 rtems_device_minor_number i = 0; 439 440 /* 441 * Initialize the Termios infrastructure. If Termios has already 442 * been initialized by another device driver, then this call will 443 * have no effect. 444 */ 445 rtems_termios_initialize(); 446 447 /* Initialize each device */ 448 for (i = 0; i < MY_DRIVER_DEVICE_NUMBER; ++i) @{ 449 my_driver_entry *e = &my_driver_table [i]; 450 451 /* 452 * Register this device in the file system. In order to use the 453 * console (i.e. being able to do printf, scanf etc. on stdin, 454 * stdout and stderr), some device must be registered 455 * as "/dev/console" (CONSOLE_DEVICE_NAME). 456 */ 457 sc = rtems_io_register_name (e->device_name, major, i); 458 RTEMS_CHECK_SC(sc, "Register IO device"); 459 460 /* 461 * Initialize this device and install the interrupt handler if 462 * necessary. You may also initialize the device in the first 463 * open call. 464 */ 465 @} 466 467 return RTEMS_SUCCESSFUL; 468 @} 469 @end group 470 @end example 471 472 @subsection Opening a serial device 473 474 The @code{console_open} function is called whenever a serial device is opened. 475 The device registered as @code{"/dev/console"} (@code{CONSOLE_DEVICE_NAME}) is 476 opened automatically during RTEMS initialization. For instance, if UART 477 channel 2 is registered as "/dev/tty1", the @code{console_open} entry point 478 will be called as the result of an @code{fopen("/dev/tty1", mode)} in the 479 application. 480 481 The @code{console_open} function has to inform Termios of the low-level 482 functions for serial line support. 483 484 @example 485 @group 486 rtems_device_driver console_open( 487 rtems_device_major_number major, 488 rtems_device_minor_number minor, 489 void *arg 523 my_driver_context *ctx = rtems_termios_get_device_context(tty); 524 rtems_status_code sc; 525 bool ok; 526 527 /* 528 * You may add some initialization code here. 529 */ 530 531 /* 532 * Sets the initial baud rate. This should be set to the value of 533 * the boot loader. This function accepts only exact Termios baud 534 * values. 535 */ 536 sc = rtems_termios_set_initial_baud(tty, MY_DRIVER_BAUD_RATE); 537 if (sc != RTEMS_SUCCESSFUL) @{ 538 /* Not a valid Termios baud */ 539 @} 540 541 /* 542 * Alternatively you can set the best baud. 543 */ 544 rtems_termios_set_best_baud(tty, MY_DRIVER_BAUD_RATE); 545 546 /* 547 * To propagate the initial Termios attributes to the device use 548 * this. 549 */ 550 ok = my_driver_set_attributes(tty, rtems_termios_get_termios(tty)); 551 if (!ok) @{ 552 /* This is bad */ 553 @} 554 555 /* 556 * Return true to indicate a successful set attributes, and false 557 * otherwise. 558 */ 559 return true; 560 @} 561 @end group 562 @end example 563 564 @subsection Closing a Serial Device 565 566 The @code{console_close()} provided by @file{console-termios.c} is invoked when 567 the serial device is to be closed. This entry point corresponds to the device 568 driver close entry point. 569 570 Termios will call the @code{my_driver_last_close()} handler if the last close 571 happens on the device. 572 @example 573 @group 574 static void my_driver_last_close( 575 rtems_termios_tty *tty, 576 rtems_libio_open_close_args_t *args 490 577 ) 491 578 @{ 492 struct rtems_termios_callbacks *callbacks = 493 &my_driver_callbacks_polled; 494 495 /* 496 * Check the minor number. Termios does currently not check 497 * the return value of the first open call so the minor 498 * number must be checked here. 499 */ 500 if (MY_DRIVER_IS_MINOR_INVALID(minor)) @{ 501 return RTEMS_INVALID_NUMBER; 502 @} 503 504 /* 505 * Depending on the IO mode you need to pass a different set of 506 * callback functions to Termios. 507 */ 508 if (MY_DRIVER_USES_INTERRUPTS(minor)) @{ 509 callbacks = &my_driver_callbacks_interrupt; 510 @} 511 512 return rtems_termios_open(major, minor, arg, callbacks); 513 @} 514 @end group 515 @end example 516 517 During the first open of the device Termios will call @code{my_driver_first_open}. 518 519 @example 520 @group 521 static int my_driver_first_open(int major, int minor, void *arg) 522 @{ 523 my_driver_entry *e = &my_driver_table [minor]; 524 struct rtems_termios_tty *tty = 525 ((rtems_libio_open_close_args_t *) arg)->iop->data1; 526 527 /* Check minor number */ 528 if (MY_DRIVER_IS_MINOR_INVALID(minor)) @{ 529 return -1; 530 @} 531 532 /* Connect the TTY data structure */ 533 e->tty = tty; 534 535 /* 536 * You may add some initialization code here. 537 */ 538 539 /* 540 * Sets the inital baud rate. This should be set to the value of 541 * the boot loader. 542 */ 543 return rtems_termios_set_initial_baud(e->tty, MY_DRIVER_BAUD_RATE); 544 @} 545 @end group 546 @end example 547 548 @subsection Closing a Serial Device 549 550 The @code{console_close} is invoked when the serial device is to be closed. 551 This entry point corresponds to the device driver close entry point. 552 553 This routine is responsible for notifying Termios that the serial device was 554 closed. This is done with a call to @code{rtems_termios_close}. 555 556 @example 557 @group 558 rtems_device_driver console_close( 559 rtems_device_major_number major, 560 rtems_device_minor_number minor, 561 void *arg 579 my_driver_context *ctx = rtems_termios_get_device_context(tty); 580 581 /* 582 * The driver may do some cleanup here. 583 */ 584 @} 585 @end group 586 @end example 587 588 @subsection Reading Characters from a Serial Device 589 590 The @code{console_read()} provided by @file{console-termios.c} is invoked when 591 the serial device is to be read from. This entry point corresponds to the 592 device driver read entry point. 593 594 @subsection Writing Characters to a Serial Device 595 596 The @code{console_write()} provided by @file{console-termios.c} is invoked when 597 the serial device is to be written to. This entry point corresponds to the 598 device driver write entry point. 599 600 @subsection Changing Serial Line Parameters 601 602 The @code{console_control()} provided by @file{console-termios.c} is invoked 603 when the line parameters for a particular serial device are to be changed. 604 This entry point corresponds to the device driver IO control entry point. 605 606 The application writer is able to control the serial line configuration with 607 Termios calls (such as the @code{ioctl()} command, see the Termios 608 documentation for more details). If the driver is to support dynamic 609 configuration, then it must have the @code{console_control()} piece of code. 610 Basically @code{ioctl()} commands call @code{console_control()} with the serial 611 line configuration in a Termios defined data structure. 612 613 The driver is responsible for reinitializing the device with the correct 614 settings. For this purpose Termios calls the @code{my_driver_set_attributes()} 615 handler. 616 617 @example 618 @group 619 static bool my_driver_set_attributes( 620 rtems_termios_tty *tty, 621 const struct termios *term 562 622 ) 563 623 @{ 564 return rtems_termios_close(arg); 565 @} 566 @end group 567 @end example 568 569 Termios will call the @code{my_driver_last_close} function if the last close 570 happens on the device. 571 @example 572 @group 573 static int my_driver_last_close(int major, int minor, void *arg) 574 @{ 575 my_driver_entry *e = &my_driver_table [minor]; 576 577 /* 578 * There is no need to check the minor number since it is derived 579 * from a file descriptor. The upper layer takes care that it is 580 * in a valid range. 581 */ 582 583 /* Disconnect the TTY data structure */ 584 e->tty = NULL; 585 586 /* 587 * The driver may do some cleanup here. 588 */ 589 590 return 0; 591 @} 592 @end group 593 @end example 594 595 @subsection Reading Characters from a Serial Device 596 597 The @code{console_read} is invoked when the serial device is to be read from. 598 This entry point corresponds to the device driver read entry point. 599 600 This routine is responsible for returning the content of the Termios input 601 buffer. This is done by invoking the @code{rtems_termios_read} routine. 602 603 @example 604 @group 605 rtems_device_driver console_read( 606 rtems_device_major_number major, 607 rtems_device_minor_number minor, 608 void *arg 609 ) 610 @{ 611 return rtems_termios_read(arg); 612 @} 613 @end group 614 @end example 615 616 @subsection Writing Characters to a Serial Device 617 618 The @code{console_write} is invoked when the serial device is to be written to. 619 This entry point corresponds to the device driver write entry point. 620 621 This routine is responsible for adding the requested characters to the Termios 622 output queue for this device. This is done by calling the routine 623 @code{rtems_termios_write} to add the characters at the end of the Termios 624 output buffer. 625 626 @example 627 @group 628 rtems_device_driver console_write( 629 rtems_device_major_number major, 630 rtems_device_minor_number minor, 631 void *arg 632 ) 633 @{ 634 return rtems_termios_write(arg); 635 @} 636 @end group 637 @end example 638 639 @subsection Changing Serial Line Parameters 640 641 The @code{console_control} is invoked when the line parameters for a particular 642 serial device are to be changed. This entry point corresponds to the device 643 driver io_control entry point. 644 645 The application writer is able to control the serial line configuration with 646 Termios calls (such as the @code{ioctl} command, see the Termios documentation 647 for more details). If the driver is to support dynamic configuration, then it 648 must have the @code{console_control} piece of code. Basically @code{ioctl} 649 commands call @code{console_control} with the serial line configuration in a 650 Termios defined data structure. 651 652 @example 653 @group 654 rtems_device_driver console_control( 655 rtems_device_major_number major, 656 rtems_device_minor_number minor, 657 void *arg 658 ) 659 @{ 660 return rtems_termios_ioctl(arg); 661 @} 662 @end group 663 @end example 664 665 The driver is responsible for reinitializing the device with the correct 666 settings. For this purpuse Termios calls the @code{my_driver_set_attributes} 667 function. 668 669 @example 670 @group 671 static int my_driver_set_attributes( 672 int minor, 673 const struct termios *t 674 ) 675 @{ 676 my_driver_entry *e = &my_driver_table [minor]; 677 678 /* 679 * There is no need to check the minor number since it is derived 680 * from a file descriptor. The upper layer takes care that it is 681 * in a valid range. 682 */ 683 684 /* 685 * Inspect the termios data structure and configure the device 686 * appropriately. The driver should only be concerned with the 687 * parts of the structure that specify hardware setting for the 688 * communications channel such as baud, character size, etc. 689 */ 690 691 return 0; 692 @} 693 @end group 694 @end example 624 my_driver_context *ctx = rtems_termios_get_device_context(tty); 625 626 /* 627 * Inspect the termios data structure and configure the device 628 * appropriately. The driver should only be concerned with the 629 * parts of the structure that specify hardware setting for the 630 * communications channel such as baud, character size, etc. 631 */ 632 633 /* 634 * Return true to indicate a successful set attributes, and false 635 * otherwise. 636 */ 637 return true; 638 @} 639 @end group 640 @end example
Note: See TracChangeset
for help on using the changeset viewer.