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