⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spi.sgml

📁 开放源码实时操作系统源码.
💻 SGML
📖 第 1 页 / 共 3 页
字号:
data transfers by calling
<function>cyg_spi_transaction_transfer</function>. This takes the same
arguments as <function>cyg_spi_transfer</function>, plus an additional
one <varname>drop_cs</varname>. A non-zero value specifies that
the device's chip select should be dropped at the end of the transfer,
otherwise the chip select remains asserted. It is essential that the
chip select be dropped in the final transfer of a transaction. If the
protocol makes this difficult then
<function>cyg_spi_transaction_tick</function> can be used to generate
dummy ticks with all chip selects dropped.
    </para>
    <para>
If the device requires additional clock ticks in the middle of a
transaction without being selected,
<function>cyg_spi_transaction_tick</function> can be used. This will
drop the device's chip select if necessary, then generate the
appropriate number of ticks. The arguments are the same as for
<function>cyg_spi_tick</function>.
    </para>
    <para>
<function>cyg_spi_transaction_end</function> should be called at the
end of a transaction. It returns the SPI bus to a quiescent state,
then unlocks it so that other threads can perform I/O.
    </para>
    <para>
A typical transaction might involve the following. First a command
should be sent to the device, consisting of four bytes. The device
will then respond with a single status byte, zero for failure,
non-zero for success. If successful then the device can accept another
n bytes of data, and will generate a 2-byte response including a
checksum. The device's chip select should remain asserted throughout.
The code for this would look something like:
    </para>
    <programlisting>
#include &lt;cyg/io/spi.h&gt;
#include &lt;cyg/hal/hal_io.h&gt;    // Defines the SPI devices
&hellip;
    cyg_spi_transaction_begin(&amp;hal_spi_eprom);
    // Interrupt-driven transfer, four bytes of command
    cyg_spi_transaction_transfer(&amp;hal_spi_eprom, 0, 4, command, NULL, 0);
    // Read back the status
    cyg_spi_transaction_transfer(&amp;hal_spi_eprom, 0, 1, NULL, status, 0);
    if (!status[0]) {
        // Command failed, generate some extra ticks to drop the chip select
        cyg_spi_transaction_tick(&amp;hal_spi_eprom, 0, 1);
    } else {
        // Transfer the data, then read back the final status. The
        // chip select should be dropped at the end of this.
        cyg_spi_transaction_transfer(&amp;hal_spi_eprom, 0, n, data, NULL, 0);
        cyg_spi_transaction_transfer(&amp;hal_spi_eprom, 0, 2, NULL, status, 1);
        // Code for checking the final status should go here 
    }
    // Transaction complete so clean up
    cyg_spi_transaction_end(&amp;hal_spi_eprom);
    </programlisting>
    <para>
A number of variations are possible. For example the command and
status could be packed into the beginning and end of two 5-byte
arrays, allowing a single transfer.
    </para>
  </refsect1>

  <refsect1 id="spi-api-config"><title>Device Configuration</title>
    <para>
The functions <function>cyg_spi_get_config</function> and
<function>cyg_spi_set_config</function> can be used to examine and
change parameters associated with SPI transfers. The only keys that
are defined for all devices are
<varname>CYG_IO_GET_CONFIG_SPI_CLOCKRATE</varname> and
<varname>CYG_IO_SET_CONFIG_SPI_CLOCKRATE</varname>. Some types of
device, for example MMC cards, support a range of clock rates. The
<structname>cyg_spi_device</structname> structure will be initialized
with a low clock rate. During system initialization the device will be
queried for the optimal clock rate, and the
<structname>cyg_spi_device</structname> should then be updated. The
argument should be a clock rate in Hertz. For example the following
code switches communication to 1Mbit/s:
    </para>
    <programlisting>
    cyg_uint32    new_clock_rate = 1000000;
    cyg_uint32    len            = sizeof(cyg_uint32);
    if (cyg_spi_set_config(&amp;hal_mmc_device,
                           CYG_IO_SET_CONFIG_SPI_CLOCKRATE,
                           (const void *)&amp;new_clock_rate, &amp;len)) {
        // Error recovery code
    }
    </programlisting>
    <para>
If an SPI bus driver does not support the exact clock rate specified
it will normally use the nearest valid one. SPI bus drivers may define
additional keys appropriate for specific hardware. This means that the
valid keys are not known by the generic code, and theoretically it is
possible to use a key that is not valid for the SPI bus to which the
device is attached. It is also possible that the argument used with
one of these keys is invalid. Hence both
<function>cyg_spi_get_config</function> and
<function>cyg_spi_set_config</function> can return error codes. The
return value will be 0 for success, non-zero for failure. The SPI bus
driver's documentation should be consulted for further details.
    </para>
    <para>
