📄 io-how-to-write-a-driver.html
字号:
<!-- Copyright (C) 2003 Red Hat, Inc. -->
<!-- This material may be distributed only subject to the terms -->
<!-- and conditions set forth in the Open Publication License, v1.0 -->
<!-- or later (the latest version is presently available at -->
<!-- http://www.opencontent.org/openpub/). -->
<!-- Distribution of the work or derivative of the work in any -->
<!-- standard (paper) book form is prohibited unless prior -->
<!-- permission is obtained from the copyright holder. -->
<HTML
><HEAD
><TITLE
>How to Write a Driver</TITLE
><meta name="MSSmartTagsPreventParsing" content="TRUE">
<META
NAME="GENERATOR"
CONTENT="Modular DocBook HTML Stylesheet Version 1.76b+
"><LINK
REL="HOME"
TITLE="eCos Reference Manual"
HREF="ecos-ref.html"><LINK
REL="UP"
TITLE="I/O Package (Device Drivers)"
HREF="io.html"><LINK
REL="PREVIOUS"
TITLE=" TTY driver"
HREF="io-tty-driver.html"><LINK
REL="NEXT"
TITLE="Serial testing with ser_filter"
HREF="io-serial-testing-with-serfilter.html"></HEAD
><BODY
CLASS="CHAPTER"
BGCOLOR="#FFFFFF"
TEXT="#000000"
LINK="#0000FF"
VLINK="#840084"
ALINK="#0000FF"
><DIV
CLASS="NAVHEADER"
><TABLE
SUMMARY="Header navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TH
COLSPAN="3"
ALIGN="center"
>eCos Reference Manual</TH
></TR
><TR
><TD
WIDTH="10%"
ALIGN="left"
VALIGN="bottom"
><A
HREF="io-tty-driver.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="80%"
ALIGN="center"
VALIGN="bottom"
></TD
><TD
WIDTH="10%"
ALIGN="right"
VALIGN="bottom"
><A
HREF="io-serial-testing-with-serfilter.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
></TABLE
><HR
ALIGN="LEFT"
WIDTH="100%"></DIV
><DIV
CLASS="CHAPTER"
><H1
><A
NAME="IO-HOW-TO-WRITE-A-DRIVER">Chapter 17. How to Write a Driver</H1
><DIV
CLASS="TOC"
><DL
><DT
><B
>Table of Contents</B
></DT
><DT
><A
HREF="io-how-to-write-a-driver.html#IO-HOW-TO-WRITE-SERIAL-INTERFACE-DRIVER"
>How to Write a Serial Hardware Interface Driver</A
></DT
><DT
><A
HREF="io-serial-testing-with-serfilter.html"
>Serial testing with ser_filter</A
></DT
></DL
></DIV
><P
>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. </P
><P
>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. </P
><P
>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. </P
><P
>The main building blocks for device drivers are found in the
include file: <TT
CLASS="FILENAME"
><cyg/io/devtab.h></TT
></P
><P
>All device drivers in <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>eCos</I
></SPAN
> are described
by a device table entry, using the <SPAN
CLASS="TYPE"
>cyg_devtab_entry_t</SPAN
> type.
The entry should be created using the <TT
CLASS="FUNCTION"
>DEVTAB_ENTRY()</TT
> macro,
like this:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
><TT
CLASS="FUNCTION"
>DEVTAB_ENTRY</TT
>(l, name, dep_name, handlers, init, lookup, priv)</PRE
></TD
></TR
></TABLE
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
>Arguments</B
></P
><DL
><DT
><TT
CLASS="PARAMETER"
><I
>l</I
></TT
></DT
><DD
><P
>The "C" label for this device table entry.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>name</I
></TT
></DT
><DD
><P
>The "C" string name for the device.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>dep_name</I
></TT
></DT
><DD
><P
>For a layered device, the "C" string name of the
device this device is built upon.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>handlers</I
></TT
></DT
><DD
><P
>A pointer to the I/O function "handlers" (see below).</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>init</I
></TT
></DT
><DD
><P
>A function called when eCos is initialized. This
function can query the device, setup hardware, etc.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>lookup</I
></TT
></DT
><DD
><P
>A function called when <TT
CLASS="FUNCTION"
>cyg_io_lookup()</TT
> is called
for this device. </P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>priv</I
></TT
></DT
><DD
><P
>A placeholder for any device specific data
required by the driver.</P
></DD
></DL
></DIV
><P
>The interface to the driver is through the <TT
CLASS="STRUCTFIELD"
><I
>handlers</I
></TT
> field. This is a pointer to
a set of functions which implement the various <TT
CLASS="FUNCTION"
>cyg_io_XXX()</TT
>
routines. This table is defined by the macro:</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>DEVIO_TABLE(l, write, read, get_config, set_config)</PRE
></TD
></TR
></TABLE
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
>Arguments</B
></P
><DL
><DT
><TT
CLASS="PARAMETER"
><I
>l</I
></TT
></DT
><DD
><P
>The "C" label for this table of handlers.</P
></DD
><DT
>write</DT
><DD
><P
>The function called as a result of
<TT
CLASS="FUNCTION"
>cyg_io_write()</TT
>.</P
></DD
><DT
>read</DT
><DD
><P
>The function called as a result of
<TT
CLASS="FUNCTION"
>cyg_io_read()</TT
>. </P
></DD
><DT
>get_config</DT
><DD
><P
>The function called as a result of
<TT
CLASS="FUNCTION"
>cyg_io_get_config()</TT
>.</P
></DD
><DT
>set_config</DT
><DD
><P
>The function called as a result of
<TT
CLASS="FUNCTION"
>cyg_io_set_config()</TT
>. </P
></DD
></DL
></DIV
><P
>When <SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>eCos</I
></SPAN
> is initialized (sometimes called
“boot” time), the <TT
CLASS="FUNCTION"
>init()</TT
> function is called
for all devices in the system. The <TT
CLASS="FUNCTION"
>init()</TT
> 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.</P
><P
>The <TT
CLASS="FUNCTION"
>lookup()</TT
> function is called whenever
the <TT
CLASS="FUNCTION"
>cyg_io_lookup()</TT
> 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.</P
><DIV
CLASS="SECTION"
><H1
CLASS="SECTION"
><A
NAME="IO-HOW-TO-WRITE-SERIAL-INTERFACE-DRIVER">How to Write a Serial Hardware Interface Driver</H1
><P
>The standard serial driver supplied with
<SPAN
CLASS="emphasis"
><I
CLASS="EMPHASIS"
>eCos</I
></SPAN
> 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. </P
><P
>The interfaces used by the serial driver and serial implementation
modules are contained in the file <TT
CLASS="FILENAME"
><cyg/io/serial.h></TT
></P
><DIV
CLASS="NOTE"
><BLOCKQUOTE
CLASS="NOTE"
><P
><B
>Note: </B
>In the sections below we use the notation <<xx>> to
mean a module specific value, referred to as “xx” below.</P
></BLOCKQUOTE
></DIV
><DIV
CLASS="SECTION"
><H2
CLASS="SECTION"
><A
NAME="AEN10880">DevTab Entry</H2
><P
>The interface module contains the devtab entry (or entries
if a single module supports more than one interface). This entry
should have the form: </P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>DEVTAB_ENTRY(<<module_name>>,
<<device_name>>,
0,
&serial_devio,
<<module_init>>,
<<module_lookup>>,
&<<serial_channel>>
);</PRE
></TD
></TR
></TABLE
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
>Arguments</B
></P
><DL
><DT
><TT
CLASS="PARAMETER"
><I
>module_name</I
></TT
></DT
><DD
><P
>The "C" label for this devtab entry</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>device_name</I
></TT
></DT
><DD
><P
>The "C" string for the
device. E.g. <TT
CLASS="FILENAME"
>/dev/serial0</TT
>.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>serial_devio</I
></TT
></DT
><DD
><P
>The table of I/O functions. This set is defined in
the hardware independent serial driver and should be used.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>module_init</I
></TT
></DT
><DD
><P
>The module initialization function.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>module_lookup</I
></TT
></DT
><DD
><P
>The device lookup function. This function
typically sets up the device for actual use, turning on
interrupts, configuring the port, etc.</P
></DD
><DT
><TT
CLASS="PARAMETER"
><I
>serial_channel</I
></TT
></DT
><DD
><P
>This table (defined below) contains the interface
between the interface module and the serial driver proper.</P
></DD
></DL
></DIV
></DIV
><DIV
CLASS="SECTION"
><H2
CLASS="SECTION"
><A
NAME="AEN10917">Serial Channel Structure</H2
><P
>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: </P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>SERIAL_CHANNEL_USING_INTERRUPTS(l, funs, dev_priv, baud,stop, parity, word_length,
flags, out_buf, out_buflen, in_buf, in_buflen)</PRE
></TD
></TR
></TABLE
><P
></P
><DIV
CLASS="VARIABLELIST"
><P
><B
>Arguments</B
></P
><DL
><DT
><TT
CLASS="PARAMETER"
><I
>l</I
></TT
></DT
><DD
><P
>The "C" label for this structure.</P
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -