X-Git-Url: https://git.karo-electronics.de/?a=blobdiff_plain;f=doc%2Fhtml%2Fref%2Fio-how-to-write-a-driver.html;fp=doc%2Fhtml%2Fref%2Fio-how-to-write-a-driver.html;h=0000000000000000000000000000000000000000;hb=739c21725ce2774a605a0f1de3edaac2c43aea0f;hp=82be9e42286bd3c2948900a14d87fac1955ff4fe;hpb=ae71e0fa8076a1b59600b3a0ea10155a2cb534ae;p=karo-tx-redboot.git diff --git a/doc/html/ref/io-how-to-write-a-driver.html b/doc/html/ref/io-how-to-write-a-driver.html deleted file mode 100644 index 82be9e42..00000000 --- a/doc/html/ref/io-how-to-write-a-driver.html +++ /dev/null @@ -1,1154 +0,0 @@ - - - - - - - - -How to Write a Driver -
eCos Reference Manual
PrevNext

Chapter 17. How to Write a Driver

Table of Contents
How to Write a Serial Hardware Interface Driver
Serial testing with ser_filter

A device driver is nothing more than a -named entity that supports the basic I/O functions - read, write, get -config, and set config. Typically a device driver also uses and -manages interrupts from the device. While the interface is generic and -device driver independent, the actual driver implementation is -completely up to the device driver designer.

That said, the reason for using a device driver is to provide -access to a device from application code in as general purpose a -fashion as reasonable. Most driver writers are also concerned with -making this access as simple as possible while being as efficient -as possible.

Most device drivers are concerned with the movement of information, -for example data bytes along a serial interface, or packets in a -network. In order to make the most efficient use of system resources, -interrupts are used. This will allow other application processing -to take place while the data transfers are under way, with interrupts -used to indicate when various events have occurred. For example, -a serial port typically generates an interrupt after a character -has been sent “down the wire” and the interface -is ready for another. It makes sense to allow further application -processing while the data is being sent since this can take quite -a long time. The interrupt can be used to allow the driver to send -a character as soon as the current one is complete, without any -active participation by the application code.

The main building blocks for device drivers are found in the -include file: <cyg/io/devtab.h>

All device drivers in eCos are described -by a device table entry, using the cyg_devtab_entry_t type. -The entry should be created using the DEVTAB_ENTRY() macro, -like this:

DEVTAB_ENTRY(l, name, dep_name, handlers, init, lookup, priv)

Arguments

l

The "C" label for this device table entry.

name

The "C" string name for the device.

dep_name

For a layered device, the "C" string name of the - device this device is built upon.

handlers

A pointer to the I/O function "handlers" (see below).

init

A function called when eCos is initialized. This - function can query the device, setup hardware, etc.

lookup

A function called when cyg_io_lookup() is called - for this device.

priv

A placeholder for any device specific data - required by the driver.

The interface to the driver is through the handlers field. This is a pointer to -a set of functions which implement the various cyg_io_XXX() -routines. This table is defined by the macro:

DEVIO_TABLE(l, write, read, get_config, set_config)

Arguments

l

The "C" label for this table of handlers.

write

The function called as a result of - cyg_io_write().

read

The function called as a result of - cyg_io_read().

get_config

The function called as a result of - cyg_io_get_config().

set_config

The function called as a result of - cyg_io_set_config().

When eCos is initialized (sometimes called -“boot” time), the init() function is called -for all devices in the system. The init() function is -allowed to return an error in which case the device will be placed -“off line” and all I/O requests to that device will be -considered in error.

The lookup() function is called whenever -the cyg_io_lookup() function -is called with this device name. The lookup function may cause the device -to come “on line” which would then allow I/O -operations to proceed. Future versions of the I/O system -will allow for other states, including power saving modes, -etc.

How to Write a Serial Hardware Interface Driver

The standard serial driver supplied with -eCos is structured as a hardware independent -portion and a hardware dependent interface module. To add support for -a new serial port, the user should be able to use the existing -hardware independent portion and just add their own interface driver which handles the details of the -actual device. The user should have no need to change the hardware -independent portion.

The interfaces used by the serial driver and serial implementation -modules are contained in the file <cyg/io/serial.h>

Note: In the sections below we use the notation <<xx>> to -mean a module specific value, referred to as “xx” below.

DevTab Entry

The interface module contains the devtab entry (or entries -if a single module supports more than one interface). This entry -should have the form:

DEVTAB_ENTRY(<<module_name>>, 
-             <<device_name>>,
-             0,
-             &serial_devio, 
-             <<module_init>>, 
-             <<module_lookup>>,
-             &<<serial_channel>>
-            );

Arguments

module_name

The "C" label for this devtab entry

device_name

The "C" string for the - device. E.g. /dev/serial0.

serial_devio

The table of I/O functions. This set is defined in - the hardware independent serial driver and should be used.

