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

GPIOTE Port event triggered by the state of the pin, not an edge change.

Hi,

I put my NRF52 to sleep (POWER OFF mode) and configure it to wake on GPIO port event like so: 

    //set up reed switch to wake up from System Off
      nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(false);
      in_config.pull = NRF_GPIO_PIN_NOPULL; //hardware pull up resistor.
      err_code = nrf_drv_gpiote_in_init(REED_SWITCH_PIN, &in_config, wake_handler);
      APP_ERROR_CHECK(err_code);
      nrf_drv_gpiote_in_event_enable(REED_SWITCH_PIN, true);
      
      SEGGER_RTT_printf(0, "Powering Down!\r\n");
      
      sd_power_system_off();

This GPIO is set up on a reed switch. Occasionally, the NRF52 will try to sleep whilst the magnet is resting next to the reed switch. I.e REED_SWITCH_PIN is at a steady state low. 

Problem:

  • When REED_SWITCH_PIN is a steady state low, the interrupt fires straight away and wakes up my sensor unexpectedly.
  • From reading the documentation I would expect that the PORT event can detect an edge change? Is this true, or am I seeing something weird?

I do have a work around which involves using a GPIOTE in event, and sending the device into System-on sleep mode, however power consumption is obviously higher - so not ideal.

  • Hi,

    The chip will wake up from system OFF if a level change is detected on a GPIO, so the chip should no wake up if the level is kept steady. Also note that the wake-up mechanism does not use the GPIOTE block, but is connected directly to the SENSE signal from the GPIO block.

    Please try the following and see if you get the same result:

            /*Pins that are not needed in system OFF should be configured to reset state
              to avoid leakage currents and unexpected wakeups.*/
            nrf_gpio_cfg_default(PIN_x);
            nrf_gpio_cfg_default(PIN_y);
            ...
            
            /* Configure wakeup pin*/
            nrf_gpio_cfg_sense_input(WAKE_UP_PIN,
                                     NRF_GPIO_PIN_NOPULL, // Apply pull if input can become floating
                                     NRF_GPIO_PIN_SENSE_HIGH);
            sd_power_system_off(); // NOTE: chip will enter emulated system OFF if chip is in debug interface mode. 

    Is the external pull up on the REED_SWITCH_PIN input enabled when the device is in system OFF? I'm wondering if the input could be floating.

     

     

  • Thanks for the quick response!

    After changing to your suggested code, the result is the same. The external pull up is a fixed resistor and PCB has been continuity checked, so I am pretty confident it is not a hardware issue. The problem in my question above occurs when the REED_SWITCH_PIN is shorted to ground, so the external pull up isn't having any effect at this time.

    Earlier in the program, before I sleep the device, the REED_SWITCH_PIN is configured as a GPIOTE interrupt (In event, not port). I enable this at the very start of the program, and then before trying to sleep I disable this interrupt and use the code in my original question. The code I use to enable/disable is below.

    Is it possible that the previous use is causing problems?

    static void init_reed_switch(void) {
      uint32_t err_code;
      nrf_drv_gpiote_in_config_t in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
      in_config.pull = NRF_GPIO_PIN_NOPULL;
      err_code = nrf_drv_gpiote_in_init(REED_SWITCH_PIN, &in_config, reed_switch_handler);
      APP_ERROR_CHECK(err_code);
      nrf_drv_gpiote_in_event_enable(REED_SWITCH_PIN, true);
    }
    
    static void disable_reed_switch(void) {
      nrf_drv_gpiote_in_event_disable(REED_SWITCH_PIN);
      nrf_drv_gpiote_in_uninit(REED_SWITCH_PIN);
    }

  • The GPIOTE module is powered down in system OFF mode, but pin configurations are retained. To narrow down the problem I suggest to go through the pin configurations to make sure that only wake up pin is configured with sense enabled. One way of doing this is to place a breakpoint at the line where sd_power_system_off(); is called, then read out the NRF_GPIO->PIN_CNF[n] registers. 

    Peripheral viewer in Keil (From menu tab: View ->System Viewer -> P0)

     

     

  • I have checked the NRF_GPIO->PIN_CNF[n] registers  - all are either configured as inputs (0x00000002) or outputs (0x00000003), apart from pin 13 (REED_SWITCH_PIN) which is 0x00030000 as expected. 

    However, I noticed in the Latch register, PIN 20 is latched (nothing else is).

    Pin 20 is an interrupt pin from an accelerometer. At the start of the program this is enabled as a PORT event, but then disabled as below, before trying to sleep. 

    static void turn_off_sensors(void) {
      nrf_drv_gpiote_in_event_disable(ACC_INT_PIN_1);
      nrf_drv_gpiote_in_uninit(ACC_INT_PIN_1);
    
      writeAccReg(LIS3DH_CTRL_REG1, 0x0F); //enter Accelerometer power down state
      while ((!acc_spi_xfer_done)) {
        power_manage();
      }
    
      nrf_drv_spi_uninit(&acc_spi);
    
      nrf_gpio_pin_clear(ACC_POWER_PIN);
      nrf_gpio_pin_clear(ACC_SS_PIN);
    
      nrf_gpio_cfg_default(ACC_INT_PIN_1);
      nrf_gpio_cfg_default(ACC_INT_PIN_2);
      nrf_gpio_cfg_default(ACC_SCK_PIN);
      nrf_gpio_cfg_default(ACC_MOSI_PIN);
      nrf_gpio_cfg_default(ACC_MISO_PIN);
    
      SEGGER_RTT_printf(0, "Sensors Off\n\r");
    }

  • I have solved the issue of PIN 20 being latched incorrectly by making PIN 20 use a GPIOTE IN event all the time, and REED_SWITCH_PIN (13) using the PORT event all the time.

    Now with a breakpoint on sd_power_system_off, everything looks normal - all PIN_CNF values are 0x00000002 or 0x00000003 with the exception of the REED_SWITCH_PIN which is 0x00030000.

    Latch registers when sleeping with the REED_SWITCH_PIN pulled high (by the external pullup) are all clear.

    Latch registers when sleeping with the REED_SWITCH_PIN pulled steady state low indicate PIN13 is latched (as expected I think?). 

    The behaviour in the main question remains unfortunately.

Related