Skip to content

Commit 0337967

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 1f169d9 commit 0337967

File tree

2 files changed

+149
-38
lines changed

2 files changed

+149
-38
lines changed

nrfx/drivers/src/nrfx_gpiote.c

Lines changed: 141 additions & 37 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+
uint8_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_GPIOTE_VAR_FEATURE_SUPPORT
209+
uint32_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+
#ifdef NRFX_GPIOTE_VAR_FEATURE_SUPPORT
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

474-
nrfy_gpiote_int_disable(p_instance->p_reg, NRFX_BIT(ch));
525+
#ifdef NRFX_GPIOTE_VAR_FEATURE_SUPPORT
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
530+
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
@@ -677,7 +734,7 @@ static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const *
677734

678735
nrfy_gpiote_event_disable(p_instance->p_reg, ch);
679736
nrfy_gpiote_event_configure(p_instance->p_reg, ch, pin, polarity);
680-
737+
get_cb(p_instance->drv_inst_idx)->ch_pin[ch] = pin;
681738
get_cb(p_instance->drv_inst_idx)->pin_flags[idx] |= (uint16_t)PIN_FLAG_TE_ID(ch);
682739
}
683740
}
@@ -689,6 +746,12 @@ static nrfx_err_t gpiote_input_configure(nrfx_gpiote_t const *
689746
}
690747
else
691748
{
749+
#if NRFX_GPIOTE_VAR_FEATURE_SUPPORT
750+
if (!get_config(p_instance->drv_inst_idx)->port_supported)
751+
{
752+
return NRFX_ERROR_INVALID_PARAM;
753+
}
754+
#endif
692755
nrf_bitmask_bit_set(pin, (uint8_t *)get_cb(p_instance->drv_inst_idx)->port_pins);
693756
}
694757
#endif
@@ -805,7 +868,8 @@ static nrfx_err_t gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrup
805868
nrfx_err_t err_code = NRFX_SUCCESS;
806869

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

810874
if (p_cb->state != NRFX_DRV_STATE_UNINITIALIZED)
811875
{
@@ -822,11 +886,18 @@ static nrfx_err_t gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrup
822886

823887
memset(p_cb->pin_flags, 0, sizeof(p_cb->pin_flags));
824888

889+
#if NRFX_GPIOTE_VAR_FEATURE_SUPPORT
890+
uint32_t int_mask = get_config(p_instance->drv_inst_idx)->port_supported ?
891+
NRF_GPIOTE_INT_PORT_MASK : 0;
892+
#else
893+
uint32_t int_mask = NRF_GPIOTE_INT_PORT_MASK;
894+
#endif
895+
825896
nrfy_gpiote_int_init(p_instance->p_reg,
826-
(uint32_t)NRF_GPIOTE_INT_PORT_MASK,
897+
int_mask,
827898
interrupt_priority,
828899
false,
829-
p_cb->channels_number);
900+
get_config(p_instance->drv_inst_idx)->channels_number);
830901

831902
p_cb->state = NRFX_DRV_STATE_INITIALIZED;
832903
p_cb->available_evt_handlers = NRFX_BIT_MASK(NRFX_GPIOTE_CONFIG_NUM_OF_EVT_HANDLERS);
@@ -875,14 +946,31 @@ static void gpiote_uninit(nrfx_gpiote_t const * p_instance)
875946

876947
static nrfx_err_t pin_channel_free(nrfx_gpiote_t const * p_instance, uint8_t channel)
877948
{
878-
return nrfx_flag32_free(&get_cb(p_instance->drv_inst_idx)->available_channels_mask, channel);
949+
#if NRFX_GPIOTE_VAR_FEATURE_SUPPORT
950+
const gpiote_config_t * p_config = get_config(p_instance->drv_inst_idx);
951+
952+
if (!p_config->dynamic_chan_supported)
953+
{
954+
return NRFX_ERROR_NOT_SUPPORTED;
955+
}
956+
#endif
957+
return nrfx_flag32_free(&available_channels_mask[p_instance->drv_inst_idx], channel);
879958
}
880959

881960
static nrfx_err_t pin_channel_alloc(nrfx_gpiote_t const * p_instance, uint8_t * p_channel)
882961
{
883962
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);
963+
(int)&available_channels_mask[p_instance->drv_inst_idx]);
964+
#if NRFX_GPIOTE_VAR_FEATURE_SUPPORT
965+
const gpiote_config_t * p_config = get_config(p_instance->drv_inst_idx);
966+
967+
if (!p_config->dynamic_chan_supported)
968+
{
969+
return NRFX_ERROR_NOT_SUPPORTED;
970+
}
971+
#endif
972+
973+
return nrfx_flag32_alloc(&available_channels_mask[p_instance->drv_inst_idx], p_channel);
886974
}
887975

