|
|
@@ -1,10 +1,11 @@
|
|
|
SPI Master Driver
|
|
|
=================
|
|
|
+:link_to_translation:`zh_CN:[中文]`
|
|
|
|
|
|
SPI Master driver is a program that controls {IDF_TARGET_NAME}'s SPI peripherals while they function as masters.
|
|
|
|
|
|
|
|
|
-Overview of {IDF_TARGET_NAME}'s SPI peripherals
|
|
|
+Overview of {IDF_TARGET_NAME}'s SPI Peripherals
|
|
|
-----------------------------------------------
|
|
|
|
|
|
{IDF_TARGET_SPI2_CS_NUM:default="6", esp32="3"}
|
|
|
@@ -16,8 +17,7 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals
|
|
|
|
|
|
.. only:: esp32
|
|
|
|
|
|
- There are quite a few limitations when using SPI Master driver on the SPI1 bus, see
|
|
|
- :ref:`spi_master_on_spi1_bus`.
|
|
|
+ There are quite a few limitations when using SPI Master driver on the SPI1 bus, see :ref:`spi_master_on_spi1_bus`.
|
|
|
|
|
|
.. only:: not esp32
|
|
|
|
|
|
@@ -25,49 +25,69 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals
|
|
|
|
|
|
.. only:: esp32
|
|
|
|
|
|
- - SPI2 and SPI3 are general purpose SPI controllers, sometimes referred to as HSPI and VSPI, respectively. They are open to users. SPI2 and SPI3 have independent bus signals with the same respective names. Each bus has three CS lines to drive up to same number of SPI slaves.
|
|
|
+ - SPI2 and SPI3 are general-purpose SPI controllers, sometimes referred to as HSPI and VSPI. They are open to users. SPI2 and SPI3 have independent bus signals with the same respective names. Each bus has three CS lines to drive up to a same number of SPI slaves.
|
|
|
|
|
|
.. only:: esp32s2 or esp32s3
|
|
|
|
|
|
- - SPI2 and SPI3 are general purpose SPI controllers. They are open to users. SPI2 and SPI3 have independent signal buses with the same respective names. SPI2 has {IDF_TARGET_SPI2_CS_NUM} CS lines. SPI3 has {IDF_TARGET_SPI3_CS_NUM} CS lines. Each CS line can be used to drive one SPI slave.
|
|
|
+ - SPI2 and SPI3 are general-purpose SPI controllers. They are open to users. SPI2 and SPI3 have independent signal buses with the same respective names. SPI2 has {IDF_TARGET_SPI2_CS_NUM} CS lines. SPI3 has {IDF_TARGET_SPI3_CS_NUM} CS lines. Each CS line can be used to drive one SPI slave.
|
|
|
|
|
|
.. only:: esp32c3 or esp32c2 or esp32c6 or esp32h2
|
|
|
|
|
|
- - SPI2 is a general purpose SPI controller. It has an independent signal bus with the same name. The bus has {IDF_TARGET_SPI2_CS_NUM} CS lines to drive up to {IDF_TARGET_SPI2_CS_NUM} SPI slaves.
|
|
|
+ - SPI2 is a general-purpose SPI controller. It has an independent signal bus with the same name. The bus has {IDF_TARGET_SPI2_CS_NUM} CS lines to drive up to {IDF_TARGET_SPI2_CS_NUM} SPI slaves.
|
|
|
|
|
|
Terminology
|
|
|
-----------
|
|
|
|
|
|
-The terms used in relation to the SPI master driver are given in the table below.
|
|
|
-
|
|
|
-================= =========================================================================================
|
|
|
-Term Definition
|
|
|
-================= =========================================================================================
|
|
|
-**Host** The SPI controller peripheral inside {IDF_TARGET_NAME} that initiates SPI transmissions over the bus, and acts as an SPI Master.
|
|
|
-**Device** SPI slave device. An SPI bus may be connected to one or more Devices. 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.
|
|
|
-**MOSI** Master Out, Slave In, a.k.a. D. Data transmission from a Host to Device. Also data0 signal in Octal/OPI mode.
|
|
|
-**MISO** Master In, Slave Out, a.k.a. Q. Data transmission from a Device to Host. Also data1 signal in Octal/OPI mode.
|
|
|
-**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. Used for 4-bit (qio/qout) transactions. Also for data2 signal in Octal/OPI mode.
|
|
|
-**QUADHD** Hold signal. Used for 4-bit (qio/qout) transactions. Also for data3 signal in Octal/OPI mode.
|
|
|
-**DATA4** Data4 signal in Octal/OPI mode.
|
|
|
-**DATA5** Data5 signal in Octal/OPI mode.
|
|
|
-**DATA6** Data6 signal in Octal/OPI mode.
|
|
|
-**DATA7** Data7 signal in Octal/OPI mode.
|
|
|
-**Assertion** The action of activating a line.
|
|
|
-**De-assertion** The action of returning the line back to inactive (back to idle) status.
|
|
|
-**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.
|
|
|
-================= =========================================================================================
|
|
|
+The terms used in relation to the SPI Master driver are given in the table below.
|
|
|
+
|
|
|
+.. list-table::
|
|
|
+ :widths: 30 70
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Term
|
|
|
+ - Definition
|
|
|
+ * - Host
|
|
|
+ - The SPI controller peripheral inside {IDF_TARGET_NAME} initiates SPI transmissions over the bus and acts as an SPI Master.
|
|
|
+ * - Device
|
|
|
+ - SPI slave Device. An SPI bus may be connected to one or more Devices. 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 a daisy-chain manner.
|
|
|
+ * - MOSI
|
|
|
+ - Master Out, Slave In, a.k.a. D. Data transmission from a Host to Device. Also data0 signal in Octal/OPI mode.
|
|
|
+ * - MISO
|
|
|
+ - Master In, Slave Out, a.k.a. Q. Data transmission from a Device to Host. Also data1 signal in Octal/OPI mode.
|
|
|
+ * - SCLK
|
|
|
+ - Serial Clock. The oscillating signal generated by a Host 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. Used for 4-bit (qio/qout) transactions. Also for the data2 signal in Octal/OPI mode.
|
|
|
+ * - QUADHD
|
|
|
+ - Hold signal. Used for 4-bit (qio/qout) transactions. Also for the data3 signal in Octal/OPI mode.
|
|
|
+ * - DATA4
|
|
|
+ - Data4 signal in Octal/OPI mode.
|
|
|
+ * - DATA5
|
|
|
+ - Data5 signal in Octal/OPI mode.
|
|
|
+ * - DATA6
|
|
|
+ - Data6 signal in Octal/OPI mode.
|
|
|
+ * - DATA7
|
|
|
+ - Data7 signal in Octal/OPI mode.
|
|
|
+ * - Assertion
|
|
|
+ - The action of activating a line.
|
|
|
+ * - De-assertion
|
|
|
+ - The action of returning the line back to inactive (back to idle) status.
|
|
|
+ * - 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.
|
|
|
|
|
|
|
|
|
Driver Features
|
|
|
---------------
|
|
|
|
|
|
-The SPI master driver governs communications of Hosts with Devices. The driver supports the following features:
|
|
|
+The SPI Master driver governs the communications between Hosts and Devices. The driver supports the following features:
|
|
|
|
|
|
- Multi-threaded environments
|
|
|
- Transparent handling of DMA transfers while reading and writing data
|
|
|
@@ -75,9 +95,9 @@ The SPI master driver governs communications of Hosts with Devices. The driver s
|
|
|
|
|
|
.. warning::
|
|
|
|
|
|
- The SPI master driver has the concept of multiple Devices connected to a single bus (sharing a single {IDF_TARGET_NAME} SPI peripheral). As long as each Device is accessed by only one task, the driver is thread safe. However, if multiple tasks try to access the same SPI Device, the driver is **not thread-safe**. In this case, it is recommended to either:
|
|
|
+ The SPI Master driver allows multiple Devices to be connected on a same SPI bus (sharing a single {IDF_TARGET_NAME} SPI peripheral). As long as each Device is accessed by only one task, the driver is thread-safe. However, if multiple tasks try to access the same SPI Device, the driver is **not thread-safe**. In this case, it is recommended to either:
|
|
|
|
|
|
- - Refactor your application so that each SPI peripheral is only accessed by a single task at a time. You can use :cpp:member:`spi_bus_config_t::isr_cpu_id` to register the SPI ISR to the same core as SPI peripheral related tasks to ensure thread safety.
|
|
|
+ - Refactor your application so that each SPI peripheral is only accessed by a single task at a time. You can use :cpp:member:`spi_bus_config_t::isr_cpu_id` to register the SPI ISR to the same core as SPI peripheral-related tasks to ensure thread safety.
|
|
|
- Add a mutex lock around the shared Device using :c:macro:`xSemaphoreCreateMutex`.
|
|
|
|
|
|
.. toctree::
|
|
|
@@ -92,24 +112,31 @@ An SPI bus transaction consists of five phases which can be found in the table b
|
|
|
|
|
|
{IDF_TARGET_ADDR_LEN:default="32", esp32="64"}
|
|
|
|
|
|
-============== =========================================================================================================
|
|
|
-Phase Description
|
|
|
-============== =========================================================================================================
|
|
|
-**Command** In this phase, a command (0-16 bit) is written to the bus by the Host.
|
|
|
-**Address** In this phase, an address (0-{IDF_TARGET_ADDR_LEN} bit) is transmitted over the bus by the Host.
|
|
|
-**Dummy** This phase is configurable and is used to meet the timing requirements.
|
|
|
-**Write** Host sends data to a Device. This data follows the optional command and address phases and is indistinguishable from them at the electrical level.
|
|
|
-**Read** Device sends data to its Host.
|
|
|
-============== =========================================================================================================
|
|
|
+.. list-table::
|
|
|
+ :widths: 30 70
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Phase
|
|
|
+ - Description
|
|
|
+ * - Command
|
|
|
+ - In this phase, a command (0-16 bit) is written to the bus by the Host.
|
|
|
+ * - Address
|
|
|
+ - In this phase, an address (0-{IDF_TARGET_ADDR_LEN} bit) is transmitted over the bus by the Host.
|
|
|
+ * - Dummy
|
|
|
+ - This phase is configurable and is used to meet the timing requirements.
|
|
|
+ * - Write
|
|
|
+ - Host sends data to a Device. This data follows the optional command and address phases and is indistinguishable from them at the electrical level.
|
|
|
+ * - Read
|
|
|
+ - Device sends data to its Host.
|
|
|
|
|
|
.. todo::
|
|
|
|
|
|
Add a package diagram.
|
|
|
|
|
|
|
|
|
-The attributes of a transaction are determined by the bus configuration structure :cpp:type:`spi_bus_config_t`, device configuration structure :cpp:type:`spi_device_interface_config_t`, and transaction configuration structure :cpp:type:`spi_transaction_t`.
|
|
|
+The attributes of a transaction are determined by the bus configuration structure :cpp:type:`spi_bus_config_t`, Device configuration structure :cpp:type:`spi_device_interface_config_t`, and transaction configuration structure :cpp:type:`spi_transaction_t`.
|
|
|
|
|
|
-An SPI Host can send full-duplex transactions, during which the read and write phases occur simultaneously. The total transaction length is determined by the sum of the following members:
|
|
|
+An SPI Host can send full-duplex transactions, during which the Read and Write phases occur simultaneously. The total transaction length is determined by the sum of the following members:
|
|
|
|
|
|
- :cpp:member:`spi_device_interface_config_t::command_bits`
|
|
|
- :cpp:member:`spi_device_interface_config_t::address_bits`
|
|
|
@@ -117,13 +144,13 @@ An SPI Host can send full-duplex transactions, during which the read and write p
|
|
|
|
|
|
While the member :cpp:member:`spi_transaction_t::rxlength` only determines the length of data received into the buffer.
|
|
|
|
|
|
-In half-duplex transactions, the read and write phases are not simultaneous (one direction at a time). The lengths of the write and read phases are determined by :cpp:member:`spi_transaction_t::length` and :cpp:member:`spi_transaction_t::rxlength` respectively.
|
|
|
+In half-duplex transactions, the Read and Write phases are not simultaneous (one direction at a time). The lengths of the Write and Read phases are determined by :cpp:member:`spi_transaction_t::length` and :cpp:member:`spi_transaction_t::rxlength` respectively.
|
|
|
|
|
|
-The command and address phases are optional, as not every SPI device requires a command and/or address. This is reflected in the Device's configuration: if :cpp:member:`spi_device_interface_config_t::command_bits` and/or :cpp:member:`spi_device_interface_config_t::address_bits` are set to zero, no command or address phase will occur.
|
|
|
+The Command and Address phases are optional, as not every SPI Device requires a command and/or address. This is reflected in the Device's configuration: if :cpp:member:`spi_device_interface_config_t::command_bits` and/or :cpp:member:`spi_device_interface_config_t::address_bits` are set to zero, no Command or Address phase will occur.
|
|
|
|
|
|
-The read and write phases can also be optional, as not every transaction requires both writing and reading data. If :cpp:member:`spi_transaction_t::rx_buffer` is NULL and :c:macro:`SPI_TRANS_USE_RXDATA` is not set, the read phase is skipped. If :cpp:member:`spi_transaction_t::tx_buffer` is NULL and :c:macro:`SPI_TRANS_USE_TXDATA` is not set, the write phase is skipped.
|
|
|
+The Read and Write phases can also be optional, as not every transaction requires both writing and reading data. If :cpp:member:`spi_transaction_t::rx_buffer` is NULL and :c:macro:`SPI_TRANS_USE_RXDATA` is not set, the Read phase is skipped. If :cpp:member:`spi_transaction_t::tx_buffer` is NULL and :c:macro:`SPI_TRANS_USE_TXDATA` is not set, the Write phase is skipped.
|
|
|
|
|
|
-The driver supports two types of transactions: the interrupt transactions and polling transactions. The programmer can choose to use a different transaction type per Device. If your Device requires both transaction types, see :ref:`mixed_transactions`.
|
|
|
+The driver supports two types of transactions: interrupt transactions and polling transactions. The programmer can choose to use a different transaction type per Device. If your Device requires both transaction types, see :ref:`mixed_transactions`.
|
|
|
|
|
|
|
|
|
.. _interrupt_transactions:
|
|
|
@@ -133,7 +160,7 @@ Interrupt Transactions
|
|
|
|
|
|
Interrupt transactions will block the transaction routine until the transaction completes, thus allowing the CPU to run other tasks.
|
|
|
|
|
|
-An application task can queue multiple transactions, and the driver will automatically handle them one-by-one in the interrupt service routine (ISR). It allows the task to switch to other procedures until all the transactions complete.
|
|
|
+An application task can queue multiple transactions, and the driver will automatically handle them one by one in the interrupt service routine (ISR). It allows the task to switch to other procedures until all the transactions are complete.
|
|
|
|
|
|
|
|
|
.. _polling_transactions:
|
|
|
@@ -145,70 +172,128 @@ Polling transactions do not use interrupts. The routine keeps polling the SPI Ho
|
|
|
|
|
|
All the tasks that use interrupt transactions can be blocked by the queue. At this point, they will need to wait for the ISR to run twice before the transaction is finished. Polling transactions save time otherwise spent on queue handling and context switching, which results in smaller transaction duration. The disadvantage is that the CPU is busy while these transactions are in progress.
|
|
|
|
|
|
-The :cpp:func:`spi_device_polling_end` routine needs an overhead of at least 1 us to unblock other tasks when the transaction is finished. It is strongly recommended to wrap a series of polling transactions using the functions :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus` to avoid the overhead. For more information, see :ref:`bus_acquiring`.
|
|
|
+The :cpp:func:`spi_device_polling_end` routine needs an overhead of at least 1 µs to unblock other tasks when the transaction is finished. It is strongly recommended to wrap a series of polling transactions using the functions :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus` to avoid the overhead. For more information, see :ref:`bus_acquiring`.
|
|
|
|
|
|
.. _transaction-line-mode:
|
|
|
|
|
|
Transaction Line Mode
|
|
|
^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-Supported line modes for {IDF_TARGET_NAME} are listed as follows, to make use of these modes, set the member `flags` in the struct :cpp:type:`spi_transaction_t` as shown in the `Transaction Flag` column. If you want to check if corresponding IO pins are set or not, set the member `flags` in the :cpp:type:`spi_bus_config_t` as shown in the `Bus IO setting Flag` column.
|
|
|
+Supported line modes for {IDF_TARGET_NAME} are listed as follows, to make use of these modes, set the member ``flags`` in the struct :cpp:type:`spi_transaction_t` as shown in the ``Transaction Flag`` column. If you want to check if corresponding IO pins are set or not, set the member ``flags`` in the :cpp:type:`spi_bus_config_t` as shown in the ``Bus IO setting Flag`` column.
|
|
|
|
|
|
|
|
|
.. only:: not SOC_SPI_SUPPORT_OCT
|
|
|
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Mode name | Command Line Width | Address Line Width | Data Line Width | Transaction Flag | Bus IO setting Flag |
|
|
|
- +==============+====================+====================+=================+============================+=========================+
|
|
|
- | Normal SPI | 1 | 1 | 1 | 0 | 0 |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Dual Output | 1 | 1 | 2 | SPI_TRANS_MODE_DIO | |
|
|
|
- | | | | | | |
|
|
|
- | | | | | | SPICOMMON_BUSFLAG_DUAL |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Dual I/O | 1 | 2 | 2 | SPI_TRANS_MODE_DIO | | |
|
|
|
- | | | | | SPI_TRANS_MULTILINE_ADDR | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Quad Output | 1 | 1 | 4 | SPI_TRANS_MODE_QIO | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+ |
|
|
|
- | Quad I/O | 1 | 4 | 4 | SPI_TRANS_MODE_QIO | | SPICOMMON_BUSFLAG_QUAD |
|
|
|
- | | | | | SPI_TRANS_MULTILINE_ADDR | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 30 40 40 40 50 50
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Mode name
|
|
|
+ - Command Line Width
|
|
|
+ - Address Line Width
|
|
|
+ - Data Line Width
|
|
|
+ - Transaction Flag
|
|
|
+ - Bus IO Setting Flag
|
|
|
+ * - Normal SPI
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 0
|
|
|
+ - 0
|
|
|
+ * - Dual Output
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 2
|
|
|
+ - {SPI_TRANS_MODE_DIO}
|
|
|
+ - {SPICOMMON_BUSFLAG_DUAL}
|
|
|
+ * - Dual I/O
|
|
|
+ - 1
|
|
|
+ - 2
|
|
|
+ - 2
|
|
|
+ - * {SPI_TRANS_MODE_DIO}
|
|
|
+ * {SPI_TRANS_MULTILINE_ADDR}
|
|
|
+ -
|
|
|
+ * - Quad Output
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 4
|
|
|
+ - {SPI_TRANS_MODE_QIO}
|
|
|
+ - {SPICOMMON_BUSFLAG_QUAD}
|
|
|
+ * - Quad I/O
|
|
|
+ - 1
|
|
|
+ - 4
|
|
|
+ - 4
|
|
|
+ - * {SPI_TRANS_MODE_QIO}
|
|
|
+ * {SPI_TRANS_MULTILINE_ADDR}
|
|
|
+ - {SPICOMMON_BUSFLAG_QUAD}
|
|
|
|
|
|
.. only:: SOC_SPI_SUPPORT_OCT
|
|
|
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Mode name | Command Line Width | Address Line Width | Data Line Width | Transaction Flag | Bus IO setting Flag |
|
|
|
- +==============+====================+====================+=================+============================+=========================+
|
|
|
- | Normal SPI | 1 | 1 | 1 | 0 | 0 |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Dual Output | 1 | 1 | 2 | SPI_TRANS_MODE_DIO | |
|
|
|
- | | | | | | |
|
|
|
- | | | | | | SPICOMMON_BUSFLAG_DUAL |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Dual I/O | 1 | 2 | 2 | SPI_TRANS_MODE_DIO | | |
|
|
|
- | | | | | SPI_TRANS_MULTILINE_ADDR | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Quad Output | 1 | 1 | 4 | SPI_TRANS_MODE_QIO | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+ |
|
|
|
- | Quad I/O | 1 | 4 | 4 | SPI_TRANS_MODE_QIO | | SPICOMMON_BUSFLAG_QUAD |
|
|
|
- | | | | | SPI_TRANS_MULTILINE_ADDR | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
- | Octal Output | 1 | 1 | 8 | SPI_TRANS_MODE_OCT | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+ |
|
|
|
- | OPI | 8 | 8 | 8 | SPI_TRANS_MODE_OCT | | SPICOMMON_BUSFLAG_OCTAL |
|
|
|
- | | | | | SPI_TRANS_MULTILINE_ADDR | | |
|
|
|
- | | | | | SPI_TRANS_MULTILINE_CMD | |
|
|
|
- +--------------+--------------------+--------------------+-----------------+----------------------------+-------------------------+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 30 40 40 40 50 50
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Mode name
|
|
|
+ - Command Line Width
|
|
|
+ - Address Line Width
|
|
|
+ - Data Line Width
|
|
|
+ - Transaction Flag
|
|
|
+ - Bus IO Setting Flag
|
|
|
+ * - Normal SPI
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 0
|
|
|
+ - 0
|
|
|
+ * - Dual Output
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 2
|
|
|
+ - {SPI_TRANS_MODE_DIO}
|
|
|
+ - {SPICOMMON_BUSFLAG_DUAL}
|
|
|
+ * - Dual I/O
|
|
|
+ - 1
|
|
|
+ - 2
|
|
|
+ - 2
|
|
|
+ - * {SPI_TRANS_MODE_DIO}
|
|
|
+ * {SPI_TRANS_MULTILINE_ADDR}
|
|
|
+ -
|
|
|
+ * - Quad Output
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 4
|
|
|
+ - {SPI_TRANS_MODE_QIO}
|
|
|
+ - {SPICOMMON_BUSFLAG_QUAD}
|
|
|
+ * - Quad I/O
|
|
|
+ - 1
|
|
|
+ - 4
|
|
|
+ - 4
|
|
|
+ - * {SPI_TRANS_MODE_QIO}
|
|
|
+ * {SPI_TRANS_MULTILINE_ADDR}
|
|
|
+ - {SPICOMMON_BUSFLAG_QUAD}
|
|
|
+ * - Octal Output
|
|
|
+ - 1
|
|
|
+ - 1
|
|
|
+ - 8
|
|
|
+ - {SPI_TRANS_MODE_OCT}
|
|
|
+ - {SPICOMMON_BUSFLAG_OCTAL}
|
|
|
+ * - OPI
|
|
|
+ - 8
|
|
|
+ - 8
|
|
|
+ - 8
|
|
|
+ - * {SPI_TRANS_MODE_OCT}
|
|
|
+ * {SPI_TRANS_MULTILINE_ADDR}
|
|
|
+ * {SPI_TRANS_MULTILINE_CMD}
|
|
|
+ - {SPICOMMON_BUSFLAG_OCTAL}
|
|
|
|
|
|
Command and Address Phases
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-During the command and address phases, the members :cpp:member:`spi_transaction_t::cmd` and :cpp:member:`spi_transaction_t::addr` are sent to the bus, nothing is read at this time. The default lengths of the command and address phases are set in :cpp:type:`spi_device_interface_config_t` by calling :cpp:func:`spi_bus_add_device`. If the flags :c:macro:`SPI_TRANS_VARIABLE_CMD` and :c:macro:`SPI_TRANS_VARIABLE_ADDR` in the member :cpp:member:`spi_transaction_t::flags` are not set, the driver automatically sets the length of these phases to default values during Device initialization.
|
|
|
+During the Command and Address phases, the members :cpp:member:`spi_transaction_t::cmd` and :cpp:member:`spi_transaction_t::addr` are sent to the bus, nothing is read at this time. The default lengths of the Command and Address phases are set in :cpp:type:`spi_device_interface_config_t` by calling :cpp:func:`spi_bus_add_device`. If the flags :c:macro:`SPI_TRANS_VARIABLE_CMD` and :c:macro:`SPI_TRANS_VARIABLE_ADDR` in the member :cpp:member:`spi_transaction_t::flags` are not set, the driver automatically sets the length of these phases to default values during Device initialization.
|
|
|
|
|
|
-If the lengths of the command and address phases need to be variable, declare the struct :cpp:type:`spi_transaction_ext_t`, set the flags :c:macro:`SPI_TRANS_VARIABLE_CMD` and/or :c:macro:`SPI_TRANS_VARIABLE_ADDR` in the member :cpp:member:`spi_transaction_ext_t::base` and configure the rest of base as usual. Then the length of each phase will be equal to :cpp:member:`spi_transaction_ext_t::command_bits` and :cpp:member:`spi_transaction_ext_t::address_bits` set in the struct :cpp:type:`spi_transaction_ext_t`.
|
|
|
+If the lengths of the Command and Address phases need to be variable, declare the struct :cpp:type:`spi_transaction_ext_t`, set the flags :c:macro:`SPI_TRANS_VARIABLE_CMD` and/or :c:macro:`SPI_TRANS_VARIABLE_ADDR` in the member :cpp:member:`spi_transaction_ext_t::base` and configure the rest of base as usual. Then the length of each phase will be equal to :cpp:member:`spi_transaction_ext_t::command_bits` and :cpp:member:`spi_transaction_ext_t::address_bits` set in the struct :cpp:type:`spi_transaction_ext_t`.
|
|
|
|
|
|
-If the command and address phase need to be as the same number of lines as data phase, you need to set `SPI_TRANS_MULTILINE_CMD` and/or `SPI_TRANS_MULTILINE_ADDR` to the `flags` member in the struct :cpp:type:`spi_transaction_t`. Also see :ref:`transaction-line-mode`.
|
|
|
+If the Command and Address phase need to have the same number of lines as the data phase, you need to set ``SPI_TRANS_MULTILINE_CMD`` and/or ``SPI_TRANS_MULTILINE_ADDR`` to the ``flags`` member in the struct :cpp:type:`spi_transaction_t`. Also see :ref:`transaction-line-mode`.
|
|
|
|
|
|
|
|
|
Write and Read Phases
|
|
|
@@ -216,31 +301,31 @@ Write and Read Phases
|
|
|
|
|
|
Normally, the data that needs to be transferred to or from a Device will be read from or written to a chunk of memory indicated by the members :cpp:member:`spi_transaction_t::rx_buffer` and :cpp:member:`spi_transaction_t::tx_buffer`. If DMA is enabled for transfers, the buffers are required to be:
|
|
|
|
|
|
- 1. Allocated in DMA-capable internal memory. If :ref:`external PSRAM is enabled<dma-capable-memory>`, this means using ``pvPortMallocCaps(size, MALLOC_CAP_DMA)``.
|
|
|
- 2. 32-bit aligned (staring from a 32-bit boundary and having a length of multiples of 4 bytes).
|
|
|
+ 1. Allocated in DMA-capable internal memory (MALLOC_CAP_DMA), see :ref:`DMA-Capable Memory<dma-capable-memory>`.
|
|
|
+ 2. 32-bit aligned (starting from a 32-bit boundary and having a length of multiples of 4 bytes).
|
|
|
|
|
|
If these requirements are not satisfied, the transaction efficiency will be affected due to the allocation and copying of temporary buffers.
|
|
|
|
|
|
-If using more than one data lines to transmit, please set `SPI_DEVICE_HALFDUPLEX` flag for the member `flags` in the struct :cpp:type:`spi_device_interface_config_t`. And the member `flags` in the struct :cpp:type:`spi_transaction_t` should be set as described in :ref:`transaction-line-mode`.
|
|
|
+If using more than one data line to transmit, please set ``SPI_DEVICE_HALFDUPLEX`` flag for the member ``flags`` in the struct :cpp:type:`spi_device_interface_config_t`. And the member ``flags`` in the struct :cpp:type:`spi_transaction_t` should be set as described in :ref:`transaction-line-mode`.
|
|
|
|
|
|
.. only:: esp32
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
- Half-duplex transactions with both read and write phases are not supported when using DMA. For details and workarounds, see :ref:`spi_known_issues`.
|
|
|
+ Half-duplex transactions with both Read and Write phases are not supported when using DMA. For details and workarounds, see :ref:`spi_known_issues`.
|
|
|
|
|
|
.. only:: esp32s3 or esp32c3 or esp32c2 or esp32c6 or esp32h2
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
- Half-duplex transactions with both read and write phases are not supported. Please use full duplex mode.
|
|
|
+ Half-duplex transactions with both Read and Write phases are not supported. Please use full duplex mode.
|
|
|
|
|
|
.. _bus_acquiring:
|
|
|
|
|
|
Bus Acquiring
|
|
|
^^^^^^^^^^^^^
|
|
|
|
|
|
-Sometimes you might want to send SPI transactions exclusively and continuously so that it takes as little time as possible. For this, you can use bus acquiring, which helps to suspend transactions (both polling or interrupt) to other devices until the bus is released. To acquire and release a bus, use the functions :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus`.
|
|
|
+Sometimes you might want to send SPI transactions exclusively and continuously so that it takes as little time as possible. For this, you can use bus acquiring, which helps to suspend transactions (both polling or interrupt) to other Devices until the bus is released. To acquire and release a bus, use the functions :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus`.
|
|
|
|
|
|
|
|
|
Driver Usage
|
|
|
@@ -248,23 +333,23 @@ Driver Usage
|
|
|
|
|
|
.. todo::
|
|
|
|
|
|
- Organize the Driver Usage into subsections that will reflect the general usage experience of the users, e.g.,
|
|
|
+ Organize the Driver Usage into subsections that will reflect the general user experience of the users, e.g.,
|
|
|
|
|
|
Configuration
|
|
|
|
|
|
- Add stuff about the configuration API here, and the various options in configuration (e.g., configure for interrupt vs. polling), and optional configuration
|
|
|
+ Add stuff about the configuration API here, the various options in configuration (e.g., configure for interrupt vs. polling), and optional configuration
|
|
|
|
|
|
Transactions
|
|
|
|
|
|
Describe how to execute a normal transaction (i.e., where data is larger than 32 bits). Describe how to configure between big and little-endian.
|
|
|
|
|
|
- - Add subsub section on how to optimize when transmitting less than 32 bits
|
|
|
- - Add subsub section on how to transmit mixed transactions to the same device
|
|
|
+ - Add a sub-sub section on how to optimize when transmitting less than 32 bits
|
|
|
+ - Add a sub-sub section on how to transmit mixed transactions to the same Device
|
|
|
|
|
|
|
|
|
- Initialize an SPI bus by calling the function :cpp:func:`spi_bus_initialize`. Make sure to set the correct I/O pins in the struct :cpp:type:`spi_bus_config_t`. Set the signals that are not needed to ``-1``.
|
|
|
|
|
|
-- Register a Device connected to the bus with the driver by calling the function :cpp:func:`spi_bus_add_device`. Make sure to configure any timing requirements the device might need with the parameter ``dev_config``. You should now have obtained the Device's handle which will be used when sending a transaction to it.
|
|
|
+- Register a Device connected to the bus with the driver by calling the function :cpp:func:`spi_bus_add_device`. Make sure to configure any timing requirements the Device might need with the parameter ``dev_config``. You should now have obtained the Device's handle which will be used when sending a transaction to it.
|
|
|
|
|
|
- To interact with the Device, fill one or more :cpp:type:`spi_transaction_t` structs with any transaction parameters required. Then send the structs either using a polling transaction or an interrupt transaction:
|
|
|
|
|
|
@@ -276,11 +361,11 @@ Driver Usage
|
|
|
|
|
|
- (Optional) To perform back-to-back transactions with a Device, call the function :cpp:func:`spi_device_acquire_bus` before sending transactions and :cpp:func:`spi_device_release_bus` after the transactions have been sent.
|
|
|
|
|
|
-- (Optional) To unload the driver for a certain Device, call :cpp:func:`spi_bus_remove_device` with the Device handle as an argument.
|
|
|
+- (Optional) To remove a certain Device from the bus, call :cpp:func:`spi_bus_remove_device` with the Device handle as an argument.
|
|
|
|
|
|
-- (Optional) To remove the driver for a bus, make sure no more drivers are attached and call :cpp:func:`spi_bus_free`.
|
|
|
+- (Optional) To remove the driver from the bus, make sure no more devices are attached and call :cpp:func:`spi_bus_free`.
|
|
|
|
|
|
-The example code for the SPI master driver can be found in the :example:`peripherals/spi_master` directory of ESP-IDF examples.
|
|
|
+The example code for the SPI Master driver can be found in the :example:`peripherals/spi_master` directory of ESP-IDF examples.
|
|
|
|
|
|
|
|
|
Transactions with Data Not Exceeding 32 Bits
|
|
|
@@ -289,16 +374,16 @@ Transactions with Data Not Exceeding 32 Bits
|
|
|
When the transaction data size is equal to or less than 32 bits, it will be sub-optimal to allocate a buffer for the data. The data can be directly stored in the transaction struct instead. For transmitted data, it can be achieved by using the :cpp:member:`spi_transaction_t::tx_data` member and setting the :c:macro:`SPI_TRANS_USE_TXDATA` flag on the transmission. For received data, use :cpp:member:`spi_transaction_t::rx_data` and set :c:macro:`SPI_TRANS_USE_RXDATA`. In both cases, do not touch the :cpp:member:`spi_transaction_t::tx_buffer` or :cpp:member:`spi_transaction_t::rx_buffer` members, because they use the same memory locations as :cpp:member:`spi_transaction_t::tx_data` and :cpp:member:`spi_transaction_t::rx_data`.
|
|
|
|
|
|
|
|
|
-Transactions with Integers Other Than ``uint8_t``
|
|
|
+Transactions with Integers Other than ``uint8_t``
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-An SPI Host reads and writes data into memory byte by byte. By default, data is sent with the most significant bit (MSB) first, as LSB first used in rare cases. If a value less than 8 bits needs to be sent, the bits should be written into memory in the MSB first manner.
|
|
|
+An SPI Host reads and writes data into memory byte by byte. By default, data is sent with the most significant bit (MSB) first, as LSB is first used in rare cases. If a value of fewer than 8 bits needs to be sent, the bits should be written into memory in the MSB first manner.
|
|
|
|
|
|
For example, if ``0b00010`` needs to be sent, it should be written into a ``uint8_t`` variable, and the length for reading should be set to 5 bits. The Device will still receive 8 bits with 3 additional "random" bits, so the reading must be performed correctly.
|
|
|
|
|
|
On top of that, {IDF_TARGET_NAME} is a little-endian chip, which means that the least significant byte of ``uint16_t`` and ``uint32_t`` variables is stored at the smallest address. Hence, if ``uint16_t`` is stored in memory, bits [7:0] are sent first, followed by bits [15:8].
|
|
|
|
|
|
-For cases when the data to be transmitted has the size differing from ``uint8_t`` arrays, the following macros can be used to transform data to the format that can be sent by the SPI driver directly:
|
|
|
+For cases when the data to be transmitted has a size differing from ``uint8_t`` arrays, the following macros can be used to transform data to the format that can be sent by the SPI driver directly:
|
|
|
|
|
|
- :c:macro:`SPI_SWAP_DATA_TX` for data to be transmitted
|
|
|
- :c:macro:`SPI_SWAP_DATA_RX` for data received
|
|
|
@@ -309,7 +394,7 @@ For cases when the data to be transmitted has the size differing from ``uint8_t`
|
|
|
Notes on Sending Mixed Transactions to the Same Device
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-To reduce coding complexity, send only one type of transactions (interrupt or polling) to one Device. However, you still can send both interrupt and polling transactions alternately. The notes below explain how to do this.
|
|
|
+To reduce coding complexity, send only one type of transaction (interrupt or polling) to one Device. However, you still can send both interrupt and polling transactions alternately. The notes below explain how to do this.
|
|
|
|
|
|
The polling transactions should be initiated only after all the polling and interrupt transactions are finished.
|
|
|
|
|
|
@@ -323,63 +408,43 @@ To have better control of the calling sequence of functions, send mixed transact
|
|
|
|
|
|
.. _spi_master_on_spi1_bus:
|
|
|
|
|
|
- Notes on Using the SPI Master driver on SPI1 Bus
|
|
|
+ Notes on Using the SPI Master Driver on SPI1 Bus
|
|
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
- Though the :ref:`spi_bus_lock` feature makes it possible to use SPI Master driver on the SPI1
|
|
|
- bus, it's still tricky and needs a lot of special treatment. It's a feature for advanced
|
|
|
- developers.
|
|
|
+ Though the :ref:`spi_bus_lock` feature makes it possible to use SPI Master driver on the SPI1 bus, it's still tricky and needs a lot of special treatment. It's a feature for advanced developers.
|
|
|
|
|
|
To use SPI Master driver on SPI1 bus, you have to take care of two problems:
|
|
|
|
|
|
- 1. The code and data, required at the meanwhile the driver is operating SPI1 bus, should be
|
|
|
- in the internal memory.
|
|
|
+ 1. The code and data should be in the internal memory when the driver is operating on SPI1 bus.
|
|
|
|
|
|
- SPI1 bus is shared among devices and the cache for data (code) in the Flash as well as the
|
|
|
- PSRAM. The cache should be disabled during the other drivers are operating the SPI1 bus.
|
|
|
- Hence the data (code) in the flash as well as the PSRAM cannot be fetched at the meanwhile
|
|
|
- the driver acquires the SPI1 bus by:
|
|
|
+ SPI1 bus is shared among Devices and the cache for data (code) in the flash as well as the PSRAM. The cache should be disabled when other drivers are operating on the SPI1 bus. Hence the data (code) in the flash as well as the PSRAM cannot be fetched while the driver acquires the SPI1 bus by:
|
|
|
|
|
|
- - Explicit bus acquiring between :cpp:func:`spi_device_acquire_bus` and
|
|
|
- :cpp:func:`spi_device_release_bus`.
|
|
|
- - Implicit bus acquiring between :cpp:func:`spi_device_polling_start` and
|
|
|
- :cpp:func:`spi_device_polling_end` (or inside :cpp:func:`spi_device_polling_transmit`).
|
|
|
+ - Explicit bus acquiring between :cpp:func:`spi_device_acquire_bus` and :cpp:func:`spi_device_release_bus`.
|
|
|
+ - Implicit bus acquiring between :cpp:func:`spi_device_polling_start` and :cpp:func:`spi_device_polling_end` (or inside :cpp:func:`spi_device_polling_transmit`).
|
|
|
|
|
|
- During the time above, all other tasks and most ISRs will be disabled (see
|
|
|
- :ref:`iram-safe-interrupt-handlers`). Application code and data used by current task
|
|
|
- should be placed in internal memory (DRAM or IRAM), or already in the ROM. Access to
|
|
|
- external memory (flash code, const data in the flash, and static/heap data in the PSRAM)
|
|
|
- will cause a `Cache disabled but cached memory region accessed` exception. For differences
|
|
|
- between IRAM, DRAM, and flash cache, please refer to the :ref:`application memory layout
|
|
|
- <memory-layout>` documentation.
|
|
|
+ During the time above, all other tasks and most ISRs will be disabled (see :ref:`iram-safe-interrupt-handlers`). Application code and data used by the current task should be placed in internal memory (DRAM or IRAM), or already in the ROM. Access to external memory (flash code, const data in the flash, and static/heap data in the PSRAM) will cause a ``Cache disabled but cached memory region accessed`` exception. For differences between IRAM, DRAM, and flash cache, please refer to the :ref:`application memory layout <memory-layout>` documentation.
|
|
|
|
|
|
To place functions into the IRAM, you can either:
|
|
|
|
|
|
- 1. Add `IRAM_ATTR` (include "esp_attr.h") to the function like:
|
|
|
+ 1. Add ``IRAM_ATTR`` (include ``esp_attr.h``) to the function like:
|
|
|
|
|
|
IRAM_ATTR void foo(void) { }
|
|
|
|
|
|
- Please note that when a function is inlined, it will follow its caller's segment, and
|
|
|
- the attribute will not take effect. You may need to use `NOLINE_ATTR` to avoid this.
|
|
|
+ Please note that when a function is inlined, it will follow its caller's segment, and the attribute will not take effect. You may need to use ``NOLINE_ATTR`` to avoid this. Please also note that the compiler may transform some code into a lookup table in the const data, so ``noflash_text`` is not safe.
|
|
|
|
|
|
- 2. Use the `noflash` placement in the `linker.lf`. See more in
|
|
|
- :doc:`../../api-guides/linker-script-generation`. Please note that, some code may be
|
|
|
- transformed into lookup table in the const data by the compiler, so `noflash_text` is not
|
|
|
- safe.
|
|
|
+ 2. Use the ``noflash`` placement in the ``linker.lf``. See more in :doc:`../../api-guides/linker-script-generation`. Please note that the compiler may transform some code into a lookup table in the const data, so ``noflash_text`` is not safe.
|
|
|
|
|
|
- Please do take care that the optimization level may affect the compiler behavior of inline,
|
|
|
- or transforming some code into lookup table in the const data, etc.
|
|
|
+ Please do take care that the optimization level may affect the compiler behavior of inline, or transform some code into a lookup table in the const data, etc.
|
|
|
|
|
|
To place data into the DRAM, you can either:
|
|
|
|
|
|
- 1. Add `DRAM_ATTR` (include "esp_attr.h") to the data definition like:
|
|
|
+ 1. Add ``DRAM_ATTR`` (include ``esp_attr.h``) to the data definition like:
|
|
|
|
|
|
DRAM_ATTR int g_foo = 3;
|
|
|
|
|
|
- 2. Use the `noflash` placement in the linker.lf. See more in
|
|
|
- :doc:`../../api-guides/linker-script-generation`.
|
|
|
+ 2. Use the ``noflash`` placement in the linker.lf. See more in :doc:`../../api-guides/linker-script-generation`.
|
|
|
|
|
|
Please also see the example :example:`peripherals/spi_master/hd_eeprom`.
|
|
|
|
|
|
@@ -389,7 +454,7 @@ GPIO Matrix and IO_MUX
|
|
|
|
|
|
.. only:: esp32
|
|
|
|
|
|
- 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.
|
|
|
+ Most of ESP32's peripheral signals have a 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 introduces flexibility of routing but also brings the following disadvantages:
|
|
|
|
|
|
@@ -402,23 +467,31 @@ GPIO Matrix and IO_MUX
|
|
|
|
|
|
The IO_MUX pins for SPI buses are given below.
|
|
|
|
|
|
- +----------+------+------+
|
|
|
- | Pin Name | SPI2 | SPI3 |
|
|
|
- + +------+------+
|
|
|
- | | GPIO Number |
|
|
|
- +==========+======+======+
|
|
|
- | CS0 [1]_ | 15 | 5 |
|
|
|
- +----------+------+------+
|
|
|
- | SCLK | 14 | 18 |
|
|
|
- +----------+------+------+
|
|
|
- | MISO | 12 | 19 |
|
|
|
- +----------+------+------+
|
|
|
- | MOSI | 13 | 23 |
|
|
|
- +----------+------+------+
|
|
|
- | QUADWP | 2 | 22 |
|
|
|
- +----------+------+------+
|
|
|
- | QUADHD | 4 | 21 |
|
|
|
- +----------+------+------+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 40 20 20
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Pin Name
|
|
|
+ - SPI 2 (GPIO Number)
|
|
|
+ - SPI 3 (GPIO Number)
|
|
|
+ * - CS0 [1]_
|
|
|
+ - 15
|
|
|
+ - 5
|
|
|
+ * - SCLK
|
|
|
+ - 14
|
|
|
+ - 18
|
|
|
+ * - MISO
|
|
|
+ - 12
|
|
|
+ - 19
|
|
|
+ * - MOSI
|
|
|
+ - 13
|
|
|
+ - 23
|
|
|
+ * - QUADWP
|
|
|
+ - 2
|
|
|
+ - 22
|
|
|
+ * - QUADHD
|
|
|
+ - 4
|
|
|
+ - 21
|
|
|
|
|
|
.. only:: not esp32
|
|
|
|
|
|
@@ -429,9 +502,9 @@ GPIO Matrix and IO_MUX
|
|
|
{IDF_TARGET_SPI2_IOMUX_PIN_HD:default="N/A", esp32s2="9" esp32s3="9", esp32c2="4" esp32c3="4", esp32c6="4", esp32h2="3"}
|
|
|
{IDF_TARGET_SPI2_IOMUX_PIN_WP:default="N/A", esp32s2="14" esp32s3="14", esp32c2="5" esp32c3="5", esp32c6="5", esp32h2="2"}
|
|
|
|
|
|
- Most of chip'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.
|
|
|
+ Most of the chip's peripheral signals have a 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.
|
|
|
|
|
|
- When an SPI Host is set to 80MHz or lower frequencies, routing SPI pins via GPIO matrix will behave the same comparing to routing them via IOMUX.
|
|
|
+ When an SPI Host is set to 80MHz or lower frequencies, routing SPI pins via the GPIO matrix will behave the same compared to routing them via IOMUX.
|
|
|
|
|
|
The IO_MUX pins for SPI buses are given below.
|
|
|
|
|
|
@@ -478,15 +551,15 @@ Transaction Duration
|
|
|
{IDF_TARGET_TRANS_TIME_INTR_CPU:default="N/A", esp32="25", esp32s2="22", esp32c3="27", esp32s3="24", esp32c2="40", esp32c6="32", esp32h2="54"}
|
|
|
{IDF_TARGET_TRANS_TIME_POLL_CPU:default="N/A", esp32="8", esp32s2="8", esp32c3="9", esp32s3="9", esp32c2="15", esp32c6="15", esp32h2="24"}
|
|
|
|
|
|
-Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transaction.
|
|
|
+Transaction duration includes setting up SPI peripheral registers, copying data to FIFOs or setting up DMA links, and the time for SPI transactions.
|
|
|
|
|
|
Interrupt transactions allow appending extra overhead to accommodate the cost of FreeRTOS queues and the time needed for switching between tasks and the ISR.
|
|
|
|
|
|
-For **interrupt transactions**, the CPU can switch to other tasks when a transaction is in progress. This saves the CPU time but increases the transaction duration. See :ref:`interrupt_transactions`. For **polling transactions**, it does not block the task but allows to do polling when the transaction is in progress. For more information, see :ref:`polling_transactions`.
|
|
|
+For **interrupt transactions**, the CPU can switch to other tasks when a transaction is in progress. This saves CPU time but increases the transaction duration. See :ref:`interrupt_transactions`. For **polling transactions**, it does not block the task but allows to do polling when the transaction is in progress. For more information, see :ref:`polling_transactions`.
|
|
|
|
|
|
-If DMA is enabled, setting up the linked list requires about 2 us per transaction. When a master is transferring data, it automatically reads the data from the linked list. If DMA is not enabled, the CPU has to write and read each byte from the FIFO by itself. Usually, this is faster than 2 us, but the transaction length is limited to 64 bytes for both write and read.
|
|
|
+If DMA is enabled, setting up the linked list requires about 2 µs per transaction. When a master is transferring data, it automatically reads the data from the linked list. If DMA is not enabled, the CPU has to write and read each byte from the FIFO by itself. Usually, this is faster than 2 µs, but the transaction length is limited to 64 bytes for both write and read.
|
|
|
|
|
|
-Typical transaction duration for one byte of data are given below.
|
|
|
+The typical transaction duration for one byte of data is given below.
|
|
|
|
|
|
- Interrupt Transaction via DMA: {IDF_TARGET_TRANS_TIME_INTR_DMA} µs.
|
|
|
- Interrupt Transaction via CPU: {IDF_TARGET_TRANS_TIME_INTR_CPU} µs.
|
|
|
@@ -498,75 +571,100 @@ Note that these data are tested with :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` enable
|
|
|
SPI Clock Frequency
|
|
|
^^^^^^^^^^^^^^^^^^^
|
|
|
|
|
|
-Clock source of the GPSPI peripherals can be selected by setting :cpp:member:`spi_device_handle_t::cfg::clock_source`. You can refer to :cpp:type:`spi_clock_source_t` to know the supported clock sources.
|
|
|
-By default driver will set :cpp:member:`spi_device_handle_t::cfg::clock_source` to `SPI_CLK_SRC_DEFAULT`. This usually stands for the highest frequency among GPSPI clock sources. Its value will be different among chips.
|
|
|
+The clock source of the GPSPI peripherals can be selected by setting :cpp:member:`spi_device_handle_t::cfg::clock_source`. You can refer to :cpp:type:`spi_clock_source_t` to know the supported clock sources.
|
|
|
+By default driver will set :cpp:member:`spi_device_handle_t::cfg::clock_source` to ``SPI_CLK_SRC_DEFAULT``. This usually stands for the highest frequency among GPSPI clock sources. Its value will be different among chips.
|
|
|
|
|
|
-Actual clock frequency of a device may not be exactly equal to the number you set, it will be re-calculated by the driver to the nearest hardware compatible number, and not larger than the clock frequency of the clock source. You can call :cpp:func:`spi_device_get_actual_freq` to know the actual frequency computed by the driver.
|
|
|
+The actual clock frequency of a Device may not be exactly equal to the number you set, it will be re-calculated by the driver to the nearest hardware-compatible number, and not larger than the clock frequency of the clock source. You can call :cpp:func:`spi_device_get_actual_freq` to know the actual frequency computed by the driver.
|
|
|
|
|
|
-Theoretical maximum transfer speed of Write or Read phase can be calculated according to the table below:
|
|
|
+The theoretical maximum transfer speed of the Write or Read phase can be calculated according to the table below:
|
|
|
|
|
|
.. only:: not SOC_SPI_SUPPORT_OCT
|
|
|
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | Line Width of Write/Read phase | Speed (Bps) |
|
|
|
- +================================+========================+
|
|
|
- | 1-Line | *SPI Frequency / 8* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | 2-Line | *SPI Frequency / 4* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | 4-Line | *SPI Frequency / 2* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 40 30
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Line Width of Write/Read phase
|
|
|
+ - Speed (Bps)
|
|
|
+ * - 1-Line
|
|
|
+ - *SPI Frequency / 8*
|
|
|
+ * - 2-Line
|
|
|
+ - *SPI Frequency / 4*
|
|
|
+ * - 4-Line
|
|
|
+ - *SPI Frequency / 2*
|
|
|
|
|
|
.. only:: SOC_SPI_SUPPORT_OCT
|
|
|
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | Line Width of Write/Read phase | Speed (Bps) |
|
|
|
- +================================+========================+
|
|
|
- | 1-Line | *SPI Frequency / 8* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | 2-Line | *SPI Frequency / 4* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | 4-Line | *SPI Frequency / 2* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
- | 8-Line | *SPI Frequency* |
|
|
|
- +--------------------------------+------------------------+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 40 30
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Line Width of Write/Read phase
|
|
|
+ - Speed (Bps)
|
|
|
+ * - 1-Line
|
|
|
+ - *SPI Frequency / 8*
|
|
|
+ * - 2-Line
|
|
|
+ - *SPI Frequency / 4*
|
|
|
+ * - 4-Line
|
|
|
+ - *SPI Frequency / 2*
|
|
|
+ * - 8-Line
|
|
|
+ - *SPI Frequency*
|
|
|
|
|
|
-The transfer speed calculation of other phases(command, address, dummy) are similar.
|
|
|
+The transfer speed calculation of other phases(Command, Address, Dummy) is similar.
|
|
|
|
|
|
.. only:: esp32
|
|
|
|
|
|
If the clock frequency is too high, the use of some functions might be limited. See :ref:`timing_considerations`.
|
|
|
|
|
|
-Cache Miss
|
|
|
-^^^^^^^^^^
|
|
|
+Cache Missing
|
|
|
+^^^^^^^^^^^^^
|
|
|
|
|
|
-The default config puts only the ISR into the IRAM. Other SPI related functions, including the driver itself and the callback, might suffer from cache misses and will need to wait until the code is read from flash. Select :ref:`CONFIG_SPI_MASTER_IN_IRAM` to put the whole SPI driver into IRAM and put the entire callback(s) and its callee functions into IRAM to prevent cache misses.
|
|
|
+The default config puts only the ISR into the IRAM. Other SPI-related functions, including the driver itself and the callback, might suffer from cache misses and will need to wait until the code is read from flash. Select :ref:`CONFIG_SPI_MASTER_IN_IRAM` to put the whole SPI driver into IRAM and put the entire callback(s) and its callee functions into IRAM to prevent cache missing.
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
SPI driver implementation is based on FreeRTOS APIs, to use :ref:`CONFIG_SPI_MASTER_IN_IRAM`, you should not enable :ref:`CONFIG_FREERTOS_PLACE_FUNCTIONS_INTO_FLASH`.
|
|
|
|
|
|
-For an interrupt transaction, the overall cost is *20+8n/Fspi[MHz]* [us] for n bytes transferred in one transaction. Hence, the transferring speed is: *n/(20+8n/Fspi)*. An example of transferring speed at 8 MHz clock speed is given in the following table.
|
|
|
-
|
|
|
-+-----------+----------------------+--------------------+------------+-------------+
|
|
|
-| Frequency | Transaction Interval | Transaction Length | Total Time | Total Speed |
|
|
|
-| | | | | |
|
|
|
-| (MHz) | (us) | (bytes) | (us) | (KBps) |
|
|
|
-+===========+======================+====================+============+=============+
|
|
|
-| 8 | 25 | 1 | 26 | 38.5 |
|
|
|
-+-----------+----------------------+--------------------+------------+-------------+
|
|
|
-| 8 | 25 | 8 | 33 | 242.4 |
|
|
|
-+-----------+----------------------+--------------------+------------+-------------+
|
|
|
-| 8 | 25 | 16 | 41 | 490.2 |
|
|
|
-+-----------+----------------------+--------------------+------------+-------------+
|
|
|
-| 8 | 25 | 64 | 89 | 719.1 |
|
|
|
-+-----------+----------------------+--------------------+------------+-------------+
|
|
|
-| 8 | 25 | 128 | 153 | 836.6 |
|
|
|
-+-----------+----------------------+--------------------+------------+-------------+
|
|
|
-
|
|
|
-When a transaction length is short, the cost of transaction interval is high. If possible, try to squash several short transactions into one transaction to achieve a higher transfer speed.
|
|
|
-
|
|
|
-Please note that the ISR is disabled during flash operation by default. To keep sending transactions during flash operations, enable :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` and set :c:macro:`ESP_INTR_FLAG_IRAM` in the member :cpp:member:`spi_bus_config_t::intr_flags`. In this case, all the transactions queued before starting flash operations will be handled by the ISR in parallel. Also note that the callback of each Device and their callee functions should be in IRAM, or your callback will crash due to cache miss. For more details, see :ref:`iram-safe-interrupt-handlers`.
|
|
|
+For an interrupt transaction, the overall cost is *20+8n/Fspi[MHz]* [µs] for n bytes transferred in one transaction. Hence, the transferring speed is: *n/(20+8n/Fspi)*. An example of transferring speed at 8 MHz clock speed is given in the following table.
|
|
|
+
|
|
|
+.. list-table::
|
|
|
+ :widths: 30 45 40 30 30
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Frequency (MHz)
|
|
|
+ - Transaction Interval (µs)
|
|
|
+ - Transaction Length (bytes)
|
|
|
+ - Total Time (µs)
|
|
|
+ - Total Speed (KBps)
|
|
|
+ * - 8
|
|
|
+ - 25
|
|
|
+ - 1
|
|
|
+ - 26
|
|
|
+ - 38.5
|
|
|
+ * - 8
|
|
|
+ - 25
|
|
|
+ - 8
|
|
|
+ - 33
|
|
|
+ - 242.4
|
|
|
+ * - 8
|
|
|
+ - 25
|
|
|
+ - 16
|
|
|
+ - 41
|
|
|
+ - 490.2
|
|
|
+ * - 8
|
|
|
+ - 25
|
|
|
+ - 64
|
|
|
+ - 89
|
|
|
+ - 719.1
|
|
|
+ * - 8
|
|
|
+ - 25
|
|
|
+ - 128
|
|
|
+ - 153
|
|
|
+ - 836.6
|
|
|
+
|
|
|
+When a transaction length is short, the cost of the transaction interval is high. If possible, try to squash several short transactions into one transaction to achieve a higher transfer speed.
|
|
|
+
|
|
|
+Please note that the ISR is disabled during flash operation by default. To keep sending transactions during flash operations, enable :ref:`CONFIG_SPI_MASTER_ISR_IN_IRAM` and set :c:macro:`ESP_INTR_FLAG_IRAM` in the member :cpp:member:`spi_bus_config_t::intr_flags`. In this case, all the transactions queued before starting flash operations will be handled by the ISR in parallel. Also note that the callback of each Device and their callee functions should be in IRAM, or your callback will crash due to cache missing. For more details, see :ref:`iram-safe-interrupt-handlers`.
|
|
|
|
|
|
|
|
|
.. only:: esp32
|
|
|
@@ -593,25 +691,36 @@ Please note that the ISR is disabled during flash operation by default. To keep
|
|
|
|
|
|
.. _dummy_bit_workaround:
|
|
|
|
|
|
- **Dummy bit workaround**: Dummy clocks, during which the Host does not read data, can be inserted before the read phase begins. The Device still sees the dummy clocks and sends out data, but the Host does not read until the read phase comes. This compensates for the lack of the MISO setup time required by the Host and allows the Host to do reading at a higher frequency.
|
|
|
+ **Dummy bit workaround**: Dummy clocks, during which the Host does not read data, can be inserted before the Read phase begins. The Device still sees the dummy clocks and sends out data, but the Host does not read until the Read phase comes. This compensates for the lack of the MISO setup time required by the Host and allows the Host to do reading at a higher frequency.
|
|
|
|
|
|
In the ideal case, if the Device is so fast that the input delay is shorter than an APB clock cycle - 12.5 ns - the maximum frequency at which the Host can read (or read and write) in different conditions is as follows:
|
|
|
|
|
|
- +-------------+-------------+------------+-----------------------------+
|
|
|
- | Frequency Limit (MHz) | Dummy Bits | Comments |
|
|
|
- +-------------+-------------+ Used + +
|
|
|
- | GPIO matrix | IO_MUX pins | By Driver | |
|
|
|
- +=============+=============+============+=============================+
|
|
|
- | 26.6 | 80 | No | |
|
|
|
- +-------------+-------------+------------+-----------------------------+
|
|
|
- | 40 | -- | Yes | Half-duplex, no DMA allowed |
|
|
|
- +-------------+-------------+------------+-----------------------------+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 30 45 40 30
|
|
|
+ :header-rows: 1
|
|
|
|
|
|
- If the Host only writes data, the *dummy bit workaround* and the frequency check can be disabled by setting the bit `SPI_DEVICE_NO_DUMMY` in the member :cpp:member:`spi_device_interface_config_t::flags`. When disabled, the output frequency can be 80MHz, even if the GPIO matrix is used.
|
|
|
+ * - Frequency Limit (MHz)
|
|
|
+ - Frequency Limit (MHz)
|
|
|
+ - Dummy Bits Used by Driver
|
|
|
+ - Comments
|
|
|
+ * - GPIO Matrix
|
|
|
+ - IO_MUX Pins
|
|
|
+ -
|
|
|
+ -
|
|
|
+ * - 26.6
|
|
|
+ - 80
|
|
|
+ - No
|
|
|
+ -
|
|
|
+ * - 40
|
|
|
+ - --
|
|
|
+ - Yes
|
|
|
+ - Half-duplex, no DMA allowed
|
|
|
+
|
|
|
+ If the Host only writes data, the *dummy bit workaround* and the frequency check can be disabled by setting the bit ``SPI_DEVICE_NO_DUMMY`` in the member :cpp:member:`spi_device_interface_config_t::flags`. When disabled, the output frequency can be 80 MHz, even if the GPIO matrix is used.
|
|
|
|
|
|
:cpp:member:`spi_device_interface_config_t::flags`
|
|
|
|
|
|
- The SPI master driver still works even if the :cpp:member:`spi_device_interface_config_t::input_delay_ns` in the structure :cpp:type:`spi_device_interface_config_t` is set to 0. However, setting an accurate value helps to:
|
|
|
+ The SPI Master driver still works even if the :cpp:member:`spi_device_interface_config_t::input_delay_ns` in the structure :cpp:type:`spi_device_interface_config_t` is set to 0. However, setting an accurate value helps to:
|
|
|
|
|
|
- Calculate the frequency limit for full-duplex transactions
|
|
|
- Compensate the timing correctly with dummy bits for half-duplex transactions
|
|
|
@@ -620,19 +729,22 @@ Please note that the ISR is disabled during flash operation by default. To keep
|
|
|
|
|
|
Please note that the actual PCB layout design and excessive loads may increase the input delay. It means that non-optimal wiring and/or a load capacitor on the bus will most likely lead to input delay values exceeding the values given in the Device specification or measured while the bus is floating.
|
|
|
|
|
|
- Some typical delay values are shown in the following table. (These data are retrieved when the slave device is on a different physical chip)
|
|
|
+ Some typical delay values are shown in the following table. These data are retrieved when the slave Device is on a different physical chip.
|
|
|
+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 40 20
|
|
|
+ :header-rows: 1
|
|
|
|
|
|
- +----------------------------------------+------------------+
|
|
|
- | Device | Input delay (ns) |
|
|
|
- +========================================+==================+
|
|
|
- | Ideal Device | 0 |
|
|
|
- +----------------------------------------+------------------+
|
|
|
- | ESP32 slave using IO_MUX* | 50 |
|
|
|
- +----------------------------------------+------------------+
|
|
|
- | ESP32 slave using GPIO_MUX* | 75 |
|
|
|
- +----------------------------------------+------------------+
|
|
|
+ * - Device
|
|
|
+ - Input Delay (ns)
|
|
|
+ * - Ideal Device
|
|
|
+ - 0
|
|
|
+ * - ESP32 slave using IO_MUX
|
|
|
+ - 50
|
|
|
+ * - ESP32 slave using GPIO_MATRIX
|
|
|
+ - 75
|
|
|
|
|
|
- The MISO path delay (valid time) consists of a slave's *input delay* plus master's *GPIO matrix delay*. This delay determines the frequency limit above which full-duplex transfers will not work as well as the dummy bits used in the half-duplex transactions. The frequency limit is:
|
|
|
+ The MISO path delay (valid time) consists of a slave's *input delay* plus the master's *GPIO matrix delay*. The delay determines the above frequency limit for full-duplex transfers. Once exceeding, full-duplex transfers will not work as well as the half-duplex transactions that use dummy bits. The frequency limit is:
|
|
|
|
|
|
*Freq limit [MHz] = 80 / (floor(MISO delay[ns]/12.5) + 1)*
|
|
|
|
|
|
@@ -642,21 +754,43 @@ Please note that the ISR is disabled during flash operation by default. To keep
|
|
|
|
|
|
Corresponding frequency limits for different Devices with different *input delay* times are shown in the table below.
|
|
|
|
|
|
- +--------+------------------+----------------------+-------------------+
|
|
|
- | Master | Input delay (ns) | MISO path delay (ns) | Freq. limit (MHz) |
|
|
|
- +========+==================+======================+===================+
|
|
|
- | IO_MUX | 0 | 0 | 80 |
|
|
|
- + (0ns) +------------------+----------------------+-------------------+
|
|
|
- | | 50 | 50 | 16 |
|
|
|
- + +------------------+----------------------+-------------------+
|
|
|
- | | 75 | 75 | 11.43 |
|
|
|
- +--------+------------------+----------------------+-------------------+
|
|
|
- | GPIO | 0 | 25 | 26.67 |
|
|
|
- + (25ns) +------------------+----------------------+-------------------+
|
|
|
- | | 50 | 75 | 11.43 |
|
|
|
- + +------------------+----------------------+-------------------+
|
|
|
- | | 75 | 100 | 8.89 |
|
|
|
- +--------+------------------+----------------------+-------------------+
|
|
|
+ When the master is IO_MUX (0 ns):
|
|
|
+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 20 40 40
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Input Delay (ns)
|
|
|
+ - MISO Path Delay (ns)
|
|
|
+ - Freq. Limit (MHz)
|
|
|
+ * - 0
|
|
|
+ - 0
|
|
|
+ - 80
|
|
|
+ * - 50
|
|
|
+ - 50
|
|
|
+ - 16
|
|
|
+ * - 75
|
|
|
+ - 75
|
|
|
+ - 11.43
|
|
|
+
|
|
|
+ When the master is GPIO_MATRIX (25 ns):
|
|
|
+
|
|
|
+ .. list-table::
|
|
|
+ :widths: 20 40 40
|
|
|
+ :header-rows: 1
|
|
|
+
|
|
|
+ * - Input Delay (ns)
|
|
|
+ - MISO Path Delay (ns)
|
|
|
+ - Freq. Limit (MHz)
|
|
|
+ * - 0
|
|
|
+ - 25
|
|
|
+ - 26.67
|
|
|
+ * - 50
|
|
|
+ - 75
|
|
|
+ - 11.43
|
|
|
+ * - 75
|
|
|
+ - 100
|
|
|
+ - 8.89
|
|
|
|
|
|
|
|
|
.. only:: esp32
|
|
|
@@ -666,7 +800,7 @@ Please note that the ISR is disabled during flash operation by default. To keep
|
|
|
Known Issues
|
|
|
------------
|
|
|
|
|
|
- 1. Half-duplex transactions are not compatible with DMA when both writing and reading phases are used.
|
|
|
+ 1. Half-duplex transactions are not compatible with DMA when both the Write and Read phases are used.
|
|
|
|
|
|
If such transactions are required, you have to use one of the alternative solutions:
|
|
|
|
|
|
@@ -675,19 +809,19 @@ Please note that the ISR is disabled during flash operation by default. To keep
|
|
|
``ret=spi_bus_initialize(VSPI_HOST, &buscfg, 0);``
|
|
|
|
|
|
This can prohibit you from transmitting and receiving data longer than 64 bytes.
|
|
|
- 3. Try using the command and address fields to replace the write phase.
|
|
|
+ 3. Try using the command and address fields to replace the Write phase.
|
|
|
|
|
|
2. Full-duplex transactions are not compatible with the *dummy bit workaround*, hence the frequency is limited. See :ref:`dummy bit speed-up workaround <dummy_bit_workaround>`.
|
|
|
|
|
|
- 3. ``dummy_bits`` in :cpp:type:`spi_device_interface_config_t` and :cpp:type:`spi_transaction_ext_t` are not available when SPI read and write phases are both enabled (regardless of full duplex or half duplex mode).
|
|
|
+ 3. ``dummy_bits`` in :cpp:type:`spi_device_interface_config_t` and :cpp:type:`spi_transaction_ext_t` are not available when SPI Read and Write phases are both enabled (regardless of full duplex or half duplex mode).
|
|
|
|
|
|
- 4. ``cs_ena_pretrans`` is not compatible with the command and address phases of full-duplex transactions.
|
|
|
+ 4. ``cs_ena_pretrans`` is not compatible with the Command and Address phases of full-duplex transactions.
|
|
|
|
|
|
|
|
|
Application Example
|
|
|
-------------------
|
|
|
|
|
|
-The code example for using the SPI master half duplex mode to read/write a AT93C46D EEPROM (8-bit mode) can be found in the :example:`peripherals/spi_master/hd_eeprom` directory of ESP-IDF examples.
|
|
|
+The code example for using the SPI master half duplex mode to read/write an AT93C46D EEPROM (8-bit mode) can be found in the :example:`peripherals/spi_master/hd_eeprom` directory of ESP-IDF examples.
|
|
|
|
|
|
|
|
|
API Reference - SPI Common
|