📄 i2c-porting.html
字号:
return result;
}
CYG_I2C_BITBANG_BUS(hal_alaia_i2c_bus, &hal_alaia_i2c_bitbang);
</PRE
></TD
></TR
></TABLE
><P
>This gives a structure <CODE
CLASS="VARNAME"
>hal_alaia_i2c_bus</CODE
> which can
be used when defining the <CODE
CLASS="VARNAME"
>cyg_i2c_device</CODE
>
structures. The second argument specifies the function which will
do the actual bit-banging. It takes two arguments. The first
identifies the bus, which can be useful if the hardware has multiple
I2C buses. The second specifies the bit-bang operation that should be
performed. To understand these operations consider how I2C devices
should be wired up according to the specification:
</P
><DIV
CLASS="INFORMALFIGURE"
><P
></P
><A
NAME="AEN8900"
></A
><DIV
CLASS="MEDIAOBJECT"
><P
><IMG
SRC="i2c_hw.png"
ALIGN="CENTER"></P
></DIV
><P
></P
></DIV
><P
>Master and slave devices are interfaced to the bus in exactly the same
way. The default state of the bus is to have both lines high via the
pull-up resistors. Any device on the bus can lower either line, when
allowed to do so by the protocol. Usually the SDA line only changes
while SCL is low, but the start and stop conditions involve SDA
changing while SCL is high. All devices have the ability to both read
and write both lines. In reality not all bit-banged hardware works
quite like this. Instead just two GPIO pins are used, and these are
switched between input and output mode as required.
</P
><P
>The bitbang function should support the following operations:
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_INIT</TT
></DT
><DD
><P
>This will be called during system initialization, as a side effect of
a prioritized C++ static constructor. The bitbang function should
ensure that both SCL and SDA are driven high.
</P
></DD
><DT
><TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SCL_HIGH</TT
>, <TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SCL_LOW</TT
>, <TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SDA_HIGH</TT
>, <TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SDA_LOW</TT
></DT
><DD
><P
>These operations simply set the appropriate lines high or low.
</P
></DD
><DT
><TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SCL_HIGH_CLOCKSTRETCH</TT
></DT
><DD
><P
>In its simplest form this operation should simply set the SCL line
high, indicating that the data on the SDA line is stable. However
there is a complication: if a device is not ready yet then it can
throttle back the master by keeping the SCL line low. This is known as
clock-stretching. Hence for this operation the bitbang function should
allow the SCL line to float high, then poll it until it really has
become high. If a single pin is used for the SCL line then this pin
should be turned back into a high output at the end of the call.
</P
></DD
><DT
><TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SCL_LOW_SDA_INPUT</TT
></DT
><DD
><P
>This is used when there is a change of direction and the slave device
is about to start driving the SDA line. This can be significant if a
single pin is used to handle both input and output of SDA, to avoid
a situation where both the master and the slave are driving the SDA
line for an extended period of time. The operation combines dropping
the SCL line and switching SDA to an input in an atomic or near-atomic
operation.
</P
></DD
><DT
><TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SDA_READ</TT
></DT
><DD
><P
>The SDA line is currently set as an input and the bitbang function
should sample and return the current state.
</P
></DD
></DL
></DIV
><P
>The bitbang function returns a boolean. For most operations this
return value is ignored. For
<TT
CLASS="LITERAL"
>CYG_I2C_BITBANG_SDA_READ</TT
> it should be the current
level of the SDA line.
</P
><P
>Depending on the hardware some care may have to be taken when
manipulating the GPIO pins. Although the I2C subsystem performs the
required locking at the bus level, the device registers controlling
the GPIO pins may get used by other subsystems or by the application.
It is the responsibility of the bitbang function to perform
appropriate locking, whether via a mutex or by briefly disabling
interrupts around the register accesses.
</P
></DIV
><DIV
CLASS="REFSECT1"
><A
NAME="I2C-PORTING-BUS"
></A
><H2
>Full Bus Driver</H2
><P
>If the processor has dedicated I2C hardware then usually this will
involve a separate device driver package in the
<TT
CLASS="FILENAME"
>devs/i2c</TT
> hierarchy of the eCos component
repository. That package should also be included in the appropriate
<SPAN
CLASS="DATABASE"
>ecos.db</SPAN
> target entry or entries. The device
driver may exist already, or it may have to be written from scratch.
</P
><P
>A new I2C driver basically involves creating an
<CODE
CLASS="STRUCTNAME"
>cyg_i2c_bus</CODE
> structure. The device driver
should supply the following fields:
</P
><P
></P
><DIV
CLASS="VARIABLELIST"
><DL
><DT
><CODE
CLASS="FUNCTION"
>i2c_init_fn</CODE
></DT
><DD
><P
>This function will be called during system initialization to set up
the I2C hardware. The generic I2C code creates a static object with a
prioritized constructor, and this constructor will invoke the init
functions for the various I2C buses in the system.
</P
></DD
><DT
><CODE
CLASS="FUNCTION"
>i2c_tx_fn</CODE
>, <CODE
CLASS="FUNCTION"
>i2c_rx_fn</CODE
>, <CODE
CLASS="FUNCTION"
>i2c_stop_fn</CODE
></DT
><DD
><P
>These functions implement the core I2C functionality. The arguments
and results are the same as for the transaction functions
<CODE
CLASS="FUNCTION"
>cyg_i2c_transaction_tx</CODE
>,
<CODE
CLASS="FUNCTION"
>cyg_i2c_transaction_rx</CODE
> and
<CODE
CLASS="FUNCTION"
>cyg_i2c_transaction_stop</CODE
>.
</P
></DD
><DT
><SPAN
CLASS="TYPE"
>void*</SPAN
> <CODE
CLASS="VARNAME"
>i2c_extra</CODE
></DT
><DD
><P
>This field holds any extra information that may be needed by the
device driver. Typically it will be a pointer to some driver-specific
data structure.
</P
></DD
></DL
></DIV
><P
>To assist with instantiating a <CODE
CLASS="STRUCTNAME"
>cyg_i2c_bus</CODE
>
object the header file <TT
CLASS="FILENAME"
>cyg/io/i2c.h</TT
> provides a macro. Typical
usage would be:
</P
><TABLE
BORDER="5"
BGCOLOR="#E0E0F0"
WIDTH="70%"
><TR
><TD
><PRE
CLASS="PROGRAMLISTING"
>struct xyzzy_data {
…
} xyzzy_object;
static void
xyzzy_i2c_init(struct cyg_i2c_bus* bus)
{
…
}
static cyg_uint32
xyzzy_i2c_tx(const cyg_i2c_device* dev,
cyg_bool send_start,
const cyg_uint8* tx_data, cyg_uint32 count,
cyg_bool send_stop)
{
…
}
static cyg_uint32
xyzzy_i2c_rx(const cyg_i2c_device* dev,
cyg_bool send_start,
cyg_uint8* rx_data, cyg_uint32 count,
cyg_bool send_nack, cyg_bool send_stop)
{
…
}
static void
xyzzy_i2c_stop(const cyg_i2c_device* dev)
{
…
}
CYG_I2C_BUS(cyg_i2c_xyzzy_bus,
&xyzzy_i2c_init,
&xyzzy_i2c_tx,
&xyzzy_i2c_rx,
&xyzzy_i2c_stop,
(void*) &xyzzy_object);
</PRE
></TD
></TR
></TABLE
><P
>The generic I2C code contains these functions for a bit-banged I2C bus
device. It can be used as a starting point for new drivers. Note that
the bit-bang code uses the <CODE
CLASS="VARNAME"
>i2c_extra</CODE
> field to hold
the hardware-specific bitbang function rather than a pointer to some
data structure.
</P
></DIV
><DIV
CLASS="NAVFOOTER"
><HR
ALIGN="LEFT"
WIDTH="100%"><TABLE
SUMMARY="Footer navigation table"
WIDTH="100%"
BORDER="0"
CELLPADDING="0"
CELLSPACING="0"
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
><A
HREF="i2c-api.html"
ACCESSKEY="P"
>Prev</A
></TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="ecos-ref.html"
ACCESSKEY="H"
>Home</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
><A
HREF="io-can.html"
ACCESSKEY="N"
>Next</A
></TD
></TR
><TR
><TD
WIDTH="33%"
ALIGN="left"
VALIGN="top"
>I2C Interface</TD
><TD
WIDTH="34%"
ALIGN="center"
VALIGN="top"
><A
HREF="io-i2c.html"
ACCESSKEY="U"
>Up</A
></TD
><TD
WIDTH="33%"
ALIGN="right"
VALIGN="top"
>CAN Support</TD
></TR
></TABLE
></DIV
></BODY
></HTML
>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -