1 // Copyright 2020 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 #pragma once
16 
17 #include <stdint.h>
18 #include <stdbool.h>
19 #include "esp_err.h"
20 #include "esp_attr.h"
21 #include "soc/soc_caps.h"
22 
23 #if SOC_DEDICATED_GPIO_SUPPORTED
24 
25 #ifdef __cplusplus
26 extern "C" {
27 #endif
28 
29 /**
30  * @brief Type of Dedicated GPIO bundle
31  */
32 typedef struct dedic_gpio_bundle_t *dedic_gpio_bundle_handle_t;
33 
34 /**
35  * @brief Type of Dedicated GPIO bundle configuration
36  */
37 typedef struct {
38     const int *gpio_array; /*!< Array of GPIO numbers, gpio_array[0] ~ gpio_array[size-1] <=> low_dedic_channel_num ~ high_dedic_channel_num */
39     size_t array_size;     /*!< Number of GPIOs in gpio_array */
40     struct {
41         int in_en: 1;      /*!< Enable input */
42         int in_invert: 1;  /*!< Invert input signal */
43         int out_en: 1;     /*!< Enable output */
44         int out_invert: 1; /*!< Invert output signal */
45     } flags; /*!< Flags to control specific behaviour of GPIO bundle */
46 } dedic_gpio_bundle_config_t;
47 
48 /**
49  * @brief Create GPIO bundle and return the handle
50  *
51  * @param[in] config Configuration of GPIO bundle
52  * @param[out] ret_bundle Returned handle of the new created GPIO bundle
53  * @return
54  *      - ESP_OK: Create GPIO bundle successfully
55  *      - ESP_ERR_INVALID_ARG: Create GPIO bundle failed because of invalid argument
56  *      - ESP_ERR_NO_MEM: Create GPIO bundle failed because of no capable memory
57  *      - ESP_ERR_NOT_FOUND: Create GPIO bundle failed because of no enough continuous dedicated channels
58  *      - ESP_FAIL: Create GPIO bundle failed because of other error
59  *
60  * @note One has to enable at least input or output mode in "config" parameter.
61  */
62 esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_gpio_bundle_handle_t *ret_bundle);
63 
64 /**
65  * @brief Destory GPIO bundle
66  *
67  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
68  * @return
69  *      - ESP_OK: Destory GPIO bundle successfully
70  *      - ESP_ERR_INVALID_ARG: Destory GPIO bundle failed because of invalid argument
71  *      - ESP_FAIL: Destory GPIO bundle failed because of other error
72  */
73 esp_err_t dedic_gpio_del_bundle(dedic_gpio_bundle_handle_t bundle);
74 
75 /**@{*/
76 /**
77  * @brief Get allocated channel mask
78  *
79  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
80  * @param[out] mask Returned mask value for on specific direction (in or out)
81  * @return
82  *      - ESP_OK: Get channel mask successfully
83  *      - ESP_ERR_INVALID_ARG: Get channel mask failed because of invalid argument
84  *      - ESP_FAIL: Get channel mask failed because of other error
85  *
86  * @note Each bundle should have at least one mask (in or/and out), based on bundle configuration.
87  * @note With the returned mask, user can directly invoke LL function like "cpu_ll_write_dedic_gpio_mask"
88  *       or write assembly code with dedicated GPIO instructions, to get better performance on GPIO manipulation.
89  */
90 esp_err_t dedic_gpio_get_out_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask);
91 esp_err_t dedic_gpio_get_in_mask(dedic_gpio_bundle_handle_t bundle, uint32_t *mask);
92 /**@}*/
93 
94 /**
95  * @brief Write value to GPIO bundle
96  *
97  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
98  * @param[in] mask Mask of the GPIOs to be written in the given bundle
99  * @param[in] value Value to write to given GPIO bundle, low bit represents low member in the bundle
100  *
101  * @note The mask is seen from the view of GPIO bundle.
102  *       For example, bundleA contains [GPIO10, GPIO12, GPIO17], to set GPIO17 individually, the mask should be 0x04.
103  * @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
104  */
105 void dedic_gpio_bundle_write(dedic_gpio_bundle_handle_t bundle, uint32_t mask, uint32_t value) IRAM_ATTR;
106 
107 /**
108  * @brief Read the value that output from the given GPIO bundle
109  *
110  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
111  * @return Value that output from the GPIO bundle, low bit represents low member in the bundle
112  *
113  * @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
114  */
115 uint32_t dedic_gpio_bundle_read_out(dedic_gpio_bundle_handle_t bundle) IRAM_ATTR;
116 
117 /**
118  * @brief Read the value that input to the given GPIO bundle
119  *
120  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
121  * @return Value that input to the GPIO bundle, low bit represents low member in the bundle
122  *
123  * @note For performance reasons, this function doesn't check the validity of any parameters, and is placed in IRAM.
124  */
125 uint32_t dedic_gpio_bundle_read_in(dedic_gpio_bundle_handle_t bundle) IRAM_ATTR;
126 
127 #if SOC_DEDIC_GPIO_HAS_INTERRUPT
128 
129 /**
130  * @brief Supported type of dedicated GPIO interrupt
131  */
132 typedef enum {
133     DEDIC_GPIO_INTR_NONE,          /*!< No interrupt */
134     DEDIC_GPIO_INTR_LOW_LEVEL = 2, /*!< Interrupt on low level */
135     DEDIC_GPIO_INTR_HIGH_LEVEL,    /*!< Interrupt on high level */
136     DEDIC_GPIO_INTR_NEG_EDGE,      /*!< Interrupt on negedge */
137     DEDIC_GPIO_INTR_POS_EDGE,      /*!< Interrupt on posedge */
138     DEDIC_GPIO_INTR_BOTH_EDGE      /*!< Interrupt on both negedge and posedge */
139 } dedic_gpio_intr_type_t;
140 
141 /**
142  * @brief Type of dedicated GPIO ISR callback function
143  *
144  * @param bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
145  * @param index Index of the GPIO in its corresponding bundle (count from 0)
146  * @param args User defined arguments for the callback function. It's passed through `dedic_gpio_bundle_set_interrupt_and_callback`
147  * @return If a high priority task is woken up by the callback function
148  */
149 typedef bool (*dedic_gpio_isr_callback_t)(dedic_gpio_bundle_handle_t bundle, uint32_t index, void *args);
150 
151 /**
152  * @brief Set interrupt and callback function for GPIO bundle
153  *
154  * @param[in] bundle Handle of GPIO bundle that returned from "dedic_gpio_new_bundle"
155  * @param[in] mask Mask of the GPIOs in the given bundle
156  * @param[in] intr_type Interrupt type, set to DEDIC_GPIO_INTR_NONE can disable interrupt
157  * @param[in] cb_isr Callback function, which got invoked in ISR context. A NULL pointer here will bypass the callback
158  * @param[in] cb_args User defined argument to be passed to the callback function
159  *
160  * @note This function is only valid for bundle with input mode enabled. See "dedic_gpio_bundle_config_t"
161  * @note The mask is seen from the view of GPIO Bundle.
162  *       For example, bundleA contains [GPIO10, GPIO12, GPIO17], to set GPIO17 individually, the mask should be 0x04.
163  *
164  * @return
165  *      - ESP_OK: Set GPIO interrupt and callback function successfully
166  *      - ESP_ERR_INVALID_ARG: Set GPIO interrupt and callback function failed because of invalid argument
167  *      - ESP_FAIL: Set GPIO interrupt and callback function failed because of other error
168  */
169 esp_err_t dedic_gpio_bundle_set_interrupt_and_callback(dedic_gpio_bundle_handle_t bundle, uint32_t mask, dedic_gpio_intr_type_t intr_type, dedic_gpio_isr_callback_t cb_isr, void *cb_args);
170 
171 #endif // SOC_DEDIC_GPIO_HAS_INTERRUPT
172 
173 #ifdef __cplusplus
174 }
175 #endif
176 
177 #endif //SOC_DEDICATED_GPIO_SUPPORTED
178