soc: arm: nrf53: workaround pop lr after wfi crash

On nRF5340 net core it was observed that when `wfi` instruction was
followed by `pop {r0, lr}` in the `arch_cpu_idle` function,
the value of `lr` sometimes got read as 0 from memory despite
having correct value stored in the memory.

This commit inserts additional `nop` instruction after waking up
to delay access to the memory.

Signed-off-by: Andrzej Kuroś <andrzej.kuros@nordicsemi.no>
This commit is contained in:
Andrzej Kuros 2023-07-06 13:32:27 +02:00 committed by Carles Cufí
commit abd90085ac
4 changed files with 46 additions and 0 deletions

View file

@ -53,6 +53,22 @@ config ARM_ON_ENTER_CPU_IDLE_HOOK
If needed, this hook can be used to prevent the CPU from actually If needed, this hook can be used to prevent the CPU from actually
entering sleep by skipping the WFE/WFI instruction. entering sleep by skipping the WFE/WFI instruction.
config ARM_ON_EXIT_CPU_IDLE
bool
help
Enables a possibility to inject SoC-specific code just after WFI/WFE
instructions of the cpu idle implementation.
Enabling this option requires that the SoC provides a soc_cpu_idle.h
header file which defines SOC_ON_EXIT_CPU_IDLE macro guarded by
_ASMLANGUAGE.
The SOC_ON_EXIT_CPU_IDLE macro is expanded just after
WFI/WFE instructions before any memory access is performed. The purpose
of the SOC_ON_EXIT_CPU_IDLE is to perform an action that mitigate issues
observed on some SoCs caused by a memory access following WFI/WFE
instructions.
rsource "core/aarch32/Kconfig" rsource "core/aarch32/Kconfig"
rsource "core/aarch32/Kconfig.vfp" rsource "core/aarch32/Kconfig.vfp"

View file

@ -13,6 +13,10 @@
#include <zephyr/toolchain.h> #include <zephyr/toolchain.h>
#include <zephyr/linker/sections.h> #include <zephyr/linker/sections.h>
#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE)
#include <soc_cpu_idle.h>
#endif
_ASM_FILE_PROLOGUE _ASM_FILE_PROLOGUE
GTEXT(z_arm_cpu_idle_init) GTEXT(z_arm_cpu_idle_init)
@ -64,6 +68,11 @@ SECTION_FUNC(TEXT, z_arm_cpu_idle_init)
dsb dsb
\wait_instruction \wait_instruction
#if defined(CONFIG_ARM_ON_EXIT_CPU_IDLE)
/* Inline the macro provided by SoC-specific code */
SOC_ON_EXIT_CPU_IDLE
#endif /* CONFIG_ARM_ON_EXIT_CPU_IDLE */
#if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK) #if defined(CONFIG_ARM_ON_ENTER_CPU_IDLE_HOOK)
_skip_\@: _skip_\@:
#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE)

View file

@ -13,6 +13,7 @@ config SOC_NRF5340_CPUAPP
config SOC_NRF5340_CPUNET config SOC_NRF5340_CPUNET
bool bool
select HAS_NO_PM select HAS_NO_PM
select ARM_ON_EXIT_CPU_IDLE
imply SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED imply SOC_NRF53_ANOMALY_160_WORKAROUND_NEEDED
choice choice

View file

@ -0,0 +1,20 @@
/*
* Copyright (c) 2023 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @file SoC extensions of cpu_idle.S for the Nordic Semiconductor nRF53 processors family.
*/
#if defined(_ASMLANGUAGE)
#define SOC_ON_EXIT_CPU_IDLE \
nop; \
nop; \
nop; \
nop;
#endif /* _ASMLANGUAGE */