1 /*
2 * Copyright (c) 2019 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8
9 #include <nrfx_gpiote.h>
10 #include <helpers/nrfx_gppi.h>
11 #if defined(DPPI_PRESENT)
12 #include <nrfx_dppi.h>
13 #else
14 #include <nrfx_ppi.h>
15 #endif
16
17 #include <zephyr/logging/log.h>
18 #include <zephyr/irq.h>
19 LOG_MODULE_REGISTER(nrfx_sample, LOG_LEVEL_INF);
20
21 #define INPUT_PIN DT_GPIO_PIN(DT_ALIAS(sw0), gpios)
22 #define OUTPUT_PIN DT_GPIO_PIN(DT_ALIAS(led0), gpios)
23
button_handler(nrfx_gpiote_pin_t pin,nrfx_gpiote_trigger_t trigger,void * context)24 static void button_handler(nrfx_gpiote_pin_t pin,
25 nrfx_gpiote_trigger_t trigger,
26 void *context)
27 {
28 LOG_INF("GPIO input event callback");
29 }
30
main(void)31 int main(void)
32 {
33 LOG_INF("nrfx_gpiote sample on %s", CONFIG_BOARD);
34
35 nrfx_err_t err;
36 uint8_t in_channel, out_channel;
37 uint8_t ppi_channel;
38
39 /* Connect GPIOTE_0 IRQ to nrfx_gpiote_irq_handler */
40 IRQ_CONNECT(DT_IRQN(DT_NODELABEL(gpiote)),
41 DT_IRQ(DT_NODELABEL(gpiote), priority),
42 nrfx_isr, nrfx_gpiote_irq_handler, 0);
43
44 /* Initialize GPIOTE (the interrupt priority passed as the parameter
45 * here is ignored, see nrfx_glue.h).
46 */
47 err = nrfx_gpiote_init(0);
48 if (err != NRFX_SUCCESS) {
49 LOG_ERR("nrfx_gpiote_init error: 0x%08X", err);
50 return 0;
51 }
52
53 err = nrfx_gpiote_channel_alloc(&in_channel);
54 if (err != NRFX_SUCCESS) {
55 LOG_ERR("Failed to allocate in_channel, error: 0x%08X", err);
56 return 0;
57 }
58
59 err = nrfx_gpiote_channel_alloc(&out_channel);
60 if (err != NRFX_SUCCESS) {
61 LOG_ERR("Failed to allocate out_channel, error: 0x%08X", err);
62 return 0;
63 }
64
65 /* Initialize input pin to generate event on high to low transition
66 * (falling edge) and call button_handler()
67 */
68 static const nrfx_gpiote_input_config_t input_config = {
69 .pull = NRF_GPIO_PIN_PULLUP,
70 };
71 const nrfx_gpiote_trigger_config_t trigger_config = {
72 .trigger = NRFX_GPIOTE_TRIGGER_HITOLO,
73 .p_in_channel = &in_channel,
74 };
75 static const nrfx_gpiote_handler_config_t handler_config = {
76 .handler = button_handler,
77 };
78 err = nrfx_gpiote_input_configure(INPUT_PIN,
79 &input_config,
80 &trigger_config,
81 &handler_config);
82 if (err != NRFX_SUCCESS) {
83 LOG_ERR("nrfx_gpiote_input_configure error: 0x%08X", err);
84 return 0;
85 }
86
87 /* Initialize output pin. SET task will turn the LED on,
88 * CLR will turn it off and OUT will toggle it.
89 */
90 static const nrfx_gpiote_output_config_t output_config = {
91 .drive = NRF_GPIO_PIN_S0S1,
92 .input_connect = NRF_GPIO_PIN_INPUT_DISCONNECT,
93 .pull = NRF_GPIO_PIN_NOPULL,
94 };
95 const nrfx_gpiote_task_config_t task_config = {
96 .task_ch = out_channel,
97 .polarity = NRF_GPIOTE_POLARITY_TOGGLE,
98 .init_val = 1,
99 };
100 err = nrfx_gpiote_output_configure(OUTPUT_PIN,
101 &output_config,
102 &task_config);
103 if (err != NRFX_SUCCESS) {
104 LOG_ERR("nrfx_gpiote_output_configure error: 0x%08X", err);
105 return 0;
106 }
107
108 nrfx_gpiote_trigger_enable(INPUT_PIN, true);
109 nrfx_gpiote_out_task_enable(OUTPUT_PIN);
110
111 LOG_INF("nrfx_gpiote initialized");
112
113 /* Allocate a (D)PPI channel. */
114 err = nrfx_gppi_channel_alloc(&ppi_channel);
115 if (err != NRFX_SUCCESS) {
116 LOG_ERR("nrfx_gppi_channel_alloc error: 0x%08X", err);
117 return 0;
118 }
119
120 /* Configure endpoints of the channel so that the input pin event is
121 * connected with the output pin OUT task. This means that each time
122 * the button is pressed, the LED pin will be toggled.
123 */
124 nrfx_gppi_channel_endpoints_setup(ppi_channel,
125 nrfx_gpiote_in_event_address_get(INPUT_PIN),
126 nrfx_gpiote_out_task_address_get(OUTPUT_PIN));
127
128 /* Enable the channel. */
129 nrfx_gppi_channels_enable(BIT(ppi_channel));
130
131 LOG_INF("(D)PPI configured, leaving main()");
132 return 0;
133 }
134