• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2010-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 // Internal header, don't use it in the user code
16 
17 #pragma once
18 
19 #include <esp_intr_alloc.h>
20 #include "driver/spi_common.h"
21 #include "esp_osal/esp_osal.h"
22 #include "hal/spi_types.h"
23 
24 #ifdef __cplusplus
25 extern "C"
26 {
27 #endif
28 
29 
30 #ifdef CONFIG_SPI_MASTER_ISR_IN_IRAM
31 #define SPI_MASTER_ISR_ATTR IRAM_ATTR
32 #else
33 #define SPI_MASTER_ISR_ATTR
34 #endif
35 
36 #ifdef CONFIG_SPI_MASTER_IN_IRAM
37 #define SPI_MASTER_ATTR IRAM_ATTR
38 #else
39 #define SPI_MASTER_ATTR
40 #endif
41 
42 
43 #define BUS_LOCK_DEBUG  0
44 
45 #if BUS_LOCK_DEBUG
46 #define BUS_LOCK_DEBUG_EXECUTE_CHECK(x)  assert(x)
47 #else
48 #define BUS_LOCK_DEBUG_EXECUTE_CHECK(x)
49 #endif
50 
51 
52 struct spi_bus_lock_t;
53 struct spi_bus_lock_dev_t;
54 /// Handle to the lock of an SPI bus
55 typedef struct spi_bus_lock_t* spi_bus_lock_handle_t;
56 /// Handle to lock of one of the device on an SPI bus
57 typedef struct spi_bus_lock_dev_t* spi_bus_lock_dev_handle_t;
58 
59 /// Background operation control function
60 typedef void (*bg_ctrl_func_t)(void*);
61 
62 /// Attributes of an SPI bus
63 typedef struct {
64     spi_bus_config_t bus_cfg;   ///< Config used to initialize the bus
65     uint32_t flags;             ///< Flags (attributes) of the bus
66     int max_transfer_sz;        ///< Maximum length of bytes available to send
67     bool dma_enabled;           ///< To enable DMA or not
68     int tx_dma_chan;            ///< TX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
69     int rx_dma_chan;            ///< RX DMA channel, on ESP32 and ESP32S2, tx_dma_chan and rx_dma_chan are same
70     int dma_desc_num;           ///< DMA descriptor number of dmadesc_tx or dmadesc_rx.
71     lldesc_t *dmadesc_tx;       ///< DMA descriptor array for TX
72     lldesc_t *dmadesc_rx;       ///< DMA descriptor array for RX
73     spi_bus_lock_handle_t lock;
74 #ifdef CONFIG_PM_ENABLE
75     esp_pm_lock_handle_t pm_lock;   ///< Power management lock
76 #endif
77 } spi_bus_attr_t;
78 
79 /// Destructor called when a bus is deinitialized.
80 typedef esp_err_t (*spi_destroy_func_t)(void*);
81 
82 
83 /**
84  * @brief Try to claim a SPI peripheral
85  *
86  * Call this if your driver wants to manage a SPI peripheral.
87  *
88  * @param host Peripheral to claim
89  * @param source The caller indentification string.
90  *
91  * @note This public API is deprecated.
92  *
93  * @return True if peripheral is claimed successfully; false if peripheral already is claimed.
94  */
95 bool spicommon_periph_claim(spi_host_device_t host, const char* source);
96 
97 /**
98  * @brief Check whether the spi periph is in use.
99  *
100  * @param host Peripheral to check.
101  *
102  * @note This public API is deprecated.
103  *
104  * @return True if in use, otherwise false.
105  */
106 bool spicommon_periph_in_use(spi_host_device_t host);
107 
108 /**
109  * @brief Return the SPI peripheral so another driver can claim it.
110  *
111  * @param host Peripheral to return
112  *
113  * @note This public API is deprecated.
114  *
115  * @return True if peripheral is returned successfully; false if peripheral was free to claim already.
116  */
117 bool spicommon_periph_free(spi_host_device_t host);
118 
119 /**
120  * @brief Alloc DMA for SPI Slave
121  *
122  * @param host_id                      SPI host ID
123  * @param dma_chan                     DMA channel to be used
124  * @param[out] out_actual_tx_dma_chan  Actual TX DMA channel (if you choose to assign a specific DMA channel, this will be the channel you assigned before)
125  * @param[out] out_actual_rx_dma_chan  Actual RX DMA channel (if you choose to assign a specific DMA channel, this will be the channel you assigned before)
126  *
127  * @return
128  *        - ESP_OK:                On success
129  *        - ESP_ERR_NO_MEM:        No enough memory
130  *        - ESP_ERR_NOT_FOUND:     There is no available DMA channel
131  */
132 esp_err_t spicommon_slave_dma_chan_alloc(spi_host_device_t host_id, spi_dma_chan_t dma_chan, uint32_t *out_actual_tx_dma_chan, uint32_t *out_actual_rx_dma_chan);
133 
134 /**
135  * @brief Free DMA for SPI Slave
136  *
137  * @param host_id  SPI host ID
138  *
139  * @return
140  *        - ESP_OK: On success
141  */
142 esp_err_t spicommon_slave_free_dma(spi_host_device_t host_id);
143 
144 /**
145  * @brief Connect a SPI peripheral to GPIO pins
146  *
147  * This routine is used to connect a SPI peripheral to the IO-pads and DMA channel given in
148  * the arguments. Depending on the IO-pads requested, the routing is done either using the
149  * IO_mux or using the GPIO matrix.
150  *
151  * @note This public API is deprecated. Please call ``spi_bus_initialize`` for master
152  *       bus initialization and ``spi_slave_initialize`` for slave initialization.
153  *
154  * @param host SPI peripheral to be routed
155  * @param bus_config Pointer to a spi_bus_config struct detailing the GPIO pins
156  * @param flags Combination of SPICOMMON_BUSFLAG_* flags, set to ensure the pins set are capable with some functions:
157  *              - ``SPICOMMON_BUSFLAG_MASTER``: Initialize I/O in master mode
158  *              - ``SPICOMMON_BUSFLAG_SLAVE``: Initialize I/O in slave mode
159  *              - ``SPICOMMON_BUSFLAG_IOMUX_PINS``: Pins set should match the iomux pins of the controller.
160  *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``:
161  *                  Make sure SCLK/MISO/MOSI is/are set to a valid GPIO. Also check output capability according to the mode.
162  *              - ``SPICOMMON_BUSFLAG_DUAL``: Make sure both MISO and MOSI are output capable so that DIO mode is capable.
163  *              - ``SPICOMMON_BUSFLAG_WPHD`` Make sure WP and HD are set to valid output GPIOs.
164  *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
165  * @param[out] flags_o A SPICOMMON_BUSFLAG_* flag combination of bus abilities will be written to this address.
166  *              Leave to NULL if not needed.
167  *              - ``SPICOMMON_BUSFLAG_IOMUX_PINS``: The bus is connected to iomux pins.
168  *              - ``SPICOMMON_BUSFLAG_SCLK``, ``SPICOMMON_BUSFLAG_MISO``, ``SPICOMMON_BUSFLAG_MOSI``: The bus has
169  *                  CLK/MISO/MOSI connected.
170  *              - ``SPICOMMON_BUSFLAG_DUAL``: The bus is capable with DIO mode.
171  *              - ``SPICOMMON_BUSFLAG_WPHD`` The bus has WP and HD connected.
172  *              - ``SPICOMMON_BUSFLAG_QUAD``: Combination of ``SPICOMMON_BUSFLAG_DUAL`` and ``SPICOMMON_BUSFLAG_WPHD``.
173  * @return
174  *         - ESP_ERR_INVALID_ARG   if parameter is invalid
175  *         - ESP_OK                on success
176  */
177 esp_err_t spicommon_bus_initialize_io(spi_host_device_t host, const spi_bus_config_t *bus_config, uint32_t flags, uint32_t *flags_o);
178 
179 /**
180  * @brief Free the IO used by a SPI peripheral
181  *
182  * @note This public API is deprecated. Please call ``spi_bus_free`` for master
183  *       bus deinitialization and ``spi_slave_free`` for slave deinitialization.
184  *
185  * @param bus_cfg Bus config struct which defines which pins to be used.
186  *
187  * @return
188  *         - ESP_ERR_INVALID_ARG   if parameter is invalid
189  *         - ESP_OK                on success
190  */
191 esp_err_t spicommon_bus_free_io_cfg(const spi_bus_config_t *bus_cfg);
192 
193 /**
194  * @brief Initialize a Chip Select pin for a specific SPI peripheral
195  *
196  * @note This public API is deprecated. Please call corresponding device initialization
197  *       functions.
198  *
199  * @param host SPI peripheral
200  * @param cs_io_num GPIO pin to route
201  * @param cs_num CS id to route
202  * @param force_gpio_matrix If true, CS will always be routed through the GPIO matrix. If false,
203  *                          if the GPIO number allows it, the routing will happen through the IO_mux.
204  */
205 void spicommon_cs_initialize(spi_host_device_t host, int cs_io_num, int cs_num, int force_gpio_matrix);
206 
207 /**
208  * @brief Free a chip select line
209  *
210  * @param cs_gpio_num CS gpio num to free
211  *
212  * @note This public API is deprecated.
213  */
214 void spicommon_cs_free_io(int cs_gpio_num);
215 
216 /**
217  * @brief Check whether all pins used by a host are through IOMUX.
218  *
219  * @param host SPI peripheral
220  *
221  * @note This public API is deprecated.
222  *
223  * @return false if any pins are through the GPIO matrix, otherwise true.
224  */
225 bool spicommon_bus_using_iomux(spi_host_device_t host);
226 
227 /**
228  * @brief Get the IRQ source for a specific SPI host
229  *
230  * @param host The SPI host
231  *
232  * @note This public API is deprecated.
233  *
234  * @return The hosts IRQ source
235  */
236 int spicommon_irqsource_for_host(spi_host_device_t host);
237 
238 /**
239  * @brief Get the IRQ source for a specific SPI DMA
240  *
241  * @param host The SPI host
242  *
243  * @note This public API is deprecated.
244  *
245  * @return The hosts IRQ source
246  */
247 int spicommon_irqdma_source_for_host(spi_host_device_t host);
248 
249 /**
250  * Callback, to be called when a DMA engine reset is completed
251 */
252 typedef void(*dmaworkaround_cb_t)(void *arg);
253 
254 
255 /**
256  * @brief Request a reset for a certain DMA channel
257  *
258  * @note In some (well-defined) cases in the ESP32 (at least rev v.0 and v.1), a SPI DMA channel will get confused. This can be remedied
259  * by resetting the SPI DMA hardware in case this happens. Unfortunately, the reset knob used for thsi will reset _both_ DMA channels, and
260  * as such can only done safely when both DMA channels are idle. These functions coordinate this.
261  *
262  * Essentially, when a reset is needed, a driver can request this using spicommon_dmaworkaround_req_reset. This is supposed to be called
263  * with an user-supplied function as an argument. If both DMA channels are idle, this call will reset the DMA subsystem and return true.
264  * If the other DMA channel is still busy, it will return false; as soon as the other DMA channel is done, however, it will reset the
265  * DMA subsystem and call the callback. The callback is then supposed to be used to continue the SPI drivers activity.
266  *
267  * @param dmachan DMA channel associated with the SPI host that needs a reset
268  * @param cb Callback to call in case DMA channel cannot be reset immediately
269  * @param arg Argument to the callback
270  *
271  * @note This public API is deprecated.
272  *
273  * @return True when a DMA reset could be executed immediately. False when it could not; in this
274  *         case the callback will be called with the specified argument when the logic can execute
275  *         a reset, after that reset.
276  */
277 bool spicommon_dmaworkaround_req_reset(int dmachan, dmaworkaround_cb_t cb, void *arg);
278 
279 
280 /**
281  * @brief Check if a DMA reset is requested but has not completed yet
282  *
283  * @note This public API is deprecated.
284  *
285  * @return True when a DMA reset is requested but hasn't completed yet. False otherwise.
286  */
287 bool spicommon_dmaworkaround_reset_in_progress(void);
288 
289 
290 /**
291  * @brief Mark a DMA channel as idle.
292  *
293  * A call to this function tells the workaround logic that this channel will
294  * not be affected by a global SPI DMA reset.
295  *
296  * @note This public API is deprecated.
297  */
298 void spicommon_dmaworkaround_idle(int dmachan);
299 
300 /**
301  * @brief Mark a DMA channel as active.
302  *
303  * A call to this function tells the workaround logic that this channel will
304  * be affected by a global SPI DMA reset, and a reset like that should not be attempted.
305  *
306  * @note This public API is deprecated.
307  */
308 void spicommon_dmaworkaround_transfer_active(int dmachan);
309 
310 /*******************************************************************************
311  * Bus attributes
312  ******************************************************************************/
313 /**
314  * @brief Set bus lock for the main bus, called by startup code.
315  *
316  * @param lock The lock to be used by the main SPI bus.
317  */
318 void spi_bus_main_set_lock(spi_bus_lock_handle_t lock);
319 
320 /**
321  * @brief Get the attributes of a specified SPI bus.
322  *
323  * @param host_id The specified host to get attribute
324  * @return (Const) Pointer to the attributes
325  */
326 const spi_bus_attr_t* spi_bus_get_attr(spi_host_device_t host_id);
327 
328 /**
329  * @brief Register a function to a initialized bus to make it called when deinitializing the bus.
330  *
331  * @param host_id   The SPI bus to register the destructor.
332  * @param f         Destructor to register
333  * @param arg       The argument to call the destructor
334  * @return Always ESP_OK.
335  */
336 esp_err_t spi_bus_register_destroy_func(spi_host_device_t host_id,
337                                         spi_destroy_func_t f, void *arg);
338 
339 /*******************************************************************************
340  * SPI Bus Lock for arbitration among SPI master (intr, polling) trans, SPI flash operations and
341  * flash/psram cache access.
342  *
343  * NON-PUBLIC API. Don't use it directly in applications.
344  *
345  * There is the main lock corresponding to an SPI bus, of which several devices (holding child
346  * locks) attaching to it. Each of the device is STRONGLY RECOMMENDED to be used in only one task
347  * to avoid concurrency issues.
348  *
349  * Terms:
350  * - BG operations (BackGround operations) means some transaction that will not immediately /
351  *   explicitly be sent in the task. It can be some cache access, or interrupt transactions.
352  *
353  * - Operation: usage of the bus, for example, do SPI transactions.
354  *
355  * - Acquiring processor: the task or the ISR that is allowed to use the bus. No operations will be
356  *   performed if there is no acquiring processor. A processor becomes the acquiring processor if
357  *   it ask for that when no acquiring processor exist, otherwise it has to wait for the acquiring
358  *   processor to handle over the role to it. The acquiring processor will and will only assign one
359  *   acquiring processor in the waiting list (if not empty) when it finishes its operation.
360  *
361  * - Acquiring device: the only device allowed to use the bus. Operations can be performed in
362  *   either the BG or the task. When there's no acquiring device, only the ISR is allowed to be the
363  *   acquiring processor and perform operations on the bus.
364  *
365  * When a device wants to perform operations, it either:
366  * 1. Acquire the bus, and operate in the task (e.g. polling transactions of SPI master, and SPI flash
367  *    operations)
368  *
369  * 2. Request a BG operation. And the ISR will be enabled at proper time.
370  *
371  *    For example if a task wants to send an interrupt transaction, it prepares the data in the task,
372  *    call `spi_bus_lock_bg_request`, and handle sending in the ISR.
373  *
374  * 3. When a device has already acquired the bus, BG operations are also allowed. After the
375  *    `spi_bus_lock_bg_request` is called, call `spi_bus_lock_wait_bg_done` before operations in task
376  *    again to wait until BG operations are done.
377  *
378  * Any device may try to invoke the ISR (by `spi_bus_lock_bg_request`). The ISR will be invoked and
379  * become the acquiring processor immediately when the bus is not acquired by other processors. Any
380  * device may also try to acquire the bus (by `spi_bus_lock_acquire_start`). The device will become
381  * the acquiring processor immediately when the bus is not acquired and there is no request active.
382  *
383  * The acquiring processor must be aware of its acquiring role, and properly transfer the acquiring
384  * processor to other tasks or ISR when they have nothing else to do. Before picking a new
385  * acquiring processor, a new acquiring device must be picked first, if there are other devices,
386  * asking to be acquiring device. After that, the new acquiring processor is picked by the sequence
387  * below:
388  *
389  * 1. If there is an acquiring device:
390  *      1.1 The ISR, if acquiring device has active BG requests
391  *      1.2 The task of the device, if no active BG request for the device
392  * 2. The ISR, if there's no acquiring device, but any BG request is active
393  * 3. No one becomes the acquiring processor
394  *
395  * The API also helps on the arbitration of SPI cs lines. The bus is initialized with a cs_num
396  * argument. When attaching devices onto the bus with `spi_bus_lock_register_dev`, it will allocate
397  * devices with different device ID according to the flags given. If the ID is smaller than the
398  * cs_num given when bus is initialized, error will be returned.
399  *
400  * Usage:
401  * * Initialization:
402  * 1. Call `spi_bus_init_lock` to register a lock for a bus.
403  * 2. Call `spi_bus_lock_set_bg_control` to prepare BG enable/disable functions for
404  *    the lock.
405  * 3. Call `spi_bus_lock_register_dev` for each devices that may make use of the
406  *    bus, properly store the returned handle, representing those devices.
407  *
408  * * Acquiring:
409  * 1. Call `spi_bus_lock_acquire_start` when a device wants to use the bus
410  * 2. Call `spi_bus_lock_touch` to mark the bus as touched by this device. Also check if the bus
411  *    has been touched by other devices.
412  * 3. (optional) Do something on the bus...
413  * 4. (optional) Call `spi_bus_lock_bg_request` to inform and invoke the BG. See ISR below about
414  *    ISR operations.
415  * 5. (optional) If `spi_bus_lock_bg_request` is done, you have to call `spi_bus_lock_wait_bg_done`
416  *    before touching the bus again, or do the following steps.
417  * 6. Call `spi_bus_lock_acquire_end` to release the bus to other devices.
418  *
419  * * ISR:
420  * 1. Call `spi_bus_lock_bg_entry` when entering the ISR, run or skip the closure for the previous
421  *    operation according to the return value.
422  * 2. Call `spi_bus_lock_get_acquiring_dev` to get the acquiring device. If there is no acquiring
423  *    device, call `spi_bus_lock_bg_check_dev_acq` to check and update a new acquiring device.
424  * 3. Call `spi_bus_lock_bg_check_dev_req` to check for request of the desired device. If the
425  *    desired device is not requested, go to step 5.
426  * 4. Check, start operation for the desired device and go to step 6; otherwise if no operations
427  *    can be performed, call `spi_bus_lock_bg_clear_req` to clear the request for this device. If
428  *    `spi_bus_lock_bg_clear_req` is called and there is no BG requests active, goto step 6.
429  * 5. (optional) If the device is the acquiring device, go to step 6, otherwise
430  *    find another desired device, and go back to step 3.
431  * 6. Call `spi_bus_lock_bg_exit` to try quitting the ISR. If failed, go back to step 2 to look for
432  *    a new request again. Otherwise, quit the ISR.
433  *
434  * * Deinitialization (optional):
435  * 1. Call `spi_bus_lock_unregister_dev` for each device when they are no longer needed.
436  * 2. Call `spi_bus_deinit_lock` to release the resources occupied by the lock.
437  *
438  * Some technical details:
439  *
440  * The child-lock of each device will have its own Binary Semaphore, which allows the task serving
441  * this device (task A) being blocked when it fail to become the acquiring processor while it's
442  * calling `spi_bus_lock_acquire_start` or `spi_bus_lock_wait_bg_done`. If it is blocked, there
443  * must be an acquiring processor (either the ISR or another task (task B)), is doing transaction
444  * on the bus. After that, task A will get unblocked and become the acquiring processor when the
445  * ISR call `spi_bus_lock_bg_resume_acquired_dev`, or task B call `spi_bus_lock_acquire_end`.
446  *
447  * When the device wants to send ISR transaction, it should call `spi_bus_lock_bg_request` after
448  * the data is prepared. This function sets a request bit in the critical resource. The ISR will be
449  * invoked and become the new acquiring processor, when:
450  *
451  * 1. A task calls `spi_bus_lock_bg_request` while there is no acquiring processor;
452  * 2. A tasks calls `spi_bus_lock_bg_request` while the task is the acquiring processor. Then the
453  *    acquiring processor is handled over to the ISR;
454  * 3. A tasks who is the acquiring processor release the bus by calling `spi_bus_lock_acquire_end`,
455  *    and the ISR happens to be the next acquiring processor.
456  *
457  * The ISR will check (by `spi_bus_lock_bg_check_dev_req`) and clear a request bit (by
458  * `spi_bus_lock_bg_clear_req`) after it confirm that all the requests of the corresponding device
459  * are served. The request bit supports being written to recursively, which means, the task don't
460  * need to wait for `spi_bus_lock_bg_clear_req` before call another `spi_bus_lock_bg_request`. The
461  * API will handle the concurrency conflicts properly.
462  *
463  * The `spi_bus_lock_bg_exit` (together with `spi_bus_lock_bg_entry` called before)` is responsible
464  * to ensure ONE and ONLY ONE of the following will happen when the ISR try to give up its
465  * acquiring processor rule:
466  *
467  * 1. ISR quit, no any task unblocked while the interrupt disabled, and none of the BG bits is
468  *    active.
469  * 2. ISR quit, there is an acquiring device, and the acquiring processor is passed to the task
470  *    serving the acquiring device by unblocking the task.
471  * 3. The ISR failed to quit and have to try again.
472  ******************************************************************************/
473 
474 #define DEV_NUM_MAX 6     ///< Number of devices supported by this lock
475 
476 /// Lock configuration struct
477 typedef struct {
478     int host_id;    ///< SPI host id
479     int cs_num;     ///< Physical cs numbers of the host
480 } spi_bus_lock_config_t;
481 
482 /// Child-lock configuration struct
483 typedef struct {
484     uint32_t flags; ///< flags for the lock, OR-ed of `SPI_BUS_LOCK_DEV_*` flags.
485 #define SPI_BUS_LOCK_DEV_FLAG_CS_REQUIRED   BIT(0)  ///< The device needs a physical CS pin.
486 } spi_bus_lock_dev_config_t;
487 
488 /************* Common *********************/
489 /**
490  * Initialize a lock for an SPI bus.
491  *
492  * @param out_lock Output of the handle to the lock
493  * @return
494  *  - ESP_ERR_NO_MEM: if memory exhausted
495  *  - ESP_OK: if success
496  */
497 esp_err_t spi_bus_init_lock(spi_bus_lock_handle_t *out_lock, const spi_bus_lock_config_t *config);
498 
499 /**
500  * Free the resources used by an SPI bus lock.
501  *
502  * @note All attached devices should have been unregistered before calling this
503  *       funciton.
504  *
505  * @param lock Handle to the lock to free.
506  */
507 void spi_bus_deinit_lock(spi_bus_lock_handle_t lock);
508 
509 /**
510  * @brief Get the corresponding lock according to bus id.
511  *
512  * @param host_id The bus id to get the lock
513  * @return The lock handle
514  */
515 spi_bus_lock_handle_t spi_bus_lock_get_by_id(spi_host_device_t host_id);
516 
517 /**
518  * @brief Configure how the SPI bus lock enable the background operation.
519  *
520  * @note The lock will not try to stop the background operations, but wait for
521  *       The background operations finished indicated by `spi_bus_lock_bg_resume_acquired_dev`.
522  *
523  * @param lock Handle to the lock to set
524  * @param bg_enable The enabling function
525  * @param bg_disable The disabling function, set to NULL if not required
526  * @param arg Argument to pass to the enabling/disabling function.
527  */
528 void spi_bus_lock_set_bg_control(spi_bus_lock_handle_t lock, bg_ctrl_func_t bg_enable,
529                                  bg_ctrl_func_t bg_disable, void *arg);
530 
531 /**
532  * Attach a device onto an SPI bus lock. The returning handle is used to perform
533  * following requests for the attached device.
534  *
535  * @param lock SPI bus lock to attach
536  * @param out_dev_handle Output handle corresponding to the device
537  * @param flags requirement of the device, bitwise OR of SPI_BUS_LOCK_FLAG_* flags
538  *
539  * @return
540  *  - ESP_ERR_NOT_SUPPORTED: if there's no hardware resources for new devices.
541  *  - ESP_ERR_NO_MEM: if memory exhausted
542  *  - ESP_OK: if success
543  */
544 esp_err_t spi_bus_lock_register_dev(spi_bus_lock_handle_t lock,
545                                     spi_bus_lock_dev_config_t *config,
546                                     spi_bus_lock_dev_handle_t *out_dev_handle);
547 
548 /**
549  * Detach a device from its bus and free the resources used
550  *
551  * @param dev_handle Handle to the device.
552  */
553 void spi_bus_lock_unregister_dev(spi_bus_lock_dev_handle_t dev_handle);
554 
555 /**
556  * @brief Get the parent bus lock of the device
557  *
558  * @param dev_handle Handle to the device to get bus lock
559  * @return The bus lock handle
560  */
561 spi_bus_lock_handle_t spi_bus_lock_get_parent(spi_bus_lock_dev_handle_t dev_handle);
562 
563 /**
564  * @brief Get the device ID of a lock.
565  *
566  * The callers should allocate CS pins according to this ID.
567  *
568  * @param dev_handle Handle to the device to get ID
569  * @return ID of the device
570  */
571 int spi_bus_lock_get_dev_id(spi_bus_lock_dev_handle_t dev_handle);
572 
573 /**
574  * @brief The device request to touch bus registers. Can only be called by the acquiring processor.
575  *
576  * Also check if the registers has been touched by other devices.
577  *
578  * @param dev_handle Handle to the device to operate the registers
579  * @return true if there has been other devices touching SPI registers.
580  *     The caller may need to do a full-configuration. Otherwise return
581  *     false.
582  */
583 bool spi_bus_lock_touch(spi_bus_lock_dev_handle_t dev_handle);
584 
585 /************* Acquiring service *********************/
586 /**
587  * Acquiring the SPI bus for exclusive use. Will also wait for the BG to finish all requests of
588  * this device before it returns.
589  *
590  * After successfully return, the caller becomes the acquiring processor.
591  *
592  * @note For the main flash bus, `bg_disable` will be called to disable the cache.
593  *
594  * @param dev_handle Handle to the device request for acquiring.
595  * @param wait Time to wait until timeout or succeed, must be `portMAX_DELAY` for now.
596  * @return
597  *  - ESP_OK: on success
598  *  - ESP_ERR_INVALID_ARG: timeout is not portMAX_DELAY
599  */
600 esp_err_t spi_bus_lock_acquire_start(spi_bus_lock_dev_handle_t dev_handle, TickType_t wait);
601 
602 /**
603  * Release the bus acquired. Will pass the acquiring processor to other blocked
604  * processors (tasks or ISR), and cause them to be unblocked or invoked.
605  *
606  * The acquiring device may also become NULL if no device is asking for acquiring.
607  * In this case, the BG may be invoked if there is any BG requests.
608  *
609  * If the new acquiring device has BG requests, the BG will be invoked before the
610  * task is resumed later after the BG finishes all requests of the new acquiring
611  * device. Otherwise the task of the new acquiring device will be resumed immediately.
612  *
613  * @param dev_handle Handle to the device releasing the bus.
614  * @return
615  *  - ESP_OK: on success
616  *  - ESP_ERR_INVALID_STATE: the device hasn't acquired the lock yet
617  */
618 esp_err_t spi_bus_lock_acquire_end(spi_bus_lock_dev_handle_t dev_handle);
619 
620 /**
621  * Get the device acquiring the bus.
622  *
623  * @note Return value is not stable as the acquiring processor may change
624  *       when this function is called.
625  *
626  * @param lock Lock of SPI bus to get the acquiring device.
627  * @return The argument corresponding to the acquiring device, see
628  *         `spi_bus_lock_register_dev`.
629  */
630 spi_bus_lock_dev_handle_t spi_bus_lock_get_acquiring_dev(spi_bus_lock_handle_t lock);
631 
632 /************* BG (Background, for ISR or cache) service *********************/
633 /**
634  * Call by a device to request a BG operation.
635  *
636  * Depending on the bus lock state, the BG operations may be resumed by this
637  * call, or pending until BG operations allowed.
638  *
639  * Cleared by `spi_bus_lock_bg_clear_req` in the BG.
640  *
641  * @param dev_handle The device requesting BG operations.
642  * @return always ESP_OK
643  */
644 esp_err_t spi_bus_lock_bg_request(spi_bus_lock_dev_handle_t dev_handle);
645 
646 /**
647  * Wait until the ISR has finished all the BG operations for the acquiring device.
648  * If any `spi_bus_lock_bg_request` for this device has been called after
649  * `spi_bus_lock_acquire_start`, this function must be called before any operation
650  * in the task.
651  *
652  * @note Can only be called when bus acquired by this device.
653  *
654  * @param dev_handle Handle to the device acquiring the bus.
655  * @param wait Time to wait until timeout or succeed, must be `portMAX_DELAY` for now.
656  * @return
657  *  - ESP_OK: on success
658  *  - ESP_ERR_INVALID_STATE: The device is not the acquiring bus.
659  *  - ESP_ERR_INVALID_ARG: Timeout is not portMAX_DELAY.
660  */
661 esp_err_t spi_bus_lock_wait_bg_done(spi_bus_lock_dev_handle_t dev_handle, TickType_t wait);
662 
663 /**
664  * Handle interrupt and closure of last operation. Should be called at the beginning of the ISR,
665  * when the ISR is acting as the acquiring processor.
666  *
667  * @param lock The SPI bus lock
668  *
669  * @return false if the ISR has already touched the HW, should run closure of the
670  *         last operation first; otherwise true if the ISR just start operating
671  *         on the HW, closure should be skipped.
672  */
673 bool spi_bus_lock_bg_entry(spi_bus_lock_handle_t lock);
674 
675 /**
676  * Handle the scheduling of other acquiring devices, and control of HW operation
677  * status.
678  *
679  * If no BG request is found, call with `wip=false`. This function will return false,
680  * indicating there is incoming BG requests for the current acquiring device (or
681  * for all devices if there is no acquiring device) and the ISR needs retry.
682  * Otherwise may schedule a new acquiring processor (unblock the task) if there
683  * is, and return true.
684  *
685  * Otherwise if a BG request is started in this ISR, call with `wip=true` and the
686  * function will enable the interrupt to make the ISR be called again when the
687  * request is done.
688  *
689  * This function is safe and should still be called when the ISR just lost its acquiring processor
690  * role, but hasn't quit.
691  *
692  * @note This function will not change acquiring device. The ISR call
693  *       `spi_bus_lock_bg_update_acquiring` to check for new acquiring device,
694  *       when acquiring devices need to be served before other devices.
695  *
696  * @param lock The SPI bus lock.
697  * @param wip Whether an operation is being executed when quitting the ISR.
698  * @param do_yield[out] Not touched when no yielding required, otherwise set
699  *                      to pdTRUE.
700  * @return false if retry is required, indicating that there is pending BG request.
701  *         otherwise true and quit ISR is allowed.
702  */
703 bool spi_bus_lock_bg_exit(spi_bus_lock_handle_t lock, bool wip, BaseType_t* do_yield);
704 
705 /**
706  * Check whether there is device asking for the acquiring device, and the desired
707  * device for the next operation is also recommended.
708  *
709  * @note Must be called when the ISR is acting as the acquiring processor, and
710  *        there is no acquiring device.
711  *
712  * @param lock The SPI bus lock.
713  * @param out_dev_lock The recommended device for hte next operation. It's the new
714  *        acquiring device when found, otherwise a device that has active BG request.
715  *
716  * @return true if the ISR need to quit (new acquiring device has no active BG
717  *         request, or no active BG requests for all devices when there is no
718  *         acquiring device), otherwise false.
719  */
720 bool spi_bus_lock_bg_check_dev_acq(spi_bus_lock_handle_t lock, spi_bus_lock_dev_handle_t *out_dev_lock);
721 
722 /**
723  * Check if the device has BG requests. Must be called when the ISR is acting as
724  * the acquiring processor.
725  *
726  * @note This is not stable, may become true again when a task request for BG
727  *       operation (by `spi_bus_lock_bg_request`).
728  *
729  * @param dev_lock The device to check.
730  * @return true if the device has BG requests, otherwise false.
731  */
732 bool spi_bus_lock_bg_check_dev_req(spi_bus_lock_dev_handle_t dev_lock);
733 
734 /**
735  * Clear the pending BG operation request of a device after served. Must be
736  * called when the ISR is acting as the acquiring processor.
737  *
738  * @note When the return value is true, the ISR will lost the acquiring processor role. Then
739  *       `spi_bus_lock_bg_exit` must be called and checked before calling all other functions that
740  *       require to be called when the ISR is the acquiring processor again.
741  *
742  * @param dev_handle The device whose request is served.
743  * @return True if no pending requests for the acquiring device, or for all devices
744  *         if there is no acquiring device. Otherwise false. When the return value is
745  *         true, the ISR is no longer the acquiring processor.
746  */
747 bool spi_bus_lock_bg_clear_req(spi_bus_lock_dev_handle_t dev_lock);
748 
749 /**
750  * Check if there is any active BG requests.
751  *
752  * @param lock The SPI bus lock.
753  * @return true if any device has active BG requst, otherwise false.
754  */
755 bool spi_bus_lock_bg_req_exist(spi_bus_lock_handle_t lock);
756 
757 /*******************************************************************************
758  * Variable and APIs for the OS to initialize the locks for the main chip
759  ******************************************************************************/
760 /// The lock for the main bus
761 extern const spi_bus_lock_handle_t g_main_spi_bus_lock;
762 
763 /**
764  * @brief Initialize the main SPI bus, called during chip startup.
765  *
766  * @return always ESP_OK
767  */
768 esp_err_t spi_bus_lock_init_main_bus(void);
769 
770 /// The lock for the main flash device
771 extern const spi_bus_lock_dev_handle_t g_spi_lock_main_flash_dev;
772 
773 /**
774  * @brief Initialize the main flash device, called during chip startup.
775  *
776  * @return
777  *      - ESP_OK: if success
778  *      - ESP_ERR_NO_MEM: memory exhausted
779  */
780 esp_err_t spi_bus_lock_init_main_dev(void);
781 
782 
783 #ifdef __cplusplus
784 }
785 #endif
786