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

PORT event interupt while sensed pin is active

Hello!

I am using the PORT event interupt sense handler to wake up the device from various pin interupts. We have in total 6 pins that need to do that.

This works fine, except for when a current pin generated an event that stays in this detected state for a while. For example, see these scope images:

The green line is a 1 hz signal from an external RTC. This sometimes needs to wakeup the device once a second (hence the interupt sense method choosen is HI to LO).

The yellow line is an interupt that needs to wakeup the device as well, but needs only to trigger an interupt when something is near (IR detection).

The problem i am facing is that during the RTC interupt from HI to LO, this IR detection interupt gets ignored, because the PORT sense event only can generate an interupt if the current pin that generated the interupt goes back to the non triggered state (AFAIK and is during debugging very apparant).

We also have a pin that is pulled LO and stays low as long as a certain cable is connected to our device, which needs to prevent the device to sleep during this event. In this case, ALL interupts from the other PORT event pins get ingnored for the set interupt event.

I tried the IN EVENT mode. That works fine for what we need, but uses way too much current during the sleep period of the device.

I tried to switch from the PORT event to the IN EVENT during wake times, but thats not ideal and gave me errors during switching.

Is there a way I can "reset" the current pin state, that generated the interupt in the PORT event, so that I can receive other interupts?

It is very important that we always have every 6 of these pins generate the interupt and that we know what pin did it.

(part of) my code:

void PIN_WAKE_ON_FTDI_IRQHandler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) // FTDI connect
{	if(pin == INTERFACE_CABLE_DETECT_PIN)
	{	PM_WakedBy |= WAKE_ON_FTDI;
	}
}

void PIN_WAKE_ON_CARDDT_IRQHandler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) //EM = Toetsen of IR
{	if(pin == EM_IRQ_PIN)
	{	PM_WakedBy |= WAKE_ON_CARDDT;
	}
}

void PIN_WAKE_ON_RTC_IRQHandler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) // WAKE_ON_RTC
{	if(pin == RTC_PCF2123_CLKOUT_PIN)
	{	PM_WakedBy |= WAKE_ON_RTC;
	}
}


