soc: mec1501: modifies interrupt restoration after deep sleep
z_power_soc_deep_sleep() is called with interrupt locked already so restoring BASEPRI is pointless here, as it would only allow exceptions afterwards. The situation is complicated by the fact that kernel/idle.c:idle() only locks interrupt without unlocking which means the BASEBRI at entry of z_power_soc_deep_sleep() is already set to allow exceptions only but not lower priority interrupts like timer. So when, e.g. timer, interrupt fires, the SoC would come out of deep sleep but the waking interrupts are never delivered since they are masked, and idle() will try to sleep again. And now it gets into a loop of going into deep sleep briefly and waking up immediately and it goes on and on. The solution is not to restore BASEPRI and simply leave it at zero. This is a workaround as a proper fix would involve invasion changes to the PM subsystem. Also, _sys_pm_power_state_exit_post_ops() is not being called when deep sleep is involved, so PRIMASK needs to be reset after coming out of deep sleep. Fixes #23274 Signed-off-by: Daniel Leung <daniel.leung@intel.com>
This commit is contained in:
parent
2e7831562a
commit
b935903543
1 changed files with 7 additions and 8 deletions
|
@ -40,8 +40,6 @@
|
|||
*/
|
||||
static void z_power_soc_deep_sleep(void)
|
||||
{
|
||||
u32_t base_pri;
|
||||
|
||||
/* Mask all exceptions and interrupts except NMI and HardFault */
|
||||
__set_PRIMASK(1);
|
||||
|
||||
|
@ -55,19 +53,13 @@ static void z_power_soc_deep_sleep(void)
|
|||
/*
|
||||
* Unmask all interrupts in BASEPRI. PRIMASK is used above to
|
||||
* prevent entering an ISR after unmasking in BASEPRI.
|
||||
* We clear PRIMASK in exit post ops.
|
||||
*/
|
||||
base_pri = __get_BASEPRI();
|
||||
__set_BASEPRI(0);
|
||||
__DSB();
|
||||
__WFI(); /* triggers sleep hardware */
|
||||
__NOP();
|
||||
__NOP();
|
||||
|
||||
if (base_pri != 0) {
|
||||
__set_BASEPRI(base_pri);
|
||||
}
|
||||
|
||||
soc_deep_sleep_disable();
|
||||
|
||||
soc_deep_sleep_non_wake_dis();
|
||||
|
@ -77,6 +69,13 @@ static void z_power_soc_deep_sleep(void)
|
|||
};
|
||||
|
||||
soc_deep_sleep_periph_restore();
|
||||
|
||||
/*
|
||||
* _sys_pm_power_state_exit_post_ops() is not being called
|
||||
* after exiting deep sleep, so need to unmask exceptions
|
||||
* and interrupts here.
|
||||
*/
|
||||
__set_PRIMASK(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue