Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015 - 2022, Nordic Semiconductor ASA
3 : : * All rights reserved.
4 : : *
5 : : * SPDX-License-Identifier: BSD-3-Clause
6 : : *
7 : : * Redistribution and use in source and binary forms, with or without
8 : : * modification, are permitted provided that the following conditions are met:
9 : : *
10 : : * 1. Redistributions of source code must retain the above copyright notice, this
11 : : * list of conditions and the following disclaimer.
12 : : *
13 : : * 2. Redistributions in binary form must reproduce the above copyright
14 : : * notice, this list of conditions and the following disclaimer in the
15 : : * documentation and/or other materials provided with the distribution.
16 : : *
17 : : * 3. Neither the name of the copyright holder nor the names of its
18 : : * contributors may be used to endorse or promote products derived from this
19 : : * software without specific prior written permission.
20 : : *
21 : : * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 : : * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 : : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 : : * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 : : * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 : : * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 : : * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 : : * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 : : * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 : : * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 : : * POSSIBILITY OF SUCH DAMAGE.
32 : : */
33 : : #include <nrfx.h>
34 : :
35 : : #if NRFX_CHECK(NRFX_GPIOTE_ENABLED)
36 : :
37 : : #include <nrfx_gpiote.h>
38 : : #include <helpers/nrfx_flag32_allocator.h>
39 : : #include "nrf_bitmask.h"
40 : : #include <string.h>
41 : :
42 : : #define NRFX_LOG_MODULE GPIOTE
43 : : #include <nrfx_log.h>
44 : :
45 : : #if (GPIO_COUNT == 1)
46 : : #define MAX_PIN_NUMBER 32
47 : : #elif (GPIO_COUNT == 2)
48 : : #define MAX_PIN_NUMBER (32 + P1_PIN_NUM)
49 : : #else
50 : : #error "Not supported."
51 : : #endif
52 : :
53 : : /* Use legacy configuration if new is not present. That will lead to slight
54 : : * increase of RAM usage since number of slots will exceed application need.
55 : : */
56 : : #ifndef NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS
57 : : #define NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS \
58 : : (GPIOTE_CH_NUM + NRFX_GPIOTE_CONFIG_NUM_OF_LOW_POWER_EVENTS)
59 : : #endif
60 : :
61 : : /* Verify that trigger matches gpiote enum. */
62 : : NRFX_STATIC_ASSERT(NRFX_GPIOTE_TRIGGER_LOTOHI == GPIOTE_CONFIG_POLARITY_LoToHi);
63 : : NRFX_STATIC_ASSERT(NRFX_GPIOTE_TRIGGER_HITOLO == GPIOTE_CONFIG_POLARITY_HiToLo);
64 : : NRFX_STATIC_ASSERT(NRFX_GPIOTE_TRIGGER_TOGGLE == GPIOTE_CONFIG_POLARITY_Toggle);
65 : :
66 : : /*
67 : : * 2 bytes are dedicated for each pin to store it's current state.
68 : : *
69 : : * +--------+-------+-----------------------+-----+--------+--------+---------+-------+
70 : : * | 0 | 1 | 2-4 | 5 | 6 | 7 | 8-12 | 13-15 |
71 : : * +--------+-------+-----------------------+-----+--------+--------+---------+-------+
72 : : * | in use | dir | nrfx_gpiote_trigger_t | te | skip | legacy |8: | TE |
73 : : * | 0: no | 0:in | | used| config | api | present | index |
74 : : * | 1: yes | 1:out | | | | |9-12: | (when |
75 : : * | | | | | | | handler | used)|
76 : : * | | | | | | | index | |
77 : : * +--------+-------+-----------------------+-----+--------+--------+---------+-------+
78 : : *
79 : : */
80 : :
81 : : /* Flags content when pin is not used by the driver. */
82 : : #define PIN_FLAG_NOT_USED 0
83 : :
84 : : #define PIN_FLAG_IN_USE NRFX_BIT(0)
85 : :
86 : : #define PIN_FLAG_DIR_MASK NRFX_BIT(1)
87 : :
88 : : /* Flag indicating output direction. */
89 : : #define PIN_FLAG_OUTPUT PIN_FLAG_DIR_MASK
90 : :
91 : : /* Macro checks if pin is output. */
92 : : #define PIN_FLAG_IS_OUTPUT(flags) ((flags & PIN_FLAG_DIR_MASK) == PIN_FLAG_OUTPUT)
93 : :
94 : : /* Trigger mode field. It stores the information about a trigger type. If trigger
95 : : * is not enabled, it holds information about task usage and pin direction. */
96 : : #define PIN_FLAG_TRIG_MODE_OFFSET 2
97 : : #define PIN_FLAG_TRIG_MODE_BITS 3
98 : : #define PIN_FLAG_TRIG_MODE_MASK \
99 : : (NRFX_BIT_MASK(PIN_FLAG_TRIG_MODE_BITS) << PIN_FLAG_TRIG_MODE_OFFSET)
100 : : NRFX_STATIC_ASSERT(NRFX_GPIOTE_TRIGGER_MAX <= NRFX_BIT(PIN_FLAG_TRIG_MODE_BITS));
101 : :
102 : : /* Macro sets trigger mode field. */
103 : : #define PIN_FLAG_TRIG_MODE_SET(trigger) (trigger << PIN_FLAG_TRIG_MODE_OFFSET)
104 : :
105 : : /* Macro gets trigger mode from pin flags. */
106 : : #define PIN_FLAG_TRIG_MODE_GET(flags) \
107 : : (nrfx_gpiote_trigger_t)((flags & PIN_FLAG_TRIG_MODE_MASK) >> PIN_FLAG_TRIG_MODE_OFFSET)
108 : :
109 : : #define PIN_FLAG_TE_USED NRFX_BIT(5)
110 : : #define PIN_FLAG_SKIP_CONFIG NRFX_BIT(6)
111 : : #define PIN_FLAG_LEGACY_API_PIN NRFX_BIT(7)
112 : :
113 : : #define PIN_FLAG_HANDLER_PRESENT NRFX_BIT(8)
114 : :
115 : : #define PIN_HANDLER_ID_SHIFT 9
116 : : #define PIN_HANDLER_ID_BITS 4
117 : : #define PIN_HANDLER_ID_MASK (NRFX_BIT_MASK(PIN_HANDLER_ID_BITS) << PIN_HANDLER_ID_SHIFT)
118 : : #define PIN_HANDLER_MASK (PIN_FLAG_HANDLER_PRESENT | PIN_HANDLER_ID_MASK)
119 : :
120 : : /* Macro for encoding handler index into the flags. */
121 : : #define PIN_FLAG_HANDLER(x) \
122 : : (PIN_FLAG_HANDLER_PRESENT | ((x) << PIN_HANDLER_ID_SHIFT))
123 : :
124 : : /* Pin in use but no handler attached. */
125 : : #define PIN_FLAG_NO_HANDLER -1
126 : :
127 : : /* Macro for getting handler index from flags. -1 is returned when no handler */
128 : : #define PIN_GET_HANDLER_ID(flags) \
129 : : ((flags & PIN_FLAG_HANDLER_PRESENT) \
130 : : ? (int32_t)((flags & PIN_HANDLER_ID_MASK) >> PIN_HANDLER_ID_SHIFT) \
131 : : : PIN_FLAG_NO_HANDLER)
132 : :
133 : : #define PIN_HANDLER_MAX_COUNT NRFX_BIT_MASK(PIN_HANDLER_ID_BITS)
134 : : NRFX_STATIC_ASSERT(NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS <= PIN_HANDLER_MAX_COUNT);
135 : :
136 : : #define PIN_TE_ID_SHIFT 13
137 : : #define PIN_TE_ID_BITS 3
138 : : #define PIN_TE_ID_MASK (NRFX_BIT_MASK(PIN_TE_ID_BITS) << PIN_TE_ID_SHIFT)
139 : :
140 : : /* Validate that field is big enough for number of channels. */
141 : : NRFX_STATIC_ASSERT((NRFX_BIT(PIN_TE_ID_BITS)) >= GPIOTE_CH_NUM);
142 : :
143 : : /* Macro for encoding Task/Event index into the flags. */
144 : : #define PIN_FLAG_TE_ID(x) \
145 : : (PIN_FLAG_TE_USED | (((x) << PIN_TE_ID_SHIFT) & PIN_TE_ID_MASK))
146 : :
147 : : /* Macro for getting Task/Event index from flags. */
148 : : #define PIN_GET_TE_ID(flags) ((flags & PIN_TE_ID_MASK) >> PIN_TE_ID_SHIFT)
149 : :
150 : : /* Structure holding state of the pins */
151 : : typedef struct
152 : : {
153 : : /* Pin specific handlers. */
154 : : nrfx_gpiote_handler_config_t handlers[NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS];
155 : :
156 : : /* Global handler called on each event */
157 : : nrfx_gpiote_handler_config_t global_handler;
158 : :
159 : : /* Each pin state */
160 : : uint16_t pin_flags[MAX_PIN_NUMBER];
161 : :
162 : : /* Mask for tracking gpiote channel allocation. */
163 : : nrfx_atomic_t available_channels_mask;
164 : :
165 : : /* Mask for tracking event handler entries allocation. */
166 : : nrfx_atomic_t available_evt_handlers;
167 : :
168 : : #if !defined(NRF_GPIO_LATCH_PRESENT)
169 : : uint32_t port_pins[GPIO_COUNT];
170 : : #endif
171 : : nrfx_drv_state_t state;
172 : : } gpiote_control_block_t;
173 : :
174 : : static gpiote_control_block_t m_cb = {
175 : : .available_channels_mask = NRFX_GPIOTE_APP_CHANNELS_MASK
176 : : };
177 : :
178 : : /** @brief Checks if pin is in use by the driver.
179 : : *
180 : : * @param[in] pin Absolute pin.
181 : : *
182 : : * @return True if pin is in use.
183 : : */
184 : 0 : static bool pin_in_use(uint32_t pin)
185 : : {
186 : 0 : return m_cb.pin_flags[pin] & PIN_FLAG_IN_USE;
187 : : }
188 : :
189 : : /** @brief Check if Task/Event is used.
190 : : *
191 : : * Assuming that pin is in use.
192 : : *
193 : : * @param[in] pin Absolute pin.
194 : : *
195 : : * @return True if pin uses GPIOTE task/event.
196 : : */
197 : 0 : static bool pin_in_use_by_te(uint32_t pin)
198 : : {
199 : 0 : return m_cb.pin_flags[pin] & PIN_FLAG_TE_USED;
200 : : }
201 : :
202 : : /** @brief Check if pin has trigger.
203 : : *
204 : : * @param[in] pin Absolute pin.
205 : : *
206 : : * @return True if pin has trigger.
207 : : */
208 : 0 : static bool pin_has_trigger(uint32_t pin)
209 : : {
210 : 0 : return PIN_FLAG_TRIG_MODE_GET(m_cb.pin_flags[pin]) != NRFX_GPIOTE_TRIGGER_NONE;
211 : : }
212 : :
213 : : /** @brief Check if pin is output.
214 : : *
215 : : * Assuming that pin is in use.
216 : : *
217 : : * @param[in] pin Absolute pin.
218 : : *
219 : : * @return True if pin is output.
220 : : */
221 : 0 : static bool pin_is_output(uint32_t pin)
222 : : {
223 : 0 : return PIN_FLAG_IS_OUTPUT(m_cb.pin_flags[pin]);
224 : : }
225 : :
226 : : /** @brief Check if pin is output controlled by GPIOTE task.
227 : : *
228 : : * @param[in] pin Absolute pin.
229 : : *
230 : : * @return True if pin is task output.
231 : : */
232 : 0 : static bool pin_is_task_output(uint32_t pin)
233 : : {
234 [ # # # # ]: 0 : return pin_is_output(pin) && pin_in_use_by_te(pin);
235 : : }
236 : :
237 : : /** @brief Check if pin is used by the driver and configured as input.
238 : : *
239 : : * @param[in] pin Absolute pin.
240 : : *
241 : : * @return True if pin is configured as input.
242 : : */
243 : 0 : static bool pin_is_input(uint32_t pin)
244 : : {
245 : 0 : return !pin_is_output(pin);
246 : : }
247 : :
248 : : /* Convert polarity enum (HAL) to trigger enum. */
249 : 0 : static nrfx_gpiote_trigger_t gpiote_polarity_to_trigger(nrf_gpiote_polarity_t polarity)
250 : : {
251 : 0 : return (nrfx_gpiote_trigger_t)polarity;
252 : : }
253 : :
254 : : /* Convert trigger enum to polarity enum (HAL). */
255 : 0 : static nrf_gpiote_polarity_t gpiote_trigger_to_polarity(nrfx_gpiote_trigger_t trigger)
256 : : {
257 : 0 : return (nrf_gpiote_polarity_t)trigger;
258 : : }
259 : :
260 : : /* Returns gpiote TE channel associated with the pin */
261 : 0 : static uint8_t pin_te_get(nrfx_gpiote_pin_t pin)
262 : : {
263 : 0 : return PIN_GET_TE_ID(m_cb.pin_flags[pin]);
264 : : }
265 : :
266 : 0 : static bool is_level(nrfx_gpiote_trigger_t trigger)
267 : : {
268 : 0 : return trigger >= NRFX_GPIOTE_TRIGGER_LOW;
269 : : }
270 : :
271 : 0 : static bool handler_in_use(int32_t handler_id)
272 : : {
273 : :
274 [ # # ]: 0 : for (uint32_t i = 0; i < MAX_PIN_NUMBER; i++)
275 : : {
276 [ # # # # ]: 0 : if (PIN_GET_HANDLER_ID(m_cb.pin_flags[i]) == handler_id)
277 : : {
278 : 0 : return true;
279 : : }
280 : : }
281 : :
282 : 0 : return false;
283 : : }
284 : :
285 : : /* Function clears pin handler flag and releases handler slot if handler+context
286 : : * pair is not used by other pin. */
287 : 0 : static void release_handler(nrfx_gpiote_pin_t pin)
288 : : {
289 [ # # ]: 0 : int32_t handler_id = PIN_GET_HANDLER_ID(m_cb.pin_flags[pin]);
290 : :
291 [ # # ]: 0 : if (handler_id == PIN_FLAG_NO_HANDLER)
292 : : {
293 : 0 : return;
294 : : }
295 : :
296 : 0 : m_cb.pin_flags[pin] &= ~PIN_HANDLER_MASK;
297 : :
298 : : /* Check if other pin is using same handler and release handler only if handler
299 : : * is not used by others.
300 : : */
301 [ # # ]: 0 : if (!handler_in_use(handler_id))
302 : : {
303 : 0 : m_cb.handlers[handler_id].handler = NULL;
304 : 0 : nrfx_err_t err = nrfx_flag32_free(&m_cb.available_evt_handlers, handler_id);
305 : : (void)err;
306 [ # # ]: 0 : NRFX_ASSERT(err == NRFX_SUCCESS);
307 : : }
308 : : }
309 : :
310 : : /* Function releases the handler associated with the pin and sets GPIOTE channel
311 : : * configuration to default if it was used with the pin.
312 : : */
313 : 0 : static void pin_handler_trigger_uninit(nrfx_gpiote_pin_t pin)
314 : : {
315 [ # # ]: 0 : if (pin_in_use_by_te(pin))
316 : : {
317 : : /* te to default */
318 : 0 : nrf_gpiote_te_default(NRF_GPIOTE, pin_te_get(pin));
319 : : }
320 : : else
321 : : {
322 : : #if !defined(NRF_GPIO_LATCH_PRESENT)
323 : : nrf_bitmask_bit_clear(pin, (uint8_t *)m_cb.port_pins);
324 : : #endif
325 : : }
326 : :
327 : 0 : release_handler(pin);
328 : 0 : m_cb.pin_flags[pin] = PIN_FLAG_NOT_USED;
329 : 0 : }
330 : :
331 : 0 : nrfx_err_t nrfx_gpiote_pin_uninit(nrfx_gpiote_pin_t pin)
332 : : {
333 [ # # ]: 0 : if (!pin_in_use(pin))
334 : : {
335 : 0 : return NRFX_ERROR_INVALID_PARAM;
336 : : }
337 : :
338 : 0 : nrfx_gpiote_trigger_disable(pin);
339 : 0 : pin_handler_trigger_uninit(pin);
340 : 0 : nrf_gpio_cfg_default(pin);
341 : :
342 : 0 : return NRFX_SUCCESS;
343 : : }
344 : :
345 : 0 : static int32_t find_handler(nrfx_gpiote_interrupt_handler_t handler, void * p_context)
346 : : {
347 [ # # ]: 0 : for (uint32_t i = 0; i < NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS; i++)
348 : : {
349 [ # # # # ]: 0 : if ((m_cb.handlers[i].handler == handler) && (m_cb.handlers[i].p_context == p_context))
350 : : {
351 : 0 : return i;
352 : : }
353 : : }
354 : :
355 : 0 : return -1;
356 : : }
357 : :
358 : : /** @brief Set new handler, if handler was not previously set allocate it. */
359 : 0 : static nrfx_err_t pin_handler_set(nrfx_gpiote_pin_t pin,
360 : : nrfx_gpiote_interrupt_handler_t handler,
361 : : void * p_context)
362 : : {
363 : : nrfx_err_t err;
364 : : int32_t handler_id;
365 : :
366 : 0 : release_handler(pin);
367 [ # # ]: 0 : if (!handler)
368 : : {
369 : 0 : return NRFX_SUCCESS;
370 : : }
371 : :
372 : 0 : handler_id = find_handler(handler, p_context);
373 : : /* Handler not found, new must be allocated. */
374 [ # # ]: 0 : if (handler_id < 0)
375 : : {
376 : : uint8_t id;
377 : :
378 : 0 : err = nrfx_flag32_alloc(&m_cb.available_evt_handlers, &id);
379 [ # # ]: 0 : if (err != NRFX_SUCCESS)
380 : : {
381 : 0 : return err;
382 : : }
383 : 0 : handler_id = (int32_t)id;
384 : : }
385 : :
386 : 0 : m_cb.handlers[handler_id].handler = handler;
387 : 0 : m_cb.handlers[handler_id].p_context = p_context;
388 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_HANDLER(handler_id);
389 : :
390 : 0 : return NRFX_SUCCESS;
391 : : }
392 : :
393 : 0 : static inline nrf_gpio_pin_sense_t get_initial_sense(nrfx_gpiote_pin_t pin)
394 : : {
395 : 0 : nrfx_gpiote_trigger_t trigger = PIN_FLAG_TRIG_MODE_GET(m_cb.pin_flags[pin]);
396 : : nrf_gpio_pin_sense_t sense;
397 : :
398 [ # # ]: 0 : if (trigger == NRFX_GPIOTE_TRIGGER_LOW)
399 : : {
400 : 0 : sense = NRF_GPIO_PIN_SENSE_LOW;
401 : : }
402 [ # # ]: 0 : else if (trigger == NRFX_GPIOTE_TRIGGER_HIGH)
403 : : {
404 : 0 : sense = NRF_GPIO_PIN_SENSE_HIGH;
405 : : }
406 : : else
407 : : {
408 : : /* If edge detection start with sensing opposite state. */
409 [ # # ]: 0 : sense = nrf_gpio_pin_read(pin) ? NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
410 : : }
411 : :
412 : 0 : return sense;
413 : : }
414 : :
415 : 0 : nrfx_err_t nrfx_gpiote_input_configure(nrfx_gpiote_pin_t pin,
416 : : nrfx_gpiote_input_config_t const * p_input_config,
417 : : nrfx_gpiote_trigger_config_t const * p_trigger_config,
418 : : nrfx_gpiote_handler_config_t const * p_handler_config)
419 : : {
420 : : nrfx_err_t err;
421 : :
422 [ # # ]: 0 : if (p_input_config)
423 : : {
424 [ # # ]: 0 : if (pin_is_task_output(pin))
425 : : {
426 : 0 : return NRFX_ERROR_INVALID_PARAM;
427 : : }
428 : :
429 : 0 : nrf_gpio_pin_dir_t dir = NRF_GPIO_PIN_DIR_INPUT;
430 : 0 : nrf_gpio_pin_input_t input_connect = NRF_GPIO_PIN_INPUT_CONNECT;
431 : :
432 : 0 : nrf_gpio_reconfigure(pin, &dir, &input_connect, &p_input_config->pull, NULL, NULL);
433 : :
434 : 0 : m_cb.pin_flags[pin] &= ~PIN_FLAG_OUTPUT;
435 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_IN_USE;
436 : : }
437 : :
438 [ # # ]: 0 : if (p_trigger_config)
439 : : {
440 : 0 : nrfx_gpiote_trigger_t trigger = p_trigger_config->trigger;
441 : 0 : bool use_evt = p_trigger_config->p_in_channel ? true : false;
442 : :
443 [ # # ]: 0 : if (pin_is_output(pin))
444 : : {
445 [ # # ]: 0 : if (use_evt)
446 : : {
447 : 0 : return NRFX_ERROR_INVALID_PARAM;
448 : : }
449 : : }
450 : : else
451 : : {
452 : 0 : m_cb.pin_flags[pin] &= ~(PIN_TE_ID_MASK | PIN_FLAG_TE_USED);
453 [ # # ]: 0 : if (use_evt)
454 : : {
455 : 0 : bool edge = trigger <= NRFX_GPIOTE_TRIGGER_TOGGLE;
456 : :
457 : : /* IN event used. */
458 [ # # ]: 0 : if (!edge)
459 : : {
460 : : /* IN event supports only edge trigger. */
461 : 0 : return NRFX_ERROR_INVALID_PARAM;
462 : : }
463 : :
464 : 0 : uint8_t ch = *p_trigger_config->p_in_channel;
465 : :
466 [ # # ]: 0 : if (trigger == NRFX_GPIOTE_TRIGGER_NONE)
467 : : {
468 : 0 : nrf_gpiote_te_default(NRF_GPIOTE, ch);
469 : : }
470 : : else
471 : : {
472 : 0 : nrf_gpiote_polarity_t polarity = gpiote_trigger_to_polarity(trigger);
473 : :
474 : 0 : nrf_gpiote_event_disable(NRF_GPIOTE, ch);
475 : 0 : nrf_gpiote_event_configure(NRF_GPIOTE, ch, pin, polarity);
476 : :
477 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_TE_ID(ch);
478 : : }
479 : : }
480 : : }
481 : : #if !defined(NRF_GPIO_LATCH_PRESENT)
482 : : if (use_evt || trigger == NRFX_GPIOTE_TRIGGER_NONE)
483 : : {
484 : : nrf_bitmask_bit_clear(pin, (uint8_t *)m_cb.port_pins);
485 : : }
486 : : else
487 : : {
488 : : nrf_bitmask_bit_set(pin, (uint8_t *)m_cb.port_pins);
489 : : }
490 : : #endif
491 : 0 : m_cb.pin_flags[pin] &= ~PIN_FLAG_TRIG_MODE_MASK;
492 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_TRIG_MODE_SET(trigger);
493 : : }
494 : :
495 [ # # ]: 0 : if (p_handler_config)
496 : : {
497 : 0 : err = pin_handler_set(pin, p_handler_config->handler, p_handler_config->p_context);
498 : : }
499 : : else
500 : : {
501 : 0 : err = NRFX_SUCCESS;
502 : : }
503 : :
504 : 0 : return err;
505 : : }
506 : :
507 : 0 : nrfx_err_t nrfx_gpiote_output_configure(nrfx_gpiote_pin_t pin,
508 : : nrfx_gpiote_output_config_t const * p_config,
509 : : nrfx_gpiote_task_config_t const * p_task_config)
510 : : {
511 [ # # ]: 0 : if (p_config)
512 : : {
513 : : /* Cannot configure pin to output if pin was using TE event. */
514 [ # # # # ]: 0 : if (pin_is_input(pin) && pin_in_use_by_te(pin))
515 : : {
516 : 0 : return NRFX_ERROR_INVALID_PARAM;
517 : : }
518 : :
519 : : /* If reconfiguring to output pin that has trigger configured then accept
520 : : * only when input is still connected. */
521 [ # # # # ]: 0 : if (pin_has_trigger(pin) && (p_config->input_connect == NRF_GPIO_PIN_INPUT_DISCONNECT))
522 : : {
523 : 0 : return NRFX_ERROR_INVALID_PARAM;
524 : : }
525 : :
526 : 0 : nrf_gpio_pin_dir_t dir = NRF_GPIO_PIN_DIR_OUTPUT;
527 : :
528 : 0 : nrf_gpio_reconfigure(pin, &dir, &p_config->input_connect, &p_config->pull,
529 : : &p_config->drive, NULL);
530 : :
531 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_IN_USE | PIN_FLAG_OUTPUT;
532 : : }
533 : :
534 [ # # ]: 0 : if (p_task_config)
535 : : {
536 [ # # ]: 0 : if (pin_is_input(pin))
537 : : {
538 : 0 : return NRFX_ERROR_INVALID_PARAM;
539 : : }
540 : :
541 : 0 : uint32_t ch = p_task_config->task_ch;
542 : :
543 : 0 : nrf_gpiote_te_default(NRF_GPIOTE, ch);
544 : 0 : m_cb.pin_flags[pin] &= ~(PIN_FLAG_TE_USED | PIN_TE_ID_MASK);
545 [ # # ]: 0 : if (p_task_config->polarity != NRF_GPIOTE_POLARITY_NONE)
546 : : {
547 : 0 : nrf_gpiote_task_configure(NRF_GPIOTE, ch, pin,
548 : : p_task_config->polarity,
549 : : p_task_config->init_val);
550 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_TE_ID(ch);
551 : : }
552 : : }
553 : :
554 : 0 : return NRFX_SUCCESS;
555 : : }
556 : :
557 : 1 : void nrfx_gpiote_global_callback_set(nrfx_gpiote_interrupt_handler_t handler, void * p_context)
558 : : {
559 : 1 : m_cb.global_handler.handler = handler;
560 : 1 : m_cb.global_handler.p_context = p_context;
561 : 1 : }
562 : :
563 : 0 : nrfx_err_t nrfx_gpiote_channel_get(nrfx_gpiote_pin_t pin, uint8_t *p_channel)
564 : : {
565 [ # # ]: 0 : NRFX_ASSERT(p_channel);
566 : :
567 [ # # ]: 0 : if (pin_in_use_by_te(pin))
568 : : {
569 : 0 : *p_channel = PIN_GET_TE_ID(m_cb.pin_flags[pin]);
570 : 0 : return NRFX_SUCCESS;
571 : : }
572 : : else
573 : : {
574 : 0 : return NRFX_ERROR_INVALID_PARAM;
575 : : }
576 : : }
577 : :
578 : : /* Return handler associated with given pin or null. */
579 : 0 : static nrfx_gpiote_handler_config_t const * channel_handler_get(nrfx_gpiote_pin_t pin)
580 : : {
581 [ # # ]: 0 : int32_t handler_id = PIN_GET_HANDLER_ID(m_cb.pin_flags[pin]);
582 : :
583 [ # # ]: 0 : if (handler_id == PIN_FLAG_NO_HANDLER)
584 : : {
585 : 0 : return NULL;
586 : : }
587 : :
588 : 0 : return &m_cb.handlers[handler_id];
589 : : }
590 : :
591 : 1 : nrfx_err_t nrfx_gpiote_init(uint8_t interrupt_priority)
592 : : {
593 : : nrfx_err_t err_code;
594 : :
595 [ - + ]: 1 : if (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED)
596 : : {
597 : 0 : err_code = NRFX_ERROR_INVALID_STATE;
598 [ # # ]: 0 : NRFX_LOG_WARNING("Function: %s, error code: %s.",
599 : : __func__,
600 : : NRFX_LOG_ERROR_STRING_GET(err_code));
601 : 0 : return err_code;
602 : : }
603 : :
604 : 1 : memset(m_cb.pin_flags, 0, sizeof(m_cb.pin_flags));
605 : :
606 : : NRFX_IRQ_PRIORITY_SET(nrfx_get_irq_number(NRF_GPIOTE), interrupt_priority);
607 : 1 : NRFX_IRQ_ENABLE(nrfx_get_irq_number(NRF_GPIOTE));
608 : :
609 : 1 : nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
610 : 1 : nrf_gpiote_int_enable(NRF_GPIOTE, (uint32_t)NRF_GPIOTE_INT_PORT_MASK);
611 : 1 : m_cb.state = NRFX_DRV_STATE_INITIALIZED;
612 : 1 : m_cb.available_evt_handlers = NRFX_BIT_MASK(NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS);
613 : :
614 : 1 : err_code = NRFX_SUCCESS;
615 [ + - ]: 1 : NRFX_LOG_INFO("Function: %s, error code: %s.", __func__, NRFX_LOG_ERROR_STRING_GET(err_code));
616 : 1 : return err_code;
617 : : }
618 : :
619 : :
620 : 2 : bool nrfx_gpiote_is_init(void)
621 : : {
622 : 2 : return (m_cb.state != NRFX_DRV_STATE_UNINITIALIZED) ? true : false;
623 : : }
624 : :
625 : :
626 : 0 : void nrfx_gpiote_uninit(void)
627 : : {
628 [ # # ]: 0 : NRFX_ASSERT(m_cb.state != NRFX_DRV_STATE_UNINITIALIZED);
629 : :
630 : : uint32_t i;
631 : :
632 [ # # ]: 0 : for (i = 0; i < MAX_PIN_NUMBER; i++)
633 : : {
634 [ # # # # ]: 0 : if (nrf_gpio_pin_present_check(i) && pin_in_use(i))
635 : : {
636 [ # # ]: 0 : if (m_cb.pin_flags[i] & PIN_FLAG_LEGACY_API_PIN)
637 : : {
638 : 0 : m_cb.pin_flags[i] &= ~PIN_FLAG_LEGACY_API_PIN;
639 [ # # ]: 0 : if (pin_has_trigger(i))
640 : : {
641 : 0 : nrfx_gpiote_in_uninit(i);
642 : : }
643 : : else
644 : : {
645 : 0 : nrfx_gpiote_out_uninit(i);
646 : : }
647 : : }
648 : : else
649 : : {
650 : 0 : nrfx_gpiote_pin_uninit(i);
651 : : }
652 : : }
653 : : }
654 : 0 : m_cb.state = NRFX_DRV_STATE_UNINITIALIZED;
655 [ # # ]: 0 : NRFX_LOG_INFO("Uninitialized.");
656 : 0 : }
657 : :
658 : 0 : nrfx_err_t nrfx_gpiote_channel_free(uint8_t channel)
659 : : {
660 : 0 : return nrfx_flag32_free(&m_cb.available_channels_mask, channel);
661 : : }
662 : :
663 : 0 : nrfx_err_t nrfx_gpiote_channel_alloc(uint8_t * p_channel)
664 : : {
665 : 0 : return nrfx_flag32_alloc(&m_cb.available_channels_mask, p_channel);
666 : : }
667 : :
668 : 0 : nrfx_err_t nrfx_gpiote_out_init(nrfx_gpiote_pin_t pin,
669 : : nrfx_gpiote_out_config_t const * p_config)
670 : : {
671 : : uint8_t ch;
672 : : nrfx_err_t err;
673 : :
674 [ # # ]: 0 : if (p_config->task_pin)
675 : : {
676 : 0 : err = nrfx_gpiote_channel_alloc(&ch);
677 [ # # ]: 0 : if (err != NRFX_SUCCESS)
678 : : {
679 : 0 : return err;
680 : : }
681 : : }
682 : : else
683 : : {
684 : : /* Value will not be used. */
685 : 0 : ch = 0xFF;
686 : : }
687 : :
688 : 0 : err = nrfx_gpiote_out_prealloc_init(pin, p_config, ch);
689 [ # # # # ]: 0 : if (err == NRFX_ERROR_BUSY && p_config->task_pin)
690 : : {
691 : 0 : nrfx_gpiote_channel_free(ch);
692 : : }
693 : :
694 : 0 : return err;
695 : : }
696 : :
697 : 0 : nrfx_err_t nrfx_gpiote_out_prealloc_init(nrfx_gpiote_pin_t pin,
698 : : nrfx_gpiote_out_config_t const * p_config,
699 : : uint8_t channel)
700 : : {
701 : 0 : nrfx_gpiote_output_config_t config = NRFX_GPIOTE_DEFAULT_OUTPUT_CONFIG;
702 : : nrfx_gpiote_task_config_t task_config;
703 : 0 : bool use_task = p_config->task_pin;
704 : : nrfx_err_t err;
705 : :
706 [ # # ]: 0 : if (pin_in_use(pin))
707 : : {
708 : 0 : return NRFX_ERROR_BUSY;
709 : : }
710 : :
711 [ # # ]: 0 : if (p_config->init_state == NRF_GPIOTE_INITIAL_VALUE_HIGH)
712 : : {
713 : 0 : nrf_gpio_pin_set(pin);
714 : : }
715 : :
716 [ # # ]: 0 : if (use_task)
717 : : {
718 : :
719 : 0 : task_config.task_ch = channel;
720 : 0 : task_config.init_val = p_config->init_state;
721 : 0 : task_config.polarity = p_config->action;
722 : : }
723 : :
724 [ # # ]: 0 : err = nrfx_gpiote_output_configure(pin, &config, use_task ? &task_config : NULL);
725 [ # # ]: 0 : if (err == NRFX_SUCCESS)
726 : : {
727 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_LEGACY_API_PIN;
728 : : }
729 : :
730 : 0 : return err;
731 : : }
732 : :
733 : 0 : void nrfx_gpiote_out_uninit(nrfx_gpiote_pin_t pin)
734 : : {
735 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
736 [ # # ]: 0 : NRFX_ASSERT(pin_in_use(pin));
737 : :
738 [ # # ]: 0 : uint8_t ch = pin_in_use_by_te(pin) ? pin_te_get(pin) : 0xFF;
739 : :
740 : 0 : nrfx_err_t err = nrfx_gpiote_pin_uninit(pin);
741 [ # # ]: 0 : NRFX_ASSERT(err == NRFX_SUCCESS);
742 : :
743 [ # # ]: 0 : if (ch != 0xFF)
744 : : {
745 : 0 : nrfx_gpiote_channel_free(ch);
746 : : }
747 : :
748 : : (void)err;
749 : 0 : }
750 : :
751 : :
752 : 0 : void nrfx_gpiote_out_set(nrfx_gpiote_pin_t pin)
753 : : {
754 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
755 [ # # # # ]: 0 : NRFX_ASSERT(pin_is_output(pin) && !pin_in_use_by_te(pin));
756 : :
757 : 0 : nrf_gpio_pin_set(pin);
758 : 0 : }
759 : :
760 : :
761 : 0 : void nrfx_gpiote_out_clear(nrfx_gpiote_pin_t pin)
762 : : {
763 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
764 [ # # # # ]: 0 : NRFX_ASSERT(pin_is_output(pin) && !pin_in_use_by_te(pin));
765 : :
766 : 0 : nrf_gpio_pin_clear(pin);
767 : 0 : }
768 : :
769 : :
770 : 0 : void nrfx_gpiote_out_toggle(nrfx_gpiote_pin_t pin)
771 : : {
772 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
773 [ # # # # ]: 0 : NRFX_ASSERT(pin_is_output(pin) && !pin_in_use_by_te(pin));
774 : :
775 : 0 : nrf_gpio_pin_toggle(pin);
776 : 0 : }
777 : :
778 : 0 : void nrfx_gpiote_out_task_enable(nrfx_gpiote_pin_t pin)
779 : : {
780 : : (void)pin_is_task_output; /* Add to avoid compiler warnings when asserts disabled.*/
781 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
782 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
783 : :
784 : 0 : nrf_gpiote_task_enable(NRF_GPIOTE, (uint32_t)pin_te_get(pin));
785 : 0 : }
786 : :
787 : :
788 : 0 : void nrfx_gpiote_out_task_disable(nrfx_gpiote_pin_t pin)
789 : : {
790 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
791 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
792 : :
793 : 0 : nrf_gpiote_task_disable(NRF_GPIOTE, (uint32_t)pin_te_get(pin));
794 : 0 : }
795 : :
796 : :
797 : 0 : nrf_gpiote_task_t nrfx_gpiote_out_task_get(nrfx_gpiote_pin_t pin)
798 : : {
799 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
800 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
801 : :
802 : 0 : return nrf_gpiote_out_task_get((uint8_t)pin_te_get(pin));
803 : : }
804 : :
805 : :
806 : 0 : uint32_t nrfx_gpiote_out_task_addr_get(nrfx_gpiote_pin_t pin)
807 : : {
808 : 0 : nrf_gpiote_task_t task = nrfx_gpiote_out_task_get(pin);
809 : 0 : return nrf_gpiote_task_address_get(NRF_GPIOTE, task);
810 : : }
811 : :
812 : :
813 : : #if defined(GPIOTE_FEATURE_SET_PRESENT)
814 : 0 : nrf_gpiote_task_t nrfx_gpiote_set_task_get(nrfx_gpiote_pin_t pin)
815 : : {
816 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
817 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
818 : :
819 : 0 : return nrf_gpiote_set_task_get((uint8_t)pin_te_get(pin));
820 : : }
821 : :
822 : :
823 : 0 : uint32_t nrfx_gpiote_set_task_addr_get(nrfx_gpiote_pin_t pin)
824 : : {
825 : 0 : nrf_gpiote_task_t task = nrfx_gpiote_set_task_get(pin);
826 : 0 : return nrf_gpiote_task_address_get(NRF_GPIOTE, task);
827 : : }
828 : : #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
829 : :
830 : :
831 : : #if defined(GPIOTE_FEATURE_CLR_PRESENT)
832 : 0 : nrf_gpiote_task_t nrfx_gpiote_clr_task_get(nrfx_gpiote_pin_t pin)
833 : : {
834 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
835 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
836 : :
837 : 0 : return nrf_gpiote_clr_task_get((uint8_t)pin_te_get(pin));
838 : : }
839 : :
840 : :
841 : 0 : uint32_t nrfx_gpiote_clr_task_addr_get(nrfx_gpiote_pin_t pin)
842 : : {
843 : 0 : nrf_gpiote_task_t task = nrfx_gpiote_clr_task_get(pin);
844 : 0 : return nrf_gpiote_task_address_get(NRF_GPIOTE, task);
845 : : }
846 : : #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
847 : :
848 : :
849 : 0 : void nrfx_gpiote_out_task_force(nrfx_gpiote_pin_t pin, uint8_t state)
850 : : {
851 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
852 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
853 : :
854 : 0 : nrf_gpiote_outinit_t init_val =
855 : 0 : state ? NRF_GPIOTE_INITIAL_VALUE_HIGH : NRF_GPIOTE_INITIAL_VALUE_LOW;
856 : 0 : nrf_gpiote_task_force(NRF_GPIOTE, (uint32_t)pin_te_get(pin), init_val);
857 : 0 : }
858 : :
859 : :
860 : 0 : void nrfx_gpiote_out_task_trigger(nrfx_gpiote_pin_t pin)
861 : : {
862 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
863 [ # # ]: 0 : NRFX_ASSERT(pin_is_task_output(pin));
864 : :
865 : 0 : nrf_gpiote_task_t task = nrf_gpiote_out_task_get((uint8_t)pin_te_get(pin));
866 : 0 : nrf_gpiote_task_trigger(NRF_GPIOTE, task);
867 : 0 : }
868 : :
869 : :
870 : : #if defined(GPIOTE_FEATURE_SET_PRESENT)
871 : 0 : void nrfx_gpiote_set_task_trigger(nrfx_gpiote_pin_t pin)
872 : : {
873 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
874 [ # # ]: 0 : NRFX_ASSERT(pin_in_use(pin));
875 [ # # ]: 0 : NRFX_ASSERT(pin_in_use_by_te(pin));
876 : :
877 : 0 : nrf_gpiote_task_t task = nrf_gpiote_set_task_get((uint8_t)pin_te_get(pin));
878 : 0 : nrf_gpiote_task_trigger(NRF_GPIOTE, task);
879 : 0 : }
880 : :
881 : :
882 : : #endif // defined(GPIOTE_FEATURE_SET_PRESENT)
883 : :
884 : : #if defined(GPIOTE_FEATURE_CLR_PRESENT)
885 : 0 : void nrfx_gpiote_clr_task_trigger(nrfx_gpiote_pin_t pin)
886 : : {
887 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
888 [ # # ]: 0 : NRFX_ASSERT(pin_in_use(pin));
889 [ # # ]: 0 : NRFX_ASSERT(pin_in_use_by_te(pin));
890 : :
891 : 0 : nrf_gpiote_task_t task = nrf_gpiote_clr_task_get((uint8_t)pin_te_get(pin));
892 : 0 : nrf_gpiote_task_trigger(NRF_GPIOTE, task);
893 : 0 : }
894 : :
895 : :
896 : : #endif // defined(GPIOTE_FEATURE_CLR_PRESENT)
897 : :
898 : :
899 : 0 : nrfx_err_t nrfx_gpiote_in_init(nrfx_gpiote_pin_t pin,
900 : : nrfx_gpiote_in_config_t const * p_config,
901 : : nrfx_gpiote_evt_handler_t evt_handler)
902 : : {
903 : : uint8_t ch;
904 : : nrfx_err_t err;
905 : :
906 [ # # ]: 0 : if (p_config->hi_accuracy)
907 : : {
908 : 0 : err = nrfx_gpiote_channel_alloc(&ch);
909 [ # # ]: 0 : if (err != NRFX_SUCCESS)
910 : : {
911 : 0 : return err;
912 : : }
913 : : }
914 : : else
915 : : {
916 : : /* Value will not be used. */
917 : 0 : ch = 0xFF;
918 : : }
919 : :
920 : 0 : err = nrfx_gpiote_in_prealloc_init(pin, p_config, ch, evt_handler);
921 [ # # # # ]: 0 : if ((err == NRFX_ERROR_NO_MEM) && p_config->hi_accuracy)
922 : : {
923 : 0 : nrfx_gpiote_channel_free(ch);
924 : : }
925 : :
926 : 0 : return err;
927 : : }
928 : :
929 : 0 : static void legacy_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t trigger, void * p_context)
930 : : {
931 [ # # ]: 0 : NRFX_ASSERT(trigger <= NRFX_GPIOTE_TRIGGER_TOGGLE);
932 : :
933 : 0 : ((nrfx_gpiote_evt_handler_t)p_context)(pin, gpiote_trigger_to_polarity(trigger));
934 : 0 : }
935 : :
936 : 0 : nrfx_err_t nrfx_gpiote_in_prealloc_init(nrfx_gpiote_pin_t pin,
937 : : nrfx_gpiote_in_config_t const * p_config,
938 : : uint8_t channel,
939 : : nrfx_gpiote_evt_handler_t evt_handler)
940 : : {
941 : : nrfx_err_t err;
942 : 0 : bool skip_in_config = false;
943 : : nrfx_gpiote_input_config_t input_config;
944 : 0 : nrfx_gpiote_trigger_config_t trigger_config = {
945 : 0 : .trigger = gpiote_polarity_to_trigger(p_config->sense),
946 [ # # ]: 0 : .p_in_channel = p_config->hi_accuracy ? &channel : NULL
947 : : };
948 : 0 : nrfx_gpiote_handler_config_t handler_config = {
949 : : .handler = legacy_handler,
950 : : .p_context = (void *)evt_handler
951 : : };
952 : :
953 [ # # ]: 0 : if (p_config->is_watcher)
954 : : {
955 : 0 : nrfx_gpiote_output_config_t output_config = {
956 : : .input_connect = NRF_GPIO_PIN_INPUT_CONNECT
957 : : };
958 : :
959 : 0 : skip_in_config = true;
960 : 0 : err = nrfx_gpiote_output_configure(pin, &output_config, NULL);
961 [ # # ]: 0 : if (err != NRFX_SUCCESS)
962 : : {
963 : 0 : return err;
964 : : }
965 : : }
966 : : else
967 : : {
968 : 0 : input_config.pull = p_config->pull;
969 : : }
970 : :
971 [ # # ]: 0 : if (p_config->skip_gpio_setup)
972 : : {
973 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_SKIP_CONFIG;
974 : 0 : skip_in_config = true;
975 : : }
976 : :
977 [ # # ]: 0 : err = nrfx_gpiote_input_configure(pin,
978 : : skip_in_config ? NULL : &input_config,
979 : : &trigger_config,
980 : : &handler_config);
981 [ # # ]: 0 : if (err == NRFX_SUCCESS)
982 : : {
983 : 0 : m_cb.pin_flags[pin] |= PIN_FLAG_LEGACY_API_PIN;
984 : : }
985 : :
986 : 0 : return err;
987 : : }
988 : :
989 : 0 : void nrfx_gpiote_trigger_enable(nrfx_gpiote_pin_t pin, bool int_enable)
990 : : {
991 [ # # ]: 0 : NRFX_ASSERT(pin_has_trigger(pin));
992 : :
993 [ # # # # ]: 0 : if (pin_in_use_by_te(pin) && pin_is_input(pin))
994 : 0 : {
995 : 0 : uint8_t ch = pin_te_get(pin);
996 : :
997 : 0 : nrf_gpiote_event_clear(NRF_GPIOTE, nrf_gpiote_in_event_get(ch));
998 : 0 : nrf_gpiote_event_enable(NRF_GPIOTE, ch);
999 [ # # ]: 0 : if (int_enable)
1000 : : {
1001 : 0 : nrf_gpiote_int_enable(NRF_GPIOTE, NRFX_BIT(ch));
1002 : : }
1003 : : }
1004 : : else
1005 : : {
1006 [ # # ]: 0 : NRFX_ASSERT(int_enable);
1007 : 0 : nrf_gpio_cfg_sense_set(pin, get_initial_sense(pin));
1008 : : }
1009 : 0 : }
1010 : :
1011 : 0 : void nrfx_gpiote_trigger_disable(nrfx_gpiote_pin_t pin)
1012 : : {
1013 [ # # # # ]: 0 : if (pin_in_use_by_te(pin) && pin_is_input(pin))
1014 : 0 : {
1015 : 0 : uint8_t ch = pin_te_get(pin);
1016 : :
1017 : 0 : nrf_gpiote_int_disable(NRF_GPIOTE, NRFX_BIT(ch));
1018 : 0 : nrf_gpiote_event_disable(NRF_GPIOTE, ch);
1019 : : }
1020 : : else
1021 : : {
1022 : 0 : nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
1023 : : }
1024 : 0 : }
1025 : :
1026 : 0 : void nrfx_gpiote_in_uninit(nrfx_gpiote_pin_t pin)
1027 : : {
1028 [ # # ]: 0 : NRFX_ASSERT(pin_in_use(pin));
1029 [ # # # # ]: 0 : NRFX_ASSERT(pin_is_input(pin) || pin_has_trigger(pin));
1030 : : nrfx_err_t err;
1031 : : uint8_t ch;
1032 : :
1033 [ # # ]: 0 : if (!pin_in_use(pin))
1034 : : {
1035 : 0 : return;
1036 : : }
1037 : :
1038 [ # # ]: 0 : ch = pin_in_use_by_te(pin) ? pin_te_get(pin) : 0xFF;
1039 : :
1040 [ # # ]: 0 : if (m_cb.pin_flags[pin] & PIN_FLAG_SKIP_CONFIG)
1041 : : {
1042 : 0 : pin_handler_trigger_uninit(pin);
1043 : 0 : m_cb.pin_flags[pin] &= ~PIN_FLAG_SKIP_CONFIG;
1044 : : }
1045 : : else
1046 : : {
1047 : 0 : err = nrfx_gpiote_pin_uninit(pin);
1048 [ # # ]: 0 : NRFX_ASSERT(err == NRFX_SUCCESS);
1049 : : }
1050 : :
1051 [ # # ]: 0 : if (ch != 0xFF)
1052 : : {
1053 : 0 : nrfx_gpiote_channel_free(ch);
1054 : : }
1055 : :
1056 : : (void)err;
1057 : : }
1058 : :
1059 : :
1060 : 0 : bool nrfx_gpiote_in_is_set(nrfx_gpiote_pin_t pin)
1061 : : {
1062 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
1063 : 0 : return nrf_gpio_pin_read(pin) ? true : false;
1064 : : }
1065 : :
1066 : :
1067 : 0 : nrf_gpiote_event_t nrfx_gpiote_in_event_get(nrfx_gpiote_pin_t pin)
1068 : : {
1069 [ # # ]: 0 : NRFX_ASSERT(nrf_gpio_pin_present_check(pin));
1070 [ # # ]: 0 : NRFX_ASSERT(pin_is_input(pin));
1071 [ # # ]: 0 : NRFX_ASSERT(pin_has_trigger(pin));
1072 : :
1073 [ # # ]: 0 : if (pin_in_use_by_te(pin))
1074 : : {
1075 : 0 : return nrf_gpiote_in_event_get((uint8_t)pin_te_get(pin));
1076 : : }
1077 : :
1078 : 0 : return NRF_GPIOTE_EVENT_PORT;
1079 : : }
1080 : :
1081 : :
1082 : 0 : uint32_t nrfx_gpiote_in_event_addr_get(nrfx_gpiote_pin_t pin)
1083 : : {
1084 : 0 : nrf_gpiote_event_t event = nrfx_gpiote_in_event_get(pin);
1085 : 0 : return nrf_gpiote_event_address_get(NRF_GPIOTE, event);
1086 : : }
1087 : :
1088 : 0 : static void call_handler(nrfx_gpiote_pin_t pin, nrfx_gpiote_trigger_t trigger)
1089 : : {
1090 : 0 : nrfx_gpiote_handler_config_t const * handler = channel_handler_get(pin);
1091 : :
1092 [ # # ]: 0 : if (handler)
1093 : : {
1094 : 0 : handler->handler(pin, trigger, handler->p_context);
1095 : : }
1096 [ # # ]: 0 : if (m_cb.global_handler.handler)
1097 : : {
1098 : 0 : m_cb.global_handler.handler(pin, trigger, m_cb.global_handler.p_context);
1099 : : }
1100 : 0 : }
1101 : :
1102 : 0 : static void next_sense_cond_call_handler(nrfx_gpiote_pin_t pin,
1103 : : nrfx_gpiote_trigger_t trigger,
1104 : : nrf_gpio_pin_sense_t sense)
1105 : : {
1106 [ # # ]: 0 : if (is_level(trigger))
1107 : : {
1108 : 0 : call_handler(pin, trigger);
1109 [ # # ]: 0 : if (nrf_gpio_pin_sense_get(pin) == sense)
1110 : : {
1111 : : /* The sensing mechanism needs to be reenabled here so that the PORT event
1112 : : * is generated again for the pin if it stays at the sensed level. */
1113 : 0 : nrf_gpio_cfg_sense_set(pin, NRF_GPIO_PIN_NOSENSE);
1114 : 0 : nrf_gpio_cfg_sense_set(pin, sense);
1115 : : }
1116 : : }
1117 : : else
1118 : : {
1119 : : /* Reconfigure sense to the opposite level, so the internal PINx.DETECT signal
1120 : : * can be deasserted. Therefore PORT event can be generated again,
1121 : : * unless some other PINx.DETECT signal is still active. */
1122 : 0 : nrf_gpio_pin_sense_t next_sense = (sense == NRF_GPIO_PIN_SENSE_HIGH) ?
1123 [ # # ]: 0 : NRF_GPIO_PIN_SENSE_LOW : NRF_GPIO_PIN_SENSE_HIGH;
1124 : :
1125 : 0 : nrf_gpio_cfg_sense_set(pin, next_sense);
1126 : :
1127 : : /* Invoke user handler only if the sensed pin level matches its polarity
1128 : : * configuration. Call handler unconditionally in case of toggle trigger or
1129 : : * level trigger. */
1130 [ # # # # ]: 0 : if ((trigger == NRFX_GPIOTE_TRIGGER_TOGGLE) ||
1131 [ # # # # ]: 0 : (sense == NRF_GPIO_PIN_SENSE_HIGH && trigger == NRFX_GPIOTE_TRIGGER_LOTOHI) ||
1132 [ # # ]: 0 : (sense == NRF_GPIO_PIN_SENSE_LOW && trigger == NRFX_GPIOTE_TRIGGER_HITOLO))
1133 : : {
1134 : 0 : call_handler(pin, trigger);
1135 : : }
1136 : : }
1137 : 0 : }
1138 : :
1139 : : #if defined(NRF_GPIO_LATCH_PRESENT)
1140 : 0 : static bool latch_pending_read_and_check(uint32_t * latch)
1141 : : {
1142 : 0 : nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, latch);
1143 : :
1144 [ # # ]: 0 : for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1145 : : {
1146 [ # # ]: 0 : if (latch[port_idx])
1147 : : {
1148 : : /* If any of the latch bits is still set, it means another edge has been captured
1149 : : * before or during the interrupt processing. Therefore event-processing loop
1150 : : * should be executed again. */
1151 : 0 : return true;
1152 : : }
1153 : : }
1154 : 0 : return false;
1155 : : }
1156 : :
1157 : 0 : static void port_event_handle(void)
1158 : : {
1159 : : uint32_t latch[GPIO_COUNT];
1160 : :
1161 : 0 : nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, latch);
1162 : :
1163 : : do {
1164 [ # # ]: 0 : for (uint32_t i = 0; i < GPIO_COUNT; i++)
1165 : : {
1166 [ # # ]: 0 : while (latch[i])
1167 : : {
1168 : 0 : uint32_t pin = NRF_CTZ(latch[i]);
1169 : :
1170 : : /* Convert to absolute value. */
1171 : 0 : pin += 32 * i;
1172 : : nrf_gpio_pin_sense_t sense;
1173 : 0 : nrfx_gpiote_trigger_t trigger = PIN_FLAG_TRIG_MODE_GET(m_cb.pin_flags[pin]);
1174 : :
1175 : 0 : nrf_bitmask_bit_clear(pin, latch);
1176 : 0 : sense = nrf_gpio_pin_sense_get(pin);
1177 : :
1178 : 0 : next_sense_cond_call_handler(pin, trigger, sense);
1179 : : /* Try to clear LATCH bit corresponding to currently processed pin.
1180 : : * This may not succeed if the pin's state changed during the interrupt processing
1181 : : * and now it matches the new sense configuration. In such case,
1182 : : * the pin will be processed again in another iteration of the outer loop. */
1183 : 0 : nrf_gpio_pin_latch_clear(pin);
1184 : : }
1185 : : }
1186 : :
1187 : : /* All pins have been handled, clear PORT, check latch again in case
1188 : : * something came between deciding to exit and clearing PORT event. */
1189 : 0 : nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
1190 [ # # ]: 0 : } while (latch_pending_read_and_check(latch));
1191 : 0 : }
1192 : :
1193 : : #else
1194 : :
1195 : : static bool input_read_and_check(uint32_t * input, uint32_t * pins_to_check)
1196 : : {
1197 : : bool process_inputs_again;
1198 : : uint32_t new_input[GPIO_COUNT];
1199 : :
1200 : : nrf_gpio_ports_read(0, GPIO_COUNT, new_input);
1201 : :
1202 : : process_inputs_again = false;
1203 : : for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1204 : : {
1205 : : /* Execute XOR to find out which inputs have changed. */
1206 : : uint32_t input_diff = input[port_idx] ^ new_input[port_idx];
1207 : : input[port_idx] = new_input[port_idx];
1208 : : if (input_diff)
1209 : : {
1210 : : /* If any differences among inputs were found, mark those pins
1211 : : * to be processed again. */
1212 : : pins_to_check[port_idx] &= input_diff;
1213 : : process_inputs_again = true;
1214 : : }
1215 : : else
1216 : : {
1217 : : pins_to_check[port_idx] = 0;
1218 : : }
1219 : : }
1220 : : return process_inputs_again;
1221 : : }
1222 : :
1223 : : static void port_event_handle(void)
1224 : : {
1225 : : uint32_t pins_to_check[GPIO_COUNT];
1226 : : uint32_t input[GPIO_COUNT] = {0};
1227 : : uint8_t rel_pin;
1228 : : uint8_t pin;
1229 : : nrfx_gpiote_trigger_t trigger;
1230 : :
1231 : : nrf_gpio_ports_read(0, GPIO_COUNT, input);
1232 : :
1233 : : for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1234 : : {
1235 : : pins_to_check[port_idx] = m_cb.port_pins[port_idx];
1236 : : }
1237 : :
1238 : : do {
1239 : : for (uint32_t i = 0; i < GPIO_COUNT; i++)
1240 : : {
1241 : : while (pins_to_check[i])
1242 : : {
1243 : : nrf_gpio_pin_sense_t sense;
1244 : : bool pin_state;
1245 : :
1246 : : rel_pin = NRF_CTZ(pins_to_check[i]);
1247 : : pins_to_check[i] &= ~NRFX_BIT(rel_pin);
1248 : : /* Absolute */
1249 : : pin = rel_pin + 32 * i;
1250 : :
1251 : : trigger = PIN_FLAG_TRIG_MODE_GET(m_cb.pin_flags[pin]);
1252 : : sense = nrf_gpio_pin_sense_get(pin);
1253 : : pin_state = nrf_bitmask_bit_is_set(pin, input);
1254 : :
1255 : : /* Process pin further only if its state matches its sense level. */
1256 : : if ((pin_state && (sense == NRF_GPIO_PIN_SENSE_HIGH)) ||
1257 : : (!pin_state && (sense == NRF_GPIO_PIN_SENSE_LOW)) )
1258 : : {
1259 : : next_sense_cond_call_handler(pin, trigger, sense);
1260 : : }
1261 : : }
1262 : : }
1263 : :
1264 : : /* All pins used with PORT must be rechecked because it's content and
1265 : : * number of port pins may have changed during handler execution. */
1266 : : for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
1267 : : {
1268 : : pins_to_check[port_idx] = m_cb.port_pins[port_idx];
1269 : : }
1270 : :
1271 : : /* Small trick to continue check if input level is equal to the trigger:
1272 : : * Set input to the opposite level. If input equals trigger level that
1273 : : * it will be set in pins_to_check. */
1274 : : for (uint32_t i = 0; i < GPIO_COUNT; i++)
1275 : : {
1276 : : uint32_t pin_mask = pins_to_check[i];
1277 : :
1278 : : while (pin_mask)
1279 : : {
1280 : : rel_pin = NRF_CTZ(pin_mask);
1281 : : pin_mask &= ~NRFX_BIT(rel_pin);
1282 : : pin = rel_pin + 32 * i;
1283 : : if (nrf_gpio_pin_sense_get(pin) != NRF_GPIO_PIN_NOSENSE)
1284 : : {
1285 : : trigger = PIN_FLAG_TRIG_MODE_GET(m_cb.pin_flags[pin]);
1286 : : if (trigger == NRFX_GPIOTE_TRIGGER_HIGH)
1287 : : {
1288 : : input[i] &= ~NRFX_BIT(rel_pin);
1289 : : }
1290 : : else if (trigger == NRFX_GPIOTE_TRIGGER_LOW)
1291 : : {
1292 : : input[i] |= NRFX_BIT(rel_pin);
1293 : : }
1294 : : }
1295 : : }
1296 : : }
1297 : :
1298 : : nrf_gpiote_event_clear(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT);
1299 : : } while (input_read_and_check(input, pins_to_check));
1300 : : }
1301 : : #endif // defined(NRF_GPIO_LATCH_PRESENT)
1302 : :
1303 : 0 : static void gpiote_evt_handle(uint32_t mask)
1304 : : {
1305 [ # # ]: 0 : while (mask)
1306 : : {
1307 : 0 : uint32_t ch = NRF_CTZ(mask);
1308 : 0 : mask &= ~NRFX_BIT(ch);
1309 : 0 : nrfx_gpiote_pin_t pin = nrf_gpiote_event_pin_get(NRF_GPIOTE, ch);
1310 : 0 : nrf_gpiote_polarity_t polarity = nrf_gpiote_event_polarity_get(NRF_GPIOTE, ch);
1311 : :
1312 : 0 : call_handler(pin, gpiote_polarity_to_trigger(polarity));
1313 : : }
1314 : 0 : }
1315 : :
1316 : 0 : void nrfx_gpiote_irq_handler(void)
1317 : : {
1318 : 0 : uint32_t status = 0;
1319 : : uint32_t i;
1320 : 0 : nrf_gpiote_event_t event = NRF_GPIOTE_EVENT_IN_0;
1321 : 0 : uint32_t mask = (uint32_t)NRF_GPIOTE_INT_IN0_MASK;
1322 : :
1323 : : /* collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
1324 [ # # ]: 0 : for (i = 0; i < GPIOTE_CH_NUM; i++)
1325 : : {
1326 [ # # # # ]: 0 : if (nrf_gpiote_event_check(NRF_GPIOTE, event) &&
1327 : 0 : nrf_gpiote_int_enable_check(NRF_GPIOTE, mask))
1328 : : {
1329 : 0 : nrf_gpiote_event_clear(NRF_GPIOTE, event);
1330 : 0 : status |= mask;
1331 : : }
1332 : 0 : mask <<= 1;
1333 : : /* Incrementing to next event, utilizing the fact that events are grouped together
1334 : : * in ascending order. */
1335 : 0 : event = (nrf_gpiote_event_t)((uint32_t)event + sizeof(uint32_t));
1336 : : }
1337 : :
1338 : : /* handle PORT event */
1339 [ # # ]: 0 : if (nrf_gpiote_event_check(NRF_GPIOTE, NRF_GPIOTE_EVENT_PORT))
1340 : : {
1341 : 0 : port_event_handle();
1342 : : }
1343 : :
1344 : : /* Process pin events. */
1345 : 0 : gpiote_evt_handle(status);
1346 : 0 : }
1347 : :
1348 : : #endif // NRFX_CHECK(NRFX_GPIOTE_ENABLED)
|