This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Understanding how the Detect signal works and how to clear it

I'm just a bit confused on how gpio detect works.  After setting the sense config for input I realize that a change in voltage will trigger a sense signal that will create a Detect.  Also the detect will set latch.  I understand the latch will not be cleared until it is reset.  What I don't understand is what happens to the detect signal.  I assumed it set the latch, triggered whatever events were tied to it and then cleared.  It does not appear to work like that. 

I read about the detect a pin triggering a latch condition when it is enabled and observed that happen.  I figured that after that occured the detect signal would have passed and I could clear the latch register.  That did not work.  The latch would not clear.  Documentation says the latch will not clear if detect is still high.  Hence my question.  It seems to me that Detect should have cleared and not be high and the latch should have reset but that did not happen.

Would appreciate some insight into how Detect pin is cleared.

Thanks!

Parents
  • Hi,

     

    The "DETECT" signal is an internal signal that sets the PORT event. This is multiplexed with all GPIOs that have the _SENSE field in PIN_CNF[] enabled. This will remain high as long as one of your _SENSE enabled GPIOs are active.

    The LATCH register will tell you which pins have been active since last clearing the LATCH register. How do you clear the LATCH register? You should write '1' to the position you want to clear (ie: NRF_GPIO->LATCH = NRF_GPIO->LATCH;).

    If you do something like this:

    NRF_GPIO->LATCH = NRF_GPIO->LATCH;
    uint32_t latch = NRF_GPIO->LATCH;

    You will run into this errata: http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.Rev2.errata/dita/errata/nRF52832/Rev2/latest/anomaly_832_173.html?cp=2_1_1_0_1_43

    To be safe, do something like this:

    NRF_GPIO->LATCH = NRF_GPIO->LATCH;
    /* Force a 16 MHz cycle delay */
    (void)NRF_TIMER1->EVENTS_COMPARE[0];
    
    uint32_t latch = NRF_GPIO->LATCH;

     

    If you still have issues, please post code.

    Kind regards,

    Håkon

  • Thank you so much for your help.  I tried something similar using GPIO HAL but I did not insert a wait statement (the statement I used is commented out in the code below).  I attempted using what you provide here as an alternative but the latch remains unfortunately.  Here is the code snippet:

    //Configure all leds on board.
    bsp_board_init(BSP_INIT_LEDS);

    //configure the interrupt pin
    nrf_gpio_cfg(INTERRUPT_PIN, GPIO_PIN_CNF_DIR_Input, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_SENSE_LOW );

    ///initialize the interrupt
    gpio_init();

    bsp_board_led_invert(led3);


    //if the interrupt has occurred
    if(nrf_gpio_pin_latch_get(INTERRUPT_PIN) == 1 && system_on == true){


        //clear the interrupt register
        // nrf_gpio_pin_latch_clear(13);
        NRF_GPIO->LATCH = NRF_GPIO->LATCH;
        /* Force a 16 MHz cycle delay */
        (void)NRF_TIMER1->EVENTS_COMPARE[0];

        uint32_t latch = NRF_GPIO->LATCH; //turn on the board led


        bsp_board_led_on(led2);

    }

  • Hi,

    mark waldin said:
    nrf_gpio_cfg(INTERRUPT_PIN, GPIO_PIN_CNF_DIR_Input, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_SENSE_LOW );

    Is this the configuration that you want? This will continuously generate a event unless something externally pulls this pin high.

    I did a quick example with the DK, and it worked on my end:

    #include <stdbool.h>
    #include <stdint.h>
    #include "boards.h"
    #include "nrf_delay.h"
    
    #define INTERRUPT_PIN BUTTON_1
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
        nrf_gpio_cfg(INTERRUPT_PIN, GPIO_PIN_CNF_DIR_Input, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_SENSE_LOW);
        bsp_board_led_invert(LED_3);
        while (1)
        {
            if (nrf_gpio_pin_latch_get(INTERRUPT_PIN) == 1)
            {
                //clear the interrupt register
                // nrf_gpio_pin_latch_clear(13);
                NRF_GPIO->LATCH = NRF_GPIO->LATCH;
                /* Force a 16 MHz cycle delay */
                (void)NRF_TIMER1->EVENTS_COMPARE[0];
                uint32_t latch = NRF_GPIO->LATCH; //turn on the board led
                nrf_gpio_pin_toggle(LED_1);
                nrf_delay_ms(100);
            }
        }
    }
     

     

    Kind regards,

    Håkon

