Merge branch 'doc/review_api-ref_periph-spi_slave' into 'master'

Doc/review api ref periph spi slave

See merge request espressif/esp-idf!5625
This commit is contained in:
Krzysztof Budzynski 2019-10-17 18:13:09 +08:00
commit acf114895d

View file

@ -1,84 +1,108 @@
SPI Slave driver
=================
SPI Slave Driver
================
Overview
--------
SPI Slave driver is a program that controls ESP32's SPI peripherals while they function as slaves.
The ESP32 has four SPI peripheral devices, called SPI0, SPI1, HSPI and VSPI. SPI0 is entirely dedicated to
the flash cache the ESP32 uses to map the SPI flash device it is connected to into memory. SPI1 is
connected to the same hardware lines as SPI0 and is used to write to the flash chip. HSPI and VSPI
are free to use, and with the spi_slave driver, these can be used as a SPI slave, driven from a
connected SPI master.
The spi_slave driver
^^^^^^^^^^^^^^^^^^^^^
Overview of ESP32's SPI peripherals
-----------------------------------
ESP32 integrates two general purpose SPI controllers which can be used as slave nodes driven by an off-chip SPI master
- SPI2, sometimes referred to as HSPI
- SPI3, sometimes referred to as VSPI
SPI2 and SPI3 have independent signal buses with the same respective names.
The spi_slave driver allows using the HSPI and/or VSPI peripheral as a
full-duplex SPI slave. It can send/receive transactions within 64 bytes, or
make use of DMA to send/receive transactions longer than that. However, there
are some `known issues <spi_dma_known_issues>`_ when the DMA is enabled.
Terminology
^^^^^^^^^^^
-----------
The spi_slave driver uses the following terms:
The terms used in relation to the SPI slave driver are given in the table below.
* Host: The SPI peripheral inside the ESP32 initiating the SPI transmissions. One of HSPI or VSPI.
* Bus: The SPI bus, common to all SPI devices connected to a master. In general the bus consists of the
miso, mosi, sclk and optionally quadwp and quadhd signals. The SPI slaves are connected to these
signals in parallel. Each SPI slave is also connected to one CS signal.
- miso - Also known as q, this is the output of the serial stream from the ESP32 to the SPI master
- mosi - Also known as d, this is the output of the serial stream from the SPI master to the ESP32
- sclk - Clock signal. Each data bit is clocked out or in on the positive or negative edge of this signal
- cs - Chip Select. An active Chip Select delineates a single transaction to/from a slave.
* Transaction: One instance of CS going active, data transfer from and to a master happening, and
CS going inactive again. Transactions are atomic, as in they will never be interrupted by another
transaction.
================= =========================================================================================
Term Definition
================= =========================================================================================
**Host** The SPI controller peripheral external to ESP32 that initiates SPI transmissions over the bus, and acts as an SPI Master.
**Device** SPI slave device, in this case the SPI2 and SPI3 controllers. Each Device shares the MOSI, MISO and SCLK signals but is only active on the bus when the Host asserts the Device's individual CS line.
**Bus** A signal bus, common to all Devices connected to one Host. In general, a bus includes the following lines: MISO, MOSI, SCLK, one or more CS lines, and, optionally, QUADWP and QUADHD. So Devices are connected to the same lines, with the exception that each Device has its own CS line. Several Devices can also share one CS line if connected in the daisy-chain manner.
- **MISO** Master In, Slave Out, a.k.a. Q. Data transmission from a Device to Host.
- **MOSI** Master In, Slave Out, a.k.a. D. Data transmission from a Host to Device.
- **SCLK** Serial Clock. Oscillating signal generated by a Host that keeps the transmission of data bits in sync.
- **CS** Chip Select. Allows a Host to select individual Device(s) connected to the bus in order to send or receive data.
- **QUADWP** Write Protect signal. Only used for 4-bit (qio/qout) transactions.
- **QUADHD** Hold signal. Only used for 4-bit (qio/qout) transactions.
- **Assertion** The action of activating a line. The opposite action of returning the line back to inactive (back to idle) is called *de-assertion*.
**Transaction** One instance of a Host asserting a CS line, transferring data to and from a Device, and de-asserting the CS line. Transactions are atomic, which means they can never be interrupted by another transaction.
**Launch edge** Edge of the clock at which the source register *launches* the signal onto the line.
**Latch edge** Edge of the clock at which the destination register *latches in* the signal.
================= =========================================================================================
SPI transactions
^^^^^^^^^^^^^^^^
A full-duplex SPI transaction starts with the master pulling CS low. After this happens, the master
starts sending out clock pulses on the CLK line: every clock pulse causes a data bit to be shifted from
the master to the slave on the MOSI line and vice versa on the MISO line. At the end of the transaction,
the master makes CS high again.
Driver Features
---------------
.. note:: The SPI slave peripheral relies on the control of software very
much. The master shouldn't start a transaction when the slave hasn't prepared
for it. Using one more GPIO as the handshake signal to sync is a good idea.
For more details, see :ref:`transaction_interval`.
The SPI slave driver allows using the SPI2 and/or SPI3 peripherals as full-duplex Devices. The driver can send/receive transactions up to 64 bytes in length, or utilize DMA to send/receive longer transactions. However, there are some :ref:`known issues <spi_dma_known_issues>` related to DMA.
GPIO matrix and IOMUX
^^^^^^^^^^^^^^^^^^^^^
Most peripheral signals in ESP32 can connect directly to a specific GPIO,
which is called its IOMUX pin. When a peripheral signal is routed to a pin
other than its IOMUX pin, ESP32 uses the less direct GPIO matrix to make this
connection.
SPI Transactions
----------------
If the driver is configured with all SPI signals set to their specific IOMUX
pins (or left unconnected), it will bypass the GPIO matrix. If any SPI signal
is configured to a pin other than its IOMUx pin, the driver will
automatically route all the signals via the GPIO Matrix. The GPIO matrix
samples all signals at 80MHz and sends them between the GPIO and the
peripheral.
A full-duplex SPI transaction begins when the Host asserts the CS line and starts sending out clock pulses on the SCLK line. Every clock pulse, a data bit is shifted from the Host to the Device on the MOSI line and back on the MISO line at the same time. At the end of the transaction, the Host de-asserts the CS line.
When the GPIO matrix is used, setup time of MISO is more easily violated,
since the output delay of MISO signal is increased.
The attributes of a transaction are determined by the configuration structure for an SPI host acting as a slave device :cpp:type:`spi_slave_interface_config_t`, and transaction configuration structure :cpp:type:`spi_slave_transaction_t`.
.. note:: More details about influence of output delay on the maximum clock
frequency, see :ref:`timing_considerations` below.
As not every transaction requires both writing and reading data, you have a choice to configure the :cpp:type:`spi_transaction_t` structure for TX only, RX only, or TX and RX transactions. If :cpp:member:`spi_slave_transaction_t::rx_buffer` is set to NULL, the read phase will be skipped. If :cpp:member:`spi_slave_transaction_t::tx_buffer` is set to NULL, the write phase will be skipped.
IOMUX pins for SPI controllers are as below:
.. note::
A Host should not start a transaction before its Device is ready for receiving data. It is recommended to use another GPIO pin for a handshake signal to sync the Devices. For more details, see :ref:`transaction_interval`.
Driver Usage
------------
- Initialize an SPI peripheral as a Device by calling the function cpp:func:`spi_slave_initialize`. Make sure to set the correct I/O pins in the struct :cpp:type:`bus_config`. Set the unused signals to ``-1``. If transactions will be longer than 32 bytes, allow a DMA channel 1 or 2 by setting the parameter ``dma_chan`` to ``1`` or ``2`` respectively. Otherwise, set ``dma_chan`` to ``0``.
- Before initiating transactions, fill one or more :cpp:type:`spi_slave_transaction_t` structs with the transaction parameters required. Either queue all transactions by calling the function :cpp:func:`spi_slave_queue_trans` and, at a later time, query the result by using the function :cpp:func:`spi_slave_get_trans_result`, or handle all requests individually by feeding them into :cpp:func:`spi_slave_transmit`. The latter two functions will be blocked until the Host has initiated and finished a transaction, causing the queued data to be sent and received.
- (Optional) To unload the SPI slave driver, call :cpp:func:`spi_slave_free`.
Transaction Data and Master/Slave Length Mismatches
---------------------------------------------------
Normally, the data that needs to be transferred to or from a Device is read or written to a chunk of memory indicated by the :cpp:member:`rx_buffer` and :cpp:member:`tx_buffer` members of the :cpp:type:`spi_transaction_t` structure. The SPI driver can be configured to use DMA for transfers, in which case these buffers must be allocated in DMA-capable memory using ``pvPortMallocCaps(size, MALLOC_CAP_DMA)``.
The amount of data that the driver can read or write to the buffers is limited by the member :cpp:member:`spi_transaction_t::length`. However, this member does not define the actual length of an SPI transaction. A transaction's length is determined by a Host which drives the clock and CS lines. The actual length of the transmission can be read only after a transaction is finished from the member :cpp:member:`spi_slave_transaction_t::trans_len`.
If the length of the transmission is greater than the buffer length, only the initial number of bits specified in the :cpp:member:`length` member will be sent and received. In this case, :cpp:member:`trans_len` is set to :cpp:member:`length` instead of the actual transaction length. To meet the actual transaction length requirements, set :cpp:member:`length` to a value greater than the maximum :cpp:member:`trans_len` expected. If the transmission length is shorter than the buffer length, only the data equal to the length of the buffer will be transmitted.
.. Warning::
The ESP32 DMA hardware has a limit to the number of bytes sent by a Host and received by a Device. The transaction length must be longer than 8 bytes and a multiple of 4 bytes; otherwise, the SPI hardware might fail to receive the last 1 to 7 bytes.
GPIO Matrix and IO_MUX
----------------------
Most of ESP32's peripheral signals have direct connection to their dedicated IO_MUX pins. However, the signals can also be routed to any other available pins using the less direct GPIO matrix.
If at least one signal is routed through the GPIO matrix, then all signals will be routed through it. The GPIO matrix samples all signals at 80 MHz and transmits them between the GPIO and the peripheral.
If the driver is configured so that all SPI signals are either routed to their dedicated IO_MUX pins or are not connected at all, the GPIO matrix will be bypassed.
The GPIO matrix introduces flexibility of routing but also increases the input delay of the MISO signal, which makes MISO setup time violations more likely. If SPI needs to operate at high speeds, use dedicated IO_MUX pins.
.. note::
For more details about the influence of the MISO input delay on the maximum clock frequency, see :ref:`timing_considerations`.
The IO_MUX pins for SPI buses are given below.
+----------+------+------+
| Pin Name | HSPI | VSPI |
| Pin Name | SPI2 | SPI3 |
+ +------+------+
| | GPIO Number |
+==========+======+======+
@ -95,139 +119,74 @@ IOMUX pins for SPI controllers are as below:
| QUADHD | 4 | 21 |
+----------+------+------+
note * Only the first device attaching to the bus can use CS0 pin.
Using the spi_slave driver
^^^^^^^^^^^^^^^^^^^^^^^^^^^
- Initialize a SPI peripheral as a slave by calling ``spi_slave_initialize``. Make sure to set the
correct IO pins in the ``bus_config`` struct. Take care to set signals that are not needed to -1.
A DMA channel (either 1 or 2) must be given if transactions will be larger than 32 bytes, if not
the dma_chan parameter may be 0.
- To set up a transaction, fill one or more spi_transaction_t structure with any transaction
parameters you need. Either queue all transactions by calling ``spi_slave_queue_trans``, later
quering the result using ``spi_slave_get_trans_result``, or handle all requests synchroneously
by feeding them into ``spi_slave_transmit``. The latter two functions will block until the
master has initiated and finished a transaction, causing the queued data to be sent and received.
- Optional: to unload the SPI slave driver, call ``spi_slave_free``.
* Only the first Device attached to the bus can use the CS0 pin.
Transaction data and master/slave length mismatches
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Normally, data to be transferred to or from a device will be read from or written to a chunk of memory
indicated by the ``rx_buffer`` and ``tx_buffer`` members of the transaction structure. The SPI driver
may decide to use DMA for transfers, so these buffers should be allocated in DMA-capable memory using
``pvPortMallocCaps(size, MALLOC_CAP_DMA)``.
The amount of data written to the buffers is limited by the ``length`` member of the transaction structure:
the driver will never read/write more data than indicated there. The ``length`` cannot define the actual
length of the SPI transaction; this is determined by the master as it drives the clock and CS lines. The actual length
transferred can be read from the ``trans_len`` member of the ``spi_slave_transaction_t`` structure after transaction.
In case the length of the transmission is larger than the buffer length, only the start of the transmission
will be sent and received, and the ``trans_len`` is set to ``length`` instead of the actual length. It's recommended to
set ``length`` longer than the maximum length expected if the ``trans_len`` is required. In case the transmission
length is shorter than the buffer length, only data up to the length of the buffer will be exchanged.
Warning: Due to a design peculiarity in the ESP32, if the amount of bytes sent by the master or the length
of the transmission queues in the slave driver, in bytes, is not both larger than eight and dividable by
four, the SPI hardware can fail to write the last one to seven bytes to the receive buffer.
Speed and Timing considerations
Speed and Timing Considerations
-------------------------------
.. _transaction_interval:
Transaction interval
Transaction Interval
^^^^^^^^^^^^^^^^^^^^
The SPI slave is designed as s general purpose device controlled by the CPU.
Different from dedicated devices, CPU-based SPI slave doesn't have too much
pre-defined registers. All transactions should be triggered by the CPU, which
means the response speed would not be real-time, and there'll always be
noticeable intervals between transfers.
The ESP32 SPI slave peripherals are designed as general purpose Devices controlled by a CPU. As opposed to dedicated slaves, CPU-based SPI Devices have a limited number of pre-defined registers. All transactions must be handled by the CPU, which means that the transfers and responses are not real-time, and there might be noticeable latency.
During the transaction intervals, the device is not prepared for
transactions, the response is not meaningful at all. It is suggested to use
:cpp:func:`spi_slave_queue_trans` with :cpp:func:`spi_slave_get_trans_result`
to shorten the interval to half the case when using
:cpp:func:`spi_slave_transmit`.
As a solution, a Device's response rate can be doubled by using the functions :cpp:func:`spi_slave_queue_trans` and then :cpp:func:`spi_slave_get_trans_result` instead of using :cpp:func:`spi_slave_transmit`.
The master should always wait for the slave to be ready to start new
transactions. Suggested way is to use a gpio by the slave to indicate whether
it's ready. The example is in :example:`peripherals/spi_slave`.
You can also configure a GPIO pin through which the Device will signal to the Host when it is ready for a new transaction. A code example of this can be found in :example:`peripherals/spi_slave`.
SCLK frequency requirement
^^^^^^^^^^^^^^^^^^^^^^^^^^
The spi slave is designed to work under 10MHz or lower. The clock and data
cannot be recognized or received correctly if the clock is too fast or
doesn't have a 50% duty cycle.
SCLK Frequency Requirements
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Moreover, there are more requirements if the data meets the timing
requirement:
The SPI slaves are designed to operate at up to 10 MHz. The data cannot be recognized or received correctly if the clock is too fast or does not have a 50% duty cycle.
On top of that, there are additional requirements for the data to meet the timing constraints:
- Read (MOSI):
Given that the MOSI is valid right at the launch edge, the slave can
read data correctly. Luckily, it's usually the case for most masters.
The Device can read data correctly only if the data is already set at the launch edge. Although it is usually the case for most masters.
- Write (MISO):
To meet the requirement that MISO is stable before the next latch edge of
SPI clock, the output delay of MISO signal should be shorter than half a
clock. The output delay and frequency limitation (given that the clock is
balanced) of different cases are as below :
The output delay of the MISO signal needs to be shorter than half of a clock cycle period so that the MISO line is stable before the next latch edge. Given that the clock is balanced, the output delay and frequency limitations in different cases are given below.
+-------------+---------------------------+------------------------+
| | Output delay of MISO (ns) | Freq. limit (MHZ) |
| | Output delay of MISO (ns) | Freq. limit (MHz) |
+=============+===========================+========================+
| IOMUX | 43.75 | <11.4 |
| IO_MUX | 43.75 | <11.4 |
+-------------+---------------------------+------------------------+
| GPIO matrix | 68.75 | <7.2 |
+-------------+---------------------------+------------------------+
Note:
1. Random error will happen if the frequency exactly equals the
limitation
2. The clock uncertainty between master and slave (12.5ns) is
included.
3. The output delay is measured under ideal case (free of load). When
the loading of MISO pin is too heavy, the output delay will be longer,
and the maximum allowed frequency will be lower.
1. If the frequency is equal to the limitation, it can lead to random errors.
2. The clock uncertainty between Host and Device (12.5ns) is included.
3. The output delay is measured under ideal circumstances (no load). If the MISO pin is heavily loaded, the output delay will be longer, and the maximum allowed frequency will be lower.
Exception: The frequency is allowed to be higher if the master has more tolerance for the MISO setup time, e.g., latch data at the next edge than expected, or configurable latching time.
There is an exceptions: The frequency is allowed to be higher if the
master has more toleration for the MISO setup time, e.g. latch data at
the next edge than expected, or configurable latching time.
.. _spi_dma_known_issues:
Restrictions and Known issues
-------------------------------
Restrictions and Known Issues
-----------------------------
1. If the DMA is enabled, the rx buffer should be WORD aligned, i.e. Start
from the boundary of 32-bit and have length of multiples of 4 bytes. Or the
DMA may write incorrectly or out of the boundary.The driver will check for
this.
1. If DMA is enabled, the rx buffer should be word-aligned (starting from a 32-bit boundary and having a length of multiples of 4 bytes). Otherwise, DMA may write incorrectly or not in a boundary aligned manner. The driver reports an error if this condition is not satisfied.
Also, master should write lengths which are a multiple of 4 bytes. Data
longer than that will be discarded.
Also, a Host should write lengths that are multiples of 4 bytes. The data with inappropriate lengths will be discarded.
2. Furthurmore, the DMA requires a spi mode 1/3 timing. When using spi mode
0/2, the MISO signal has to output half a clock earlier to meet the timing.
The new timing is as below:
2. Furthermore, DMA requires SPI modes 1 and 3. For SPI modes 0 and 2, the MISO signal has to be launched half a clock cycle earlier to meet the timing. The new timing is as follows:
.. image:: /../_static/spi_slave_miso_dma.png
The hold time after the latch edge is 68.75ns (when GPIO matrix is
bypassed), no longer half a SPI clock. The master should sample immediately
at the latch edge, or communicate in mode 1/3. Or just initial the spi
slave without DMA.
If DMA is enabled, a Device's launch edge is half of an SPI clock cycle ahead of the normal time, shifting to the Master's actual latch edge. In this case, if the GPIO matrix is bypassed, the hold time for data sampling is 68.75 ns and no longer a half of an SPI clock cycle. If the GPIO matrix is used, the hold time will increase to 93.75 ns. The Host should sample the data immediately at the latch edge or communicate in SPI modes 1 or 3. If your Host cannot meet these timing requirements, initialize your Device without DMA.
Application Example
-------------------
Slave/master communication: :example:`peripherals/spi_slave`.
The code example for Device/Host communication can be found in the :example:`peripherals/spi_slave` directory of ESP-IDF examples.
API Reference
-------------