In Nordic's Zephyr fork (sdk-zephyr) there's this GPIO driver function:
drivers/gpio/gpio_nrfx.c:202
static int gpio_nrfx_port_get_raw(const struct device *port, uint32_t *value)
{
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
*value = nrf_gpio_port_in_read(reg);
return 0;
}
I don't think this is the entire story of querying GPIOs, though. This appears to only query the *input* GPIOs via IN, and does not read the current state of any *output* GPIOs via OUT/OUTSET/OUTCLR. The HAL drivers actually have an additional output read API for this, nrf_gpio_port_out_read().
Looking at the registers on my nRF9160, I see:
(gdb) print/x *(NRF_GPIO_Type *)0x50842500
$8 = {RESERVED = 0x0, OUT = 0x28014002, OUTSET = 0x28014002, OUTCLR = 0x28014002, IN = 0x30000003, DIR = 0x2801401e, DIRSET = 0x2801401e, DIRCLR = 0x2801401e,
LATCH = 0x0, DETECTMODE = 0x0, DETECTMODE_SEC = 0x0, RESERVED1 = {0x0 <repeats 54 times>, 0x1, 0x1, 0x1, 0x0 <repeats 24 times>, 0x1, 0x0, 0x0, 0x0, 0x1,
0x0 <repeats 21 times>, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0}, PIN_CNF = {0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x3,
0x0, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x0, 0x3, 0x0, 0x3, 0x2, 0x2}}
I can then turn on an LED on our board using pin 2:
(gdb) set ((NRF_GPIO_Type *)0x50842500)->OUT=0x28014006
The LED does indeed turn on, IN hasn't changed, and OUT/OUTSET/OUTCLR show the new pin state:
(gdb) print/x *(NRF_GPIO_Type *)0x50842500
$16 = {RESERVED = 0x0, OUT = 0x28014006, OUTSET = 0x28014006, OUTCLR = 0x28014006, IN = 0x30000003, DIR = 0x2801401e, DIRSET = 0x2801401e, DIRCLR = 0x2801401e,
LATCH = 0x0, DETECTMODE = 0x0, DETECTMODE_SEC = 0x0, RESERVED1 = {0x0 <repeats 54 times>, 0x1, 0x1, 0x1, 0x1, 0x0 <repeats 23 times>, 0x1, 0x0, 0x0, 0x0, 0x1,
0x0 <repeats 21 times>, 0x1, 0x0, 0x0, 0x1, 0x1, 0x1, 0x0, 0x0, 0x0, 0x0}, PIN_CNF = {0x0, 0x3, 0x3, 0x3, 0x3, 0x4, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x3,
0x0, 0x3, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x2, 0x0, 0x3, 0x0, 0x3, 0x2, 0x2}}
So clearly IN doesn't reflect the state of output pins. Since this is the only API that the Zephyr GPIO driver uses to get a current output pin state, doesn't this *have* to also take into account the current configurations of pins and their state in OUT/OUTSET/OUTCLR? Interestingly, your previous driver actually did this correctly:
static int gpio_nrfx_read(struct device *port, int access_op,
u32_t pin, u32_t *value)
{
NRF_GPIO_Type *reg = get_port_cfg(port)->port;
struct gpio_nrfx_data *data = get_port_data(port);
u32_t dir = nrf_gpio_port_dir_read(reg);
u32_t port_in = nrf_gpio_port_in_read(reg) & ~dir;
u32_t port_out = nrf_gpio_port_out_read(reg) & dir;
u32_t port_val = (port_in | port_out) ^ data->inverted;
if (access_op == GPIO_ACCESS_BY_PORT) {
*value = port_val;
} else {
*value = (port_val & BIT(pin)) ? 1 : 0;
}
return 0;
}
but that API was removed in:
commit 1f9beb193f354d52573c43f390d880e29de7d935 Author: Peter Bigot <[email protected]> Date: Thu Jan 30 09:06:37 2020 -0600 gpio: remove legacy read/write API functions The last external reference to these was removed when the pin write/read functions were deprecated. Remove the syscall support, API function table entries, and implementation from all drivers. Signed-off-by: Peter Bigot <[email protected]>
in favor of the "raw" API in:
commit ff90b2c1d638748bf9a445848c920eb2b68a5349 Author: Piotr Mienkowski <[email protected]> Date: Tue Aug 6 00:56:05 2019 +0200 drivers: gpio_nrfx: update to use new GPIO API Update driver code and board files to use new GPIO configuration flags such as GPIO_ACTIVE_LOW. Also add implementation of new port_* driver API as well as gpio_pin_interrupt_configure function. Tested on nrf52840_pca10056 board. Signed-off-by: Piotr Mienkowski <[email protected]> Signed-off-by: Peter Bigot <[email protected]>