GPIO Latch not behaving consistently

Hi,

I'm trying to get latch functionality working on two GPIO pins, but cannot seem get the latch register to behave consistently.

I have my GPIOs configured using a custom DTS binding and overlay, something like this:

mbuttons { 
    compatible = "any,spdt-switch";
    rmb: switch_0 { 
        ncgpios = <&gpio1 13 0>;
        nogpios = <&gpio1 12 0>;
    };
};

In my main code, the flow is roughly as follows:

#define RMB_NODE DT_NODELABEL(rmb)

// in main
// edit: I tried both low and high sense settings, but expect low to work as I need it to here
nrf_gpio_cfg_sense_input(NRF_DT_GPIOS_TO_PSEL(RMB_NODE, nogpios), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
nrf_gpio_cfg_sense_input(NRF_DT_GPIOS_TO_PSEL(RMB_NODE, ncgpios), NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);

uint32_t p_mask;

while(1) {
    // I've also tried this one, with p_masks etc
    // pmask = nrf_gpio_latches_read_and_clear(0, 2, p_masks);
    
    // read latch values
    p_mask = NRF_P1->LATCH;
    
    // and clear them 
    NRF_P1->LATCH = p_mask;
    
    if (p_mask != 0){
        LOG_INF("Event: %d", p_mask);
    }
}

I get the logging statement very rarely when actuating my switch. I have the switch hooked up to a scope, which is showing behavior as I'd expect for an SPDT switch (common is GND, default NC low & NO high, on click switching to NC high and NO low, where high is ~3.4v and low is ~200mv). 

A few questions:

1. Is there anything obviously wrong here?

2. Is there a recommended workflow for working with NRF-specific functionality in NCS/Zephyr? I'm using functions from nrf_gpio.h, e.g. nrf_gpio_cfg_sense_input, etc. I couldn't find any documentation on detect/latch configuration in the context of Zephyr/NCS, just GPIOTE (which I don't necessarily need/want to use yet).

  • Ok, glad that you wrote that you are using some other sensors on that port.  In that case you must have enabled nrfx_gpiote driver which then owns the gpio ports (with config NRF_GPIO_LATCH_PRESENT)

    .You should not try to figure out if the pin sense has been detected in the application logic but instead rely that the handler set in nrfx_gpiote_input_configure will be called when the gpiote driver has processed the detected sense on your pin. 

    If you want to handle the pin directly in your application then you need to disable NRFX_GPIOTE which then relinquishes control on the port.

  • In this particular application, I'd like to read the latch directly than to rely on any interrupts/handlers/callbacks from GPIOTE. If I want to do that, should I be OK if I sit it on its own separate port, e.g. my sensor on P0 and everything I want to read via latch on P1? 

  • unfortunately the driver owns all gpio ports once enabled. You can try to change that behavior by replace GPIO_COUNT with 1 in nrfx_gpiote.c and then this driver will not sniff port 1 gpio pins.

    #if defined(NRF_GPIO_LATCH_PRESENT)
    static bool latch_pending_read_and_check(uint32_t * latch)
    {
        nrf_gpio_latches_read_and_clear(0, GPIO_COUNT, latch);
    
        for (uint32_t port_idx = 0; port_idx < GPIO_COUNT; port_idx++)
        {
            if (latch[port_idx])
            {
                /* If any of the latch bits is still set, it means another edge has been captured
                 * before or during the interrupt processing. Therefore event-processing loop
                 * should be executed again. */
                return true;
            }
        }
        return false;
    }

Related