Skip to content

Commit f9ce0c8

Browse files
committed
nrfx: drivers: gpiote: Add support for GPIOTE0 on cpurad
GPIOTE0 on radio core is special in a way that: - PORT event is not supported - Channel id is fixed to pin - Various interrupt register that shall be used (index 0 for GPIOTE0 and index 2 for GPIOTE130) Signed-off-by: Krzysztof Chruściński <[email protected]>
1 parent 9587b1d commit f9ce0c8

File tree

2 files changed

+155
-45
lines changed

2 files changed

+155
-45
lines changed

nrfx/drivers/src/nrfx_gpiote.c

Lines changed: 149 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -190,15 +190,28 @@ typedef struct
190190
/* Mask for tracking event handler entries allocation. */
191191
nrfx_atomic_t available_evt_handlers;
192192

193-
/* Mask of available ports for GPIOTE instance. */
194-
uint32_t available_gpio_ports;
195-
193+
uint16_t ch_pin[GPIOTE_CH_NUM];
196194
#if !defined(NRF_GPIO_LATCH_PRESENT)
197195
uint32_t port_pins[GPIO_COUNT];
198196
#endif
199197
nrfx_drv_state_t state;
200198
} gpiote_control_block_t;
201199

200+
typedef struct
201+
{
202+
/* Number of GPIOTE channels. */
203+
uint32_t channels_number;
204+
205+
/* Mask of available ports for GPIOTE instance. */
206+
uint32_t available_gpio_ports;
207+
208+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
209+
uint8_t group_idx;
210+
bool port_supported;
211+
bool dynamic_chan_supported;
212+
#endif
213+
} gpiote_config_t;
214+
202215
#if !defined(__NRFX_DOXYGEN__)
203216
#if (defined(NRF_GPIOTE) || defined(NRF_GPIOTE0)) && !defined(NRFX_GPIOTE0_CHANNELS_USED)
204217
/* Bitmask that defines GPIOTE0 channels that are reserved for use outside of the nrfx library. */
@@ -231,16 +244,34 @@ typedef struct
231244
#endif
232245
#endif // !defined(__NRFX_DOXYGEN__)
233246

234-
#define _NRFX_GPIOTE_CB_INITIALIZER(periph_name, prefix, idx, _) \
247+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
248+
#define GPIOTE_VAR_INIT(prefix, idx) \
249+
.group_idx = idx == 0 ? 0 : NRF_GPIOTE_IRQ_GROUP, \
250+
.port_supported = idx != 0, \
251+
.dynamic_chan_supported = idx != 0,
252+
#else
253+
#define GPIOTE_VAR_INIT(prefix, idx)
254+
#endif
255+
256+
#define _NRFX_GPIOTE_CONFIG_INITIALIZER(periph_name, prefix, idx, _) \
235257
[NRFX_CONCAT(NRFX_, periph_name, idx, _INST_IDX)] = { \
236258
.channels_number = NRFX_CONCAT_3(periph_name, idx, _CH_NUM), \
237-
.available_channels_mask = (nrfx_atomic_t)NRFX_GPIOTE_APP_CHANNELS_MASK(idx), \
238259
.available_gpio_ports = NRFX_CONCAT_3(periph_name, idx, _AVAILABLE_GPIO_PORTS), \
260+
GPIOTE_VAR_INIT(prefix, idx) \
239261
},
240262

