1 /*
2  * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #pragma once
8 
9 #include <stdint.h>
10 #include "esp_err.h"
11 #include "esp_intr_alloc.h"
12 #include "freertos/FreeRTOS.h"
13 #include "freertos/queue.h"
14 #include "freertos/semphr.h"
15 
16 #ifdef __cplusplus
17 extern "C" {
18 #endif
19 
20 #if CONFIG_BTDM_CTRL_HLI
21 
22 /*** Queues ***/
23 
24 struct hli_queue_t
25 {
26     size_t elem_size;
27     char* begin;
28     char* end;
29     const char* bufend;
30     QueueHandle_t downstream;
31     int flags;
32     char buf[0];
33 };
34 
35 /**
36  * @brief Register a high level interrupt function
37  *
38  * @param handler  interrupt handler function
39  * @param arg      argument to pass to the interrupt handler
40  * @param intr_reg   address of the peripheral register containing the interrupt status,
41  *                   or value 0 to get the status from CPU INTERRUPT register
42  * @param intr_mask  mask of the interrupt, in the interrupt status register
43  * @return
44  *      - ESP_OK on success
45  *      - ESP_ERR_NO_MEM if too many handlers are registered
46  */
47 esp_err_t hli_intr_register(intr_handler_t handler, void* arg, uint32_t intr_reg, uint32_t intr_mask);
48 
49 /**
50  * @brief Mask all interrupts (including high level ones) on the current CPU
51  *
52  * @return uint32_t interrupt status, pass it to hli_intr_restore
53  */
54 uint32_t hli_intr_disable(void);
55 
56 /**
57  * @brief Re-enable interrupts
58  *
59  * @param state value returned by hli_intr_disable
60  */
61 void hli_intr_restore(uint32_t state);
62 
63 /**
64  * @brief Type of a hli queue
65  */
66 typedef struct hli_queue_t* hli_queue_handle_t;
67 
68 /**
69  * @brief Initialize hli_queue module. Must be called once before using hli queue APIs.
70  */
71 void hli_queue_setup(void);
72 
73 /**
74  * @brief Shutdown hli_queue module.
75  */
76 void hli_queue_shutdown(void);
77 
78 /**
79  * @brief Create a hli queue, wrapping a FreeRTOS queue
80  *
81  * This queue can be used from high level interrupts,
82  * but **ONLY ON THE CPU WHERE hli_queue_setup WAS CALLED**. Values sent to this
83  * queue are automatically forwarded to "downstream" FreeRTOS queue using a level 3
84  * software interrupt.
85  *
86  * @param nelem  number of elements in the queue
87  * @param elem_size  size of one element; must match element size of a downstream queue
88  * @param downstream  FreeRTOS queue to send the values to
89  * @return hli_queue_handle_t  handle of the created queue, or NULL on failure
90  */
91 hli_queue_handle_t hli_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream);
92 
93 /**
94  * @brief Create a customer hli queue, wrapping a FreeRTOS queue
95  *
96  * This queue can be used from high level interrupts,
97  * but **ONLY ON THE CPU WHERE hli_queue_setup WAS CALLED**. Values sent to this
98  * queue are automatically forwarded to "downstream" FreeRTOS queue using a level 3
99  * software interrupt.
100  *
101  * @param nelem  number of elements in the queue
102  * @param elem_size  size of one element; must match element size of a downstream queue
103  * @param downstream  FreeRTOS queue to send the values to
104  * @return hli_queue_handle_t  handle of the created queue, or NULL on failure
105  */
106 hli_queue_handle_t hli_customer_queue_create(size_t nelem, size_t elem_size, QueueHandle_t downstream);
107 
108 /**
109  * @brief Create a hli queue, wrapping a FreeRTOS semaphore
110  *
111  * See notes on hli_queue_create.
112  *
113  * @param max_count  maximum semaphore count
114  * @param downstream  FreeRTOS semaphore to forward the calls to
115  * @return hli_queue_handle_t  handle of the created queue, or NULL on failure
116  */
117 hli_queue_handle_t hli_semaphore_create(size_t max_count, SemaphoreHandle_t downstream);
118 
119 /**
120  * @brief Delete a hli queue
121  *
122  * Make sure noone is using the queue before deleting it.
123  *
124  * @param queue  handle returned by hli_queue_create or hli_semaphore_create
125  */
126 void hli_queue_delete(hli_queue_handle_t queue);
127 
128 /**
129  * @brief Get one element from a hli queue
130  *
131  * Usually not used, values get sent to a downstream FreeRTOS queue automatically.
132  * However if downstream queue is NULL, this API can be used to get values from a hli queue.
133  *
134  * @param queue  handle of a queue
135  * @param out  pointer where to store the element
136  * @return true if the element was successfully read from the queue
137  */
138 bool hli_queue_get(hli_queue_handle_t queue, void* out);
139 
140 /**
141  * @brief Put one element into a hli queue
142  *
143  * This puts copies an element into the queue and raises a software interrupt (level 3).
144  * In the interrupt, the value is copied to a FreeRTOS "downstream" queue.
145  *
146  * Note that if the value does not fit into a downstream queue, no error is returned,
147  * and the value is lost.
148  *
149  * @param queue handle of a queue
150  * @param data  pointer to the element to be sent
151  * @return true if data was placed into the hli queue successfully
152  */
153 bool hli_queue_put(hli_queue_handle_t queue, const void* data);
154 
155 /**
156  * @brief "Give" a semaphore wrapped by a hli queue
157  *
158  * @param queue  handle returned by hli_semaphore_create
159  * @return true  if the event was sent to a hli queue successfully
160  */
161 bool hli_semaphore_give(hli_queue_handle_t queue);
162 
163 #endif /* CONFIG_BTDM_CTRL_HLI */
164 
165 #ifdef __cplusplus
166 }
167 #endif
168