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 master (common part) 22 23 // SPI HAL usages: 24 // 1. initialize the bus 25 // 2. initialize the DMA descriptors if DMA used 26 // 3. setup the clock speed (since this takes long time) 27 // 4. call setup_device to update parameters for the specific device 28 // 5. call setup_trans to update parameters for the specific transaction 29 // 6. prepare data to send, and prepare the receiving buffer 30 // 7. trigger user defined SPI transaction to start 31 // 8. wait until the user transaction is done 32 // 9. fetch the received data 33 // Parameter to be updated only during ``setup_device`` will be highlighted in the 34 // field comments. 35 36 #pragma once 37 #include "hal/spi_ll.h" 38 #include <esp_err.h> 39 #include "soc/lldesc.h" 40 #include "soc/soc_caps.h" 41 #include "hal/spi_types.h" 42 43 /** 44 * Input parameters to the ``spi_hal_cal_clock_conf`` to calculate the timing configuration 45 */ 46 typedef struct { 47 uint32_t half_duplex; ///< Whether half duplex mode is used, device specific 48 uint32_t no_compensate; ///< No need to add dummy to compensate the timing, device specific 49 uint32_t clock_speed_hz; ///< Desired frequency. 50 uint32_t duty_cycle; ///< Desired duty cycle of SPI clock 51 uint32_t input_delay_ns; /**< Maximum delay between SPI launch clock and the data to be valid. 52 * This is used to compensate/calculate the maximum frequency allowed. 53 * Left 0 if not known. 54 */ 55 bool use_gpio; ///< True if the GPIO matrix is used, otherwise false 56 } spi_hal_timing_param_t; 57 58 /** 59 * Timing configuration structure that should be calculated by 60 * ``spi_hal_cal_clock_conf`` at initialization and hold. Filled into the 61 * ``timing_conf`` member of the context of HAL before setup a device. 62 */ 63 typedef struct { 64 spi_ll_clock_val_t clock_reg; ///< Register value used by the LL layer 65 int timing_dummy; ///< Extra dummy needed to compensate the timing 66 int timing_miso_delay; ///< Extra miso delay clocks to compensate the timing 67 } spi_hal_timing_conf_t; 68 69 /** 70 * DMA configuration structure 71 * Should be set by driver at initialization 72 */ 73 typedef struct { 74 spi_dma_dev_t *dma_in; ///< Input DMA(DMA -> RAM) peripheral register address 75 spi_dma_dev_t *dma_out; ///< Output DMA(RAM -> DMA) peripheral register address 76 bool dma_enabled; ///< Whether the DMA is enabled, do not update after initialization 77 lldesc_t *dmadesc_tx; /**< Array of DMA descriptor used by the TX DMA. 78 * The amount should be larger than dmadesc_n. The driver should ensure that 79 * the data to be sent is shorter than the descriptors can hold. 80 */ 81 lldesc_t *dmadesc_rx; /**< Array of DMA descriptor used by the RX DMA. 82 * The amount should be larger than dmadesc_n. The driver should ensure that 83 * the data to be sent is shorter than the descriptors can hold. 84 */ 85 uint32_t tx_dma_chan; ///< TX DMA channel 86 uint32_t rx_dma_chan; ///< RX DMA channel 87 int dmadesc_n; ///< The amount of descriptors of both ``dmadesc_tx`` and ``dmadesc_rx`` that the HAL can use. 88 } spi_hal_config_t; 89 90 /** 91 * Transaction configuration structure, this should be assigned by driver each time. 92 * All these parameters will be updated to the peripheral every transaction. 93 */ 94 typedef struct { 95 uint16_t cmd; ///< Command value to be sent 96 int cmd_bits; ///< Length (in bits) of the command phase 97 int addr_bits; ///< Length (in bits) of the address phase 98 int dummy_bits; ///< Base length (in bits) of the dummy phase. Note when the compensation is enabled, some extra dummy bits may be appended. 99 int tx_bitlen; ///< TX length, in bits 100 int rx_bitlen; ///< RX length, in bits 101 uint64_t addr; ///< Address value to be sent 102 uint8_t *send_buffer; ///< Data to be sent 103 uint8_t *rcv_buffer; ///< Buffer to hold the receive data. 104 spi_line_mode_t line_mode; ///< SPI line mode of this transaction 105 int cs_keep_active; ///< Keep CS active after transaction 106 } spi_hal_trans_config_t; 107 108 /** 109 * Context that should be maintained by both the driver and the HAL. 110 */ 111 typedef struct { 112 /* These two need to be malloced by the driver first */ 113 lldesc_t *dmadesc_tx; /**< Array of DMA descriptor used by the TX DMA. 114 * The amount should be larger than dmadesc_n. The driver should ensure that 115 * the data to be sent is shorter than the descriptors can hold. 116 */ 117 lldesc_t *dmadesc_rx; /**< Array of DMA descriptor used by the RX DMA. 118 * The amount should be larger than dmadesc_n. The driver should ensure that 119 * the data to be sent is shorter than the descriptors can hold. 120 */ 121 122 /* Configured by driver at initialization, don't touch */ 123 spi_dev_t *hw; ///< Beginning address of the peripheral registers. 124 spi_dma_dev_t *dma_in; ///< Address of the DMA peripheral registers which stores the data received from a peripheral into RAM (DMA -> RAM). 125 spi_dma_dev_t *dma_out; ///< Address of the DMA peripheral registers which transmits the data from RAM to a peripheral (RAM -> DMA). 126 bool dma_enabled; ///< Whether the DMA is enabled, do not update after initialization 127 uint32_t tx_dma_chan; ///< TX DMA channel 128 uint32_t rx_dma_chan; ///< RX DMA channel 129 int dmadesc_n; ///< The amount of descriptors of both ``dmadesc_tx`` and ``dmadesc_rx`` that the HAL can use. 130 131 /* Internal parameters, don't touch */ 132 spi_hal_trans_config_t trans_config; ///< Transaction configuration 133 } spi_hal_context_t; 134 135 /** 136 * Device configuration structure, this should be initialised by driver based on different devices respectively. 137 * All these parameters will be updated to the peripheral only when ``spi_hal_setup_device``. 138 * They may not get updated when ``spi_hal_setup_trans``. 139 */ 140 typedef struct { 141 int mode; ///< SPI mode, device specific 142 int cs_setup; ///< Setup time of CS active edge before the first SPI clock, device specific 143 int cs_hold; ///< Hold time of CS inactive edge after the last SPI clock, device specific 144 int cs_pin_id; ///< CS pin to use, 0-2, otherwise all the CS pins are not used. Device specific 145 spi_hal_timing_conf_t timing_conf; /**< This structure holds the pre-calculated timing configuration for the device 146 * at initialization, device specific 147 */ 148 struct { 149 uint32_t sio : 1; ///< Whether to use SIO mode, device specific 150 uint32_t half_duplex : 1; ///< Whether half duplex mode is used, device specific 151 uint32_t tx_lsbfirst : 1; ///< Whether LSB is sent first for TX data, device specific 152 uint32_t rx_lsbfirst : 1; ///< Whether LSB is received first for RX data, device specific 153 uint32_t no_compensate : 1; ///< No need to add dummy to compensate the timing, device specific 154 #if SOC_SPI_SUPPORT_AS_CS 155 uint32_t as_cs : 1; ///< Whether to toggle the CS while the clock toggles, device specific 156 #endif 157 uint32_t positive_cs : 1; ///< Whether the postive CS feature is abled, device specific 158 };//boolean configurations 159 } spi_hal_dev_config_t; 160 161 /** 162 * Init the peripheral and the context. 163 * 164 * @param hal Context of the HAL layer. 165 * @param host_id Index of the SPI peripheral. 0 for SPI1, 1 for SPI2 and 2 for SPI3. 166 * @param hal_config Configuration of the hal defined by the upper layer. 167 */ 168 void spi_hal_init(spi_hal_context_t *hal, uint32_t host_id, const spi_hal_config_t *hal_config); 169 170 /** 171 * Deinit the peripheral (and the context if needed). 172 * 173 * @param hal Context of the HAL layer. 174 */ 175 void spi_hal_deinit(spi_hal_context_t *hal); 176 177 /** 178 * Setup device-related configurations according to the settings in the context. 179 * 180 * @param hal Context of the HAL layer. 181 * @param hal_dev Device configuration 182 */ 183 void spi_hal_setup_device(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev); 184 185 /** 186 * Setup transaction related configurations according to the settings in the context. 187 * 188 * @param hal Context of the HAL layer. 189 * @param hal_dev Device configuration 190 * @param hal_trans Transaction configuration 191 */ 192 void spi_hal_setup_trans(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev, const spi_hal_trans_config_t *hal_trans); 193 194 /** 195 * Prepare the data for the current transaction. 196 * 197 * @param hal Context of the HAL layer. 198 * @param hal_dev Device configuration 199 * @param hal_trans Transaction configuration 200 */ 201 void spi_hal_prepare_data(spi_hal_context_t *hal, const spi_hal_dev_config_t *hal_dev, const spi_hal_trans_config_t *hal_trans); 202 203 /** 204 * Trigger start a user-defined transaction. 205 * 206 * @param hal Context of the HAL layer. 207 */ 208 void spi_hal_user_start(const spi_hal_context_t *hal); 209 210 /** 211 * Check whether the transaction is done (trans_done is set). 212 * 213 * @param hal Context of the HAL layer. 214 */ 215 bool spi_hal_usr_is_done(const spi_hal_context_t *hal); 216 217 /** 218 * Post transaction operations, mainly fetch data from the buffer. 219 * 220 * @param hal Context of the HAL layer. 221 */ 222 void spi_hal_fetch_result(const spi_hal_context_t *hal); 223 224 /*---------------------------------------------------------- 225 * Utils 226 * ---------------------------------------------------------*/ 227 /** 228 * Calculate the configuration of clock and timing. The configuration will be used when ``spi_hal_setup_device``. 229 * 230 * It is highly suggested to do this at initialization, since it takes long time. 231 * 232 * @param timing_param Input parameters to calculate timing configuration 233 * @param out_freq Output of the actual frequency, left NULL if not required. 234 * @param timing_conf Output of the timing configuration. 235 * 236 * @return ESP_OK if desired is available, otherwise fail. 237 */ 238 esp_err_t spi_hal_cal_clock_conf(const spi_hal_timing_param_t *timing_param, int *out_freq, spi_hal_timing_conf_t *timing_conf); 239 240 /** 241 * Get the frequency actual used. 242 * 243 * @param hal Context of the HAL layer. 244 * @param fapb APB clock frequency. 245 * @param hz Desired frequencyc. 246 * @param duty_cycle Desired duty cycle. 247 */ 248 int spi_hal_master_cal_clock(int fapb, int hz, int duty_cycle); 249 250 /** 251 * Get the timing configuration for given parameters. 252 * 253 * @param eff_clk Actual SPI clock frequency 254 * @param gpio_is_used true if the GPIO matrix is used, otherwise false. 255 * @param input_delay_ns Maximum delay between SPI launch clock and the data to 256 * be valid. This is used to compensate/calculate the maximum frequency 257 * allowed. Left 0 if not known. 258 * @param dummy_n Dummy cycles required to correctly read the data. 259 * @param miso_delay_n suggested delay on the MISO line, in APB clocks. 260 */ 261 void spi_hal_cal_timing(int eff_clk, bool gpio_is_used, int input_delay_ns, int *dummy_n, int *miso_delay_n); 262 263 /** 264 * Get the maximum frequency allowed to read if no compensation is used. 265 * 266 * @param gpio_is_used true if the GPIO matrix is used, otherwise false. 267 * @param input_delay_ns Maximum delay between SPI launch clock and the data to 268 * be valid. This is used to compensate/calculate the maximum frequency 269 * allowed. Left 0 if not known. 270 */ 271 int spi_hal_get_freq_limit(bool gpio_is_used, int input_delay_ns); 272