Skip to content

Commit b935903

Browse files
dcpleungnashif
authored andcommitted
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 <[email protected]>
1 parent 2e78315 commit b935903

File tree

1 file changed

+7
-8
lines changed
  • soc/arm/microchip_mec/mec1501

1 file changed

+7
-8
lines changed

soc/arm/microchip_mec/mec1501/power.c

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,6 @@
4040
*/
4141
static void z_power_soc_deep_sleep(void)
4242
{
43-
u32_t base_pri;
44-
4543
/* Mask all exceptions and interrupts except NMI and HardFault */
4644
__set_PRIMASK(1);
4745

@@ -55,19 +53,13 @@ static void z_power_soc_deep_sleep(void)
5553
/*
5654
* Unmask all interrupts in BASEPRI. PRIMASK is used above to
5755
* prevent entering an ISR after unmasking in BASEPRI.
58-
* We clear PRIMASK in exit post ops.
5956
*/
60-
base_pri = __get_BASEPRI();
6157
__set_BASEPRI(0);
6258
__DSB();
6359
__WFI(); /* triggers sleep hardware */
6460
__NOP();
6561
__NOP();
6662

67-
if (base_pri != 0) {
68-
__set_BASEPRI(base_pri);
69-
}
70-
7163
soc_deep_sleep_disable();
7264

7365
soc_deep_sleep_non_wake_dis();
@@ -77,6 +69,13 @@ static void z_power_soc_deep_sleep(void)
7769
};
7870

7971
soc_deep_sleep_periph_restore();
72+
73+
/*
74+
* _sys_pm_power_state_exit_post_ops() is not being called
75+
* after exiting deep sleep, so need to unmask exceptions
76+
* and interrupts here.
77+
*/
78+
__set_PRIMASK(0);
8079
}
8180
#endif
8281

0 commit comments

Comments
 (0)