888976
static void pin_out_set(nrfx_gpiote_t const * p_instance, nrfx_gpiote_pin_t pin)
@@ -1017,11 +1105,6 @@ static void pin_trigger_enable(nrfx_gpiote_t const * p_instance,
10171105
{
10181106
NRFX_ASSERT(pin_has_trigger(p_instance, pin));
10191107

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-
10251108
if (pin_in_use_by_te(p_instance, pin) && pin_is_input(p_instance, pin))
10261109
{
10271110
uint8_t ch = pin_te_get(p_instance, pin);
@@ -1030,11 +1113,22 @@ static void pin_trigger_enable(nrfx_gpiote_t const * p_instance,
10301113
nrfy_gpiote_event_enable(p_instance->p_reg, ch);
10311114
if (int_enable)
10321115
{
1116+
#if NRFX_GPIOTE_VAR_FEATURE_SUPPORT
1117+
nrf_gpiote_int_group_enable(p_instance->p_reg,
1118+
get_config(p_instance->drv_inst_idx)->group_idx,
1119+
NRFX_BIT(ch));
1120+
#else
10331121
nrfy_gpiote_int_enable(p_instance->p_reg, NRFX_BIT(ch));
1122+
#endif
10341123
}
10351124
}
10361125
else
10371126
{
1127+
if (!nrfy_gpiote_int_enable_check(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK))
1128+
{
1129+
nrfy_gpiote_int_enable(p_instance->p_reg, (uint32_t)NRF_GPIOTE_INT_PORT_MASK);
1130+
}
1131+
10381132
NRFX_ASSERT(int_enable);
10391133
nrfy_gpio_cfg_sense_set(pin, get_initial_sense(p_instance, pin));
10401134
}
@@ -1079,9 +1173,7 @@ nrfx_err_t nrfx_gpiote_channel_get(nrfx_gpiote_t const * p_instance,
10791173

10801174
uint32_t nrfx_gpiote_channels_number_get(nrfx_gpiote_t const * p_instance)
10811175
{
1082-
gpiote_control_block_t * p_cb = get_cb(p_instance->drv_inst_idx);
1083-
1084-
return p_cb->channels_number;
1176+
return get_config(p_instance->drv_inst_idx)->channels_number;
10851177
}
10861178

10871179
nrfx_err_t nrfx_gpiote_init(nrfx_gpiote_t const * p_instance, uint8_t interrupt_priority)
@@ -1479,16 +1571,17 @@ static bool latch_pending_read_and_check(uint32_t * latch, uint32_t available_gp
14791571
return false;
14801572
}
14811573

1482-
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1574+
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb,
1575+
const gpiote_config_t * p_config)
14831576
{
14841577
uint32_t latch[GPIO_COUNT] = {0};
14851578

1486-
latch_pending_read_and_check(latch, p_cb->available_gpio_ports);
1579+
latch_pending_read_and_check(latch, p_config->available_gpio_ports);
14871580

14881581
do {
14891582
for (uint32_t i = 0; i < GPIO_COUNT; i++)
14901583
{
1491-
if (nrf_bitmask_bit_is_set(port_index[i], &p_cb->available_gpio_ports))
1584+
if (nrf_bitmask_bit_is_set(port_index[i], &p_config->available_gpio_ports))
14921585
{
14931586
while (latch[i])
14941587
{
@@ -1516,7 +1609,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
15161609
/* All pins have been handled, clear PORT, check latch again in case
15171610
* something came between deciding to exit and clearing PORT event. */
15181611
(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));
1612+
} while (latch_pending_read_and_check(latch, p_config->available_gpio_ports));
15201613
}
15211614

15221615
#else
@@ -1554,7 +1647,8 @@ static bool input_read_and_check(uint32_t * input,
15541647
return process_inputs_again;
15551648
}
15561649

1557-
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
1650+
static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb,
1651+
const gpiote_config_t * p_config)
15581652
{
15591653
uint32_t pins_to_check[GPIO_COUNT] = {0};
15601654
uint32_t input[GPIO_COUNT] = {0};
@@ -1564,7 +1658,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
15641658

15651659
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
15661660
{
1567-
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_cb->available_gpio_ports))
1661+
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_config->available_gpio_ports))
15681662
{
15691663
nrfy_gpio_ports_read(port_idx, 1, &input[port_idx]);
15701664
pins_to_check[port_idx] = p_cb->port_pins[port_idx];
@@ -1599,7 +1693,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
15991693

16001694
for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
16011695
{
1602-
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_cb->available_gpio_ports))
1696+
if (nrf_bitmask_bit_is_set(port_index[port_idx], &p_config->available_gpio_ports))
16031697
{
16041698
/* All pins used with PORT must be rechecked because it's content and
16051699
* number of port pins may have changed during handler execution. */
@@ -1633,7 +1727,7 @@ static void port_event_handle(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t
16331727
}
16341728

16351729
(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));
1730+
} while (input_read_and_check(input, pins_to_check, p_config->available_gpio_ports));
16371731
}
16381732
#endif // defined(NRF_GPIO_LATCH_PRESENT)
16391733

