📄 i2c.sgml
字号:
<!-- DOCTYPE part PUBLIC "-//OASIS//DTD DocBook V3.1//EN" -->
<!-- {{{ Banner -->
<!-- =============================================================== -->
<!-- -->
<!-- i2c.sgml -->
<!-- -->
<!-- Generic I2C documentation. -->
<!-- -->
<!-- =============================================================== -->
<!-- ####COPYRIGHTBEGIN#### -->
<!-- -->
<!-- =============================================================== -->
<!-- Copyright (C) 2004 eCosCentric Limited -->
<!-- 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 obtained from the copyright holder -->
<!-- =============================================================== -->
<!-- -->
<!-- ####COPYRIGHTEND#### -->
<!-- =============================================================== -->
<!-- #####DESCRIPTIONBEGIN#### -->
<!-- -->
<!-- Author(s): bartv -->
<!-- Date: 2004/10/05 -->
<!-- -->
<!-- ####DESCRIPTIONEND#### -->
<!-- =============================================================== -->
<!-- }}} -->
<part id="io-i2c"><title>I2C Support</title>
<refentry id="i2c">
<refmeta>
<refentrytitle>Overview</refentrytitle>
</refmeta>
<refnamediv>
<refname>Overview</refname>
<refpurpose>eCos Support for I2C, the Inter IC Bus</refpurpose>
</refnamediv>
<refsect1 id="i2c-description"><title>Description</title>
<para>
The Inter IC Bus (I2C) is one of a number of serial bus technologies.
It can be used to connect a processor to one or more peripheral chips,
for example analog-to-digital convertors or real time clocks, using
only a small number of pins and PCB tracks. The technology was
originally developed by Philips Semiconductors but is supported by
many other vendors. The bus specification is freely available.
</para>
<para>
In a typical I2C system the processor acts as the I2C bus master. The
peripheral chips act as slaves. The bus consists of just two wires:
SCL carries a clock signal generated by the master, and SDA is a
bi-directional data line. The normal clock frequency is 100KHz. Each
slave has a 7-bit address. With some chips the address is hard-wired,
and it is impossible to have two of these chips on the same bus. With
other chips it is possible to choose between one of a small number of
addresses by connecting spare pins to either VDD or GND.
</para>
<para>
An I2C data transfer involves a number of stages:
</para>
<orderedlist>
<listitem><para>
The bus master generates a start condition, a high-to-low transition
on the SDA line while SCL is kept high. This signalling cannot occur
during data transfer.
</para></listitem>
<listitem><para>
The bus master clocks the 7-bit slave address onto the SDA line,
followed by a direction bit to distinguish between reads and writes.
</para></listitem>
<listitem><para>
The addressed device acknowledges. If the master does not see an
acknowledgement then this suggests it is using the wrong address for
the slave device.
</para></listitem>
<listitem><para>
If the master is transmitting data to the slave then it will send this
data one byte at a time. The slave acknowledges each byte. If the
slave is unable to accept more data, for example because it has run
out of buffer space, then it will generate a nack and the master
should stop sending.
</para></listitem>
<listitem><para>
If the master is receiving data from the slave then the slave will
send this data one byte at a time. The master should acknowledge each
byte, until the last one. When the master has received all the data it
wants it should generate a nack and the slave will stop sending. This
nack is essential because it causes the slave to stop driving the SDA
line, releasing it back to the master.
</para></listitem>
<listitem><para>
It is possible to switch direction in a single transfer, using what is
known as a repeated start. This involves generating another start
condition, sending the 7-bit address again, followed by a new
direction bit.
</para></listitem>
<listitem><para>
At the end of a transfer the master should generate a stop condition,
a low-to-high transition on the SDA line while SCL is kept high. Again
this signalling does not occur at other times.
</para></listitem>
</orderedlist>
<para>
There are a number of extensions. The I2C bus supports multiple bus
masters and there is an arbitration procedure to allow a master to
claim the bus. Some devices can have 10-bit addresses rather than
7-bit addresses. There is a fast mode operating at 400KHz instead of
the usual 100KHz, and a high-speed mode operating at 3.4MHz. Currently
most I2C-based systems do not involve any of these extensions.
</para>
<para>
At the hardware level I2C bus master support can be implemented in one
of two ways. Some processors provide a dedicated I2C device, with the
hardware performing much of the work. On other processors the I2C
device is implemented in software, by bit-banging some GPIO pins. The
latter approach can consume a significant number of cpu cycles, but is
often acceptable because only occasional access to the I2C devices is
needed.
</para>
</refsect1>
<refsect1 id="i2c-ecos-implementation"><title>eCos Support for I2C</title>
<para>
The eCos I2C support for any given platform is spread over a number of
different packages:
</para>
<itemizedlist>
<listitem><para>
This package, <varname>CYGPKG_IO_I2C</varname>, exports a generic API
for accessing devices attached to an I2C bus. This API handles issues
such as locking between threads. The package does not contain any
hardware-specific code. Instead it will use a separate I2C bus driver
to handle the hardware, and it defines the interface that such bus
drivers should provide. The package only provides support for a bus
master, not for acting as a slave device.
</para>
<para>
<varname>CYGPKG_IO_I2C</varname> also provides the
hardware-independent portion of a bit-banged bus implementation. This
needs to be complemented by a hardware-specific function that actually
manipulates the SDA and SCL lines.
</para></listitem>
<listitem><para>
If the processor has a dedicated I2C device then there will be a bus
driver package for that hardware. The processor may be used on
many different platforms and the same bus driver can be used on each one.
The actual I2C devices attached to the bus will vary from one platform to
the next.
</para></listitem>
<listitem><para>
The generic API depends on <structname>cyg_i2c_device</structname>
data structures. These contain the information needed by a bus driver,
for example the device address. Usually the data structures are
provided by the platform HAL since it is that package which knows
about all the devices on the platform.
</para>
<para>
On some development boards the I2C lines are brought out to expansion
connectors, allowing end users to add extra devices. In such cases the
platform HAL may not know about all the devices on the board. Data
structures for the additional devices can instead be supplied by
application code.
</para></listitem>
<listitem><para>
If the board uses a bit-banged bus then typically the platform HAL
will also instantiate the bus instance, providing the function that
handles the low-level SDA and SCL manipulation. Usually this code
cannot be shared because each board may use different GPIO pins for
driving SCL and SDA, so the code belongs in the platform HAL rather
than in a separate package.
</para></listitem>
<listitem><para>
Some types of I2C devices may have their own driver package. For
example a common type of I2C device is a battery-backed wallclock, and
eCos defines how these devices should be supported. Such an I2C device
will have its own wallclock device driver and the device will not be
accessed directly by application code. For other types of device eCos
does not define an API and there will not be separate device driver
packages. Instead application code is expected to use the
<structname>cyg_i2c_device</structname> structures directly to access
the hardware.
</para></listitem>
</itemizedlist>
<para>
Typically all appropriate packages will be loaded automatically when
you configure eCos for a given platform. If the application does not use
any of the I2C I/O facilities, directly or indirectly, then linker
garbage collection should eliminate all unnecessary code and data. All
necessary initialization should happen automatically. However the
exact details may depend on the platform, so the platform HAL
documentation should be checked for further details.
</para>
<para>
There is one important exception to this: if the I2C devices are
attached to an expansion connector then the platform HAL will not know
about these devices. Instead more work will have to be done by
application code.
</para>
</refsect1>
</refentry>
<refentry id="i2c-api">
<refmeta>
<refentrytitle>I2C Interface</refentrytitle>
</refmeta>
<refnamediv>
<refname>I2C Functions</refname>
<refpurpose>allow applications and other packages to access I2C devices</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>
#include <cyg/io/i2c.h>
</funcsynopsisinfo>
<funcprototype>
<funcdef>cyg_uint32 <function>cyg_i2c_tx</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
<paramdef>const cyg_uint8* <parameter>tx_data</parameter></paramdef>
<paramdef>cyg_uint32 <parameter>count</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>cyg_uint32 <function>cyg_i2c_rx</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
<paramdef>cyg_uint8* <parameter>rx_data</parameter></paramdef>
<paramdef>cyg_uint32 <parameter>count</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>void <function>cyg_i2c_transaction_begin</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>cyg_bool <function>cyg_i2c_transaction_begin_nb</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>cyg_uint32 <function>cyg_i2c_transaction_tx</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
<paramdef>cyg_bool <parameter>send_start</parameter></paramdef>
<paramdef>const cyg_uint8* <parameter>tx_data</parameter></paramdef>
<paramdef>cyg_uint32 <parameter>count</parameter></paramdef>
<paramdef>cyg_bool <parameter>send_stop</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>cyg_uint32 <function>cyg_i2c_transaction_rx</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
<paramdef>cyg_bool <parameter>send_start</parameter></paramdef>
<paramdef>cyg_uint8* <parameter>rx_data</parameter></paramdef>
<paramdef>cyg_uint32 <parameter>count</parameter></paramdef>
<paramdef>cyg_bool <parameter>send_nack</parameter></paramdef>
<paramdef>cyg_bool <parameter>send_stop</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>void <function>cyg_i2c_transaction_stop</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>void <function>cyg_i2c_transaction_end</function></funcdef>
<paramdef>const cyg_i2c_device* <parameter>device</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1 id="i2c-api-description"><title>Description</title>
<para>
All I2C functions take a pointer to a
<structname>cyg_i2c_device</structname> structure as their first
argument. These structures are usually provided by the platform HAL.
They contain the information needed by the I2C bus driver to interact
with the device, for example the device address.
</para>
<para>
An I2C transaction involves the following stages:
</para>
<orderedlist>
<listitem><para>
Perform thread-level locking on the bus. Only one thread at a time is
allowed to access an I2C bus. This eliminates the need to worry about
locking at the bus driver level. If a platform involves multiple I2C
buses then each one will have its own lock.
</para></listitem>
<listitem><para>
Generate a start condition, send the address and direction bit, and
wait for an acknowledgement from the addressed device.
</para></listitem>
<listitem><para>
Either transmit data to or receive data from the addressed device.
</para></listitem>
<listitem><para>
The previous two steps may be repeated several times, allowing data to
move in both directions during a single transfer.
</para></listitem>
<listitem><para>
Generate a stop condition, ending the current data transfer. It is
now possible to start another data transfer while the bus is still
locked, if desired.
</para></listitem>
<listitem><para>
End the transaction by unlocking the bus, allowing other threads to
access other devices on the bus.
</para></listitem>
</orderedlist>
<para>
The simple functions <function>cyg_i2c_tx</function> and
<function>cyg_i2c_rx</function> perform all these steps in a single
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -