diff --git a/components/spi_flash/README.rst b/components/spi_flash/README.rst index 02c26950c..6c56ff7a3 100644 --- a/components/spi_flash/README.rst +++ b/components/spi_flash/README.rst @@ -94,6 +94,8 @@ To avoid reading flash cache accidentally, when one CPU initiates a flash write If one CPU initiates a flash write or erase operation, the other CPU is put into a blocked state to avoid reading flash cache accidentally. All interrupts not safe for IRAM are disabled on both CPUs until the flash operation completes. +Please also see :ref:`esp_flash_os_func`, :ref:`spi_bus_lock`. + .. _iram-safe-interrupt-handlers: IRAM-Safe Interrupt Handlers @@ -219,21 +221,28 @@ chip. The chip driver relies on the host driver. +.. _esp_flash_os_func: + OS functions ^^^^^^^^^^^^ -Currently the OS function layer provides a lock and a delay entries. +Currently the OS function layer provides entries of a lock and delay. -The lock is used to resolve the conflicts between the SPI chip access and -other functions. E.g. the cache (used for the code and PSRAM data fetch) -should be disabled when the flash chip on the SPI0/1 is being accessed. Also, -some devices which don't have CS wire, or the wire is controlled by the -software (e.g. SD card via SPI interface), requires the bus to be monopolized -during a period. +The lock (see :ref:`spi_bus_lock`) is used to resolve the conflicts among the access of devices +on the same SPI bus, and the SPI Flash chip access. E.g. + +1. On SPI1 bus, the cache (used to fetch the data (code) in the Flash and PSRAM) should be + disabled when the flash chip on the SPI0/1 is being accessed. + +2. On the other buses, the flash driver needs to disable the ISR registered by SPI Master driver, + to avoid conflicts. + +3. Some devices of SPI Master driver may requires to use the bus monopolized during a period. + (especially when the device doesn't have CS wire, or the wire is controlled by the software + like SDSPI driver). The delay is used by some long operations which requires the master to wait or polling periodically. - The top API wraps these the chip driver and OS functions into an entire component, and also provides some argument checking. diff --git a/docs/en/api-reference/peripherals/spi_features.rst b/docs/en/api-reference/peripherals/spi_features.rst new file mode 100644 index 000000000..cf9b94715 --- /dev/null +++ b/docs/en/api-reference/peripherals/spi_features.rst @@ -0,0 +1,39 @@ +SPI Features +============ + +.. _spi_master_features: + +SPI Master +---------- + +.. _spi_bus_lock: + +SPI Bus Lock +^^^^^^^^^^^^ + +To realize the multiplexing of different devices from different drivers (SPI Master, SPI Flash, +etc.), an SPI bus lock is applied on each SPI bus. Drivers can attach their devices onto the bus +with the arbitration of the lock. + +Each bus lock are initialized with a BG (background) service registered, all devices request to +do transactions on the bus should wait until the BG to be successfully disabled. + +- For SPI1 bus, the BG is the cache, the bus lock will help to disable the cache before device + operations starts, and enable it again after device releasing the lock. No devices on SPI1 is + allowed using ISR (it's meaningless for the task to yield to other tasks when the cache is + disabled). + + .. only:: esp32 + + There are quite a few limitations when using SPI Master driver on the SPI1 bus, see + :ref:`spi_master_on_spi1_bus`. + + .. only:: esp32s2 + + The SPI Master driver hasn't supported SPI1 bus. Only SPI Flash driver can attach to the bus. + +- For other buses, the driver may register its ISR as the BG. The bus lock will block a device + task when it requests for exclusive use of the bus, try to disable the ISR, and unblock the + device task allowed to exclusively use the bus when the ISR is successfully disabled. When the + task releases the lock, the lock will also try to resume the ISR if there are pending + transactions to be done in the ISR. diff --git a/docs/en/api-reference/peripherals/spi_master.rst b/docs/en/api-reference/peripherals/spi_master.rst index ddb565401..adbf52ec0 100644 --- a/docs/en/api-reference/peripherals/spi_master.rst +++ b/docs/en/api-reference/peripherals/spi_master.rst @@ -9,7 +9,17 @@ Overview of {IDF_TARGET_NAME}'s SPI peripherals ESP32 integrates four SPI peripherals. -- SPI0 and SPI1 are used internally to access the ESP32's attached flash memory and thus are currently not open to users. They share one signal bus via an arbiter. +- SPI0 and SPI1 are used internally to access the ESP32's attached flash memory and share an arbiter. + + .. only:: esp32 + + There are quite a few limitations when using SPI Master driver on the SPI1 bus, see + :ref:`spi_master_on_spi1_bus`. + + .. only:: esp32s2 + + Currently SPI Master driver hasn't supported SPI1 bus. + - 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 signal buses with the same respective names. Each bus has three CS lines to drive up to three SPI slaves. @@ -44,7 +54,7 @@ The SPI master driver governs communications of Hosts with Devices. The driver s - Multi-threaded environments - Transparent handling of DMA transfers while reading and writing data -- Automatic time-division multiplexing of data coming from different Devices on the same signal bus +- Automatic time-division multiplexing of data coming from different Devices on the same signal bus, see :ref:`spi_bus_lock`. .. warning:: @@ -53,6 +63,10 @@ The SPI master driver governs communications of Hosts with Devices. The driver s - Refactor your application so that each SPI peripheral is only accessed by a single task at a time. - Add a mutex lock around the shared Device using :c:macro:`xSemaphoreCreateMutex`. +.. toctree:: + :hidden: + + SPI Features SPI Transactions ---------------- @@ -224,6 +238,69 @@ To have better control of the calling sequence of functions, send mixed transact .. only:: esp32 + .. _spi_master_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. + + 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. + + 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: + + - 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 + ` documentation. + + To place functions into the IRAM, you can either: + + 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. + + 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. + + 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. + + To place data into the DRAM, you can either: + + 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`. + + Please also see the example :example:`peripherals/spi_master/hd_eeprom`. + + GPIO Matrix and IO_MUX ---------------------- diff --git a/docs/zh_CN/api-reference/peripherals/spi_features.rst b/docs/zh_CN/api-reference/peripherals/spi_features.rst new file mode 100644 index 000000000..81d130515 --- /dev/null +++ b/docs/zh_CN/api-reference/peripherals/spi_features.rst @@ -0,0 +1 @@ +.. include:: ../../../en/api-reference/peripherals/spi_features.rst \ No newline at end of file