1 /* 2 * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /******************************************************************************* 8 * NOTICE 9 * The hal is not public api, don't use in application code. 10 * See readme.md in hal/include/hal/readme.md 11 ******************************************************************************/ 12 13 // The HAL layer for SPI slave (common part) 14 15 // SPI slave HAL usages: 16 // 1. initialize the bus 17 // 2. initialize the DMA descriptors if DMA used 18 // 3. call setup_device to update parameters for the device 19 // 4. prepare data to send, and prepare the receiving buffer 20 // 5. trigger user defined SPI transaction to start 21 // 6. wait until the user transaction is done 22 // 7. store the received data and get the length 23 // 8. check and reset the DMA (if needed) before the next transaction 24 25 #pragma once 26 27 #include <esp_types.h> 28 #include "soc/lldesc.h" 29 #include "soc/spi_struct.h" 30 #include "soc/soc_caps.h" 31 #include "hal/spi_ll.h" 32 33 /** 34 * Context that should be maintained by both the driver and the HAL. 35 */ 36 typedef struct { 37 /* configured by driver at initialization, don't touch */ 38 spi_dev_t *hw; ///< Beginning address of the peripheral registers. 39 spi_dma_dev_t *dma_in; ///< Address of the DMA peripheral registers which stores the data received from a peripheral into RAM. 40 spi_dma_dev_t *dma_out; ///< Address of the DMA peripheral registers which transmits the data from RAM to a peripheral. 41 /* should be configured by driver at initialization */ 42 lldesc_t *dmadesc_rx; /**< Array of DMA descriptor used by the TX DMA. 43 * The amount should be larger than dmadesc_n. The driver should ensure that 44 * the data to be sent is shorter than the descriptors can hold. 45 */ 46 lldesc_t *dmadesc_tx; /**< Array of DMA descriptor used by the RX DMA. 47 * The amount should be larger than dmadesc_n. The driver should ensure that 48 * the data to be sent is shorter than the descriptors can hold. 49 */ 50 int dmadesc_n; ///< The amount of descriptors of both ``dmadesc_tx`` and ``dmadesc_rx`` that the HAL can use. 51 uint32_t tx_dma_chan; ///< TX DMA channel 52 uint32_t rx_dma_chan; ///< RX DMA channel 53 54 /* 55 * configurations to be filled after ``spi_slave_hal_init``. Updated to 56 * peripheral registers when ``spi_slave_hal_setup_device`` is called. 57 */ 58 struct { 59 uint32_t rx_lsbfirst : 1; 60 uint32_t tx_lsbfirst : 1; 61 uint32_t use_dma : 1; 62 }; 63 int mode; 64 65 /* 66 * Transaction specific (data), all these parameters will be updated to the 67 * peripheral every transaction. 68 */ 69 uint32_t bitlen; ///< Expected maximum length of the transaction, in bits. 70 const void *tx_buffer; ///< Data to be sent 71 void *rx_buffer; ///< Buffer to hold the received data. 72 73 /* Other transaction result after one transaction */ 74 uint32_t rcv_bitlen; ///< Length of the last transaction, in bits. 75 } spi_slave_hal_context_t; 76 77 typedef struct { 78 uint32_t host_id; ///< SPI controller ID 79 spi_dma_dev_t *dma_in; ///< Input DMA(DMA -> RAM) peripheral register address 80 spi_dma_dev_t *dma_out; ///< Output DMA(RAM -> DMA) peripheral register address 81 } spi_slave_hal_config_t; 82 83 /** 84 * Init the peripheral and the context. 85 * 86 * @param hal Context of the HAL layer. 87 * @param hal_config Configuration of the HAL 88 */ 89 void spi_slave_hal_init(spi_slave_hal_context_t *hal, const spi_slave_hal_config_t *hal_config); 90 91 /** 92 * Deinit the peripheral (and the context if needed). 93 * 94 * @param hal Context of the HAL layer. 95 */ 96 void spi_slave_hal_deinit(spi_slave_hal_context_t *hal); 97 98 /** 99 * Setup device-related configurations according to the settings in the context. 100 * 101 * @param hal Context of the HAL layer. 102 */ 103 void spi_slave_hal_setup_device(const spi_slave_hal_context_t *hal); 104 105 /** 106 * Prepare the data for the current transaction. 107 * 108 * @param hal Context of the HAL layer. 109 */ 110 void spi_slave_hal_prepare_data(const spi_slave_hal_context_t *hal); 111 112 /** 113 * Trigger start a user-defined transaction. 114 * 115 * @param hal Context of the HAL layer. 116 */ 117 void spi_slave_hal_user_start(const spi_slave_hal_context_t *hal); 118 119 /** 120 * Check whether the transaction is done (trans_done is set). 121 * 122 * @param hal Context of the HAL layer. 123 */ 124 bool spi_slave_hal_usr_is_done(spi_slave_hal_context_t* hal); 125 126 /** 127 * Post transaction operations, fetch data from the buffer and recored the length. 128 * 129 * @param hal Context of the HAL layer. 130 */ 131 void spi_slave_hal_store_result(spi_slave_hal_context_t *hal); 132 133 /** 134 * Get the length of last transaction, in bits. Should be called after ``spi_slave_hal_store_result``. 135 * 136 * Note that if last transaction is longer than configured before, the return 137 * value will be truncated to the configured length. 138 * 139 * @param hal Context of the HAL layer. 140 * 141 * @return Length of the last transaction, in bits. 142 */ 143 uint32_t spi_slave_hal_get_rcv_bitlen(spi_slave_hal_context_t *hal); 144 145 #if CONFIG_IDF_TARGET_ESP32 146 /** 147 * Check whether we need to reset the DMA according to the status of last transactions. 148 * 149 * In ESP32, sometimes we may need to reset the DMA for the slave before the 150 * next transaction. Call this to check it. 151 * 152 * @param hal Context of the HAL layer. 153 * 154 * @return true if reset is needed, else false. 155 */ 156 bool spi_slave_hal_dma_need_reset(const spi_slave_hal_context_t *hal); 157 #endif //#if CONFIG_IDF_TARGET_ESP32 158