Reply
  • Hi,

    mark waldin said:
    nrf_gpio_cfg(INTERRUPT_PIN, GPIO_PIN_CNF_DIR_Input, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLDOWN, NRF_GPIO_PIN_S0D1, NRF_GPIO_PIN_SENSE_LOW );

    Is this the configuration that you want? This will continuously generate a event unless something externally pulls this pin high.

    I did a quick example with the DK, and it worked on my end:

    #include <stdbool.h>
    #include <stdint.h>
    #include "boards.h"
    #include "nrf_delay.h"
    
    #define INTERRUPT_PIN BUTTON_1
    
    /**
     * @brief Function for application main entry.
     */
    int main(void)
    {
        bsp_board_init(BSP_INIT_LEDS);
        nrf_gpio_cfg(INTERRUPT_PIN, GPIO_PIN_CNF_DIR_Input, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_SENSE_LOW);
        bsp_board_led_invert(LED_3);
        while (1)
        {
            if (nrf_gpio_pin_latch_get(INTERRUPT_PIN) == 1)
            {
                //clear the interrupt register
                // nrf_gpio_pin_latch_clear(13);
                NRF_GPIO->LATCH = NRF_GPIO->LATCH;
                /* Force a 16 MHz cycle delay */
                (void)NRF_TIMER1->EVENTS_COMPARE[0];
                uint32_t latch = NRF_GPIO->LATCH; //turn on the board led
                nrf_gpio_pin_toggle(LED_1);
                nrf_delay_ms(100);
            }
        }
    }
     

     

    Kind regards,

    Håkon

Children
  • Thank you for looking at this once again.  I see it does toggle.  However, based on the code if the pin is latched in one cycle it should clear and then remain cleared since the if statement will not be satisfied.  In looking at the pin state using EmbedStudio it remains latched and never clears.  

    To test further, I changed your code as below so that if it were clearing it would toggle.  Using this the led remains lit.  Not sure what is going on.

    while(1){

    if (nrf_gpio_pin_latch_get(INTERRUPT_PIN) == 1)
    {
    //clear the interrupt register
    // nrf_gpio_pin_latch_clear(13);
    NRF_GPIO->LATCH = NRF_GPIO->LATCH;
    /* Force a 16 MHz cycle delay */
    (void)NRF_TIMER1->EVENTS_COMPARE[0];
    uint32_t latch = NRF_GPIO->LATCH; //turn on the board led
    nrf_gpio_pin_set(LED_1);
    nrf_delay_ms(100);
    }else{
    nrf_gpio_pin_clear(LED_1);
    nrf_delay_ms(100);
    }

    }

  • mark waldin said:
    In looking at the pin state using EmbedStudio it remains latched and never clears. 

     Did you change your initial gpio configuration? You need to take a look at that again, as you had it always latched (pull down + SENSE_LOW) unless you actively set the GPIO externally to VDD.

    Instead of looking at the register while running (which may be cached), trust the behavior of your program instead. Register views are often cached, especially while running the code. In situations like these, break; then read the register, or use a variable to read out the LATCH state.

    mark waldin said:
    Using this the led remains lit.

    Are you using the nRF52-DK? Do note that the LEDs and buttons are all active low. So setting the pin low will light up the LED.

    Kind regards,

    Håkon

  • I did make the change to the config and set the pull up resistor high.  The way I was testing was to set breakpoints and check the register status on pin 13.  Thank you for the advice to check the board leds instead.

    I apologize but I just do not understand how your code shows the latch is clearing.  For each loop of the WHILE statement we are testing to see if the latch is set.  If the routine cleared the latch the if statement would fail, the latch would remain cleared and the light would stop blinking.  But as you say the light toggles.  Does not this show that the latch is NOT being cleared?  I am clearing missing something here. Thank you for your patience on this.

  • I solved the problem.  I changed the Interrupt from 13 (Button1) to 14 (Button2).  It started working after that.  It appears that button 1 has a mechanical problem.  It now works as expected.  Thank you for your help.

  • Hi,

    I'm glad to hear that you found the source of the issue!

    Kind regards,

    Håkon

Related