How to check the reason for wakeup from idle and GPIO interrupt unresponsive in idle

I am working on an ongoing project where some minor power management is implemented:

void exit_sleep(enum pm_state state)
{
	/* turn on gyroscope 5V power supply */
	set_5v_reg(true);
}

void enter_sleep(enum pm_state state)
{
	/* turn off gyroscope 5V power supply */
	set_5v_reg(false);
}

static pm_notifier notifier = {.state_entry = enter_sleep, .state_exit = exit_sleep};

void suspend()
{
	/* Information about the suspend state */
	pm_state_info suspend{PM_STATE_SUSPEND_TO_IDLE, 0, 0, 0};
	/* Forces power management to go to a suspend state */
	pm_state_force(0u, &suspend);
}

void init()
{
	pm_notifier_register(&notifier);
	set_5v_reg(true);
}

suspend is called when measurements go to idle. But while debugging the application behaves strangely. The system goes into suspend after power up as intended, deactivates a 5 V power line and waits for a GPIO trigger. But the application instead starts up again immediately. The GPIO interrupt generally works here as its callback is called when triggered. When it goes into suspend again after some time it stays in idle and the GPIO interrupt does not get triggered again.

As far as I know the power states are not defined in the device tree as I have seen in some documentations.

The first problem is now that I don't even know what triggered the wakeup from idle. Is there any way to check the wakeup reason? Debugging does not help here as the reason is obfuscated by the OS. Maybe a register value?

For the second problem I am not even sure how the GPIO interrupt is supposedly linked to the wakeup. Is there a resource with an appropriate example? Most examples with the interfaces used in the code only handle the power down but not the power up, or it is thread triggered and not by interrupt.

Many thanks,

Rico

Related