mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2025-01-18 12:52:44 +01:00
Merge pull request #10828 from aabadie/pr/cpu/nrf5x_gpiote_multi_channel
cpu/nrf5x: handle multiple exti pins in gpio driver
This commit is contained in:
commit
5d1f2e24c3
@ -1,6 +1,7 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Jan Wagner <mail@jwagner.eu>
|
||||
* 2015-2016 Freie Universität Berlin
|
||||
* 2019 Inria
|
||||
*
|
||||
* This file is subject to the terms and conditions of the GNU Lesser
|
||||
* General Public License v2.1. See the file LICENSE in the top level
|
||||
@ -22,6 +23,7 @@
|
||||
* @author Timo Ziegler <timo.ziegler@fu-berlin.de>
|
||||
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
|
||||
* @author Jan Wagner <mail@jwagner.eu>
|
||||
* @author Alexandre Abadie <alexandre.abadie@inria.fr>
|
||||
*
|
||||
* @}
|
||||
*/
|
||||
@ -35,10 +37,30 @@
|
||||
#define PIN_MASK (0x1f)
|
||||
|
||||
#ifdef MODULE_PERIPH_GPIO_IRQ
|
||||
|
||||
#if CPU_FAM_NRF51
|
||||
#define GPIOTE_CHAN_NUMOF (4U)
|
||||
#else
|
||||
#define GPIOTE_CHAN_NUMOF (8U)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Index of next interrupt in GPIOTE channel list.
|
||||
*
|
||||
* The index is incremented at the end of each call to gpio_init_int.
|
||||
* The index cannot be greater or equal than GPIOTE_CHAN_NUMOF.
|
||||
*/
|
||||
static uint8_t _gpiote_next_index = 0;
|
||||
|
||||
/**
|
||||
* @brief Array containing a mapping between GPIOTE channel and pin
|
||||
*/
|
||||
static gpio_t _exti_pins[GPIOTE_CHAN_NUMOF];
|
||||
|
||||
/**
|
||||
* @brief Place to store the interrupt context
|
||||
*/
|
||||
static gpio_isr_ctx_t exti_chan;
|
||||
static gpio_isr_ctx_t exti_chan[GPIOTE_CHAN_NUMOF];
|
||||
#endif /* MODULE_PERIPH_GPIO_IRQ */
|
||||
|
||||
/**
|
||||
@ -125,44 +147,76 @@ void gpio_write(gpio_t pin, int value)
|
||||
int gpio_init_int(gpio_t pin, gpio_mode_t mode, gpio_flank_t flank,
|
||||
gpio_cb_t cb, void *arg)
|
||||
{
|
||||
/* disable external interrupt in case one is active */
|
||||
NRF_GPIOTE->INTENSET &= ~(GPIOTE_INTENSET_IN0_Msk);
|
||||
uint8_t _pin_index = 0xff;
|
||||
/* Looking for already known pin in exti table */
|
||||
for (unsigned int i = 0; i < _gpiote_next_index; i++) {
|
||||
if (_exti_pins[i] == pin) {
|
||||
_pin_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* New pin */
|
||||
if (_pin_index == 0xff) {
|
||||
assert(_gpiote_next_index < GPIOTE_CHAN_NUMOF);
|
||||
_pin_index = _gpiote_next_index;
|
||||
/* associate the current pin with channel index */
|
||||
_exti_pins[_pin_index] = pin;
|
||||
/* increase next index for next pin initialization */
|
||||
_gpiote_next_index++;
|
||||
}
|
||||
|
||||
/* save callback */
|
||||
exti_chan.cb = cb;
|
||||
exti_chan.arg = arg;
|
||||
exti_chan[_pin_index].cb = cb;
|
||||
exti_chan[_pin_index].arg = arg;
|
||||
/* configure pin as input */
|
||||
gpio_init(pin, mode);
|
||||
/* set interrupt priority and enable global GPIOTE interrupt */
|
||||
NVIC_EnableIRQ(GPIOTE_IRQn);
|
||||
/* configure the GPIOTE channel: set even mode, pin and active flank */
|
||||
NRF_GPIOTE->CONFIG[0] = (GPIOTE_CONFIG_MODE_Event |
|
||||
NRF_GPIOTE->CONFIG[_pin_index] = (GPIOTE_CONFIG_MODE_Event |
|
||||
(pin_num(pin) << GPIOTE_CONFIG_PSEL_Pos) |
|
||||
#ifdef CPU_MODEL_NRF52840XXAA
|
||||
((pin & PORT_BIT) << 8) |
|
||||
#endif
|
||||
(flank << GPIOTE_CONFIG_POLARITY_Pos));
|
||||
/* enable external interrupt */
|
||||
NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN0_Msk;
|
||||
NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN0_Msk << _pin_index);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void gpio_irq_enable(gpio_t pin)
|
||||
{
|
||||
(void) pin;
|
||||
NRF_GPIOTE->INTENSET |= GPIOTE_INTENSET_IN0_Msk;
|
||||
for (unsigned int i = 0; i < _gpiote_next_index; i++) {
|
||||
if (_exti_pins[i] == pin) {
|
||||
NRF_GPIOTE->CONFIG[i] |= GPIOTE_CONFIG_MODE_Event;
|
||||
NRF_GPIOTE->INTENSET |= (GPIOTE_INTENSET_IN0_Msk << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_irq_disable(gpio_t pin)
|
||||
{
|
||||
(void) pin;
|
||||
NRF_GPIOTE->INTENCLR |= GPIOTE_INTENSET_IN0_Msk;
|
||||
for (unsigned int i = 0; i < _gpiote_next_index; i++) {
|
||||
if (_exti_pins[i] == pin) {
|
||||
/* Clear mode configuration: 00 = Disabled */
|
||||
NRF_GPIOTE->CONFIG[i] &= ~(GPIOTE_CONFIG_MODE_Msk);
|
||||
NRF_GPIOTE->INTENCLR = (GPIOTE_INTENCLR_IN0_Msk << i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void isr_gpiote(void)
|
||||
{
|
||||
if (NRF_GPIOTE->EVENTS_IN[0] == 1) {
|
||||
NRF_GPIOTE->EVENTS_IN[0] = 0;
|
||||
exti_chan.cb(exti_chan.arg);
|
||||
for (unsigned int i = 0; i < _gpiote_next_index; ++i) {
|
||||
if (NRF_GPIOTE->EVENTS_IN[i] == 1) {
|
||||
NRF_GPIOTE->EVENTS_IN[i] = 0;
|
||||
exti_chan[i].cb(exti_chan[i].arg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
cortexm_isr_end();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user