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