Commit 22b17e49 authored by Andrzej Głąbek's avatar Andrzej Głąbek Committed by Carles Cufi
Browse files

arch: arm: aarch32: Introduce z_arm_on_enter_cpu_idle() hook



Introduce an optional hook to be called when the CPU is made idle.
If needed, this hook can be used to prevent the CPU from actually
entering sleep by skipping the WFE/WFI instruction.

Signed-off-by: default avatarAndrzej Głąbek <andrzej.glabek@nordicsemi.no>
parent 68bd0369
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -45,6 +45,14 @@ config CODE_DATA_RELOCATION_SRAM
	  config is used to create an MPU entry for the SRAM space used for code
	  relocation.

config ARM_ON_ENTER_CPU_IDLE_HOOK
	bool
	help
	  Enables a hook (z_arm_on_enter_cpu_idle()) that is called when
	  the CPU is made idle (by k_cpu_idle() or k_cpu_atomic_idle()).
	  If needed, this hook can be used to prevent the CPU from actually
	  entering sleep by skipping the WFE/WFI instruction.

rsource "core/aarch32/Kconfig"
rsource "core/aarch32/Kconfig.vfp"

+30 −9
Original line number Diff line number Diff line
@@ -48,6 +48,33 @@ SECTION_FUNC(TEXT, z_arm_cpu_idle_init)
#endif
	bx	lr

.macro _sleep_if_allowed wait_instruction
#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK)
	push	{r0, lr}
	bl	z_arm_on_enter_cpu_idle
	/* Skip the wait instruction if on_enter_cpu_idle() returns false. */
	cmp	r0, #0
	beq	_skip_\@
#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */

	/*
	 * Wait for all memory transactions to complete before entering low
	 * power state.
	 */
	dsb
	\wait_instruction

#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK)
_skip_\@:
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)
	pop	{r0, r1}
	mov	lr, r1
#else
	pop	{r0, lr}
#endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */
#endif /* CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK */
.endm

SECTION_FUNC(TEXT, arch_cpu_idle)
#ifdef CONFIG_TRACING
	push	{r0, lr}
@@ -89,14 +116,8 @@ SECTION_FUNC(TEXT, arch_cpu_idle)
	 */
#endif /* CONFIG_ARMV7_M_ARMV8_M_MAINLINE */

	/*
	 * Wait for all memory transactions to complete before entering low
	 * power state.
	 */
	dsb

	/* Enter low power state */
	wfi
	_sleep_if_allowed wfi

	/*
	 * Clear PRIMASK and flush instruction buffer to immediately service
@@ -139,7 +160,7 @@ SECTION_FUNC(TEXT, arch_cpu_atomic_idle)
	/* No BASEPRI, call wfe directly
	 * (SEVONPEND is set in z_arm_cpu_idle_init())
	 */
	wfe
	_sleep_if_allowed wfe

	cmp	r0, #0
	bne	_irq_disabled
@@ -153,7 +174,7 @@ _irq_disabled:
	/* unlock BASEPRI so wfe gets interrupted by incoming interrupts */
	msr	BASEPRI, r1

	wfe
	_sleep_if_allowed wfe

	msr	BASEPRI, r0
	cpsie	i
+9 −0
Original line number Diff line number Diff line
@@ -42,6 +42,15 @@ static ALWAYS_INLINE void arch_nop(void)
extern bool z_arm_thread_is_in_user_mode(void);
#endif

#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK)
/* Prototype of a hook that can be enabled to be called every time the CPU is
 * made idle (the calls will be done from k_cpu_idle() and k_cpu_atomic_idle()).
 * If this hook returns false, the CPU is prevented from entering the actual
 * sleep (the WFE/WFI instruction is skipped).
 */
bool z_arm_on_enter_cpu_idle(void);
#endif

#endif

#ifdef __cplusplus