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 /*
14  * The HAL layer for SPI Slave HD mode.
15  *
16  * Usage (segment mode):
17  * - Firstly, initialize the slave with `spi_slave_hd_hal_init`
18  *
19  * - Event handling:
20  *     - (Optional) Call ``spi_slave_hd_hal_enable_event_intr`` to enable the used interrupts
21  *     - (Basic) Call ``spi_slave_hd_hal_check_clear_event`` to check whether an event happen, and also
22  *       clear its interrupt. For events: SPI_EV_BUF_TX, SPI_EV_BUF_RX, SPI_EV_BUF_RX, SPI_EV_CMD9,
23  *       SPI_EV_CMDA.
24  *     - (Advanced) Call ``spi_slave_hd_hal_check_disable_event`` to disable the interrupt of an event,
25  *       so that the task can call ``spi_slave_hd_hal_invoke_event_intr`` later to manually invoke the
26  *       ISR. For SPI_EV_SEND, SPI_EV_RECV.
27  *
28  * - TXDMA:
29  *     - To send data through DMA, call `spi_slave_hd_hal_txdma`
30  *     - When the operation is done, SPI_EV_SEND will be triggered.
31  *
32  * - RXDMA:
33  *     - To receive data through DMA, call `spi_slave_hd_hal_rxdma`
34  *     - When the operation is done, SPI_EV_RECV will be triggered.
35  *     - Call ``spi_slave_hd_hal_rxdma_seg_get_len`` to get the received length
36  *
37  *  - Shared buffer:
38  *      - Call ``spi_slave_hd_hal_write_buffer`` to write the shared register buffer. When the buffer is
39  *        read by the master (regardless of the read address), SPI_EV_BUF_TX will be triggered
40  *      - Call ``spi_slave_hd_hal_read_buffer`` to read the shared register buffer. When the buffer is
41  *        written by the master (regardless of the written address), SPI_EV_BUF_RX will be triggered.
42  */
43 
44 #pragma once
45 
46 #include <esp_types.h>
47 #include "esp_err.h"
48 #include "hal/spi_ll.h"
49 #include "hal/spi_types.h"
50 
51 /**
52  * @brief Type of dma descriptor with appended members
53  *        this structure inherits DMA descriptor, with a pointer to the transaction descriptor passed from users.
54  */
55 typedef struct {
56     lldesc_t      desc;                             ///< DMA descriptor
57     void          *arg;                             ///< This points to the transaction descriptor user passed in
58 } spi_slave_hd_hal_desc_append_t;
59 
60 /// Configuration of the HAL
61 typedef struct {
62     uint32_t      host_id;                          ///< Host ID of the spi peripheral
63     spi_dma_dev_t *dma_in;                          ///< Input  DMA(DMA -> RAM) peripheral register address
64     spi_dma_dev_t *dma_out;                         ///< Output DMA(RAM -> DMA) peripheral register address
65     bool          dma_enabled;                      ///< DMA enabled or not
66     uint32_t      tx_dma_chan;                      ///< TX DMA channel used.
67     uint32_t      rx_dma_chan;                      ///< RX DMA channel used.
68     bool          append_mode;                      ///< True for DMA append mode, false for segment mode
69     uint32_t      spics_io_num;                     ///< CS GPIO pin for this device
70     uint8_t       mode;                             ///< SPI mode (0-3)
71     uint32_t      command_bits;                     ///< command field bits, multiples of 8 and at least 8.
72     uint32_t      address_bits;                     ///< address field bits, multiples of 8 and at least 8.
73     uint32_t      dummy_bits;                       ///< dummy field bits, multiples of 8 and at least 8.
74 
75     struct {
76         uint32_t  tx_lsbfirst : 1;                  ///< Whether TX data should be sent with LSB first.
77         uint32_t  rx_lsbfirst : 1;                  ///< Whether RX data should be read with LSB first.
78     };
79 } spi_slave_hd_hal_config_t;
80 
81 /// Context of the HAL, initialized by :cpp:func:`spi_slave_hd_hal_init`.
82 typedef struct {
83     /* These two need to be malloced by the driver first */
84     spi_slave_hd_hal_desc_append_t  *dmadesc_tx;            ///< Head of the TX DMA descriptors.
85     spi_slave_hd_hal_desc_append_t  *dmadesc_rx;            ///< Head of the RX DMA descriptors.
86 
87     /* address of the hardware */
88     spi_dev_t                       *dev;                   ///< Beginning address of the peripheral registers.
89     spi_dma_dev_t                   *dma_in;                ///< Address of the DMA peripheral registers which stores the data received from a peripheral into RAM.
90     spi_dma_dev_t                   *dma_out;               ///< Address of the DMA peripheral registers which transmits the data from RAM to a peripheral.
91     bool                            dma_enabled;            ///< DMA enabled or not
92     uint32_t                        tx_dma_chan;            ///< TX DMA channel used.
93     uint32_t                        rx_dma_chan;            ///< RX DMA channel used.
94     bool                            append_mode;            ///< True for DMA append mode, false for segment mode
95     uint32_t                        dma_desc_num;           ///< Number of the available DMA descriptors. Calculated from ``bus_max_transfer_size``.
96     spi_slave_hd_hal_desc_append_t  *tx_cur_desc;           ///< Current TX DMA descriptor that could be linked (set up).
97     spi_slave_hd_hal_desc_append_t  *tx_dma_head;           ///< Head of the linked TX DMA descriptors which are not used by hardware
98     spi_slave_hd_hal_desc_append_t  *tx_dma_tail;           ///< Tail of the linked TX DMA descriptors which are not used by hardware
99     spi_slave_hd_hal_desc_append_t  tx_dummy_head;          ///< Dummy descriptor for ``tx_dma_head`` to start
100     uint32_t                        tx_used_desc_cnt;       ///< Number of the TX descriptors that have been setup
101     uint32_t                        tx_recycled_desc_cnt;   ///< Number of the TX descriptors that could be recycled
102     spi_slave_hd_hal_desc_append_t  *rx_cur_desc;           ///< Current RX DMA descriptor that could be linked (set up).
103     spi_slave_hd_hal_desc_append_t  *rx_dma_head;           ///< Head of the linked RX DMA descriptors which are not used by hardware
104     spi_slave_hd_hal_desc_append_t  *rx_dma_tail;           ///< Tail of the linked RX DMA descriptors which are not used by hardware
105     spi_slave_hd_hal_desc_append_t  rx_dummy_head;          ///< Dummy descriptor for ``rx_dma_head`` to start
106     uint32_t                        rx_used_desc_cnt;       ///< Number of the RX descriptors that have been setup
107     uint32_t                        rx_recycled_desc_cnt;   ///< Number of the RX descriptors that could be recycled
108 
109     /* Internal status used by the HAL implementation, initialized as 0. */
110     uint32_t                        intr_not_triggered;
111     bool                            tx_dma_started;
112     bool                            rx_dma_started;
113 } spi_slave_hd_hal_context_t;
114 
115 /**
116  * @brief Initialize the hardware and part of the context
117  *
118  * @param hal        Context of the HAL layer
119  * @param hal_config Configuration of the HAL
120  */
121 void spi_slave_hd_hal_init(spi_slave_hd_hal_context_t *hal, const spi_slave_hd_hal_config_t *hal_config);
122 
123 /**
124  * @brief Get the size of one DMA descriptor
125  *
126  * @param hal       Context of the HAL layer
127  * @param bus_size  SPI bus maximum transfer size, in bytes.
128  * @return          Total size needed for all the DMA descriptors
129  */
130 uint32_t spi_slave_hd_hal_get_total_desc_size(spi_slave_hd_hal_context_t *hal, uint32_t bus_size);
131 
132 /**
133  * @brief Get the actual bus size
134  *
135  * @param hal       Context of the HAL layer
136  * @return          Actual bus transaction size
137  */
138 uint32_t spi_salve_hd_hal_get_max_bus_size(spi_slave_hd_hal_context_t *hal);
139 
140 /**
141  * @brief Check and clear signal of one event
142  *
143  * @param hal       Context of the HAL layer
144  * @param ev        Event to check
145  * @return          True if event triggered, otherwise false
146  */
147 bool spi_slave_hd_hal_check_clear_event(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
148 
149 /**
150  * @brief Check and clear the interrupt of one event.
151  *
152  * @note The event source will be kept, so that the interrupt can be invoked by
153  *       :cpp:func:`spi_slave_hd_hal_invoke_event_intr`. If event not triggered, its interrupt source
154  *       will not be disabled either.
155  *
156  * @param hal       Context of the HAL layer
157  * @param ev        Event to check and disable
158  * @return          True if event triggered, otherwise false
159  */
160 bool spi_slave_hd_hal_check_disable_event(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
161 
162 /**
163  * @brief Enable to invole the ISR of corresponding event.
164  *
165  * @note The function, compared with :cpp:func:`spi_slave_hd_hal_enable_event_intr`, contains a
166  *       workaround to force trigger the interrupt, even if the interrupt source cannot be initialized
167  *       correctly.
168  *
169  * @param hal       Context of the HAL layer
170  * @param ev        Event (reason) to invoke the ISR
171  */
172 void spi_slave_hd_hal_invoke_event_intr(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
173 
174 /**
175  * @brief Enable the interrupt source of corresponding event.
176  *
177  * @param hal       Context of the HAL layer
178  * @param ev        Event whose corresponding interrupt source should be enabled.
179  */
180 void spi_slave_hd_hal_enable_event_intr(spi_slave_hd_hal_context_t* hal, spi_event_t ev);
181 
182 ////////////////////////////////////////////////////////////////////////////////
183 // RX DMA
184 ////////////////////////////////////////////////////////////////////////////////
185 /**
186  * @brief Start the RX DMA operation to the specified buffer.
187  *
188  * @param hal       Context of the HAL layer
189  * @param[out] out_buf  Buffer to receive the data
190  * @param len       Maximul length to receive
191  */
192 void spi_slave_hd_hal_rxdma(spi_slave_hd_hal_context_t *hal, uint8_t *out_buf, size_t len);
193 
194 /**
195  * @brief Get the length of total received data
196  *
197  * @param hal       Context of the HAL layer
198  * @return          The received length
199  */
200 int spi_slave_hd_hal_rxdma_seg_get_len(spi_slave_hd_hal_context_t *hal);
201 
202 ////////////////////////////////////////////////////////////////////////////////
203 // TX DMA
204 ////////////////////////////////////////////////////////////////////////////////
205 /**
206  * @brief Start the TX DMA operation with the specified buffer
207  *
208  * @param hal       Context of the HAL layer
209  * @param data      Buffer of data to send
210  * @param len       Size of the buffer, also the maximum length to send
211  */
212 void spi_slave_hd_hal_txdma(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len);
213 
214 ////////////////////////////////////////////////////////////////////////////////
215 // Shared buffer
216 ////////////////////////////////////////////////////////////////////////////////
217 /**
218  * @brief Read from the shared register buffer
219  *
220  * @param hal       Context of the HAL layer
221  * @param addr      Address of the shared regsiter to read
222  * @param out_data  Buffer to store the read data
223  * @param len       Length to read from the shared buffer
224  */
225 void spi_slave_hd_hal_read_buffer(spi_slave_hd_hal_context_t *hal, int addr, uint8_t *out_data, size_t len);
226 
227 /**
228  * @brief Write the shared register buffer
229  *
230  * @param hal       Context of the HAL layer
231  * @param addr      Address of the shared register to write
232  * @param data      Buffer of the data to write
233  * @param len       Length to write into the shared buffer
234  */
235 void spi_slave_hd_hal_write_buffer(spi_slave_hd_hal_context_t *hal, int addr, uint8_t *data, size_t len);
236 
237 /**
238  * @brief Get the length of previous transaction.
239  *
240  * @param hal       Context of the HAL layer
241  * @return          The length of previous transaction
242  */
243 int spi_slave_hd_hal_get_rxlen(spi_slave_hd_hal_context_t *hal);
244 
245 /**
246  * @brief Get the address of last transaction
247  *
248  * @param hal       Context of the HAL layer
249  * @return          The address of last transaction
250  */
251 int spi_slave_hd_hal_get_last_addr(spi_slave_hd_hal_context_t *hal);
252 
253 
254 ////////////////////////////////////////////////////////////////////////////////
255 // Append Mode
256 ////////////////////////////////////////////////////////////////////////////////
257 /**
258  * @brief Return the finished TX transaction
259  *
260  * @note This API is based on this assumption: the hardware behaviour of current transaction completion is only modified by the its own caller layer.
261  * This means if some other code changed the hardware behaviour (e.g. clear intr raw bit), or the caller call this API without noticing the HW behaviour,
262  * this API will go wrong.
263  *
264  * @param hal            Context of the HAL layer
265  * @param out_trans      Pointer to the caller-defined transaction
266  * @return               1: Transaction is finished; 0: Transaction is not finished
267  */
268 bool spi_slave_hd_hal_get_tx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans);
269 
270 /**
271  * @brief Return the finished RX transaction
272  *
273  * @note This API is based on this assumption: the hardware behaviour of current transaction completion is only modified by the its own caller layer.
274  * This means if some other code changed the hardware behaviour (e.g. clear intr raw bit), or the caller call this API without noticing the HW behaviour,
275  * this API will go wrong.
276  *
277  * @param hal            Context of the HAL layer
278  * @param out_trans      Pointer to the caller-defined transaction
279  * @param out_len        Actual number of bytes of received data
280  * @return               1: Transaction is finished; 0: Transaction is not finished
281  */
282 bool spi_slave_hd_hal_get_rx_finished_trans(spi_slave_hd_hal_context_t *hal, void **out_trans, size_t *out_len);
283 
284 /**
285  * @brief Load the TX DMA descriptors without stopping the DMA
286  *
287  * @param hal            Context of the HAL layer
288  * @param data           Buffer of the transaction data
289  * @param len            Length of the data
290  * @param arg            Pointer used by the caller to indicate the tranaction. Will be returned by ``spi_slave_hd_hal_get_tx_finished_trans`` when transaction is finished
291  * @return
292  *        - ESP_OK: on success
293  *        - ESP_ERR_INVALID_STATE: Function called in invalid state.
294  */
295 esp_err_t spi_slave_hd_hal_txdma_append(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len, void *arg);
296 
297 /**
298  * @brief Load the RX DMA descriptors without stopping the DMA
299  *
300  * @param hal            Context of the HAL layer
301  * @param data           Buffer of the transaction data
302  * @param len            Length of the data
303  * @param arg            Pointer used by the caller to indicate the tranaction. Will be returned by ``spi_slave_hd_hal_get_rx_finished_trans`` when transaction is finished
304  * @return
305  *        - ESP_OK: on success
306  *        - ESP_ERR_INVALID_STATE: Function called in invalid state.
307  */
308 esp_err_t spi_slave_hd_hal_rxdma_append(spi_slave_hd_hal_context_t *hal, uint8_t *data, size_t len, void *arg);
309