void PM_Init(void)
{	ret_code_t err_code;
	nrfx_gpiote_in_config_t nrfx_gpiote_in_config;
	err_code = nrfx_gpiote_init(); // init de GPIOTE module
	APP_ERROR_CHECK(err_code);

	nrfx_gpiote_in_config.hi_accuracy = false; // Set hi_accu to false for PORT event
	
	// WAKE_ON_FTDI this is a pin that stays low during placement of the cable and needs to prevent the device from sleep
	nrfx_gpiote_in_uninit(INTERFACE_CABLE_DETECT_PIN);
	nrfx_gpiote_in_config.sense = NRF_GPIOTE_POLARITY_HITOLO;
	nrfx_gpiote_in_config.pull = (nrf_gpio_pin_pull_t)INTERFACE_CABLE_DETECT_PIN_PULL_CFG;
	err_code = nrfx_gpiote_in_init(INTERFACE_CABLE_DETECT_PIN, &nrfx_gpiote_in_config, PIN_WAKE_ON_FTDI_IRQHandler);  
	APP_ERROR_CHECK(err_code);
	nrfx_gpiote_in_event_enable(INTERFACE_CABLE_DETECT_PIN, true);
	
	// WAKE_ON_CARDDT this is a pin that needs to detect a near detection at all times
	nrfx_gpiote_in_uninit(EM_IRQ_PIN);
	nrfx_gpiote_in_config.sense = NRF_GPIOTE_POLARITY_HITOLO;
	nrfx_gpiote_in_config.pull = (nrf_gpio_pin_pull_t)EM_IRQ_PIN_PULL_CFG;
	err_code = nrfx_gpiote_in_init(EM_IRQ_PIN, &nrfx_gpiote_in_config, PIN_WAKE_ON_CARDDT_IRQHandler);
	APP_ERROR_CHECK(err_code);
	nrfx_gpiote_in_event_enable(EM_IRQ_PIN, true);	
	
	// WAKE_ON_RTC this is a 1 hz interupt pin that sometimes needs to wake the device every second for a few seconds
	nrfx_gpiote_in_uninit(RTC_PCF2123_CLKOUT_PIN);
	nrfx_gpiote_in_config.sense = NRF_GPIOTE_POLARITY_HITOLO;
	nrfx_gpiote_in_config.pull = (nrf_gpio_pin_pull_t)RTC_PCF2123_CLKOUT_PIN_PULL_CFG;
	err_code = nrfx_gpiote_in_init(RTC_PCF2123_CLKOUT_PIN, &nrfx_gpiote_in_config, PIN_WAKE_ON_RTC_IRQHandler);
	APP_ERROR_CHECK(err_code);
	nrfx_gpiote_in_event_enable(RTC_PCF2123_CLKOUT_PIN, true);
}

	

  • Ah, yes. In any case what you are trying to do is not really supported by the HW. You will not be able to get reliable low power interrupts for specific pins.

  • I think the only reliable method would be to switch to high accuracy mode (IN_EVENT) when waking up from any PORT event to get interupts from any pin.

    and then going back to PORT mode just before going back to sleep, am I correct? Or is this not possible?

  • You are right. I was under the impression that you did not want to do that, but it is how it is normally done. If you require interrupts for each pin and this could occur on more pins simultaneously, then switching to pin events is the only way. You can always switch back to port event afterwards.

  • Its not ideal and I couldnt get it to work reliably (I got some errors during debugging from switching between PORT and IN_EVENT mode). But I will focus on that now I guess, cause toggling and waking on every level change is not very much ideal either. Thanks for your time!

  • Its been a few days of struggling, but I can not make it work as I want to and about to loose my mind on this issue... I want to configure the pins for a PORT sense event just before sleeping and once the chip wakes up because of a PORT event, I want to switch over to the IN_EVENT on the same pins. But whatever I try to do, switching the sense mechanism of these pins, triggers the interupts for these pins. What am I doing wrong?

    Below a (simplified) example of what I am currently stranded on:

    #define RTC_PCF2123_CLKOUT_PIN 11
    #define RTC_PCF2123_CLKOUT_PIN_PULL_CFG 0
    
    
    void PIN_WAKE_ON_RTC_IRQHandler(nrfx_gpiote_pin_t pin, nrf_gpiote_polarity_t action) // WAKE_ON_RTC
    {	if(pin == RTC_PCF2123_CLKOUT_PIN)
    	{	BuzzerTimed(BUZZER_TONE_OK,10); // make a beep sound for testing IRQ
    	}
    }
    
    void power_management(void)
    {	ret_code_t err_code;
    	nrfx_gpiote_in_config_t nrfx_gpiote_in_config;
    	nrfx_gpiote_in_config.is_watcher = false; // True when the input pin is tracking an output pin.
    	
    	nrfx_gpiote_in_config.hi_accuracy = false; // Set hi_accu to false for PORT event
    	nrfx_gpiote_in_uninit(RTC_PCF2123_CLKOUT_PIN); // uninit this pin, else we get error
    	nrfx_gpiote_in_config.sense = NRF_GPIOTE_POLARITY_HITOLO;
    	nrfx_gpiote_in_config.pull = (nrf_gpio_pin_pull_t)RTC_PCF2123_CLKOUT_PIN_PULL_CFG;
    	err_code = nrfx_gpiote_in_init(RTC_PCF2123_CLKOUT_PIN, &nrfx_gpiote_in_config, PIN_WAKE_ON_RTC_IRQHandler);
    	APP_ERROR_CHECK(err_code);	
    	nrfx_gpiote_in_event_enable(RTC_PCF2123_CLKOUT_PIN, false);	// enable het 1 hz PORT event
    	
    	// going to sleep
    	
    	nrf_pwr_mgmt_run(); // Sleeping
    	
    	// woken up due to PORT event
    	
    	nrfx_gpiote_in_config.hi_accuracy = true; // Set hi_accu to true for IN_EVENT event
    	nrfx_gpiote_in_uninit(RTC_PCF2123_CLKOUT_PIN);
    	nrfx_gpiote_in_config.sense = NRF_GPIOTE_POLARITY_HITOLO;
    	nrfx_gpiote_in_config.pull = (nrf_gpio_pin_pull_t)RTC_PCF2123_CLKOUT_PIN_PULL_CFG;
    	err_code = nrfx_gpiote_in_init(RTC_PCF2123_CLKOUT_PIN, &nrfx_gpiote_in_config, PIN_WAKE_ON_RTC_IRQHandler);
    	APP_ERROR_CHECK(err_code);	
    	nrfx_gpiote_in_event_enable(RTC_PCF2123_CLKOUT_PIN, false);	// enable het 1 hz IN_EVENT
    }

    Please help me

Related