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