241-
static gpiote_control_block_t m_cb[NRFX_GPIOTE_ENABLED_COUNT] = {
242-
NRFX_FOREACH_ENABLED(GPIOTE, _NRFX_GPIOTE_CB_INITIALIZER, (), ())
263+
#define _NRFX_GPIOTE_CHANNEL_INITIALIZER(periph_name, prefix, idx, _) \
264+
[NRFX_CONCAT(NRFX_, periph_name, idx, _INST_IDX)] = \
265+
(nrfx_atomic_t)NRFX_GPIOTE_APP_CHANNELS_MASK(idx),
266+
267+
/* Mask for tracking GPIOTE channel allocation. */
268+
static nrfx_atomic_t available_channels_mask[NRFX_GPIOTE_ENABLED_COUNT] = {
269+
NRFX_FOREACH_ENABLED(GPIOTE, _NRFX_GPIOTE_CHANNEL_INITIALIZER, (), ())
243270
};
271+
static const gpiote_config_t m_config[NRFX_GPIOTE_ENABLED_COUNT] = {
272+
NRFX_FOREACH_ENABLED(GPIOTE, _NRFX_GPIOTE_CONFIG_INITIALIZER, (), ())
273+
};
274+
static gpiote_control_block_t m_cb[NRFX_GPIOTE_ENABLED_COUNT];
244275

245276
#if defined(NRF_GPIO_LATCH_PRESENT) || (!FULL_PORTS_PRESENT)
246277
static const uint8_t ports[GPIO_COUNT] = GPIO_PORT_NUM_LIST;
@@ -301,6 +332,26 @@ static gpiote_control_block_t * get_cb(uint32_t idx)
301332
}
302333
}
303334

