• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2   ****************************************************************************************
3   * @file    app_gpiote.c
4   * @author  BLE Driver Team
5   * @brief   HAL APP module driver.
6   ****************************************************************************************
7   * @attention
8   #####Copyright (c) 2019 GOODIX
9    All rights reserved.
10 
11    Redistribution and use in source and binary forms, with or without
12    modification, are permitted provided that the following conditions are met:
13    * Redistributions of source code must retain the above copyright
14     notice, this list of conditions and the following disclaimer.
15    * Redistributions in binary form must reproduce the above copyright
16      notice, this list of conditions and the following disclaimer in the
17      documentation and/or other materials provided with the distribution.
18    * Neither the name of GOODIX nor the names of its contributors may be used
19      to endorse or promote products derived from this software without
20      specific prior written permission.
21 
22    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
23    AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24    IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25    ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
26    LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
27    CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
28    SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
29    INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
30    CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31    ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32    POSSIBILITY OF SUCH DAMAGE.
33   ****************************************************************************************
34   */
35 
36 /*
37  * INCLUDE FILES
38  *****************************************************************************************
39  */
40 #include <string.h>
41 #include "app_pwr_mgmt.h"
42 #include "platform_sdk.h"
43 #include "app_gpiote.h"
44 
45 /*
46  * DEFINES
47  *****************************************************************************************
48  */
49 #define BIT_8                     8
50 #define BIT_16                    16
51 #define BIT_24                    24
52 
53 #define GPIOTE_USE_PATTERN        0x47
54 #define GPIOTE_USE_MAX            32
55 #define GPIOTE_AON_PIN_USE_MAX    8
56 /*
57  * STRUCT DEFINE
58  *****************************************************************************************
59  */
60 struct gpiote_env_t {
61     uint8_t            total_used;
62     app_gpiote_param_t params[GPIOTE_USE_MAX];
63 };
64 
65 /*
66  * LOCAL FUNCTION DECLARATION
67  *****************************************************************************************
68  */
69 static bool gpiote_prepare_for_sleep(void);
70 static void gpiote_sleep_canceled(void);
71 static void gpiote_wake_up_ind(void);
72 
73 /*
74  * LOCAL VARIABLE DEFINITIONS
75  *****************************************************************************************
76  */
77 static   struct gpiote_env_t s_gpiote_env;
78 
79 static bool     s_sleep_cb_registered_flag = false;
80 static uint16_t s_gpiote_pwr_id;
81 
82 static const app_sleep_callbacks_t gpiote_sleep_cb = {
83     .app_prepare_for_sleep = gpiote_prepare_for_sleep,
84     .app_sleep_canceled    = gpiote_sleep_canceled,
85     .app_wake_up_ind       = gpiote_wake_up_ind
86 };
87 
88 static app_io_callback_t aon_cb_called_table[GPIOTE_AON_PIN_USE_MAX];
89 /*
90  * LOCAL FUNCTION DEFINITIONS
91  *****************************************************************************************
92  */
gpiote_prepare_for_sleep(void)93 static bool gpiote_prepare_for_sleep(void)
94 {
95     return true;
96 }
97 
gpiote_sleep_canceled(void)98 static void gpiote_sleep_canceled(void)
99 {
100 }
101 
gpiote_wake_up_ind(void)102 SECTION_RAM_CODE static void gpiote_wake_up_ind(void)
103 {
104     bool is_ext0_need_enable = false;
105     bool is_ext1_need_enable = false;
106 
107     for (int idx = 0; idx < s_gpiote_env.total_used; idx++) {
108         if (s_gpiote_env.params[idx].type == APP_IO_TYPE_NORMAL) {
109             if (APP_IO_PINS_0_15 & s_gpiote_env.params[idx].pin) {
110                 is_ext0_need_enable = true;
111                 continue;
112             }
113             if (APP_IO_PINS_16_31 & s_gpiote_env.params[idx].pin) {
114                 is_ext1_need_enable = true;
115                 continue;
116             }
117         }
118     }
119 
120     if (is_ext0_need_enable) {
121         hal_nvic_enable_irq(EXT0_IRQn);
122     }
123 
124     if (is_ext1_need_enable) {
125         hal_nvic_enable_irq(EXT1_IRQn);
126     }
127 
128     return;
129 }
130 
params_check(const app_gpiote_param_t * p_params,uint8_t table_cnt)131 static uint16_t params_check(const app_gpiote_param_t *p_params, uint8_t table_cnt)
132 {
133     if (p_params == NULL) {
134         return APP_DRV_ERR_POINTER_NULL;
135     }
136 
137     if (((s_gpiote_env.total_used + table_cnt) > GPIOTE_USE_MAX) && table_cnt) {
138         return APP_DRV_ERR_INVALID_PARAM;
139     }
140 
141     return APP_DRV_SUCCESS;
142 }
143 
gpiote_wakeup_mode_config(uint8_t idx,const app_gpiote_param_t * p_params)144 static void gpiote_wakeup_mode_config(uint8_t idx, const app_gpiote_param_t *p_params)
145 {
146     if ((p_params[idx].handle_mode == APP_IO_ENABLE_WAKEUP) && (p_params[idx].type == APP_IO_TYPE_AON)) {
147         switch (p_params[idx].mode) {
148             case APP_IO_MODE_IT_RISING:
149                 hal_pwr_config_ext_wakeup(p_params[idx].pin, PWR_EXTWKUP_TYPE_RISING);
150                 break;
151 
152             case APP_IO_MODE_IT_FALLING:
153                 hal_pwr_config_ext_wakeup(p_params[idx].pin, PWR_EXTWKUP_TYPE_FALLING);
154                 break;
155 
156             case APP_IO_MODE_IT_HIGH:
157                 hal_pwr_config_ext_wakeup(p_params[idx].pin, PWR_EXTWKUP_TYPE_HIGH);
158                 break;
159 
160             case APP_IO_MODE_IT_LOW:
161                 hal_pwr_config_ext_wakeup(p_params[idx].pin, PWR_EXTWKUP_TYPE_LOW);
162                 break;
163 
164             default:
165                 break;
166         }
167         pwr_mgmt_wakeup_source_setup(PWR_WKUP_COND_EXT);
168     }
169 }
170 
register_cb(void)171 static uint16_t register_cb(void)
172 {
173     if (!s_sleep_cb_registered_flag) { // register sleep callback
174         s_gpiote_pwr_id = pwr_register_sleep_cb(&gpiote_sleep_cb, APP_DRIVER_GPIOTE_WAPEUP_PRIORITY);
175         if (s_gpiote_pwr_id < 0) {
176             return APP_DRV_ERR_INVALID_PARAM;
177         }
178         s_sleep_cb_registered_flag = true;
179     }
180 
181     return APP_DRV_SUCCESS;
182 }
183 
184 /*
185  * GLOBAL FUNCTION DEFINITIONS
186  ****************************************************************************************
187  */
app_gpiote_init(const app_gpiote_param_t * p_params,uint8_t table_cnt)188 uint16_t app_gpiote_init(const app_gpiote_param_t *p_params, uint8_t table_cnt)
189 {
190     static uint8_t exit_flag = 0x0;
191     app_io_init_t io_init;
192     app_drv_err_t err_code;
193 
194     err_code = params_check(p_params, table_cnt);
195     APP_DRV_ERR_CODE_CHECK(err_code);
196 
197     for (uint8_t idx = 0; idx < table_cnt; idx++) {
198         exit_flag = 0x0;
199 
200         for (uint8_t index = 0; index < s_gpiote_env.total_used; index ++) {
201             if (s_gpiote_env.params[index].pin == p_params[idx].pin && \
202                     s_gpiote_env.params[index].type == p_params[idx].type) {
203                 exit_flag = 0x1;
204                 break;
205             }
206         }
207 
208         io_init.pin  = p_params[idx].pin;
209         io_init.mode = p_params[idx].mode;
210         io_init.pull = p_params[idx].pull;
211         io_init.mux  = APP_IO_MUX_7;
212 
213         app_io_deinit(p_params[idx].type, io_init.pin);
214         err_code = app_io_init(p_params[idx].type, &io_init);
215         APP_DRV_ERR_CODE_CHECK(err_code);
216 
217         if (exit_flag) {
218             continue;
219         }
220 
221         memcpy_s(&s_gpiote_env.params[s_gpiote_env.total_used],
222                  sizeof(s_gpiote_env.params[s_gpiote_env.total_used]),
223                  &p_params[idx], sizeof(app_gpiote_param_t));
224 
225         gpiote_wakeup_mode_config(idx, p_params);
226 
227         if (p_params[idx].type == APP_IO_TYPE_NORMAL) {
228             hal_nvic_clear_pending_irq(EXT0_IRQn);
229             hal_nvic_enable_irq(EXT0_IRQn);
230             hal_nvic_clear_pending_irq(EXT1_IRQn);
231             hal_nvic_enable_irq(EXT1_IRQn);
232         } else if (p_params[idx].type == APP_IO_TYPE_AON) {
233             hal_nvic_clear_pending_irq(EXT2_IRQn);
234             hal_nvic_enable_irq(EXT2_IRQn);
235         }
236 
237         s_gpiote_env.total_used += 1;
238     }
239 
240     err_code = register_cb();
241     APP_DRV_ERR_CODE_CHECK(err_code);
242 
243     return APP_DRV_SUCCESS;
244 }
245 
gpiote_config_wake_up_config(const app_gpiote_param_t * p_config)246 static void gpiote_config_wake_up_config(const app_gpiote_param_t *p_config)
247 {
248     if ((p_config->handle_mode == APP_IO_ENABLE_WAKEUP) && (p_config->type == APP_IO_TYPE_AON)) {
249         switch (p_config->mode) {
250             case APP_IO_MODE_IT_RISING:
251                 hal_pwr_config_ext_wakeup(p_config->pin, PWR_EXTWKUP_TYPE_RISING);
252                 break;
253 
254             case APP_IO_MODE_IT_FALLING:
255                 hal_pwr_config_ext_wakeup(p_config->pin, PWR_EXTWKUP_TYPE_FALLING);
256                 break;
257 
258             case APP_IO_MODE_IT_HIGH:
259                 hal_pwr_config_ext_wakeup(p_config->pin, PWR_EXTWKUP_TYPE_HIGH);
260                 break;
261 
262             case APP_IO_MODE_IT_LOW:
263                 hal_pwr_config_ext_wakeup(p_config->pin, PWR_EXTWKUP_TYPE_LOW);
264                 break;
265 
266             default:
267                 break;
268         }
269         pwr_mgmt_wakeup_source_setup(PWR_WKUP_COND_EXT);
270     }
271 }
272 
app_gpiote_config(const app_gpiote_param_t * p_config)273 uint16_t app_gpiote_config(const app_gpiote_param_t *p_config)
274 {
275     uint8_t exit_flag = 0x0;
276     uint8_t index;
277     app_io_init_t io_init;
278     app_drv_err_t err_code;
279 
280     if (p_config == NULL) {
281         return APP_DRV_ERR_POINTER_NULL;
282     }
283 
284     for (index = 0; index < s_gpiote_env.total_used; index ++) {
285         if (s_gpiote_env.params[index].pin == p_config->pin && \
286                 s_gpiote_env.params[index].type == p_config->type) {
287             exit_flag = 0x1;
288             break;
289         }
290     }
291 
292     if (!exit_flag || index >= GPIOTE_USE_MAX) {
293         return APP_DRV_ERR_INVALID_PARAM;
294     }
295 
296     memcpy_s(&s_gpiote_env.params[index], sizeof(s_gpiote_env.params[index]),
297              p_config, sizeof(app_gpiote_param_t));
298 
299     io_init.pin  = p_config->pin;
300     io_init.mode = p_config->mode;
301     io_init.pull = p_config->pull;
302     io_init.mux  = APP_IO_MUX_7;
303 
304     app_io_deinit(p_config->type, p_config->pin);
305     err_code = app_io_init(p_config->type, &io_init);
306     APP_DRV_ERR_CODE_CHECK(err_code);
307 
308     gpiote_config_wake_up_config(p_config);
309 
310     if ((p_config->handle_mode == APP_IO_DISABLE_WAKEUP) && (p_config->type == APP_IO_TYPE_AON)) {
311         hal_pwr_disable_ext_wakeup(p_config->pin);
312     }
313 
314     if (p_config->type == APP_IO_TYPE_NORMAL) {
315         hal_nvic_clear_pending_irq(EXT0_IRQn);
316         hal_nvic_enable_irq(EXT0_IRQn);
317         hal_nvic_clear_pending_irq(EXT1_IRQn);
318         hal_nvic_enable_irq(EXT1_IRQn);
319     } else if (p_config->type == APP_IO_TYPE_AON) {
320         hal_nvic_clear_pending_irq(EXT2_IRQn);
321         hal_nvic_enable_irq(EXT2_IRQn);
322     }
323 
324     return APP_DRV_SUCCESS;
325 }
326 
app_gpiote_deinit(void)327 void app_gpiote_deinit(void)
328 {
329     for (int idx = 0; idx < s_gpiote_env.total_used; idx++) {
330         app_io_deinit(s_gpiote_env.params[idx].type, s_gpiote_env.params[idx].pin);
331     }
332     hal_nvic_disable_irq(EXT0_IRQn);
333     hal_nvic_disable_irq(EXT1_IRQn);
334     hal_nvic_disable_irq(EXT2_IRQn);
335     pwr_unregister_sleep_cb(s_gpiote_pwr_id);
336     s_gpiote_env.total_used = 0;
337 }
338 
hal_gpio_exti_callback(gpio_regs_t * GPIOx,uint16_t gpio_pin)339 void hal_gpio_exti_callback(gpio_regs_t *GPIOx, uint16_t gpio_pin)
340 {
341     uint32_t io_pin = gpio_pin;
342     app_gpiote_evt_t gpiote_evt;
343 
344     if (GPIO1 == GPIOx) {
345         io_pin = (uint32_t)(gpio_pin << BIT_16);
346     }
347 
348     gpiote_evt.type = APP_IO_TYPE_NORMAL;
349     gpiote_evt.pin = io_pin;
350     gpiote_evt.ctx_type = APP_IO_CTX_INT;
351 
352     for (uint8_t idx = 0; idx < s_gpiote_env.total_used; idx++) {
353         if ((s_gpiote_env.params[idx].type == APP_IO_TYPE_NORMAL) && (io_pin == s_gpiote_env.params[idx].pin)) {
354             if (s_gpiote_env.params[idx].io_evt_cb)
355                 s_gpiote_env.params[idx].io_evt_cb(&gpiote_evt);
356         }
357     }
358 }
359 
gpio_callback_config(uint8_t idx,uint16_t aon_gpio_pin,uint8_t * p_called_flag,uint8_t * p_called_table_used_pos,app_gpiote_evt_t gpiote_evt)360 static void gpio_callback_config(uint8_t idx, uint16_t aon_gpio_pin, uint8_t *p_called_flag,
361                                  uint8_t *p_called_table_used_pos, app_gpiote_evt_t gpiote_evt)
362 {
363     if ((s_gpiote_env.params[idx].type == APP_IO_TYPE_AON) && \
364         (aon_gpio_pin & s_gpiote_env.params[idx].pin) && \
365         (s_gpiote_env.params[idx].io_evt_cb)) {
366         for (uint8_t i = 0; i < *p_called_table_used_pos; i++) {
367             if (aon_cb_called_table[i] == s_gpiote_env.params[idx].io_evt_cb) {
368                 *p_called_flag = 1;
369                 break;
370             } else {
371                 *p_called_flag = 0;
372             }
373         }
374         if (*p_called_flag == 0) {
375             s_gpiote_env.params[idx].io_evt_cb(&gpiote_evt);
376             aon_cb_called_table[*p_called_table_used_pos] = s_gpiote_env.params[idx].io_evt_cb;
377             *p_called_table_used_pos++;
378         }
379     }
380 }
381 
hal_aon_gpio_callback(uint16_t aon_gpio_pin)382 void hal_aon_gpio_callback(uint16_t aon_gpio_pin)
383 {
384     uint8_t called_table_used_pos = 0;
385     uint8_t called_flag = 0;
386 
387     app_gpiote_evt_t gpiote_evt;
388 
389     gpiote_evt.type = APP_IO_TYPE_AON;
390     gpiote_evt.pin = aon_gpio_pin;
391 
392     if (pwr_mgmt_get_wakeup_flag() == WARM_BOOT) {
393         gpiote_evt.ctx_type = APP_IO_CTX_WAKEUP;
394     } else {
395         gpiote_evt.ctx_type = APP_IO_CTX_INT;
396     }
397 
398     memset_s(aon_cb_called_table, sizeof(aon_cb_called_table), 0, sizeof(aon_cb_called_table));
399     for (uint8_t idx = 0; idx < s_gpiote_env.total_used; idx++) {
400         gpio_callback_config(idx, aon_gpio_pin, &called_flag,
401                              &called_table_used_pos, gpiote_evt);
402     }
403 }
404 
EXT0_IRQHandler(void)405 SECTION_RAM_CODE void EXT0_IRQHandler(void)
406 {
407 #if FLASH_PROTECT_PRIORITY
408     platform_interrupt_protection_push();
409 #endif
410     hal_gpio_exti_irq_handler(GPIO0);
411 #if FLASH_PROTECT_PRIORITY
412     platform_interrupt_protection_pop();
413 #endif
414 }
415 
EXT1_IRQHandler(void)416 SECTION_RAM_CODE void EXT1_IRQHandler(void)
417 {
418 #if FLASH_PROTECT_PRIORITY
419     platform_interrupt_protection_push();
420 #endif
421     hal_gpio_exti_irq_handler(GPIO1);
422 #if FLASH_PROTECT_PRIORITY
423     platform_interrupt_protection_pop();
424 #endif
425 }
426 
EXT2_IRQHandler(void)427 SECTION_RAM_CODE void EXT2_IRQHandler(void)
428 {
429 #if FLASH_PROTECT_PRIORITY
430     platform_interrupt_protection_push();
431 #endif
432     hal_aon_gpio_irq_handler();
433 #if FLASH_PROTECT_PRIORITY
434     platform_interrupt_protection_pop();
435 #endif
436 }
437