2021-05-23 19:50:04 -04:00
/*
2024-04-08 23:58:11 -04:00
* SPDX - FileCopyrightText : 2010 - 2024 Espressif Systems ( Shanghai ) CO LTD
2021-05-23 19:50:04 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
2017-03-31 03:05:25 -04:00
2019-06-25 23:30:07 -04:00
# pragma once
2017-03-31 03:05:25 -04:00
# include <stdint.h>
# include <stdbool.h>
2022-01-05 03:17:12 -05:00
# include "sdkconfig.h"
2017-03-31 03:05:25 -04:00
# include "esp_err.h"
2023-01-09 03:18:24 -05:00
# include "esp_ipc.h"
2023-07-12 22:44:06 -04:00
# include "esp_intr_types.h"
2019-06-13 02:12:54 -04:00
# include "hal/spi_types.h"
2017-03-31 03:05:25 -04:00
# ifdef __cplusplus
extern " C "
{
# endif
//Maximum amount of bytes that can be put in one DMA descriptor
# define SPI_MAX_DMA_LEN (4096-4)
2018-06-27 06:41:57 -04:00
/**
* Transform unsigned integer of length < = 32 bits to the format which can be
* sent by the SPI driver directly .
*
* E . g . to send 9 bits of data , you can :
*
* uint16_t data = SPI_SWAP_DATA_TX ( 0x145 , 9 ) ;
*
* Then points tx_buffer to ` ` & data ` ` .
*
2019-09-01 15:41:34 -04:00
* @ param DATA Data to be sent , can be uint8_t , uint16_t or uint32_t .
* @ param LEN Length of data to be sent , since the SPI peripheral sends from
* the MSB , this helps to shift the data to the MSB .
2018-06-27 06:41:57 -04:00
*/
2019-09-01 15:41:34 -04:00
# define SPI_SWAP_DATA_TX(DATA, LEN) __builtin_bswap32((uint32_t)(DATA)<<(32-(LEN)))
2018-06-27 06:41:57 -04:00
/**
* Transform received data of length < = 32 bits to the format of an unsigned integer .
*
* E . g . to transform the data of 15 bits placed in a 4 - byte array to integer :
*
* uint16_t data = SPI_SWAP_DATA_RX ( * ( uint32_t * ) t - > rx_data , 15 ) ;
*
2019-09-01 15:41:34 -04:00
* @ param DATA Data to be rearranged , can be uint8_t , uint16_t or uint32_t .
* @ param LEN Length of data received , since the SPI peripheral writes from
2018-06-27 06:41:57 -04:00
* the MSB , this helps to shift the data to the LSB .
*/
2019-09-01 15:41:34 -04:00
# define SPI_SWAP_DATA_RX(DATA, LEN) (__builtin_bswap32(DATA)>>(32-(LEN)))
2017-03-31 03:05:25 -04:00
2019-09-03 02:06:26 -04:00
# define SPICOMMON_BUSFLAG_SLAVE 0 ///< Initialize I/O in slave mode
# define SPICOMMON_BUSFLAG_MASTER (1<<0) ///< Initialize I/O in master mode
# 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.
2020-04-29 04:18:25 -04:00
# 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.
# define SPICOMMON_BUSFLAG_SCLK (1<<3) ///< Check existing of SCLK pin. Or indicates CLK line initialized.
# define SPICOMMON_BUSFLAG_MISO (1<<4) ///< Check existing of MISO pin. Or indicates MISO line initialized.
# define SPICOMMON_BUSFLAG_MOSI (1<<5) ///< Check existing of MOSI pin. Or indicates MOSI line initialized.
# define SPICOMMON_BUSFLAG_DUAL (1<<6) ///< Check MOSI and MISO pins can output. Or indicates bus able to work under DIO mode.
# define SPICOMMON_BUSFLAG_WPHD (1<<7) ///< Check existing of WP and HD pins. Or indicates WP & HD pins initialized.
2019-09-03 02:06:26 -04:00
# 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.
2021-07-09 04:46:27 -04:00
# define SPICOMMON_BUSFLAG_IO4_IO7 (1<<8) ///< Check existing of IO4~IO7 pins. Or indicates IO4~IO7 pins initialized.
# define SPICOMMON_BUSFLAG_OCTAL (SPICOMMON_BUSFLAG_QUAD|SPICOMMON_BUSFLAG_IO4_IO7) ///< Check existing of MOSI/MISO/WP/HD/SPIIO4/SPIIO5/SPIIO6/SPIIO7 pins as output. Or indicates bus able to work under octal mode.
2019-09-03 02:06:26 -04:00
# define SPICOMMON_BUSFLAG_NATIVE_PINS SPICOMMON_BUSFLAG_IOMUX_PINS
2021-02-19 22:03:28 -05:00
/**
* @ brief SPI DMA channels
*/
typedef enum {
2023-10-19 02:38:32 -04:00
SPI_DMA_DISABLED = 0 , ///< Do not enable DMA for SPI
2021-02-19 22:03:28 -05:00
# if CONFIG_IDF_TARGET_ESP32
2023-10-19 02:38:32 -04:00
SPI_DMA_CH1 = 1 , ///< Enable DMA, select DMA Channel 1
SPI_DMA_CH2 = 2 , ///< Enable DMA, select DMA Channel 2
2021-02-19 22:03:28 -05:00
# endif
2023-10-19 02:38:32 -04:00
SPI_DMA_CH_AUTO = 3 , ///< Enable DMA, channel is automatically selected by driver
2021-02-19 22:03:28 -05:00
} spi_common_dma_t ;
# if __cplusplus
/* Needed for C++ backwards compatibility with earlier ESP-IDF where this argument is a bare 'int'. Can be removed in ESP-IDF 5 */
typedef int spi_dma_chan_t ;
# else
typedef spi_common_dma_t spi_dma_chan_t ;
# endif
2019-09-03 02:06:26 -04:00
2017-03-31 03:05:25 -04:00
/**
* @ brief This is a configuration structure for a SPI bus .
*
* You can use this structure to specify the GPIO pins of the bus . Normally , the driver will use the
2018-06-27 06:41:57 -04:00
* GPIO matrix to route the signals . An exception is made when all signals either can be routed through
2024-02-29 03:51:31 -05:00
* the IO_MUX or are - 1. In that case , the IO_MUX is used . On ESP32 , using GPIO matrix will bring about 25 ns of input
* delay , which may cause incorrect read for > 40 MHz speeds .
2017-05-02 04:36:01 -04:00
*
2024-03-25 02:11:33 -04:00
* @ note Be advised that the slave driver does not use the quadwp / quadhd lines and fields in spi_bus_config_t referring to these lines will be ignored and can thus safely be left uninitialized .
2017-03-31 03:05:25 -04:00
*/
typedef struct {
2021-07-09 04:46:27 -04:00
union {
2023-10-19 02:38:32 -04:00
int mosi_io_num ; ///< GPIO pin for Master Out Slave In (=spi_d) signal, or -1 if not used.
int data0_io_num ; ///< GPIO pin for spi data0 signal in quad/octal mode, or -1 if not used.
2021-07-09 04:46:27 -04:00
} ;
union {
2023-10-19 02:38:32 -04:00
int miso_io_num ; ///< GPIO pin for Master In Slave Out (=spi_q) signal, or -1 if not used.
int data1_io_num ; ///< GPIO pin for spi data1 signal in quad/octal mode, or -1 if not used.
2021-07-09 04:46:27 -04:00
} ;
int sclk_io_num ; ///< GPIO pin for SPI Clock signal, or -1 if not used.
union {
2023-10-19 02:38:32 -04:00
int quadwp_io_num ; ///< GPIO pin for WP (Write Protect) signal, or -1 if not used.
int data2_io_num ; ///< GPIO pin for spi data2 signal in quad/octal mode, or -1 if not used.
2021-07-09 04:46:27 -04:00
} ;
union {
2023-10-19 02:38:32 -04:00
int quadhd_io_num ; ///< GPIO pin for HD (Hold) signal, or -1 if not used.
int data3_io_num ; ///< GPIO pin for spi data3 signal in quad/octal mode, or -1 if not used.
2021-07-09 04:46:27 -04:00
} ;
int data4_io_num ; ///< GPIO pin for spi data4 signal in octal mode, or -1 if not used.
int data5_io_num ; ///< GPIO pin for spi data5 signal in octal mode, or -1 if not used.
int data6_io_num ; ///< GPIO pin for spi data6 signal in octal mode, or -1 if not used.
int data7_io_num ; ///< GPIO pin for spi data7 signal in octal mode, or -1 if not used.
int max_transfer_sz ; ///< Maximum transfer size, in bytes. Defaults to 4092 if 0 when DMA enabled, or to `SOC_SPI_MAXIMUM_BUFFER_SIZE` if DMA is disabled.
uint32_t flags ; ///< Abilities of bus to be checked by the driver. Or-ed value of ``SPICOMMON_BUSFLAG_*`` flags.
2023-07-12 22:44:06 -04:00
esp_intr_cpu_affinity_t isr_cpu_id ; ///< Select cpu core to register SPI ISR.
2021-07-09 04:46:27 -04:00
int intr_flags ; /**< Interrupt flag for the bus to set the priority, and IRAM attribute, see
* ` ` esp_intr_alloc . h ` ` . Note that the EDGE , INTRDISABLED attribute are ignored
* by the driver . Note that if ESP_INTR_FLAG_IRAM is set , ALL the callbacks of
* the driver , and their callee functions , should be put in the IRAM .
*/
2017-03-31 03:05:25 -04:00
} spi_bus_config_t ;
2019-06-25 01:36:24 -04:00
/**
* @ brief Initialize a SPI bus
*
2021-03-05 03:20:33 -05:00
* @ warning SPI0 / 1 is not supported
2019-06-25 01:36:24 -04:00
*
2021-02-03 02:14:17 -05:00
* @ param host_id SPI peripheral that controls this bus
* @ param bus_config Pointer to a spi_bus_config_t struct specifying how the host should be initialized
2021-02-19 22:03:28 -05:00
* @ 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 .
* - Selecting SPI_DMA_DISABLED limits the size of transactions .
* - Set to SPI_DMA_DISABLED if only the SPI flash uses this bus .
* - Set to SPI_DMA_CH_AUTO to let the driver to allocate the DMA channel .
2019-06-25 01:36:24 -04:00
*
* @ warning If a DMA channel is selected , any transmit and receive buffer used should be allocated in
* DMA - capable memory .
*
* @ warning The ISR of SPI is always executed on the core which calls this
* function . Never starve the ISR on this core or the SPI transactions will not
* be handled .
*
* @ return
* - ESP_ERR_INVALID_ARG if configuration is invalid
2021-02-03 02:14:17 -05:00
* - ESP_ERR_INVALID_STATE if host already is in use
* - ESP_ERR_NOT_FOUND if there is no available DMA channel
2019-06-25 01:36:24 -04:00
* - ESP_ERR_NO_MEM if out of memory
* - ESP_OK on success
*/
2021-02-19 22:03:28 -05:00
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 ) ;
2019-06-25 01:36:24 -04:00
/**
* @ brief Free a SPI bus
*
* @ warning In order for this to succeed , all devices have to be removed first .
*
2019-10-24 07:00:26 -04:00
* @ param host_id SPI peripheral to free
2019-06-25 01:36:24 -04:00
* @ return
* - ESP_ERR_INVALID_ARG if parameter is invalid
2022-03-24 04:28:37 -04:00
* - ESP_ERR_INVALID_STATE if bus hasn ' t been initialized before , or not all devices on the bus are freed
2019-06-25 01:36:24 -04:00
* - ESP_OK on success
*/
2019-10-24 07:00:26 -04:00
esp_err_t spi_bus_free ( spi_host_device_t host_id ) ;
2019-06-25 01:36:24 -04:00
2024-04-08 23:58:11 -04:00
/**
* @ brief Helper function for malloc DMA capable memory for SPI driver
*
* @ note This API will take care of the cache and hardware alignment internally .
* To free / release memory allocated by this helper function , simply calling ` free ( ) `
*
* @ param [ in ] size Size in bytes , the amount of memory to allocate
* @ param [ out ] out_ptr Pointer to the memory if allocated successfully
* @ param [ in ] extra_heap_caps Extra heap caps based on MALLOC_CAP_DMA
* @ param [ out ] actual_size Optional , Actual size for allocation in bytes , when the size you specified doesn ' t meet the internal alignment requirements ,
* This value might be bigger than the size you specified . Set NULL if don ' t care this value .
*
* @ return
* - ESP_ERR_INVALID_ARG Invalid argument
* - ESP_ERR_NO_MEM No enough memory for allocation
* - ESP_OK on success
*/
esp_err_t spi_bus_dma_memory_malloc ( size_t size , void * * out_ptr , uint32_t extra_heap_caps , size_t * actual_size ) ;
2017-03-31 03:05:25 -04:00
# ifdef __cplusplus
}
# endif