335+
/** @brief Function for getting instance configuration structure.
336+
*
337+
* Function is optimized for case when there is only one GPIOTE instance.
338+
*
339+
* @param[in] idx Instance index.
340+
*
341+
* @return Configure structure.
342+
*/
343+
static const gpiote_config_t * get_config(uint32_t idx)
344+
{
345+
if (NRFX_GPIOTE_ENABLED_COUNT == 1)
346+
{
347+
return &m_config[0];
348+
}
349+
else
350+
{
351+
return &m_config[idx];
352+
}
353+
}
354+
304355
/** @brief Checks if pin is in use by a given GPIOTE instance.
305356
*
306357
* @param[in] p_instance Pointer to the driver instance structure.
@@ -471,7 +522,13 @@ static void pin_trigger_disable(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pi
471522
{
472523
uint8_t ch = pin_te_get(p_instance, pin);
473524

525+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
526+
nrf_gpiote_int_group_disable(p_instance->p_reg,
527+
get_config(p_instance->drv_inst_idx)->group_idx,
528+
NRFX_BIT(ch));
529+
#else
474530
nrfy_gpiote_int_disable(p_instance->p_reg, NRFX_BIT(ch));
531+
#endif
475532
nrfy_gpiote_event_disable(p_instance->p_reg, ch);
476533
}
477534
else
@@ -622,6 +679,7 @@ static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const *
622679
{
623680
nrfx_err_t err;
624681
uint8_t idx = get_pin_idx(pin);
682+
gpiote_control_block_t *cb = get_cb(p_instance->drv_inst_idx);
625683

626684
if (p_config->p_pull_config)
627685
{
@@ -635,8 +693,8 @@ static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const *
635693

636694
nrfy_gpio_reconfigure(pin, &dir, &input_connect, p_config->p_pull_config, NULL, NULL);
637695

638-
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &= (uint16_t)~PIN_FLAG_OUTPUT;
639-
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= PIN_FLAG_IN_USE;
696+
cb->pin_flags[idx] &= (uint16_t)~PIN_FLAG_OUTPUT;
697+
cb->pin_flags[idx] |= PIN_FLAG_IN_USE;
640698
}
641699

642700
if (p_config->p_trigger_config)
@@ -653,7 +711,7 @@ static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const *
653711
}
654712
else
655713
{
656-
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &=
714+
cb->pin_flags[idx] &=
657715
(uint16_t) ~(PIN_TE_ID_MASK | PIN_FLAG_TE_USED);
658716
if (use_evt) {
659717
bool edge = trigger <= NRFX_GPIOTE_TRIGGER_TOGGLE;
@@ -677,23 +735,29 @@ static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const *
677735

678736
nrfy_gpiote_event_disable(p_instance->p_reg, ch);
679737
nrfy_gpiote_event_configure(p_instance->p_reg, ch, pin, polarity);
680-
681-
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= (uint16_t)PIN_FLAG_TE_ID(ch);
738+
cb->ch_pin[ch] = (uint16_t)pin;
739+
cb->pin_flags[idx] |= (uint16_t)PIN_FLAG_TE_ID(ch);
682740
}
683741
}
684742
}
685743
#if !defined(NRF_GPIO_LATCH_PRESENT)
686744
if (use_evt || trigger == NRFX_GPIOTE_TRIGGER_NONE)
687745
{
688-
nrf_bitmask_bit_clear(pin, (uint8_t *)get_cb(p_instance->drv_inst_idx)->port_pins);
746+
nrf_bitmask_bit_clear(pin, (uint8_t *)cb->port_pins);
689747
}
690748
else
691749
{
692-
nrf_bitmask_bit_set(pin, (uint8_t *)get_cb(p_instance->drv_inst_idx)->port_pins);
750+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
751+
if (!get_config(p_instance->drv_inst_idx)->port_supported)
752+
{
753+
return NRFX_ERROR_INVALID_PARAM;
754+
}
755+
#endif
756+
nrf_bitmask_bit_set(pin, (uint8_t *)cb->port_pins);
693757
}
694758
#endif
695-
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] &= (uint16_t)~PIN_FLAG_TRIG_MODE_MASK;
696-
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= (uint16_t)PIN_FLAG_TRIG_MODE_SET(trigger);
759+
cb->pin_flags[idx] &= (uint16_t)~PIN_FLAG_TRIG_MODE_MASK;
760+
cb->pin_flags[idx] |= (uint16_t)PIN_FLAG_TRIG_MODE_SET(trigger);
697761
}
698762

699763
if (p_config->p_handler_config)
@@ -805,7 +869,8 @@ static nrfx_err_t gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrup
805869
nrfx_err_t err_code = NRFX_SUCCESS;
806870

807871
NRFX_LOG_INFO("channels_number: %d, available_channels_mask: 0x%x",
808-
(int)p_cb->channels_number, (int)p_cb->available_channels_mask);
872+
(int)get_config(p_instance->drv_inst_idx)->channels_number,
873+
(int)available_channels_mask[p_instance->drv_inst_idx]);
809874

810875
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
811876
{
@@ -822,11 +887,18 @@ static nrfx_err_t gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrup
822887

823888
memset(p_cb->pin_flags, 0, sizeof(p_cb->pin_flags));
824889

890+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
891+
uint32_t int_mask = get_config(p_instance->drv_inst_idx)->port_supported ?
892+
NRF_GPIOTE_INT_PORT_MASK : 0;
893+
#else
894+
uint32_t int_mask = NRF_GPIOTE_INT_PORT_MASK;
895+
#endif
896+
825897
nrfy_gpiote_int_init(p_instance->p_reg,
826-
(uint32_t)NRF_GPIOTE_INT_PORT_MASK,
898+
int_mask,
827899
interrupt_priority,
828900
false,
829-
p_cb->channels_number);
901+
get_config(p_instance->drv_inst_idx)->channels_number);
830902

831903
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
832904
p_cb->available_evt_handlers = NRFX_BIT_MASK(NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS);
@@ -875,14 +947,31 @@ static void gpiote_uninit(nrfx_gpiote_t const * p_instance)
875947

876948
static nrfx_err_t pin_channel_free(nrfx_gpiote_t const * p_instance, uint8_t channel)
877949
{
878-
return nrfx_flag32_free(&get_cb(p_instance->drv_inst_idx)->available_channels_mask, channel);
950+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
951+
const gpiote_config_t * p_config = get_config(p_instance->drv_inst_idx);
952+
953+
if (!p_config->dynamic_chan_supported)
954+
{
955+
return NRFX_ERROR_NOT_SUPPORTED;
956+
}
957+
#endif
958+
return nrfx_flag32_free(&available_channels_mask[p_instance->drv_inst_idx], channel);
879959
}
880960

881961
static nrfx_err_t pin_channel_alloc(nrfx_gpiote_t const * p_instance, uint8_t * p_channel)
882962
{
883963
NRFX_LOG_INFO("available_channels_mask = %d",
884-
(int)get_cb(p_instance->drv_inst_idx)->available_channels_mask);
885-
return nrfx_flag32_alloc(&get_cb(p_instance->drv_inst_idx)->available_channels_mask, p_channel);
964+
(int)&available_channels_mask[p_instance->drv_inst_idx]);
965+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
966+
const gpiote_config_t * p_config = get_config(p_instance->drv_inst_idx);
967+
968+
if (!p_config->dynamic_chan_supported)
969+
{
970+
return NRFX_ERROR_NOT_SUPPORTED;
971+
}
972+
#endif
973+
974+
return nrfx_flag32_alloc(&available_channels_mask[p_instance->drv_inst_idx], p_channel);
886975
}
887976

888977
static void pin_out_set(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
@@ -1017,11 +1106,6 @@ static void pin_trigger_enable(nrfx_gpiote_t const * p_instance,
10171106
{
10181107
NRFX_ASSERT(pin_has_trigger(p_instance, pin));
10191108

1020-
if (!nrfy_gpiote_int_enable_check(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK))
1021-
{
1022-
nrfy_gpiote_int_enable(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK);
1023-
}
1024-
10251109
if (pin_in_use_by_te(p_instance, pin) && pin_is_input(p_instance, pin))
10261110
{
10271111
uint8_t ch = pin_te_get(p_instance, pin);
@@ -1030,11 +1114,22 @@ static void pin_trigger_enable(nrfx_gpiote_t const * p_instance,
10301114
nrfy_gpiote_event_enable(p_instance->p_reg, ch);
10311115
if (int_enable)
10321116
{
1117+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
1118+
nrf_gpiote_int_group_enable(p_instance->p_reg,
1119+
get_config(p_instance->drv_inst_idx)->group_idx,
1120+
NRFX_BIT(ch));
1121+
#else
10331122
nrfy_gpiote_int_enable(p_instance->p_reg, NRFX_BIT(ch));
1123+
#endif
10341124
}
10351125
}
10361126
else
10371127
{
1128+
if (!nrfy_gpiote_int_enable_check(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK))
1129+
{
1130+
nrfy_gpiote_int_enable(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK);
1131+
}
1132+
10381133
NRFX_ASSERT(int_enable);
10391134
nrfy_gpio_cfg_sense_set(pin, get_initial_sense(p_instance, pin));
10401135
}
@@ -1079,9 +1174,7 @@ nrfx_err_t nrfx_gpiote_channel_get(nrfx_gpiote_t const * p_instance,
10791174

10801175
uint32_t nrfx_gpiote_channels_number_get(nrfx_gpiote_t const * p_instance)
10811176
{
1082-
gpiote_control_block_t * p_cb = get_cb(p_instance->drv_inst_idx);
1083-
1084-
return p_cb->channels_number;
1177+
return get_config(p_instance->drv_inst_idx)->channels_number;
10851178
}
10861179

10871180
nrfx_err_t nrfx_gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrupt_priority)
@@ -1479,16 +1572,17 @@ static bool latch_pending_read_and_check(uint32_t * latch, uint32_t available_gp
14791572
return false;
14801573
}
14811574

1482-
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1575+
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb,
1576+
const gpiote_config_t * p_config)
14831577
{
14841578
uint32_t latch[GPIO_COUNT] = {0};
14851579

1486-
latch_pending_read_and_check(latch, p_cb->available_gpio_ports);
1580+
latch_pending_read_and_check(latch, p_config->available_gpio_ports);
14871581

14881582
do {
14891583
for (uint32_t i = 0; i < GPIO_COUNT; i++)
14901584
{
1491-
if (nrf_bitmask_bit_is_set(port_index[i], &p_cb->available_gpio_ports))
1585+
if (nrf_bitmask_bit_is_set(port_index[i], &p_config->available_gpio_ports))
14921586
{
14931587
while (latch[i])
14941588
{
@@ -1516,7 +1610,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
15161610
/* All pins have been handled, clear PORT, check latch again in case
15171611
* something came between deciding to exit and clearing PORT event. */
15181612
(void)nrfy_gpiote_events_process(p_gpiote, (uint32_t)NRF_GPIOTE_INT_PORT_MASK, 0);
1519-
} while (latch_pending_read_and_check(latch, p_cb->available_gpio_ports));
1613+
} while (latch_pending_read_and_check(latch, p_config->available_gpio_ports));
15201614
}
15211615