Both configuration functions will lock the bus, in the same way as
<function>cyg_spi_transfer</function>. Changing the clock rate in the
middle of a transfer or manipulating other parameters would have
unexpected consequences.
    </para>
  </refsect1>

</refentry>

<refentry id="spi-porting">
  <refmeta>
    <refentrytitle>Porting to New Hardware</refentrytitle>
  </refmeta>
  <refnamediv>
    <refname>Porting</refname>
    <refpurpose>Adding SPI support to new hardware</refpurpose>
  </refnamediv>

  <refsect1 id="spi-porting-description"><title>Description</title>
    <para>
Adding SPI support to an eCos port can take two forms. If there is
already an SPI bus driver for the target hardware then both that
driver and this generic SPI package <varname>CYGPKG_IO_SPI</varname>
should be included in the <database>ecos.db</database> target entry.
Typically the platform HAL will need to supply some platform-specific
information needed by the bus driver. In addition the platform HAL
should provide <structname>cyg_spi_device</structname> structures for
every device attached to the bus. The exact details of this depend on
the bus driver so its documentation should be consulted for further
details. If there is no suitable SPI bus driver yet then a new driver
package will have to be written.
    </para>
  </refsect1>

  <refsect1 id="spi-porting-devices"><title>Adding a Device</title>
    <para>
The generic SPI package <varname>CYGPKG_IO_SPI</varname> defines a
data structure <structname>cyg_spi_device</structname>. This contains
the information needed by the generic package, but not the additional
information needed by a bus driver to interact with the device. Each
bus driver will define a larger data structure, for example
<structname>cyg_mcf52xx_qspi_device</structname>, which contains a
<structname>cyg_spi_device</structname> as its first field. This is
analogous to C++ base and derived classes, but without any use of
virtual functions. The bus driver package should be consulted for the
details.
    </para>
    <para>
During initialization an SPI bus driver may need to know about all the
devices attached to that bus. For example it may need to know which
cpu pins should be configured as chip selects rather than GPIO pins.
To achieve this all device definitions should specify the particular
bus to which they are attached, for example:
    </para>
    <programlisting>
struct cyg_mcf52xx_qspi_device hal_spi_atod = {
    .spi_common.spi_bus = &amp;cyg_mcf52xx_qspi_bus,
    &hellip;
} CYG_SPI_DEVICE_ON_BUS(0);
    </programlisting>
    <para>
The <function>CYG_SPI_DEVICE_ON_BUS</function> macro adds information
to the structure which causes the linker to group all such structures
in a single table. The bus driver's initialization code can then
iterate over this table. 
    </para>
  </refsect1>

  <refsect1 id="spi-porting-bus"><title>Adding Bus Support</title>
    <para>
An SPI bus driver usually involves a new hardware package. This needs
to perform the following:
    </para>
    <orderedlist>
      <listitem><para>
Define a device structure which contains a
<structname>cyg_spi_device</structname> as its first element. This
should contain all the information needed by the bus driver to
interact with a device on that bus.
      </para></listitem>
      <listitem><para>
Provide functions for the following operations:
      </para>
      <simplelist type="vert" columns="1">
        <member><function>spi_transaction_begin</function></member>
        <member><function>spi_transaction_transfer</function></member>
        <member><function>spi_transaction_tick</function></member>
        <member><function>spi_transaction_end</function></member>
        <member><function>spi_get_config</function></member>
        <member><function>spi_set_config</function></member>
      </simplelist>
      <para>
These correspond to the main API functions, but can assume that the
bus is already locked so no other thread will be manipulating the bus
or any of the attached devices. Some of these operations may be no-ops.
      </para></listitem>
      <listitem><para>
Define a bus structure which contains a
<structname>cyg_spi_bus</structname> as its first element. This should
contain any additional information needed by the bus driver.
      </para></listitem>
      <listitem><para>
Optionally, instantiate the bus structure. The instance should have a
well-known name since it needs to be referenced by the device
structure initializers. For some drivers it may be best to create the
bus inside the driver package. For other drivers it may be better to
leave this to the platform HAL or the application. It depends on how
much platform-specific knowledge is needed to fill in the bus
structure.
      </para></listitem>
      <listitem><para>
Create a HAL table for the devices attached to this bus.
      </para></listitem>
      <listitem><para>
Arrange for the bus to be initialized early on during system
initialization. Typically this will happen via a prioritized static
constructor. As part of this initialization the bus driver should
invoke the <function>CYG_SPI_BUS_COMMON_INIT</function> macro on its
<structname>cyg_spi_bus</structname> field.
      </para></listitem>
      <listitem><para>
Provide the appropriate documentation, including details of how the
SPI device structures should be initialized.
      </para></listitem>
    </orderedlist>
    <para>
There are no standard SPI testcases. It is not possible to write SPI
code without knowing about the devices attached to the bus, and those
are inherently hardware-specific.
    </para>
  </refsect1>

</refentry>
</part>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -