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