15221616
#else
@@ -1554,7 +1648,8 @@ static bool input_read_and_check(uint32_t * input,
15541648
return process_inputs_again;
15551649
}
15561650

1557-
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1651+
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb,
1652+
const gpiote_config_t * p_config)
15581653
{
15591654
uint32_t pins_to_check[GPIO_COUNT] = {0};
15601655
uint32_t input[GPIO_COUNT] = {0};
@@ -1564,7 +1659,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
15641659

15651660
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
15661661
{
1567-
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_cb->available_gpio_ports))
1662+
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_config->available_gpio_ports))
15681663
{
15691664
nrfy_gpio_ports_read(port_idx, 1, &input[port_idx]);
15701665
pins_to_check[port_idx] = p_cb->port_pins[port_idx];
@@ -1599,7 +1694,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
15991694

16001695
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
16011696
{
1602-
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_cb->available_gpio_ports))
1697+
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_config->available_gpio_ports))
16031698
{
16041699
/* All pins used with PORT must be rechecked because it's content and
16051700
* number of port pins may have changed during handler execution. */
@@ -1633,7 +1728,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
16331728
}
16341729

16351730
(void)nrfy_gpiote_events_process(p_gpiote, (uint32_t)NRF_GPIOTE_INT_PORT_MASK, 0);
1636-
} while (input_read_and_check(input, pins_to_check, p_cb->available_gpio_ports));
1731+
} while (input_read_and_check(input, pins_to_check, p_config->available_gpio_ports));
16371732
}
16381733
#endif // defined(NRF_GPIO_LATCH_PRESENT)
16391734

