1 // Copyright 2010-2019 Espressif Systems (Shanghai) PTE LTD 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 #pragma once 16 17 #include <stdint.h> 18 #include <stdbool.h> 19 #include "esp_err.h" 20 #include "soc/lldesc.h" 21 #include "soc/spi_periph.h" 22 #include "hal/spi_types.h" 23 #include "sdkconfig.h" 24 25 #ifdef __cplusplus 26 extern "C" 27 { 28 #endif 29 30 //Maximum amount of bytes that can be put in one DMA descriptor 31 #define SPI_MAX_DMA_LEN (4096-4) 32 33 /** 34 * Transform unsigned integer of length <= 32 bits to the format which can be 35 * sent by the SPI driver directly. 36 * 37 * E.g. to send 9 bits of data, you can: 38 * 39 * uint16_t data = SPI_SWAP_DATA_TX(0x145, 9); 40 * 41 * Then points tx_buffer to ``&data``. 42 * 43 * @param DATA Data to be sent, can be uint8_t, uint16_t or uint32_t. 44 * @param LEN Length of data to be sent, since the SPI peripheral sends from 45 * the MSB, this helps to shift the data to the MSB. 46 */ 47 #define SPI_SWAP_DATA_TX(DATA, LEN) __builtin_bswap32((uint32_t)(DATA)<<(32-(LEN))) 48 49 /** 50 * Transform received data of length <= 32 bits to the format of an unsigned integer. 51 * 52 * E.g. to transform the data of 15 bits placed in a 4-byte array to integer: 53 * 54 * uint16_t data = SPI_SWAP_DATA_RX(*(uint32_t*)t->rx_data, 15); 55 * 56 * @param DATA Data to be rearranged, can be uint8_t, uint16_t or uint32_t. 57 * @param LEN Length of data received, since the SPI peripheral writes from 58 * the MSB, this helps to shift the data to the LSB. 59 */ 60 #define SPI_SWAP_DATA_RX(DATA, LEN) (__builtin_bswap32(DATA)>>(32-(LEN))) 61 62 #define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode 63 #define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode 64 #define SPICOMMON_BUSFLAG_IOMUX_PINS (1<<1) ///< Check using iomux pins. Or indicates the pins are configured through the IO mux rather than GPIO matrix. 65 #define SPICOMMON_BUSFLAG_GPIO_PINS (1<<2) ///< Force the signals to be routed through GPIO matrix. Or indicates the pins are routed through the GPIO matrix. 66 #define SPICOMMON_BUSFLAG_SCLK (1<<3) ///< Check existing of SCLK pin. Or indicates CLK line initialized. 67 #define SPICOMMON_BUSFLAG_MISO (1<<4) ///< Check existing of MISO pin. Or indicates MISO line initialized. 68 #define SPICOMMON_BUSFLAG_MOSI (1<<5) ///< Check existing of MOSI pin. Or indicates MOSI line initialized. 69 #define SPICOMMON_BUSFLAG_DUAL (1<<6) ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode. 70 #define SPICOMMON_BUSFLAG_WPHD (1<<7) ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized. 71 #define SPICOMMON_BUSFLAG_QUAD (SPICOMMON_BUSFLAG_DUAL|SPICOMMON_BUSFLAG_WPHD) ///< Check existing of MOSI/MISO/WP/HD pins as output. Or indicates bus able to work under QIO mode. 72 73 #define SPICOMMON_BUSFLAG_NATIVE_PINS SPICOMMON_BUSFLAG_IOMUX_PINS 74 75 /** 76 * @brief SPI DMA channels 77 */ 78 typedef enum { 79 SPI_DMA_DISABLED = 0, ///< Do not enable DMA for SPI 80 #if CONFIG_IDF_TARGET_ESP32 81 SPI_DMA_CH1 = 1, ///< Enable DMA, select DMA Channel 1 82 SPI_DMA_CH2 = 2, ///< Enable DMA, select DMA Channel 2 83 #endif 84 SPI_DMA_CH_AUTO = 3, ///< Enable DMA, channel is automatically selected by driver 85 } spi_common_dma_t; 86 87 #if __cplusplus 88 /* Needed for C++ backwards compatibility with earlier ESP-IDF where this argument is a bare 'int'. Can be removed in ESP-IDF 5 */ 89 typedef int spi_dma_chan_t; 90 #else 91 typedef spi_common_dma_t spi_dma_chan_t; 92 #endif 93 94 /** 95 * @brief This is a configuration structure for a SPI bus. 96 * 97 * You can use this structure to specify the GPIO pins of the bus. Normally, the driver will use the 98 * GPIO matrix to route the signals. An exception is made when all signals either can be routed through 99 * the IO_MUX or are -1. In that case, the IO_MUX is used, allowing for >40MHz speeds. 100 * 101 * @note Be advised that the slave driver does not use the quadwp/quadhd lines and fields in spi_bus_config_t refering to these lines will be ignored and can thus safely be left uninitialized. 102 */ 103 typedef struct { 104 int mosi_io_num; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used. 105 int miso_io_num; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used. 106 int sclk_io_num; ///< GPIO pin for Spi CLocK signal, or -1 if not used. 107 int quadwp_io_num; ///< GPIO pin for WP (Write Protect) signal which is used as D2 in 4-bit communication modes, or -1 if not used. 108 int quadhd_io_num; ///< GPIO pin for HD (HolD) signal which is used as D3 in 4-bit communication modes, or -1 if not used. 109 int max_transfer_sz; ///< Maximum transfer size, in bytes. Defaults to 4094 if 0. 110 uint32_t flags; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags. 111 int intr_flags; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see 112 * ``esp_intr_alloc.h``. Note that the EDGE, INTRDISABLED attribute are ignored 113 * by the driver. Note that if ESP_INTR_FLAG_IRAM is set, ALL the callbacks of 114 * the driver, and their callee functions, should be put in the IRAM. 115 */ 116 } spi_bus_config_t; 117 118 119 /** 120 * @brief Initialize a SPI bus 121 * 122 * @warning SPI0/1 is not supported 123 * 124 * @param host_id SPI peripheral that controls this bus 125 * @param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized 126 * @param dma_chan - Selecting a DMA channel for an SPI bus allows transactions on the bus with size only limited by the amount of internal memory. 127 * - Selecting SPI_DMA_DISABLED limits the size of transactions. 128 * - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus. 129 * - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel. 130 * 131 * @warning If a DMA channel is selected, any transmit and receive buffer used should be allocated in 132 * DMA-capable memory. 133 * 134 * @warning The ISR of SPI is always executed on the core which calls this 135 * function. Never starve the ISR on this core or the SPI transactions will not 136 * be handled. 137 * 138 * @return 139 * - ESP_ERR_INVALID_ARG if configuration is invalid 140 * - ESP_ERR_INVALID_STATE if host already is in use 141 * - ESP_ERR_NOT_FOUND if there is no available DMA channel 142 * - ESP_ERR_NO_MEM if out of memory 143 * - ESP_OK on success 144 */ 145 esp_err_t spi_bus_initialize(spi_host_device_t host_id, const spi_bus_config_t *bus_config, spi_dma_chan_t dma_chan); 146 147 /** 148 * @brief Free a SPI bus 149 * 150 * @warning In order for this to succeed, all devices have to be removed first. 151 * 152 * @param host_id SPI peripheral to free 153 * @return 154 * - ESP_ERR_INVALID_ARG if parameter is invalid 155 * - ESP_ERR_INVALID_STATE if not all devices on the bus are freed 156 * - ESP_OK on success 157 */ 158 esp_err_t spi_bus_free(spi_host_device_t host_id); 159 160 #ifdef __cplusplus 161 } 162 #endif 163