1 /* 2 * SPDX-FileCopyrightText: 2010-2021 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 #pragma once 8 9 #include "esp_types.h" 10 #include "soc/soc_caps.h" 11 #include "freertos/FreeRTOS.h" 12 13 #include "hal/spi_types.h" 14 #include "driver/spi_common.h" 15 #include "sdkconfig.h" 16 17 #ifdef __cplusplus 18 extern "C" 19 { 20 #endif 21 22 #if !SOC_SPI_SUPPORT_SLAVE_HD_VER2 && !CI_HEADER_CHECK 23 #error The SPI peripheral does not support this feature 24 #endif 25 26 /// Descriptor of data to send/receive 27 typedef struct { 28 uint8_t* data; ///< Buffer to send, must be DMA capable 29 size_t len; ///< Len of data to send/receive. For receiving the buffer length should be multiples of 4 bytes, otherwise the extra part will be truncated. 30 size_t trans_len; ///< For RX direction, it indicates the data actually received. For TX direction, it is meaningless. 31 void* arg; ///< Extra argument indiciating this data 32 } spi_slave_hd_data_t; 33 34 /// Information of SPI Slave HD event 35 typedef struct { 36 spi_event_t event; ///< Event type 37 spi_slave_hd_data_t* trans; ///< Corresponding transaction for SPI_EV_SEND and SPI_EV_RECV events 38 } spi_slave_hd_event_t; 39 40 /// Callback for SPI Slave HD 41 typedef bool (*slave_cb_t)(void* arg, spi_slave_hd_event_t* event, BaseType_t* awoken); 42 43 /// Channel of SPI Slave HD to do data transaction 44 typedef enum { 45 SPI_SLAVE_CHAN_TX = 0, ///< The output channel (RDDMA) 46 SPI_SLAVE_CHAN_RX = 1, ///< The input channel (WRDMA) 47 } spi_slave_chan_t; 48 49 /// Callback configuration structure for SPI Slave HD 50 typedef struct { 51 slave_cb_t cb_buffer_tx; ///< Callback when master reads from shared buffer 52 slave_cb_t cb_buffer_rx; ///< Callback when master writes to shared buffer 53 slave_cb_t cb_send_dma_ready; ///< Callback when TX data buffer is loaded to the hardware (DMA) 54 slave_cb_t cb_sent; ///< Callback when data are sent 55 slave_cb_t cb_recv_dma_ready; ///< Callback when RX data buffer is loaded to the hardware (DMA) 56 slave_cb_t cb_recv; ///< Callback when data are received 57 slave_cb_t cb_cmd9; ///< Callback when CMD9 received 58 slave_cb_t cb_cmdA; ///< Callback when CMDA received 59 void* arg; ///< Argument indicating this SPI Slave HD peripheral instance 60 } spi_slave_hd_callback_config_t; 61 62 63 //flags for ``spi_slave_hd_slot_config_t`` to use 64 #define SPI_SLAVE_HD_TXBIT_LSBFIRST (1<<0) ///< Transmit command/address/data LSB first instead of the default MSB first 65 #define SPI_SLAVE_HD_RXBIT_LSBFIRST (1<<1) ///< Receive data LSB first instead of the default MSB first 66 #define SPI_SLAVE_HD_BIT_LSBFIRST (SPI_SLAVE_HD_TXBIT_LSBFIRST|SPI_SLAVE_HD_RXBIT_LSBFIRST) ///< Transmit and receive LSB first 67 #define SPI_SLAVE_HD_APPEND_MODE (1<<2) ///< Adopt DMA append mode for transactions. In this mode, users can load(append) DMA descriptors without stopping the DMA 68 69 /// Configuration structure for the SPI Slave HD driver 70 typedef struct { 71 uint8_t mode; /**< SPI mode, representing a pair of (CPOL, CPHA) configuration: 72 - 0: (0, 0) 73 - 1: (0, 1) 74 - 2: (1, 0) 75 - 3: (1, 1) 76 */ 77 uint32_t spics_io_num; ///< CS GPIO pin for this device 78 uint32_t flags; ///< Bitwise OR of SPI_SLAVE_HD_* flags 79 uint32_t command_bits; ///< command field bits, multiples of 8 and at least 8. 80 uint32_t address_bits; ///< address field bits, multiples of 8 and at least 8. 81 uint32_t dummy_bits; ///< dummy field bits, multiples of 8 and at least 8. 82 uint32_t queue_size; ///< Transaction queue size. This sets how many transactions can be 'in the air' (queued using spi_slave_hd_queue_trans but not yet finished using spi_slave_hd_get_trans_result) at the same time 83 spi_dma_chan_t dma_chan; ///< DMA channel to used. 84 spi_slave_hd_callback_config_t cb_config; ///< Callback configuration 85 } spi_slave_hd_slot_config_t; 86 87 /** 88 * @brief Initialize the SPI Slave HD driver. 89 * 90 * @param host_id The host to use 91 * @param bus_config Bus configuration for the bus used 92 * @param config Configuration for the SPI Slave HD driver 93 * @return 94 * - ESP_OK: on success 95 * - ESP_ERR_INVALID_ARG: invalid argument given 96 * - ESP_ERR_INVALID_STATE: function called in invalid state, may be some resources are already in use 97 * - ESP_ERR_NOT_FOUND if there is no available DMA channel 98 * - ESP_ERR_NO_MEM: memory allocation failed 99 * - or other return value from `esp_intr_alloc` 100 */ 101 esp_err_t spi_slave_hd_init(spi_host_device_t host_id, const spi_bus_config_t *bus_config, 102 const spi_slave_hd_slot_config_t *config); 103 104 /** 105 * @brief Deinitialize the SPI Slave HD driver 106 * 107 * @param host_id The host to deinitialize the driver 108 * @return 109 * - ESP_OK: on success 110 * - ESP_ERR_INVALID_ARG: if the host_id is not correct 111 */ 112 esp_err_t spi_slave_hd_deinit(spi_host_device_t host_id); 113 114 /** 115 * @brief Queue transactions (segment mode) 116 * 117 * @param host_id Host to queue the transaction 118 * @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX 119 * @param trans Transaction descriptors 120 * @param timeout Timeout before the data is queued 121 * @return 122 * - ESP_OK: on success 123 * - ESP_ERR_INVALID_ARG: The input argument is invalid. Can be the following reason: 124 * - The buffer given is not DMA capable 125 * - The length of data is invalid (not larger than 0, or exceed the max transfer length) 126 * - The transaction direction is invalid 127 * - ESP_ERR_TIMEOUT: Cannot queue the data before timeout. Master is still processing previous transaction. 128 * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under segment mode. 129 */ 130 esp_err_t spi_slave_hd_queue_trans(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t* trans, TickType_t timeout); 131 132 /** 133 * @brief Get the result of a data transaction (segment mode) 134 * 135 * @note This API should be called successfully the same times as the ``spi_slave_hd_queue_trans``. 136 * 137 * @param host_id Host to queue the transaction 138 * @param chan Channel to get the result, SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX 139 * @param[out] out_trans Pointer to the transaction descriptor (``spi_slave_hd_data_t``) passed to the driver before. Hardware has finished this transaction. Member ``trans_len`` indicates the actual number of bytes of received data, it's meaningless for TX. 140 * @param timeout Timeout before the result is got 141 * @return 142 * - ESP_OK: on success 143 * - ESP_ERR_INVALID_ARG: Function is not valid 144 * - ESP_ERR_TIMEOUT: There's no transaction done before timeout 145 * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under segment mode. 146 */ 147 esp_err_t spi_slave_hd_get_trans_res(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t **out_trans, TickType_t timeout); 148 149 /** 150 * @brief Read the shared registers 151 * 152 * @param host_id Host to read the shared registers 153 * @param addr Address of register to read, 0 to ``SOC_SPI_MAXIMUM_BUFFER_SIZE-1`` 154 * @param[out] out_data Output buffer to store the read data 155 * @param len Length to read, not larger than ``SOC_SPI_MAXIMUM_BUFFER_SIZE-addr`` 156 */ 157 void spi_slave_hd_read_buffer(spi_host_device_t host_id, int addr, uint8_t *out_data, size_t len); 158 159 /** 160 * @brief Write the shared registers 161 * 162 * @param host_id Host to write the shared registers 163 * @param addr Address of register to write, 0 to ``SOC_SPI_MAXIMUM_BUFFER_SIZE-1`` 164 * @param data Buffer holding the data to write 165 * @param len Length to write, ``SOC_SPI_MAXIMUM_BUFFER_SIZE-addr`` 166 */ 167 void spi_slave_hd_write_buffer(spi_host_device_t host_id, int addr, uint8_t *data, size_t len); 168 169 /** 170 * @brief Load transactions (append mode) 171 * 172 * @note In this mode, user transaction descriptors will be appended to the DMA and the DMA will keep processing the data without stopping 173 * 174 * @param host_id Host to load transactions 175 * @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX 176 * @param trans Transaction descriptor 177 * @param timeout Timeout before the transaction is loaded 178 * @return 179 * - ESP_OK: on success 180 * - ESP_ERR_INVALID_ARG: The input argument is invalid. Can be the following reason: 181 * - The buffer given is not DMA capable 182 * - The length of data is invalid (not larger than 0, or exceed the max transfer length) 183 * - The transaction direction is invalid 184 * - ESP_ERR_TIMEOUT: Master is still processing previous transaction. There is no available transaction for slave to load 185 * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under append mode. 186 */ 187 esp_err_t spi_slave_hd_append_trans(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t *trans, TickType_t timeout); 188 189 /** 190 * @brief Get the result of a data transaction (append mode) 191 * 192 * @note This API should be called the same times as the ``spi_slave_hd_append_trans`` 193 * 194 * @param host_id Host to load the transaction 195 * @param chan SPI_SLAVE_CHAN_TX or SPI_SLAVE_CHAN_RX 196 * @param[out] out_trans Pointer to the transaction descriptor (``spi_slave_hd_data_t``) passed to the driver before. Hardware has finished this transaction. Member ``trans_len`` indicates the actual number of bytes of received data, it's meaningless for TX. 197 * @param timeout Timeout before the result is got 198 * @return 199 * - ESP_OK: on success 200 * - ESP_ERR_INVALID_ARG: Function is not valid 201 * - ESP_ERR_TIMEOUT: There's no transaction done before timeout 202 * - ESP_ERR_INVALID_STATE: Function called in invalid state. This API should be called under append mode. 203 */ 204 esp_err_t spi_slave_hd_get_append_trans_res(spi_host_device_t host_id, spi_slave_chan_t chan, spi_slave_hd_data_t **out_trans, TickType_t timeout); 205 206 #ifdef __cplusplus 207 } 208 #endif 209