@@ -1645,7 +1740,7 @@ static void gpiote_evt_handle(NRF_GPIOTE_Type * p_gpiote,
16451740
{
16461741
uint32_t ch = NRF_CTZ(mask);
16471742
mask &= ~NRFX_BIT(ch);
1648-
nrfx_gpiote_pin_t pin = nrfy_gpiote_event_pin_get(p_gpiote, ch);
1743+
nrfx_gpiote_pin_t pin = p_cb->ch_pin[ch];
16491744
nrf_gpiote_polarity_t polarity = nrfy_gpiote_event_polarity_get(p_gpiote, ch);
16501745

16511746
call_handler(p_cb, pin, gpiote_polarity_to_trigger(polarity));
@@ -1654,17 +1749,27 @@ static void gpiote_evt_handle(NRF_GPIOTE_Type * p_gpiote,
16541749

16551750
static void irq_handler(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
16561751
{
1752+
uint32_t instance_idx = ((uintptr_t)p_cb - (uintptr_t)m_cb) / sizeof(gpiote_control_block_t);
1753+
const gpiote_config_t * p_config = get_config(instance_idx);
16571754
/* Collect status of all GPIOTE pin events. Processing is done once all are collected and cleared.*/
1658-
uint32_t enabled_in_events = nrf_gpiote_int_enable_check(p_gpiote, NRF_GPIOTE_INT_IN_MASK);
1755+
#if NRFX_CHECK(NRFX_GPIOTE_CONFIG_NONUNIFORM_INSTANCES)
1756+
uint32_t enabled_in_events = nrf_gpiote_int_group_enable_check(p_gpiote,
1757+
p_config->group_idx,
1758+
NRF_GPIOTE_INT_IN_MASK);
1759+
uint32_t enabled_events = enabled_in_events |
1760+
(p_config->port_supported ? NRF_GPIOTE_INT_PORT_MASK : 0);
1761+
#else
1762+
uint32_t enabled_events = nrf_gpiote_int_enable_check(p_gpiote, NRF_GPIOTE_INT_IN_MASK) |
1763+
NRF_GPIOTE_INT_PORT_MASK;
1764+
#endif
16591765
uint32_t evt_mask = nrfy_gpiote_events_process(p_gpiote,
1660-
enabled_in_events |
1661-
(uint32_t)NRF_GPIOTE_INT_PORT_MASK,
1662-
p_cb->channels_number);
1766+
enabled_events,
1767+
p_config->channels_number);
16631768

16641769
/* Handle PORT event. */
16651770
if (evt_mask & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
16661771
{
1667-
port_event_handle(p_gpiote, p_cb);
1772+
port_event_handle(p_gpiote, p_cb, p_config);
16681773
evt_mask &= ~(uint32_t)NRF_GPIOTE_INT_PORT_MASK;
16691774
}
16701775

0 commit comments

Comments
 (0)