module_init

The module initialization function.

module_lookup

The device lookup function. This function - typically sets up the device for actual use, turning on - interrupts, configuring the port, etc.

serial_channel

This table (defined below) contains the interface - between the interface module and the serial driver proper.

Serial Channel Structure

Each serial device must have a “serial channel”. -This is a set of data which describes all operations on the device. -It also contains buffers, etc., if the device is to be buffered. -The serial channel is created by the macro:

SERIAL_CHANNEL_USING_INTERRUPTS(l, funs, dev_priv, baud,stop, parity, word_length,
-                                flags, out_buf, out_buflen, in_buf, in_buflen)

Arguments

l

The "C" label for this structure.

funs

The set of interface functions (see below).

dev_priv

A placeholder for any device specific data for - this channel.

baud

The initial baud rate value - (cyg_serial_baud_t).

stop

The initial stop bits value - (cyg_serial_stop_bits_t).

parity

The initial parity mode value - (cyg_serial_parity_t).

word_length

The initial word length value - (cyg_serial_word_length_t).

flags

The initial driver flags value.

out_buf

Pointer to the output - buffer. NULL if none required.

out_buflen

The length of the output buffer.

in_buf

pointer to the input - buffer. NULL if none required.

in_buflen

The length of the input buffer.

If either buffer length is zero, no buffering will take place -in that direction and only polled mode functions will be used.

The interface from the hardware independent driver into the -hardware interface module is contained in the funs table. -This is defined by the macro:

Serial Functions Structure

SERIAL_FUNS(l, putc, getc, set_config, start_xmit, stop_xmit)

Arguments

l

The "C" label for this structure.

putc

bool (*putc)(serial_channel *priv, unsigned char - c)

This function sends one character to the interface. It should - return true if the character is actually consumed. It should - return false if there is no space in the interface -

getc

unsigned char (*getc)(serial_channel *priv)

This function fetches one character from the interface. It will - be only called in a non-interrupt driven mode, thus it should - wait for a character by polling the device until ready. -

set_config

bool (*set_config)(serial_channel - *priv,cyg_serial_info_t *config)

This function is used to configure the port. It should return - true if the hardware is updated to match the desired - configuration. It should return false if the port cannot - support some parameter specified by the given - configuration. E.g. selecting 1.5 stop bits and 8 data bits is - invalid for most serial devices and should not be allowed. -

start_xmit

void (*start_xmit)(serial_channel *priv)

In interrupt mode, turn on the transmitter and allow for - transmit interrupts. -

stop_xmit

void (*stop_xmit)(serial_channel *priv)

In interrupt mode, turn off the transmitter.

Callbacks

The device interface module can execute functions in the -hardware independent driver via chan->callbacks. -These functions are available:

void (*serial_init)( serial_channel *chan )

This function is used to initialize the serial channel. It -is only required if the channel is being used in interrupt -mode.

void (*xmt_char)( serial_channel *chan )

This function would be called from an interrupt handler after a -transmit interrupt indicating that additional characters may be -sent. The upper driver will call the putc -function as appropriate to send more data to the device.

void (*rcv_char)( serial_channel *chan, unsigned char c )

This function is used to tell the driver that a character has arrived -at the interface. This function is typically called from the interrupt -handler.

Furthermore, if the device has a FIFO it should require the hardware -independent driver to provide block transfer functionality (driver CDL -should include "implements -CYGINT_IO_SERIAL_BLOCK_TRANSFER"). In that case, the following -functions are available as well:

bool (*data_xmt_req)(serial_channel *chan,
-                     int space,
-                     int* chars_avail,
-                     unsigned char** chars)
-void (*data_xmt_done)(serial_channel *chan)

Instead of calling xmt_char() to get a single -character for transmission at a time, the driver should call -data_xmt_req() in a loop, requesting character -blocks for transfer. Call with a space argument of how much space -there is available in the FIFO.

If the call returns true, the driver can read -chars_avail characters from -chars and copy them into the FIFO.

If the call returns false, there are -no more buffered characters and the driver should continue without -filling up the FIFO.

When all data has been unloaded, the -driver must call data_xmt_done().

bool (*data_rcv_req)(serial_channel *chan,
-                     int avail,
-                     int* space_avail,
-                     unsigned char** space)
-void (*data_rcv_done)(serial_channel *chan)

Instead of calling rcv_char() with a single -character at a time, the driver should call -data_rcv_req() in a loop, requesting space to -unload the FIFO to. avail is the number of -characters the driver wishes to unload.

If the call returns true, the driver can copy -space_avail characters to -space.

If the call returns false, the input buffer is -full. It is up to the driver to decide what to do in that case -(callback functions for registering overflow are being planned for -later versions of the serial driver).

When all data has been unloaded, the driver must call -data_rcv_done().


PrevHomeNext
TTY driverUpSerial testing with ser_filter
\ No newline at end of file