@@ -1645,7 +1739,7 @@ static void gpiote_evt_handle(NRF_GPIOTE_Type * p_gpiote,
16451739
{
16461740
uint32_t ch = NRF_CTZ(mask);
16471741
mask &= ~NRFX_BIT(ch);
1648-
nrfx_gpiote_pin_t pin = nrfy_gpiote_event_pin_get(p_gpiote, ch);
1742+
nrfx_gpiote_pin_t pin = p_cb->ch_pin[ch];
16491743
nrf_gpiote_polarity_t polarity = nrfy_gpiote_event_polarity_get(p_gpiote, ch);
16501744

16511745
call_handler(p_cb, pin, gpiote_polarity_to_trigger(polarity));
@@ -1654,17 +1748,27 @@ static void gpiote_evt_handle(NRF_GPIOTE_Type * p_gpiote,
16541748

16551749
static void irq_handler(NRF_GPIOTE_Type * p_gpiote, gpiote_control_block_t * p_cb)
16561750
{
1751+
uint32_t instance_idx = ((uintptr_t)p_cb - (uintptr_t)m_cb) / sizeof(gpiote_control_block_t);
1752+
const gpiote_config_t * p_config = get_config(instance_idx);
16571753
/* 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);
1754+
#if NRFX_GPIOTE_VAR_FEATURE_SUPPORT
1755+
uint32_t enabled_in_events = nrf_gpiote_int_group_enable_check(p_gpiote,
1756+
p_config->group_idx,
1757+
NRF_GPIOTE_INT_IN_MASK);
1758+
uint32_t enabled_events = enabled_in_events |
1759+
(p_config->port_supported ? NRF_GPIOTE_INT_PORT_MASK : 0);
1760+
#else
1761+
uint32_t enabled_events = nrf_gpiote_int_enable_check(p_gpiote, NRF_GPIOTE_INT_IN_MASK) |
1762+
NRF_GPIOTE_INT_PORT_MASK;
1763+
#endif
16591764
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);
1765+
enabled_events,
1766+
p_config->channels_number);
16631767

16641768
/* Handle PORT event. */
16651769
if (evt_mask & (uint32_t)NRF_GPIOTE_INT_PORT_MASK)
16661770
{
1667-
port_event_handle(p_gpiote, p_cb);
1771+
port_event_handle(p_gpiote, p_cb, p_config);
16681772
evt_mask &= ~(uint32_t)NRF_GPIOTE_INT_PORT_MASK;
16691773
}
16701774

nrfx/haly/nrfy_gpiote.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ NRFY_STATIC_INLINE void nrfy_gpiote_int_init(NRF_GPIOTE_Type * p_reg,
9595
#if defined(NRF_GPIOTE_IRQn_EXT)
9696
IRQn_Type irqn = NRF_GPIOTE_IRQn_EXT;
9797
#elif defined(NRF_GPIOTE130)
98+
#if defined(NRF_GPIOTE0)
99+
IRQn_Type irqn = (p_reg == NRF_GPIOTE0) ? GPIOTE_0_IRQn : GPIOTE130_IRQn;
100+
#else
98101
IRQn_Type irqn = GPIOTE130_IRQn;
102+
#endif
99103
#elif defined(LUMOS_XXAA) && defined(NRF_APPLICATION) && !defined(NRF_TRUSTZONE_NONSECURE)
100104
IRQn_Type irqn = (IRQn_Type)(nrfx_get_irq_number(p_reg) + 1);
101105
#else
@@ -412,7 +416,10 @@ NRFY_STATIC_INLINE uint32_t __nrfy_internal_gpiote_events_process(NRF_GPIOTE_Typ
412416
&event_mask);
413417
}
414418

415-
(void)__nrfy_internal_gpiote_event_handle(p_reg, mask, NRF_GPIOTE_EVENT_PORT, &event_mask);
419+
if (mask & NRF_GPIOTE_INT_PORT_MASK)
420+
{
421+
(void)__nrfy_internal_gpiote_event_handle(p_reg, mask, NRF_GPIOTE_EVENT_PORT, &event_mask);
422+
}
416423

417424
return event_mask;
418425
}

0 commit comments

Comments
 (0)